crojsdoc
Version:
A documentation generator for JavaScript and CoffeeScript
291 lines (285 loc) • 7.75 kB
JavaScript
// Generated by CoffeeScript 1.8.0
(function() {
var dox;
dox = require('./dox');
exports.parseCommentsCoffee = function(coffee, options) {
var addBuf, addBufLine, addComment, buf, buf_line_number, comments, getCodeContext, ignore, indent, j, len, line_number, pos, raw;
if (options == null) {
options = {};
}
coffee = coffee.replace(/\r\n/gm, '\n');
comments = [];
raw = options.raw;
buf = '';
line_number = 1;
indent = void 0;
buf_line_number = void 0;
getCodeContext = function() {
var code, comment, i, indentre, line, lines, _i, _len;
lines = buf.split('\n');
while (lines.length > 0 && lines[0].trim() === '') {
lines.splice(0, 1);
buf_line_number++;
}
if (lines.length !== 0) {
indentre = new RegExp('^' + lines[0].match(/^(\s*)/)[1]);
for (i = _i = 0, _len = lines.length; _i < _len; i = ++_i) {
line = lines[i];
if (line.trim() === '') {
continue;
}
lines[i] = line = line.replace(indentre, '');
if (i !== 0 && !line.match(/^\s/)) {
break;
}
}
lines.length = i;
}
code = lines.join('\n').trim();
comment = comments[comments.length - 1];
if (comment) {
i = comments.length - 2;
while (i >= 0) {
if (comments[i].indent.search(comment.indent) < 0) {
break;
}
i--;
}
comment.ctx = exports.parseCodeContextCoffee(code, i >= 0 ? comments[i] : null);
comment.tags.forEach(function(tag) {
if (tag.type === 'class') {
comment.ctx || (comment.ctx = {});
comment.ctx.type = 'class';
}
});
if (comment.ctx && comment.ctx.type === 'class') {
comment.class_code = code;
comment.class_line_number = buf_line_number;
} else {
comment.code = code;
comment.line_number = buf_line_number;
}
}
return buf = '';
};
addBuf = function() {
buf += coffee[pos];
if ('\n' === coffee[pos]) {
line_number++;
return true;
}
return false;
};
addBufLine = function() {
var _results;
_results = [];
while (pos < len) {
if (addBuf()) {
break;
}
_results.push(pos++);
}
return _results;
};
addComment = function() {
var comment;
comment = dox.parseComment(buf, options);
comment.ignore = ignore;
comment.indent = indent;
comments.push(comment);
buf = '';
return buf_line_number = line_number;
};
pos = 0;
len = coffee.length;
while (pos < coffee.length) {
if (coffee.slice(pos, pos + 3) === '###') {
indent = buf.match(/([ \t]*)$/)[1];
getCodeContext();
pos += 3;
if ('\n' === coffee[pos]) {
line_number++;
}
ignore = '!' === coffee[pos];
pos++;
while (pos < len) {
if (coffee.slice(pos, pos + 3) === '###') {
pos += 3;
if ('\n' === coffee[pos]) {
line_number++;
}
buf = buf.replace(/^[ \t]*[\*\#] ?/gm, '');
addComment();
break;
}
addBuf();
pos++;
}
} else if ('#' === coffee[pos] && '#' === coffee[pos + 1]) {
indent = buf.match(/([ \t]*)$/)[1];
getCodeContext();
pos += 2;
ignore = '!' === coffee[pos];
if ('\n' === coffee[pos]) {
line_number++;
} else {
pos++;
addBufLine();
}
while (1) {
pos++;
j = pos;
while (j < len) {
if ('#' === coffee[j]) {
break;
}
if (' ' !== coffee[j] && '\t' !== coffee[j]) {
break;
}
j++;
}
if ('#' !== coffee[j]) {
buf = buf.replace(/^[ \t]*#{1,2} {0,2}/gm, '');
addComment();
pos--;
break;
}
addBufLine();
}
} else if ('#' === coffee[pos]) {
addBufLine();
} else {
addBuf();
}
pos++;
}
if (comments.length === 0) {
comments.push({
tags: [],
description: {
full: '',
summary: '',
body: ''
},
isPrivate: false
});
}
getCodeContext();
return comments;
};
exports.parseCodeContextCoffee = function(str, parent) {
var class_name;
str = str.split('\n')[0];
if (/^(\w+) *= *(\(.*\)|) *[-=]>/.exec(str)) {
return {
type: 'function',
name: RegExp.$1,
string: RegExp.$1 + '()'
};
} else if (/^(\w+)::(\w+) *= *(\(.*\)|) *[-=]>/.exec(str)) {
return {
type: 'method',
constructor: RegExp.$1,
cons: RegExp.$1,
name: RegExp.$2,
string: RegExp.$1 + '::' + RegExp.$2 + '()'
};
} else if (/^(\w+)::(\w+) *= *([^\n]+)/.exec(str)) {
return {
type: 'property',
constructor: RegExp.$1,
cons: RegExp.$1,
name: RegExp.$2,
value: RegExp.$3,
string: RegExp.$1 + '::' + RegExp.$2
};
} else if (/^[\w.]*?(\w+)\.(\w+) *= *(\(.*\)|) *[-=]>/.exec(str)) {
return {
type: 'method',
receiver: RegExp.$1,
name: RegExp.$2,
string: RegExp.$1 + '.' + RegExp.$2 + '()'
};
} else if (/^[\w.]*?(\w+)\.(\w+) *= *([^\n]+)/.exec(str)) {
return {
type: 'property',
receiver: RegExp.$1,
name: RegExp.$2,
value: RegExp.$3,
string: RegExp.$1 + '.' + RegExp.$2
};
} else if (/^(\w+) *= *([^\n]+)/.exec(str)) {
return {
type: 'declaration',
name: RegExp.$1,
value: RegExp.$2,
string: RegExp.$1
};
}
if (parent && parent.ctx && parent.ctx.type === 'class') {
class_name = parent.ctx.name;
}
if (/\bclass +(\w+)/.exec(str)) {
return {
type: 'class',
name: RegExp.$1,
string: 'class ' + RegExp.$1
};
} else if (/^(\w+) *: *(\(.*\)|) *[-=]>/.exec(str)) {
if (class_name) {
return {
type: 'method',
constructor: class_name,
cons: class_name,
name: RegExp.$1,
string: class_name + '::' + RegExp.$1 + '()',
is_coffeescript_constructor: RegExp.$1 === 'constructor'
};
} else {
return {
type: 'method',
name: RegExp.$1,
string: RegExp.$1 + '()'
};
}
} else if (/^(\w+) *: *([^\n]+)/.exec(str)) {
if (class_name) {
return {
type: 'property',
constructor: class_name,
cons: class_name,
name: RegExp.$1,
value: RegExp.$2,
string: class_name + '::' + RegExp.$1
};
} else {
return {
type: 'property',
name: RegExp.$1,
value: RegExp.$2,
string: RegExp.$1
};
}
} else if (!class_name) {
} else if (/^@(\w+) *: *(\(.*\)|) *[-=]>/.exec(str)) {
return {
type: 'method',
receiver: class_name,
name: RegExp.$1,
string: class_name + '.' + RegExp.$1 + '()'
};
} else if (/^@(\w+) *: *([^\n]+)/.exec(str)) {
return {
type: 'property',
receiver: class_name,
name: RegExp.$1,
value: RegExp.$2,
string: class_name + '.' + RegExp.$1
};
} else {
return {
class_name: class_name
};
}
};
}).call(this);