jam 0.2

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