JsRender/Node.vala
[app.Builder.js] / JsRender / Node.vala
1
2 // test..
3 // valac gitlive/app.Builder.js/JsRender/Lang.vala gitlive/app.Builder.js/JsRender/Node.vala --pkg gee-1.0 --pkg=json-glib-1.0 -o /tmp/Lang ;/tmp/Lang
4
5 class JsRender.Node  {
6     
7     GLib.List<JsRender.Node> items; // child items..
8     
9     Gee.HashMap<string,string> props; // the properties..
10     
11   
12     
13     public bool is_array;
14     
15     Node()
16     {
17         this.items = new GLib.List<JsRender.Node>();
18         this.props = new Gee.HashMap<string,string>();
19         this.is_array = false;
20         
21     }
22     
23     
24     
25     
26     bool isArray()
27     {
28         return this.is_array;
29     }
30     bool hasChildren()
31     {
32         return this.items.length() > 0;
33     }
34     bool hasXnsType()
35     {
36         if (this.props.get("|xns") != null && this.props.get("xtype") != null) {
37             return true;
38             
39         }
40         return false;
41     }
42     // wrapper around get props that returns empty string if not found.
43     string get(string key)
44     {
45         var k = this.props.get(key);
46         if (k == null) {
47             return "";
48         }
49         return k;
50         
51     }
52      
53     /* creates javascript based on the rules */
54     
55     string mungeToString (bool isListener, string pad)
56     {
57         
58          
59         pad = pad.length < 1 ? "    " : pad;
60         
61         
62          
63         
64         //isListener = isListener || false;
65
66        //var keys = this.keys();
67         var isArray = this.isArray();
68         
69         
70         var els = new GLib.List<string>(); 
71         var skip = new Gee.ArrayList<string>();
72         if (!isArray && this.hasXnsType() ) {
73                 // this.mungeXtype(obj['|xns'] + '.' + obj['xtype'], els); ??????
74                 
75                 
76                skip.add("|xns");
77                skip.add("xtype");
78                
79         }
80         //var newitems = new Gee.ArrayList<JsRender.Node>();
81         var oprops = new Gee.HashMap<string,JsRender.Node>();
82         
83         if (!isArray && this.hasChildren()) {
84             // look for '*props'
85            
86             for (var ii =0; ii< this.items.length(); ii++) {
87                 var pl = this.items.nth_data(ii);
88                 if (!pl.props.has_key("*prop")) {
89                     //newitems.add(pl);
90                     continue;
91                 }
92                 
93                 //print(JSON.stringify(pl,null,4));
94                 // we have a prop...
95                 //var prop = pl['*prop'] + '';
96                 //delete pl['*prop'];
97                 var prop = pl.get("*prop");
98                 // name ends in [];
99                 if (! Regex.match_simple("\\[\\]$", prop)) {
100                     // it's a standard prop..
101                     
102                     // munge property..??
103                     oprops.set(prop, pl);
104                     
105                     
106                     //keys.push(prop);
107                     continue;
108                 }
109                 
110                 prop  = prop.substring(0,  -2); //strip []
111                 // it's an array type..
112                 if (!oprops.has_key(prop)) {
113                     var cn = new JsRender.Node();
114                     oprops.set(prop, pl);
115                     
116                 }
117                 // ignores the fact it might be duplciated...
118                 oprops.get(prop).is_array = true;
119                 oprops.get(prop).items.append(pl);
120               
121                 
122                 
123                 
124             }
125             
126             //obj.items = newitems;
127             //if (!obj.items.length) {
128             //    delete obj.items;
129             //}
130             
131         }
132         if (this.isArray()) {
133             
134             
135             for (var i=0;i< this.items.length();i++) {
136                 var el = this.items.nth_data(i);
137                 
138                 els.append("%d".printf(i) + " : " + el.mungeToString(false, pad));
139                 
140             }
141             var spad = pad.substring(0, pad.length-4);
142             return   "{\n" +
143                 pad  + string.join(",\n" + pad , els) + 
144                 "\n" + spad +  "}";
145                
146             
147             
148             
149           
150         } 
151         string left;
152         Regex func_regex ;
153         try {
154             func_regex = new Regex("^\\s+|\\s+$");
155         } catch (Error e) {
156             print("failed to build regex");
157             return "";
158         }
159         var piter = this.props.map_iterator();
160         while (piter.next() ) {
161             var k = piter.get_key();
162             var v = piter.get_value();
163             
164             if (skip.contains(k) ) {
165                 continue;
166             }
167             
168             
169             string leftv = k[0] == '|' ? k.substring(1) : k;
170             // skip builder stuff. prefixed with  '.' .. just like unix fs..
171             if (leftv[0] == '.') { // |. or . -- do not output..
172                 continue;
173             }
174              if (k[0] == '*') {
175                 // ignore '*prop';
176                 continue;
177              }
178                 
179             
180             if (JsRender.Lang.isKeyword(leftv) || JsRender.Lang.isBuiltin(leftv)) {
181                 left = "'" + leftv + "'";
182             } else if (Regex.match_simple("[^A-Za-z_]+",leftv)) { // not plain a-z... - quoted.
183                 var val = this.quoteString(leftv);
184                 
185                 left = "'" + val.substring(1, val.length-1).replace("'", "\\'") + "'";
186             } else {
187                 left = leftv;
188             }
189             left += " : ";
190             
191             if (isListener) {
192             // change the lines...
193                 var str= func_regex.replace(v, v.length, 0, "");  // remove bar. ???
194                 var lines = str.split("\n");
195                 if (lines.length > 1) {
196                     str = string.join("\n" + pad, lines);
197                 }
198                 
199                 els.append(left  + str);
200                 continue;
201             }
202              
203             // next.. is it a function..
204             if (k[0] == '|') {
205                 // does not hapepnd with arrays.. 
206                 if (v.length < 1) {  //if (typeof(el) == 'string' && !obj[i].length) { //skip empty.
207                     continue;
208                 }
209                 
210                 var str= func_regex.replace(v,v.length, 0, "");
211                 var lines = str.split("\n");
212                 if (lines.length > 1) {
213                     str =  string.join("\n" + pad, lines);
214                 }
215                 
216                 els.append(left + str);
217                 continue;
218             }
219             // standard..
220             
221             
222             if (JsRender.Lang.isNumber(v) || JsRender.Lang.isBoolean(v)) { // boolean or number...?
223                 els.append(left + v );
224                 continue;
225             }
226             /* -- fix me - we need a wrapper that starts this..
227             // strings..
228             if (!this.doubleStringProps.length) {
229                 els.append(left + this.quoteString(v));
230                 continue;
231             }
232            
233             if (this.doubleStringProps.index(k) > -1) {
234                 els.append(left + this.quoteString(v));
235                 continue;
236             }
237             */
238             // single quote.. v.substring(1, v.length-1).replace("'", "\\'") + "'";
239             els.append(left + "'" + v.substring(1, v.length-1).replace("'", "\\'") + "'");
240             
241
242            
243            
244            
245         }
246         var iter = oprops.map_iterator();
247         while (iter.next()) {
248             var k = iter.get_key();
249             var vo = iter.get_value();
250             string leftv = k[0] == '|' ? k.substring(1) : k;
251             if (JsRender.Lang.isKeyword(leftv) || JsRender.Lang.isBuiltin(leftv)) {
252                 left = "'" + leftv + "'";
253             } else if (Regex.match_simple("[^A-Za-z_]+",leftv)) { // not plain a-z... - quoted.
254                 var val = this.quoteString(leftv);
255                 
256                 left = "'" + val.substring(1, val.length-1).replace("'", "\\'") + "'";
257             } else {
258                 left = leftv;
259             }
260             left += " : ";
261             
262             var right = vo.mungeToString(k == "listeners", pad + "    ");
263             
264             //if (!left.length && isArray) print(right);
265             
266             if (right.length > 0){
267                 els.append(left + right);
268             }
269         
270             
271         }
272         if (els.length < 1) {
273             return "";
274         }
275         // oprops...    
276             
277         var spad = pad.substring(0, pad.length-4);
278         return   "{\n" +
279             pad  + string.join(",\n" + pad , els) + 
280             "\n" + spad +  "}";
281            
282            
283                
284         
285         
286     }
287     static Json.Generator gen = null;
288     
289     string quoteString(string str)
290     {
291         if (Node.gen == null) {
292             Node.gen = new Json.Generator();
293         }
294         var builder = new Json.Builder();
295         builder.add_string_value(str);
296         Node.gen.set_root (builder.get_root ());
297         return  Node.gen.to_data (null);   
298     }
299     
300 }