initial import
[roojs1] / buildSDK / doc_templates / publish.js
1 //<script type="text/javascript">
2 // not we use xxx = function() - as this get's loaded by a nested eval..
3 // 
4
5
6 JSON = new (function(){
7     var useHasOwn = {}.hasOwnProperty ? true : false;
8     
9     // crashes Safari in some instances
10     //var validRE = /^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/;
11     
12     var pad = function(n) {
13         return n < 10 ? "0" + n : n;
14     };
15     
16     var m = {
17         "\b": '\\b',
18         "\t": '\\t',
19         "\n": '\\n',
20         "\f": '\\f',
21         "\r": '\\r',
22         '"' : '\\"',
23         "\\": '\\\\'
24     };
25
26     var encodeString = function(s){
27         if (/["\\\x00-\x1f]/.test(s)) {
28             return '"' + s.replace(/([\x00-\x1f\\"])/g, function(a, b) {
29                 var c = m[b];
30                 if(c){
31                     return c;
32                 }
33                 c = b.charCodeAt();
34                 return "\\u00" +
35                     Math.floor(c / 16).toString(16) +
36                     (c % 16).toString(16);
37             }) + '"';
38         }
39         return '"' + s + '"';
40     };
41     
42     var encodeArray = function(o){
43         var a = ["["], b, i, l = o.length, v;
44             for (i = 0; i < l; i += 1) {
45                 v = o[i];
46                 switch (typeof v) {
47                     case "undefined":
48                     case "function":
49                     case "unknown":
50                         break;
51                     default:
52                         if (b) {
53                             a.push(',');
54                         }
55                         a.push(v === null ? "null" : JSON.encode(v));
56                         b = true;
57                 }
58             }
59             a.push("]");
60             return a.join("");
61     };
62     
63     var encodeDate = function(o){
64         return '"' + o.getFullYear() + "-" +
65                 pad(o.getMonth() + 1) + "-" +
66                 pad(o.getDate()) + "T" +
67                 pad(o.getHours()) + ":" +
68                 pad(o.getMinutes()) + ":" +
69                 pad(o.getSeconds()) + '"';
70     };
71     
72     /**
73      * Encodes an Object, Array or other value
74      * @param {Mixed} o The variable to encode
75      * @return {String} The JSON string
76      */
77     this.encode = function(o){
78         if(typeof o == "undefined" || o === null){
79             return "null";
80         }else if(o instanceof Array){
81             return encodeArray(o);
82         }else if(o instanceof Date){
83             return encodeDate(o);
84         }else if(typeof o == "string"){
85             return encodeString(o);
86         }else if(typeof o == "number"){
87             return isFinite(o) ? String(o) : "null";
88         }else if(typeof o == "boolean"){
89             return String(o);
90         }else {
91             var a = ["{"], b, i, v;
92             for (i in o) {
93                 if(!useHasOwn || o.hasOwnProperty(i)) {
94                     v = o[i];
95                     switch (typeof v) {
96                     case "undefined":
97                     case "function":
98                     case "unknown":
99                         break;
100                     default:
101                         if(b){
102                             a.push(',');
103                         }
104                         a.push(this.encode(i), ":",
105                                 v === null ? "null" : this.encode(v));
106                         b = true;
107                     }
108                 }
109             }
110             a.push("}");
111             return a.join("");
112         }
113     };
114     
115     /**
116      * Decodes (parses) a JSON string to an object. If the JSON is invalid, this function throws a SyntaxError.
117      * @param {String} json The JSON string
118      * @return {Object} The resulting object
119      */
120     this.decode = function(json){
121         /**
122          * eval:var:json
123          */
124         return eval("(" + json + ')');
125     };
126 })();
127
128
129
130 publish  = function(symbolSet) {
131         publish.conf = {  // trailing slash expected for dirs
132                 ext: ".html",
133                 
134                 templatesDir: JSDOC.opt.t + "/",
135                 symbolsDir: "symbols/",
136                 srcDir: "symbols/src/"
137         };
138   
139         publish.conf.outDir = (JSDOC.opt.d.length > 0 ? JSDOC.opt.d : "/tmp/jsdoc/");
140         
141     
142     
143     
144         if (JSDOC.opt.s && defined(Link) && Link.prototype._makeSrcLink) {
145                 Link.prototype._makeSrcLink = function(srcFilePath) {
146                         return "&lt;"+srcFilePath+"&gt;";
147                 }
148         }
149         
150     println(publish.conf.outDir);
151     
152     if (!File.exists(publish.conf.outDir))
153         File.mkdir(publish.conf.outDir);
154     if (!File.exists(publish.conf.outDir+"symbols"))
155         File.mkdir(publish.conf.outDir+"symbols");
156     if (!File.exists(publish.conf.outDir+"symbols/src"))
157         File.mkdir(publish.conf.outDir+"symbols/src");
158     
159     IO.copyFile (publish.conf.templatesDir+"static/default.css", publish.conf.outDir, "default.css");
160     IO.copyFile (publish.conf.templatesDir+"static/doc.js", publish.conf.outDir, "doc.js");
161     IO.copyFile (publish.conf.templatesDir+"static/page.js", publish.conf.outDir, "page.js");
162   
163     
164         //IO.mkPath((publish.conf.outDir+"symbols/src").split("/"));
165                 
166         // used to check the details of things being linked to
167         Link.symbolSet = symbolSet;
168
169         //try {
170                 var classTemplate = new JSDOC.JsPlate(publish.conf.templatesDir+"class.tmpl");
171                 var classesTemplate = new JSDOC.JsPlate(publish.conf.templatesDir+"allclasses.tmpl");
172         //}
173         //atch(e) {
174         //      print(e.message);
175         ///     quit();
176         //}
177         
178         // filters
179     
180     classTemplate.symbolSet = symbolSet;
181     
182     
183         function hasNoParent($) {return ($.memberOf == "")}
184         function isaFile($) {return ($.is("FILE"))}
185         function isaClass($) { return ($.is("CONSTRUCTOR") || $.isNamespace); }
186         
187         var symbols = symbolSet.toArray();
188         
189         var files = JSDOC.opt.srcFiles;
190         for (var i = 0, l = files.length; i < l; i++) {
191                 var file = files[i];
192                 var srcDir = publish.conf.outDir + "symbols/src/";
193                 makeSrcFile(file, srcDir);
194         }
195         
196         var classes = symbols.filter(isaClass).sort(makeSortby("alias"));
197         
198         Link.base = "../";
199         publish.classesIndex = classesTemplate.process(classes); // kept in memory
200         
201     IO.makeDir(publish.conf.outDir+"json");
202     
203         for (var i = 0, l = classes.length; i < l; i++) {
204                 var symbol = classes[i];
205                 var output = "";
206         
207                 output = classTemplate.process(symbol);
208                 println("write " + publish.conf.outDir+"symbols/" +symbol.alias+publish.conf.ext);
209                 IO.saveFile(publish.conf.outDir+"symbols/", symbol.alias+publish.conf.ext, output);
210         // dump out a 
211         IO.saveFile(publish.conf.outDir+"json/",  symbol.alias+'.json' , publish.jsonRender(symbol));
212         
213         
214         }
215         
216         // regenrate the index with different relative links
217         Link.base = "";
218         publish.classesIndex = classesTemplate.process(classes);
219         
220         try {
221                 var classesindexTemplate = new JSDOC.JsPlate(publish.conf.templatesDir+"index.tmpl");
222         }
223         catch(e) { print(e.message); quit(); }
224         
225         var classesIndex = classesindexTemplate.process(classes);
226         IO.saveFile(publish.conf.outDir, "index"+publish.conf.ext, classesIndex);
227         classesindexTemplate = classesIndex = classes = null;
228         
229         try {
230                 var fileindexTemplate = new JSDOC.JsPlate(publish.conf.templatesDir+"allfiles.tmpl");
231         }
232         catch(e) { print(e.message); quit(); }
233         
234         var documentedFiles = symbols.filter(isaFile);
235         var allFiles = [];
236         
237         for (var i = 0; i < files.length; i++) {
238                 allFiles.push(new JSDOC.Symbol(files[i], [], "FILE", new JSDOC.DocComment("/** */")));
239         }
240         
241         for (var i = 0; i < documentedFiles.length; i++) {
242                 var offset = files.indexOf(documentedFiles[i].alias);
243                 allFiles[offset] = documentedFiles[i];
244         }
245                 
246         allFiles = allFiles.sort(makeSortby("name"));
247
248         var filesIndex = fileindexTemplate.process(allFiles);
249         IO.saveFile(publish.conf.outDir, "files"+publish.conf.ext, filesIndex);
250         fileindexTemplate = filesIndex = files = null;
251 }
252
253 publish.jsonRender = function(data)
254 {
255     // what we need to output to be usefull...
256     // a) props..
257     var cfgProperties = [];
258         if (!data.comment.getTag('singleton').length) {
259                 cfgProperties = data.configToArray();
260                 cfgProperties = cfgProperties.sort(makeSortby("name"));
261                 
262         }
263     var props = []; 
264     //println(cfgProperties.toSource());
265     var p ='';
266     for(var i =0; i < cfgProperties.length;i++) {
267         p = cfgProperties[i];
268         props.push( {
269             name : p.name,
270             type : p.type,
271             desc : p.desc,
272             memberOf : p.memberOf == data.alias ? '' : p.memberOf
273         });
274     }
275     
276      
277     var ownEvents = data.methods.filter( function(e){
278             return e.isEvent && !e.comment.getTag('hide').length;
279         }).sort(makeSortby("name"));
280                  
281     
282     var events = [];
283     var m;
284         for(var i =0; i < ownEvents.length;i++) {
285         m = ownEvents[i];
286         events.push( {
287             name : m.name.substring(1),
288             sig : makeFuncSkel(m.params),
289             type : 'function',
290             desc : m.desc
291         });
292     }
293     //println(props.toSource());
294     // we need to output:
295     //classname => {
296     //    propname => 
297     //        type=>
298     //        desc=>
299     //    }
300
301     var ret = {
302         props : props,
303         events: events
304     };
305     return JSON.encode(ret);
306         
307     
308     // b) methods
309     // c) events
310     
311     
312 }
313
314
315
316 /** Just the first sentence. */
317 summarize = function(desc) {
318         if (typeof desc != "undefined")
319                 return desc.match(/([\w\W]+?\.)[^a-z0-9]/i)? RegExp.$1 : desc;
320 }
321
322 /** make a symbol sorter by some attribute */
323 makeSortby = function(attribute) {
324         return function(a, b) {
325                 if (a[attribute] != undefined && b[attribute] != undefined) {
326                         a = a[attribute]; //.toLowerCase();
327                         b = b[attribute];//.toLowerCase();
328                         if (a < b) return -1;
329                         if (a > b) return 1;
330                         return 0;
331                 }
332         }
333 }
334 /*
335 function include(path) {
336         var path = publish.conf.templatesDir+path;
337         return IO.readFile(path);
338 }
339 */
340
341 function makeSrcFile(path, srcDir, name) {
342         if (JSDOC.opt.s) return;
343         
344         if (!name) {
345                 name = path.replace(/\.\.?[\\\/]/g, "").replace(/[\\\/]/g, "_");
346                 name = name.replace(/\:/g, "_");
347         }
348         
349         var src = {path: path, name:name, charset: IO.encoding, hilited: ""};
350         
351         if (JSDOC.hasOwnProperty('PluginManager')) {
352                 JSDOC.PluginManager.run("onPublishSrc", src);
353         }
354
355         if (src.hilited) {
356                 IO.saveFile(srcDir, name+publish.conf.ext, src.hilited);
357         }
358 }
359
360 makeSignature= function(params) {
361         if (!params) return "()";
362         var signature = "("     +
363         params.filter(
364             function($) {
365                 return $.name.indexOf(".") == -1; // don't show config params in signature
366             }
367         ).map(
368             function($) {
369                 $.defaultValue = typeof($.defaultValue) == 'undefined' ? false : $.defaultValue;
370                 
371                 return "" +
372                     ($.isOptional ? "[" : "") +
373                     (($.type) ? (new Link().toSymbol($.type)) + " " : "") + 
374                     "<B><i>" +$.name + "</i></B>" +
375                     ($.defaultValue ? "=" +item.defaultValue : "") +
376                     ($.isOptional ? "]" : "");
377                 
378                  
379             }
380         ).join(", ")
381         +
382         ")";
383         return signature;
384 }
385
386 makeFuncSkel =  function(params) {
387         if (!params) return "function ()\n{\n\n}";
388         return "function ("     +
389         params.filter(
390             function($) {
391                 return $.name.indexOf(".") == -1; // don't show config params in signature
392             }
393         ).map( function($) { return $.name == 'this' ? '_self' : $.name; } ).join(", ")
394         +
395         ")\n{\n\n}";
396         
397 }
398
399 /** Find symbol {@link ...} strings in text and turn into html links */
400 resolveLinks = function (str, from) {
401     if (typeof(str) == 'undefined') {
402         return '';
403     }
404         str = str.replace(/\{@link ([^} ]+) ?\}/gi,
405                 function(match, symbolName) {
406                         return new Link().toSymbol(symbolName);
407                 }
408         );
409         
410     str = str.replace(/\{([a-z\.\/]+)\}/gi,
411                 function(match, symbolName) {
412             //println("got match " + symbolName);
413             bits = symbolName.split('/');
414             var mret = '';
415             for(var i = 0; i < bits.length; i++) {
416                 
417                 mret += (mret.length ? '&nbsp;|&nbsp;' : '') + new Link().toSymbol(bits[i]);
418             }
419             
420             return mret; //new Link().toSymbol(symbolName);
421                 }
422         );
423     
424     // look for aaaa.\S+  ??? this might work???
425     /*
426     str = str.replace(/\([a-z]+\.\S+)/gi,
427                 function(match, symbolName) {
428             return new Link().toSymbol(symbolName);
429                 }
430         );
431     */
432     
433         return str;
434 }