jam 0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,75 @@
1
+ = Unit Tests for Jam LibXML Adapter
2
+
3
+ Require adapter.
4
+
5
+ require "jam/libxml"
6
+
7
+ This automatically requires 'libxml' too.
8
+
9
+ == LibXML::XML::Document
10
+
11
+ === #jam
12
+
13
+ Jam data into a LibXML Document.
14
+
15
+ xml = LibXML::XML::Document.string <<-EOS
16
+ <root><x><m id="a">dummy</m><n id="b">dummy</n></x></root>
17
+ EOS
18
+
19
+ data = {
20
+ :a => "A",
21
+ :b => "B"
22
+ }
23
+
24
+ out = xml.jam(data)
25
+ out = out.root.to_s.gsub(/\n\s*/,'')
26
+
27
+ out.should == %{<root><x><m id="a">A</m><n id="b">B</n></x></root>}
28
+
29
+ == LibXML::XML::Node
30
+
31
+ === #jam
32
+
33
+ Jam data into a LibXML Node.
34
+
35
+ xml = LibXML::XML::Document.string <<-EOS
36
+ <root><x><m id="a">dummy</m><n id="b">dummy</n></x></root>
37
+ EOS
38
+
39
+ node = xml.root
40
+
41
+ data = {
42
+ :a => "A",
43
+ :b => "B"
44
+ }
45
+
46
+ out = node.jam(data)
47
+ out = out.to_s.gsub(/\n\s*/,'')
48
+
49
+ out.should == %{<root><x><m id="a">A</m><n id="b">B</n></x></root>}
50
+
51
+ == LibXML::XML::XPath::Object
52
+
53
+ === #jam
54
+
55
+ Jam data into the Nodes of a LibXML::XPath::Object.
56
+
57
+ xml = LibXML::XML::Document.string <<-EOS
58
+ <root><x><m id="a" class="q">dummy</m><n id="b" class="q">dummy</n></x></root>
59
+ EOS
60
+
61
+ nodes = xml.find(".//*[@class='q']") #('.q')
62
+
63
+ data = { :a => "A", :b => "B" }
64
+
65
+ out = nodes.jam(data)
66
+
67
+ # can't get string?
68
+ out = out.inject(""){ |m, n| m += n.to_s }
69
+
70
+ out = out.gsub(/\n\s*/,'')
71
+
72
+ out.should == %{<m id="a" class="q">A</m><n id="b" class="q">B</n>}
73
+
74
+ QED.
75
+
@@ -0,0 +1,148 @@
1
+ = Unit Tests for Jam Nokogiri Adapter
2
+
3
+ Require adapter.
4
+
5
+ require "jam/nokogiri"
6
+
7
+ This automatically requires 'nokogiri' too.
8
+
9
+ == Jam::Nokogiri
10
+
11
+ Support objects for following tests.
12
+
13
+ @xml = "<root><a>A</a><b>B</b><c>C</c></root>"
14
+ @eng = Jam::Nokogiri.new
15
+
16
+ BEFORE: We will resuse this XML document.
17
+
18
+ @doc = @eng.document(@xml)
19
+
20
+ === #append
21
+
22
+ Append should be able to append an XML node.
23
+
24
+ node = @doc.root
25
+ node2 = node.children[0].dup
26
+
27
+ @eng.append(node, node2)
28
+
29
+ out = node.to_s.gsub(/\n\s*/,'')
30
+ out.should == '<root><a>A</a><b>B</b><c>C</c><a>A</a></root>'
31
+
32
+ Append should be able to append a NodeSet.
33
+
34
+ node = @doc.root
35
+ nodeset = @doc.root.children.dup
36
+
37
+ @eng.append(node, nodeset)
38
+
39
+ out = node.to_s.gsub(/\n\s*/,'')
40
+ out.should == '<root><a>A</a><b>B</b><c>C</c><a>A</a><b>B</b><c>C</c></root>'
41
+
42
+ Append should be able to append an XML text fragment.
43
+
44
+ node = @doc.root
45
+
46
+ @eng.append(node, '<d>D</d>')
47
+
48
+ out = node.to_s.gsub(/\n\s*/,'')
49
+ out.should == '<root><a>A</a><b>B</b><c>C</c><d>D</d></root>'
50
+
51
+ === #replace_content_with_text
52
+
53
+ It should replace node children with given text.
54
+
55
+ node = @doc.root
56
+
57
+ @eng.replace_content_with_text(node, 'H')
58
+
59
+ out = node.to_s.gsub(/\n\s*/,'')
60
+ out.should == '<root>H</root>'
61
+
62
+ It should be able to replace the children of each node of a NodeSet with text.
63
+
64
+ node = @doc.root
65
+ nodeset = @doc.root.children
66
+
67
+ @eng.replace_content_with_text(nodeset, 'H')
68
+
69
+ out = node.to_s.gsub(/\n\s*/,'')
70
+ out.should == '<root><a>H</a><b>H</b><c>H</c></root>'
71
+
72
+ === #cleanup
73
+
74
+ This will clean a document, or node, of any elements that request it.
75
+
76
+ doc = @eng.document('<root><a jam="erase">This is text.</a></root>')
77
+
78
+ @eng.cleanup(doc)
79
+
80
+ out = doc.root.to_s.gsub(/\n\s*/,'')
81
+ out.should == '<root>This is text.</root>'
82
+
83
+
84
+ == ::Nokogiri::Document
85
+
86
+ === #jam
87
+
88
+ Jam data into a Nokogiri Document.
89
+
90
+ xml = Nokogiri::XML <<-EOS
91
+ <root><x><m id="a">dummy</m><n id="b">dummy</n></x></root>
92
+ EOS
93
+
94
+ data = {
95
+ :a => "A",
96
+ :b => "B"
97
+ }
98
+
99
+ out = xml.jam(data)
100
+ out = out.root.to_s.gsub(/\n\s*/,'')
101
+
102
+ out.should == %{<root><x><m id="a">A</m><n id="b">B</n></x></root>}
103
+
104
+ == ::Nokogiri::Node
105
+
106
+ === #jam
107
+
108
+ Jam data into a Nokogiri Node.
109
+
110
+ xml = Nokogiri::XML <<-EOS
111
+ <root><x><m id="a">dummy</m><n id="b">dummy</n></x></root>
112
+ EOS
113
+
114
+ node = xml.root
115
+
116
+ data = {
117
+ :a => "A",
118
+ :b => "B"
119
+ }
120
+
121
+ out = node.jam(data)
122
+ out = out.to_s.gsub(/\n\s*/,'')
123
+
124
+ out.should == %{<root><x><m id="a">A</m><n id="b">B</n></x></root>}
125
+
126
+ == ::Nokogiri::NodeSet
127
+
128
+ === #jam
129
+
130
+ Jam data into a Nokogiri Node.
131
+
132
+ xml = Nokogiri::XML <<-EOS
133
+ <root><x><m id="a" class="q">dummy</m><n id="b" class="q">dummy</n></x></root>
134
+ EOS
135
+
136
+ nodeset = xml.search('.q')
137
+
138
+ p nodeset.search('#a')
139
+
140
+ data = { :a => "A", :b => "B" }
141
+
142
+ out = nodeset.jam(data)
143
+ out = out.to_s.gsub(/\n\s*/,'')
144
+
145
+ out.should == %{<m id="a" class="q">A</m><n id="b" class="q">B</n>}
146
+
147
+ QED.
148
+
@@ -0,0 +1,63 @@
1
+ = Unit Tests for Jam REXML Adapter
2
+
3
+ Require adapter.
4
+
5
+ require "jam/rexml"
6
+
7
+ This automatically requires 'rexml/document' too.
8
+
9
+ == REXML::Document
10
+
11
+ === #jam
12
+
13
+ Jam data into a REXML Document.
14
+
15
+ xml = REXML::Document.new <<-EOS
16
+ <root><x><m id="a">dummy</m><n id="b">dummy</n></x></root>
17
+ EOS
18
+
19
+ data = {:a => "A", :b => "B"}
20
+
21
+ out = xml.jam(data)
22
+ out = out.root.to_s.gsub(/\n\s*/,'')
23
+
24
+ out.should == %{<root><x><m id="a">A</m><n id="b">B</n></x></root>}
25
+
26
+ == REXML::Node
27
+
28
+ === #jam
29
+
30
+ Jam data into a REXML Node.
31
+
32
+ xml = REXML::Document.new <<-EOS
33
+ <root><x><m id="a">dummy</m><n id="b">dummy</n></x></root>
34
+ EOS
35
+
36
+ node = xml.root
37
+
38
+ data = {:a => "A", :b => "B"}
39
+
40
+ out = node.jam(data)
41
+ out = out.to_s.gsub(/\n\s*/,'')
42
+
43
+ out.should == %{<root><x><m id="a">A</m><n id="b">B</n></x></root>}
44
+
45
+ == REXML::XPath
46
+
47
+ === #jam_each
48
+
49
+ Jam data into the nodes of a REXML::XPath object.
50
+
51
+ xml = REXML::Document.new <<-EOS
52
+ <root><x><m id="a" class="q">dummy</m><n id="b" class="q">dummy</n></x></root>
53
+ EOS
54
+
55
+ data = { :a => "A", :b => "B" }
56
+
57
+ out = REXML::XPath.jam(xml, data)
58
+ out = out.to_s.gsub(/\n\s*/,'')
59
+
60
+ out.should == %{<m id="a" class="q">A</m><n id="b" class="q">B</n>}
61
+
62
+ QED.
63
+
@@ -0,0 +1,20 @@
1
+ require 'jam'
2
+
3
+ tmpl = Jam::Template.new <<-END
4
+ <html>
5
+ <body>
6
+ <h1 id="title">title will be inserted here</h1>
7
+ <p id="body">body text will be inserted here</p>
8
+ </body>
9
+ </html>
10
+ END
11
+
12
+ data = {
13
+ :title => "hello world",
14
+ :body => "Amrita is a html template libraly for Ruby"
15
+ }
16
+
17
+ out = tmpl.expand(data)
18
+
19
+ puts out
20
+
@@ -0,0 +1,12 @@
1
+ require 'jam'
2
+
3
+ tmpl = Jam::Template.new <<-END
4
+ <example id="a"></example>]
5
+ END
6
+
7
+ data = { :a => "Hello World" }
8
+
9
+ out = tmpl.render(data)
10
+
11
+ puts out
12
+
@@ -0,0 +1,19 @@
1
+ require 'jam'
2
+
3
+ class A
4
+ attr :a
5
+ def initialize
6
+ @a = "A"
7
+ end
8
+ end
9
+
10
+ tmpl = Jam::Template.new <<-END
11
+ <example id="a"></example>]
12
+ END
13
+
14
+ data = A.new
15
+
16
+ out = tmpl.render(data)
17
+
18
+ puts out
19
+
@@ -0,0 +1,24 @@
1
+ require 'jam'
2
+
3
+ tmpl = Jam::Template.new <<-END
4
+ <table border="1">
5
+ <tr><th>name</th><th>author</th></tr>
6
+ <tr id="table1">
7
+ <td id="name"></td>
8
+ <td id="author"></td>
9
+ </tr>
10
+ </table>
11
+ END
12
+
13
+ data = {
14
+ :table1=>[
15
+ { :name=>"Ruby", :author=>"Matz" },
16
+ { :name=>"Perl", :author=>"Larry Wall" },
17
+ { :name=>"Python", :author=>"Guido van Rossum" }
18
+ ]
19
+ }
20
+
21
+ out = tmpl.expand(data)
22
+
23
+ puts out
24
+
@@ -0,0 +1,230 @@
1
+ // Jam Templates -- a jQuery Plugin
2
+ // Copyright (c) 2007,2008 Tiger Ops
3
+ // http://tigerops.psytower.info
4
+ //
5
+ // Jam is a "weaving" template system that
6
+ // operate fully on the front-end, thus off-loading
7
+ // some of the back-end work load while also
8
+ // providing 100% SOC (Seperation of Concern).
9
+ //
10
+ // Example:
11
+ //
12
+ // data = {
13
+ // hello: "Hello, World!"
14
+ // }
15
+ //
16
+ // $.jam(data)
17
+ //
18
+ // Jam templates are especially useful when
19
+ // filled via AJAX with JSON data. For this reason
20
+ // a shortcut is provided.
21
+ //
22
+ // $.jam_ajax('http://somewhere/data.json')
23
+ //
24
+
25
+ // FOR DEBUGGING
26
+ /*
27
+ function inspect(obj) {
28
+ var txt = "";
29
+ for(var prop in obj) {
30
+ txt += prop + ": " + obj[prop] + "\n";
31
+ }
32
+ alert(txt);
33
+ };
34
+ */
35
+
36
+ //
37
+ //
38
+ //
39
+ jQuery.jam_ajax = function(url) {
40
+ result = url.match(/[.]xml$/);
41
+ if (result != null) {
42
+ jQuery.getXML(url, jQuery.cherry_xml);
43
+ } else {
44
+ jQuery.getJSON(url, jQuery.cherry);
45
+ }
46
+ };
47
+
48
+ //
49
+ //
50
+ //
51
+ jQuery.getXML = function(url, callback) {
52
+ jQuery.ajax({
53
+ dataType: "xml",
54
+ url: url,
55
+ success: callback
56
+ });
57
+ };
58
+
59
+ //
60
+ // Interpolate XML by converting to JSON.
61
+ // This only work is xml2json.js is loaded.
62
+ //
63
+ jQuery.jam_xml = function(xml) {
64
+ var json = xml2json(xml,' ');
65
+ //var data = json.parseJSON();
66
+ var data = eval('(' + json + ')'); // SECURE ME!
67
+ jQuery.jam(data);
68
+ };
69
+
70
+ //
71
+ // Interpolate JSON data.
72
+ //
73
+ // TODO: how to do whole document instead of body?
74
+ jQuery.jam = function(data) {
75
+ // jQuery('body').interpolate(data);
76
+ // jQuery('body').jam_cleanup();
77
+ jQuery.interpolate(data);
78
+ jQuery.jam_cleanup();
79
+ };
80
+
81
+ //
82
+ // Remove any unwanted jam tags.
83
+ //
84
+ // TODO: remove jam attributes too.
85
+ jQuery.jam_cleanup = function() {
86
+ jQuery("[@jam='erase']").unwrap();
87
+ };
88
+
89
+ //
90
+ // Interpolate data into template nodes.
91
+ //
92
+ jQuery.fn.interpolate = function(data) {
93
+ if(!data) {
94
+ this.remove();
95
+ }
96
+ else if (data instanceof Array) {
97
+ this.interpolate_sequence(data);
98
+ }
99
+ else if(data instanceof Object) {
100
+ this.interpolate_object(data);
101
+ }
102
+ else {
103
+ this.interpolate_scalar(data);
104
+ };
105
+ return this;
106
+ };
107
+
108
+ //
109
+ // Interpolate object mapping.
110
+ //
111
+ jQuery.fn.interpolate_object = function(data) {
112
+ var qry;
113
+ var attr;
114
+ var tag;
115
+ var result;
116
+ var match;
117
+
118
+ for (var id in data) {
119
+ attr = false;
120
+ tag = false;
121
+ qry = id;
122
+
123
+ result = qry.match(/^<(.*?)>$/);
124
+ if (result != null) {
125
+ tag = true;
126
+ qry = result[1];
127
+ };
128
+
129
+ result = qry.match(/^((.*?)\/)?([@](.*?))$/);
130
+ if (result != null) {
131
+ if (result[2] == undefined) { result[2] = null };
132
+ attr = result[4];
133
+ qry = result[2] //+ '[@' + attr + ']';
134
+ }
135
+ else {
136
+ attr = false;
137
+ };
138
+
139
+ if (attr == false) {
140
+ if (tag == false) { qry = '#' + qry; }
141
+ // probably change to use 'ref' attribute instead of 'id'
142
+ match = this.find(qry)
143
+ if (match.size() > 0) {
144
+ match.interpolate(data[id]);
145
+ }
146
+ }
147
+ else {
148
+ //qry = qry + '[@' + attr + ']';
149
+ //this.find(qry).attr(attr,data[id]);
150
+ if (qry != null) {
151
+ if (tag == false) { qry = '#' + qry; }
152
+ this.find(qry).attr(attr,data[id]);
153
+ } else {
154
+ this.attr(attr,data[id]);
155
+ }
156
+ };
157
+ };
158
+ };
159
+
160
+ //
161
+ // Interpolate attribute.
162
+ //
163
+ // TODO
164
+
165
+ //
166
+ // Interpolate array sequence.
167
+ //
168
+ jQuery.fn.interpolate_sequence = function(data) {
169
+ var temp = this.clone();
170
+ this.empty();
171
+ for (var i in data) {
172
+ var newNode = temp.clone();
173
+ newNode.interpolate(data[i]);
174
+ this.append(newNode); //.children());
175
+ };
176
+ };
177
+
178
+ //
179
+ // Interpolate scalar value.
180
+ //
181
+ // TODO: Should this has some special HTML features?
182
+ //
183
+ // TODO: Should we have two modes --one with and one
184
+ // without the extra HTML features?
185
+ //
186
+ jQuery.fn.interpolate_scalar = function(data) {
187
+ //var all_special = new Array;
188
+
189
+ // text inputs
190
+ //var special = this.find('input[@type=text]');
191
+ //special.val(data.toString());
192
+ //all_special.concat(special);
193
+ // textarea
194
+ // TODO
195
+
196
+ //this.not(special).empty();
197
+ //this.not(special).append(data.toString());
198
+ //alert(data);
199
+ this.empty();
200
+ this.append(data.toString());
201
+ };
202
+
203
+ //
204
+ // Unwrap a node, such that the outer tag is
205
+ // removed, leaving only it's own children.
206
+ //
207
+ jQuery.fn.unwrap = function(expr) {
208
+ return this.each(function(){
209
+ $(this).parents(expr).eq(0).after(this).remove();
210
+ });
211
+ };
212
+
213
+
214
+
215
+ /*
216
+ // Interpolate list.
217
+
218
+ function interpolate_list(node, data) {
219
+ temp = node.copy(true)
220
+ node.empty!
221
+ for (var d in data) {
222
+ nc = temp.copy(true);
223
+ interpolate_children( nc, d )
224
+ for (var c in nc.children) {
225
+ node.add(c);
226
+ };
227
+ };
228
+ };
229
+ */
230
+