erbal 0.0.3.rc1 → 1.0.rc1

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.
data/ext/erbal/parser.c CHANGED
@@ -23,10 +23,11 @@ static int act, cs;
23
23
 
24
24
  inline void erbal_parser_tag_open_common(erbal_parser *parser, int shift) {
25
25
  if (parser->chars_seen != 0) {
26
- rb_str_concat(parser->src, parser->buffer_name);
27
- rb_str_buf_cat(parser->src, ".concat(\"", 9);
26
+ if (!parser->in_buffer_shift) {
27
+ erbal_open_buffer_shift(parser);
28
+ }
29
+
28
30
  erbal_concat_chars_seen(parser, shift);
29
- rb_str_buf_cat(parser->src, "\");", 3);
30
31
  parser->chars_seen = 0;
31
32
  }
32
33
  }
@@ -51,11 +52,18 @@ inline void erbal_parser_non_tag(erbal_parser *parser) {
51
52
 
52
53
  inline void erbal_parser_tag_close_common(erbal_parser *parser, int tag_size) {
53
54
  if (parser->state == TAG_OPEN_FOR_OUTPUT) {
54
- rb_str_concat(parser->src, parser->buffer_name);
55
- rb_str_buf_cat(parser->src, ".concat((", 9);
55
+ if (!parser->in_buffer_shift) {
56
+ erbal_open_buffer_shift(parser);
57
+ }
58
+
59
+ rb_str_buf_cat(parser->src, "#{", 2);
56
60
  erbal_concat_chars_seen(parser, -tag_size);
57
- rb_str_buf_cat(parser->src, ").to_s);", 8);
61
+ rb_str_buf_cat(parser->src, "}", 1);
58
62
  } else if (parser->state == TAG_OPEN) {
63
+ if (parser->in_buffer_shift) {
64
+ erbal_close_buffer_shift(parser);
65
+ }
66
+
59
67
  erbal_concat_chars_seen(parser, -tag_size);
60
68
  rb_str_buf_cat(parser->src, ";", 1);
61
69
  }
@@ -76,31 +84,84 @@ inline void erbal_parser_tag_close(erbal_parser *parser) {
76
84
  erbal_parser_tag_close_common(parser, 1);
77
85
  }
78
86
 
79
- inline void erbal_concat_chars_seen(erbal_parser *parser, int rewind_chars) {
87
+ inline VALUE erbal_escape_special_chars(erbal_parser *parser, int shift) {
88
+ VALUE buf = rb_str_buf_new(0);
89
+ int i, n, slashes_seen = 0;
90
+ char *current_char;
91
+
92
+ for (i = 0; i < parser->chars_seen; i++) {
93
+ current_char = (((p + shift) - parser->chars_seen) + i);
94
+
95
+ if (*current_char == '#' || *current_char == '`') {
96
+ if (slashes_seen == 0) {
97
+ rb_str_buf_cat(buf, "\\", 1);
98
+ rb_str_buf_cat(buf, current_char, 1);
99
+ } else {
100
+ for (n = 0; n <= (1 * slashes_seen); n++) {
101
+ rb_str_buf_cat(buf, "\\", 1);
102
+ }
103
+ rb_str_buf_cat(buf, current_char, 1);
104
+ }
105
+
106
+ slashes_seen = 0;
107
+ } else if (*current_char == '\\') {
108
+ slashes_seen++;
109
+ rb_str_buf_cat(buf, current_char, 1);
110
+ } else {
111
+ rb_str_buf_cat(buf, current_char, 1);
112
+ }
113
+ }
114
+
115
+ return buf;
116
+ }
117
+
118
+ inline void erbal_concat_chars_seen(erbal_parser *parser, int shift) {
80
119
  if (parser->chars_seen != 0) {
81
- rb_str_buf_cat(parser->src, ((p + rewind_chars) - parser->chars_seen), parser->chars_seen);
120
+ if (parser->in_buffer_shift) {
121
+ rb_str_concat(parser->src, erbal_escape_special_chars(parser, shift));
122
+ } else {
123
+ rb_str_buf_cat(parser->src, ((p + shift) - parser->chars_seen), parser->chars_seen);
124
+ }
82
125
  }
83
126
 
84
127
  parser->chars_seen = 0;
85
128
  }
86
129
 
130
+ inline void erbal_open_buffer_shift(erbal_parser *parser) {
131
+ rb_str_concat(parser->src, parser->buffer_name);
132
+ rb_str_buf_cat(parser->src, " << %Q`", 7);
133
+ parser->in_buffer_shift = 1;
134
+ }
135
+
136
+ inline void erbal_close_buffer_shift(erbal_parser *parser) {
137
+ rb_str_buf_cat(parser->src, "`;", 2);
138
+ parser->in_buffer_shift = 0;
139
+ }
140
+
87
141
  inline void erbal_parser_finish(erbal_parser *parser) {
88
142
  if (parser->chars_seen != 0) {
89
- rb_str_concat(parser->src, parser->buffer_name);
90
- rb_str_buf_cat(parser->src, ".concat(\"", 9);
143
+ if (!parser->in_buffer_shift) {
144
+ erbal_open_buffer_shift(parser);
145
+ }
146
+
91
147
  erbal_concat_chars_seen(parser, 0);
92
- rb_str_buf_cat(parser->src, "\");", 3);
93
148
  }
149
+
150
+ if (parser->in_buffer_shift) {
151
+ erbal_close_buffer_shift(parser);
152
+ }
153
+
94
154
  rb_str_concat(parser->src, parser->buffer_name);
95
155
  }
96
156
 
97
157
  void erbal_parser_init(erbal_parser *parser) {
98
- parser->state = 0;
99
158
  parser->chars_seen = 0;
159
+ parser->in_buffer_shift = 0;
160
+ parser->state = OUTSIDE_TAG;
100
161
  parser->src = rb_str_dup(parser->buffer_name);
101
- rb_str_buf_cat(parser->src, "=\"\";", 4);
162
+ rb_str_buf_cat(parser->src, " = '';", 6);
102
163
 
103
- #line 104 "parser.c"
164
+ #line 165 "parser.c"
104
165
  {
105
166
  cs = erbal_parser_start;
106
167
  ts = 0;
@@ -108,14 +169,14 @@ void erbal_parser_init(erbal_parser *parser) {
108
169
  act = 0;
109
170
  }
110
171
 
111
- #line 101 "parser.rl"
172
+ #line 162 "parser.rl"
112
173
  }
113
174
 
114
175
  void erbal_parser_exec(erbal_parser *parser) {
115
176
  p = RSTRING(parser->str)->ptr;
116
177
  pe = p + strlen(p);
117
178
 
118
- #line 119 "parser.c"
179
+ #line 180 "parser.c"
119
180
  {
120
181
  if ( p == pe )
121
182
  goto _test_eof;
@@ -161,7 +222,7 @@ st1:
161
222
  case 1:
162
223
  #line 1 "NONE"
163
224
  {ts = p;}
164
- #line 165 "parser.c"
225
+ #line 226 "parser.c"
165
226
  switch( (*p) ) {
166
227
  case 37: goto st2;
167
228
  case 45: goto tr4;
@@ -183,7 +244,7 @@ st3:
183
244
  if ( ++p == pe )
184
245
  goto _test_eof3;
185
246
  case 3:
186
- #line 187 "parser.c"
247
+ #line 248 "parser.c"
187
248
  if ( (*p) == 37 )
188
249
  goto st0;
189
250
  goto tr6;
@@ -232,6 +293,6 @@ case 5:
232
293
 
233
294
  }
234
295
 
235
- #line 107 "parser.rl"
296
+ #line 168 "parser.rl"
236
297
  erbal_parser_finish(parser);
237
298
  }
data/ext/erbal/parser.h CHANGED
@@ -4,7 +4,7 @@
4
4
  #include "ruby.h"
5
5
 
6
6
  typedef struct erbal_parser {
7
- unsigned int state, chars_seen, tag_seen;
7
+ unsigned int state, chars_seen, in_buffer_shift;
8
8
  VALUE str, src, buffer_name;
9
9
  } erbal_parser;
10
10
 
@@ -18,6 +18,9 @@ inline void erbal_parser_tag_close_common(erbal_parser*, int shift);
18
18
  inline void erbal_parser_finish(erbal_parser*);
19
19
  inline void erbal_concat_chars_seen(erbal_parser*, int shift);
20
20
  inline void erbal_parser_tag_open_common(erbal_parser*, int shift);
21
+ inline void erbal_open_buffer_shift(erbal_parser*);
22
+ inline void erbal_close_buffer_shift(erbal_parser*);
23
+ inline VALUE erbal_escape_special_chars(erbal_parser*, int shift);
21
24
 
22
25
  #define TAG_OPEN 1
23
26
  #define TAG_OPEN_FOR_COMMENT 2
data/ext/erbal/parser.rl CHANGED
@@ -21,10 +21,11 @@ static int act, cs;
21
21
 
22
22
  inline void erbal_parser_tag_open_common(erbal_parser *parser, int shift) {
23
23
  if (parser->chars_seen != 0) {
24
- rb_str_concat(parser->src, parser->buffer_name);
25
- rb_str_buf_cat(parser->src, ".concat(\"", 9);
24
+ if (!parser->in_buffer_shift) {
25
+ erbal_open_buffer_shift(parser);
26
+ }
27
+
26
28
  erbal_concat_chars_seen(parser, shift);
27
- rb_str_buf_cat(parser->src, "\");", 3);
28
29
  parser->chars_seen = 0;
29
30
  }
30
31
  }
@@ -49,11 +50,18 @@ inline void erbal_parser_non_tag(erbal_parser *parser) {
49
50
 
50
51
  inline void erbal_parser_tag_close_common(erbal_parser *parser, int tag_size) {
51
52
  if (parser->state == TAG_OPEN_FOR_OUTPUT) {
52
- rb_str_concat(parser->src, parser->buffer_name);
53
- rb_str_buf_cat(parser->src, ".concat((", 9);
53
+ if (!parser->in_buffer_shift) {
54
+ erbal_open_buffer_shift(parser);
55
+ }
56
+
57
+ rb_str_buf_cat(parser->src, "#{", 2);
54
58
  erbal_concat_chars_seen(parser, -tag_size);
55
- rb_str_buf_cat(parser->src, ").to_s);", 8);
59
+ rb_str_buf_cat(parser->src, "}", 1);
56
60
  } else if (parser->state == TAG_OPEN) {
61
+ if (parser->in_buffer_shift) {
62
+ erbal_close_buffer_shift(parser);
63
+ }
64
+
57
65
  erbal_concat_chars_seen(parser, -tag_size);
58
66
  rb_str_buf_cat(parser->src, ";", 1);
59
67
  }
@@ -74,29 +82,82 @@ inline void erbal_parser_tag_close(erbal_parser *parser) {
74
82
  erbal_parser_tag_close_common(parser, 1);
75
83
  }
76
84
 
77
- inline void erbal_concat_chars_seen(erbal_parser *parser, int rewind_chars) {
85
+ inline VALUE erbal_escape_special_chars(erbal_parser *parser, int shift) {
86
+ VALUE buf = rb_str_buf_new(0);
87
+ int i, n, slashes_seen = 0;
88
+ char *current_char;
89
+
90
+ for (i = 0; i < parser->chars_seen; i++) {
91
+ current_char = (((p + shift) - parser->chars_seen) + i);
92
+
93
+ if (*current_char == '#' || *current_char == '`') {
94
+ if (slashes_seen == 0) {
95
+ rb_str_buf_cat(buf, "\\", 1);
96
+ rb_str_buf_cat(buf, current_char, 1);
97
+ } else {
98
+ for (n = 0; n <= (1 * slashes_seen); n++) {
99
+ rb_str_buf_cat(buf, "\\", 1);
100
+ }
101
+ rb_str_buf_cat(buf, current_char, 1);
102
+ }
103
+
104
+ slashes_seen = 0;
105
+ } else if (*current_char == '\\') {
106
+ slashes_seen++;
107
+ rb_str_buf_cat(buf, current_char, 1);
108
+ } else {
109
+ rb_str_buf_cat(buf, current_char, 1);
110
+ }
111
+ }
112
+
113
+ return buf;
114
+ }
115
+
116
+ inline void erbal_concat_chars_seen(erbal_parser *parser, int shift) {
78
117
  if (parser->chars_seen != 0) {
79
- rb_str_buf_cat(parser->src, ((p + rewind_chars) - parser->chars_seen), parser->chars_seen);
118
+ if (parser->in_buffer_shift) {
119
+ rb_str_concat(parser->src, erbal_escape_special_chars(parser, shift));
120
+ } else {
121
+ rb_str_buf_cat(parser->src, ((p + shift) - parser->chars_seen), parser->chars_seen);
122
+ }
80
123
  }
81
124
 
82
125
  parser->chars_seen = 0;
83
126
  }
84
127
 
128
+ inline void erbal_open_buffer_shift(erbal_parser *parser) {
129
+ rb_str_concat(parser->src, parser->buffer_name);
130
+ rb_str_buf_cat(parser->src, " << %Q`", 7);
131
+ parser->in_buffer_shift = 1;
132
+ }
133
+
134
+ inline void erbal_close_buffer_shift(erbal_parser *parser) {
135
+ rb_str_buf_cat(parser->src, "`;", 2);
136
+ parser->in_buffer_shift = 0;
137
+ }
138
+
85
139
  inline void erbal_parser_finish(erbal_parser *parser) {
86
140
  if (parser->chars_seen != 0) {
87
- rb_str_concat(parser->src, parser->buffer_name);
88
- rb_str_buf_cat(parser->src, ".concat(\"", 9);
141
+ if (!parser->in_buffer_shift) {
142
+ erbal_open_buffer_shift(parser);
143
+ }
144
+
89
145
  erbal_concat_chars_seen(parser, 0);
90
- rb_str_buf_cat(parser->src, "\");", 3);
91
146
  }
147
+
148
+ if (parser->in_buffer_shift) {
149
+ erbal_close_buffer_shift(parser);
150
+ }
151
+
92
152
  rb_str_concat(parser->src, parser->buffer_name);
93
153
  }
94
154
 
95
155
  void erbal_parser_init(erbal_parser *parser) {
96
- parser->state = 0;
97
156
  parser->chars_seen = 0;
157
+ parser->in_buffer_shift = 0;
158
+ parser->state = OUTSIDE_TAG;
98
159
  parser->src = rb_str_dup(parser->buffer_name);
99
- rb_str_buf_cat(parser->src, "=\"\";", 4);
160
+ rb_str_buf_cat(parser->src, " = '';", 6);
100
161
  %% write init;
101
162
  }
102
163
 
data/spec/erbal_spec.rb CHANGED
@@ -1,47 +1,82 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Erbal do
4
- def parse(str)
4
+ def erbal_parse(str)
5
5
  Erbal.new(str, '@out').parse
6
6
  end
7
7
 
8
+ def erubis_parse(str)
9
+ require 'rubygems'
10
+ require 'erubis'
11
+ Erubis::FastEruby.new.convert(str)
12
+ end
13
+
14
+ def compare(str)
15
+ erbal_parse(str).should == erb_parse(str)
16
+ end
17
+
8
18
  it "should parse a blank string" do
9
- parse("").should == '@out="";@out'
19
+ erbal_parse("").should == "@out = '';@out"
10
20
  end
11
21
 
12
22
  it "should parse content without any tags" do
13
- parse("I love unicorns!").should == '@out="";@out.concat("I love unicorns!");@out'
23
+ erbal_parse("I love unicorns!").should == "@out = '';@out << %Q`I love unicorns!`;@out"
14
24
  end
15
25
 
16
26
  it "should parse the <% tag" do
17
- parse("<% 1 + 1 %>").should == '@out=""; 1 + 1 ;@out'
27
+ erbal_parse("<% 1 + 1 %>").should == "@out = ''; 1 + 1 ;@out"
18
28
  end
19
29
 
20
30
  it "should parse the <%= tag" do
21
- parse("<%= 1 + 1 %>").should == '@out="";@out.concat(( 1 + 1 ).to_s);@out'
31
+ erbal_parse("<%= 1 + 1 %>").should == "@out = '';@out << %Q`\#{ 1 + 1 }`;@out"
22
32
  end
23
33
 
24
34
  it "should parse the comment tag <%#" do
25
- parse("<%# I'm a comment %>").should == '@out="";@out'
35
+ erbal_parse("<%# I'm a comment %>").should == "@out = '';@out"
26
36
  end
27
37
 
28
38
  it "should swallow the following newline if the -%> tag is used" do
29
- parse("<%= 1 + 1 -%>\n").should == '@out="";@out.concat(( 1 + 1 ).to_s);@out'
39
+ erbal_parse("<%= 1 + 1 -%>\n\n").should == "@out = '';@out << %Q`\#{ 1 + 1 }\n`;@out"
30
40
  end
31
41
 
32
42
  it "should not swallow the following character if the -%> tag is used and the following character is not a newline" do
33
- parse("<%= 1 + 1 -%>Z").should == '@out="";@out.concat(( 1 + 1 ).to_s);@out.concat("Z");@out'
43
+ erbal_parse("<%= 1 + 1 -%>Z").should == "@out = '';@out << %Q`\#{ 1 + 1 }Z`;@out"
34
44
  end
35
45
 
36
46
  it "should concat text surrounding the tags when the opening tag is <%" do
37
- parse("1 + 1 is <% 1 + 1 %>. Easy!").should == '@out="";@out.concat("1 + 1 is "); 1 + 1 ;@out.concat(". Easy!");@out'
47
+ erbal_parse("1 + 1 is <% 1 + 1 %>. Easy!").should == "@out = '';@out << %Q`1 + 1 is `; 1 + 1 ;@out << %Q`. Easy!`;@out"
38
48
  end
39
49
 
40
50
  it "should concat text surrounding the tags when the opening tag is <%=" do
41
- parse("1 + 1 is <%= 1 + 1 %>. Easy!").should == '@out="";@out.concat("1 + 1 is ");@out.concat(( 1 + 1 ).to_s);@out.concat(". Easy!");@out'
51
+ erbal_parse("1 + 1 is <%= 1 + 1 %>. Easy!").should == "@out = '';@out << %Q`1 + 1 is \#{ 1 + 1 }. Easy!`;@out"
42
52
  end
43
53
 
44
- it "should escape double quotes used outside tags" do
45
- puts eval(parse("1 + \" 1 is <%= \"weeee\" %>. Easy!"))
54
+ it "should not open a new buffer shift when there is more than one consecutive <%= tag" do
55
+ erbal_parse("1 + 1 is <%= 1 + 1 %>, and 2 + 2 is <%= 2 + 2 %>. Easy!").should == "@out = '';@out << %Q`1 + 1 is \#{ 1 + 1 }, and 2 + 2 is \#{ 2 + 2 }. Easy!`;@out"
56
+ end
57
+
58
+ it "should escape a hash character that signifies the start of a string interpolation" do
59
+ erbal_parse("<%= 1 + 1 -%> wee \#{1 + 3}").should == "@out = '';@out << %Q`\#{ 1 + 1 } wee \\\#{1 + 3}`;@out"
60
+ eval(erbal_parse("<%= 1 + 1 -%> wee \#{1 + 3}")).should == eval(erubis_parse("<%= 1 + 1 -%> wee \#{1 + 3}"))
61
+
62
+ erbal_parse("<%= 1 + 1 -%> wee \\\#{1 + 3}").should == "@out = '';@out << %Q`\#{ 1 + 1 } wee \\\\\\\#{1 + 3}`;@out"
63
+ eval(erbal_parse("<%= 1 + 1 -%> wee \\\#{1 + 3}")).should == eval(erubis_parse("<%= 1 + 1 -%> wee \\\#{1 + 3}"))
64
+
65
+ erbal_parse("<%= 1 + 1 -%> wee \\\\\\\#{1 + 3}").should == "@out = '';@out << %Q`\#{ 1 + 1 } wee \\\\\\\\\\\\\\\#{1 + 3}`;@out"
66
+ eval(erbal_parse("<%= 1 + 1 -%> wee \\\\\\\#{1 + 3}")).should == eval(erubis_parse("<%= 1 + 1 -%> wee \\\\\\\#{1 + 3}"))
67
+
68
+ erbal_parse('<%= 1 + 1 -%> wee #{1 + 3}').should == "@out = '';@out << %Q`\#{ 1 + 1 } wee \\\#{1 + 3}`;@out"
69
+ eval(erbal_parse('<%= 1 + 1 -%> wee #{1 + 3}')).should == eval(erubis_parse('<%= 1 + 1 -%> wee #{1 + 3}'))
70
+ end
71
+
72
+ it "should escape a backtick character that signifies the end off a buffer shift" do
73
+ erbal_parse("weeee `").should == "@out = '';@out << %Q`weeee \\``;@out"
74
+ eval(erbal_parse("weeee `")).should == eval(erubis_parse("weeee `"));
75
+
76
+ erbal_parse("weeee \\`").should == "@out = '';@out << %Q`weeee \\\\\\``;@out"
77
+ eval(erbal_parse("weeee \\`")).should == eval(erubis_parse("weeee \\`"))
78
+
79
+ erbal_parse("weeee \\\\\\\`").should == "@out = '';@out << %Q`weeee \\\\\\\\\\\\\\``;@out"
80
+ eval(erbal_parse("weeee \\\\\\\`")).should == eval(erubis_parse("weeee \\\\\\\`"))
46
81
  end
47
82
  end
data/spec/spec_helper.rb CHANGED
@@ -1,3 +1,5 @@
1
+ require 'erb'
2
+
1
3
  $:.unshift(File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib')))
2
4
  `rake clean`
3
5
  `rake compile`
data/tasks/gem.rake CHANGED
@@ -2,7 +2,7 @@ require 'rake/gempackagetask'
2
2
  require 'yaml'
3
3
 
4
4
  WIN_SUFFIX = ENV['WIN_SUFFIX'] || 'i386-mswin32'
5
- ERBAL_VERSION = '0.0.3.rc1'
5
+ ERBAL_VERSION = '1.0.rc1'
6
6
 
7
7
  task :clean => :clobber_package
8
8
 
@@ -13,7 +13,7 @@ spec = Gem::Specification.new do |s|
13
13
  s.summary =
14
14
  s.description = "Very small, very fast Ragel/C based ERB parser"
15
15
  s.author = "Ian Leitch"
16
- s.email = 'ian.leitch@systino.net'
16
+ s.email = 'port001@gmail.com'
17
17
  s.homepage = 'http://github.com/ileitch/erbal'
18
18
  s.has_rdoc = false
19
19
 
@@ -35,8 +35,7 @@ Rake::GemPackageTask.new(spec) do |p|
35
35
  end
36
36
 
37
37
  namespace :gem do
38
- desc "Update the gemspec for GitHub's gem server"
39
- task :github do
38
+ task :gemspec do
40
39
  File.open("erbal.gemspec", 'w') { |f| f << YAML.dump(spec) }
41
40
  end
42
41
  end
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: erbal
3
3
  version: !ruby/object:Gem::Version
4
- hash: 977940546
4
+ hash: 977940502
5
5
  prerelease: true
6
6
  segments:
7
+ - 1
7
8
  - 0
8
- - 0
9
- - 3
10
9
  - rc1
11
- version: 0.0.3.rc1
10
+ version: 1.0.rc1
12
11
  platform: ruby
13
12
  authors:
14
13
  - Ian Leitch
@@ -16,12 +15,12 @@ autorequire:
16
15
  bindir: bin
17
16
  cert_chain: []
18
17
 
19
- date: 2010-12-17 00:00:00 +11:00
18
+ date: 2010-12-29 00:00:00 +11:00
20
19
  default_executable:
21
20
  dependencies: []
22
21
 
23
22
  description: Very small, very fast Ragel/C based ERB parser
24
- email: ian.leitch@systino.net
23
+ email: port001@gmail.com
25
24
  executables: []
26
25
 
27
26
  extensions:
@@ -34,7 +33,6 @@ files:
34
33
  - README.rdoc
35
34
  - Rakefile
36
35
  - lib/erbal/rails.rb
37
- - lib/erbal.bundle
38
36
  - spec/erbal_spec.rb
39
37
  - spec/spec_helper.rb
40
38
  - tasks/ext.rake
data/lib/erbal.bundle DELETED
Binary file