Пример #1
0
  // TODO: move the tutorial functions to templateHelper.js
  function generateTutorial(title, tutorial, filename) {
    var tutorialData = {
      title: title,
      header: tutorial.title,
      content: tutorial.parse(),
      children: tutorial.children,
      docs: null
    };

    var tutorialPath = path.join(outdir, filename),
      html = view.render('tutorial.tmpl', tutorialData);

    // yes, you can use {@link} in tutorials too!
    html = helper.resolveLinks(html); // turn {@link foo} into <a href="foodoc.html">foo</a>

    if (searchEnabled) {
      searchableDocuments[filename] = {
        "id": filename,
        "title": title,
        "body": searchData(html)
      };
    }

    fs.writeFileSync(tutorialPath, html, 'utf8');
  }
Пример #2
0
    // TODO: move the tutorial functions to templateHelper.js
    function generateTutorial(title, tutorial, fileName, originalFileName, isHtmlTutorial) {
        var tutorialData = {
            docs: null, // If there is no "docs" prop, Erros in layout.tmpl. (For left-nav member listing control)
            isTutorial: true,
            env: env,
            title: title,
            header: tutorial.title,
            children: tutorial.children,
            isHtmlTutorial: isHtmlTutorial,
            package: find({kind: 'package'})[0]
        };

        if (isHtmlTutorial) {
            _.extend(tutorialData, generateHtmlTutorialData(tutorial, fileName, originalFileName));
        } else {
            tutorialData.content = tutorial.parse();
        }

        var tutorialPath = path.join(outdir, fileName),
            html = view.render('tutorial.tmpl', tutorialData);

        // yes, you can use {@link} in tutorials too!
        html = helper.resolveLinks(html); // turn {@link foo} into <a href="foodoc.html">foo</a>

        fs.writeFileSync(tutorialPath, html, 'utf8');
    }
Пример #3
0
    function generate(title, docs, filename) {
      var data = {
        title: title,
        docs: docs
      };

      var path = outdir + '/' + filename,
        html = view.render('container.tmpl', data);

      html = helper.resolveLinks(html); // turn {@link foo} into <a href="foodoc.html">foo</a>

      fs.writeFileSync(path, html)
    }
Пример #4
0
    // TODO: move the tutorial functions to templateHelper.js
    function generateTutorial(title, tutorial, filename) {
        var tutorialData = {
            title: title,
            header: tutorial.title,
            content: tutorial.parse(),
            children: tutorial.children
        };

        var tutorialPath = path.join(outdir, filename);
        var html = view.render('tutorial.tmpl', tutorialData);

        // yes, you can use {@link} in tutorials too!
        html = helper.resolveLinks(html); // turn {@link foo} into <a href="foodoc.html">foo</a>
        fs.writeFileSync(tutorialPath, html, 'utf8');
    }
Пример #5
0
        function generateIndex(title, filename) {
            var classes = find({kind: 'class', longname: longname});

            var data = {
                title: title,
                docs: classes
            };

            var path = outdir + '/' + filename,
                html = view.render(product + '-index.tmpl', data);

            html = helper.resolveLinks(html); // turn {@link foo} into <a href="foodoc.html">foo</a>

            fs.writeFileSync(path, html)
        }
Пример #6
0
	// TODO: move the tutorial functions to templateHelper.js
	function generateTutorial(title, tutorial, filename) {
		var tutorialData = {
			title: title,
			header: tutorial.title,
			content: tutorial.parse(),
			children: tutorial.children
		};

		var tutorialPath = path.join('./', filename);
		var markdown = view.render('tutorial.tmpl', tutorialData);
		markdown = markdown.replace(/\n+/g, '\n');
		// yes, you can use {@link} in tutorials too!
		markdown = helper.resolveLinks(markdown); // turn {@link foo} into <a href="foodoc.html">foo</a>

		fs.writeFileSync(tutorialPath, markdown, 'utf8');
	}
Пример #7
0
  // TODO: move the tutorial functions to templateHelper.js
  function generateTutorial(title, tutorial, filename) {
    var tutorialData = {
      title: title,
      header: tutorial.title,
      content: tutorial.parse(),
      children: tutorial.children,
      filename: filename
    };

    var tutorialPath = path.join(outdir, filename),
      html = view.render('tutorial.tmpl', tutorialData);

    // turn {@link foo} into <a href="foodoc.html">foo</a>
    html = helper.resolveLinks(html);
    if(tutorial.demo || (tutorial.parent && tutorial.parent.demo)) {
      tutorialPath = tutorialPath.replace('tutorial-', 'demo-');
    }


    fs.writeFileSync(tutorialPath, html, 'utf8');
  }
Пример #8
0
        function generate(title, docs, filename) {
            var data = {
                title: title,
                docs: docs
            };

            var path = outdir + '/' + filename,
                html = view.render('container.tmpl', data),
                titleLower = title.toLowerCase();
            
            html = helper.resolveLinks(html); // turn {@link foo} into <a href="foodoc.html">foo</a>
            
            if (titleLower in types_json) {
                types_json[titleLower].push(filename);
            } else {
                types_json[titleLower] = [ filename ];
            }
            
            var pos = 0, pos2, member, memberLower, match = 'h4 class="name" id="', matchLen = match.length;
            while ((pos = html.indexOf(match, pos)) >= 0) {
                pos += matchLen;
                if ((pos2 = html.indexOf('"', pos)) > 0) {
                    member = html.substring(pos, pos2);
                    memberLower = member.toLowerCase();
                    if (memberLower !== titleLower) {
                        if (memberLower in types_json) {
                            // Note ".toString" and ".valueOf" used to be discarded here, before .toLowerCase() was used.
                            if (typeof types_json[memberLower].push === 'function') {
                                types_json[memberLower].push(filename + '#' + member);
                            }
                        } else {
                            types_json[memberLower] = [ filename + '#' + member ];
                        }
                    }
                }
            }
            
            fs.writeFileSync(path, html);
        }
exports.publish = function(taffyData, opts, tutorials) {
    data = taffyData;

    var conf = env.conf.templates || {};
    conf['default'] = conf['default'] || {};
    conf['weswit'] = conf['weswit'] || {};

    var templatePath = opts.template;
    view = new template.Template(templatePath + '/tmpl');
    
    // claim some special filenames in advance, so the All-Powerful Overseer of Filename Uniqueness
    // doesn't try to hand them out later
    var indexUrl = helper.getUniqueFilename('index');
    var indexAllUrl = helper.getUniqueFilename('index-all');
    
    // don't call registerLink() on this one! 'index' is also a valid longname

    var globalUrl = helper.getUniqueFilename('global');
    helper.registerLink('global', globalUrl);

    // set up templating
    view.layout = 'layout.tmpl';

    // set up tutorials for helper
    helper.setTutorials(tutorials);
    
    var externs = {};


         function searchDescription(className,methodName) {

            var _class = find({longname:className});
            for (var c=0; c<_class.length; c++) {
                if (_class[c].augments) {
                    for (var a = 0; a < _class[c].augments.length; a++) {

                        var _superMethod = find({longname: _class[c].augments[a] + "#" + methodName});
                        for (var s = 0; s < _superMethod.length; s++) {
                            if (_superMethod[s].inherits) {
                                return _superMethod[s].inherits;
                            } else if (_superMethod[s].description) {
                                return _superMethod[s].longname;
                            }
                        }


                        var inherits = searchDescription(_class[c].augments[a], methodName);
                        if (inherits) {
                            return inherits;
                        }

                    }
                }
            }

            return null;
        }



    //create summary if missing
    var methods = find({kind: 'function'});
    
    methods.forEach(function(m) {
      if (!m.summary && m.description) {
        var d = m.description;
        m.summary = d.indexOf(".") > -1 ? d.substring(0,d.indexOf(".")+1) : d;
      }
      
      if (!m.inherited) {
        m.inherited = false;
      }
      
      if (m.reimplemented !== true && m.reimplemented !== false) {
        var others = find({kind: 'function', longname: m.longname, inherited: true, memberof: m.memberof});
        var f = 0;
        others.forEach(function(o) {
          f++;
          if (!m.inherited) {
            m.inherits = o.inherits;
            o.reimplemented = true;
          } else if (f>1) {
            o.reimplemented = true;
          } else {
            o.reimplemented = false;
          }
        });

        if (!m.description && !m.inherits) {
            m.inherits = searchDescription(m.memberof, m.name);
            if (m.inherits) {
                m.inherited = true;
            }
        }
      }
      
    });
    
    var stuffWithSource = find({kind:  ['class', 'module', 'global']});
    stuffWithSource.forEach(function(m) {
      m.printSourceLink = conf['default'] && conf['default'].outputSourceFiles === true;
    });
    

    data = helper.prune(data);
    data.sort('longname, version, since');
    helper.addEventListeners(data);

    var sourceFiles = {};
    var sourceFilePaths = [];
    data().each(function(doclet) {
         doclet.attribs = '';
        
        if (doclet.examples) {
            doclet.examples = doclet.examples.map(function(example) {
                var caption, code;
                
                if (example.match(/^\s*<caption>([\s\S]+?)<\/caption>(\s*[\n\r])([\s\S]+)$/i)) {
                    caption = RegExp.$1;
                    code    = RegExp.$3;
                }
                
                return {
                    caption: caption || '',
                    code: code || example
                };
            });
        }
        if (doclet.see) {
            doclet.see.forEach(function(seeItem, i) {
                doclet.see[i] = hashToLink(doclet, seeItem);
            });
        }

        // build a list of source files
        var sourcePath;
        var resolvedSourcePath;
        if (doclet.meta) {
            sourcePath = getPathFromDoclet(doclet);
            resolvedSourcePath = resolveSourcePath(sourcePath);
            sourceFiles[sourcePath] = {
                resolved: resolvedSourcePath,
                shortened: null
            };
            sourceFilePaths.push(resolvedSourcePath);
        }
    });
    
    // update outdir if necessary, then create outdir
    var packageInfo = ( find({kind: 'package'}) || [] ) [0];
    if (packageInfo && packageInfo.name) {
        outdir = path.join(outdir, packageInfo.name, packageInfo.version);
    }
    fs.mkPath(outdir);

    // copy the template's static files to outdir
    var fromDir = path.join(templatePath, 'static');
    var staticFiles = fs.ls(fromDir, 3);

    staticFiles.forEach(function(fileName) {
        var toDir = fs.toDir( fileName.replace(fromDir, outdir) );
        fs.mkPath(toDir);
        fs.copyFileSync(fileName, toDir);
    });

    // copy user-specified static files to outdir
    var staticFilePaths;
    var staticFileFilter;
    var staticFileScanner;
    if (conf['default'].staticFiles) {
        staticFilePaths = conf['default'].staticFiles.paths || [];
        staticFileFilter = new (require('jsdoc/src/filter')).Filter(conf['default'].staticFiles);
        staticFileScanner = new (require('jsdoc/src/scanner')).Scanner();

        staticFilePaths.forEach(function(filePath) {
            var extraStaticFiles = staticFileScanner.scan([filePath], 10, staticFileFilter);

            extraStaticFiles.forEach(function(fileName) {
                var sourcePath = fs.statSync(filePath).isDirectory() ? filePath :
                    path.dirname(filePath);
                var toDir = fs.toDir( fileName.replace(sourcePath, outdir) );
                fs.mkPath(toDir);
                fs.copyFileSync(fileName, toDir);
            });
        });
    }
    
    if (sourceFilePaths.length) {
        sourceFiles = shortenPaths( sourceFiles, path.commonPrefix(sourceFilePaths) );
    }
    data().each(function(doclet) {
        var url = helper.createLink(doclet);
        helper.registerLink(doclet.longname, url);

        // replace the filename with a shortened version of the full path
        var docletPath;
        if (doclet.meta) {
            docletPath = getPathFromDoclet(doclet);
            docletPath = sourceFiles[docletPath].shortened;
            if (docletPath) {
                doclet.meta.filename = docletPath;
            }
        }
    });
    
    var namesForIndex = [];
    
    data().each(function(doclet) {
        
        //prepare alphabetic index (currently handles methods classes and modules TODO complete)
        //TODO might we use doclet.kind?
        var longname = doclet.longname
        if (longname.indexOf("~") > -1) { 
          //hide private stuff
        } else if (longname.indexOf("#") > -1) {
          //instance methods
          var shortName = longname.substring(longname.indexOf("#")+1);
          shortName = shortName.replace('"','',"g");
          
          var cName = longname.substring(0,longname.indexOf("#"));
          cName = cName.substring(cName.indexOf(":")+1);
          if (cName == "undefined") {
            cName = "Globals";
          }
          
          namesForIndex.push({name: shortName, 
            definition: "Instance method in " + cName, 
            extern: cName+".prototype."+shortName+" = function() {};",
            longname: longname, 
            memberof: cName}); 
             
        } else if (longname.indexOf(".") > -1) {     
          //static methods
          var shortName = longname.substring(longname.indexOf(".")+1);
          shortName = shortName.replace('"','',"g");
          
          var cName = longname.substring(0,longname.indexOf("."));
          cName = cName.substring(cName.indexOf(":")+1);
          if (cName == "undefined") {
            cName = "Globals";
          }
          
          namesForIndex.push({name: shortName, 
            definition: "Static method in " + cName, 
            extern: cName+"."+shortName+" = function() {};",
            longname: longname, 
            memberof: cName}); 
        
        } else if (longname.indexOf(":") > -1) {     
        
          //name undefined means globals
        
          //modules
          var shortName = longname.substring(longname.indexOf(":")+1);
          shortName = shortName.replace('"','',"g");
          if (shortName == "undefined") {
            shortName="Globals";
          }
          
          namesForIndex.push({name: shortName, 
            definition: "Module " + shortName, 
            extern: shortName+" = {};",
            longname: longname});
        } else {
          //classes
          var shortName = longname.replace('"','',"g");
          namesForIndex.push({name: shortName, 
            extern: shortName+" = function() {};",
            definition: "Class " + longname, 
            longname: longname});
        }
    
        var url = helper.longnameToUrl[doclet.longname];

        if (url.indexOf('#') > -1) {
            doclet.id = helper.longnameToUrl[doclet.longname].split(/#/).pop();
        }
        else {
            doclet.id = doclet.name;
        }
        
        if ( needsSignature(doclet) ) {
            addSignatureParams(doclet);
            addSignatureReturns(doclet);
            addAttribs(doclet);
        }
    });
    
    namesForIndex = namesForIndex.sort(function(a,b) {
      var al = a.name.toLowerCase();
      var bl = b.name.toLowerCase();
      if (al == bl) {
        return 0;
      }
      return al < bl ? -1 : 1;
    });
    var byLetterIndex = [];//would be easier with a {}
    
    var curr = null;
    namesForIndex.forEach(function(el) {
      var l = el.name[0].toUpperCase();
      if (l != curr) {
        byLetterIndex.push([]);
        curr = l;
      }
      byLetterIndex[byLetterIndex.length-1].push(el);
    });
    
    
    
    namesForIndex = namesForIndex.sort(function(a,b) {
      if (a.memberof == b.memberof) {
        return 0;
      } else if (!a.memberof) {
        if (!b.memberof) {
          return 0;
        }
        return -1;
      } else if (!b.memberof) {
        return 1;
      }
      return a.memberof < b.memberof ? -1 : 1;
    });
    
    var externsIndex = [];
    externsIndex.push([]);
    curr = null;
    namesForIndex.forEach(function(el) {
      var l = el.memberof;
      if (l != curr) {
        externsIndex.push([]);
        curr = l;
      }
      externsIndex[externsIndex.length-1].push(el);
    });
    
    
    // do this after the urls have all been generated
    data().each(function(doclet) {
        doclet.ancestors = getAncestorLinks(doclet);

        if (doclet.kind === 'member') {
            addSignatureTypes(doclet);
            addAttribs(doclet);
        }
        
        if (doclet.kind === 'constant') {
            addSignatureTypes(doclet);
            addAttribs(doclet);
            doclet.kind = 'member';
        }
    });
    
    var members = helper.getMembers(data);
    members.tutorials = tutorials.children;

    // add template helpers
    view.find = find;
    view.linkto = linkto;
    view.resolveAuthorLinks = resolveAuthorLinks;
    view.tutoriallink = tutoriallink;
    view.htmlsafe = htmlsafe;

    // once for all
    view.nav = buildNav(members,conf["weswit"].logo);
    attachModuleSymbols( find({ kind: ['class', 'function'], longname: {left: 'module:'} }),
        members.modules );

    // do not output pretty-printed source files by default; do this before generating any other pages, so
    // that the other pages can link to the source files
    if (!conf['default'] || conf['default'].outputSourceFiles === true) {
        generateSourceFiles(sourceFiles, opts.encoding, conf["weswit"]);
    }
    
    

    if (members.globals.length) { generate('Global', [{kind: 'globalobj'}], globalUrl, conf["weswit"]); }
    
    // index page displays information from package.json and lists files
    var files = find({kind: 'file'}),
        packages = find({kind: 'package'});
        
     
    var libName = conf["weswit"] && conf["weswit"].extendedLibraryName ? conf["weswit"].extendedLibraryName : "Index";
    var summaryText = conf["weswit"].summaryFile ? fs.readFileSync( conf["weswit"].summaryFile, 'utf8' ) : (!opts.readme ? "Javascript Documentation" : null);
        
    generate(libName,
        packages.concat(
            [{
              kind: 'mainpage', 
              readme: opts.readme, 
              longname: (opts.mainpagetitle) ? opts.mainpagetitle : 'Main Page',
              summary:summaryText
            }]
        ).concat(files),
    indexUrl, conf["weswit"]);
    
    generateIndex("Index",
      packages.concat(
        [{
          kind: 'index', 
          longname: 'Index Page', 
        }]).concat(files),
    indexAllUrl, conf["weswit"],  byLetterIndex);
    
    generateExterns(externsIndex);

    // set up the lists that we'll use to generate pages
    var classes = taffy(members.classes);
    var modules = taffy(members.modules);
    var namespaces = taffy(members.namespaces);
    var mixins = taffy(members.mixins);
    var externals = taffy(members.externals);
    
    Object.keys(helper.longnameToUrl).forEach(function(longname) {
        var myClasses = helper.find(classes, {longname: longname});
        if (myClasses.length) {
            generate('Class: ' + myClasses[0].name, myClasses, helper.longnameToUrl[longname], conf["weswit"]);
        }
        
        var myModules = helper.find(modules, {longname: longname});
        if (myModules.length) {
            generate('Module: ' + myModules[0].name, myModules, helper.longnameToUrl[longname], conf["weswit"]);
        }

        var myNamespaces = helper.find(namespaces, {longname: longname});
        if (myNamespaces.length) {
            generate('Namespace: ' + myNamespaces[0].name, myNamespaces, helper.longnameToUrl[longname], conf["weswit"]);
        }
        
        var myMixins = helper.find(mixins, {longname: longname});
        if (myMixins.length) {
            generate('Mixin: ' + myMixins[0].name, myMixins, helper.longnameToUrl[longname], conf["weswit"]);
        }

        var myExternals = helper.find(externals, {longname: longname});
        if (myExternals.length) {
            generate('External: ' + myExternals[0].name, myExternals, helper.longnameToUrl[longname], conf["weswit"]);
        }
    });

    // TODO: move the tutorial functions to templateHelper.js
    function generateTutorial(title, tutorial, filename) {
        var tutorialData = {
            title: title,
            header: tutorial.title,
            content: tutorial.parse(),
            children: tutorial.children
        };
        
        var tutorialPath = path.join(outdir, filename),
            html = view.render('tutorial.tmpl', tutorialData);
        
        // yes, you can use {@link} in tutorials too!
        html = helper.resolveLinks(html); // turn {@link foo} into <a href="foodoc.html">foo</a>
        
        fs.writeFileSync(tutorialPath, html, 'utf8');
    }
    
    // tutorials can have only one parent so there is no risk for loops
    function saveChildren(node) {
        node.children.forEach(function(child) {
            generateTutorial('Tutorial: ' + child.title, child, helper.tutorialToUrl(child.name));
            saveChildren(child);
        });
    }
    saveChildren(tutorials);
};
Пример #10
0
exports.publish = function(taffyData, opts, tutorials) {
  data = taffyData;

  var conf = env.conf.templates || {};
  conf['default'] = conf['default'] || {};

  var templatePath = opts.template;
  view = new template.Template(templatePath + '/tmpl');

  // claim some special filenames in advance, so the All-Powerful Overseer of Filename Uniqueness
  // doesn't try to hand them out later
  var indexUrl = helper.getUniqueFilename('index');
  // don't call registerLink() on this one! 'index' is also a valid longname

  var globalUrl = helper.getUniqueFilename('global');
  helper.registerLink('global', globalUrl);

  // set up templating
  view.layout = 'layout.tmpl';


  
  extendTutorialsObj(tutorials, "external");
  extendTutorialsObj(tutorials, "demo");

  console.log(tutorials.children[0]);
  
  // set up tutorials for helper
  helper.setTutorials(tutorials);

  data = helper.prune(data);
  data.sort('longname, version, since');
  helper.addEventListeners(data);

  var sourceFiles = {};
  var sourceFilePaths = [];
  data().each(function(doclet) {
    doclet.attribs = '';

    if (doclet.examples) {
      doclet.examples = doclet.examples.map(function(example) {
        var caption, code;

        if (example.match(/^\s*(?:<p>)?\s*<caption>([\s\S]+?)<\/caption>\s*(?:<\/p>)?[\s\r\n]*([\s\S]+)$/i)) {
          caption = RegExp.$1;
          code    = RegExp.$2;
        }

        return {
          caption: caption || '',
          code: code || example
        };
      });
    }
    if (doclet.see) {
      doclet.see.forEach(function(seeItem, i) {
        doclet.see[i] = hashToLink(doclet, seeItem);
      });
    }

    // build a list of source files
    var sourcePath;
    var resolvedSourcePath;
    if (doclet.meta) {
      sourcePath = getPathFromDoclet(doclet);
      resolvedSourcePath = resolveSourcePath(sourcePath);
      sourceFiles[sourcePath] = {
        resolved: resolvedSourcePath,
        shortened: null
      };
      sourceFilePaths.push(resolvedSourcePath);
    }
  });

  // update outdir if necessary, then create outdir
  var packageInfo = ( find({kind: 'package'}) || [] ) [0];
  if (packageInfo && packageInfo.name) {
    outdir = path.join(outdir, packageInfo.name, packageInfo.version);
  }
  fs.mkPath(outdir);

  // copy the template's static files to outdir
  var fromDir = path.join(templatePath, 'static');
  var staticFiles = fs.ls(fromDir, 3);

  staticFiles.forEach(function(fileName) {
    var toDir = fs.toDir( fileName.replace(fromDir, outdir) );
    fs.mkPath(toDir);
    fs.copyFileSync(fileName, toDir);
  });

  // copy user-specified static files to outdir
  var staticFilePaths;
  var staticFileFilter;
  var staticFileScanner;
  if (conf['default'].staticFiles) {
    staticFilePaths = conf['default'].staticFiles.paths || [];
    staticFileFilter = new (require('jsdoc/src/filter')).Filter(conf['default'].staticFiles);
    staticFileScanner = new (require('jsdoc/src/scanner')).Scanner();

    staticFilePaths.forEach(function(filePath) {
      var extraStaticFiles = staticFileScanner.scan([filePath], 10, staticFileFilter);

      extraStaticFiles.forEach(function(fileName) {
        var sourcePath = fs.statSync(filePath).isDirectory() ? filePath :
          path.dirname(filePath);
        var toDir = fs.toDir( fileName.replace(sourcePath, outdir) );
        fs.mkPath(toDir);
        fs.copyFileSync(fileName, toDir);
      });
    });
  }

  if (sourceFilePaths.length) {
    sourceFiles = shortenPaths( sourceFiles, path.commonPrefix(sourceFilePaths) );
  }
  data().each(function(doclet) {
    var url = helper.createLink(doclet);
    helper.registerLink(doclet.longname, url);

    // replace the filename with a shortened version of the full path
    var docletPath;
    if (doclet.meta) {
      docletPath = getPathFromDoclet(doclet);
      docletPath = sourceFiles[docletPath].shortened;
      if (docletPath) {
        doclet.meta.filename = docletPath;
      }
    }
  });

  data().each(function(doclet) {
    var url = helper.longnameToUrl[doclet.longname];

    if (url.indexOf('#') > -1) {
      doclet.id = helper.longnameToUrl[doclet.longname].split(/#/).pop();
    }
    else {
      doclet.id = doclet.name;
    }

    if ( needsSignature(doclet) ) {
      addSignatureParams(doclet);
      addSignatureReturns(doclet);
      addAttribs(doclet);
    }
  });

  // do this after the urls have all been generated
  data().each(function(doclet) {
    doclet.ancestors = getAncestorLinks(doclet);

    if (doclet.kind === 'member') {
      addSignatureTypes(doclet);
      addAttribs(doclet);
    }

    if (doclet.kind === 'constant') {
      addSignatureTypes(doclet);
      addAttribs(doclet);
      doclet.kind = 'member';
    }
  });

  var members = helper.getMembers(data);
  members.tutorials = tutorials.children;


  // add template helpers
  view.find = find;
  view.linkto = linkto;
  view.resolveAuthorLinks = resolveAuthorLinks;
  view.tutoriallink = tutoriallink;

  view.htmlsafe = htmlsafe;
  view.members = members; //@davidshimjs: To make navigation for customizing

  // once for all
  view.nav = buildNav(members);
  attachModuleSymbols(find({ kind: ['class', 'function'], longname: {left: 'module:'} }), members.modules);

  // only output pretty-printed source files if requested; do this before generating any other
  // pages, so the other pages can link to the source files
  if (conf['default'].outputSourceFiles) {
    generateSourceFiles(sourceFiles);
  }

  if (members.globals.length) {
    generate('Global', [{kind: 'globalobj'}], globalUrl);
  }

  // index page displays information from package.json and lists files
  var files = find({kind: 'file'}),
    packages = find({kind: 'package'});

  generate('Index',
    packages.concat(
      [{kind: 'mainpage', readme: opts.readme, longname: (opts.mainpagetitle) ? opts.mainpagetitle : 'Main Page'}]
    ).concat(files),
    indexUrl);

  // set up the lists that we'll use to generate pages
  var classes = taffy(members.classes);
  var modules = taffy(members.modules);
  var namespaces = taffy(members.namespaces);
  var mixins = taffy(members.mixins);
  var externals = taffy(members.externals);

  for (var longname in helper.longnameToUrl) {
    if ( hasOwnProp.call(helper.longnameToUrl, longname) ) {
      var myClasses = helper.find(classes, {longname: longname});
      if (myClasses.length) {
        generate('Class: ' + myClasses[0].name, myClasses, helper.longnameToUrl[longname]);
      }

      var myModules = helper.find(modules, {longname: longname});
      if (myModules.length) {
        generate('Module: ' + myModules[0].name, myModules, helper.longnameToUrl[longname]);
      }

      var myNamespaces = helper.find(namespaces, {longname: longname});
      if (myNamespaces.length) {
        generate('Namespace: ' + myNamespaces[0].name, myNamespaces, helper.longnameToUrl[longname]);
      }

      var myMixins = helper.find(mixins, {longname: longname});
      if (myMixins.length) {
        generate('Mixin: ' + myMixins[0].name, myMixins, helper.longnameToUrl[longname]);
      }

      var myExternals = helper.find(externals, {longname: longname});
      if (myExternals.length) {
        generate('External: ' + myExternals[0].name, myExternals, helper.longnameToUrl[longname]);
      }
    }
  }

  // TODO: move the tutorial functions to templateHelper.js
  function generateTutorial(title, tutorial, filename) {
    var tutorialData = {
      title: title,
      header: tutorial.title,
      content: tutorial.parse(),
      children: tutorial.children,
      filename: filename
    };

    var tutorialPath = path.join(outdir, filename),
      html = view.render('tutorial.tmpl', tutorialData);

    // turn {@link foo} into <a href="foodoc.html">foo</a>
    html = helper.resolveLinks(html);
    if(tutorial.demo || (tutorial.parent && tutorial.parent.demo)) {
      tutorialPath = tutorialPath.replace('tutorial-', 'demo-');
    }


    fs.writeFileSync(tutorialPath, html, 'utf8');
  }

  // tutorials can have only one parent so there is no risk for loops
  function saveChildren(node) {
    node.children.forEach(function(child) {
      
      // Do not generate static pages for the main 'headers'
      if(child.parent.name !== 'index' && !child.external) {
          generateTutorial('Tutorial: ' + child.title, child, helper.tutorialToUrl(child.name));

      }
      saveChildren(child);

    });
  }

  function getExtendedTutorialProperties (parsedJSON, extension, list, name) {
    var init,
      children;

    if(!list) {
      var list = [];

      init = true;
      parsedJSON = parsedJSON.index;
    } else {
      init = false;
    }
    
    if(parsedJSON.hasOwnProperty(extension)) {
      list.push({
        'name': name || 'index',
        'extensionValue': parsedJSON[extension]
      });
    }

    if(parsedJSON.hasOwnProperty('children')) {
      children = Object.keys(parsedJSON.children);
      for(var i = 0; i < children.length; i++) {
        getExtendedTutorialProperties(parsedJSON.children[children[i]], extension, list, children[i]);
      }
    }

    if(init) {
      return list;
    }
  }

  function setExtendedTutorialProperties (tutorials, extension, extended) {
    for(var i = 0; i < extended.length; i++) {
      tutorials.getByName(extended[i].name)[extension] = extended[i].extensionValue;
    }
  }

  function extendTutorialsObj (tutorials, extensions) {
    var extensionsArray = [],
      extended,
      json,
      parsed;

    if(typeof extensions === 'string') {
      extensionsArray.push(extensions);
    }

    json = fs.readFileSync(env.opts.template + '/' + env.opts.tutorials + '/' + env.opts.tutorials + '.json' , env.opts.encoding);
    parsed = JSON.parse(json);

    for(var i = 0; i < extensionsArray.length; i++) {
      extended = getExtendedTutorialProperties (parsed, extensionsArray[i]);
      setExtendedTutorialProperties(tutorials, extensionsArray[i], extended);
    }

    return tutorials;
  }

  saveChildren(tutorials);
};
Пример #11
0
exports.publish = function ( taffyData, opts, tutorials ) {
	data = taffyData;

	conf['default'] = conf['default'] || {};

	var templatePath = opts.template;
	view = new template.Template( templatePath + '/tmpl' );

	// claim some special filenames in advance, so the All-Powerful Overseer of Filename Uniqueness
	// doesn't try to hand them out later
//	var indexUrl = helper.getUniqueFilename( 'index' );
	// don't call registerLink() on this one! 'index' is also a valid longname

//	var globalUrl = helper.getUniqueFilename( 'global' );
	helper.registerLink( 'global', globalUrl );

	// set up templating
	view.layout = 'layout.tmpl';

	// set up tutorials for helper
	helper.setTutorials( tutorials );

	data = helper.prune( data );
	data.sort( 'longname, version, since' );
	helper.addEventListeners( data );

	var sourceFiles = {};
	var sourceFilePaths = [];
	data().each( function ( doclet ) {
		doclet.attribs = '';

		if ( doclet.examples ) {
			doclet.examples = doclet.examples.map( function ( example ) {
				var caption, code, lang;

				if ( example.match( /^\s*<caption>([\s\S]+?)<\/caption>(\s*[\n\r])([\s\S]+)$/i ) ) {
					caption = RegExp.$1;
					code = RegExp.$3;
				}

				var lang = /{@lang (.*?)}/.exec( example );

				if ( lang && lang[1] ) {
					example = example.replace( lang[0], "" );
					lang = lang[1];

				} else {
					lang = null;
				}

				return {
					caption : caption || '',
					code    : code || example,
					lang    : (lang && navOptions.highlightTutorialCode) ? lang : "javascript"
				};
			} );
		}
		if ( doclet.see ) {
			doclet.see.forEach( function ( seeItem, i ) {
				doclet.see[i] = hashToLink( doclet, seeItem );
			} );
		}

		// build a list of source files
		var sourcePath;
		if ( doclet.meta ) {
			sourcePath = getPathFromDoclet( doclet );
			sourceFiles[sourcePath] = {
				resolved  : sourcePath,
				shortened : null
			};

			sourceFilePaths.push( sourcePath );

		}
	} );

	// update outdir if necessary, then create outdir
	var packageInfo = ( find( {kind : 'package'} ) || [] ) [0];
	if ( packageInfo && packageInfo.name ) {
		outdir = path.join( outdir, packageInfo.name, packageInfo.version );
	}
	fs.mkPath( outdir );

	// copy static files to outdir
	var fromDir = path.join( templatePath, 'static' ),
		staticFiles = fs.ls( fromDir, 3 );

	staticFiles.forEach( function ( fileName ) {
		var toDir = fs.toDir( fileName.replace( fromDir, outdir ) );
		fs.mkPath( toDir );
		fs.copyFileSync( fileName, toDir );
	} );

	if ( sourceFilePaths.length ) {
		var payload = navOptions.sourceRootPath;
		if ( !payload ) {
			payload = path.commonPrefix( sourceFilePaths );
		}
		sourceFiles = shortenPaths( sourceFiles, payload );
	}
	data().each( function ( doclet ) {
		var url = helper.createLink( doclet );
		helper.registerLink( doclet.longname, url );

		// add a shortened version of the full path
		var docletPath;
		if ( doclet.meta ) {
			docletPath = getPathFromDoclet( doclet );
			if ( !_.isEmpty( sourceFiles[docletPath] ) ) {
				docletPath = sourceFiles[docletPath].shortened;
				if ( docletPath ) {
					doclet.meta.shortpath = docletPath;
				}
			}
		}
	} );

	data().each( function ( doclet ) {
		var url = helper.longnameToUrl[doclet.longname];

		if ( url.indexOf( '#' ) > -1 ) {
			doclet.id = helper.longnameToUrl[doclet.longname].split( /#/ ).pop();
		}
		else {
			doclet.id = doclet.name;
		}

		if ( needsSignature( doclet ) ) {
			addSignatureParams( doclet );
			addSignatureReturns( doclet );
			addAttribs( doclet );
		}
	} );

	// do this after the urls have all been generated
	data().each( function ( doclet ) {
		doclet.ancestors = getAncestorLinks( doclet );

		if ( doclet.kind === 'member' ) {
			addSignatureTypes( doclet );
			addAttribs( doclet );
		}

		if ( doclet.kind === 'constant' ) {
			addSignatureTypes( doclet );
			addAttribs( doclet );
			doclet.kind = 'member';
		}
	} );

	var members = helper.getMembers( data );
	members.tutorials = tutorials.children;

	// add template helpers
	view.find = find;
	view.linkto = linkto;
	view.resolveAuthorLinks = resolveAuthorLinks;
	view.tutoriallink = tutoriallink;
	view.htmlsafe = htmlsafe;
	view.moment = moment;

	// once for all
	buildNav( members );
	view.nav = navigationMaster;
	view.navOptions = navOptions;
	attachModuleSymbols( find( { kind : ['class', 'function'], longname : {left : 'module:'} } ),
		members.modules );

	// only output pretty-printed source files if requested; do this before generating any other
	// pages, so the other pages can link to the source files
	if ( navOptions.outputSourceFiles ) {
		generateSourceFiles( sourceFiles );
	}

	if ( members.globals.length ) {
		generate( 'global', 'Global', [
			{kind : 'globalobj'}
		], globalUrl );
	}

	// some browsers can't make the dropdown work
	if ( view.nav.module && view.nav.module.members.length ) {
		generate( 'module', view.nav.module.title, [
			{kind : 'sectionIndex', contents : view.nav.module}
		], navigationMaster.module.link );
	}

	if ( view.nav.class && view.nav.class.members.length ) {
		generate( 'class', view.nav.class.title, [
			{kind : 'sectionIndex', contents : view.nav.class}
		], navigationMaster.class.link );
	}

	if ( view.nav.namespace && view.nav.namespace.members.length ) {
		generate( 'namespace', view.nav.namespace.title, [
			{kind : 'sectionIndex', contents : view.nav.namespace}
		], navigationMaster.namespace.link );
	}

	if ( view.nav.mixin && view.nav.mixin.members.length ) {
		generate( 'mixin', view.nav.mixin.title, [
			{kind : 'sectionIndex', contents : view.nav.mixin}
		], navigationMaster.mixin.link );
	}

	if ( view.nav.external && view.nav.external.members.length ) {
		generate( 'external', view.nav.external.title, [
			{kind : 'sectionIndex', contents : view.nav.external}
		], navigationMaster.external.link );
	}

	if ( view.nav.tutorial && view.nav.tutorial.members.length ) {
		generate( 'tutorial', view.nav.tutorial.title, [
			{kind : 'sectionIndex', contents : view.nav.tutorial}
		], navigationMaster.tutorial.link );
	}

	// index page displays information from package.json and lists files
	var files = find( {kind : 'file'} ),
		packages = find( {kind : 'package'} );

	generate( 'index', 'Index',
		packages.concat(
			[
				{kind : 'mainpage', readme : opts.readme, longname : (opts.mainpagetitle) ? opts.mainpagetitle : 'Main Page'}
			]
		).concat( files ),
		indexUrl );

	// set up the lists that we'll use to generate pages
	var classes = taffy( members.classes );
	var modules = taffy( members.modules );
	var namespaces = taffy( members.namespaces );
	var mixins = taffy( members.mixins );
	var externals = taffy( members.externals );

	for ( var longname in helper.longnameToUrl ) {
		if ( hasOwnProp.call( helper.longnameToUrl, longname ) ) {
			var myClasses = helper.find( classes, {longname : longname} );
			if ( myClasses.length ) {
				generate( 'class', 'Class: ' + myClasses[0].name, myClasses, helper.longnameToUrl[longname] );
			}

			var myModules = helper.find( modules, {longname : longname} );
			if ( myModules.length ) {
				generate( 'module', 'Module: ' + myModules[0].name, myModules, helper.longnameToUrl[longname] );
			}

			var myNamespaces = helper.find( namespaces, {longname : longname} );
			if ( myNamespaces.length ) {
				generate( 'namespace', 'Namespace: ' + myNamespaces[0].name, myNamespaces, helper.longnameToUrl[longname] );
			}

			var myMixins = helper.find( mixins, {longname : longname} );
			if ( myMixins.length ) {
				generate( 'mixin', 'Mixin: ' + myMixins[0].name, myMixins, helper.longnameToUrl[longname] );
			}

			var myExternals = helper.find( externals, {longname : longname} );
			if ( myExternals.length ) {
				generate( 'external', 'External: ' + myExternals[0].name, myExternals, helper.longnameToUrl[longname] );
			}
		}
	}

	// TODO: move the tutorial functions to templateHelper.js
	function generateTutorial( title, tutorial, filename ) {
		var tutorialData = {
			title    : title,
			header   : tutorial.title,
			content  : tutorial.parse(),
			children : tutorial.children,
			docs     : null
		};

		var tutorialPath = path.join( outdir, filename ),
			html = view.render( 'tutorial.tmpl', tutorialData );

		// yes, you can use {@link} in tutorials too!
		html = helper.resolveLinks( html ); // turn {@link foo} into <a href="foodoc.html">foo</a>

		fs.writeFileSync( tutorialPath, html, 'utf8' );
	}

	// tutorials can have only one parent so there is no risk for loops
	function saveChildren( node ) {
		node.children.forEach( function ( child ) {
			generateTutorial( 'tutorial' + child.title, child, helper.tutorialToUrl( child.name ) );
			saveChildren( child );
		} );
	}

	saveChildren( tutorials );
};
Пример #12
0
exports.publish = function (taffyData, opts, tutorials) {
  data = taffyData;

  var conf = env.conf.templates || {};
  conf['default'] = conf['default'] || {};

  var templatePath = opts.template;
  view = new template.Template(templatePath + '/tmpl');

  // claim some special filenames in advance, so the All-Powerful Overseer of Filename Uniqueness
  // doesn't try to hand them out later
  var indexUrl = helper.getUniqueFilename('index');
  // don't call registerLink() on this one! 'index' is also a valid longname

  var globalUrl = helper.getUniqueFilename('global');
  helper.registerLink('global', globalUrl);

  // set up templating
  view.layout = 'layout.tmpl';

  // set up tutorials for helper
  helper.setTutorials(tutorials);

  data = helper.prune(data);
  data.sort('longname, version, since');

  var sourceFiles = {};
  var sourceFilePaths = [];

  processInheritance();

  data().each(function (doclet) {
    if (doclet.name) doclet.name = doclet.name.replace(/']/g, '').replace(/\['/g, '');
    if (doclet.longname) doclet.longname = doclet.longname.replace(/']/g, '').replace(/\['/g, '');

    doclet.attribs = '';

    if (doclet.examples) {
      doclet.examples = doclet.examples.map(function (example) {
        var caption, code;

        if (example.match(/^\s*<caption>([\s\S]+?)<\/caption>(\s*[\n\r])([\s\S]+)$/i)) {
          caption = RegExp.$1;
          code = RegExp.$3;
        }

        return {
          caption: caption || '',
          code: code || example
        };
      });
    }
    if (doclet.see) {
      doclet.see.forEach(function (seeItem, i) {
        doclet.see[i] = hashToLink(doclet, seeItem);
      });
    }

    // build a list of source files
    var sourcePath;
    var resolvedSourcePath;
    if (doclet.meta) {
      sourcePath = getPathFromDoclet(doclet);
      resolvedSourcePath = resolveSourcePath(sourcePath);
      sourceFiles[sourcePath] = {
        resolved: resolvedSourcePath,
        shortened: null
      };
      sourceFilePaths.push(resolvedSourcePath);
    }
  });

  // update outdir if necessary, then create outdir
  var packageInfo = ( find({kind: 'package'}) || [] ) [0];
  if (packageInfo && packageInfo.name) {
    outdir = path.join(outdir, packageInfo.name, packageInfo.version);
  }
  fs.mkPath(outdir);

  // copy static files to outdir
  var fromDir = path.join(templatePath, 'static'),
      staticFiles = fs.ls(fromDir, 3);

  staticFiles.forEach(function (fileName) {
    var toDir = fs.toDir(fileName.replace(fromDir, outdir));
    fs.mkPath(toDir);
    fs.copyFileSync(fileName, toDir);
  });

  if (sourceFilePaths.length) {
    sourceFiles = shortenPaths(sourceFiles, path.commonPrefix(sourceFilePaths));
  }
  data().each(function (doclet) {
    var url = helper.createLink(doclet);
    helper.registerLink(doclet.longname, url);

    // replace the filename with a shortened version of the full path
    var docletPath;
    if (doclet.meta) {
      docletPath = getPathFromDoclet(doclet);
      docletPath = sourceFiles[docletPath].shortened;
      if (docletPath) {
        doclet.meta.filename = docletPath;
      }
    }
  });

  data().each(function (doclet) {
    var url = helper.longnameToUrl[doclet.longname];

    if (url.indexOf('#') > -1) {
      doclet.id = helper.longnameToUrl[doclet.longname].split(/#/).pop();
    }
    else {
      doclet.id = doclet.name;
    }

    if (needsSignature(doclet)) {
      addSignatureParams(doclet);
      addSignatureReturns(doclet);
      addAttribs(doclet);
    }
  });

  // do this after the urls have all been generated
  data().each(function (doclet) {
    doclet.ancestors = getAncestorLinks(doclet);

    if (doclet.kind === 'member') {
      addSignatureTypes(doclet);
      addAttribs(doclet);
    }

    if (doclet.kind === 'constant') {
      addSignatureTypes(doclet);
      addAttribs(doclet);
      doclet.kind = 'member';
    }
  });

  var members = helper.getMembers(data);
  members.tutorials = tutorials.children;

  // add template helpers
  view.find = find;
  view.linkto = linkto;
  view.resolveAuthorLinks = resolveAuthorLinks;
  view.tutoriallink = tutoriallink;
  view.htmlsafe = htmlsafe;

  // once for all
  view.nav = buildNav(members);

  // only output pretty-printed source files if requested; do this before generating any other
  // pages, so the other pages can link to the source files
  if (conf['default'].outputSourceFiles) {
    generateSourceFiles(sourceFiles);
  }

  if (members.globals.length) {
    generate('Global', [
      {kind: 'globalobj'}
    ], globalUrl);
  }

  // index page displays information from package.json and lists files
  var files = find({kind: 'file'}),
      packages = find({kind: 'package'});

  generate('Index',
      packages.concat(
          [
            {kind: 'mainpage', readme: opts.readme, longname: (opts.mainpagetitle) ? opts.mainpagetitle : 'Main Page'}
          ]
      ).concat(files),
      indexUrl);

  // set up the lists that we'll use to generate pages
  var classes = taffy(members.classes);
  var modules = taffy(members.modules);
  var namespaces = taffy(members.namespaces);
  var mixins = taffy(members.mixins);
  var externals = taffy(members.externals);

  members.functions = helper.find(data, {kind: 'function', includeDoc: true});
  var functions = taffy(members.functions);

  var counter=0;
  for (var longname in helper.longnameToUrl) {
    if (hasOwnProp.call(helper.longnameToUrl, longname)) {
      var myClasses = helper.find(classes, {longname: longname});
      if (myClasses.length) {
        generate(myClasses[0].name, myClasses, helper.longnameToUrl[longname]);
      }

      var myModules = helper.find(modules, {longname: longname});
      if (myModules.length) {
        generate('Module: ' + myModules[0].name, myModules, helper.longnameToUrl[longname]);
      }

      var myNamespaces = helper.find(namespaces, {longname: longname});
      if (myNamespaces.length) {
        generate('Namespace: ' + myNamespaces[0].name, myNamespaces, helper.longnameToUrl[longname],undefined, members);
      }

      var myMixins = helper.find(mixins, {longname: longname});
      if (myMixins.length) {
        generate('Mixin: ' + myMixins[0].name, myMixins, helper.longnameToUrl[longname]);
      }

      var myExternals = helper.find(externals, {longname: longname});
      if (myExternals.length) {
        generate('External: ' + myExternals[0].name, myExternals, helper.longnameToUrl[longname]);
      }

      var myFunctions = helper.find(functions, {longname: longname, includeDoc: true});
      if (myFunctions.length) {
        var newName = myFunctions[0].memberof +'.'+myFunctions[0].name+'.html';
//        newName = newName.replace(/#/ig,'');
//        newName = newName.replace(/[']/ig,'');
//        log(myFunctions[0].memberof);
        generate(myFunctions[0].name, myFunctions, newName);
      }
    }
  }

  // TODO: move the tutorial functions to templateHelper.js
  function generateTutorial(title, tutorial, filename) {
    var tutorialData = {
      title: title,
      header: tutorial.title,
      content: tutorial.parse(),
      children: tutorial.children
    };

    var tutorialPath = path.join(outdir, filename),
        html = view.render('tutorial.tmpl', tutorialData);

    // yes, you can use {@link} in tutorials too!
    html = helper.resolveLinks(html); // turn {@link foo} into <a href="foodoc.html">foo</a>

    fs.writeFileSync(tutorialPath, html, 'utf8');
  }

  // tutorials can have only one parent so there is no risk for loops
  function saveChildren(node) {
    node.children.forEach(function (child) {
      generateTutorial('Tutorial: ' + child.title, child, helper.tutorialToUrl(child.name));
      saveChildren(child);
    });
  }

  saveChildren(tutorials);
};
exports.publish = function(taffyData, opts, tutorials) {
    data = taffyData;

    var conf = env.conf.templates || {};
    conf.default = conf.default || {};
    var templatePath = path.normalize(opts.template);
    view = new template.Template( path.join(templatePath, 'tmpl') );

    // claim some special filenames in advance, so the All-Powerful Overseer of Filename Uniqueness
    // doesn't try to hand them out later
    var indexUrl = helper.getUniqueFilename('index');
    // don't call registerLink() on this one! 'index' is also a valid longname

    var globalUrl = helper.getUniqueFilename('global');
    helper.registerLink('global', globalUrl);

    // set up templating
    view.layout = opts.layoutFile;

    // set up tutorials for helper
    helper.setTutorials(tutorials);

    data = helper.prune(data);
    data.sort('longname, version, since');
    helper.addEventListeners(data);

    var sourceFiles = {};
    var sourceFilePaths = [];
    data().each(function(doclet) {
         doclet.attribs = '';

        if (doclet.examples) {
            doclet.examples = doclet.examples.map(function(example) {
                var caption, code;

                if (example.match(/^\s*<caption>([\s\S]+?)<\/caption>(\s*[\n\r])([\s\S]+)$/i)) {
                    caption = RegExp.$1;
                    code = RegExp.$3;
                }

                return {
                    caption: caption || '',
                    code: code || example
                };
            });
        }
        if (doclet.codeExamples) {
            doclet.codeExamples = doclet.codeExamples.map(function(codeExample) {
                var caption, code;

                if (codeExample.match(/^\s*<caption>([\s\S]+?)<\/caption>(\s*[\n\r])([\s\S]+)$/i)) {
                    caption = RegExp.$1;
                    code = RegExp.$3;
                }

                return {
                    caption: caption || '',
                    code: code || codeExample
                };
            });
        }
        if (doclet.see) {
            doclet.see.forEach(function(seeItem, i) {
                doclet.see[i] = hashToLink(doclet, seeItem);
            });
        }

        // build a list of source files
        var sourcePath;
        if (doclet.meta) {
            sourcePath = getPathFromDoclet(doclet);
            sourceFiles[sourcePath] = {
                resolved: sourcePath,
                shortened: null
            };
            if (sourceFilePaths.indexOf(sourcePath) === -1) {
                sourceFilePaths.push(sourcePath);
            }
        }
    });

    /*
     * Handle the defaul values for non optional properties correctly. 
     * 
     */
    data().each(function(doclet) {
        if (doclet.properties) {
            doclet.properties = doclet.properties.map(function(property) {
                var separator = " - ",
                    separatorLength = separator.length;
                
                var defaultvalue = property.defaultvalue;
                var description = property.description;

                if( property.defaultvalue !== 'undefined' && !property.optional && description.indexOf(separator) > 0) {
                    var index = description.indexOf(separator);
                    defaultvalue += " " + description.substr(separatorLength, index-separatorLength);
                    description = "<p>" + description.substr(index + separatorLength, description.length);
                }

                return {
                    defaultvalue: defaultvalue,
                    description: description,
                    type: property.type,
                    name: property.name
                }  
            });                  
        }
    });

    // update outdir if necessary, then create outdir
    var packageInfo = ( find({kind: 'package'}) || [] ) [0];
    if (packageInfo && packageInfo.name) {
        outdir = path.join( outdir, packageInfo.name, (packageInfo.version || '') );
    }
    fs.mkPath(outdir);

    // copy the template's static files to outdir
    var fromDir = path.join(templatePath, 'static');
    var staticFiles = fs.ls(fromDir, 3);

    staticFiles.forEach(function(fileName) {
        var toDir = fs.toDir( fileName.replace(fromDir, outdir) );
        fs.mkPath(toDir);
        fs.copyFileSync(fileName, toDir);
    });

    // copy user-specified static files to outdir
    var staticFilePaths;
    var staticFileFilter;
    var staticFileScanner;
    if (conf.default.staticFiles) {
        // The canonical property name is `include`. We accept `paths` for backwards compatibility
        // with a bug in JSDoc 3.2.x.
        staticFilePaths = conf.default.staticFiles.include ||
            conf.default.staticFiles.paths ||
            [];
        staticFileFilter = new (require('jsdoc/src/filter')).Filter(conf.default.staticFiles);
        staticFileScanner = new (require('jsdoc/src/scanner')).Scanner();

        staticFilePaths.forEach(function(filePath) {
            var extraStaticFiles;

            filePath = path.resolve(env.pwd, filePath);
            extraStaticFiles = staticFileScanner.scan([filePath], 10, staticFileFilter);

            extraStaticFiles.forEach(function(fileName) {
                var sourcePath = fs.toDir(filePath);
                var toDir = fs.toDir( fileName.replace(sourcePath, outdir) );
                fs.mkPath(toDir);
                fs.copyFileSync(fileName, toDir);
            });
        });
    }

    if (sourceFilePaths.length) {
        sourceFiles = shortenPaths( sourceFiles, path.commonPrefix(sourceFilePaths) );
    }
    data().each(function(doclet) {
        var url = helper.createLink(doclet);
        helper.registerLink(doclet.longname, url);

        // add a shortened version of the full path
        var docletPath;
        if (doclet.meta) {
            docletPath = getPathFromDoclet(doclet);
            docletPath = sourceFiles[docletPath].shortened;
            if (docletPath) {
                doclet.meta.shortpath = docletPath;
            }
        }

        var sourceLink;
        if (doclet.meta) {
            sourceLink = getLinkFromDoclet(doclet);
            doclet.meta.sourceLink = sourceLink;
        }
    });

    data().each(function(doclet) {
        var url = helper.longnameToUrl[doclet.longname];

        if (url.indexOf('#') > -1) {
            doclet.id = helper.longnameToUrl[doclet.longname].split(/#/).pop();
        }
        else {
            doclet.id = doclet.name;
        }

        if ( needsSignature(doclet) ) {
            addSignatureParams(doclet);
            //addSignatureReturns(doclet);
            addAttribs(doclet);
        }
    });

    // do this after the urls have all been generated
    data().each(function(doclet) {
        doclet.ancestors = getAncestorLinks(doclet);

        if (doclet.kind === 'member') {
            addSignatureTypes(doclet);
            addAttribs(doclet);
        }

        if (doclet.kind === 'constant') {
            addSignatureTypes(doclet);
            addAttribs(doclet);
            doclet.kind = 'member';
            doclet.constant = true;
        }
    });

    data().each(function(doclet) {
        if(!doclet.ignore) {
            var parent = find({longname: doclet.memberof})[0];
            if( !parent ) {
                doclet.scopeEf = doclet.scope;
            } else {
                if(doclet.scope === 'static' && parent.kind !== 'class') {
                    doclet.scopeEf = 'instance';
                } else if(doclet.scope === 'static' && parent.static && parent.kind === 'class') {
                    doclet.scopeEf = 'instance';
                } else {
                    doclet.scopeEf = doclet.scope;
                }
            }
        }
    });

    // handle summary, description and class description default values properly
    data().each(function(doclet) {
        if(!doclet.ignore) {
            var desc;
            if(!doclet.summary && (desc = (doclet.description || doclet.classdesc))) {
                // Try to split when a "." or a ".</htmlTag>" is found.
                /*
                    ^              - start of string
                    \s*            - optional leading space
                    <tagName>      - optional tag, whose tagName is captured in m[1] and \1
                    \s*            - optional white space
                    (.|\n|\r)+?\.  - summary text, that can cross lines, and ends in a period; captured in m[2]
                    \s*            - optional white space
                    (
                      $          - the end of the string, or
                      \r|\n      - line-break, or
                      </tagName> - the closing tag from the corresponding to the beginning opening tag
                    )
                */
                var m = (/^\s*(?:<(\w+)>)?\s*((?:.|\n|\r)+?\.)\s*?($|(\r|\n)|(<\/\1>))/i).exec(desc);
                if(m) {
                  // MATCHED!
                  var tagName = m[1];
                  var summary = m[2];
                  if(tagName) summary = "<" + tagName + ">" + summary + "</" + tagName + ">";

                  doclet.summary = summary;
                  //console.log("summary: " + summary);
                  //console.log("  description: " + desc);
                  //console.log(" ");
                } else {
                  console.warn("Could not determine summary for: " + desc);
                }
            }

            var checkP = function(prop) {
                if(!prop) return;

                prop = prop.replace(/<p><p>/g, "<p>");

                if(prop.indexOf("<p>") == -1) {
                    return "<p>" + prop + "</p>";
                } 

                return prop;
            };

            var replaceCode = function(string) {
                if(!string) return;
                var flip = true;
                var idx = string.indexOf("`");
                while(idx > -1) {
                  string = string.substr(0, idx) + (flip ? "<code>" : "</code>") + string.substr(idx + 1);
                  flip = !flip;
                  idx = string.indexOf("`");
                }
                return string;
            };

            doclet.summary = replaceCode(checkP(doclet.summary));
            doclet.description = replaceCode(checkP(doclet.description));
            doclet.classdesc = replaceCode(checkP(doclet.classdesc));
        }
    });

    //handle splits and joins on names
    data().each(function(doclet) {
        if(!doclet.ignore) {
            var split = function(str, sep) {
                if(str) {
                    return str.split(sep).join('');
                } 
            }

            //dont split for code
            if(doclet.description && doclet.description.indexOf("syntax.javascript") == -1) {
                doclet.description = split(doclet.description, '<br>');
            }
            if(doclet.classdesc && doclet.classdesc.indexOf("syntax.javascript") == -1) {
                doclet.classdesc = split(doclet.classdesc, '<br>');
            }
            if(doclet.summary && doclet.summary.indexOf("syntax.javascript") == -1) { 
                doclet.summary = split(doclet.summary, '<br>');
            }
            
            doclet.parsedName = split(doclet.name, '"')
            doclet.parsedLongname = split(doclet.longname, '"')
        }
    });

    var members = helper.getMembers(data);
    members.tutorials = tutorials.children;
    
    // add template helpers
    view.find = find;
    view.linkto = linkto;
    view.resolveAuthorLinks = resolveAuthorLinks;
    view.tutoriallink = tutoriallink;
    view.htmlsafe = htmlsafe;
    
    // once for all
    view.nav = buildNav(findMembers(data, 'namespace'));
    attachModuleSymbols( find({ longname: {left: 'module:'} }), members.modules );

    if (members.globals.length) { generate('Global', [{kind: 'globalobj'}], globalUrl); }

    // index page displays information from package.json and lists files
    var files = find({kind: 'file'}),
        packages = find({kind: 'package'});

    generate('Home',
        packages.concat(
            [{kind: 'mainpage', readme: opts.readme, longname: (opts.mainpagetitle) ? opts.mainpagetitle : 'Main Page'}]
        ).concat(files),
    indexUrl);

    // set up the lists that we'll use to generate pages
    var classes = taffy(members.classes);
    var modules = taffy(members.modules);
    var namespaces = taffy(members.namespaces);
    var mixins = taffy(members.mixins);
    var externals = taffy(members.externals);
    var interfaces = taffy(members.interfaces);

    Object.keys(helper.longnameToUrl).forEach(function(longname) {
        var myModules = helper.find(modules, {longname: longname});
        if (myModules.length) {
            generate('Module: ' + myModules[0].name, myModules, helper.longnameToUrl[longname]);
        }

        var myClasses = helper.find(classes, {longname: longname});
        if (myClasses.length) {
            generate('Class: ' + myClasses[0].name, myClasses, helper.longnameToUrl[longname]);
        }

        var myNamespaces = helper.find(namespaces, {longname: longname});
        if (myNamespaces.length) {
            generate('Namespace: ' + myNamespaces[0].name, myNamespaces, helper.longnameToUrl[longname]);
        }

        var myMixins = helper.find(mixins, {longname: longname});
        if (myMixins.length) {
            generate('Mixin: ' + myMixins[0].name, myMixins, helper.longnameToUrl[longname]);
        }

        var myExternals = helper.find(externals, {longname: longname});
        if (myExternals.length) {
            generate('External: ' + myExternals[0].name, myExternals, helper.longnameToUrl[longname]);
        }

        var myInterfaces = helper.find(interfaces, {longname: longname});
        if (myInterfaces.length) {
            generate('Interface: ' + myInterfaces[0].name, myInterfaces, helper.longnameToUrl[longname]);
        }
    });

    // TODO: move the tutorial functions to templateHelper.js
    function generateTutorial(title, tutorial, filename) {
        var tutorialData = {
            title: title,
            header: tutorial.title,
            content: tutorial.parse(),
            children: tutorial.children
        };

        var tutorialPath = path.join(outdir, filename),
            html = view.render('tutorial.tmpl', tutorialData);

        // yes, you can use {@link} in tutorials too!
        html = helper.resolveLinks(html); // turn {@link foo} into <a href="foodoc.html">foo</a>

        fs.writeFileSync(tutorialPath, html, 'utf8');
    }

    // tutorials can have only one parent so there is no risk for loops
    function saveChildren(node) {
        node.children.forEach(function(child) {
            generateTutorial('Tutorial: ' + child.title, child, helper.tutorialToUrl(child.name));
            saveChildren(child);
        });
    }
    saveChildren(tutorials);
};
Пример #14
0
    publish = function(data, opts, tutorials) {
        var out = '',
            view = new template.Template(__dirname + '/templates/default/tmpl');
        
        // set up templating
        view.layout = 'layout.tmpl';

        // set up tutorials for helper
        helper.setTutorials(tutorials);

        function find(spec) {
            return data.get( data.find(spec) );
        }
        
        function htmlsafe(str) {
            return str.replace(/</g, '&lt;');
        }

        function addSignatureParams(f) {
            var pnames = [];
            if (f.params) {
                f.params.forEach(function(p) {
                    if (p.name && p.name.indexOf('.') === -1) {
                        if (p.optional) { pnames.push('<span class="optional">'+p.name+'</span>'); }
                        else { pnames.push(p.name); }
                    }
                });
            }
            
            f.signature = (f.signature || '') + '('+pnames.join(', ')+')';
        }
        
        function generateAncestry(thisdoc) {
            var ancestors = [],
                doc = thisdoc;

            while (doc = doc.memberof) {
                doc = find({longname: doc});
                if (doc) { doc = doc[0]; }
                if (!doc) break;
                ancestors.unshift( linkto(doc.longname, (scopeToPunc[doc.scope] || '') + doc.name) );
            }
            if (ancestors.length) {
                ancestors[ancestors.length-1] += (scopeToPunc[thisdoc.scope] || '');
            }
            return ancestors;
        }
        
        function addSignatureReturns(f) {
            var returnTypes = [];
            
            if (f.returns) {
                f.returns.forEach(function(r) {
                    if (r.type && r.type.names) {
                        if (! returnTypes.length) { returnTypes = r.type.names; }
                    }
                });
            }
            
            if (returnTypes && returnTypes.length) {
                returnTypes = returnTypes.map(function(r) {
                    return linkto(r);
                });
            }
            f.signature = '<span class="signature">'+(f.signature || '') + '</span>' + '<span class="type-signature">'+(returnTypes.length? ' &rarr; {'+returnTypes.join('|')+'}' : '')+'</span>';
        }
        
        function addSignatureType(f) {
            var types = [];
            
            if (f.type && f.type.names) {
                types = f.type.names;
            }
            
            if (types && types.length) {
                types = types.map(function(t) {
                    return linkto(t, htmlsafe(t));
                });
            } 
               
            f.signature = (f.signature || '') + '<span class="type-signature">'+(types.length? ' :'+types.join('|') : '')+'</span>';
        }
        
        function addAttribs(f) {
            var attribs = [];
            
            if (f.virtual) {
                attribs.push('virtual');
            }
            
            if (f.access && f.access !== 'public') {
                attribs.push(f.access);
            }
            
            if (f.scope && f.scope !== 'instance' && f.scope !== 'global') {
                if (f.kind == 'function' || f.kind == 'member' || f.kind == 'constant') attribs.push(f.scope);
            }
            
            if (f.readonly === true) {
                if (f.kind == 'member') attribs.push('readonly');
            }
            
            if (f.kind === 'constant') {
                attribs.push('constant');
                f.kind = 'member';
            }
            
            f.attribs = '<span class="type-signature">'+htmlsafe(attribs.length? '<'+attribs.join(', ')+'> ' : '')+'</span>';
        }
        
        data.remove({undocumented: true});
        data.remove({ignore: true});
        if (!opts.private) { data.remove({access: 'private'}); }
        data.remove({memberof: '<anonymous>'});
	    
	    var packageInfo = (find({kind: 'package'}) || []) [0];
        
        //function renderLinks(text) {
        //    return helper.resolveLinks(text);
        //}
        
	    data.forEach(function(doclet) {
             doclet.attribs = '';

	        
	        if (doclet.examples) {
	            doclet.examples = doclet.examples.map(function(example) {
	                var caption, code;
	                
	                if (example.match(/^\s*<caption>([\s\S]+?)<\/caption>(\s*[\n\r])([\s\S]+)$/i)) {
	                    caption = RegExp.$1;
	                    code    = RegExp.$3;
	                }
	                
                    return {
                        caption: caption || '',
                        code: code || example
                    };
                });
	        }
	        if (doclet.see) {
	            doclet.see.forEach(function(seeItem, i) {
	                doclet.see[i] = hashToLink(doclet, seeItem);
	            });
	        }
	    });
	    
	    data.orderBy(['longname', 'version', 'since']);
        
        // kinds of containers
        var globals = find( {kind: ['member', 'function', 'constant', 'typedef'], memberof: {isUndefined: true}} ),
            modules = find({kind: 'module'}),
            externals = find({kind: 'external'}),
            mixins = find({kind: 'mixin'}),
	        namespaces = find({kind: 'namespace'}),
			glslTypes = find({kind: 'glsl'});

        var outdir = opts.destination;
        if (packageInfo && packageInfo.name) {
            outdir += '/' + packageInfo.name + '/' + packageInfo.version + '/';
        }
        fs.mkPath(outdir);

        // copy static files to outdir
        var fromDir = __dirname + '/templates/default/static',
            staticFiles = fs.ls(fromDir, 3);
            
        staticFiles.forEach(function(fileName) {
            var toDir = fs.toDir(fileName.replace(fromDir, outdir));
            fs.mkPath(toDir);
            fs.copyFile(fileName, toDir);
        });
        
        function linkto(longname, linktext) {
            var url = helper.longnameToUrl[longname];
            return url? '<a href="'+url+'">'+(linktext || longname)+'</a>' : (linktext || longname);
        }
        
        function tutoriallink(tutorial) {
            return helper.toTutorial(tutorial);
        }
        
        var containers = ['class', 'module', 'external', 'namespace', 'mixin'];
        
        data.forEach(function(doclet) {
            var url = helper.createLink(doclet);
            helper.registerLink(doclet.longname, url);
        });
        
        data.forEach(function(doclet) {
            var url = helper.longnameToUrl[doclet.longname];

	        if (url.indexOf('#') > -1) {
	            doclet.id = helper.longnameToUrl[doclet.longname].split(/#/).pop();
	        }
	        else {
	            doclet.id = doclet.name;
	        }
	        
	        if (doclet.kind === 'function' || doclet.kind === 'class') {
	            addSignatureParams(doclet);
	            addSignatureReturns(doclet);
	            addAttribs(doclet);
	        }
	    })
        
        // do this after the urls have all been generated
        data.forEach(function(doclet) {
            doclet.ancestors = generateAncestry(doclet);
            
            doclet.signature = '';
	        
	        if (doclet.kind === 'member') {
	            addSignatureType(doclet);
	            addAttribs(doclet)
	        }
	        
	        if (doclet.kind === 'constant') {
	            addSignatureType(doclet);
	            addAttribs(doclet)
	        }
        });
        
        var nav = '',
            seen = {};
        
        nav += '<ul id="ClassList"><div id="classItems">';	// Start single class list, begin JavaScript div
        var classNames = find({kind: 'class'});
        if (classNames.length) {
            //nav += '<h3>Classes</h3><ul>';
            classNames.forEach(function(c) {
                var moduleSameName = find({kind: 'module', longname: c.longname});
                if (moduleSameName.length) {
                    c.name = c.name.replace('module:', 'require(')+')';
                    moduleSameName[0].module = c;
                }
                
                if (!seen.hasOwnProperty(c.longname) ) nav += '<li>'+linkto(c.longname, c.name)+'</li>';
                seen[c.longname] = true;
            });
            //nav += '</ul>';
        }
		
        var moduleNames = find({kind: 'module'});
        if (moduleNames.length) {
            //nav += '<h3>Modules</h3><ul>';
            moduleNames.forEach(function(m) {
                if ( !seen.hasOwnProperty(m.longname) ) nav += '<li>'+linkto(m.longname, m.name)+'</li>';
                seen[m.longname] = true;
            });
            //nav += '</ul>';
        }
        
        var externalNames = find({kind: 'external'});
        if (externalNames.length) {
            //nav += '<h3>Externals</h3><ul>';
            externalNames.forEach(function(e) {
                if ( !seen.hasOwnProperty(e.longname) ) nav += '<li>'+linkto( e.longname, e.name.replace(/(^"|"$)/g, '') )+'</li>';
                seen[e.longname] = true;
            });
            //nav += '</ul>';
        }
        
        var namespaceNames = find({kind: 'namespace'});
        if (namespaceNames.length) {
            //nav += '<h3>Namespaces</h3><ul>';
            namespaceNames.forEach(function(n) {
                if ( !seen.hasOwnProperty(n.longname) ) nav += '<li>'+linkto(n.longname, n.name)+'</li>';
                seen[n.longname] = true;
            });
            //nav += '</ul>';
        }
		
        var glslNames = find({kind: 'glsl'});
        nav += '</div><div id="glslItems">';	// End classItems div, start GLSL div
        if (glslNames.length) {
            glslNames.forEach(function(g) {
                if ( !seen.hasOwnProperty(g.longname) ) nav += '<li>'+linkto(g.longname, g.name)+'</li>';
                seen[g.longname] = true;
            });    
        }
        nav += '</div></ul>';	// End GLSL div, end Class list
        
//         var constantNames = find({kind: 'constants'});
//         if (constantNames.length) {
//             nav += '<h3>Constants</h3><ul>';
//             constantNames.forEach(function(c) {
//                 if ( !seen.hasOwnProperty(c.longname) ) nav += '<li>'+linkto(c.longname, c.name)+'</li>';
//                 seen[c.longname] = true;
//             });
//             
//             nav += '</ul>';
//         }
/*        
        var mixinNames = find({kind: 'mixin'});
        if (mixinNames.length) {
            nav += '<h3>Mixins</h3><ul>';
            mixinNames.forEach(function(m) {
                if ( !seen.hasOwnProperty(m.longname) ) nav += '<li>'+linkto(m.longname, m.name)+'</li>';
                seen[m.longname] = true;
            });
            
            nav += '</ul>';
        }

        if (tutorials.children.length) {
            nav += '<h3>Tutorials</h3><ul>';
            tutorials.children.forEach(function(t) {
                nav += '<li>'+tutoriallink(t.name)+'</li>';
            });
            
            nav += '</ul>';
        }
        
        var globalNames = find({kind: ['members', 'function', 'constant', 'typedef'], 'memberof': {'isUndefined': true}});
        if (globalNames.length) {
            nav += '<h3>Global</h3><ul>';
            globalNames.forEach(function(g) {
                if ( g.kind !== 'typedef' && !seen.hasOwnProperty(g.longname) ) nav += '<li>'+linkto(g.longname, g.name)+'</li>';
                seen[g.longname] = true;
            });
            
            nav += '</ul>';
        }
 */		
        // add template helpers
        view.find = find;
        view.linkto = linkto;
        view.tutoriallink = tutoriallink;
        view.htmlsafe = htmlsafe;
        // once for all
        view.nav = nav;

        var types_json = {};
        for (var longname in helper.longnameToUrl) {
            var classes = find({kind: 'class', longname: longname});
            if (classes.length) generate(classes[0].name, classes, helper.longnameToUrl[longname]);
			
			var glslTypes = find({kind: 'glsl', longname: longname});
            if (glslTypes.length) generate(glslTypes[0].name, glslTypes, helper.longnameToUrl[longname]);
			
            var modules = find({kind: 'module', longname: longname});
            if (modules.length) generate(modules[0].name, modules, helper.longnameToUrl[longname]);
            
            var namespaces = find({kind: 'namespace', longname: longname});
            if (namespaces.length) generate('Namespace: '+namespaces[0].name, namespaces, helper.longnameToUrl[longname]);        
            
//            var constants = find({kind: 'constant', longname: longname});
//            if (constants.length) generate('Constant: '+constants[0].name, constants, helper.longnameToUrl[longname]);        

            var mixins = find({kind: 'mixin', longname: longname});
            if (mixins.length) generate('Mixin: '+mixins[0].name, mixins, helper.longnameToUrl[longname]);        
        
            var externals = find({kind: 'external', longname: longname});
            if (externals.length) generate('External: '+externals[0].name, externals, helper.longnameToUrl[longname]);
        }

        //if (globals.length) generate('Global', [{kind: 'globalobj'}], 'global.html');
        
        view.layout = 'index.tmpl';
        var indexHtml = view.render('empty.tmpl', { title: 'Cesium Documentation' });
        fs.writeFileSync(outdir + '/index.html', indexHtml);
        
        fs.writeFileSync(outdir + '/types.txt', JSON.stringify(types_json));
        
        function generate(title, docs, filename) {
            var data = {
                title: title,
                docs: docs
            };
            
            var path = outdir + '/' + filename,
                html = view.render('container.tmpl', data);
            
            html = helper.resolveLinks(html); // turn {@link foo} into <a href="foodoc.html">foo</a>
            
            if (title in types_json) {
                types_json[title].push(filename);
            } else {
                types_json[title] = [ filename ];
            }
            
            var pos = 0, pos2, member, match = 'h4 class="name" id="', matchLen = match.length;
            while ((pos = html.indexOf(match, pos)) >= 0) {
                pos += matchLen;
                if ((pos2 = html.indexOf('"', pos)) > 0) {
                    member = html.substring(pos, pos2);
                    if (member !== title) {
                        if (member in types_json) {
                            // Note that ".toString" and ".valueOf" are discarded here.
                            if (typeof types_json[member].push === 'function') {
                                types_json[member].push(filename + '#' + member);
                            }
                        } else {
                            types_json[member] = [ filename + '#' + member ];
                        }
                    }
                }
            }
            
            fs.writeFileSync(path, html);
        }
        
        function generateTutorial(title, tutorial, filename) {
            var data = {
                title: title,
                header: tutorial.title,
                content: tutorial.parse(),
                children: tutorial.children
            };
            
            var path = outdir + '/' + filename,
                html = view.render('tutorial.tmpl', data);
            
            // yes, you can use {@link} in tutorials too!
            html = helper.resolveLinks(html); // turn {@link foo} into <a href="foodoc.html">foo</a>
            
            fs.writeFileSync(path, html);
        }
        
        // tutorials can have only one parent so there is no risk for loops
        function saveChildren(node) {
            node.children.forEach(function(child) {
                generateTutorial('Tutorial: '+child.title, child, helper.tutorialToUrl(child.name));
                saveChildren(child);
            });
        }
        saveChildren(tutorials);
    }
Пример #15
0
exports.publish = function (taffyData, opts, tutorials) {
    data = taffyData

    var conf     = env.conf.templates || {}
    conf.default = conf.default || {}

    var templatePath = path.normalize(opts.template)
    view             = new template.Template(path.join(templatePath, "tmpl"))

    // claim some special filenames in advance, so the All-Powerful Overseer of Filename Uniqueness
    // doesn't try to hand them out later
    var indexUrl = helper.getUniqueFilename("index")

    // don't call registerLink() on this one! 'index' is also a valid longname
    var globalUrl = helper.getUniqueFilename("global")
    helper.registerLink("global", globalUrl)

    // set up templating
    view.layout = conf.default.layoutFile
        ? path.getResourcePath(
            path.dirname(conf.default.layoutFile),
            path.basename(conf.default.layoutFile)
        )
        : "layout.tmpl"

    // set up tutorials for helper
    helper.setTutorials(tutorials)
    data = helper.prune(data)
    data.sort("longname, version, since")
    helper.addEventListeners(data)

    var sourceFiles     = {}
    var sourceFilePaths = []

    data().each(function (doclet) {
        doclet.attribs = ""

        if (doclet.examples) {
            doclet.examples = doclet.examples.map(function (example) {
                var caption, code

                if (
                    example.match(
                        /^\s*<caption>([\s\S]+?)<\/caption>(\s*[\n\r])([\s\S]+)$/i
                    )
                ) {
                    caption = RegExp.$1
                    code    = RegExp.$3
                }

                return {
                    caption: caption || "",
                    code:    code || example
                }
            })
        }

        if (doclet.see) {
            doclet.see.forEach(function (seeItem, i) {
                doclet.see[i] = hashToLink(doclet, seeItem)
            })
        }

        // build a list of source files
        var sourcePath
        if (doclet.meta) {
            sourcePath = getPathFromDoclet(doclet)

            sourceFiles[sourcePath] = {
                resolved:  sourcePath,
                shortened: null
            }

            if (sourceFilePaths.indexOf(sourcePath) === -1) {
                sourceFilePaths.push(sourcePath)
            }
        }
    })

    // update outdir if necessary, then create outdir
    var packageInfo = (find({kind: "package"}) || [])[0]
    if (packageInfo && packageInfo.name) {
        outdir = path.join(outdir, packageInfo.name, packageInfo.version || "")
    }
    fs.mkPath(outdir)

    // copy the template's static files to outdir
    var fromDir     = path.join(templatePath, "static")
    var staticFiles = fs.ls(fromDir, 3)

    staticFiles.forEach(function (fileName) {
        var toDir = fs.toDir(fileName.replace(fromDir, outdir))
        fs.mkPath(toDir)
        fs.copyFileSync(fileName, toDir)
    })

    // copy user-specified static files to outdir
    var staticFilePaths
    var staticFileFilter
    var staticFileScanner
    if (conf.default.staticFiles) {
        // The canonical property name is `include`. We accept `paths` for backwards compatibility
        // with a bug in JSDoc 3.2.x.
        staticFilePaths   = conf.default.staticFiles.include ||
            conf.default.staticFiles.paths || []
        staticFileFilter  = new (require("jsdoc/src/filter").Filter)(
            conf.default.staticFiles
        )
        staticFileScanner = new (require("jsdoc/src/scanner").Scanner)()

        staticFilePaths.forEach(function (filePath) {
            var extraStaticFiles = staticFileScanner.scan(
                [filePath],
                10,
                staticFileFilter
            )

            extraStaticFiles.forEach(function (fileName) {
                var sourcePath = fs.toDir(filePath)
                var toDir      = fs.toDir(fileName.replace(sourcePath, outdir))
                fs.mkPath(toDir)
                fs.copyFileSync(fileName, toDir)
            })
        })
    }

    if (sourceFilePaths.length) {
        sourceFiles = shortenPaths(sourceFiles, path.commonPrefix(sourceFilePaths))
    }

    data().each(function (doclet) {
        var url = helper.createLink(doclet)
        helper.registerLink(doclet.longname, url)

        // add a shortened version of the full path
        var docletPath
        if (doclet.meta) {
            docletPath = getPathFromDoclet(doclet)
            docletPath = sourceFiles[docletPath].shortened
            if (docletPath) {
                doclet.meta.shortpath = docletPath
            }
        }
    })

    data().each(function (doclet) {
        var url = helper.longnameToUrl[doclet.longname]

        if (url.indexOf("#") > -1) {
            doclet.id = helper.longnameToUrl[doclet.longname].split(/#/).pop()
        } else {
            doclet.id = doclet.name
        }

        if (needsSignature(doclet)) {
            addSignatureParams(doclet)
            addSignatureReturns(doclet)
            addAttribs(doclet)
        }
    })

    // do this after the urls have all been generated
    data().each(function (doclet) {
        doclet.ancestors = getAncestorLinks(doclet)

        if (doclet.kind === "member") {
            addSignatureTypes(doclet)
            addAttribs(doclet)
        }

        if (doclet.kind === "constant") {
            addSignatureTypes(doclet)
            addAttribs(doclet)
            doclet.kind = "member"
        }
    })

    var members       = helper.getMembers(data)
    members.tutorials = tutorials.children

    // output pretty-printed source files by default
    var outputSourceFiles = conf.default &&
    conf.default.outputSourceFiles !== false
        ? true
        : false

    // add template helpers
    view.find               = find
    view.linkto             = linkto
    view.resolveAuthorLinks = resolveAuthorLinks
    view.tutoriallink       = tutoriallink
    view.htmlsafe           = htmlsafe
    view.outputSourceFiles  = outputSourceFiles

    // once for all
    view.nav = buildNav(members)
    attachModuleSymbols(find({longname: {left: "module:"}}), members.modules)

    // generate the pretty-printed source files first so other pages can link to them
    if (outputSourceFiles) {
        generateSourceFiles(sourceFiles, opts.encoding)
    }

    if (members.globals.length) {
        generate("", "Global", [{kind: "globalobj"}], globalUrl)
    }

    // index page displays information from package.json and lists files
    var files    = find({kind: "file"})
    var packages = find({kind: "package"})

    generate(
        "",
        "Home",
        packages
            .concat([
                {
                    kind:     "mainpage",
                    readme:   opts.readme,
                    longname: opts.mainpagetitle ? opts.mainpagetitle : "Main Page"
                }
            ])
            .concat(files),
        indexUrl
    )

    // set up the lists that we'll use to generate pages
    var classes    = taffy(members.classes)
    var modules    = taffy(members.modules)
    var namespaces = taffy(members.namespaces)
    var mixins     = taffy(members.mixins)
    var externals  = taffy(members.externals)
    var interfaces = taffy(members.interfaces)

    Object.keys(helper.longnameToUrl).forEach(function (longname) {
        var myModules = helper.find(modules, {longname: longname})
        if (myModules.length) {
            generate(
                "Module",
                myModules[0].name,
                myModules,
                helper.longnameToUrl[longname]
            )
        }

        var myClasses = helper.find(classes, {longname: longname})
        if (myClasses.length) {
            generate(
                "Class",
                myClasses[0].name,
                myClasses,
                helper.longnameToUrl[longname]
            )
        }

        var myNamespaces = helper.find(namespaces, {longname: longname})
        if (myNamespaces.length) {
            generate(
                "Namespace",
                myNamespaces[0].name,
                myNamespaces,
                helper.longnameToUrl[longname]
            )
        }

        var myMixins = helper.find(mixins, {longname: longname})
        if (myMixins.length) {
            generate(
                "Mixin",
                myMixins[0].name,
                myMixins,
                helper.longnameToUrl[longname]
            )
        }

        var myExternals = helper.find(externals, {longname: longname})
        if (myExternals.length) {
            generate(
                "External",
                myExternals[0].name,
                myExternals,
                helper.longnameToUrl[longname]
            )
        }

        var myInterfaces = helper.find(interfaces, {longname: longname})
        if (myInterfaces.length) {
            generate(
                "Interface",
                myInterfaces[0].name,
                myInterfaces,
                helper.longnameToUrl[longname]
            )
        }
    })

    // TODO: move the tutorial functions to templateHelper.js
    function generateTutorial(title, tutorial, filename) {
        var tutorialData = {
            title:    title,
            header:   tutorial.title,
            content:  tutorial.parse(),
            children: tutorial.children
        }

        var tutorialPath = path.join(outdir, filename)
        var html         = view.render("tutorial.tmpl", tutorialData)

        // yes, you can use {@link} in tutorials too!
        html = helper.resolveLinks(html) // turn {@link foo} into <a href="foodoc.html">foo</a>
        fs.writeFileSync(tutorialPath, html, "utf8")
    }

    // tutorials can have only one parent so there is no risk for loops
    function saveChildren(node) {
        node.children.forEach(function (child) {
            generateTutorial(
                child.title,
                child,
                helper.tutorialToUrl(child.name)
            )
            saveChildren(child)
        })
    }

    saveChildren(tutorials)
}
Пример #16
0
exports.publish = function(taffyData, opts, tutorials) {
    data = taffyData;

    var conf = env.conf.templates || {};
    conf.default = conf.default || {};

    var templatePath = path.normalize(opts.template);
    view = new template.Template( path.join(templatePath, 'tmpl') );

    // claim some special filenames in advance, so the All-Powerful Overseer of Filename Uniqueness
    // doesn't try to hand them out later
    var indexUrl = helper.getUniqueFilename('index');
    // don't call registerLink() on this one! 'index' is also a valid longname

    var globalUrl = helper.getUniqueFilename('global');
    helper.registerLink('global', globalUrl);

    // set up templating
    view.layout = conf.default.layoutFile ?
        path.getResourcePath(path.dirname(conf.default.layoutFile),
            path.basename(conf.default.layoutFile) ) :
        'layout.tmpl';

    // set up tutorials for helper
    helper.setTutorials(tutorials);

    data = helper.prune(data);
    data.sort('longname, version, since');
    helper.addEventListeners(data);

    var sourceFiles = {};
    var sourceFilePaths = [];
    data().each(function(doclet) {
         doclet.attribs = '';

        if (doclet.examples) {
            doclet.examples = doclet.examples.map(function(example) {
                var caption, code;

                if (example.match(/^\s*<caption>([\s\S]+?)<\/caption>(\s*[\n\r])([\s\S]+)$/i)) {
                    caption = RegExp.$1;
                    code = RegExp.$3;
                }

                return {
                    caption: caption || '',
                    code: code || example
                };
            });
        }
        if (doclet.see) {
            doclet.see.forEach(function(seeItem, i) {
                doclet.see[i] = hashToLink(doclet, seeItem);
            });
        }

        // build a list of source files
        var sourcePath;
        if (doclet.meta) {
            sourcePath = getPathFromDoclet(doclet);
            sourceFiles[sourcePath] = {
                resolved: sourcePath,
                shortened: null
            };
            if (sourceFilePaths.indexOf(sourcePath) === -1) {
                sourceFilePaths.push(sourcePath);
            }
        }
    });

    // update outdir if necessary, then create outdir
    var packageInfo = ( find({kind: 'package'}) || [] ) [0];
    if (packageInfo && packageInfo.name) {
        outdir = path.join( outdir, packageInfo.name, (packageInfo.version || '') );
    }
    fs.mkPath(outdir);

    // copy the template's static files to outdir
    var fromDir = path.join(templatePath, 'static');
    var staticFiles = fs.ls(fromDir, 3);

    staticFiles.forEach(function(fileName) {
        var toDir = fs.toDir( fileName.replace(fromDir, outdir) );
        fs.mkPath(toDir);
        fs.copyFileSync(fileName, toDir);
    });

    // copy user-specified static files to outdir
    var staticFilePaths;
    var staticFileFilter;
    var staticFileScanner;
    if (conf.default.staticFiles) {
        // The canonical property name is `include`. We accept `paths` for backwards compatibility
        // with a bug in JSDoc 3.2.x.
        staticFilePaths = conf.default.staticFiles.include ||
            conf.default.staticFiles.paths ||
            [];
        staticFileFilter = new (require('jsdoc/src/filter')).Filter(conf.default.staticFiles);
        staticFileScanner = new (require('jsdoc/src/scanner')).Scanner();

        staticFilePaths.forEach(function(filePath) {
            var extraStaticFiles = staticFileScanner.scan([filePath], 10, staticFileFilter);

            extraStaticFiles.forEach(function(fileName) {
                var sourcePath = fs.toDir(filePath);
                var toDir = fs.toDir( fileName.replace(sourcePath, outdir) );
                fs.mkPath(toDir);
                fs.copyFileSync(fileName, toDir);
            });
        });
    }

    if (sourceFilePaths.length) {
        sourceFiles = shortenPaths( sourceFiles, path.commonPrefix(sourceFilePaths) );
    }
    data().each(function(doclet) {
        var url = helper.createLink(doclet);
        helper.registerLink(doclet.longname, url);

        // add a shortened version of the full path
        var docletPath;
        if (doclet.meta) {
            docletPath = getPathFromDoclet(doclet);
            docletPath = sourceFiles[docletPath].shortened;
            if (docletPath) {
                doclet.meta.shortpath = docletPath;
            }
        }
    });

    data().each(function(doclet) {
        var url = helper.longnameToUrl[doclet.longname];

        if (url.indexOf('#') > -1) {
            doclet.id = helper.longnameToUrl[doclet.longname].split(/#/).pop();
        }
        else {
            doclet.id = doclet.name;
        }

        if ( needsSignature(doclet) ) {
            addSignatureParams(doclet);
            addSignatureReturns(doclet);
            addAttribs(doclet);
        }
    });

    // do this after the urls have all been generated
    data().each(function(doclet) {
        doclet.ancestors = getAncestorLinks(doclet);

        if (doclet.kind === 'member') {
            addSignatureTypes(doclet);
            addAttribs(doclet);
        }

        if (doclet.kind === 'constant') {
            addSignatureTypes(doclet);
            addAttribs(doclet);
            doclet.kind = 'member';
        }
    });

    var members = helper.getMembers(data);
    members.tutorials = tutorials.children;

    // output pretty-printed source files by default
    var outputSourceFiles = conf.default && conf.default.outputSourceFiles !== false
        ? true
        : false;

    // add template helpers
    view.find = find;
    view.linkto = linkto;
    view.resolveAuthorLinks = resolveAuthorLinks;
    view.tutoriallink = tutoriallink;
    view.htmlsafe = htmlsafe;
    view.outputSourceFiles = outputSourceFiles;

    // once for all
    view.nav = buildNav(members);
    attachModuleSymbols( find({ longname: {left: 'module:'} }), members.modules );

    // generate the pretty-printed source files first so other pages can link to them
    if (outputSourceFiles) {
        generateSourceFiles(sourceFiles, opts.encoding);
    }

    if (members.globals.length) {
        generate('', 'Global', [{kind: 'globalobj'}], globalUrl);
    }

    // index page displays information from package.json and lists files
    var files = find({kind: 'file'});
    var packages = find({kind: 'package'});

    generate('', 'Home',
            [{kind: 'mainpage', readme: opts.readme, longname: (opts.mainpagetitle) ? opts.mainpagetitle : 'Main Page'}],
    indexUrl);

    // set up the lists that we'll use to generate pages
    var classes = taffy(members.classes);
    var modules = taffy(members.modules);
    var namespaces = taffy(members.namespaces);
    var mixins = taffy(members.mixins);
    var externals = taffy(members.externals);
    var interfaces = taffy(members.interfaces);

    Object.keys(helper.longnameToUrl).forEach(function(longname) {
        var myModules = helper.find(modules, {longname: longname});
        if (myModules.length) {
            generate('Module', myModules[0].name, myModules, helper.longnameToUrl[longname]);
        }

        var myClasses = helper.find(classes, {longname: longname});
        if (myClasses.length) {
            generate('Class', myClasses[0].name, myClasses, helper.longnameToUrl[longname]);
        }

        var myNamespaces = helper.find(namespaces, {longname: longname});
        if (myNamespaces.length) {
            generate('Namespace', myNamespaces[0].name, myNamespaces, helper.longnameToUrl[longname]);
        }

        var myMixins = helper.find(mixins, {longname: longname});
        if (myMixins.length) {
            generate('Mixin', myMixins[0].name, myMixins, helper.longnameToUrl[longname]);
        }

        var myExternals = helper.find(externals, {longname: longname});
        if (myExternals.length) {
            generate('External', myExternals[0].name, myExternals, helper.longnameToUrl[longname]);
        }

        var myInterfaces = helper.find(interfaces, {longname: longname});
        if (myInterfaces.length) {
            generate('Interface', myInterfaces[0].name, myInterfaces, helper.longnameToUrl[longname]);
        }
    });

    // TODO: move the tutorial functions to templateHelper.js
    function generateTutorial(title, tutorial, filename) {
        var tutorialData = {
            title: title,
            header: tutorial.title,
            content: tutorial.parse(),
            children: tutorial.children
        };

        var tutorialPath = path.join(outdir, filename);
        var html = view.render('tutorial.tmpl', tutorialData);

        // yes, you can use {@link} in tutorials too!
        html = helper.resolveLinks(html); // turn {@link foo} into <a href="foodoc.html">foo</a>
        fs.writeFileSync(tutorialPath, html, 'utf8');
    }

    // tutorials can have only one parent so there is no risk for loops
    function saveChildren(node) {
        node.children.forEach(function(child) {
            generateTutorial('Tutorial: ' + child.title, child, helper.tutorialToUrl(child.name));
            saveChildren(child);
        });
    }

    saveChildren(tutorials);
};
Пример #17
0
exports.publish = function(taffyData, opts, tutorials) {
  data = taffyData;

  conf['default'] = conf['default'] || {};

  var templatePath = opts.template;
  view = new template.Template(templatePath + '/tmpl');

  // claim some special filenames in advance, so the All-Powerful Overseer of Filename Uniqueness
  // doesn't try to hand them out later
  //	var indexUrl = helper.getUniqueFilename( 'index' );
  // don't call registerLink() on this one! 'index' is also a valid longname

  //	var globalUrl = helper.getUniqueFilename( 'global' );
  helper.registerLink('global', globalUrl);

  // set up templating
  // set up templating
  view.layout = conf['default'].layoutFile ?
    path.getResourcePath(path.dirname(conf['default'].layoutFile),
    path.basename(conf['default'].layoutFile) ) : 'layout.tmpl';

  // set up tutorials for helper
  helper.setTutorials(tutorials);

  data = helper.prune(data);

  var sortOption = navOptions.sort === undefined ? opts.sort : navOptions.sort;
  sortOption = sortOption === undefined ? true : sortOption;
  sortOption = sortOption === true ? 'longname, version, since' : sortOption;
  if (sortOption) {
    data.sort(sortOption);
  }
  helper.addEventListeners(data);

  var sourceFiles = {};
  var sourceFilePaths = [];
  data().each(function(doclet) {
    doclet.attribs = '';

    if (doclet.examples) {
      doclet.examples = doclet.examples.map(function(example) {
        var caption, lang;

        // allow using a markdown parser on the examples captions (surrounded by useless HTML p tags)
        if (example.match(/^\s*(<p>)?<caption>([\s\S]+?)<\/caption>(\s*)([\s\S]+?)(<\/p>)?$/i)) {
          caption = RegExp.$2;
          example = RegExp.$4 + (RegExp.$1 ? '' : RegExp.$5);
        }

        var lang = /{@lang (.*?)}/.exec(example);

        if (lang && lang[1]) {
          example = example.replace(lang[0], "");
          lang = lang[1];

        } else {
          lang = null;
        }

        return {
          caption: caption || '',
          code: example,
          lang: lang || "javascript"
        };
      });
    }
    if (doclet.see) {
      doclet.see.forEach(function(seeItem, i) {
        doclet.see[i] = hashToLink(doclet, seeItem);
      });
    }

    // build a list of source files
    var sourcePath;
    if (doclet.meta) {
      sourcePath = getPathFromDoclet(doclet);
      sourceFiles[sourcePath] = {
        resolved: sourcePath,
        shortened: null
      };

      //Check to see if the array of source file paths already contains
      // the source path, if not then add it
      if (sourceFilePaths.indexOf(sourcePath) === -1) {
          sourceFilePaths.push(sourcePath)
      }
    }
  });

  // update outdir if necessary, then create outdir
  var packageInfo = (find({
    kind: 'package'
  }) || [])[0];
  if (navOptions.disablePackagePath !== true && packageInfo && packageInfo.name) {
    if (packageInfo.version) {
      outdir = path.join(outdir, packageInfo.name, packageInfo.version);
    } else {
      outdir = path.join(outdir, packageInfo.name);
    }
  }
  fs.mkPath(outdir);

	// copy the template's static files to outdir
	var fromDir = path.join( templatePath, 'static' );
	var staticFiles = fs.ls( fromDir, 3 );

	staticFiles.forEach( function ( fileName ) {
		var toDir = fs.toDir( fileName.replace( fromDir, outdir ) );
		fs.mkPath( toDir );
		fs.copyFileSync( fileName, toDir );
	} );

    // copy user-specified static files to outdir
    var staticFilePaths;
    var staticFileFilter;
    var staticFileScanner;
    if (conf.default.staticFiles) {
        // The canonical property name is `include`. We accept `paths` for backwards compatibility
        // with a bug in JSDoc 3.2.x.
        staticFilePaths = conf.default.staticFiles.include ||
            conf.default.staticFiles.paths ||
            [];
        staticFileFilter = new (require('jsdoc/src/filter')).Filter(conf.default.staticFiles);
        staticFileScanner = new (require('jsdoc/src/scanner')).Scanner();

        staticFilePaths.forEach(function(filePath) {
            var extraStaticFiles = staticFileScanner.scan([filePath], 10, staticFileFilter);

            extraStaticFiles.forEach(function(fileName) {
                var sourcePath = fs.toDir(filePath);
                var toDir = fs.toDir( fileName.replace(sourcePath, outdir) );
                fs.mkPath(toDir);
                fs.copyFileSync(fileName, toDir);
            });
        });
    }

  if (sourceFilePaths.length) {
    var payload = navOptions.sourceRootPath;
    if (!payload) {
      payload = path.commonPrefix(sourceFilePaths);
    }
    sourceFiles = shortenPaths(sourceFiles, payload);
  }
  data().each(function(doclet) {
    var url = helper.createLink(doclet);
    helper.registerLink(doclet.longname, url);

    // add a shortened version of the full path
    var docletPath;
    if (doclet.meta) {
      docletPath = getPathFromDoclet(doclet);
      if (!_.isEmpty(sourceFiles[docletPath])) {
        docletPath = sourceFiles[docletPath].shortened;
        if (docletPath) {
          doclet.meta.shortpath = docletPath;
        }
      }
    }
  });

  data().each(function(doclet) {
    var url = helper.longnameToUrl[doclet.longname];

    if (url.indexOf('#') > -1) {
      doclet.id = helper.longnameToUrl[doclet.longname].split(/#/).pop();
    } else {
      doclet.id = doclet.name;
    }

    if (needsSignature(doclet)) {
      addSignatureParams(doclet);
      addSignatureReturns(doclet);
      addAttribs(doclet);
    }
  });

  // do this after the urls have all been generated
  data().each(function(doclet) {
    doclet.ancestors = getAncestorLinks(doclet);

    if (doclet.kind === 'member') {
      addSignatureTypes(doclet);
      addAttribs(doclet);
    }

    if (doclet.kind === 'constant') {
      addSignatureTypes(doclet);
      addAttribs(doclet);
      doclet.kind = 'member';
    }
  });

  var members = helper.getMembers(data);
  members.tutorials = tutorials.children;

  // add template helpers
  view.find = find;
  view.linkto = linkto;
  view.resolveAuthorLinks = resolveAuthorLinks;
  view.tutoriallink = tutoriallink;
  view.htmlsafe = htmlsafe;
  view.moment = moment;

  // once for all
  buildNav(members);
  view.nav = navigationMaster;
  view.navOptions = navOptions;
  attachModuleSymbols(find({
      kind: ['class', 'function'],
      longname: {
        left: 'module:'
      }
    }),
    members.modules);

  // only output pretty-printed source files if requested; do this before generating any other
  // pages, so the other pages can link to the source files
  if (navOptions.outputSourceFiles) {
    generateSourceFiles(sourceFiles);
  }

  if (members.globals.length) {
    generate('global', 'Global', [{
      kind: 'globalobj'
    }], globalUrl);
  }

  // some browsers can't make the dropdown work
  if (view.nav.module && view.nav.module.members.length) {
    generate('module', view.nav.module.title, [{
      kind: 'sectionIndex',
      contents: view.nav.module
    }], navigationMaster.module.link);
  }

  if (view.nav.class && view.nav.class.members.length) {
    generate('class', view.nav.class.title, [{
      kind: 'sectionIndex',
      contents: view.nav.class
    }], navigationMaster.class.link);
  }

  if (view.nav.namespace && view.nav.namespace.members.length) {
    generate('namespace', view.nav.namespace.title, [{
      kind: 'sectionIndex',
      contents: view.nav.namespace
    }], navigationMaster.namespace.link);
  }

  if (view.nav.mixin && view.nav.mixin.members.length) {
    generate('mixin', view.nav.mixin.title, [{
      kind: 'sectionIndex',
      contents: view.nav.mixin
    }], navigationMaster.mixin.link);
  }

  if (view.nav.interface && view.nav.interface.members.length) {
    generate('interface', view.nav.interface.title, [{
      kind: 'sectionIndex',
      contents: view.nav.interface
    }], navigationMaster.interface.link);
  }

  if (view.nav.external && view.nav.external.members.length) {
    generate('external', view.nav.external.title, [{
      kind: 'sectionIndex',
      contents: view.nav.external
    }], navigationMaster.external.link);
  }

  if (view.nav.tutorial && view.nav.tutorial.members.length) {
    generate('tutorial', view.nav.tutorial.title, [{
      kind: 'sectionIndex',
      contents: view.nav.tutorial
    }], navigationMaster.tutorial.link);
  }

  // index page displays information from package.json and lists files
  var files = find({
      kind: 'file'
    }),
    packages = find({
      kind: 'package'
    });

  generate('index', 'Index',
    packages.concat(
      [{
        kind: 'mainpage',
        readme: opts.readme,
        longname: (opts.mainpagetitle) ? opts.mainpagetitle : 'Main Page'
      }]
    ).concat(files),
    indexUrl);

  // set up the lists that we'll use to generate pages
  var classes = taffy(members.classes);
  var modules = taffy(members.modules);
  var namespaces = taffy(members.namespaces);
  var mixins = taffy(members.mixins);
  var interfaces = taffy(members.interfaces);
  var externals = taffy(members.externals);

  for (var longname in helper.longnameToUrl) {
    if (hasOwnProp.call(helper.longnameToUrl, longname)) {
      var myClasses = helper.find(classes, {
        longname: longname
      });
      if (myClasses.length) {
        generate('class', 'Class: ' + myClasses[0].name, myClasses, helper.longnameToUrl[longname]);
      }

      var myModules = helper.find(modules, {
        longname: longname
      });
      if (myModules.length) {
        generate('module', 'Module: ' + myModules[0].name, myModules, helper.longnameToUrl[longname]);
      }

      var myNamespaces = helper.find(namespaces, {
        longname: longname
      });
      if (myNamespaces.length) {
        generate('namespace', 'Namespace: ' + myNamespaces[0].name, myNamespaces, helper.longnameToUrl[longname]);
      }

      var myMixins = helper.find(mixins, {
        longname: longname
      });
      if (myMixins.length) {
        generate('mixin', 'Mixin: ' + myMixins[0].name, myMixins, helper.longnameToUrl[longname]);
      }

      var myInterfaces = helper.find(interfaces, {
        longname: longname
      });
      if (myInterfaces.length) {
        generate('interface', 'Interface: ' + myInterfaces[0].name, myInterfaces, helper.longnameToUrl[longname]);
      }

      var myExternals = helper.find(externals, {
        longname: longname
      });
      if (myExternals.length) {
        generate('external', 'External: ' + myExternals[0].name, myExternals, helper.longnameToUrl[longname]);
      }
    }
  }

  // TODO: move the tutorial functions to templateHelper.js
  function generateTutorial(title, tutorial, filename) {
    var tutorialData = {
      title: title,
      header: tutorial.title,
      content: tutorial.parse(),
      children: tutorial.children,
      docs: null
    };

    var tutorialPath = path.join(outdir, filename),
      html = view.render('tutorial.tmpl', tutorialData);

    // yes, you can use {@link} in tutorials too!
    html = helper.resolveLinks(html); // turn {@link foo} into <a href="foodoc.html">foo</a>

    searchableDocuments[filename] = {
      "id": filename,
      "title": title,
      "body": searchData(html)
    };

    fs.writeFileSync(tutorialPath, html, 'utf8');
  }

  // tutorials can have only one parent so there is no risk for loops
  function saveChildren(node) {
    node.children.forEach(function(child) {
      generateTutorial('Tutorial: ' + child.title, child, helper.tutorialToUrl(child.name));
      saveChildren(child);
    });
  }

  function generateQuickTextSearch(templatePath, searchableDocuments, navOptions) {
      var data = {
          searchableDocuments: JSON.stringify(searchableDocuments),
          navOptions: navOptions
      };

      var tmplString = fs.readFileSync(templatePath + "/quicksearch.tmpl").toString(),
            tmpl = _.template(tmplString);

      var html = tmpl(data),
            outpath = path.join(outdir, "quicksearch.html");

      fs.writeFileSync(outpath, html, "utf8");
  }

  saveChildren(tutorials);
  generateQuickTextSearch(templatePath + '/tmpl', searchableDocuments, navOptions);
};
Пример #18
0
    publish = function(data, opts, tutorials) {

        // The 'product' variable is specified on the command line, and it used to customize output for Montage and Screening.
        // for example:
        // jsdoc -t templates/tetsubo --query product=montage -r ../montage/ui ../montage/core
        var product;
        if(opts.query) {
            product = opts.query.product;
            if ((product === "montage") || (product === "screening")) {
                console.log("\tBuilding docs for: " + product);
            } else {
                console.log("\tInvalid product specified '" + product + "'.");
                return;
            }
        } else {
            console.log("\n\tNo product specified in --query parameter. Example usage: ");
            console.log("\t./jsdoc -t templates/unity -q product=montage -r ../montage/core ../montage/ui ../montage/data");
            return;
        }

        var out = '',
            view = new template.Template(__dirname + '/templates/unity/tmpl');

        // set up templating
        view.layout = product + '-layout.tmpl';

        // set up tutorials for helper
        helper.setTutorials(tutorials);

        function find(spec) {
            return data.get( data.find(spec) );
        }

        function htmlsafe(str) {
            return str.replace(/</g, '&lt;');
        }

        function addSignatureParams(f) {
            var pnames = [];
            if (f.params) {
                f.params.forEach(function(p) {
                    if (p.name && p.name.indexOf('.') === -1) {
                        if (p.optional) { pnames.push('<span class="optional">'+p.name+'</span>'); }
                        else { pnames.push(p.name); }
                    }
                });
            }

            f.signature = (f.signature || '') + '('+pnames.join(', ')+')';
        }

        function generateAncestry(thisdoc) {
            var ancestors = [],
                doc = thisdoc;

            while (doc = doc.memberof) {
                doc = find({longname: doc});
                if (doc) { doc = doc[0]; }
                if (!doc) break;
                ancestors.unshift( linkto(doc.longname, (scopeToPunc[doc.scope] || '') + doc.name) );
            }
            if (ancestors.length) {
                ancestors[ancestors.length-1] += (scopeToPunc[thisdoc.scope] || '');
            }
            return ancestors;
        }

        function addSignatureReturns(f) {
            var returnTypes = [];

            if (f.returns) {
                f.returns.forEach(function(r) {
                    if (r.type && r.type.names) {
                        if (! returnTypes.length) { returnTypes = r.type.names; }
                    }
                });
            }

            if (returnTypes && returnTypes.length) {
                returnTypes = returnTypes.map(function(r) {
                    return linkto(r);
                });
            }
            f.signature = '<span class="signature">'+(f.signature || '') + '</span>' + '<span class="type-signature">'+(returnTypes.length? ' &rarr; {'+returnTypes.join('|')+'}' : '')+'</span>';
        }

        function addSignatureType(f) {
            var types = [];

            if (f.type && f.type.names) {
                types = f.type.names;
            }

            if (types && types.length) {
                types = types.map(function(t) {
                    return linkto(t, htmlsafe(t));
                });
            }

            f.signature = (f.signature || '') + '<span class="type-signature">'+(types.length? ' :'+types.join('|') : '')+'</span>';
        }

        function removeQuotesFromReelModule(module) {
            var moduleName = module.name;
            if(moduleName.indexOf(".reel\"") !== -1) {
                moduleName = moduleName.replace(".reel\"", ".reel");
                moduleName = moduleName.replace("\"", "");
            }
            module.name = moduleName;
        }

        function addAttribs(f) {
            var attribs = [];

            if (f.virtual) {
                attribs.push('virtual');
            }

            if (f.access && f.access !== 'public') {
                attribs.push(f.access);
            }

            if (f.scope && f.scope !== 'instance' && f.scope !== 'global') {
                if (f.kind == 'function' || f.kind == 'member' || f.kind == 'constant') attribs.push(f.scope);
            }

            if (f.readonly === true) {
                if (f.kind == 'member') attribs.push('readonly');
            }

            if (f.kind === 'constant') {
                attribs.push('constant');
                f.kind = 'member';
            }

            f.attribs = '<span class="type-signature">'+htmlsafe(attribs.length? '<'+attribs.join(', ')+'> ' : '')+'</span>';
        }

        data.remove({undocumented: true});
        data.remove({ignore: true});
        if (!opts.private) { data.remove({access: 'private'}); }
        data.remove({memberof: '<anonymous>'});

	    var packageInfo = (find({kind: 'package'}) || []) [0];

        //function renderLinks(text) {
        //    return helper.resolveLinks(text);
        //}

	    data.forEach(function(doclet) {
             doclet.attribs = '';


	        if (doclet.examples) {
	            doclet.examples = doclet.examples.map(function(example) {
	                var caption, code;

	                if (example.match(/^\s*<caption>([\s\S]+?)<\/caption>(\s*[\n\r])([\s\S]+)$/i)) {
	                    caption = RegExp.$1;
	                    code    = RegExp.$3;
	                }

                    return {
                        caption: caption || '',
                        code: code || example
                    };
                });
	        }
	        if (doclet.see) {
	            doclet.see.forEach(function(seeItem, i) {
	                doclet.see[i] = hashToLink(doclet, seeItem);
	            });
	        }

           if (doclet.kind === 'module') {
                removeQuotesFromReelModule(doclet);
            }
        });


	    data.orderBy(['longname', 'version', 'since']);

        // kinds of containers
        var globals = find( {kind: ['member', 'function', 'constant', 'typedef'], memberof: {isUndefined: true}} ),
            modules = find({kind: 'module'}),
            externals = find({kind: 'external'}),
            mixins = find({kind: 'mixin'}),
	        namespaces = find({kind: 'namespace'});

        var outdir = opts.destination;
        if (packageInfo && packageInfo.name) {
            outdir += '/' + packageInfo.name + '/' + packageInfo.version + '/';
        }
        fs.mkPath(outdir);

        // copy product-specific static files to outdir
        var fromDir = __dirname + '/templates/unity/static/' + product + '/styles',
            staticFiles = fs.ls(fromDir, 3);


        staticFiles.forEach(function(fileName) {
            var toDir = fs.toDir(fileName.replace(fromDir, outdir));
            fs.mkPath(toDir);
            fs.copyFile(fileName, toDir);
        });


        function linkto(longname, linktext) {
            var url = helper.longnameToUrl[longname];
            return url? '<a class="prototype" href="'+url+'">'+(linktext || longname)+'</a>' : (linktext || longname);
        }

        function tutoriallink(tutorial) {
            return helper.toTutorial(tutorial);
        }

        var containers = ['class', 'module', 'external', 'namespace', 'mixin'];

        data.forEach(function(doclet) {
            var url = helper.createLink(doclet);
            helper.registerLink(doclet.longname, url);
        });

        data.forEach(function(doclet) {
            var url = helper.longnameToUrl[doclet.longname];

	        if (url.indexOf('#') > -1) {
	            doclet.id = helper.longnameToUrl[doclet.longname].split(/#/).pop();
	        }
	        else {
	            doclet.id = doclet.name;
	        }

	        if (doclet.kind === 'function' || doclet.kind === 'class') {
	            addSignatureParams(doclet);
	            addSignatureReturns(doclet);
	            addAttribs(doclet);
	        }
	    })

        // do this after the urls have all been generated
        data.forEach(function(doclet) {
            doclet.ancestors = generateAncestry(doclet);

            doclet.signature = '';

	        if (doclet.kind === 'member') {
	            addSignatureType(doclet);
	            addAttribs(doclet)
	        }

	        if (doclet.kind === 'constant') {
	            addSignatureType(doclet);
	            addAttribs(doclet)
	        }
        });

        var nav = '',
            seen = {};


        var classNames = find({kind: 'class'});
        if (classNames.length) {
            classNames.sort(alphabetical);
            nav += '<h3>Prototypes</h3>';
            nav += '<div id="class-list">';
            nav += '<input id="search" class="search" placeholder="Filter by name" /><ul class=\"list\">';
            classNames.forEach(function(c) {
                var moduleSameName = find({kind: 'module', longname: c.longname});
                if (moduleSameName.length) {
                    c.name = c.name.replace('module:', 'require(')+')';
                    moduleSameName[0].module = c;
                }

                if (!seen.hasOwnProperty(c.longname) ) nav += '<li>'+linkto(c.longname, c.name)+'</li>';
                seen[c.longname] = true;
            });

            nav += '</ul></div>';
        }

        var externalNames = find({kind: 'external'});
        if (externalNames.length) {
            nav = nav + '<h3>Externals</h3>';
            nav += '<div id="externals-list">';
            externalNames.sort(alphabetical);
            nav += '<input id="search" class="search" placeholder="Filter by name" /><ul class=\"list\">';
            externalNames.forEach(function(e) {
                if ( !seen.hasOwnProperty(e.longname) ) nav += '<li>'+linkto( e.longname, e.name.replace(/(^"|"$)/g, '') )+'</li>';
                seen[e.longname] = true;
            });
            nav += '</ul>';
            nav += '</div>';
        }

        var moduleNames = find({kind: 'module'});
        if (moduleNames.length) {
            nav += '<h3>Modules</h3>';
            nav += '<div id="modules-list">';
            moduleNames.sort(alphabetical);
            nav += '<input id="search" class="search" placeholder="Filter by name" /><ul class=\"list\">';            
            moduleNames.forEach(function(m) {
                if ( !seen.hasOwnProperty(m.longname) ) nav += '<li>'+linkto(m.longname, m.name)+'</li>';
                seen[m.longname] = true;
            });

            nav += '</ul>';
            nav += '</div>';
        }


        var namespaceNames = find({kind: 'namespace'});
        if (namespaceNames.length) {
            nav += '<h3>Namespaces</h3>';
            nav += '<ul class=\"list\">';
            namespaceNames.forEach(function(n) {
                if ( !seen.hasOwnProperty(n.longname) ) nav += '<li>'+linkto(n.longname, n.name)+'</li>';
                seen[n.longname] = true;
            });

            nav += '</ul>';
        }

//         var constantNames = find({kind: 'constants'});
//         if (constantNames.length) {
//             nav += '<h3>Constants</h3><ul>';
//             constantNames.forEach(function(c) {
//                 if ( !seen.hasOwnProperty(c.longname) ) nav += '<li>'+linkto(c.longname, c.name)+'</li>';
//                 seen[c.longname] = true;
//             });
//
//             nav += '</ul>';
//         }

        var mixinNames = find({kind: 'mixin'});
        if (mixinNames.length) {
            nav += '<h3>Mixins</h3><ul>';
            mixinNames.forEach(function(m) {
                if ( !seen.hasOwnProperty(m.longname) ) nav += '<li>'+linkto(m.longname, m.name)+'</li>';
                seen[m.longname] = true;
            });

            nav += '</ul>';
        }

        if (tutorials.children.length) {
            nav += '<h3>Tutorials</h3><ul>';
            tutorials.children.forEach(function(t) {
                nav += '<li>'+tutoriallink(t.name)+'</li>';
            });

            nav += '</ul>';
        }

        var globalNames = find({kind: ['member', 'function', 'constant', 'typedef'], 'memberof': {'isUndefined': true}});

        if (globalNames.length) {
            nav = nav + '<h3>Globals</h3>';
            nav += '<div id="globals-list">';
            nav += '<input id="search" class="search" placeholder="Filter by name" /><ul class=\"list\">';

            globalNames.forEach(function(g) {
                if ( g.kind !== 'typedef' && !seen.hasOwnProperty(g.longname) ) nav += '<li>'+linkto(g.longname, g.name)+'</li>';
                seen[g.longname] = true;
            });

            nav += '</ul>';
            nav += '</div>';
        }


        // add template helpers
        view.find = find;
        view.linkto = linkto;
        view.tutoriallink = tutoriallink;
        view.htmlsafe = htmlsafe;
        // once for all
        view.nav = nav;

        for (var longname in helper.longnameToUrl) {
            var classes = find({kind: 'class', longname: longname});
            if (classes.length) generate('Prototype: '+classes[0].name, classes, helper.longnameToUrl[longname]);

            var modules = find({kind: 'module', longname: longname});
            if (modules.length) generate('Module: '+modules[0].name, modules, helper.longnameToUrl[longname]);

            var namespaces = find({kind: 'namespace', longname: longname});
            if (namespaces.length) generate('Namespace: '+namespaces[0].name, namespaces, helper.longnameToUrl[longname]);

//             var constants = find({kind: 'constant', longname: longname});
//             if (constants.length) generate('Constant: '+constants[0].name, constants, helper.longnameToUrl[longname]);

            var mixins = find({kind: 'mixin', longname: longname});
            if (mixins.length) generate('Mixin: '+mixins[0].name, mixins, helper.longnameToUrl[longname]);

            var externals = find({kind: 'external', longname: longname});
            if (externals.length) generate('External: '+externals[0].name, externals, helper.longnameToUrl[longname]);
        }

        if (globals.length) generate('Global', [{kind: 'globalobj'}], 'global.html');

        generateIndex('Index', 'index.html');


        function generate(title, docs, filename) {
            var data = {
                title: title,
                docs: docs
            };

            var path = outdir + '/' + filename,
                html = view.render('container.tmpl', data);

            html = helper.resolveLinks(html); // turn {@link foo} into <a href="foodoc.html">foo</a>

            fs.writeFileSync(path, html)
        }

        function generateIndex(title, filename) {
            var classes = find({kind: 'class', longname: longname});

            var data = {
                title: title,
                docs: classes
            };

            var path = outdir + '/' + filename,
                html = view.render(product + '-index.tmpl', data);

            html = helper.resolveLinks(html); // turn {@link foo} into <a href="foodoc.html">foo</a>

            fs.writeFileSync(path, html)
        }

        function generateTutorial(title, tutorial, filename) {
            var data = {
                title: title,
                header: tutorial.title,
                content: tutorial.parse(),
                children: tutorial.children
            };

            var path = outdir + '/' + filename,
                html = view.render('tutorial.tmpl', data);

            // yes, you can use {@link} in tutorials too!
            html = helper.resolveLinks(html); // turn {@link foo} into <a href="foodoc.html">foo</a>

            fs.writeFileSync(path, html)
        }

        // tutorials can have only one parent so there is no risk for loops
        function saveChildren(node) {
            node.children.forEach(function(child) {
                generateTutorial('Tutorial: '+child.title, child, helper.tutorialToUrl(child.name));
                saveChildren(child);
            });
        }
        saveChildren(tutorials);
    }
Пример #19
0
exports.publish = function(taffyData, opts, tutorials) {
    data = taffyData;

    var conf = env.conf.templates || {};
    conf['default'] = conf['default'] || {};

    var templatePath = opts.template;
    view = new template.Template(templatePath + '/tmpl');

    // claim some special filenames in advance, so the All-Powerful Overseer of Filename Uniqueness
    // doesn't try to hand them out later
    var indexUrl = helper.getUniqueFilename('index');
    // don't call registerLink() on this one! 'index' is also a valid longname

    var globalUrl = helper.getUniqueFilename('global');
    helper.registerLink('global', globalUrl);

    // set up templating
    view.layout = conf['default'].layoutFile ?
        path.getResourcePath(path.dirname(conf['default'].layoutFile),
            path.basename(conf['default'].layoutFile) ) :
        'layout.tmpl';

    // set up tutorials for helper
    helper.setTutorials(tutorials);

    data = helper.prune(data);
    data.sort('longname, version, since');
    helper.addEventListeners(data);

    var sourceFiles = {};
    var sourceFilePaths = [];
    data().each(function(doclet) {

        doclet.attribs = '';

        switch(doclet.ngdoc) {
          case "provider":
            doclet.kind = "class";
            break;
          case "service":
            doclet.kind = "class";
            break;
          case "type":
            doclet.kind = "typedef";
            break;
          case "property":
            doclet.kind = "member";
            break;
          case "event":
            doclet.kind = "function";
            break;
        }

        if (doclet.ngdoc == "provider" || doclet.ngdoc == "service") {
          doclet.kind = "class";
        }

        if (doclet.examples) {
            doclet.examples = doclet.examples.map(function(example) {
                var caption, code;

                if (example.match(/^\s*<caption>([\s\S]+?)<\/caption>(\s*[\n\r])([\s\S]+)$/i)) {
                    caption = RegExp.$1;
                    code    = RegExp.$3;
                }

                return {
                    caption: caption || '',
                    code: code || example
                };
            });
        }
        if (doclet.see) {
            doclet.see.forEach(function(seeItem, i) {
                doclet.see[i] = hashToLink(doclet, seeItem);
            });
        }

        // build a list of source files
        var sourcePath;
        var resolvedSourcePath;
        if (doclet.meta) {
            sourcePath = getPathFromDoclet(doclet);
            resolvedSourcePath = resolveSourcePath(sourcePath);
            sourceFiles[sourcePath] = {
                resolved: resolvedSourcePath,
                shortened: null
            };
            sourceFilePaths.push(resolvedSourcePath);
        }
    });

    // update outdir if necessary, then create outdir
    var packageInfo = ( find({kind: 'package'}) || [] ) [0];
    if (packageInfo && packageInfo.name) {
        outdir = path.join(outdir, packageInfo.name, packageInfo.version);
    }
    fs.mkPath(outdir);

    // copy the template's static files to outdir
    var fromDir = path.join(templatePath, 'static'),
        staticFiles = fs.ls(fromDir, 3);

    staticFiles.forEach(function(fileName) {
        var toDir = fs.toDir( fileName.replace(fromDir, outdir) );
        fs.mkPath(toDir);
        fs.copyFileSync(fileName, toDir);
    });

    // copy user-specified static files to outdir
    var staticFilePaths;
    var staticFileFilter;
    var staticFileScanner;
    if (conf['default'].staticFiles) {
        staticFilePaths = conf['default'].staticFiles.paths || [];
        staticFileFilter = new (require('jsdoc/src/filter')).Filter(conf['default'].staticFiles);
        staticFileScanner = new (require('jsdoc/src/scanner')).Scanner();

        staticFilePaths.forEach(function(filePath) {
            var extraStaticFiles = staticFileScanner.scan([filePath], 10, staticFileFilter);

            extraStaticFiles.forEach(function(fileName) {
                var sourcePath = fs.toDir(filePath);
                var toDir = fs.toDir( fileName.replace(sourcePath, outdir) );
                fs.mkPath(toDir);
                fs.copyFileSync(fileName, toDir);
            });
        });
    }
    if (sourceFilePaths.length) {
        sourceFiles = shortenPaths( sourceFiles, path.commonPrefix(sourceFilePaths) );
    }
    data().each(function(doclet) {
        var url = helper.createLink(doclet);
        helper.registerLink(doclet.longname, url);

        // replace the filename with a shortened version of the full path
        var docletPath;
        if (doclet.meta) {
            docletPath = getPathFromDoclet(doclet);
            docletPath = sourceFiles[docletPath].shortened;
            if (docletPath) {
                doclet.meta.filename = docletPath;
            }
        }
    });

    data().each(function(doclet) {
        var url = helper.longnameToUrl[doclet.longname];

        if (url.indexOf('#') > -1) {
            doclet.id = helper.longnameToUrl[doclet.longname].split(/#/).pop();
        }
        else {
            doclet.id = doclet.name;
        }

        if ( needsSignature(doclet) ) {
            addSignatureParams(doclet);
            addSignatureReturns(doclet);
            addAttribs(doclet);
        }
    });

    // do this after the urls have all been generated
    data().each(function(doclet) {
        doclet.ancestors = getAncestorLinks(doclet);

        if (doclet.kind === 'member') {
            addSignatureTypes(doclet);
            addAttribs(doclet);
        }

        if (doclet.kind === 'constant') {
            addSignatureTypes(doclet);
            addAttribs(doclet);
            doclet.kind = 'member';
        }
    });

    var members = helper.getMembers(data);
    members.tutorials = tutorials.children;
    // add template helpers
    view.find = find;
    view.linkto = linkto;
    view.resolveAuthorLinks = resolveAuthorLinks;
    view.tutoriallink = tutoriallink;
    view.htmlsafe = htmlsafe;
    //grimbo: pass the conf to the template.
    view.outputSourceReference = (true === conf['default'].outputSourceReference);

    // once for all
    view.nav = buildNav(members);
    attachModuleSymbols( find({ kind: ['class', 'function'], longname: {left: 'module:'} }),
        members.modules );

    // only output pretty-printed source files if requested; do this before generating any other
    // pages, so the other pages can link to the source files
    if (conf['default'].outputSourceFiles) {
        generateSourceFiles(sourceFiles);
    }

    if (members.globals.length) { generate('Global', [{kind: 'globalobj'}], globalUrl); }

    // index page displays information from package.json and lists files
    var files = find({kind: 'file'}),
        packages = find({kind: 'package'});

    generate('Index',
        packages.concat(
            [{kind: 'mainpage', readme: opts.readme, longname: (opts.mainpagetitle) ? opts.mainpagetitle : 'Main Page'}]
        ).concat(files),
    indexUrl);

    // set up the lists that we'll use to generate pages
    var classes = taffy(members.classes);
    var modules = taffy(members.modules);
    var namespaces = taffy(members.namespaces);
    var mixins = taffy(members.mixins);
    var externals = taffy(members.externals);

    for (var longname in helper.longnameToUrl) {
        if ( hasOwnProp.call(helper.longnameToUrl, longname) ) {
            var myClasses = helper.find(classes, {longname: longname});
            if (myClasses.length) {
                var titlePrefix = myClasses[0].ngdoc ? myClasses[0].ngdoc : 'Class';

                var iconPrefix = '';
                switch (titlePrefix.toLowerCase()) {
                    case "class":
                    case "provider":
                    case "service":
                        iconPrefix = '<i class="icon-shield" style="color:#0186d1"></i> ';
                        break;
                    case "directive":
                        iconPrefix = '<i class="icon-archive"></i> ';
                        break;
                    case "type":
                        iconPrefix = '<i class="icon-key"></i> ';
                        break;
                    case "property":
                        iconPrefix = '<i class="icon-maxcdn"></i> ';
                        break;
                    case "module":
                    case "modules":
                        iconPrefix = '<i class="icon-puzzle-piece"></i> ';
                        break;
                    case "event":
                        iconPrefix = '<i class="icon-cogs"></i> ';
                        break;
                }

                generate(iconPrefix + titlePrefix + ': ' + myClasses[0].name, myClasses, helper.longnameToUrl[longname]);
            }

            var myModules = helper.find(modules, {longname: longname});
            if (myModules.length) {
                generate('<i class="icon-puzzle-piece"></i> ' + 'Module: ' + myModules[0].name, myModules, helper.longnameToUrl[longname]);
            }

            var myNamespaces = helper.find(namespaces, {longname: longname});
            if (myNamespaces.length) {
                generate('<i class="icon-code"></i> ' + 'Namespace: ' +  myNamespaces[0].name, myNamespaces, helper.longnameToUrl[longname]);
            }

            var myMixins = helper.find(mixins, {longname: longname});
            if (myMixins.length) {
                generate('<i class="icon-beaker"></i> ' + 'Mixin: ' +  myMixins[0].name, myMixins, helper.longnameToUrl[longname]);
            }

            var myExternals = helper.find(externals, {longname: longname});
            if (myExternals.length) {
                generate('External: ' + myExternals[0].name, myExternals, helper.longnameToUrl[longname]);
            }
        }
    }

    // TODO: move the tutorial functions to templateHelper.js
    function generateTutorial(title, tutorial, filename) {
        var tutorialData = {
            title: title,
            header: tutorial.title,
            content: tutorial.parse(),
            children: tutorial.children
        };

        var tutorialPath = path.join(outdir, filename),
            html = view.render('tutorial.tmpl', tutorialData);

        // yes, you can use {@link} in tutorials too!
        html = helper.resolveLinks(html); // turn {@link foo} into <a href="foodoc.html">foo</a>

        fs.writeFileSync(tutorialPath, html, 'utf8');
    }

    // tutorials can have only one parent so there is no risk for loops
    function saveChildren(node) {
        node.children.forEach(function(child) {
            generateTutorial('Tutorial: ' + child.title, child, helper.tutorialToUrl(child.name));
            saveChildren(child);
        });
    }
    saveChildren(tutorials);
};
Пример #20
0
exports.publish = function(taffyData, opts, tutorials) {
    data = taffyData;

    var conf = env.conf.templates || {};
    conf['default'] = conf['default'] || {};

    var templatePath = opts.template;
    view = new template.Template(templatePath + '/tmpl');
    
    // claim some special filenames in advance, so the All-Powerful Overseer of Filename Uniqueness
    // doesn't try to hand them out later
    var indexUrl = helper.getUniqueFilename('index');
    // don't call registerLink() on this one! 'index' is also a valid longname

    var globalUrl = helper.getUniqueFilename('global');
    helper.registerLink('global', globalUrl);

    // set up templating
    view.layout = 'layout.tmpl';

    // set up tutorials for helper
    helper.setTutorials(tutorials);

    data = helper.prune(data);
    data.sort('longname, version, since');
    helper.addEventListeners(data);

    var sourceFiles = {};
    var sourceFilePaths = [];
    data().each(function(doclet) {
         doclet.attribs = '';
        
        if (doclet.examples) {
            doclet.examples = doclet.examples.map(function(example) {
                var caption, code;
                
                if (example.match(/^\s*<caption>([\s\S]+?)<\/caption>(\s*[\n\r])([\s\S]+)$/i)) {
                    caption = RegExp.$1;
                    code    = RegExp.$3;
                }
                
                return {
                    caption: caption || '',
                    code: code || example
                };
            });
        }
        if (doclet.see) {
            doclet.see.forEach(function(seeItem, i) {
                doclet.see[i] = hashToLink(doclet, seeItem);
            });
        }

        // build a list of source files
        var sourcePath;
        var resolvedSourcePath;
        if (doclet.meta) {
            sourcePath = getPathFromDoclet(doclet);
            resolvedSourcePath = resolveSourcePath(sourcePath);
            sourceFiles[sourcePath] = {
                resolved: resolvedSourcePath,
                shortened: null
            };
            sourceFilePaths.push(resolvedSourcePath);
        }
    });
    
    // update outdir if necessary, then create outdir
    var packageInfo = ( find({kind: 'package'}) || [] ) [0];
    if (packageInfo && packageInfo.name) {
        outdir = path.join(outdir, packageInfo.name, packageInfo.version);
    }
    fs.mkPath(outdir);

    // copy the template's static files to outdir
    var fromDir = path.join(templatePath, 'static');
    var staticFiles = fs.ls(fromDir, 3);

    staticFiles.forEach(function(fileName) {
        var toDir = fs.toDir( fileName.replace(fromDir, outdir) );
        fs.mkPath(toDir);
        fs.copyFileSync(fileName, toDir);
    });

    // copy user-specified static files to outdir
    var staticFilePaths;
    var staticFileFilter;
    var staticFileScanner;
    if (conf['default'].staticFiles) {
        staticFilePaths = conf['default'].staticFiles.paths || [];
        staticFileFilter = new (require('jsdoc/src/filter')).Filter(conf['default'].staticFiles);
        staticFileScanner = new (require('jsdoc/src/scanner')).Scanner();

        staticFilePaths.forEach(function(filePath) {
            var extraStaticFiles = staticFileScanner.scan([filePath], 10, staticFileFilter);

            extraStaticFiles.forEach(function(fileName) {
                var sourcePath = fs.statSync(filePath).isDirectory() ? filePath :
                    path.dirname(filePath);
                var toDir = fs.toDir( fileName.replace(sourcePath, outdir) );
                fs.mkPath(toDir);
                fs.copyFileSync(fileName, toDir);
            });
        });
    }
    
    if (sourceFilePaths.length) {
        sourceFiles = shortenPaths( sourceFiles, path.commonPrefix(sourceFilePaths) );
    }
    data().each(function(doclet) {
        var url = helper.createLink(doclet);
        helper.registerLink(doclet.longname, url);

        // replace the filename with a shortened version of the full path
        var docletPath;
        if (doclet.meta) {
            docletPath = getPathFromDoclet(doclet);
            docletPath = sourceFiles[docletPath].shortened;
            if (docletPath) {
                doclet.meta.filename = docletPath;
            }
        }
    });
    
    data().each(function(doclet) {
        var url = helper.longnameToUrl[doclet.longname];

        if (url.indexOf('#') > -1) {
            doclet.id = helper.longnameToUrl[doclet.longname].split(/#/).pop();
        }
        else {
            doclet.id = doclet.name;
        }
        
        if ( needsSignature(doclet) ) {
            addSignatureParams(doclet);
            addSignatureReturns(doclet);
            addAttribs(doclet);
        }
    });
    
    // do this after the urls have all been generated
    data().each(function(doclet) {
        doclet.ancestors = getAncestorLinks(doclet);

        if (doclet.kind === 'member') {
            addSignatureTypes(doclet);
            addAttribs(doclet);
        }
        
        if (doclet.kind === 'constant') {
            addSignatureTypes(doclet);
            addAttribs(doclet);
            doclet.kind = 'member';
        }
    });
    
    var members = helper.getMembers(data);
    members.tutorials = tutorials.children;

    ////**debug**
    //if (debugMode) {
    //    debugHtml += ('<h3>members.classes</h3>\n<pre class="source-code">\nmembers.classes =\n' + JSON.stringify(members.classes, null, "  ") + '</pre>\n');
    //}
    ////**debug**

    // add template helpers
    view.find = find;
    view.linkto = linkto;
    view.resolveAuthorLinks = resolveAuthorLinks;
    view.tutoriallink = tutoriallink;
    view.htmlsafe = htmlsafe;
    view.hljs = hljs;

    // once for all
    view.nav = buildNav(members);
    attachModuleSymbols( find({ kind: ['class', 'function'], longname: {left: 'module:'} }),
        members.modules );

    // output source files by default; do this before generating any other pages, so
    // that the other pages can link to the source files
    if (!conf['default'] || conf['default'].outputSourceFiles !== false) {
        generateSourceFiles(sourceFiles, opts.encoding);
    }

    if (members.globals.length) { generate(null, 'Global', [{kind: 'globalobj'}], globalUrl); }
    
    // index page displays information from package.json and lists files
    var files = find({kind: 'file'}),
        packages = find({kind: 'package'});

    //**debug**
    if (debugMode) {
        debugHtml += ('<h3>mainpage docs</h3>\n<pre class="source-code">\ndocs =\n' + JSON.stringify(packages.concat([{kind: 'mainpage', readme: opts.readme, longname: (opts.mainpagetitle) ? opts.mainpagetitle : 'Main Page'}]), null, "  ") + '</pre>\n');
    }
    //**debug**
    generate('OpenSeadragonImaging API', 'OpenSeadragonImaging API',
        packages.concat(
            [{kind: 'mainpage', readme: opts.readme, longname: (opts.mainpagetitle) ? opts.mainpagetitle : 'Main Page'}]
        ).concat(files),
    indexUrl);

    // set up the lists that we'll use to generate pages
    var classes = taffy(members.classes);
    var modules = taffy(members.modules);
    var namespaces = taffy(members.namespaces);
    var mixins = taffy(members.mixins);
    var externals = taffy(members.externals);
    
    Object.keys(helper.longnameToUrl).forEach(function(longname) {
        var myClasses = helper.find(classes, {longname: longname});
        if (myClasses.length) {
            generate(null, 'Class: ' + myClasses[0].name, myClasses, helper.longnameToUrl[longname]);
        }
        
        var myModules = helper.find(modules, {longname: longname});
        if (myModules.length) {
            generate(null, 'Module: ' + myModules[0].name, myModules, helper.longnameToUrl[longname]);
        }

        var myNamespaces = helper.find(namespaces, {longname: longname});
        if (myNamespaces.length) {
            generate(null, 'Namespace: ' + myNamespaces[0].name, myNamespaces, helper.longnameToUrl[longname]);
        }
        
        var myMixins = helper.find(mixins, {longname: longname});
        if (myMixins.length) {
            generate(null, 'Mixin: ' + myMixins[0].name, myMixins, helper.longnameToUrl[longname]);
        }

        var myExternals = helper.find(externals, {longname: longname});
        if (myExternals.length) {
            generate(null, 'External: ' + myExternals[0].name, myExternals, helper.longnameToUrl[longname]);
        }
    });

    // TODO: move the tutorial functions to templateHelper.js
    function generateTutorial(title, tutorial, filename) {
        var tutorialData = {
            title: title,
            header: tutorial.title,
            content: tutorial.parse(),
            children: tutorial.children
        };
        
        var tutorialPath = path.join(outdir, filename),
            html = view.render('tutorial.tmpl', tutorialData);
        
        // yes, you can use {@link} in tutorials too!
        html = helper.resolveLinks(html); // turn {@link foo} into <a href="foodoc.html">foo</a>
        
        fs.writeFileSync(tutorialPath, html, 'utf8');
    }
    
    // tutorials can have only one parent so there is no risk for loops
    function saveChildren(node) {
        node.children.forEach(function(child) {
            generateTutorial('Tutorial: ' + child.title, child, helper.tutorialToUrl(child.name));
            saveChildren(child);
        });
    }
    saveChildren(tutorials);

    if (logMode) {
        fs.writeFileSync(logTextFile, logText, 'utf8');
    }
    if (debugMode) {
        fs.writeFileSync(debugHtmlFile, debugHtmlHeader + debugHtml + debugHtmlFooter, 'utf8');
    }
};
Пример #21
0
exports.publish = function(taffyData, opts, tutorials) {
    data = taffyData;

    var conf = env.conf.templates || {};
    conf['default'] = conf['default'] || {};

    var templatePath = opts.template;
    view = new template.Template(templatePath + '/tmpl');

    // claim some special filenames in advance, so the All-Powerful Overseer of Filename Uniqueness
    // doesn't try to hand them out later
    var indexUrl = helper.getUniqueFilename('index');
    // don't call registerLink() on this one! 'index' is also a valid longname

    var globalUrl = helper.getUniqueFilename('global');
    helper.registerLink('global', globalUrl);

    // set up templating
    view.layout = 'layout.tmpl';

    // set up tutorials for helper
    helper.setTutorials(tutorials);

    data = helper.prune(data);
    data.sort('longname, version, since');
    helper.addEventListeners(data);

    var sourceFiles = {};
    var sourceFilePaths = [];

    data().each(function(doclet) {
        doclet.attribs = '';

        if (doclet.examples) {
            doclet.examples = doclet.examples.map(function(example) {
                var caption, code;

                if (example.match(/^\s*<caption>([\s\S]+?)<\/caption>(\s*[\n\r])([\s\S]+)$/i)) {
                    caption = RegExp.$1;
                    code    = RegExp.$3;
                }

                return {
                    caption: caption || '',
                    code: code || example
                };
            });
        }
        if (doclet.see) {
            doclet.see.forEach(function(seeItem, i) {
                doclet.see[i] = hashToLink(doclet, seeItem);
            });
        }

        // build a list of source files
        var sourcePath;
        var resolvedSourcePath;
        if (doclet.meta) {
            sourcePath = getPathFromDoclet(doclet);
            resolvedSourcePath = resolveSourcePath(sourcePath);
            sourceFiles[sourcePath] = {
                resolved: resolvedSourcePath,
                shortened: null
            };
            sourceFilePaths.push(resolvedSourcePath);
        }
    });

    // update outdir if necessary, then create outdir
    var packageInfo = ( find({kind: 'package'}) || [] ) [0];
    if (packageInfo && packageInfo.name) {
        outdir = path.join(outdir, packageInfo.name, packageInfo.version);
    }
    fs.mkPath(outdir);

    // copy the template's static files to outdir
    var fromDir = path.join(templatePath, 'static');
    var staticFiles = fs.ls(fromDir, 3);

    staticFiles.forEach(function(fileName) {
        var toDir = fs.toDir( fileName.replace(fromDir, outdir) );
        fs.mkPath(toDir);
        fs.copyFileSync(fileName, toDir);
    });

    // copy user-specified static files to outdir
    var staticFilePaths;
    var staticFileFilter;
    var staticFileScanner;
    if (conf['default'].staticFiles) {
        staticFilePaths = conf['default'].staticFiles.paths || [];
        staticFileFilter = new (require('jsdoc/src/filter')).Filter(conf['default'].staticFiles);
        staticFileScanner = new (require('jsdoc/src/scanner')).Scanner();

        staticFilePaths.forEach(function(filePath) {
            var extraStaticFiles = staticFileScanner.scan([filePath], 10, staticFileFilter);

            extraStaticFiles.forEach(function(fileName) {
                var sourcePath = fs.statSync(filePath).isDirectory() ? filePath :
                    path.dirname(filePath);
                var toDir = fs.toDir( fileName.replace(sourcePath, outdir) );
                fs.mkPath(toDir);
                fs.copyFileSync(fileName, toDir);
            });
        });
    }

    if (sourceFilePaths.length) {
        sourceFiles = shortenPaths( sourceFiles, path.commonPrefix(sourceFilePaths) );
    }
    // sets the meta.filename property on each doclet
    data().each(function(doclet) {
        var url = helper.createLink(doclet);
        helper.registerLink(doclet.longname, url);

        // replace the filename with a shortened version of the full path
        var docletPath;
        if (doclet.meta) {
            docletPath = getPathFromDoclet(doclet);
            docletPath = sourceFiles[docletPath].shortened;
            if (docletPath) {
                doclet.meta.filename = docletPath;
            }
        }
    });

    // sets the id property for each doclet
    data().each(function(doclet) {
        var url = helper.longnameToUrl[doclet.longname];

        if (url.indexOf('#') > -1) {
            doclet.id = helper.longnameToUrl[doclet.longname].split(/#/).pop();
        }
        else {
            doclet.id = doclet.name;
        }

        if ( needsSignature(doclet) ) {
            addSignatureParams(doclet);
            addSignatureReturns(doclet);
            addAttribs(doclet);
        }
    });

    // do this after the urls have all been generated (set sign types and attribs)
    data().each(function(doclet) {
        doclet.ancestors = getAncestorLinks(doclet);

        if (doclet.kind === 'member') {
            addSignatureTypes(doclet);
            addAttribs(doclet);
        }

        if (doclet.kind === 'constant') {
            addSignatureTypes(doclet);
            addAttribs(doclet);
            doclet.kind = 'member';
        }
    });

    // inherited members/methods dont show up by default in the file which extends
    // their parent class. let's rectify that.
    //console.log(data()); //returns a taffy object with taffy functions
    data().each(function(doclet) {
        var docletMembersMethodsObj, parentMembersMethodsObj;
        // console.log('data().each() --',doclet.kind,':',doclet.longname);

        if (doclet.kind == 'class' && doclet.augments) {
            // console.log('>>> CLASS:', doclet.name);
            // console.log('>>  AUGMENTS:', doclet.augments);

            docletMembersMethodsObj = getMembersMethodsObj(doclet);
            // console.log('>>> docletMembersMethodsObj', docletMembersMethodsObj);

            doclet.augments.forEach(function(aug) {
                // console.log('checking:', aug);
                // console.log('>>>>> parent Class', aug);
                parentMembersMethodsObj = getMembersMethodsObj(find({ kind: 'class', longname: aug })[0]);
                // console.log('>>>>>>> parentMembersMethodsObj', parentMembersMethodsObj);

                // find overridden members/methods and update the db
                // console.log('  flagOverrides for methods');
                flagOverrides(docletMembersMethodsObj.methods, parentMembersMethodsObj.methods);
                // console.log('  flagOverrides for members');
                flagOverrides(docletMembersMethodsObj.members, parentMembersMethodsObj.members);

                // find inherited members/methods and update the db
                // addInherited(docletMembersMethodsObj.members, parentMembersMethodsObj.members, doclet.longname);
                // addInherited(docletMembersMethodsObj.methods, parentMembersMethodsObj.methods, doclet.longname);
            });
        }
    });
    // end inheritance enhancement

    var members = helper.getMembers(data);
    members.tutorials = tutorials.children;

    // add template helpers
    view.find = find;
    view.linkto = linkto;
    view.resolveAuthorLinks = resolveAuthorLinks;
    view.tutoriallink = tutoriallink;
    view.htmlsafe = htmlsafe;
    // custom
    view.taffyResultsToObj = taffyResultsToObj;
    view.killQuotes = killQuotes;
    // view.findInherited = findInherited;
    // view.findOverrides = findOverrides;

    // once for all
    view.nav = buildNav(members);
    attachModuleSymbols( find({ kind: ['class', 'function'], longname: {left: 'module:'} }),
        members.modules );
    // only output pretty-printed source files if requested; do this before generating any other
    // pages, so the other pages can link to the source files
    if (conf['default'].outputSourceFiles) {
        generateSourceFiles(sourceFiles);
    }

    if (members.globals.length) { generate('Global', [{kind: 'globalobj'}], globalUrl); }

    // index page displays information from package.json and lists files
    var files = find({kind: 'file'}),
        packages = find({kind: 'package'});

    generate('Index',
        packages.concat(
            [{kind: 'mainpage', readme: opts.readme, longname: (opts.mainpagetitle) ? opts.mainpagetitle : 'Main Page'}]
        ).concat(files),
    indexUrl);

    // set up the lists that we'll use to generate pages
    /**
     *  These vars returns an object:
     *  { [Function]
     *  insert: [Function],
     *  merge: [Function],
     *  TAFFY: true,
     *  sort: [Function],
     *  settings: [Function],
     *  store: [Function] }
     */
    var classes = taffy(members.classes);
    var modules = taffy(members.modules);
    var namespaces = taffy(members.namespaces);
    var mixins = taffy(members.mixins);
    var externals = taffy(members.externals);

    Object.keys(helper.longnameToUrl).forEach(function(longname) {
        var myClasses = helper.find(classes, {longname: longname});
        if (myClasses.length) {
            generate('Class: ' + myClasses[0].name, myClasses, helper.longnameToUrl[longname]);
        }

        var myModules = helper.find(modules, {longname: longname});
        if (myModules.length) {
            generate('Module: ' + myModules[0].name, myModules, helper.longnameToUrl[longname]);
        }

        var myNamespaces = helper.find(namespaces, {longname: longname});
        if (myNamespaces.length) {
            generate('Namespace: ' + myNamespaces[0].name, myNamespaces, helper.longnameToUrl[longname]);
        }

        var myMixins = helper.find(mixins, {longname: longname});
        if (myMixins.length) {
            generate('Mixin: ' + myMixins[0].name, myMixins, helper.longnameToUrl[longname]);
        }

        var myExternals = helper.find(externals, {longname: longname});
        if (myExternals.length) {
            generate('External: ' + myExternals[0].name, myExternals, helper.longnameToUrl[longname]);
        }
    });

    // TODO: move the tutorial functions to templateHelper.js
    function generateTutorial(title, tutorial, filename) {
        var tutorialData = {
            title: title,
            header: tutorial.title,
            content: tutorial.parse(),
            children: tutorial.children
        };

        var tutorialPath = path.join(outdir, filename),
            html = view.render('tutorial.tmpl', tutorialData);

        // yes, you can use {@link} in tutorials too!
        html = helper.resolveLinks(html); // turn {@link foo} into <a href="foodoc.html">foo</a>

        fs.writeFileSync(tutorialPath, html, 'utf8');
    }

    // tutorials can have only one parent so there is no risk for loops
    function saveChildren(node) {
        node.children.forEach(function(child) {
            generateTutorial('Tutorial: ' + child.title, child, helper.tutorialToUrl(child.name));
            saveChildren(child);
        });
    }
    saveChildren(tutorials);
};
Пример #22
0
exports.publish = function(taffyData, opts, tutorials) {
    data = taffyData;

    var templatePath = opts.template;
    view = new template.Template(templatePath + '/tmpl');
    
    // set up templating
    view.layout = 'layout.tmpl';

    // set up tutorials for helper
    helper.setTutorials(tutorials);

    data = helper.prune(data);
    data.sort('longname, version, since');

    data().each(function(doclet) {
         doclet.attribs = '';
        
        if (doclet.examples) {
            doclet.examples = doclet.examples.map(function(example) {
                var caption, code;
                
                if (example.match(/^\s*<caption>([\s\S]+?)<\/caption>(\s*[\n\r])([\s\S]+)$/i)) {
                    caption = RegExp.$1;
                    code    = RegExp.$3;
                }
                
                return {
                    caption: caption || '',
                    code: code || example
                };
            });
        }
        if (doclet.see) {
            doclet.see.forEach(function(seeItem, i) {
                doclet.see[i] = hashToLink(doclet, seeItem);
            });
        }
    });
    
    // update outdir if necessary, then create outdir
    var packageInfo = ( find({kind: 'package'}) || [] ) [0];
    if (packageInfo && packageInfo.name) {
        outdir = path.join(outdir, packageInfo.name, packageInfo.version);
    }
    fs.mkPath(outdir);

    // copy static files to outdir
    var fromDir = path.join(templatePath, 'static'),
        staticFiles = fs.ls(fromDir, 3);
        
    staticFiles.forEach(function(fileName) {
        var toDir = fs.toDir( fileName.replace(fromDir, outdir) );
        fs.mkPath(toDir);
        fs.copyFileSync(fileName, toDir);
    });
    
    data().each(function(doclet) {
        var url = helper.createLink(doclet);
        helper.registerLink(doclet.longname, url);
    });
    
    data().each(function(doclet) {
        var url = helper.longnameToUrl[doclet.longname];

        if (url.indexOf('#') > -1) {
            doclet.id = helper.longnameToUrl[doclet.longname].split(/#/).pop();
        }
        else {
            doclet.id = doclet.name;
        }
        
        if (doclet.kind === 'function' || doclet.kind === 'class') {
            addSignatureParams(doclet);
            addSignatureReturns(doclet);
            addAttribs(doclet);
        }
    });
    
    // do this after the urls have all been generated
    data().each(function(doclet) {
        doclet.ancestors = getAncestorLinks(doclet);

        doclet.signature = '';
        
        if (doclet.kind === 'member') {
            addSignatureTypes(doclet);
            addAttribs(doclet);
        }
        
        if (doclet.kind === 'constant') {
            addSignatureTypes(doclet);
            addAttribs(doclet);
            doclet.kind = 'member';
        }
    });
    
    var members = helper.getMembers(data);
    members.tutorials = tutorials.children;

    // add template helpers
    view.find = find;
    view.linkto = linkto;
    view.tutoriallink = tutoriallink;
    view.htmlsafe = htmlsafe;

    // once for all
    view.nav = buildNav(members);

    for (var longname in helper.longnameToUrl) {
        if ( hasOwnProp.call(helper.longnameToUrl, longname) ) {
            // reuse 'members', which speeds things up a bit
            var classes = taffy(members.classes);
            classes = helper.find(classes, {longname: longname});
            if (classes.length) {
                generate('Class: ' + classes[0].longname, classes, helper.longnameToUrl[longname]);
            }
    
            var modules = taffy(members.modules);
            modules = helper.find(modules, {longname: longname});
            if (modules.length) {
                generate('Module: ' + modules[0].longname, modules, helper.longnameToUrl[longname]);
            }
        
            var namespaces = taffy(members.namespaces);
            namespaces = helper.find(namespaces, {longname: longname});
            if (namespaces.length) {
                generate('Namespace: ' + namespaces[0].longname, namespaces, helper.longnameToUrl[longname]);
            }
        
            var mixins = taffy(members.mixins);
            mixins = helper.find(mixins, {longname: longname});
            if (mixins.length) {
                generate('Mixin: ' + mixins[0].longname, mixins, helper.longnameToUrl[longname]);
            }
    
            var externals = taffy(members.externals);
            externals = helper.find(externals, {longname: longname});
            if (externals.length) {
                generate('External: ' + externals[0].longname, externals, helper.longnameToUrl[longname]);
            }
        }
    }

    if (members.globals.length) { generate('Global', members.globals, 'global.html'); }
    
    // index page displays information from package.json and lists files
    var files = find({kind: 'file'}),
        packages = find({kind: 'package'});

    generate('Index',
		packages.concat(
            [{kind: 'mainpage', readme: opts.readme, longname: (opts.mainpagetitle) ? opts.mainpagetitle : 'Main Page'}]
		).concat(files),
	'index.html');
    
    // TODO: move the tutorial functions to templateHelper.js
    function generateTutorial(title, tutorial, filename) {
        var tutorialData = {
            title: title,
            header: tutorial.title,
            content: tutorial.parse(),
            children: tutorial.children
        };
        
        var tutorialPath = path.join(outdir, filename),
            html = view.render('tutorial.tmpl', tutorialData);
        
        // yes, you can use {@link} in tutorials too!
        html = helper.resolveLinks(html); // turn {@link foo} into <a href="foodoc.html">foo</a>
        
        fs.writeFileSync(tutorialPath, html, 'utf8');
    }
    
    // tutorials can have only one parent so there is no risk for loops
    function saveChildren(node) {
        node.children.forEach(function(child) {
            generateTutorial('Tutorial: ' + child.title, child, helper.tutorialToUrl(child.name));
            saveChildren(child);
        });
    }
    saveChildren(tutorials);
};
Пример #23
0
exports.publish = function (taffyData, opts, tutorials) {
	data = taffyData;
//console.log(env)
	var conf = env.conf.templates || {};
	conf['default'] = conf['default'] || {};

	var templatePath = opts.template;
	view = new template.Template(templatePath + '/tmpl');

	// claim some special filenames in advance, so the All-Powerful Overseer of Filename Uniqueness
	// doesn't try to hand them out later
	var indexUrl = helper.getUniqueFilename('index');
	// don't call registerLink() on this one! 'index' is also a valid longname

	var globalUrl = helper.getUniqueFilename('global');
	helper.registerLink('global', globalUrl);

	// set up templating
	view.layout = conf['default'].layoutFile ?
		path.getResourcePath(path.dirname(conf['default'].layoutFile), path.basename(conf['default'].layoutFile)) :
		'layout.tmpl';

	// set up tutorials for helper
	helper.setTutorials(tutorials);

	data = helper.prune(data);
	data.sort('longname, version, since');
	helper.addEventListeners(data);

	var sourceFiles = {};
	var sourceFilePaths = [];
	data().each(function (doclet) {
		doclet.attribs = '';

		if (doclet.examples) {
			doclet.examples = doclet.examples.map(function (example) {
				var caption, code;

				if (example.match(/^\s*<caption>([\s\S]+?)<\/caption>(\s*[\n\r])([\s\S]+)$/i)) {
					caption = RegExp.$1;
					code = RegExp.$3;
				}

				return {
					caption: caption || '',
					code: code || example
				};
			});
		}
		if (doclet.see) {
			doclet.see.forEach(function (seeItem, i) {
				doclet.see[i] = hashToLink(doclet, seeItem);
			});
		}

		// build a list of source files
		var sourcePath;
		if (doclet.meta) {
			sourcePath = getPathFromDoclet(doclet);
			sourceFiles[sourcePath] = {
				resolved: sourcePath,
				shortened: null
			};
			if (sourceFilePaths.indexOf(sourcePath) === -1) {
				sourceFilePaths.push(sourcePath);
			}
		}
	});

	if (sourceFilePaths.length) {
		sourceFiles = shortenPaths(sourceFiles, path.commonPrefix(sourceFilePaths));
	}

	data().each(function (doclet) {
		var url = helper.createLink(doclet);

		helper.registerLink(doclet.longname, url);

		// add a shortened version of the full path
		var docletPath;
		if (doclet.meta) {
			docletPath = getPathFromDoclet(doclet);
			docletPath = sourceFiles[docletPath].shortened;
			if (docletPath) {
				doclet.meta.shortpath = docletPath;
			}
		}
	});

	data().each(function (doclet) {
		var url = helper.longnameToUrl[doclet.longname];

		if (url.indexOf('#') > -1) {
			doclet.id = helper.longnameToUrl[doclet.longname].split(/#/).pop();
		}
		else {
			doclet.id = doclet.name;
		}

		if (needsSignature(doclet)) {
			addSignatureParams(doclet);
			addSignatureReturns(doclet);
			addAttribs(doclet);
		}
	});

	// do this after the urls have all been generated
	data().each(function (doclet) {
		doclet.ancestors = getAncestorLinks(doclet);

		if (doclet.kind === 'member') {
			addSignatureTypes(doclet);
			addAttribs(doclet);
		}

		if (doclet.kind === 'constant') {
			addSignatureTypes(doclet);
			addAttribs(doclet);
			doclet.kind = 'member';
		}
	});

	var members = helper.getMembers(data);
	members.tutorials = tutorials.children;

	// output pretty-printed source files by default
	var outputSourceFiles = conf['default'] && conf['default'].outputSourceFiles !== false ? true :	false;

	// add template helpers
	view.find = find;
	view.linkto = linkto;
	view.resolveAuthorLinks = resolveAuthorLinks;
	view.tutoriallink = tutoriallink;
	view.htmlsafe = htmlsafe;
	view.outputSourceFiles = outputSourceFiles;


	// generate the pretty-printed source files first so other pages can link to them
	if (outputSourceFiles) {
		registerSourceFiles(sourceFiles, opts.encoding);
	}

	// once for all
	attachModuleSymbols(find({ kind: ['class', 'function'], longname: { left: 'module:' } }), members.modules);


	if (members.globals.length) {
		generate('Global', [
			{ kind: 'globalobj' }
		], globalUrl);
	}

	// index page displays information from package.json and lists files
	var files = find({ kind: 'file' });
	var packages = find({ kind: 'package' });

	// set up the lists that we'll use to generate pages
	var classes = taffy(members.classes);
	var modules = taffy(members.modules);
	var namespaces = taffy(members.namespaces);
	var mixins = taffy(members.mixins);
	var externals = taffy(members.externals);

	Object.keys(helper.longnameToUrl).forEach(function (longname) {
		var myClasses = helper.find(classes, { longname: longname });
		if (myClasses.length) {
			generate('Class: ' + myClasses[0].name, myClasses, helper.longnameToUrl[longname]);
		}

		var myModules = helper.find(modules, { longname: longname });
		if (myModules.length) {
			generate('Module: ' + myModules[0].name, myModules, helper.longnameToUrl[longname]);
		}

		var myNamespaces = helper.find(namespaces, { longname: longname });
		if (myNamespaces.length) {
			generate('Namespace: ' + myNamespaces[0].name, myNamespaces, helper.longnameToUrl[longname]);
		}

		var myMixins = helper.find(mixins, { longname: longname });
		if (myMixins.length) {
			generate('Mixin: ' + myMixins[0].name, myMixins, helper.longnameToUrl[longname]);
		}

		var myExternals = helper.find(externals, { longname: longname });
		if (myExternals.length) {
			generate('External: ' + myExternals[0].name, myExternals, helper.longnameToUrl[longname]);
		}
	});

	// TODO: move the tutorial functions to templateHelper.js
	function generateTutorial(title, tutorial, filename) {
		var tutorialData = {
			title: title,
			header: tutorial.title,
			content: tutorial.parse(),
			children: tutorial.children
		};

		var tutorialPath = path.join('./', filename);
		var markdown = view.render('tutorial.tmpl', tutorialData);
		markdown = markdown.replace(/\n+/g, '\n');
		// yes, you can use {@link} in tutorials too!
		markdown = helper.resolveLinks(markdown); // turn {@link foo} into <a href="foodoc.html">foo</a>

		fs.writeFileSync(tutorialPath, markdown, 'utf8');
	}

	// tutorials can have only one parent so there is no risk for loops
	function saveChildren(node) {
		node.children.forEach(function (child) {
			generateTutorial('Tutorial: ' + child.title, child, helper.tutorialToUrl(child.name));
			saveChildren(child);
		});
	}

	saveChildren(tutorials);
};
Пример #24
0
    publish = function(data, opts, tutorials) {
        var defaultTemplatePath = 'templates/default';
        var templatePath = (opts.template) ? opts.template : defaultTemplatePath;
        var out = '',
            view = new template.Template(env.dirname + '/' + templatePath + '/tmpl');
        
        // set up templating
        view.layout = 'layout.tmpl';

        // set up tutorials for helper
        helper.setTutorials(tutorials);

        function find(spec) {
            return data.get( data.find(spec) );
        }
        
        function htmlsafe(str) {
            return str.replace(/</g, '&lt;');
        }

        function addSignatureParams(f) {
            var pnames = [];
            if (f.params) {
                f.params.forEach(function(p) {
                    if (p.name && p.name.indexOf('.') === -1) {
                        if (p.optional) { pnames.push('<span class="optional">'+p.name+'</span>'); }
                        else { pnames.push(p.name); }
                    }
                });
            }
            
            f.signature = (f.signature || '') + '('+pnames.join(', ')+')';
        }
        
        function generateAncestry(thisdoc) {
            var ancestors = [],
                doc = thisdoc;

            while (doc = doc.memberof) {
                doc = find({longname: doc});
                if (doc) { doc = doc[0]; }
                if (!doc) { break; }
                ancestors.unshift( linkto(doc.longname, (scopeToPunc[doc.scope] || '') + doc.name) );
            }
            if (ancestors.length) {
                ancestors[ancestors.length-1] += (scopeToPunc[thisdoc.scope] || '');
            }
            return ancestors;
        }
        
        function addSignatureReturns(f) {
            var returnTypes = [];
            
            if (f.returns) {
                f.returns.forEach(function(r) {
                    if (r.type && r.type.names) {
                        if (! returnTypes.length) { returnTypes = r.type.names; }
                    }
                });
            }
            
            if (returnTypes && returnTypes.length) {
                returnTypes = returnTypes.map(function(r) {
                    return linkto(r);
                });
            }
            f.signature = '<span class="signature">'+(f.signature || '') + '</span>' + '<span class="type-signature">'+(returnTypes.length? ' &rarr; {'+returnTypes.join('|')+'}' : '')+'</span>';
        }
        
        function addSignatureType(f) {
            var types = [];
            
            if (f.type && f.type.names) {
                types = f.type.names;
            }
            
            if (types && types.length) {
                types = types.map(function(t) {
                    return linkto(t, htmlsafe(t));
                });
            }
            
            f.signature = (f.signature || '') + '<span class="type-signature">'+(types.length? ' :'+types.join('|') : '')+'</span>';
        }
        
        function addAttribs(f) {
            var attribs = [];
            
            if (f.virtual) {
                attribs.push('virtual');
            }
            
            if (f.access && f.access !== 'public') {
                attribs.push(f.access);
            }
            
            if (f.scope && f.scope !== 'instance' && f.scope !== 'global') {
                if (f.kind == 'function' || f.kind == 'member' || f.kind == 'constant') {
                    attribs.push(f.scope);
                }
            }
            
            if (f.readonly === true) {
                if (f.kind == 'member') {
                    attribs.push('readonly');
                }
            }
            
            if (f.kind === 'constant') {
                attribs.push('constant');
                f.kind = 'member';
            }
            
            f.attribs = '<span class="type-signature">'+htmlsafe(attribs.length? '<'+attribs.join(', ')+'> ' : '')+'</span>';
        }
        
        data.remove({undocumented: true});
        data.remove({ignore: true});
        if (!opts.private) { data.remove({access: 'private'}); }
        data.remove({memberof: '<anonymous>'});
	    
	    var packageInfo = (find({kind: 'package'}) || []) [0];
        
        //function renderLinks(text) {
        //    return helper.resolveLinks(text);
        //}
        
	    data.forEach(function(doclet) {
             doclet.attribs = '';

	        
	        if (doclet.examples) {
	            doclet.examples = doclet.examples.map(function(example) {
	                var caption, code;
	                
	                if (example.match(/^\s*<caption>([\s\S]+?)<\/caption>(\s*[\n\r])([\s\S]+)$/i)) {
	                    caption = RegExp.$1;
	                    code    = RegExp.$3;
	                }
	                
                    return {
                        caption: caption || '',
                        code: code || example
                    };
                });
	        }
	        if (doclet.see) {
	            doclet.see.forEach(function(seeItem, i) {
	                doclet.see[i] = hashToLink(doclet, seeItem);
	            });
	        }
	    });
	    
	    data.orderBy(['longname', 'version', 'since']);
        
        // kinds of containers
        var globals = find( {kind: ['member', 'function', 'constant', 'typedef'], memberof: {isUndefined: true}} ),
            modules = find({kind: 'module'}),
            externals = find({kind: 'external'}),
            mixins = find({kind: 'mixin'}),
	        namespaces = find({kind: 'namespace'});

        var outdir = opts.destination;
        if (packageInfo && packageInfo.name) {
            outdir += '/' + packageInfo.name + '/' + packageInfo.version + '/';
        }
        fs.mkPath(outdir);

        // copy static files to outdir
        var fromDir = env.dirname + '/' + templatePath + '/static',
            staticFiles = fs.ls(fromDir, 3);
            
        staticFiles.forEach(function(fileName) {
            var toDir = fs.toDir(fileName.replace(fromDir, outdir));
            fs.mkPath(toDir);
            fs.copyFile(fileName, toDir);
        });
        
        function linkto(longname, linktext) {
            var url = helper.longnameToUrl[longname];
            return url? '<a href="'+url+'">'+(linktext || longname)+'</a>' : (linktext || longname);
        }
        
        function tutoriallink(tutorial) {
            return helper.toTutorial(tutorial);
        }
        
        var containers = ['class', 'module', 'external', 'namespace', 'mixin'];
        
        data.forEach(function(doclet) {
            var url = helper.createLink(doclet);
            helper.registerLink(doclet.longname, url);
        });
        
        data.forEach(function(doclet) {
            var url = helper.longnameToUrl[doclet.longname];

	        if (url.indexOf('#') > -1) {
	            doclet.id = helper.longnameToUrl[doclet.longname].split(/#/).pop();
	        }
	        else {
	            doclet.id = doclet.name;
	        }
	        
	        if (doclet.kind === 'function' || doclet.kind === 'class') {
	            addSignatureParams(doclet);
	            addSignatureReturns(doclet);
	            addAttribs(doclet);
	        }
	    });
        
        // do this after the urls have all been generated
        data.forEach(function(doclet) {
            doclet.ancestors = generateAncestry(doclet);
            
            doclet.signature = '';
	        
	        if (doclet.kind === 'member') {
	            addSignatureType(doclet);
	            addAttribs(doclet);
	        }
	        
	        if (doclet.kind === 'constant') {
	            addSignatureType(doclet);
	            addAttribs(doclet);
	        }
        });
        
        var nav = '<h2><a href="index.html">Index</a></h2>',
            seen = {};
        
        var moduleNames = find({kind: 'module'});
        moduleNames.sort(function(a, b) {
            return a.name > b.name;
        });
        if (moduleNames.length) {
            nav += '<h3>Modules</h3><ul>';
            moduleNames.forEach(function(m) {
                if ( !hasOwnProp.call(seen, m.longname) ) {
                    nav += '<li>'+linkto(m.longname, m.name)+'</li>';
                }
                seen[m.longname] = true;
            });
            
            nav += '</ul>';
        }
        
        var externalNames = find({kind: 'external'});
        externalNames.sort(function(a, b) {
            return a.name > b.name;
        });
        if (externalNames.length) {
            nav += '<h3>Externals</h3><ul>';
            externalNames.forEach(function(e) {
                if ( !hasOwnProp.call(seen, e.longname) ) {
                    nav += '<li>'+linkto( e.longname, e.name.replace(/(^"|"$)/g, '') )+'</li>';
                }
                seen[e.longname] = true;
            });
            
            nav += '</ul>';
        }
    
        var classNames = find({kind: 'class'});
        classNames.sort(function(a, b) {
            return a.name > b.name;
        });
        if (classNames.length) {
            var moduleClasses = 0;
            classNames.forEach(function(c) {
                var moduleSameName = find({kind: 'module', longname: c.longname});
                if (moduleSameName.length) {
                    c.name = c.name.replace('module:', 'require("')+'")';
                    moduleClasses++;
                    moduleSameName[0].module = c;
                }
                if (moduleClasses !== -1 && moduleClasses < classNames.length) {
                    nav += '<h3>Classes</h3><ul>';
                    moduleClasses = -1;
                }
                if ( !hasOwnProp.call(seen, c.longname) ) {
                    nav += '<li>'+linkto(c.longname, c.name)+'</li>';
                }
                seen[c.longname] = true;
            });
            
            nav += '</ul>';
        }
        
        var namespaceNames = find({kind: 'namespace'});
        namespaceNames.sort(function(a, b) {
            return a.name > b.name;
        });
        if (namespaceNames.length) {
            nav += '<h3>Namespaces</h3><ul>';
            namespaceNames.forEach(function(n) {
                if ( !hasOwnProp.call(seen, n.longname) ) {
                    nav += '<li>'+linkto(n.longname, n.name)+'</li>';
                }
                seen[n.longname] = true;
            });
            
            nav += '</ul>';
        }
        
//         var constantNames = find({kind: 'constants'});
//         if (constantNames.length) {
//             nav += '<h3>Constants</h3><ul>';
//             constantNames.forEach(function(c) {
//                 if ( !hasOwnProp.call(seen, c.longname) ) {
//                     nav += '<li>'+linkto(c.longname, c.name)+'</li>';
//                 }
//                 seen[c.longname] = true;
//             });
//
//             nav += '</ul>';
//         }
        
        var mixinNames = find({kind: 'mixin'});
        mixinNames.sort(function(a, b) {
            return a.name > b.name;
        });
        if (mixinNames.length) {
            nav += '<h3>Mixins</h3><ul>';
            mixinNames.forEach(function(m) {
                if ( !hasOwnProp.call(seen, m.longname) ) {
                    nav += '<li>'+linkto(m.longname, m.name)+'</li>';
                }
                seen[m.longname] = true;
            });
            
            nav += '</ul>';
        }

        if (tutorials.children.length) {
            nav += '<h3>Tutorials</h3><ul>';
            tutorials.children.forEach(function(t) {
                nav += '<li>'+tutoriallink(t.name)+'</li>';
            });
            
            nav += '</ul>';
        }
        
        var globalNames = find({kind: ['member', 'function', 'constant', 'typedef'], 'memberof': {'isUndefined': true}});
        globalNames.sort(function(a, b) {
            return a.name > b.name;
        });
        if (globalNames.length) {
            nav += '<h3>Global</h3><ul>';
            
            globalNames.forEach(function(g) {
                if ( g.kind !== 'typedef' && !hasOwnProp.call(seen, g.longname) ) {
                    nav += '<li>'+linkto(g.longname, g.name)+'</li>';
                }
                seen[g.longname] = true;
            });
            
            nav += '</ul>';
        }
        
        // add template helpers
        view.find = find;
        view.linkto = linkto;
        view.tutoriallink = tutoriallink;
        view.htmlsafe = htmlsafe;
        // once for all
        view.nav = nav;

        function generate(title, docs, filename) {
            var data = {
                title: title,
                docs: docs
            };
            
            var path = outdir + '/' + filename,
                html = view.render('container.tmpl', data);
            
            html = helper.resolveLinks(html); // turn {@link foo} into <a href="foodoc.html">foo</a>
            
            fs.writeFileSync(path, html);
        }
        
        for (var longname in helper.longnameToUrl) {
            if ( hasOwnProp.call(helper.longnameToUrl, longname) ) {
                var classes = find({kind: 'class', longname: longname});
                if (classes.length) { generate('Class: '+classes[0].name, classes, helper.longnameToUrl[longname]); }
        
                var modules = find({kind: 'module', longname: longname});
                if (modules.length) { generate('Module: '+modules[0].name, modules, helper.longnameToUrl[longname]); }
            
                var namespaces = find({kind: 'namespace', longname: longname});
                if (namespaces.length) { generate('Namespace: '+namespaces[0].name, namespaces, helper.longnameToUrl[longname]); }
            
//                var constants = find({kind: 'constant', longname: longname});
//                if (constants.length) { generate('Constant: '+constants[0].name, constants, helper.longnameToUrl[longname]); }

                var mixins = find({kind: 'mixin', longname: longname});
                if (mixins.length) { generate('Mixin: '+mixins[0].name, mixins, helper.longnameToUrl[longname]); }
        
                var externals = find({kind: 'external', longname: longname});
                if (externals.length) { generate('External: '+externals[0].name, externals, helper.longnameToUrl[longname]); }
            }
        }

        if (globals.length) { generate('Global', [{kind: 'globalobj'}], 'global.html'); }
        
        // index page displays information from package.json and lists files
        var files = find({kind: 'file'}),
            packages = find({kind: 'package'});

        generate('Index',
			packages.concat(
			    [{kind: 'mainpage', readme: opts.readme, longname: (opts.mainpagetitle) ? opts.mainpagetitle : 'Main Page'}]
			).concat(files)
		, 'index.html');
        
        
        function generateTutorial(title, tutorial, filename) {
            var data = {
                title: title,
                header: tutorial.title,
                content: tutorial.parse(),
                children: tutorial.children
            };
            
            var path = outdir + '/' + filename,
                html = view.render('tutorial.tmpl', data);
            
            // yes, you can use {@link} in tutorials too!
            html = helper.resolveLinks(html); // turn {@link foo} into <a href="foodoc.html">foo</a>
            
            fs.writeFileSync(path, html);
        }
        
        // tutorials can have only one parent so there is no risk for loops
        function saveChildren(node) {
            node.children.forEach(function(child) {
                generateTutorial('Tutorial: '+child.title, child, helper.tutorialToUrl(child.name));
                saveChildren(child);
            });
        }
        saveChildren(tutorials);
    };