ice 0.2.2 → 0.2.3
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/README.markdown +80 -3
- data/VERSION +1 -1
- data/ice.gemspec +3 -2
- data/ice_js/lib/path_helper.js +35 -10
- data/ice_js/spec/support/js.jar +0 -0
- data/ice_js/spec/unit/spec.js +92 -9
- data/init.rb +3 -1
- data/lib/extras/ice_view.rb +0 -3
- data/lib/ice/cubeable.rb +0 -1
- data/lib/parser.js +2 -21
- data/spec/cube_spec.rb +0 -1
- data/spec/ice_spec.rb +5 -2
- data/spec/spec_helper.rb +0 -1
- metadata +4 -3
data/README.markdown
CHANGED
@@ -1,8 +1,10 @@
|
|
1
1
|
# Ice Ice Baby!
|
2
2
|
|
3
|
-
The Ice project allows user-created templates to be written in the javascript programming language.
|
3
|
+
The Ice project allows user-created templates to be written in the javascript programming language. Thanks to the [therubyracer](http://github.com/cowboyd/therubyracer) they are then interpreted using Google's V8 javascript engine.
|
4
4
|
|
5
|
-
Ice
|
5
|
+
Ice is similar to Liquid in terms of safety, but uses javascript to leverage the powers of a language most developers are familiar with. Ice runs the templates through an erb-ish parser (written by [Mark Turansky](http://blog.markturansky.com/BetterJavascriptTemplates.html)).
|
6
|
+
|
7
|
+
Your users can then write Ice templates like:
|
6
8
|
|
7
9
|
<table>
|
8
10
|
<tr><th>Name</th><th>Email</th></tr>
|
@@ -19,7 +21,7 @@ These templates can be run from the appropriate views directory, provided they h
|
|
19
21
|
|
20
22
|
## Why another templating engine when there is Liquid?
|
21
23
|
|
22
|
-
Liquid is excellent but
|
24
|
+
[Liquid](http://github.com/tobi/liquid) is excellent but it showing its age in a few ways:
|
23
25
|
|
24
26
|
* Hard to extend without knowing Liquid internals
|
25
27
|
* Introduces yet-another-language, whereas many designers/developers are already familiar with javascript
|
@@ -28,6 +30,8 @@ Liquid is excellent but has several disadvantages
|
|
28
30
|
|
29
31
|
Note that we're still big fans of Liquid. In fact, we call this project "Ice" as a tribute (extending the metaphor, we use "Cubes" where they have "Drops").
|
30
32
|
|
33
|
+
In addition, our ice_view.rb file is almost directly ripped out of the liquid project.
|
34
|
+
|
31
35
|
## Installation
|
32
36
|
|
33
37
|
For Rails:
|
@@ -79,6 +83,79 @@ This generates association helper functions such as comment_ids, num_comments, h
|
|
79
83
|
|
80
84
|
Note that the results of all associations and revealed functions are also sanitized via to_ice.
|
81
85
|
|
86
|
+
## NavBar
|
87
|
+
|
88
|
+
To make it easier to generate links, we added a NavBar class to the javascript helpers. THis class has an open and close method, as well as a link_to mehod which either takes a url, or a url and a link label.
|
89
|
+
|
90
|
+
<% var nav = new NavBar() %>
|
91
|
+
<%= nav.open() %>
|
92
|
+
<%= nav.link_to("Bar", "/foo") %>
|
93
|
+
<%= nav.link_to("http://ludicast.com") %>
|
94
|
+
<%= nav.close() %>
|
95
|
+
|
96
|
+
This then generates the following html
|
97
|
+
|
98
|
+
<ul class="linkBar">
|
99
|
+
<li><a href="/foo">Bar</a></li>
|
100
|
+
<li><a href="http://ludicast.com">http://ludicast.com</a></li>
|
101
|
+
</ul>
|
102
|
+
|
103
|
+
You'll notice that the resulting html code is shorter than the generator code, making this look inefficient. However the NavBar also takes options so if the NavBar above was instantiated with:
|
104
|
+
|
105
|
+
<% var nav = new NavBar({nav_open:"<div>", nav_close:"</div>",link_wrapper:function(link){
|
106
|
+
return "<span>" + link + "</span>"
|
107
|
+
|
108
|
+
it would automatically generate
|
109
|
+
|
110
|
+
<div>
|
111
|
+
<span><a href="/foo">Bar</a></span>
|
112
|
+
<span><a href="http://ludicast.com">http://ludicast.com</a></span>
|
113
|
+
</div>
|
114
|
+
|
115
|
+
Also, if you want to make a site- or page-wide change, all you need to do is add these options to the NavBar class like
|
116
|
+
|
117
|
+
NavBar.default_options = {nav_open:"<div>", nav_close:"</div>",link_wrapper:function(link){
|
118
|
+
return "<span>" + link + "</span>"
|
119
|
+
}}
|
120
|
+
|
121
|
+
Then all links will generate with these options, unless overridden in the NavBar's constructor. If the NavBar has a separator property added, it will add that separator between links. If a link is not shown (due to access restrictions or whatever in the link_wrapper function) the separator obviously will not appear for that link. So the code
|
122
|
+
|
123
|
+
bar.separator = "---"
|
124
|
+
bar.link_wrapper = function (link) {
|
125
|
+
if (link.match(/aa/)) {
|
126
|
+
return ""
|
127
|
+
} else {
|
128
|
+
return link
|
129
|
+
}
|
130
|
+
}
|
131
|
+
|
132
|
+
would cause
|
133
|
+
|
134
|
+
bar.open() + bar.link_to("ff") + bar.link_to("aa") + bar.link_to("gg") + bar.close()
|
135
|
+
|
136
|
+
to render as:
|
137
|
+
|
138
|
+
links.should.eql "<div><a href=\"ff\">ff</a>----<a href=\"gg\">gg</a></div>"
|
139
|
+
|
140
|
+
## Routes
|
141
|
+
|
142
|
+
Keeping with our tradition of stealing from other projects, we took the code from [RouteJs middleware](http://coderack.org/users/kossnocorp/middlewares/88-routesjs) to expose to our templates all your routes. This is a big convenience and lets you put in your templates things like:
|
143
|
+
|
144
|
+
<% var nav = new NavBar() %>
|
145
|
+
<%= nav.open() %>
|
146
|
+
<%= nav.link_to("List Pizzas", pizzas_path() ) %>
|
147
|
+
<%= nav.link_to("Modify Pizza", edit_pizza_path({id: pizza.id})) %>
|
148
|
+
<%= nav.close() %>
|
149
|
+
|
150
|
+
which is converted into
|
151
|
+
|
152
|
+
<ul class="linkBar">
|
153
|
+
<li><a href="/pizzas">List Pizzas</a></li>
|
154
|
+
<li><a href="/pizzas/2/edit">Modify Pizza</a></li>
|
155
|
+
</ul>
|
156
|
+
|
157
|
+
Note that some people might claim that it is insecure to expose your resources like this, but that probably should be dealt with on a case-by-case basis.
|
158
|
+
|
82
159
|
## Note on Patches/Pull Requests
|
83
160
|
|
84
161
|
* Fork the project.
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.2.
|
1
|
+
0.2.3
|
data/ice.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{ice}
|
8
|
-
s.version = "0.2.
|
8
|
+
s.version = "0.2.3"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Nate Kidwell"]
|
12
|
-
s.date = %q{2010-06-
|
12
|
+
s.date = %q{2010-06-09}
|
13
13
|
s.description = %q{User templates written in javascript}
|
14
14
|
s.email = %q{nate@ludicast.com}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -33,6 +33,7 @@ Gem::Specification.new do |s|
|
|
33
33
|
"ice_js/spec/rhino.js",
|
34
34
|
"ice_js/spec/server.html",
|
35
35
|
"ice_js/spec/server.rb",
|
36
|
+
"ice_js/spec/support/js.jar",
|
36
37
|
"ice_js/spec/unit/spec.helper.js",
|
37
38
|
"ice_js/spec/unit/spec.js",
|
38
39
|
"init.rb",
|
data/ice_js/lib/path_helper.js
CHANGED
@@ -1,24 +1,49 @@
|
|
1
|
-
function link_to(
|
2
|
-
if (!
|
3
|
-
|
1
|
+
function link_to(label, link, opts) {
|
2
|
+
if (! link) {
|
3
|
+
link = label
|
4
4
|
}
|
5
|
-
|
6
|
-
return "<a href=\"" + location + "\">" + label + "</a>"
|
5
|
+
return "<a href=\"" + link + "\">" + label + "</a>"
|
7
6
|
}
|
8
7
|
|
9
|
-
var NavBar = function () {
|
8
|
+
var NavBar = function (options) {
|
9
|
+
var defaults = NavBar.default_options
|
10
|
+
for (var default_option in defaults) {
|
11
|
+
if (defaults.hasOwnProperty(default_option)) {
|
12
|
+
this[default_option] = defaults[default_option]
|
13
|
+
}
|
14
|
+
}
|
10
15
|
|
16
|
+
for (var option in options) {
|
17
|
+
if (options.hasOwnProperty(option)) {
|
18
|
+
this[option] = options[option]
|
19
|
+
}
|
20
|
+
}
|
11
21
|
}
|
12
22
|
|
13
|
-
NavBar.prototype.link_to = function (link) {
|
14
|
-
|
23
|
+
NavBar.prototype.link_to = function (label, link) {
|
24
|
+
link_code = link_to(label, link)
|
25
|
+
|
26
|
+
if (this.link_wrapper) {
|
27
|
+
link_data = this.link_wrapper(link_code)
|
28
|
+
} else {
|
29
|
+
link_data = "<li>" + link_code + "</li>"
|
30
|
+
}
|
31
|
+
if (link_data) {
|
32
|
+
if (this.link_data && this.separator) {
|
33
|
+
link_data = this.separator + link_data
|
34
|
+
}
|
35
|
+
this.link_data = link_data
|
36
|
+
}
|
37
|
+
return link_data;
|
15
38
|
}
|
16
39
|
|
40
|
+
|
17
41
|
NavBar.prototype.open = function () {
|
18
|
-
return "<ul class=\"linkBar\">"
|
42
|
+
return this.nav_open || "<ul class=\"linkBar\">"
|
19
43
|
}
|
20
44
|
|
21
45
|
NavBar.prototype.close = function () {
|
22
|
-
return "</ul>"
|
46
|
+
return this.nav_close || "</ul>"
|
23
47
|
}
|
24
48
|
|
49
|
+
NavBar.default_options = {}
|
Binary file
|
data/ice_js/spec/unit/spec.js
CHANGED
@@ -1,17 +1,100 @@
|
|
1
|
-
describe "
|
2
|
-
|
3
|
-
|
1
|
+
describe "NavBar"
|
2
|
+
|
3
|
+
describe "by default"
|
4
|
+
before_each
|
5
|
+
bar = new NavBar()
|
6
|
+
end
|
7
|
+
|
8
|
+
|
9
|
+
it "should generate list by default"
|
10
|
+
(bar.open() + bar.close()).should.eql "<ul class=\"linkBar\"></ul>"
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should generate list with internal links"
|
14
|
+
|
15
|
+
links = (bar.open() + bar.link_to("ff") + bar.link_to("aa") + bar.close())
|
16
|
+
|
17
|
+
links.should.eql "<ul class=\"linkBar\"><li><a href=\"ff\">ff</a></li><li><a href=\"aa\">aa</a></li></ul>"
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should take optional titles"
|
21
|
+
|
22
|
+
links = (bar.open() + bar.link_to("ff", "aa") + bar.close())
|
23
|
+
|
24
|
+
links.should.eql "<ul class=\"linkBar\"><li><a href=\"aa\">ff</a></li></ul>"
|
25
|
+
end
|
26
|
+
|
4
27
|
end
|
5
28
|
|
29
|
+
describe "with options"
|
30
|
+
before_each
|
31
|
+
bar = new NavBar( {nav_open:"<div>", nav_close:"</div>",link_wrapper:function(link){
|
32
|
+
return "<span>" + link + "</span>"
|
33
|
+
}} )
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should generate list with wrappers"
|
37
|
+
links = (bar.open() + bar.link_to("ff") + bar.close())
|
38
|
+
|
39
|
+
links.should.eql "<div><span><a href=\"ff\">ff</a></span></div>"
|
40
|
+
end
|
6
41
|
|
7
|
-
it "should generate list by default"
|
8
|
-
(bar.open() + bar.close()).should.eql "<ul class=\"linkBar\"></ul>"
|
9
42
|
end
|
10
43
|
|
11
|
-
|
44
|
+
describe "with separator"
|
45
|
+
before_each
|
46
|
+
separator = " --- "
|
47
|
+
bar = new NavBar({separator: separator})
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should not separate single links"
|
51
|
+
links = (bar.open() + bar.link_to("ff") + bar.close())
|
52
|
+
links.should.eql "<ul class=\"linkBar\"><li><a href=\"ff\">ff</a></li></ul>"
|
53
|
+
end
|
12
54
|
|
13
|
-
|
55
|
+
it "should separate multiple links"
|
56
|
+
links = (bar.open() + bar.link_to("ff") + bar.link_to("aa") + bar.close())
|
57
|
+
links.should.eql "<ul class=\"linkBar\"><li><a href=\"ff\">ff</a></li>" + separator + "<li><a href=\"aa\">aa</a></li></ul>"
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should not display for missing links"
|
61
|
+
bar.nav_open = "<div>"
|
62
|
+
bar.nav_close = "</div>"
|
63
|
+
bar.link_wrapper = function (link) {
|
64
|
+
if (link.match(/aa/)) {
|
65
|
+
return ""
|
66
|
+
} else {
|
67
|
+
return link
|
68
|
+
}
|
69
|
+
}
|
70
|
+
|
71
|
+
links = (bar.open() + bar.link_to("ff") + bar.link_to("aa") + bar.link_to("gg") + bar.close())
|
72
|
+
links.should.eql "<div><a href=\"ff\">ff</a>" + separator + "<a href=\"gg\">gg</a></div>"
|
73
|
+
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
|
78
|
+
describe "with class-wide options"
|
79
|
+
before_each
|
80
|
+
NavBar.default_options = {nav_open:"<div>", nav_close:"</div>",link_wrapper:function(link){
|
81
|
+
return "<span>" + link + "</span>"
|
82
|
+
}}
|
83
|
+
bar = new NavBar( )
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should generate list with wrappers"
|
87
|
+
links = (bar.open() + bar.link_to("ff") + bar.close())
|
88
|
+
|
89
|
+
links.should.eql "<div><span><a href=\"ff\">ff</a></span></div>"
|
90
|
+
end
|
91
|
+
|
92
|
+
after_each
|
93
|
+
NavBar.default_options = {}
|
94
|
+
end
|
14
95
|
|
15
|
-
links.should.eql "<ul class=\"linkBar\"><li><a href=\"ff\">ff</a></li><li><a href=\"aa\">aa</a></li></ul>"
|
16
96
|
end
|
17
|
-
|
97
|
+
|
98
|
+
|
99
|
+
end
|
100
|
+
|
data/init.rb
CHANGED
data/lib/extras/ice_view.rb
CHANGED
@@ -44,12 +44,9 @@ class IceView
|
|
44
44
|
assigns.merge!(local_assigns.stringify_keys)
|
45
45
|
|
46
46
|
route_functions = "<% " + get_routes + " %>"
|
47
|
-
puts route_functions
|
48
|
-
5.times {puts "****************************"}
|
49
47
|
|
50
48
|
path_helper_code = File.read(File.dirname(__FILE__) + "/../../ice_js/lib/path_helper.js")
|
51
49
|
path_helper = "<% " + path_helper_code + " %>"
|
52
|
-
puts path_helper
|
53
50
|
source = route_functions + path_helper + source
|
54
51
|
|
55
52
|
|
data/lib/ice/cubeable.rb
CHANGED
data/lib/parser.js
CHANGED
@@ -256,19 +256,6 @@ var Jst = function () {
|
|
256
256
|
return fragment.toString();
|
257
257
|
}
|
258
258
|
|
259
|
-
function safeWrite(s) {
|
260
|
-
s = s.toString();
|
261
|
-
s = s.replaceAll('&', '&');
|
262
|
-
s = s.replaceAll('"', '"');
|
263
|
-
s = s.replaceAll('<', '<');
|
264
|
-
s = s.replaceAll('>', '>');
|
265
|
-
html += s;
|
266
|
-
}
|
267
|
-
|
268
|
-
function safeWriteln(s) {
|
269
|
-
safeWrite(s + "\n");
|
270
|
-
}
|
271
|
-
|
272
259
|
function write(s) {
|
273
260
|
html += s;
|
274
261
|
}
|
@@ -292,14 +279,8 @@ var Jst = function () {
|
|
292
279
|
c = stack.pop();
|
293
280
|
if (stack.peek() == '%') { //delimiter!
|
294
281
|
c = stack.pop();
|
295
|
-
if (stack.peek() == "=") {
|
296
|
-
//
|
297
|
-
stack.pop();
|
298
|
-
fragment = parseExpression(stack);
|
299
|
-
appendExpressionFragment(writer, fragment,
|
300
|
-
"safeWrite");
|
301
|
-
} else if (stack.peek() == "+") {
|
302
|
-
// expression, don't escape html
|
282
|
+
if (stack.peek() == "=" || stack.peek() == "+") {
|
283
|
+
//not escaping html right now
|
303
284
|
stack.pop()
|
304
285
|
fragment = parseExpression(stack);
|
305
286
|
appendExpressionFragment(writer, fragment,
|
data/spec/cube_spec.rb
CHANGED
data/spec/ice_spec.rb
CHANGED
@@ -2,8 +2,6 @@ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
|
2
2
|
|
3
3
|
describe "Ice" do
|
4
4
|
|
5
|
-
|
6
|
-
|
7
5
|
it "converts a javascript template to html" do
|
8
6
|
Ice.convert_template("<%= 'hello world' %>").should == "hello world"
|
9
7
|
end
|
@@ -13,6 +11,11 @@ describe "Ice" do
|
|
13
11
|
Ice.convert_template("<%= hola + ' ' + mundo %>", vars).should == "hello world"
|
14
12
|
end
|
15
13
|
|
14
|
+
it "accepts ampersands" do
|
15
|
+
vars = {:foo => "&"}
|
16
|
+
Ice.convert_template("<%= foo %>", vars).should == "&"
|
17
|
+
end
|
18
|
+
|
16
19
|
it "takes variables as string" do
|
17
20
|
vars = {'hola' => "hello", 'mundo' => "world" }
|
18
21
|
Ice.convert_template("<%= hola + ' ' + mundo %>", vars).should == "hello world"
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 2
|
8
|
-
-
|
9
|
-
version: 0.2.
|
8
|
+
- 3
|
9
|
+
version: 0.2.3
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Nate Kidwell
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-06-
|
17
|
+
date: 2010-06-09 00:00:00 -04:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -85,6 +85,7 @@ files:
|
|
85
85
|
- ice_js/spec/rhino.js
|
86
86
|
- ice_js/spec/server.html
|
87
87
|
- ice_js/spec/server.rb
|
88
|
+
- ice_js/spec/support/js.jar
|
88
89
|
- ice_js/spec/unit/spec.helper.js
|
89
90
|
- ice_js/spec/unit/spec.js
|
90
91
|
- init.rb
|