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.
@@ -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