mirror of
https://github.com/jsdoc/jsdoc.git
synced 2025-12-08 19:46:11 +00:00
Merged @tutorial tag in.
This commit is contained in:
commit
279554f1a3
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,2 +1,3 @@
|
|||||||
build-files/java/build
|
build-files/java/build
|
||||||
jsdoc.jar
|
jsdoc.jar
|
||||||
|
test/tutorials/out
|
||||||
|
|||||||
@ -21,6 +21,10 @@
|
|||||||
{
|
{
|
||||||
"name": "Michael Mathews",
|
"name": "Michael Mathews",
|
||||||
"email": "micmath@gmail.com"
|
"email": "micmath@gmail.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Rafa\u0105 Wrzeszcz",
|
||||||
|
"email": "rafal.wrzeszcz@wrzasq.pl"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"maintainers": [
|
"maintainers": [
|
||||||
|
|||||||
15
jsdoc.js
15
jsdoc.js
@ -142,7 +142,8 @@ function main() {
|
|||||||
opts: {
|
opts: {
|
||||||
parser: require('jsdoc/opts/parser'),
|
parser: require('jsdoc/opts/parser'),
|
||||||
}
|
}
|
||||||
};
|
},
|
||||||
|
resolver;
|
||||||
|
|
||||||
env.opts = jsdoc.opts.parser.parse(env.args);
|
env.opts = jsdoc.opts.parser.parse(env.args);
|
||||||
|
|
||||||
@ -240,6 +241,15 @@ function main() {
|
|||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// load this module anyway to ensure root instance exists
|
||||||
|
// it's not a problem since without tutorials root node will have empty children list
|
||||||
|
resolver = require('jsdoc/tutorial/resolver');
|
||||||
|
|
||||||
|
if (env.opts.tutorials) {
|
||||||
|
resolver.load(env.opts.tutorials);
|
||||||
|
resolver.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
env.opts.template = env.opts.template || 'templates/default';
|
env.opts.template = env.opts.template || 'templates/default';
|
||||||
|
|
||||||
// should define a global "publish" function
|
// should define a global "publish" function
|
||||||
@ -248,7 +258,8 @@ function main() {
|
|||||||
if (typeof publish === 'function') {
|
if (typeof publish === 'function') {
|
||||||
publish(
|
publish(
|
||||||
new (require('typicaljoe/taffy'))(docs),
|
new (require('typicaljoe/taffy'))(docs),
|
||||||
env.opts
|
env.opts,
|
||||||
|
resolver.root
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else { // TODO throw no publish warning?
|
else { // TODO throw no publish warning?
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "JSDoc",
|
"name": "JSDoc",
|
||||||
"version": "3.0.0alpha",
|
"version": "3.0.0alpha",
|
||||||
"revision": "1323214202201",
|
"revision": "1323947228470",
|
||||||
"description": "An automatic documentation generator for javascript.",
|
"description": "An automatic documentation generator for javascript.",
|
||||||
"keywords": [ "documentation", "javascript" ],
|
"keywords": [ "documentation", "javascript" ],
|
||||||
"licenses": [
|
"licenses": [
|
||||||
@ -21,6 +21,10 @@
|
|||||||
{
|
{
|
||||||
"name": "Michael Mathews",
|
"name": "Michael Mathews",
|
||||||
"email": "micmath@gmail.com"
|
"email": "micmath@gmail.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Rafa\u0105 Wrzeszcz",
|
||||||
|
"email": "rafal.wrzeszcz@wrzasq.pl"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"maintainers": [
|
"maintainers": [
|
||||||
|
|||||||
@ -133,7 +133,7 @@ exports.copyFile = function(inFile, outDir, fileName) {
|
|||||||
bis.close();
|
bis.close();
|
||||||
};
|
};
|
||||||
|
|
||||||
function toFile(path) {
|
var toFile = exports.toFile = function(path) {
|
||||||
var parts = path.split(/[\\\/]/);
|
var parts = path.split(/[\\\/]/);
|
||||||
return parts.pop();
|
return parts.pop();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -48,6 +48,8 @@
|
|||||||
members = getMembers(parents[j], docs);
|
members = getMembers(parents[j], docs);
|
||||||
for (var k=0, kk=members.length; k<kk; ++k) {
|
for (var k=0, kk=members.length; k<kk; ++k) {
|
||||||
member = doop(members[k]);
|
member = doop(members[k]);
|
||||||
|
member.inherits = member.longname;
|
||||||
|
member.inherited = true;
|
||||||
member.memberof = doc.longname;
|
member.memberof = doc.longname;
|
||||||
parts = member.longname.split("#");
|
parts = member.longname.split("#");
|
||||||
parts[0] = doc.longname;
|
parts[0] = doc.longname;
|
||||||
|
|||||||
@ -12,7 +12,6 @@ var common = {
|
|||||||
var argParser = new common.args.ArgParser(),
|
var argParser = new common.args.ArgParser(),
|
||||||
ourOptions,
|
ourOptions,
|
||||||
defaults = {
|
defaults = {
|
||||||
template: 'templates/default',
|
|
||||||
destination: './out/'
|
destination: './out/'
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -26,6 +25,7 @@ argParser.addOption('r', 'recurse', false, 'Recurse into subdirectories when
|
|||||||
argParser.addOption('h', 'help', false, 'Print this message and quit.');
|
argParser.addOption('h', 'help', false, 'Print this message and quit.');
|
||||||
argParser.addOption('X', 'explain', false, 'Dump all found doclet internals to console and quit.');
|
argParser.addOption('X', 'explain', false, 'Dump all found doclet internals to console and quit.');
|
||||||
argParser.addOption('q', 'query', true, 'Provide a querystring to define custom variable names/values to add to the options hash.');
|
argParser.addOption('q', 'query', true, 'Provide a querystring to define custom variable names/values to add to the options hash.');
|
||||||
|
argParser.addOption('u', 'tutorials', true, 'Directory in which JSDoc should search for tutorials.');
|
||||||
|
|
||||||
|
|
||||||
// TODO [-R, recurseonly] = a number representing the depth to recurse
|
// TODO [-R, recurseonly] = a number representing the depth to recurse
|
||||||
|
|||||||
@ -54,6 +54,13 @@ exports.jsdocSchema = {
|
|||||||
"items": {
|
"items": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"tutorials": { // extended tutorials
|
||||||
|
"type": ["string", "array"],
|
||||||
|
"optional": true,
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"deprecated": { // is usage of this symbol deprecated?
|
"deprecated": { // is usage of this symbol deprecated?
|
||||||
"type": ["string", "boolean"],
|
"type": ["string", "boolean"],
|
||||||
|
|||||||
@ -486,6 +486,14 @@ exports.defineTags = function(dictionary) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
dictionary.defineTag('tutorial', {
|
||||||
|
mustHaveValue: true,
|
||||||
|
onTagged: function(doclet, tag) {
|
||||||
|
if (!doclet.tutorials) { doclet.tutorials = []; }
|
||||||
|
doclet.tutorials.push(tag.value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
dictionary.defineTag('type', {
|
dictionary.defineTag('type', {
|
||||||
mustHaveValue: true,
|
mustHaveValue: true,
|
||||||
canHaveType: true,
|
canHaveType: true,
|
||||||
|
|||||||
89
rhino_modules/jsdoc/tutorial.js
Normal file
89
rhino_modules/jsdoc/tutorial.js
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
/**
|
||||||
|
@overview
|
||||||
|
@author Rafał Wrzeszcz <rafal.wrzeszcz@wrzasq.pl>
|
||||||
|
@license Apache License 2.0 - See file 'LICENSE.md' in this project.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var mdParser = require('evilstreak/markdown');
|
||||||
|
|
||||||
|
/**
|
||||||
|
@module jsdoc/tutorial
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
@class
|
||||||
|
@classdesc Represents a single JSDoc tutorial.
|
||||||
|
@param {string} name - Tutorial name.
|
||||||
|
@param {string} content - Text content.
|
||||||
|
@param {number} type - Source formating.
|
||||||
|
*/
|
||||||
|
exports.Tutorial = function(name, content, type) {
|
||||||
|
this.title = this.name = name;
|
||||||
|
this.content = content;
|
||||||
|
this.type = type;
|
||||||
|
|
||||||
|
// default values
|
||||||
|
this.parent = null;
|
||||||
|
this.children = [];
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Moves children from current parent to different one.
|
||||||
|
@param {Tutorial} parent - New parent.
|
||||||
|
*/
|
||||||
|
exports.Tutorial.prototype.setParent = function(parent) {
|
||||||
|
// removes node from old parent
|
||||||
|
if (this.parent) {
|
||||||
|
this.parent.removeChild(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.parent = parent;
|
||||||
|
this.parent.addChild(this);
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Removes children from current node.
|
||||||
|
@param {Tutorial} child - Old child.
|
||||||
|
*/
|
||||||
|
exports.Tutorial.prototype.removeChild = function(child) {
|
||||||
|
var index = this.children.indexOf(child);
|
||||||
|
if (index != -1) {
|
||||||
|
this.children.splice(index, 1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Adds new children to current node.
|
||||||
|
@param {Tutorial} child - New child.
|
||||||
|
*/
|
||||||
|
exports.Tutorial.prototype.addChild = function(child) {
|
||||||
|
this.children.push(child);
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Prepares source.
|
||||||
|
@return {string} HTML source.
|
||||||
|
*/
|
||||||
|
exports.Tutorial.prototype.parse = function() {
|
||||||
|
switch (this.type) {
|
||||||
|
// nothing to do
|
||||||
|
case exports.TYPES.HTML:
|
||||||
|
return this.content;
|
||||||
|
|
||||||
|
// markdown
|
||||||
|
case exports.TYPES.MARKDOWN:
|
||||||
|
return mdParser.toHTML(this.content)
|
||||||
|
.replace(/&/g, '&') // because markdown escapes these
|
||||||
|
.replace(/</g, '<')
|
||||||
|
.replace(/>/g, '>');
|
||||||
|
|
||||||
|
// uhm... should we react somehow?
|
||||||
|
// if not then this case can be merged with TYPES.HTML
|
||||||
|
default:
|
||||||
|
return this.content;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Tutorial source types.
|
||||||
|
@enum {number}
|
||||||
|
*/
|
||||||
|
exports.TYPES = {
|
||||||
|
HTML: 1,
|
||||||
|
MARKDOWN: 2
|
||||||
|
};
|
||||||
126
rhino_modules/jsdoc/tutorial/resolver.js
Normal file
126
rhino_modules/jsdoc/tutorial/resolver.js
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
/**
|
||||||
|
@overview
|
||||||
|
@author Rafał Wrzeszcz <rafal.wrzeszcz@wrzasq.pl>
|
||||||
|
@license Apache License 2.0 - See file 'LICENSE.md' in this project.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
@module jsdoc/tutorial/resolver
|
||||||
|
*/
|
||||||
|
|
||||||
|
var tutorial = require('jsdoc/tutorial'),
|
||||||
|
fs = require('fs'),
|
||||||
|
conf = {},
|
||||||
|
tutorials = {},
|
||||||
|
finder = /^(.*)\.(x(?:ht)?ml|html?|md|markdown|js(?:on)?)$/i;
|
||||||
|
|
||||||
|
/** Adds new tutorial.
|
||||||
|
@param {tutorial.Tutorial} current - New tutorial.
|
||||||
|
*/
|
||||||
|
exports.addTutorial = function(current) {
|
||||||
|
tutorials[current.name] = current;
|
||||||
|
|
||||||
|
// default temporary parent
|
||||||
|
current.setParent(exports.root);
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Root tutorial.
|
||||||
|
@type tutorial.Tutorial
|
||||||
|
*/
|
||||||
|
exports.root = new tutorial.Tutorial('', '');
|
||||||
|
|
||||||
|
/** Additional instance method for root node.
|
||||||
|
@param {string} name - Tutorial name.
|
||||||
|
@reutrn {tutorial.Tutorial} Tutorial instance.
|
||||||
|
*/
|
||||||
|
exports.root.getByName = function(name) {
|
||||||
|
return tutorials[name];
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Load tutorials from given path.
|
||||||
|
@param {string} path - Tutorials directory.
|
||||||
|
*/
|
||||||
|
exports.load = function(path) {
|
||||||
|
var match,
|
||||||
|
type,
|
||||||
|
name,
|
||||||
|
current,
|
||||||
|
files = fs.ls(path);
|
||||||
|
|
||||||
|
// tutorials handling
|
||||||
|
files.forEach(function(file) {
|
||||||
|
match = file.match(finder);
|
||||||
|
|
||||||
|
// any filetype that can apply to tutorials
|
||||||
|
if (match) {
|
||||||
|
name = fs.toFile(match[1]);
|
||||||
|
content = fs.readFileSync(file);
|
||||||
|
|
||||||
|
switch (match[2].toLowerCase()) {
|
||||||
|
// HTML type
|
||||||
|
case 'xml':
|
||||||
|
case 'xhtml':
|
||||||
|
case 'html':
|
||||||
|
case 'htm':
|
||||||
|
type = tutorial.TYPES.HTML;
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Markdown typs
|
||||||
|
case 'md':
|
||||||
|
case 'markdown':
|
||||||
|
type = tutorial.TYPES.MARKDOWN;
|
||||||
|
break;
|
||||||
|
|
||||||
|
// configuration file
|
||||||
|
case 'js':
|
||||||
|
case 'json':
|
||||||
|
conf[name] = JSON.parse(content);
|
||||||
|
|
||||||
|
// how can it be? check `finder' regexp
|
||||||
|
default:
|
||||||
|
// not a file we want to work with
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
current = new tutorial.Tutorial(name, content, type);
|
||||||
|
exports.addTutorial(current);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Resolves hierarchical structure.
|
||||||
|
@param {object} map - Contents map.
|
||||||
|
*/
|
||||||
|
exports.resolve = function() {
|
||||||
|
var item,
|
||||||
|
current;
|
||||||
|
for (var name in conf) {
|
||||||
|
// should we be restrictive here?
|
||||||
|
// what is someone just wants to keep sample sources in same directory with tutorials?
|
||||||
|
// I've decided to leave such cases alone
|
||||||
|
if (!(name in tutorials)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
item = conf[name];
|
||||||
|
current = tutorials[name]
|
||||||
|
|
||||||
|
// set title
|
||||||
|
if (item.title) {
|
||||||
|
current.title = item.title;
|
||||||
|
}
|
||||||
|
|
||||||
|
// add children
|
||||||
|
if (item.children) {
|
||||||
|
item.children.forEach(function(child) {
|
||||||
|
// I really didn't want to throw you an exception in most cases
|
||||||
|
// but now, user, you pissed me off ;)
|
||||||
|
if (!(child in tutorials)) {
|
||||||
|
throw new Error("Missing child tutorial: " + child);
|
||||||
|
}
|
||||||
|
|
||||||
|
tutorials[child].setParent(current);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
@ -8,7 +8,7 @@ var dictionary = require('jsdoc/tag/dictionary');
|
|||||||
exports.globalName = 'global';
|
exports.globalName = 'global';
|
||||||
exports.fileExtension = '.html';
|
exports.fileExtension = '.html';
|
||||||
|
|
||||||
/** Find symbol {@link ...} strings in text and turn into html links */
|
/** Find symbol {@link ...} and {@tutorial ...} strings in text and turn into html links */
|
||||||
exports.resolveLinks = function(str) {
|
exports.resolveLinks = function(str) {
|
||||||
str = str.replace(/(?:\[(.+?)\])?\{@link +(.+?)\}/gi,
|
str = str.replace(/(?:\[(.+?)\])?\{@link +(.+?)\}/gi,
|
||||||
function(match, content, longname) {
|
function(match, content, longname) {
|
||||||
@ -16,6 +16,12 @@ exports.resolveLinks = function(str) {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
str = str.replace(/(?:\[(.+?)\])?\{@tutorial +(.+?)\}/gi,
|
||||||
|
function(match, content, tutorial) {
|
||||||
|
return toTutorial(tutorial, content);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,4 +108,40 @@ function toLink(longname, content) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @external {jsdoc.tutorial.Tutorial} */
|
||||||
|
var tutorials;
|
||||||
|
|
||||||
|
/** Sets tutorials map.
|
||||||
|
@param {jsdoc.tutorial.Tutorial} root - Root tutorial node.
|
||||||
|
*/
|
||||||
|
exports.setTutorials = function(root) {
|
||||||
|
tutorials = root;
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.toTutorial = toTutorial = function(tutorial, content) {
|
||||||
|
if (!tutorial) {
|
||||||
|
throw new Error('Missing required parameter: tutorial');
|
||||||
|
}
|
||||||
|
|
||||||
|
var node = tutorials.getByName(tutorial);
|
||||||
|
// no such tutorial
|
||||||
|
if (!node) {
|
||||||
|
return '<em class="disabled">Tutorial: '+tutorial+'</em>';
|
||||||
|
}
|
||||||
|
|
||||||
|
content = content || node.title;
|
||||||
|
|
||||||
|
return '<a href="'+exports.tutorialToUrl(tutorial)+'">'+content+'</a>';
|
||||||
|
}
|
||||||
|
|
||||||
exports.longnameToUrl = linkMap.longnameToUrl;
|
exports.longnameToUrl = linkMap.longnameToUrl;
|
||||||
|
|
||||||
|
exports.tutorialToUrl = function(tutorial) {
|
||||||
|
var node = tutorials.getByName(tutorial);
|
||||||
|
// no such tutorial
|
||||||
|
if (!node) {
|
||||||
|
throw new Error('No such tutorial: '+tutorial);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 'tutorial-'+strToFilename(node.name)+exports.fileExtension;
|
||||||
|
};
|
||||||
|
|||||||
@ -13,10 +13,15 @@
|
|||||||
@global
|
@global
|
||||||
@param {TAFFY} data See <http://taffydb.com/>.
|
@param {TAFFY} data See <http://taffydb.com/>.
|
||||||
@param {object} opts
|
@param {object} opts
|
||||||
|
@param {Tutorial} tutorials
|
||||||
*/
|
*/
|
||||||
publish = function(data, opts) {
|
publish = function(data, opts, tutorials) {
|
||||||
var out = '',
|
var out = '',
|
||||||
containerTemplate = template.render(fs.readFileSync(__dirname + '/templates/default/tmpl/container.tmpl'));
|
containerTemplate = template.render(fs.readFileSync(__dirname + '/templates/default/tmpl/container.tmpl')),
|
||||||
|
tutorialTemplate = template.render(fs.readFileSync(__dirname + '/templates/default/tmpl/tutorial.tmpl'));
|
||||||
|
|
||||||
|
// set up tutorials for helper
|
||||||
|
helper.setTutorials(tutorials);
|
||||||
|
|
||||||
function render(tmpl, partialData) {
|
function render(tmpl, partialData) {
|
||||||
var renderFunction = arguments.callee.cache[tmpl];
|
var renderFunction = arguments.callee.cache[tmpl];
|
||||||
@ -26,6 +31,7 @@
|
|||||||
partialData.render = arguments.callee;
|
partialData.render = arguments.callee;
|
||||||
partialData.find = find;
|
partialData.find = find;
|
||||||
partialData.linkto = linkto;
|
partialData.linkto = linkto;
|
||||||
|
partialData.tutoriallink = tutoriallink;
|
||||||
partialData.htmlsafe = htmlsafe;
|
partialData.htmlsafe = htmlsafe;
|
||||||
|
|
||||||
return renderFunction.call(partialData, partialData);
|
return renderFunction.call(partialData, partialData);
|
||||||
@ -162,7 +168,7 @@
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else if (doclet.see) {
|
if (doclet.see) {
|
||||||
doclet.see.forEach(function(seeItem, i) {
|
doclet.see.forEach(function(seeItem, i) {
|
||||||
doclet.see[i] = hashToLink(doclet, seeItem);
|
doclet.see[i] = hashToLink(doclet, seeItem);
|
||||||
});
|
});
|
||||||
@ -199,6 +205,10 @@
|
|||||||
return url? '<a href="'+url+'">'+(linktext || longname)+'</a>' : (linktext || longname);
|
return url? '<a href="'+url+'">'+(linktext || longname)+'</a>' : (linktext || longname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function tutoriallink(tutorial) {
|
||||||
|
return helper.toTutorial(tutorial);
|
||||||
|
}
|
||||||
|
|
||||||
var containers = ['class', 'module', 'external', 'namespace', 'mixin'];
|
var containers = ['class', 'module', 'external', 'namespace', 'mixin'];
|
||||||
|
|
||||||
data.forEach(function(doclet) {
|
data.forEach(function(doclet) {
|
||||||
@ -245,29 +255,29 @@
|
|||||||
|
|
||||||
var moduleNames = find({kind: 'module'});
|
var moduleNames = find({kind: 'module'});
|
||||||
if (moduleNames.length) {
|
if (moduleNames.length) {
|
||||||
nav = nav + '<h3>Modules</h3><ul>';
|
nav += '<h3>Modules</h3><ul>';
|
||||||
moduleNames.forEach(function(m) {
|
moduleNames.forEach(function(m) {
|
||||||
if ( !seen.hasOwnProperty(m.longname) ) nav += '<li>'+linkto(m.longname, m.name)+'</li>';
|
if ( !seen.hasOwnProperty(m.longname) ) nav += '<li>'+linkto(m.longname, m.name)+'</li>';
|
||||||
seen[m.longname] = true;
|
seen[m.longname] = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
nav = nav + '</ul>';
|
nav += '</ul>';
|
||||||
}
|
}
|
||||||
|
|
||||||
var externalNames = find({kind: 'external'});
|
var externalNames = find({kind: 'external'});
|
||||||
if (externalNames.length) {
|
if (externalNames.length) {
|
||||||
nav = nav + '<h3>Externals</h3><ul>';
|
nav += '<h3>Externals</h3><ul>';
|
||||||
externalNames.forEach(function(e) {
|
externalNames.forEach(function(e) {
|
||||||
if ( !seen.hasOwnProperty(e.longname) ) nav += '<li>'+linkto( e.longname, e.name.replace(/(^"|"$)/g, '') )+'</li>';
|
if ( !seen.hasOwnProperty(e.longname) ) nav += '<li>'+linkto( e.longname, e.name.replace(/(^"|"$)/g, '') )+'</li>';
|
||||||
seen[e.longname] = true;
|
seen[e.longname] = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
nav = nav + '</ul>';
|
nav += '</ul>';
|
||||||
}
|
}
|
||||||
|
|
||||||
var classNames = find({kind: 'class'});
|
var classNames = find({kind: 'class'});
|
||||||
if (classNames.length) {
|
if (classNames.length) {
|
||||||
nav = nav + '<h3>Classes</h3><ul>';
|
nav += '<h3>Classes</h3><ul>';
|
||||||
classNames.forEach(function(c) {
|
classNames.forEach(function(c) {
|
||||||
var moduleSameName = find({kind: 'module', longname: c.longname});
|
var moduleSameName = find({kind: 'module', longname: c.longname});
|
||||||
if (moduleSameName.length) {
|
if (moduleSameName.length) {
|
||||||
@ -279,52 +289,61 @@
|
|||||||
seen[c.longname] = true;
|
seen[c.longname] = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
nav = nav + '</ul>';
|
nav += '</ul>';
|
||||||
}
|
}
|
||||||
|
|
||||||
var namespaceNames = find({kind: 'namespace'});
|
var namespaceNames = find({kind: 'namespace'});
|
||||||
if (namespaceNames.length) {
|
if (namespaceNames.length) {
|
||||||
nav = nav + '<h3>Namespaces</h3><ul>';
|
nav += '<h3>Namespaces</h3><ul>';
|
||||||
namespaceNames.forEach(function(n) {
|
namespaceNames.forEach(function(n) {
|
||||||
if ( !seen.hasOwnProperty(n.longname) ) nav += '<li>'+linkto(n.longname, n.name)+'</li>';
|
if ( !seen.hasOwnProperty(n.longname) ) nav += '<li>'+linkto(n.longname, n.name)+'</li>';
|
||||||
seen[n.longname] = true;
|
seen[n.longname] = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
nav = nav + '</ul>';
|
nav += '</ul>';
|
||||||
}
|
}
|
||||||
|
|
||||||
// var constantNames = find({kind: 'constants'});
|
// var constantNames = find({kind: 'constants'});
|
||||||
// if (constantNames.length) {
|
// if (constantNames.length) {
|
||||||
// nav = nav + '<h3>Constants</h3><ul>';
|
// nav += '<h3>Constants</h3><ul>';
|
||||||
// constantNames.forEach(function(c) {
|
// constantNames.forEach(function(c) {
|
||||||
// if ( !seen.hasOwnProperty(c.longname) ) nav += '<li>'+linkto(c.longname, c.name)+'</li>';
|
// if ( !seen.hasOwnProperty(c.longname) ) nav += '<li>'+linkto(c.longname, c.name)+'</li>';
|
||||||
// seen[c.longname] = true;
|
// seen[c.longname] = true;
|
||||||
// });
|
// });
|
||||||
//
|
//
|
||||||
// nav = nav + '</ul>';
|
// nav += '</ul>';
|
||||||
// }
|
// }
|
||||||
|
|
||||||
var mixinNames = find({kind: 'mixin'});
|
var mixinNames = find({kind: 'mixin'});
|
||||||
if (mixinNames.length) {
|
if (mixinNames.length) {
|
||||||
nav = nav + '<h3>Mixins</h3><ul>';
|
nav += '<h3>Mixins</h3><ul>';
|
||||||
mixinNames.forEach(function(m) {
|
mixinNames.forEach(function(m) {
|
||||||
if ( !seen.hasOwnProperty(m.longname) ) nav += '<li>'+linkto(m.longname, m.name)+'</li>';
|
if ( !seen.hasOwnProperty(m.longname) ) nav += '<li>'+linkto(m.longname, m.name)+'</li>';
|
||||||
seen[m.longname] = true;
|
seen[m.longname] = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
nav = nav + '</ul>';
|
nav += '</ul>';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tutorials.children.length) {
|
||||||
|
nav += '<h3>Tutorials</h3><ul>';
|
||||||
|
tutorials.children.forEach(function(t) {
|
||||||
|
nav += '<li>'+tutoriallink(t.name)+'</li>';
|
||||||
|
});
|
||||||
|
|
||||||
|
nav += '</ul>';
|
||||||
}
|
}
|
||||||
|
|
||||||
var globalNames = find({kind: ['member', 'function', 'constant', 'typedef'], 'memberof': {'isUndefined': true}});
|
var globalNames = find({kind: ['member', 'function', 'constant', 'typedef'], 'memberof': {'isUndefined': true}});
|
||||||
|
|
||||||
if (globalNames.length) {
|
if (globalNames.length) {
|
||||||
nav = nav + '<h3>Global</h3><ul>';
|
nav += '<h3>Global</h3><ul>';
|
||||||
globalNames.forEach(function(g) {
|
globalNames.forEach(function(g) {
|
||||||
if ( g.kind !== 'typedef' && !seen.hasOwnProperty(g.longname) ) nav += '<li>'+linkto(g.longname, g.name)+'</li>';
|
if ( g.kind !== 'typedef' && !seen.hasOwnProperty(g.longname) ) nav += '<li>'+linkto(g.longname, g.name)+'</li>';
|
||||||
seen[g.longname] = true;
|
seen[g.longname] = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
nav = nav + '</ul>';
|
nav += '</ul>';
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var longname in helper.longnameToUrl) {
|
for (var longname in helper.longnameToUrl) {
|
||||||
@ -360,6 +379,7 @@
|
|||||||
render: render,
|
render: render,
|
||||||
find: find,
|
find: find,
|
||||||
linkto: linkto,
|
linkto: linkto,
|
||||||
|
tutoriallink: tutoriallink,
|
||||||
htmlsafe: htmlsafe
|
htmlsafe: htmlsafe
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -370,6 +390,39 @@
|
|||||||
|
|
||||||
fs.writeFileSync(path, html)
|
fs.writeFileSync(path, html)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function generateTutorial(title, tutorial, filename) {
|
||||||
|
var data = {
|
||||||
|
title: title,
|
||||||
|
header: tutorial.title,
|
||||||
|
content: tutorial.parse(),
|
||||||
|
children: tutorial.children,
|
||||||
|
nav: nav,
|
||||||
|
|
||||||
|
// helpers
|
||||||
|
render: render,
|
||||||
|
find: find,
|
||||||
|
linkto: linkto,
|
||||||
|
tutoriallink: tutoriallink,
|
||||||
|
htmlsafe: htmlsafe
|
||||||
|
};
|
||||||
|
|
||||||
|
var path = outdir + '/' + filename,
|
||||||
|
html = tutorialTemplate.call(data, data);
|
||||||
|
|
||||||
|
// yes, you can use {@link} in tutorials too!
|
||||||
|
html = helper.resolveLinks(html); // turn {@link foo} into <a href="foodoc.html">foo</a>
|
||||||
|
|
||||||
|
fs.writeFileSync(path, html)
|
||||||
|
}
|
||||||
|
|
||||||
|
// tutorials can have only one parent so there is no risk for loops
|
||||||
|
function saveChildren(node) {
|
||||||
|
node.children.forEach(function(child) {
|
||||||
|
generateTutorial('Tutorial: '+child.title, child, helper.tutorialToUrl(child.name));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
saveChildren(tutorials);
|
||||||
}
|
}
|
||||||
|
|
||||||
function hashToLink(doclet, hash) {
|
function hashToLink(doclet, hash) {
|
||||||
|
|||||||
@ -254,3 +254,7 @@ h6
|
|||||||
|
|
||||||
.params th, .props th { border-right: 1px solid #aaa; }
|
.params th, .props th { border-right: 1px solid #aaa; }
|
||||||
.params thead .last, .props thead .last { border-right: 1px solid #ddd; }
|
.params thead .last, .props thead .last { border-right: 1px solid #ddd; }
|
||||||
|
|
||||||
|
.disabled {
|
||||||
|
color: #454545;
|
||||||
|
}
|
||||||
|
|||||||
@ -61,6 +61,17 @@
|
|||||||
<dd class="tag-source"><ul class="dummy"><li><?js= meta.filename ?>, line <?js= meta.lineno ?></li></ul></dd>
|
<dd class="tag-source"><ul class="dummy"><li><?js= meta.filename ?>, line <?js= meta.lineno ?></li></ul></dd>
|
||||||
<?js } ?>
|
<?js } ?>
|
||||||
|
|
||||||
|
<?js if (this.tutorials && tutorials.length) {?>
|
||||||
|
<dt class="tag-tutorial">Tutorials:</dt>
|
||||||
|
<dd class="tag-tutorial">
|
||||||
|
<ul><?js
|
||||||
|
tutorials.forEach(function(t) {
|
||||||
|
print('<li>'+tutoriallink(t)+'</li>');
|
||||||
|
});
|
||||||
|
?></ul>
|
||||||
|
</dd>
|
||||||
|
<?js } ?>
|
||||||
|
|
||||||
<?js if (this.see && see.length) {?>
|
<?js if (this.see && see.length) {?>
|
||||||
<dt class="tag-see">See:</dt>
|
<dt class="tag-see">See:</dt>
|
||||||
<dd class="tag-see">
|
<dd class="tag-see">
|
||||||
|
|||||||
53
templates/default/tmpl/tutorial.tmpl
Normal file
53
templates/default/tmpl/tutorial.tmpl
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>JSDoc: <?js= title ?></title>
|
||||||
|
|
||||||
|
<script src="http://shjs.sourceforge.net/sh_main.min.js"> </script>
|
||||||
|
<script src="http://shjs.sourceforge.net/lang/sh_javascript.min.js"> </script>
|
||||||
|
|
||||||
|
<link type="text/css" rel="stylesheet" href="styles/node-dark.css">
|
||||||
|
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div id="main">
|
||||||
|
|
||||||
|
<h1 class="page-title"><?js= title ?></h1>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
|
||||||
|
<header>
|
||||||
|
<?js if (children.length > 0) { ?>
|
||||||
|
<ul><?js
|
||||||
|
children.forEach(function(t) {
|
||||||
|
print('<li>'+tutoriallink(t.name)+'</li>');
|
||||||
|
});
|
||||||
|
?></ul>
|
||||||
|
<?js } ?>
|
||||||
|
|
||||||
|
<h2><?js= header ?></h2>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<article>
|
||||||
|
<?js= content ?>
|
||||||
|
</article>
|
||||||
|
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<nav>
|
||||||
|
<?js= nav ?>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<br clear="both">
|
||||||
|
|
||||||
|
<footer>
|
||||||
|
Documentation generated by <a href="https://github.com/micmath/jsdoc">JSDoc 3</a> on <?js= (new Date()) ?>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<script> sh_highlightDocument(); </script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
2
test/tutorials/build.sh
Executable file
2
test/tutorials/build.sh
Executable file
@ -0,0 +1,2 @@
|
|||||||
|
rm -rf out
|
||||||
|
../../jsdoc -u tutorials src -d out
|
||||||
8
test/tutorials/src/x.js
Normal file
8
test/tutorials/src/x.js
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
/**
|
||||||
|
* Test {@tutorial test2} {@tutorial dupa}
|
||||||
|
*
|
||||||
|
* @class
|
||||||
|
* @tutorial test
|
||||||
|
* @tutorial jasia
|
||||||
|
*/
|
||||||
|
function Test() {}
|
||||||
3
test/tutorials/tutorials/test.html
Normal file
3
test/tutorials/tutorials/test.html
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<h1>Test.html</h1>
|
||||||
|
|
||||||
|
<p>{@link Test}</p>
|
||||||
1
test/tutorials/tutorials/test.js
Normal file
1
test/tutorials/tutorials/test.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
{"title": "Test tutorial", "children": ["test2"]}
|
||||||
1
test/tutorials/tutorials/test2.json
Normal file
1
test/tutorials/tutorials/test2.json
Normal file
@ -0,0 +1 @@
|
|||||||
|
{"title": "Test 2"}
|
||||||
1
test/tutorials/tutorials/test2.markdown
Normal file
1
test/tutorials/tutorials/test2.markdown
Normal file
@ -0,0 +1 @@
|
|||||||
|
# test2.markdown
|
||||||
Loading…
x
Reference in New Issue
Block a user