UNPKG

savvy-js

Version:

Savvy - Style sheet documentation tool

227 lines (198 loc) 7.09 kB
(function(){ 'use strict'; var lineExpression = /\n/gm, nameExpression = /^\s*[a-zA-z_-]*/, commentExpression = /\/\*{2}([\s\S]+?)\*\//gm, argumentExpression = /\*\s{0,3}@/g, statementTypes = ['class', 'module', 'submodule', 'stateof', 'parent', 'comment']; /** * Extract all documentation comment blocks from a file and return them as array. * * CommentBlock is an object that contains the line number, index, abd the comment string: * * { * line : number, // The line number in the style document where the comments begins * index : number, // The character index in the style document where the comments begins * comment : string // The comment itself. * } * * @method extractComments * @param {string} document - The document (style file content) in which to look for comments. * @returns {commentBlock[]} a list of comments that were extracted from the document */ function extractComments(document){ var comments = [], lines = extractLines(document), lastLineIndex = 0, match; while(match = commentExpression.exec(document)) { while(lines[lastLineIndex] <= match.index){ lastLineIndex++; } comments.push({ line : lastLineIndex + 1, index : match.index, comment : match[1] }); } return comments; } /** * Remove the opening and closing of a comment * * @method trimComment * @param {string} comment */ function trimComment(comment){ var closingIndex = comment.lastIndexOf('*/'); closingIndex = closingIndex === -1 ? comment.length - 1 : closingIndex; comment = comment.substring(0, closingIndex).replace('/**', ''); return comment; } /** * Get array of line indexes from a document. * * @method extractLines * @param {string} document - The document (style file content) in which to look for lines. * @returns {Array} a list of line break indexes. * @private */ function extractLines(document){ var lines = [], line; while(line = lineExpression.exec(document)){ lines.push(line.index); } return lines; } /** * Parse a comment into an object * * @method parseComment * @type {function( comment : commentBlock )} * @returns [] */ function parseComment(commentBlock){ var result = { description : [], line : commentBlock.line }, rawArguments = trimComment(commentBlock.comment).split(argumentExpression), statementType, statement; rawArguments.forEach(function(statementString){ statement = parseStatement(statementString); if(statement.type === 'comment'){ result.description = [].concat(result.description, statement.description); } else{ statementType = statement.type; delete statement.type; result[statementType] = statement; } }); return result; } /** * Parse a statement within a comment. For example, convert * * @class myStuff * * To * * { type : 'class', name : 'myStuff', description : [] } * * @param {string} statement */ function parseStatement(statement){ var lines = statement.split(lineExpression), currentParagraph = null, result = { type : null, name : null, description : [] }; function setStatementType(line, index){ if(index === 0){ result.type = findStatementType(line); if(result.type !== 'comment' || line.indexOf(result.type) > -1) { line = line.substring(line.indexOf(result.type) + result.type.length); } } return line; } function setStatementName(line, index){ var match; if(index === 0 && result.type !== 'comment'){ match = line.match(nameExpression); if(match){ line = line.substring(match[0].length); result.name = match[0].trim(); } } return line; } function setStatementDescription(line, index){ var description = { type : 'text', text : '' }; line = removeLeadingAstrix(line); if(line) { if(line.indexOf(' ') === 0){ description.type = 'code'; description.text = line; } else{ description.text = line.trim(); } result.description.push(description); } else if(index > 0 && result.description.length > 0){ description.type = 'paragraph'; result.description.push(description); } } // remove the astrix from the beginning of the line function removeLeadingAstrix(line){ line = line.replace(/^(\s)*\*+/, ''); // remove spaces, unless its at least 4 spaces then it's a code description if(line.indexOf(' ') !== 0){ line = line.replace(/^(\s)*/, ''); } return line; } lines.forEach(function(line, index){ if(index === 0) { line = removeLeadingAstrix(line); line = setStatementType(line, index); line = setStatementName(line, index); } setStatementDescription(line, index); }); return result; } /** * Take a line, and find out if it starts with a known statement. * * @method findStatementType * @param {string} line - a line of text from the comment */ function findStatementType(line){ var result = 'comment', tokenExpression; statementTypes.forEach(function(statementType){ tokenExpression = new RegExp('^[@]?' + statementType + '\\s', 'i'); if(line.match(tokenExpression)){ result = statementType; return false; // break forEach loop } }); return result; } module.exports = { extractComments : extractComments, parseComment : parseComment, parseStatement : parseStatement }; }());