Comparing version 2.1.4 to 2.2.0
@@ -7,2 +7,6 @@ #!/usr/bin/env node | ||
function list(val) { | ||
return val.split(','); | ||
} | ||
program | ||
@@ -12,4 +16,5 @@ .description(pkg.description) | ||
.usage('[options] <file ...>') | ||
.option('-r, --reporter [reporter]', 'use reporter (table|json|xml|markdown|raw) (Default: table)', 'table') | ||
.option('-t, --filetype [filetype]', 'force the filetype to parse. Useful for streams (Default: .js)') | ||
.option('-r, --reporter [reporter]', 'use reporter (table|json|xml|markdown|raw) (default: table)', 'table') | ||
.option('-t, --filetype [filetype]', 'force the filetype to parse. Useful for streams (default: .js)') | ||
.option('-T, --tags <tags>', 'add additional comment types to find (alongside todo & fixme)', list, []) | ||
.on('--help', function () { | ||
@@ -30,2 +35,5 @@ console.log(' Examples:'); | ||
console.log(''); | ||
console.log(' # Search for REVIEW comments as well'); | ||
console.log(' $ leasot --tags review index.js'); | ||
console.log(''); | ||
console.log(' # Export TODOS as markdown to a TODO.md file'); | ||
@@ -32,0 +40,0 @@ console.log(' $ leasot --reporter markdown app/**/*.py > TODO.md'); |
@@ -11,14 +11,12 @@ var fs = require('fs'); | ||
function outputReport(reporter, todos) { | ||
try { | ||
var output = leasot.reporter(todos, { | ||
reporter: reporter | ||
}); | ||
console.log(output); | ||
} catch (e) { | ||
console.log(logSymbols.error, e.toString()); | ||
} | ||
function getFiletype(specified, file) { | ||
return specified || path.extname(file) || DEFAULT_EXTENSION; | ||
} | ||
function parseContents(filetype, contents, file) { | ||
function run(contents, params) { | ||
params = params || {}; | ||
var file = params.file; | ||
var filetype = getFiletype(params.filetype, file); | ||
var tags = params.tags; | ||
if (!leasot.isExtSupported(filetype)) { | ||
@@ -28,19 +26,15 @@ console.log(logSymbols.error, 'Filetype ' + filetype + ' is unsupported.'); | ||
} | ||
var todos = leasot.parse(filetype, contents, file); | ||
return todos; | ||
return leasot.parse(filetype, contents, file, tags); | ||
} | ||
function run(contents, params) { | ||
params = params || {}; | ||
var file = params.file; | ||
var filetype = params.filetype || path.extname(file) || DEFAULT_EXTENSION; | ||
return parseContents(filetype, contents, file); | ||
} | ||
function outputTodos(todos, reporter) { | ||
outputReport(reporter, todos); | ||
if (!todos.length) { | ||
process.exit(0); | ||
try { | ||
var output = leasot.reporter(todos, { | ||
reporter: reporter | ||
}); | ||
console.log(output); | ||
} catch (e) { | ||
console.log(logSymbols.error, e.toString()); | ||
} | ||
process.exit(1); | ||
process.exit(todos.length ? 1 : 0); | ||
} | ||
@@ -50,2 +44,4 @@ | ||
var files = program.args; | ||
var tags = program.tags; | ||
var filetype = program.filetype; | ||
// Get all files and their resolved globs | ||
@@ -65,5 +61,7 @@ files = files.reduce(function (newFiles, file) { | ||
var cwd = process.cwd(); | ||
// Async read all of the given files | ||
mapAsync(files, function (file, cb) { | ||
fs.readFile(path.resolve(process.cwd(), file), 'utf8', cb); | ||
fs.readFile(path.resolve(cwd, file), 'utf8', cb); | ||
}, function (err, results) { | ||
@@ -77,3 +75,4 @@ if (err) { | ||
file: files[i], | ||
filetype: program.filetype | ||
filetype: filetype, | ||
tags: tags | ||
}); | ||
@@ -94,3 +93,4 @@ }).filter(function (item) { | ||
var todos = run(contents, { | ||
filetype: program.filetype | ||
filetype: program.filetype, | ||
tags: program.tags | ||
}); | ||
@@ -97,0 +97,0 @@ outputTodos(todos, program.reporter); |
'use strict'; | ||
var getParser = { | ||
var parsers = { | ||
'.js': function () { | ||
@@ -82,26 +82,17 @@ return require('./parsers/defaultParser'); | ||
function isExtSupported(ext) { | ||
return Boolean(getParser[ext]); | ||
return Boolean(parsers[ext]); | ||
} | ||
function getMappedComment(comment, file) { | ||
return { | ||
file: file || 'unknown file', | ||
text: comment.text.trim(), | ||
kind: comment.kind.toUpperCase(), | ||
line: comment.line | ||
}; | ||
} | ||
function mapComments(comments, file) { | ||
return comments.map(function (comment) { | ||
return getMappedComment(comment, file); | ||
}); | ||
} | ||
function parse(ext, contents, file) { | ||
function parse(ext, contents, file, customTags) { | ||
if (!isExtSupported(ext)) { | ||
throw Error('extension ' + ext + ' is not supported.'); | ||
throw new Error('extension ' + ext + ' is not supported.'); | ||
} | ||
var comments = getParser[ext]()(contents); | ||
return mapComments(comments, file); | ||
if (customTags && !Array.isArray(customTags)) { | ||
throw new TypeError('`customTags` must be an array'); | ||
} | ||
var parseOptions = { | ||
customTags: customTags | ||
}; | ||
var parser = parsers[ext]()(parseOptions); | ||
return parser(contents, file); | ||
} | ||
@@ -108,0 +99,0 @@ |
'use strict'; | ||
var regex = require('../regex'); | ||
var commentsRegex = new RegExp('^\\s*#' + regex + '$', 'mig'); | ||
var commentsUtil = require('../utils/comments'); | ||
module.exports = function (contents) { | ||
var lines = contents.split('\n'); | ||
module.exports = function (params) { | ||
params = params || {}; | ||
var regex = commentsUtil.getRegex(params.customTags); | ||
var commentsRegex = new RegExp('^\\s*#' + regex + '$', 'mig'); | ||
var comments = []; | ||
lines.forEach(function (line, index) { | ||
var match = commentsRegex.exec(line); | ||
while (match) { | ||
if (!match || !match.length) { | ||
break; | ||
return function parse(contents, file) { | ||
var comments = []; | ||
contents.split('\n').forEach(function (line, index) { | ||
var match = commentsRegex.exec(line); | ||
var comment = commentsUtil.prepareComment(match, index + 1, file); | ||
if (!comment) { | ||
return; | ||
} | ||
//verify kind exists | ||
if (!match[1]) { | ||
break; | ||
} | ||
comments.push({ | ||
kind: match[1], | ||
text: match[2].trim(), | ||
line: index + 1 | ||
}); | ||
match = commentsRegex.exec(line); | ||
} | ||
}); | ||
return comments; | ||
comments.push(comment); | ||
}); | ||
return comments; | ||
}; | ||
}; |
'use strict'; | ||
var getLineFromPos = require('get-line-from-pos'); | ||
var regex = require('../regex'); | ||
var rLineComment = new RegExp('^\\s*\\/\\/' + regex + '$', 'mig'); | ||
var commentsUtil = require('../utils/comments'); | ||
var rBlockComment = /\/\*(?:[\s\S]*?)\*\//gmi; | ||
var rInnerBlock = new RegExp('^\\s*(?:\\/\\*)?\\**!?' + regex + '(?:\\**\\/)?$', 'mig'); | ||
module.exports = function (contents) { | ||
var comments = []; | ||
module.exports = function (params) { | ||
params = params || {}; | ||
var regex = commentsUtil.getRegex(params.customTags); | ||
var rLineComment = new RegExp('^\\s*\\/\\/' + regex + '$', 'mig'); | ||
var rInnerBlock = new RegExp('^\\s*(?:\\/\\*)?\\**!?' + regex + '(?:\\**\\/)?$', 'mig'); | ||
contents.split('\n').forEach(function (line, index) { | ||
var match = rLineComment.exec(line); | ||
return function parse(contents, file) { | ||
var comments = []; | ||
contents.split('\n').forEach(function (line, index) { | ||
var match = rLineComment.exec(line); | ||
while (match) { | ||
var comment = commentsUtil.prepareComment(match, index + 1, file); | ||
if (!comment) { | ||
break; | ||
} | ||
comments.push(comment); | ||
match = rLineComment.exec(line); | ||
} | ||
}); | ||
//look for block comments | ||
var match = rBlockComment.exec(contents); | ||
while (match) { | ||
@@ -19,50 +34,27 @@ if (!match || !match.length) { | ||
} | ||
//verify kind and text exists | ||
if (!match[1]) { | ||
break; | ||
} | ||
comments.push({ | ||
kind: match[1], | ||
text: match[2].trim(), | ||
line: index + 1 | ||
//use first match as basis to look into todos/fixmes | ||
var baseMatch = match[0]; | ||
// jshint loopfunc:true | ||
baseMatch.split('\n').forEach(function (line, index) { | ||
var subMatch = rInnerBlock.exec(line); | ||
while (subMatch) { | ||
var adjustedLine = getLineFromPos(contents, match.index) + index; | ||
var comment = commentsUtil.prepareComment(subMatch, adjustedLine, file); | ||
if (!comment) { | ||
break; | ||
} | ||
comments.push(comment); | ||
subMatch = rInnerBlock.exec(line); | ||
} | ||
}); | ||
match = rLineComment.exec(line); | ||
match = rBlockComment.exec(contents); | ||
} | ||
}); | ||
// sort by line number | ||
comments = comments.sort(function (a, b) { | ||
return a.line - b.line; | ||
}); | ||
//look for block comments | ||
var match = rBlockComment.exec(contents); | ||
while (match) { | ||
if (!match || !match.length) { | ||
break; | ||
} | ||
//use first match as basis to look into todos/fixmes | ||
var baseMatch = match[0]; | ||
// jshint loopfunc:true | ||
baseMatch.split('\n').forEach(function (line, index) { | ||
var subMatch = rInnerBlock.exec(line); | ||
while (subMatch) { | ||
if (!subMatch || !subMatch.length) { | ||
break; | ||
} | ||
//verify kind and text exists | ||
if (!subMatch[1]) { | ||
break; | ||
} | ||
comments.push({ | ||
kind: subMatch[1], | ||
text: subMatch[2].trim(), | ||
line: getLineFromPos(contents, match.index) + index | ||
}); | ||
subMatch = rInnerBlock.exec(line); | ||
} | ||
}); | ||
match = rBlockComment.exec(contents); | ||
return comments; | ||
} | ||
// sort by line number | ||
comments = comments.sort(function (a, b) { | ||
return a.line - b.line; | ||
}); | ||
return comments; | ||
}; |
'use strict'; | ||
var regex = require('../regex'); | ||
var commentsRegex = new RegExp('{{!(?:--)?' + regex + '(?:--)?}}', 'mig'); | ||
var commentsUtil = require('../utils/comments'); | ||
module.exports = function (contents) { | ||
var comments = []; | ||
contents.split('\n').forEach(function (line, index) { | ||
var match = commentsRegex.exec(line); | ||
while (match) { | ||
if (!match || !match.length) { | ||
break; | ||
module.exports = function (params) { | ||
params = params || {}; | ||
var regex = commentsUtil.getRegex(params.customTags); | ||
var commentsRegex = new RegExp('{{!(?:--)?' + regex + '(?:--)?}}', 'mig'); | ||
return function parse(contents, file) { | ||
var comments = []; | ||
contents.split('\n').forEach(function (line, index) { | ||
var match = commentsRegex.exec(line); | ||
while (match) { | ||
var comment = commentsUtil.prepareComment(match, index + 1, file); | ||
if (!comment) { | ||
break; | ||
} | ||
comments.push(comment); | ||
match = commentsRegex.exec(line); | ||
} | ||
//verify kind exists | ||
if (!match[1]) { | ||
break; | ||
} | ||
comments.push({ | ||
kind: match[1], | ||
text: match[2].trim(), | ||
line: index + 1 | ||
}); | ||
match = commentsRegex.exec(line); | ||
} | ||
}); | ||
return comments; | ||
}); | ||
return comments; | ||
}; | ||
}; |
'use strict'; | ||
var regex = require('../regex'); | ||
var commentsRegex = new RegExp('^\\s*\\/\\/-?' + regex + '$', 'mig'); | ||
var commentsUtil = require('../utils/comments'); | ||
module.exports = function (contents) { | ||
var comments = []; | ||
contents.split('\n').forEach(function (line, index) { | ||
var match = commentsRegex.exec(line); | ||
if (!match || !match.length) { | ||
return; | ||
} | ||
//verify kind exists | ||
if (!match[1]) { | ||
return; | ||
} | ||
comments.push({ | ||
kind: match[1], | ||
text: match[2].trim(), | ||
line: index + 1 | ||
module.exports = function (params) { | ||
params = params || {}; | ||
var regex = commentsUtil.getRegex(params.customTags); | ||
var commentsRegex = new RegExp('^\\s*\\/\\/-?' + regex + '$', 'mig'); | ||
return function parse(contents, file) { | ||
var comments = []; | ||
contents.split('\n').forEach(function (line, index) { | ||
var match = commentsRegex.exec(line); | ||
var comment = commentsUtil.prepareComment(match, index + 1, file); | ||
if (!comment) { | ||
return; | ||
} | ||
comments.push(comment); | ||
}); | ||
}); | ||
return comments; | ||
return comments; | ||
}; | ||
}; |
'use strict'; | ||
var regex = require('../regex'); | ||
var commentsUtil = require('../utils/comments'); | ||
var commentsRegex = new RegExp('^\\s*#' + regex + '$', 'mig'); | ||
var multiLineRegex = new RegExp('^\\s*"""' + regex + '"""$', 'mig'); | ||
module.exports = function (params) { | ||
params = params || {}; | ||
var regex = commentsUtil.getRegex(params.customTags); | ||
var commentsRegex = new RegExp('^\\s*#' + regex + '$', 'mig'); | ||
var multiLineRegex = new RegExp('^\\s*"""' + regex + '"""$', 'mig'); | ||
module.exports = function (contents) { | ||
var comments = []; | ||
contents.split('\n').forEach(function (line, index) { | ||
var hashMatch = commentsRegex.exec(line); | ||
while (hashMatch) { | ||
if (!hashMatch || !hashMatch.length) { | ||
break; | ||
return function parse(contents, file) { | ||
var comments = []; | ||
contents.split('\n').forEach(function (line, index) { | ||
var hashMatch = commentsRegex.exec(line); | ||
var comment; | ||
while (hashMatch) { | ||
comment = commentsUtil.prepareComment(hashMatch, index + 1, file); | ||
if (!comment) { | ||
break; | ||
} | ||
comments.push(comment); | ||
hashMatch = commentsRegex.exec(line); | ||
} | ||
//verify kind exists | ||
if (!hashMatch[1]) { | ||
break; | ||
var multiLineMatch = multiLineRegex.exec(line); | ||
while (multiLineMatch) { | ||
comment = commentsUtil.prepareComment(multiLineMatch, index + 1, file); | ||
if (!comment) { | ||
break; | ||
} | ||
comments.push(comment); | ||
multiLineMatch = multiLineRegex.exec(line); | ||
} | ||
comments.push({ | ||
kind: hashMatch[1], | ||
text: hashMatch[2].trim(), | ||
line: index + 1 | ||
}); | ||
hashMatch = commentsRegex.exec(line); | ||
} | ||
}); | ||
// sort by line number | ||
comments = comments.sort(function (a, b) { | ||
return a.line - b.line; | ||
}); | ||
return comments; | ||
var multiLineMatch = multiLineRegex.exec(line); | ||
while (multiLineMatch) { | ||
if (!multiLineMatch || !multiLineMatch.length) { | ||
break; | ||
} | ||
//verify kind exists | ||
if (!multiLineMatch[1]) { | ||
break; | ||
} | ||
comments.push({ | ||
kind: multiLineMatch[1], | ||
text: multiLineMatch[2].trim(), | ||
line: index + 1 | ||
}); | ||
multiLineMatch = multiLineRegex.exec(line); | ||
} | ||
}); | ||
// sort by line number | ||
comments = comments.sort(function (a, b) { | ||
return a.line - b.line; | ||
}); | ||
return comments; | ||
}; | ||
}; |
'use strict'; | ||
var regex = require('../regex'); | ||
var commentsUtil = require('../utils/comments'); | ||
var bangComment = new RegExp('{#' + regex + '#}', 'mig'); | ||
var htmlComment = new RegExp('<!--' + regex + '-->', 'mig'); | ||
module.exports = function (params) { | ||
params = params || {}; | ||
var regex = commentsUtil.getRegex(params.customTags); | ||
var bangComment = new RegExp('{#' + regex + '#}', 'mig'); | ||
var htmlComment = new RegExp('<!--' + regex + '-->', 'mig'); | ||
module.exports = function (contents) { | ||
var comments = []; | ||
contents.split('\n').forEach(function (line, index) { | ||
var bangCommentMatch = bangComment.exec(line); | ||
while (bangCommentMatch) { | ||
if (!bangCommentMatch || !bangCommentMatch.length) { | ||
break; | ||
return function parse(contents, file) { | ||
var comments = []; | ||
contents.split('\n').forEach(function (line, index) { | ||
var bangCommentMatch = bangComment.exec(line); | ||
var comment; | ||
while (bangCommentMatch) { | ||
comment = commentsUtil.prepareComment(bangCommentMatch, index + 1, file); | ||
if (!comment) { | ||
break; | ||
} | ||
comments.push(comment); | ||
bangCommentMatch = bangComment.exec(line); | ||
} | ||
//verify kind exists | ||
if (!bangCommentMatch[1]) { | ||
break; | ||
var htmlCommentMatch = htmlComment.exec(line); | ||
while (htmlCommentMatch) { | ||
comment = commentsUtil.prepareComment(htmlCommentMatch, index + 1, file); | ||
if (!comment) { | ||
break; | ||
} | ||
comments.push(comment); | ||
htmlCommentMatch = htmlComment.exec(line); | ||
} | ||
comments.push({ | ||
kind: bangCommentMatch[1], | ||
text: bangCommentMatch[2].trim(), | ||
line: index + 1 | ||
}); | ||
bangCommentMatch = bangComment.exec(line); | ||
} | ||
}); | ||
// sort by line number | ||
comments = comments.sort(function (a, b) { | ||
return a.line - b.line; | ||
}); | ||
return comments; | ||
var htmlCommentMatch = htmlComment.exec(line); | ||
while (htmlCommentMatch) { | ||
if (!htmlCommentMatch || !htmlCommentMatch.length) { | ||
break; | ||
} | ||
//verify kind exists | ||
if (!htmlCommentMatch[1]) { | ||
break; | ||
} | ||
comments.push({ | ||
kind: htmlCommentMatch[1], | ||
text: htmlCommentMatch[2].trim(), | ||
line: index + 1 | ||
}); | ||
htmlCommentMatch = htmlComment.exec(line); | ||
} | ||
}); | ||
// sort by line number | ||
comments = comments.sort(function (a, b) { | ||
return a.line - b.line; | ||
}); | ||
return comments; | ||
}; | ||
}; |
{ | ||
"name": "leasot", | ||
"description": "Parse and output TODOs and FIXMEs from comments in your files", | ||
"version": "2.1.4", | ||
"version": "2.2.0", | ||
"author": "Gilad Peleg <giladp007@gmail.com> (http://giladpeleg.com)", | ||
@@ -6,0 +6,0 @@ "bin": "./bin/leasot.js", |
@@ -23,3 +23,4 @@ ![leasot](media/leasot.png) | ||
- Spaces are trimmed around comment text. | ||
- Supported types are `TODO` and `FIXME` - case insensitive. | ||
- Supported default types are `TODO` and `FIXME` - case insensitive. | ||
- Additional types can be added (using `tags` in cli and `customTags` in `leasot.parse`) | ||
@@ -60,3 +61,3 @@ ## Supported languages: | ||
```bash | ||
```sh | ||
$ npm install --global leasot | ||
@@ -67,3 +68,3 @@ ``` | ||
```bash | ||
```sh | ||
❯ leasot --help | ||
@@ -79,4 +80,5 @@ | ||
-V, --version output the version number | ||
-r, --reporter [reporter] use reporter (table|json|xml|markdown|raw) (Default: table) | ||
-t, --filetype [filetype] force the filetype to parse. Useful for streams (Default: .js) | ||
-r, --reporter [reporter] use reporter (table|json|xml|markdown|raw) (default: table) | ||
-t, --filetype [filetype] force the filetype to parse. Useful for streams (default: .js) | ||
-T, --tags <tags> add additional comment types to find (alongside todo & fixme) | ||
@@ -97,2 +99,5 @@ Examples: | ||
# Search for REVIEW comments as well | ||
$ leasot --tags review index.js | ||
# Export TODOS as markdown to a TODO.md file | ||
@@ -109,3 +114,3 @@ $ leasot --reporter markdown app/**/*.py > TODO.md | ||
```bash | ||
```sh | ||
$ npm install --save-dev leasot | ||
@@ -160,3 +165,3 @@ ``` | ||
### .parse(extension, contents, filename) | ||
### .parse(extension, contents, filename, customTags) | ||
@@ -172,2 +177,4 @@ Parse the contents, using the provided `extension`. `filename` will be attached | ||
`customTags` is an optional array with additional tags (comment types) to search for (alongside todo & fixme). | ||
**Returns**: `Array` of comments. | ||
@@ -174,0 +181,0 @@ |
32685
334
644