1 //<script type="text/javascript">
2 // not we use xxx = function() - as this get's loaded by a nested eval..
6 JSON = new (function(){
7 var useHasOwn = {}.hasOwnProperty ? true : false;
9 // crashes Safari in some instances
10 //var validRE = /^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/;
12 var pad = function(n) {
13 return n < 10 ? "0" + n : n;
26 var encodeString = function(s){
27 if (/["\\\x00-\x1f]/.test(s)) {
28 return '"' + s.replace(/([\x00-\x1f\\"])/g, function(a, b) {
35 Math.floor(c / 16).toString(16) +
36 (c % 16).toString(16);
42 var encodeArray = function(o){
43 var a = ["["], b, i, l = o.length, v;
44 for (i = 0; i < l; i += 1) {
55 a.push(v === null ? "null" : JSON.encode(v));
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()) + '"';
73 * Encodes an Object, Array or other value
74 * @param {Mixed} o The variable to encode
75 * @return {String} The JSON string
77 this.encode = function(o){
78 if(typeof o == "undefined" || o === null){
80 }else if(o instanceof Array){
81 return encodeArray(o);
82 }else if(o instanceof Date){
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"){
91 var a = ["{"], b, i, v;
93 if(!useHasOwn || o.hasOwnProperty(i)) {
104 a.push(this.encode(i), ":",
105 v === null ? "null" : this.encode(v));
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
120 this.decode = function(json){
124 return eval("(" + json + ')');
130 publish = function(symbolSet) {
131 publish.conf = { // trailing slash expected for dirs
134 templatesDir: JSDOC.opt.t + "/",
135 symbolsDir: "symbols/",
136 srcDir: "symbols/src/"
139 publish.conf.outDir = (JSDOC.opt.d.length > 0 ? JSDOC.opt.d : "/tmp/jsdoc/");
144 if (JSDOC.opt.s && defined(Link) && Link.prototype._makeSrcLink) {
145 Link.prototype._makeSrcLink = function(srcFilePath) {
146 return "<"+srcFilePath+">";
150 println(publish.conf.outDir);
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");
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");
164 //IO.mkPath((publish.conf.outDir+"symbols/src").split("/"));
166 // used to check the details of things being linked to
167 Link.symbolSet = symbolSet;
170 var classTemplate = new JSDOC.JsPlate(publish.conf.templatesDir+"class.tmpl");
171 var classesTemplate = new JSDOC.JsPlate(publish.conf.templatesDir+"allclasses.tmpl");
180 classTemplate.symbolSet = symbolSet;
183 function hasNoParent($) {return ($.memberOf == "")}
184 function isaFile($) {return ($.is("FILE"))}
185 function isaClass($) { return ($.is("CONSTRUCTOR") || $.isNamespace); }
187 var symbols = symbolSet.toArray();
189 var files = JSDOC.opt.srcFiles;
190 for (var i = 0, l = files.length; i < l; i++) {
192 var srcDir = publish.conf.outDir + "symbols/src/";
193 makeSrcFile(file, srcDir);
196 var classes = symbols.filter(isaClass).sort(makeSortby("alias"));
199 publish.classesIndex = classesTemplate.process(classes); // kept in memory
201 IO.makeDir(publish.conf.outDir+"json");
203 for (var i = 0, l = classes.length; i < l; i++) {
204 var symbol = classes[i];
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);
211 IO.saveFile(publish.conf.outDir+"json/", symbol.alias+'.json' , publish.jsonRender(symbol));
216 // regenrate the index with different relative links
218 publish.classesIndex = classesTemplate.process(classes);
221 var classesindexTemplate = new JSDOC.JsPlate(publish.conf.templatesDir+"index.tmpl");
223 catch(e) { print(e.message); quit(); }
225 var classesIndex = classesindexTemplate.process(classes);
226 IO.saveFile(publish.conf.outDir, "index"+publish.conf.ext, classesIndex);
227 classesindexTemplate = classesIndex = classes = null;
230 var fileindexTemplate = new JSDOC.JsPlate(publish.conf.templatesDir+"allfiles.tmpl");
232 catch(e) { print(e.message); quit(); }
234 var documentedFiles = symbols.filter(isaFile);
237 for (var i = 0; i < files.length; i++) {
238 allFiles.push(new JSDOC.Symbol(files[i], [], "FILE", new JSDOC.DocComment("/** */")));
241 for (var i = 0; i < documentedFiles.length; i++) {
242 var offset = files.indexOf(documentedFiles[i].alias);
243 allFiles[offset] = documentedFiles[i];
246 allFiles = allFiles.sort(makeSortby("name"));
248 var filesIndex = fileindexTemplate.process(allFiles);
249 IO.saveFile(publish.conf.outDir, "files"+publish.conf.ext, filesIndex);
250 fileindexTemplate = filesIndex = files = null;
253 publish.jsonRender = function(data)
255 // what we need to output to be usefull...
257 var cfgProperties = [];
258 if (!data.comment.getTag('singleton').length) {
259 cfgProperties = data.configToArray();
260 cfgProperties = cfgProperties.sort(makeSortby("name"));
264 //println(cfgProperties.toSource());
266 for(var i =0; i < cfgProperties.length;i++) {
267 p = cfgProperties[i];
272 memberOf : p.memberOf == data.alias ? '' : p.memberOf
277 var ownEvents = data.methods.filter( function(e){
278 return e.isEvent && !e.comment.getTag('hide').length;
279 }).sort(makeSortby("name"));
284 for(var i =0; i < ownEvents.length;i++) {
287 name : m.name.substring(1),
288 sig : makeFuncSkel(m.params),
293 //println(props.toSource());
294 // we need to output:
305 return JSON.encode(ret);
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;
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;
335 function include(path) {
336 var path = publish.conf.templatesDir+path;
337 return IO.readFile(path);
341 function makeSrcFile(path, srcDir, name) {
342 if (JSDOC.opt.s) return;
345 name = path.replace(/\.\.?[\\\/]/g, "").replace(/[\\\/]/g, "_");
346 name = name.replace(/\:/g, "_");
349 var src = {path: path, name:name, charset: IO.encoding, hilited: ""};
351 if (JSDOC.hasOwnProperty('PluginManager')) {
352 JSDOC.PluginManager.run("onPublishSrc", src);
356 IO.saveFile(srcDir, name+publish.conf.ext, src.hilited);
360 makeSignature= function(params) {
361 if (!params) return "()";
362 var signature = "(" +
365 return $.name.indexOf(".") == -1; // don't show config params in signature
369 $.defaultValue = typeof($.defaultValue) == 'undefined' ? false : $.defaultValue;
372 ($.isOptional ? "[" : "") +
373 (($.type) ? (new Link().toSymbol($.type)) + " " : "") +
374 "<B><i>" +$.name + "</i></B>" +
375 ($.defaultValue ? "=" +item.defaultValue : "") +
376 ($.isOptional ? "]" : "");
386 makeFuncSkel = function(params) {
387 if (!params) return "function ()\n{\n\n}";
388 return "function (" +
391 return $.name.indexOf(".") == -1; // don't show config params in signature
393 ).map( function($) { return $.name == 'this' ? '_self' : $.name; } ).join(", ")
399 /** Find symbol {@link ...} strings in text and turn into html links */
400 resolveLinks = function (str, from) {
401 if (typeof(str) == 'undefined') {
404 str = str.replace(/\{@link ([^} ]+) ?\}/gi,
405 function(match, symbolName) {
406 return new Link().toSymbol(symbolName);
410 str = str.replace(/\{([a-z\.\/]+)\}/gi,
411 function(match, symbolName) {
412 //println("got match " + symbolName);
413 bits = symbolName.split('/');
415 for(var i = 0; i < bits.length; i++) {
417 mret += (mret.length ? ' | ' : '') + new Link().toSymbol(bits[i]);
420 return mret; //new Link().toSymbol(symbolName);
424 // look for aaaa.\S+ ??? this might work???
426 str = str.replace(/\([a-z]+\.\S+)/gi,
427 function(match, symbolName) {
428 return new Link().toSymbol(symbolName);