renshi 0.2.4 → 0.2.5
Sign up to get free protection for your applications and to get access to all the features.
- data/README +35 -10
- data/lib/renshi/parser.rb +29 -14
- data/lib/renshi.rb +1 -1
- data/spec/each_spec.rb +1 -1
- data/spec/parser_spec.rb +128 -104
- metadata +2 -2
data/README
CHANGED
@@ -1,18 +1,33 @@
|
|
1
|
-
Renshi
|
1
|
+
Renshi - a templating language which is friendly and powerful with your HTML structures.
|
2
|
+
|
3
|
+
Works with Rails and Sinatra - no config.. Just 'require renshi'. In Sinatra use 'ren' where you would have used the 'erb'/'haml' methods.
|
4
|
+
|
5
|
+
index.html.ren means you're working with a Renshi file!
|
2
6
|
|
3
|
-
Renshi integrates with Rails and Sinatra transparently. Simply 'require renshi'. In Sinatra use 'ren' where you would have used the 'erb'/'haml' methods. Renshi templates are appended with the suffix of .ren, e.g. index.html.ren or index.ren.
|
4
7
|
|
5
8
|
$ Ruby Interpretation
|
6
9
|
=====================
|
7
|
-
|
10
|
+
$ interprets everything after it as ruby which will be to_stringed until the next $, a newline character, or the end of the element.
|
11
|
+
|
12
|
+
e.g. you can do this
|
13
|
+
|
14
|
+
$stylesheet_link_tag "atsida"
|
15
|
+
|
16
|
+
e.g. or this
|
17
|
+
<p>$foo $bar</p>
|
18
|
+
|
8
19
|
|
9
|
-
|
20
|
+
${} delimits where the ruby begins and ends, for inplace insertions"
|
10
21
|
|
11
|
-
|
22
|
+
e.g.
|
23
|
+
<p>${some_function "takes this string as input"} and this is normal HTML</p>
|
12
24
|
|
13
|
-
|
25
|
+
$^ outputs a single phrase:
|
14
26
|
|
15
|
-
|
27
|
+
e.g.
|
28
|
+
<p>What are you doing up at $^Time.now when you should be asleep?</p>
|
29
|
+
|
30
|
+
$[] allows ruby src code to be embedded. It's a bad practice (use helpers or something) but we let you do it.
|
16
31
|
|
17
32
|
$[if foo]
|
18
33
|
$foo
|
@@ -20,14 +35,14 @@ $[end]
|
|
20
35
|
|
21
36
|
Attribute Expressions
|
22
37
|
=====================
|
23
|
-
|
38
|
+
Attribute expressions are insertable into HTML elements.
|
24
39
|
|
25
40
|
<p r:if="user.known?">Welcome $user.name</p>
|
26
41
|
|
27
42
|
They can be combined on elements and are interpreted in the order of appearance and are cumulative, allowing you to program inline on the HTML structure.
|
28
43
|
|
29
44
|
<li r:each="@sphinx.results[:words], |k,v|" r:if="v[:hits].to_i > 0">
|
30
|
-
|
45
|
+
$^k - Hits $^v[:hits] in $^v[:docs] documents
|
31
46
|
</li>
|
32
47
|
|
33
48
|
In the above, you can see that the if statement is scoped within the preceding each block, so you can reference variables between attr. expressions. Variables within an attr. expression don't need the $ symbol. That's only for setting up Ruby insertions within regular HTML.
|
@@ -146,7 +161,17 @@ To print a $ use $$, e.g. $$10.95 comes out as $10.95
|
|
146
161
|
|
147
162
|
Because the $foo evaluation can take all sorts of symbols to interpret a Ruby statement, if you are using a special symbol *immediately* before it, you'll have to use ${foo} instead. For example, because $greetings[0].upcase is interpretable, if you want to output "[HELLO]" where the brackets surround the string, you'd use [${greetings[0].upcase}]
|
148
163
|
|
149
|
-
The
|
164
|
+
The $^ parser *delimits* (splits) on any character which is not in this list - . " ' { } ( ) + = * / \ - @ [ ] : ? ! % \w
|
165
|
+
|
166
|
+
To output xml elements in a string use the escaped versions - e.g.for
|
167
|
+
|
168
|
+
(incorrect)
|
169
|
+
${@page.section.root? ? "<li>Home</li>" : render_breadcrumbs(:from_top => 1)}
|
170
|
+
|
171
|
+
use, instead,
|
172
|
+
|
173
|
+
(correct)
|
174
|
+
${@page.section.root? ? "<li>Home</li>" : render_breadcrumbs(:from_top => 1)}
|
150
175
|
|
151
176
|
Installation
|
152
177
|
============
|
data/lib/renshi/parser.rb
CHANGED
@@ -105,7 +105,7 @@ module Renshi
|
|
105
105
|
|
106
106
|
while idx != nil do
|
107
107
|
next_char = text[(idx + 1)..(idx + 1)]
|
108
|
-
|
108
|
+
|
109
109
|
if next_char == " "
|
110
110
|
raise SyntaxError, "Floating $ - use $$ to output '$': #{text[(idx +1)..-1]}", caller
|
111
111
|
elsif next_char == "("
|
@@ -116,7 +116,6 @@ module Renshi
|
|
116
116
|
#an escaped $ - i.e. '$$'
|
117
117
|
end_statement_idx = (idx + 2)
|
118
118
|
bits << "$"
|
119
|
-
|
120
119
|
#${...}
|
121
120
|
elsif next_char == "{"
|
122
121
|
begin
|
@@ -128,8 +127,7 @@ module Renshi
|
|
128
127
|
end_statement_idx = closing_brace_idx + 1
|
129
128
|
rescue StandardError
|
130
129
|
raise SyntaxError, "No closing brace: #{text}", caller
|
131
|
-
end
|
132
|
-
|
130
|
+
end
|
133
131
|
#$[...]
|
134
132
|
elsif next_char == "["
|
135
133
|
begin
|
@@ -141,16 +139,33 @@ module Renshi
|
|
141
139
|
end_statement_idx = closing_brace_idx + 1
|
142
140
|
rescue StandardError
|
143
141
|
raise SyntaxError, "No closing bracket: #{text}", caller
|
144
|
-
end
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
142
|
+
end
|
143
|
+
elsif next_char == "^" #$!foo
|
144
|
+
#divide with a delimiter for anything which is not a name character - alpa-numeric and underscore
|
145
|
+
words = text[(idx + 2)..-1].split(/[^\w."'{}()+=*\/\-@\[\]:?!%]/)
|
146
|
+
words[0] = "'$'" if words[0] == "$"
|
147
|
+
statement_str = words.first
|
148
|
+
statement = Statement.new(statement_str)
|
149
|
+
bits << statement.compile_to_print!
|
150
|
+
end_statement_idx = (words.first.length) + 2 + idx
|
151
|
+
else #$foo
|
152
|
+
#divide with a delimiter on \n or $ or assume ruby until the end of element
|
153
|
+
words = text[(idx +1)..-1].split(/[\n$]/)
|
154
|
+
words[0] = "'$'" if words[0] == "$"
|
155
|
+
|
156
|
+
#now respect whitespace trailing the word - e.g. $foo $bar should not render as "helloworld"
|
157
|
+
if words.first.index(/\s/)
|
158
|
+
before_whitespace = words.first.rindex(/[^\s]/)
|
159
|
+
src = words.first[0..(before_whitespace)]
|
160
|
+
else
|
161
|
+
src = words.first
|
162
|
+
end
|
163
|
+
|
164
|
+
statement_str = src
|
165
|
+
statement = Statement.new(statement_str)
|
166
|
+
bits << statement.compile_to_print!
|
167
|
+
end_statement_idx = (src.length) + 1 + idx
|
168
|
+
end
|
154
169
|
|
155
170
|
next_statement_idx = text.index("$", end_statement_idx)
|
156
171
|
|
data/lib/renshi.rb
CHANGED
data/spec/each_spec.rb
CHANGED
data/spec/parser_spec.rb
CHANGED
@@ -86,7 +86,7 @@ describe Renshi::Parser do
|
|
86
86
|
it "should interpret all Renshi instructions and remove them from the document" do
|
87
87
|
raw = compile_file("data/example1.ren")
|
88
88
|
html = eval(raw, binding)
|
89
|
-
|
89
|
+
|
90
90
|
html.should_not =~/R_INSTR_IDX_START/
|
91
91
|
html.should_not =~/R_INSTR_IDX_END/
|
92
92
|
html.should_not =~/@output_buffer.concat/
|
@@ -101,8 +101,8 @@ describe Renshi::Parser do
|
|
101
101
|
html.should =~/head/
|
102
102
|
end
|
103
103
|
|
104
|
-
it "should interpret single
|
105
|
-
raw = Renshi::Parser.parse("
|
104
|
+
it "should interpret single $^foos using \W, i.e. $^foo$^bar should render" do
|
105
|
+
raw = Renshi::Parser.parse("$^foo$^bar")
|
106
106
|
foo = "hello"
|
107
107
|
bar = " world"
|
108
108
|
|
@@ -118,106 +118,130 @@ class Test
|
|
118
118
|
end
|
119
119
|
|
120
120
|
it "should interpret single $foo.bar " do
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
121
|
+
raw = Renshi::Parser.parse("$foo.bar")
|
122
|
+
foo = Test.new
|
123
|
+
html = eval(raw, binding)
|
124
|
+
|
125
|
+
html.should eql "hello world"
|
126
|
+
end
|
127
|
+
|
128
|
+
it "should interpret single $1+1 and $2*2 and $3/3 and $4-4 " do
|
129
|
+
raw = Renshi::Parser.parse("$1+1")
|
130
|
+
foo = Test.new
|
131
|
+
html = eval(raw, binding)
|
132
|
+
html.should eql "2"
|
133
|
+
|
134
|
+
raw = Renshi::Parser.parse("$2*2")
|
135
|
+
foo = Test.new
|
136
|
+
html = eval(raw, binding)
|
137
|
+
html.should eql "4"
|
138
|
+
|
139
|
+
raw = Renshi::Parser.parse("$3/3")
|
140
|
+
foo = Test.new
|
141
|
+
html = eval(raw, binding)
|
142
|
+
html.should eql "1"
|
143
|
+
|
144
|
+
raw = Renshi::Parser.parse("$4-4")
|
145
|
+
foo = Test.new
|
146
|
+
html = eval(raw, binding)
|
147
|
+
html.should eql "0"
|
148
|
+
end
|
149
|
+
|
150
|
+
|
151
|
+
it "should interpret $foo[0] " do
|
152
|
+
raw = Renshi::Parser.parse("$foo[0]")
|
153
|
+
foo = ["hello world"]
|
154
|
+
html = eval(raw, binding)
|
155
|
+
|
156
|
+
html.should eql "hello world"
|
157
|
+
end
|
158
|
+
|
159
|
+
|
160
|
+
it "should interpret \"${@foo}\" " do
|
161
|
+
raw = Renshi::Parser.parse(%Q!"${@foo}"!)
|
162
|
+
puts raw
|
163
|
+
@foo = "hello world"
|
164
|
+
html = eval(raw, binding)
|
165
|
+
|
166
|
+
html.should eql %Q!"hello world"!
|
167
|
+
end
|
168
|
+
|
169
|
+
class R
|
170
|
+
attr_accessor :path
|
171
|
+
|
172
|
+
def initialize
|
173
|
+
@path = "/hello/world"
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
it "should interpret <a href='{$r.path}'>hello</a>" do
|
178
|
+
r = R.new
|
179
|
+
raw = Renshi::Parser.parse(%Q!<a href="${r.path}">hello</a>!)
|
180
|
+
html = eval(raw, binding)
|
181
|
+
|
182
|
+
html.should eql "<a href=\"#{r.path}\">hello</a>"
|
183
|
+
end
|
184
|
+
|
185
|
+
it "should interpret $foo.nil?" do
|
186
|
+
foo = nil
|
187
|
+
raw = Renshi::Parser.parse("$foo.nil?")
|
188
|
+
html = eval(raw, binding)
|
189
|
+
|
190
|
+
html.should eql true.to_s
|
191
|
+
end
|
192
|
+
|
193
|
+
it "should interpret $@foo.nil?" do
|
194
|
+
@foo = nil
|
195
|
+
raw = Renshi::Parser.parse("$@foo.nil?")
|
196
|
+
html = eval(raw, binding)
|
197
|
+
|
198
|
+
html.should eql true.to_s
|
199
|
+
end
|
200
|
+
|
201
|
+
it "should interpret $a$b$c" do
|
202
|
+
a = 'a'; b = 'b'; c = 'c';
|
203
|
+
raw = Renshi::Parser.parse("$a$b$c")
|
204
|
+
html = eval(raw, binding)
|
205
|
+
|
206
|
+
html.should eql "abc"
|
207
|
+
end
|
208
|
+
|
209
|
+
it "should interpret $'foo'.upcase!" do
|
210
|
+
raw = Renshi::Parser.parse("$'foo'.upcase!")
|
211
|
+
html = eval(raw, binding)
|
212
|
+
|
213
|
+
html.should eql "FOO"
|
214
|
+
end
|
215
|
+
|
216
|
+
it "should interpret $Time.now.strftime('%I:%M')" do
|
217
|
+
raw = Renshi::Parser.parse("$Time.now.strftime('%I:%M')")
|
218
|
+
html = eval(raw, binding)
|
219
|
+
|
220
|
+
html.should =~ /:/
|
221
|
+
end
|
222
|
+
|
223
|
+
it "should evaluate ternary statements in the curly braces" do
|
224
|
+
foo = nil
|
225
|
+
raw = Renshi::Parser.parse("${foo.nil? ? '>li<hello>/li<' : '>li<goodbye>/li<'}")
|
226
|
+
html = eval(raw, binding)
|
227
|
+
html.should =~ /hello/
|
228
|
+
foo = ""
|
229
|
+
html = eval(raw, binding)
|
230
|
+
html.should =~ /goodbye/
|
231
|
+
end
|
232
|
+
|
233
|
+
it "should interpret $foo until \n or end of element as ruby to string" do
|
234
|
+
raw = Renshi::Parser.parse("$'this should output as a string'")
|
235
|
+
html = eval(raw, binding)
|
236
|
+
|
237
|
+
html.should =~ /this should output as a string/
|
238
|
+
end
|
171
239
|
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
raw = Renshi::Parser.parse(%Q!<a href="${r.path}">hello</a>!)
|
180
|
-
html = eval(raw, binding)
|
181
|
-
|
182
|
-
html.should eql "<a href=\"#{r.path}\">hello</a>"
|
183
|
-
end
|
184
|
-
|
185
|
-
it "should interpret $foo.nil?" do
|
186
|
-
foo = nil
|
187
|
-
raw = Renshi::Parser.parse("$foo.nil?")
|
188
|
-
html = eval(raw, binding)
|
189
|
-
|
190
|
-
html.should eql true.to_s
|
191
|
-
end
|
192
|
-
|
193
|
-
it "should interpret $@foo.nil?" do
|
194
|
-
@foo = nil
|
195
|
-
raw = Renshi::Parser.parse("$@foo.nil?")
|
196
|
-
html = eval(raw, binding)
|
197
|
-
|
198
|
-
html.should eql true.to_s
|
199
|
-
end
|
200
|
-
|
201
|
-
it "should interpret $a$b$c" do
|
202
|
-
a = 'a'; b = 'b'; c = 'c';
|
203
|
-
raw = Renshi::Parser.parse("$a$b$c")
|
204
|
-
html = eval(raw, binding)
|
205
|
-
|
206
|
-
html.should eql "abc"
|
207
|
-
end
|
208
|
-
|
209
|
-
it "should interpret $'foo'.upcase!" do
|
210
|
-
raw = Renshi::Parser.parse("$'foo'.upcase!")
|
211
|
-
html = eval(raw, binding)
|
212
|
-
|
213
|
-
html.should eql "FOO"
|
214
|
-
end
|
215
|
-
|
216
|
-
it "should interpret $Time.now.strftime('%I:%M')" do
|
217
|
-
raw = Renshi::Parser.parse("$Time.now.strftime('%I:%M')")
|
218
|
-
html = eval(raw, binding)
|
219
|
-
|
220
|
-
html.should =~ /:/
|
221
|
-
end
|
222
|
-
|
240
|
+
it "should interpret $^foo as the single phrase" do
|
241
|
+
raw = Renshi::Parser.parse("this should $^foo 'hello'")
|
242
|
+
foo = "say"
|
243
|
+
html = eval(raw, binding)
|
244
|
+
|
245
|
+
html.should =~ /this should say 'hello'/
|
246
|
+
end
|
223
247
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: renshi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nicholas Faiz
|
@@ -9,7 +9,7 @@ autorequire: renshi
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
12
|
+
date: 2009-10-06 00:00:00 +11:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|