166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis/** Called automatically by JsDoc Toolkit. */ 266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennisfunction publish(symbolSet) { 366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis publish.conf = { // trailing slash expected for dirs 466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis ext: ".html", 566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis outDir: JSDOC.opt.d || SYS.pwd+"../out/jsdoc/", 666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis templatesDir: JSDOC.opt.t || SYS.pwd+"../jsdoc-template/", 766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis symbolsDir: "symbols/", 866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis srcDir: "symbols/src/" 966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis }; 1066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis 1166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis // is source output is suppressed, just display the links to the source file 1266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis if (JSDOC.opt.s && defined(Link) && Link.prototype._makeSrcLink) { 1366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis Link.prototype._makeSrcLink = function(srcFilePath) { 1466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis return "<"+srcFilePath+">"; 1566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis } 1666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis } 1766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis 1866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis // create the folders and subfolders to hold the output 1966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis IO.mkPath((publish.conf.outDir+"symbols/src").split("/")); 2066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis 2166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis // used to allow Link to check the details of things being linked to 2266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis Link.symbolSet = symbolSet; 2366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis 2466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis // create the required templates 2566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis try { 2666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis var classTemplate = new JSDOC.JsPlate(publish.conf.templatesDir+"class.tmpl"); 2766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis var classesTemplate = new JSDOC.JsPlate(publish.conf.templatesDir+"allclasses.tmpl"); 2866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis } 2966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis catch(e) { 3066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis print("Couldn't create the required templates: "+e); 3166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis quit(); 3266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis } 3366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis 3466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis // some ustility filters 3566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis function hasNoParent($) {return ($.memberOf == "")} 3666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis function isaFile($) {return ($.is("FILE"))} 3766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis function isaClass($) {return ($.is("CONSTRUCTOR") || $.isNamespace)} 3866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis 3966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis // get an array version of the symbolset, useful for filtering 4066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis var symbols = symbolSet.toArray(); 4166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis 4266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis // create the hilited source code files 4366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis var files = JSDOC.opt.srcFiles; 4466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis for (var i = 0, l = files.length; i < l; i++) { 4566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis var file = files[i]; 4666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis var srcDir = publish.conf.outDir + "symbols/src/"; 4766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis makeSrcFile(file, srcDir); 4866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis } 4966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis 5066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis // get a list of all the classes in the symbolset 5166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis var classes = symbols.filter(isaClass).sort(makeSortby("alias")); 5266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis 5366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis // create a filemap in which outfiles must be to be named uniquely, ignoring case 5466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis if (JSDOC.opt.u) { 5566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis var filemapCounts = {}; 5666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis Link.filemap = {}; 5766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis for (var i = 0, l = classes.length; i < l; i++) { 5866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis var lcAlias = classes[i].alias.toLowerCase(); 5966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis 6066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis if (!filemapCounts[lcAlias]) filemapCounts[lcAlias] = 1; 6166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis else filemapCounts[lcAlias]++; 6266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis 6366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis Link.filemap[classes[i].alias] = 6466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis (filemapCounts[lcAlias] > 1)? 6566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis lcAlias+"_"+filemapCounts[lcAlias] : lcAlias; 6666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis } 6766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis } 6866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis 6966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis // create a class index, displayed in the left-hand column of every class page 7066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis Link.base = "../"; 7166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis publish.classesIndex = classesTemplate.process(classes); // kept in memory 7266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis 7366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis // create each of the class pages 7466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis for (var i = 0, l = classes.length; i < l; i++) { 7566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis var symbol = classes[i]; 7666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis 7766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis symbol.events = symbol.getEvents(); // 1 order matters 7866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis symbol.methods = symbol.getMethods(); // 2 7966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis 8066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis Link.currentSymbol= symbol; 8166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis var output = ""; 8266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis output = classTemplate.process(symbol); 8366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis 8466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis IO.saveFile(publish.conf.outDir+"symbols/", ((JSDOC.opt.u)? Link.filemap[symbol.alias] : symbol.alias) + publish.conf.ext, output); 8566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis } 8666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis 8766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis // regenerate the index with different relative links, used in the index pages 8866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis Link.base = ""; 8966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis publish.classesIndex = classesTemplate.process(classes); 9066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis 9166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis // create the class index page 9266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis try { 9366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis var classesindexTemplate = new JSDOC.JsPlate(publish.conf.templatesDir+"index.tmpl"); 9466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis } 9566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis catch(e) { print(e.message); quit(); } 9666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis 9766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis var classesIndex = classesindexTemplate.process(classes); 9866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis IO.saveFile(publish.conf.outDir, "index"+publish.conf.ext, classesIndex); 9966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis classesindexTemplate = classesIndex = classes = null; 10066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis 10166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis // create the file index page 10266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis try { 10366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis var fileindexTemplate = new JSDOC.JsPlate(publish.conf.templatesDir+"allfiles.tmpl"); 10466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis } 10566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis catch(e) { print(e.message); quit(); } 10666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis 10766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis var documentedFiles = symbols.filter(isaFile); // files that have file-level docs 10866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis var allFiles = []; // not all files have file-level docs, but we need to list every one 10966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis 11066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis for (var i = 0; i < files.length; i++) { 11166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis allFiles.push(new JSDOC.Symbol(files[i], [], "FILE", new JSDOC.DocComment("/** */"))); 11266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis } 11366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis 11466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis for (var i = 0; i < documentedFiles.length; i++) { 11566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis var offset = files.indexOf(documentedFiles[i].alias); 11666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis allFiles[offset] = documentedFiles[i]; 11766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis } 11866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis 11966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis allFiles = allFiles.sort(makeSortby("name")); 12066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis 12166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis // output the file index page 12266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis var filesIndex = fileindexTemplate.process(allFiles); 12366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis IO.saveFile(publish.conf.outDir, "files"+publish.conf.ext, filesIndex); 12466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis fileindexTemplate = filesIndex = files = null; 12566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis} 12666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis 12766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis 12866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis/** Just the first sentence (up to a full stop). Should not break on dotted variable names. */ 12966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennisfunction summarize(desc) { 13066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis if (typeof desc != "undefined") 13166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis return desc.match(/([\w\W]+?\.)[^a-z0-9_$]/i)? RegExp.$1 : desc; 13266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis} 13366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis 13466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis/** Make a symbol sorter by some attribute. */ 13566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennisfunction makeSortby(attribute) { 13666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis return function(a, b) { 13766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis if (a[attribute] != undefined && b[attribute] != undefined) { 13866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis a = a[attribute].toLowerCase(); 13966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis b = b[attribute].toLowerCase(); 14066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis if (a < b) return -1; 14166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis if (a > b) return 1; 14266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis return 0; 14366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis } 14466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis } 14566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis} 14666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis 14766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis/** Pull in the contents of an external file at the given path. */ 14866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennisfunction include(path) { 14966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis var path = publish.conf.templatesDir+path; 15066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis return IO.readFile(path); 15166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis} 15266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis 15366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis/** Turn a raw source file into a code-hilited page in the docs. */ 15466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennisfunction makeSrcFile(path, srcDir, name) { 15566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis if (JSDOC.opt.s) return; 15666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis 15766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis if (!name) { 15866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis name = path.replace(/\.\.?[\\\/]/g, "").replace(/[\\\/]/g, "_"); 15966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis name = name.replace(/\:/g, "_"); 16066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis } 16166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis 16266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis var src = {path: path, name:name, charset: IO.encoding, hilited: ""}; 16366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis 16466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis if (defined(JSDOC.PluginManager)) { 16566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis JSDOC.PluginManager.run("onPublishSrc", src); 16666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis } 16766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis 16866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis if (src.hilited) { 16966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis IO.saveFile(srcDir, name+publish.conf.ext, src.hilited); 17066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis } 17166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis} 17266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis 17366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis/** Build output for displaying function parameters. */ 17466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennisfunction makeSignature(params) { 17566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis if (!params) return "()"; 17666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis var signature = "(" 17766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis + 17866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis params.filter( 17966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis function($) { 18066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis return $.name.indexOf(".") == -1; // don't show config params in signature 18166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis } 18266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis ).map( 18366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis function($) { 18466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis return $.name; 18566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis } 18666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis ).join(", ") 18766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis + 18866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis ")"; 18966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis return signature; 19066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis} 19166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis 19266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis/** Find symbol {@link ...} strings in text and turn into html links */ 19366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennisfunction resolveLinks(str, from) { 19466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis str = str.replace(/\{@link ([^} ]+) ?\}/gi, 19566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis function(match, symbolName) { 19666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis return new Link().toSymbol(symbolName); 19766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis } 19866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis ); 19966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis 20066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis return str; 20166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis} 202