ice 0.2.2 → 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -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. They are then interpreted in a sandboxed environment. Ice is similar to Liquid in terms of safety, but uses javascript to leverage the powers of a language most developers are familiar with.
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 runs the templates through an erb-ish parser and then uses the [therubyracer](http://github.com/cowboyd/therubyracer) to interpet the javascript using Google's V8 javascript engine. Your users can then write Ice templates like:
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 has several disadvantages
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.2
1
+ 0.2.3
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{ice}
8
- s.version = "0.2.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-04}
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",
@@ -1,24 +1,49 @@
1
- function link_to(location, default_label, opts) {
2
- if (! default_label) {
3
- default_label = location
1
+ function link_to(label, link, opts) {
2
+ if (! link) {
3
+ link = label
4
4
  }
5
- label = (opts && opts.label) || default_label
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
- return "<li>" + link_to(link) + "</li>"
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 = {}
@@ -1,17 +1,100 @@
1
- describe "nav bar helper"
2
- before_each
3
- bar = new NavBar()
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
- it "should generate list with internal links"
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
- links = (bar.open() + bar.link_to("ff") + bar.link_to("aa") + bar.close())
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
- end
97
+
98
+
99
+ end
100
+
data/init.rb CHANGED
@@ -1,4 +1,6 @@
1
1
  require 'ice'
2
2
  require 'ice/cubeable'
3
3
  require 'ice/cube_association'
4
- require 'ice/base_cube'
4
+ require 'ice/base_cube'
5
+
6
+ require 'active_support'
@@ -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
 
@@ -3,7 +3,6 @@ module Ice
3
3
  def get_cube_class(class_obj)
4
4
  begin
5
5
  cube_string = class_obj.to_s + "Cube"
6
- puts "getting string #{cube_string}"
7
6
  cube_string.constantize
8
7
  rescue
9
8
  get_cube_class class_obj.superclass
@@ -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('&', '&amp;');
262
- s = s.replaceAll('"', '&quot;');
263
- s = s.replaceAll('<', '&lt;');
264
- s = s.replaceAll('>', '&gt;');
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
- // expression, escape all html
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,
@@ -58,7 +58,6 @@ class BaseCubeWithHasMany
58
58
  def initialize
59
59
  @source = ChildModel.new
60
60
  end
61
-
62
61
  has_many :tags
63
62
  has_many :children
64
63
  end
@@ -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"
@@ -4,7 +4,6 @@ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
4
4
  require File.dirname(__FILE__) + "/../init"
5
5
  require 'spec'
6
6
  require 'spec/autorun'
7
- require 'active_support'
8
7
 
9
8
 
10
9
 
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 2
8
- - 2
9
- version: 0.2.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-04 00:00:00 -04:00
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