示例#1
0
        it('should not return the same filename twice', function() {
            var name = 'polymorphic';
            var filename1 = helper.getUniqueFilename(name);
            var filename2 = helper.getUniqueFilename(name);

            expect(filename1).not.toEqual(filename2);
        });
示例#2
0
var PublishJob = module.exports = function(template, options) {
    // directories created by the publish job
    this.outputDirectories = {};
    this.templateConfig = template.config;

    this.options = options;
    this.destination = this.options.destination;
    this.navTree = null;
    this.package = null;
    this.pageTitlePrefix = '';
    this.template = template.init();
    this.renderOptions = {
        beautify: this.templateConfig.beautify
    };

    init();

    // claim some special filenames in advance
    // TODO: we used to avoid calling `registerLink` on `index`; okay that we do it now?
    // if not, should we stop registering `global`, too?
    this.indexUrl = helper.getUniqueFilename('index');
    helper.registerLink('index', this.indexUrl);
    this.globalUrl = helper.getUniqueFilename('global');
    helper.registerLink('global', this.globalUrl);
};
示例#3
0
        it('should not consider the same name with different letter case to be unique', function() {
            var camel = 'myJavaScriptIdentifier';
            var pascal = 'MyJavaScriptIdentifier';
            var filename1 = helper.getUniqueFilename(camel);
            var filename2 = helper.getUniqueFilename(pascal);

            expect( filename1.toLowerCase() ).not.toEqual( filename2.toLowerCase() );
        });
示例#4
0
文件: publish.js 项目: ozio/oz-jsdoc
		function( file ) {
			var source;
			// links are keyed to the shortened path in each doclet's `meta.shortpath` property
			var sourceOutfile = helper.getUniqueFilename( sourceFiles[file].shortened );
			helper.registerLink( sourceFiles[file].shortened, sourceOutfile );

			try {
				source = {
					kind : 'source',
					code : helper.htmlsafe( fs.readFileSync( sourceFiles[file].resolved, encoding ) )
				};
			} catch( e ) {
				logger.error( 'Error while generating source file %s: %s', file, e.message );
			}

			generate( 'Source', sourceFiles[file].shortened, [source], sourceOutfile, false );
		}
    Object.keys(sourceFiles).forEach(function(file) {
        var source;
        // links are keyed to the shortened path in each doclet's `meta.filename` property
        var sourceOutfile = helper.getUniqueFilename(sourceFiles[file].shortened);
        helper.registerLink(sourceFiles[file].shortened, sourceOutfile);

        try {
            source = {
                kind: 'source',
                code: helper.htmlsafe( fs.readFileSync(sourceFiles[file].resolved, encoding) )
            };
        }
        catch(e) {
            handle(e);
        }

        generate('Source: ' + sourceFiles[file].shortened, [source], sourceOutfile,
            conf, false);
    });
示例#6
0
        Object.keys(pathMap).forEach(function(file) {
            var data = {
                docs: null,
                pageCategory: CATEGORIES.SOURCES,
                pageTitle: pathMap[file],
                pageTitlePrefix: this.pageTitlePrefix
            };

            // links are keyed to the shortened path
            url = helper.getUniqueFilename(pathMap[file]);
            helper.registerLink(pathMap[file], url);

            try {
                data.docs = helper.htmlsafe(fs.readFileSync(file, encoding));
            }
            catch (e) {
                logger.error('Unable to generate output for source file %s: %s', file, e.message);
                return;
            }

            self.generate('source', data, url);
        }, this);
示例#7
0
 it('should convert a string with slashes into an alphanumeric hash plus the default extension', function() {
     var filename = helper.getUniqueFilename('tick/tock');
     expect(filename).toMatch(/^[A-Za-z0-9]+\.html$/);
 });
示例#8
0
 it('should convert a simple string into the string plus the default extension', function() {
     var filename = helper.getUniqueFilename('BackusNaur');
     expect(filename).toEqual('BackusNaur.html');
 });
示例#9
0
文件: publish.js 项目: ozio/oz-jsdoc
exports.publish = function( taffyData, opts, tutorials ) {
	data = taffyData;

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

	// Default a few config settings
	if( conf.addProjectSubdir === undefined || conf.addProjectSubdir !== true ) {
		conf.addProjectSubdir = false;
	}
	if( conf.addVersionSubdir === undefined || conf.addVersionSubdir !== true ) {
		conf.addVersionSubdir = false;
	}

	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 ) {

		if( conf.addProjectSubdir ) {
			outdir = path.join( outdir, packageInfo.name );
		}
		if( conf.addVersionSubdir ) {
			outdir = path.join( outdir, (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( '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'] || {};
    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);
};
示例#11
0
 it('should convert a string with slashes into the text following the last slash plus the default extension', function() {
     var filename = helper.getUniqueFilename('tick/tock');
     expect(filename).toMatch(/^tock\.html$/);
 });
示例#12
0
文件: publish.js 项目: bmorrise/cdf
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) {
            if(!doclet.summary && (desc = (doclet.description || doclet.classdesc))) {
                //Try to split when a "." or a ".</htmlTag>" is found.
                //TODO: When markdown is present it fails the split and dumps all description in the summary.
                var split = desc.split(/(\.(<\/?([^<]+)>)?\s*)$/)
                doclet.summary = split[0] + (split[1] || "");
            }

            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);
};
示例#13
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);
};
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');
    }
};
示例#15
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);
};
示例#16
0
  helper = require('jsdoc/util/templateHelper'),
  moment = require('moment'),
  htmlsafe = helper.htmlsafe,
  sanitizeHtml = require('sanitize-html'),
  linkto = helper.linkto,
  resolveAuthorLinks = helper.resolveAuthorLinks,
  hasOwnProp = Object.prototype.hasOwnProperty,
  conf = env.conf.templates || {},
  data,
  view,
  outdir = env.opts.destination,
  searchEnabled = conf.search !== false;

logger.info('logger level', logger.getLevel());

var globalUrl = helper.getUniqueFilename('global');
var indexUrl = helper.getUniqueFilename('index');

if (conf.syntaxTheme) {
  logger.warn('`template.syntaxTheme` is ignored. You can change the syntax theme by modifying template/styles/main.less.');
}

var navOptions = {
  analytics: conf.analytics || null,
  collapseSymbols: conf.collapseSymbols || false,
  copyright: conf.copyright || '',
  dateFormat: conf.dateFormat,
  disablePackagePath: conf.disablePackagePath,
  footer: conf.footer || '',
  includeDate: conf.includeDate !== false,
  inverseNav: conf.inverseNav,
示例#17
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;
        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);
    });

    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;
                doclet.meta.sourceUrl = conf['sourceUrl'].replace('{version}', process.env.CESIUM_VERSION).replace('{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);

    // 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);
    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'}),
        packages = find({kind: 'package'});

    var origLayout = view.layout;
    view.layout = 'indexLayout.tmpl';
    generate('Index',
        packages.concat(
            [{kind: 'mainpage', readme: opts.readme, longname: (opts.mainpagetitle) ? opts.mainpagetitle : 'Main Page'}]
        ).concat(files),
    indexUrl);
    view.layout = origLayout;

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

    var typesJson = {};

    Object.keys(helper.longnameToUrl).forEach(function(longname) {
        var items = helper.find(classes, {longname: longname});

        if (!items.length) {
            items = helper.find(modules, {longname: longname});
        }

        if (items.length) {
            var title = items[0].name;
            var filename = helper.longnameToUrl[longname];
            generate(title, items, filename);

            var titleLower = title.toLowerCase();

            typesJson[titleLower] = typesJson[titleLower] || [];
            typesJson[titleLower].push(filename);

            var members = find({kind: ['function','member'], memberof: longname});
            members.forEach(function(member) {
                member = member.id;
                var memberLower = member.toLowerCase();

                typesJson[memberLower] = typesJson[memberLower] || [];
                typesJson[memberLower].push(filename + '#' + member);
            });
        }
    });

    fs.writeFileSync(outdir + '/types.txt', JSON.stringify(typesJson), 'utf8');
};
示例#18
0
	_ = require( 'underscore' ),
	path = require( 'jsdoc/path' ),
	taffy = require( 'taffydb' ).taffy,
	handle = require( 'jsdoc/util/error' ).handle,
	helper = require( 'jsdoc/util/templateHelper' ),
	htmlsafe = helper.htmlsafe,
	linkto = helper.linkto,
	resolveAuthorLinks = helper.resolveAuthorLinks,
	scopeToPunc = helper.scopeToPunc,
	hasOwnProp = Object.prototype.hasOwnProperty,
	conf = env.conf.templates || {},
	data = {version: 2},
	view,
	outdir = env.opts.destination;

var globalUrl = helper.getUniqueFilename( 'global' );
var indexUrl = helper.getUniqueFilename( 'index' );

var navOptions = {
	systemName      : conf.systemName || "Documentation",
	navType         : conf.navType || "vertical",
	footer          : conf.footer || "",
	copyright       : conf.copyright || "",
	theme           : conf.theme || "simplex",
	linenums        : conf.linenums,
	collapseSymbols : conf.collapseSymbols || false,
	inverseNav      : conf.inverseNav
};

var navigationMaster = {
	index     : {
示例#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 = 'layout.tmpl';

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

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

    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 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);
    var summaryData = buildSummary(members);
    //console.log(summaryData);

    // 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',summaryData:summaryData}]
        ).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) {
                //test
                //if(longname=="$.Scroll"){
                    //console.log(myClasses);
                    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);
};
示例#20
0
文件: example.js 项目: plouc/flambo
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)
}