mirror of
https://github.com/jsdoc/jsdoc.git
synced 2025-12-08 19:46:11 +00:00
Fixes in JSON output module to escape newlines, added normal templates module, added start of haruki template.
This commit is contained in:
parent
1170f87b15
commit
532672c71d
@ -14,7 +14,14 @@ var jsDump;
|
||||
|
||||
(function(){
|
||||
function quote( str ){
|
||||
return '"' + str.toString().replace(/"/g, '\\"') + '"';
|
||||
return '"' + str.toString()
|
||||
.replace(/\\/g, "\\\\")
|
||||
.replace(/"/g, '\\"')
|
||||
.replace(/\f/g, "\\f")
|
||||
.replace(/\n/g, "\\n")
|
||||
.replace(/\r/g, "\\r")
|
||||
.replace(/\t/g, "\\t")
|
||||
+ '"';
|
||||
};
|
||||
function literal( o ){
|
||||
return o + '';
|
||||
|
||||
199
modules/normal/template.js
Normal file
199
modules/normal/template.js
Normal file
@ -0,0 +1,199 @@
|
||||
/**
|
||||
* Normal Template
|
||||
*/
|
||||
|
||||
var TOKEN_RE = new RegExp("(\{[\=\:\#\/].+?\})"),
|
||||
COMMAND_RE = new RegExp("^\{[\:\/\=]");
|
||||
|
||||
var xpath = function (path) {
|
||||
if (path === '$last') {
|
||||
return "$last";
|
||||
}
|
||||
|
||||
if (/\||;|\$|~/.test(path)) {
|
||||
throw new Error("Invalid characters in path '" + path + "'");
|
||||
}
|
||||
|
||||
path = path.replace(/\//g, ".").replace(/'|"/, "");
|
||||
|
||||
if (path == ".") {
|
||||
return "d";
|
||||
} else if (/^\./.test(path)) {
|
||||
return "data" + path;
|
||||
} else {
|
||||
return "d." + path;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Template filters. Add your own to this dictionary.
|
||||
*/
|
||||
exports.filters = {
|
||||
str: function (val) { // used to override default filtering.
|
||||
return val.toString();
|
||||
},
|
||||
strip: function (val) {
|
||||
return val.toString().replace(/<([^>]+)>/g, "");
|
||||
},
|
||||
html: function (val) {
|
||||
return val.toString().replace(/&/g, "&").replace(/>/g, ">").
|
||||
replace(/</g, "<");
|
||||
},
|
||||
attr: function (val) {
|
||||
return val.toString().replace(/&/g, "&").replace(/>/g, ">").
|
||||
replace(/</g, "<").replace(/"/g, """);
|
||||
},
|
||||
uri: encodeURI
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile the template source into the template function.
|
||||
*/
|
||||
exports.compile = function (src, options) {
|
||||
// v = curent value, d = cursor, a = reduced array, df = default filter, res = result
|
||||
var code = ['var v,a,d = data,res = [];'],
|
||||
stack = ["data"],
|
||||
nesting = [],
|
||||
tokens = src.split(TOKEN_RE);
|
||||
|
||||
var filters, tag;
|
||||
|
||||
if (options && options.filters) {
|
||||
filters = {};
|
||||
for (var i in exports.filters) filters[i] = exports.filters[i];
|
||||
for (var i in options.filters) filters[i] = options.filters[i];
|
||||
} else {
|
||||
filters = exports.filters;
|
||||
}
|
||||
|
||||
if (filters.defaultfilter) {
|
||||
code.push('var df = filters.defaultfilter;');
|
||||
}
|
||||
|
||||
for (var i = 0; i < tokens.length; i++) {
|
||||
var token = tokens[i];
|
||||
|
||||
if (token == "") continue;
|
||||
|
||||
if (token.match(COMMAND_RE)) {
|
||||
if (token[1] == ":") { // open tag
|
||||
var parts = token.substring(2, token.length-1).split(" "),
|
||||
cmd = parts[0],
|
||||
arg = parts[1],
|
||||
val;
|
||||
|
||||
switch (cmd) {
|
||||
case "if": // checks for undefined and boolean.
|
||||
nesting.push("if");
|
||||
val = xpath(arg);
|
||||
code.push('if (' + val + ') {');
|
||||
continue;
|
||||
|
||||
case "select":
|
||||
case "s":
|
||||
nesting.push("select");
|
||||
val = xpath(arg);
|
||||
code.push('d = ' + val + ';if (d != undefined) {');
|
||||
stack.unshift(val.replace(/^d\./, stack[0] + "."));
|
||||
continue;
|
||||
|
||||
case "reduce":
|
||||
case "r":
|
||||
nesting.push("reduce");
|
||||
val = xpath(arg);
|
||||
var depth = stack.length;
|
||||
code.push('var a' + depth + ' = ' + val + ';if ((a' + depth + ' != undefined) && (a' + depth + '.length > 0)) ');
|
||||
stack.unshift("a" + depth + "[i" + depth + "]");
|
||||
code.push('for (var i' + depth + ' = 0,l' + depth + ' = a' + depth + '.length; i' + depth + ' < l' + depth + '; i' + depth + '++) {$last = (i' + depth + ' == l' + depth + '-1); d = a' + depth + '[i' + depth + '];');
|
||||
continue;
|
||||
|
||||
case "else":
|
||||
case "e":
|
||||
tag = nesting.pop();
|
||||
if (tag) {
|
||||
code.push('} else {');
|
||||
nesting.push(tag);
|
||||
} else {
|
||||
throw new Error("Unbalanced 'else' tag");
|
||||
}
|
||||
continue;
|
||||
|
||||
case "lb": // output left curly bracket '{'
|
||||
code.push('res.push("{");');
|
||||
continue;
|
||||
|
||||
case "rb": // output right curly bracket '}'
|
||||
code.push('res.push("}");');
|
||||
continue;
|
||||
|
||||
case "!": // comment
|
||||
continue;
|
||||
}
|
||||
} else if (token[1] == "/") { // close tag
|
||||
if (token[2] == ":") {
|
||||
var cmd = token.substring(3, token.length-1).split(" ")[0];
|
||||
|
||||
switch (cmd) {
|
||||
case "if":
|
||||
tag = nesting.pop();
|
||||
if (tag == "if") {
|
||||
code.push('};');
|
||||
} else {
|
||||
throw new Error("Unbalanced 'if' close tag" + (tag ? ", expecting '" + tag + "' close tag" : ""));
|
||||
}
|
||||
continue;
|
||||
|
||||
case "select":
|
||||
case "s":
|
||||
tag = nesting.pop();
|
||||
if (tag == "select") {
|
||||
stack.shift();
|
||||
code.push('};d = ' + stack[0] + ';');
|
||||
} else {
|
||||
throw new Error("Unbalanced 'select' close tag" + (tag ? ", expecting '" + tag + "' close tag" : ""));
|
||||
}
|
||||
continue;
|
||||
|
||||
case "reduce":
|
||||
case "r":
|
||||
tag = nesting.pop();
|
||||
if (tag == "reduce") {
|
||||
stack.shift();
|
||||
code.push('}; $last = false; d = ' + stack[0] + ';');
|
||||
} else {
|
||||
throw new Error("Unbalanced 'reduce' close tag" + (tag ? ", expecting '" + tag + "' close tag" : ""));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
} else if (token[1] == "=") { // interpolation
|
||||
var parts = token.substring(2, token.length-1).split(" "),
|
||||
pre = "", post = "";
|
||||
for (var j = 0; j < parts.length-1; j++) {
|
||||
pre += "filters." + parts[j] + "("; post += ")";
|
||||
}
|
||||
if (pre == "") {
|
||||
if (filters.defaultfilter) {
|
||||
pre = "df("; post = ")";
|
||||
}
|
||||
}
|
||||
code.push('v = ' + xpath(parts[j]) + ';if (v != undefined) res.push(' + pre + 'v' + post +');');
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// plain text
|
||||
code.push('res.push("' + token.replace(/\\/g, "\\\\").replace(/\r/g, "").replace(/\n/g, "\\n").replace(/"/g, '\\"') + '");');
|
||||
}
|
||||
|
||||
tag = nesting.pop();
|
||||
if (tag) {
|
||||
throw new Error("Unbalanced '" + tag + "' tag, is not closed");
|
||||
}
|
||||
|
||||
code.push('return res.join("");');
|
||||
|
||||
var func = new Function("data", "filters", code.join(""));
|
||||
|
||||
return function (data) { return func(data, filters) };
|
||||
}
|
||||
73
templates/haruki/publish.js
Normal file
73
templates/haruki/publish.js
Normal file
@ -0,0 +1,73 @@
|
||||
(function() {
|
||||
var fs = require('common/fs');
|
||||
|
||||
publish = function(docs, opts) { // global
|
||||
var classes;
|
||||
|
||||
classes = docs.doc.filter(function(element, index, array) {
|
||||
return (element.kind === 'constructor');
|
||||
});
|
||||
|
||||
// add properties and methods
|
||||
classes.forEach(function(classElement) {
|
||||
classElement.properties = docs.doc.filter(function(memberElement) {
|
||||
return (
|
||||
memberElement.kind === 'property'
|
||||
&& memberElement.memberof === classElement.path
|
||||
);
|
||||
});
|
||||
|
||||
classElement.methods = docs.doc.filter(function(memberElement) {
|
||||
return (
|
||||
memberElement.kind === 'method'
|
||||
&& memberElement.memberof === classElement.path
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
||||
|
||||
// templates!
|
||||
var normal = require('normal/template'),
|
||||
src = fs.read( BASEDIR + 'templates/haruki/tmpl/docs.json' ),
|
||||
template = normal.compile(src,
|
||||
{
|
||||
'filters': {
|
||||
'json': function(str) {
|
||||
return str.replace(/\\/g, "\\\\")
|
||||
.replace(/"/g, '\\"')
|
||||
.replace(/\f/g, "\\f")
|
||||
.replace(/\n/g, "\\n")
|
||||
.replace(/\r/g, "\\r")
|
||||
.replace(/\t/g, "\\t");
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
print( template( {classes: classes} ) );
|
||||
}
|
||||
|
||||
function getDoc(docpath) {
|
||||
var i, doc;
|
||||
|
||||
if ( doc = getDoc.cache[docpath] ) {
|
||||
return doc;
|
||||
}
|
||||
|
||||
i = docs.doc.length;
|
||||
while (i--) {
|
||||
if (docs.doc[i].path === docpath) {
|
||||
return docs.doc[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
getDoc.cache = {};
|
||||
|
||||
// helpers
|
||||
publish.summarize = function(desc) { // just the first line
|
||||
return /(.*)/.test(desc), RegExp.$1;
|
||||
}
|
||||
|
||||
})();
|
||||
22
templates/haruki/tmpl/docs.json
Normal file
22
templates/haruki/tmpl/docs.json
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"classes":{
|
||||
{:reduce classes}
|
||||
"{=name}": {
|
||||
"name": "{=name}",
|
||||
"properties":{{:reduce properties}
|
||||
"{=name}": {
|
||||
"name": "{=name}",
|
||||
"description": "{=json desc}"
|
||||
}{:if $last}{:else},{/:if}
|
||||
{/:reduce properties}},
|
||||
"methods":{{:reduce methods}
|
||||
"{=name}": {
|
||||
"name": "{=name}",
|
||||
"description": "{=json desc}"
|
||||
}{:if $last}{:else},{/:if}
|
||||
{/:reduce methods}},
|
||||
"description": "{=json desc}"
|
||||
}
|
||||
{/:reduce classes}
|
||||
}
|
||||
}
|
||||
@ -5,7 +5,7 @@
|
||||
(function(){
|
||||
var cache = {};
|
||||
|
||||
this.tmpl = function tmpl(/** templatefilename | templatesrc */str, data){ // templatefilename not contain `<`
|
||||
this.tmpl = function tmpl(/** templatefilename | templatesrc */str, data){ // templatefilename must not contain `<`, templatesrc must contain <
|
||||
var fn = str.indexOf('<') === -1 ?
|
||||
cache[str] = cache[str] || tmpl(readFile(str)) :
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user