UNPKG

crojsdoc

Version:

A documentation generator for JavaScript and CoffeeScript

229 lines (220 loc) 6.59 kB
// Generated by CoffeeScript 1.8.0 (function() { var escape, markdown; markdown = require('marked'); escape = require('./utils').escape; exports.parseComments = function(js, options) { var buf, code, comment, comments, i, ignore, len, raw, withinMultiline, withinSingle; if (options == null) { options = {}; } js = js.replace(/\r\n/gm, '\n'); comments = []; raw = options.raw; buf = ''; withinMultiline = false; withinSingle = false; i = 0; len = js.length; while (i < len) { if (!withinMultiline && !withinSingle && '/' === js[i] && '*' === js[i + 1]) { if (buf.trim().length) { comment = comments[comments.length - 1]; if (comment) { comment.code = code = buf.trim(); comment.ctx = exports.parseCodeContext(code); } buf = ''; } i += 2; withinMultiline = true; ignore = '!' === js[i]; } else if (withinMultiline && !withinSingle && '*' === js[i] && '/' === js[i + 1]) { i += 2; buf = buf.replace(/^[ \t]*\* ?/gm, ''); comment = exports.parseComment(buf, options); comment.ignore = ignore; comments.push(comment); withinMultiline = ignore = false; buf = ''; } else if (!withinSingle && !withinMultiline && '/' === js[i] && '/' === js[i + 1]) { withinSingle = true; buf += js[i]; } else if (withinSingle && !withinMultiline && '\n' === js[i]) { withinSingle = false; buf += js[i]; } else { buf += js[i]; } i++; } if (comments.length === 0) { comments.push({ tags: [], description: { full: '', summary: '', body: '' }, isPrivate: false }); } if (buf.trim().length) { comment = comments[comments.length - 1]; code = buf.trim(); comment.code = code; comment.ctx = exports.parseCodeContext(code); } return comments; }; exports.parseComment = function(str, options) { var comment, description, raw, tags; if (options == null) { options = {}; } str = str.trim(); comment = { tags: [] }; raw = options.raw; description = {}; if (str[0] === '@') { str = '\n' + str; } description.full = str.split('\n@')[0]; description.summary = description.full.split('\n\n')[0]; description.body = description.full.split('\n\n').slice(1).join('\n\n'); comment.description = description; if (~str.indexOf('\n@')) { tags = '@' + str.split('\n@').slice(1).join('\n@'); comment.tags = tags.split('\n').map(exports.parseTag); comment.isPrivate = comment.tags.some(function(tag) { return 'api' === tag.type && 'private' === tag.visibility; }); } if (!raw) { description.full = markdown(description.full); description.summary = markdown(description.summary); description.body = markdown(description.body); } return comment; }; exports.parseTag = function(str) { var parts, tag, type; tag = {}; parts = str.split(/\ +/); type = tag.type = parts.shift().replace('@', '').toLowerCase(); switch (type) { case 'param': tag.types = /{.*}/.test(parts[0]) ? exports.parseTagTypes(parts.shift()) : []; tag.name = parts.shift() || ''; tag.description = parts.join(' '); break; case 'return': tag.types = /{.*}/.test(parts[0]) ? exports.parseTagTypes(parts.shift()) : []; tag.description = parts.join(' '); break; case 'see': if (~str.indexOf('http')) { tag.title = parts.length > 1 ? parts.shift() : ''; tag.url = parts.join(' '); } else { tag.local = parts.join(' '); } break; case 'api': tag.visibility = parts.shift(); break; case 'type': tag.types = exports.parseTagTypes(parts.shift()); break; case 'memberof': tag.parent = parts.shift(); break; case 'augments': tag.otherClass = parts.shift(); break; case 'borrows': tag.otherMemberName = parts.join(' ').split(' as ')[0]; tag.thisMemberName = parts.join(' ').split(' as ')[1]; break; case 'throws': tag.string = parts.join(' '); break; default: tag.string = parts.join(' '); } return tag; }; exports.parseTagTypes = function(str) { return str.replace(/[{}]/g, '').split(/\ *[|,\/] */); }; exports.parseCodeContext = function(str) { str = str.split('\n')[0]; if (/^function (\w+) *\(/.exec(str)) { return { type: 'function', name: RegExp.$1, string: RegExp.$1 + '()' }; } else if (/^var *(\w+)[ \t]*=[ \t]*function/.exec(str)) { return { type: 'function', name: RegExp.$1, string: RegExp.$1 + '()' }; } else if (/^(\w+)\.prototype\.(\w+)[ \t]*=[ \t]*function/.exec(str)) { return { type: 'method', constructor: RegExp.$1, cons: RegExp.$1, name: RegExp.$2, string: RegExp.$1 + '.prototype.' + RegExp.$2 + '()' }; } else if (/^(\w+)\.prototype\.(\w+)[ \t]*=[ \t]*([^\n;]+)/.exec(str)) { return { type: 'property', constructor: RegExp.$1, cons: RegExp.$1, name: RegExp.$2, value: RegExp.$3, string: RegExp.$1 + '.prototype.' + RegExp.$2 }; } else if (/^([\w.]+)\.(\w+)[ \t]*=[ \t]*function/.exec(str)) { return { type: 'method', receiver: RegExp.$1, name: RegExp.$2, string: RegExp.$1 + '.' + RegExp.$2 + '()' }; } else if (/^(\w+)\.(\w+)[ \t]*=[ \t]*([^\n;]+)/.exec(str)) { return { type: 'property', receiver: RegExp.$1, name: RegExp.$2, value: RegExp.$3, string: RegExp.$1 + '.' + RegExp.$2 }; } else if (/^var +(\w+)[ \t]*=[ \t]*([^\n;]+)/.exec(str)) { return { type: 'declaration', name: RegExp.$1, value: RegExp.$2, string: RegExp.$1 }; } else if (/^(\w+) *: *function/.exec(str)) { return { type: 'method', name: RegExp.$1, string: RegExp.$1 + '()' }; } else if (/^(\w+) *: *([^\n;]+)/.exec(str)) { return { type: 'property', name: RegExp.$1, value: RegExp.$2, string: RegExp.$1 }; } }; }).call(this);