Socket
Socket
Sign inDemoInstall

extract-comments

Package Overview
Dependencies
Maintainers
1
Versions
27
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

extract-comments - npm Package Compare versions

Comparing version 0.8.4 to 0.8.5

284

index.js

@@ -8,194 +8,102 @@ 'use strict';

/**
* Get the first block comment from the given string
* Extract comments from the given `string`.
*
* ```js
* extract(str, options);
* ```
* @param {String} `string`
* @param {Object} `options` Pass `first: true` to return after the first comment is found.
* @return {String}
* @api public
*/
function first(str) {
function comments(str, options, fn) {
if (typeof str !== 'string') {
throw new TypeError('expected a string');
}
str = utils.normalize(str);
if (!/^\/\*{1,2}!?/.test(str)) {
return null;
}
var i = str.indexOf('*/');
if (i === -1) return null;
if (/['"\w]/.test(str[i + 2])) {
return null;
}
return str.slice(0, i + 2);
return block(str, options, fn)
.concat(line(str, options, fn))
.sort(compare);
}
/**
* Get block and line comments from the given string
* Extract block comments from the given `string`.
*
* ```js
* extract.block(str, options);
* ```
* @param {String} `string`
* @param {Object} `options` Pass `first: true` to return after the first comment is found.
* @return {String}
* @api public
*/
function comments(str, options, fn) {
if (typeof str !== 'string') {
throw new TypeError('expected a string');
}
function block(str, options, fn) {
return factory('/*', '*/', Block)(str, options, fn);
}
if (typeof options === 'function') {
fn = options;
options = {};
}
if (typeof fn !== 'function') {
fn = utils.identity;
}
var ranges = utils.getRanges(str);
var opts = extend({}, options);
str = utils.normalize(str);
var arr = [];
var start = findStart('/*');
var end = findEnd('*/');
var len = str.length;
var startIdx = start(str, 0);
var endIdx = 0, prevIdx;
while (startIdx !== -1 && endIdx < len) {
endIdx = end(str, startIdx, len);
if (endIdx === -1) break;
var quoted = utils.isQuotedString(startIdx, ranges);
if (quoted) {
startIdx = endIdx;
continue;
}
if (typeof prevIdx === 'number' && opts.line !== false) {
if (typeof opts.combine === 'undefined') {
opts.combine = true;
}
var nonblock = str.slice(prevIdx, startIdx);
var lineComments = line(nonblock, opts, fn);
arr = arr.concat(lineComments);
}
var comment = fn(new Block(str, startIdx, endIdx));
arr.push(comment);
if (opts.first && arr.length === 1) {
return arr;
}
prevIdx = endIdx + 2;
startIdx = start(str, prevIdx);
if (startIdx >= len) break;
}
if (!arr.length) {
return line(str, opts, fn);
}
return arr;
}
/**
* Get block comments from the given string
* Extract line comments from the given `string`.
*
* ```js
* extract.line(str, options);
* ```
* @param {String} `string`
* @param {Object} `options` Pass `first: true` to return after the first comment is found.
* @return {String}
* @api public
*/
function block(str, fn) {
if (typeof str !== 'string') {
throw new TypeError('expected a string');
}
return comments(str, {line: false}, fn);
function line(str, options, fn) {
return factory('//', '\n', Line)(str, options, fn);
}
/**
* Get line comments from the given string
* Factory for extracting comments from a string.
*
* @param {String} `string`
* @return {String}
*/
function line(str, options, fn) {
if (typeof str !== 'string') {
throw new TypeError('expected a string');
}
function factory(open, close, Ctor) {
return function(str, options, fn) {
if (typeof str !== 'string') {
throw new TypeError('expected a string');
}
str = utils.normalize(str);
var comments = [];
if (typeof options === 'function') {
fn = options;
options = {};
}
if (typeof fn !== 'function') {
fn = utils.identity;
}
var ranges = utils.getRanges(str);
var opts = extend({}, options);
var combine = opts.combine === true;
var start = findStart('//');
var end = findEnd('\n');
var len = str.length;
var startIdx = start(str, 0);
var endIdx = 0, prev;
var stacked = null;
while (startIdx !== -1 && endIdx < len) {
if (startIdx >= len || endIdx >= len) {
break;
if (typeof options === 'function') {
fn = options;
options = {};
}
endIdx = end(str, startIdx, len);
if (endIdx === -1) {
endIdx = len;
if (typeof fn !== 'function') {
fn = utils.identity;
}
var quoted = utils.isQuotedString(startIdx, ranges);
var comment = new Line(str, startIdx, endIdx);
var opts = extend({}, options);
str = utils.normalize(str);
str = utils.escapeQuoted(str);
startIdx = start(str, endIdx);
if (quoted) {
startIdx = endIdx + 1;
continue;
var res = [];
var start = str.indexOf(open);
var end = str.indexOf(close, start);
var len = str.length;
if (end === -1) {
end = len;
}
if (prev && combine && isStacked(comment, prev, opts)) {
var curr = comment.loc.end.line;
var last = comments[comments.length - 1];
prev = merge(str, comment, prev);
if (last && prev.start === last.start) {
comments.pop();
while (start !== -1 && end <= len) {
var comment = fn(new Ctor(str, start, end, open, close));
res.push(comment);
if (opts.first && res.length === 1) {
return res;
}
prev.loc.start.line = curr;
stacked = prev;
continue;
start = str.indexOf(open, end + 1);
end = str.indexOf(close, start);
if (end === -1) {
end = len;
}
}
if (stacked) {
comments.push(fn(stacked));
stacked = null;
}
comment = fn(comment);
prev = comment;
comments.push(comment);
}
if (stacked) {
comments.push(fn(stacked));
}
return comments;
}
/**
* Returns a function for getting the index the
* given "end" character(s)
*
* @param {String} endChars
*/
function findStart(startChars) {
return function(str, idx) {
var i = str.indexOf(startChars, idx);
var prev = str[i - 1];
if (prev && /['"\w]/.test(prev)) {
i = str.indexOf(startChars, i + 1);
prev = str[i - 1];
}
return i;
return res;
};

@@ -205,38 +113,30 @@ }

/**
* Returns a function for getting the index the
* given "end" character(s)
* Extract the first comment from the given `string`.
*
* @param {String} endChars
* @param {String} `string`
* @param {Object} `options` Pass `first: true` to return after the first comment is found.
* @return {String}
* @api public
*/
function findEnd(endChars) {
return function(str, start) {
var idx = str.indexOf(endChars, start + 2);
var ch = str[idx + 2];
while (ch && /['"]/.test(ch)) {
idx = str.indexOf(endChars, idx + 2);
ch = str[idx + 2];
}
return idx;
};
}
function first(str) {
if (typeof str !== 'string') {
throw new TypeError('expected a string');
}
/**
* Returns true if the previous line was a line comment.
*/
function isStacked(comment, prev) {
var prevLine = prev.loc.start.line;
var line = comment.loc.end.line;
return line === prevLine + 1;
var arr = comments(str, {first: true});
if (arr && arr.length) {
return arr[0].raw;
} else {
return null;
}
}
/**
* Merge line comments
* Utility for sorting line and block comments into
* the correct order.
*/
function merge(str, curr, prev) {
var i = prev.loc.start.pos;
var end = curr.loc.end.pos;
return new Line(str, i, end);
function compare(a, b) {
return a.loc.start.pos - b.loc.start.pos;
}

@@ -267,1 +167,7 @@

module.exports.line = line;
/**
* Expose `extract.factory` method
*/
module.exports.factory = factory;

@@ -6,9 +6,20 @@ 'use strict';

function Comment(str, i, end) {
var value = str.slice(i, end + 2);
var lineno = str.slice(0, i).split('\n').length;
var rawLines = value.split('\n');
var linesLen = rawLines.length;
var lines = utils.strip(value.slice(2, -2).split('\n'));
/**
* Create a new BlockComment with:
* - `str` the entire string
* - `idx` the starting index of the comment
* - `end` the ending index of the comment
* - `open` the opening character(s) of the comment
* - `close` the closing character(s) of the comment
*/
function BlockComment(str, idx, end, open, close) {
var ol = open.length;
var cl = close.length;
var lineno = utils.linesCount(str, idx);
var value = utils.restore(str.slice(idx, end + cl));
var inner = value.slice(ol, -cl);
var lines = utils.strip(inner.split('\n'));
this.type = 'block';

@@ -18,13 +29,18 @@ this.raw = value;

this.lines = lines;
this.loc = {
start: {
line: lineno,
pos: i
pos: idx
},
end: {
line: lineno + linesLen - 1,
pos: end + 2
line: lineno + utils.linesCount(value) - 1,
pos: end + cl
}
};
/**
* Add code context
*/
this.code = new Code(str, this);

@@ -34,5 +50,5 @@ }

/**
* expose `Comment`
* expose `BlockComment`
*/
module.exports = Comment;
module.exports = BlockComment;
'use strict';
var codeContext = require('parse-code-context');
var utils = require('./utils');
function Code(str, comment) {
str = utils.restore(str);
var start = comment.loc.end.pos;
var endLine = comment.loc.end.line;
var orig = str;
var lineno = comment.loc.end.line + 1;
var ctx = {};
str = str.slice(start);
var slen = str.length, idx = -1;
var chars, lines = 0;
while (++idx < slen) {
var ch = str[idx];
if (ch === '\n') {
++lines;
continue;
}
if (!/[\W\s]/.test(ch)) {
chars = idx;
var lines = str.split('\n').slice(lineno);
for (var i = 0; i < lines.length; i++) {
var res = codeContext(lines[i], lineno + i);
if (res) {
ctx = res;
lineno += i;
break;

@@ -24,15 +22,13 @@ }

start += chars;
var next = orig.indexOf('\n', start);
var code = orig.slice(start);
var codeLine = code.slice(0, next);
var lineno = endLine + lines - 1;
var val = ctx.original || '';
var pos = str.slice(start).indexOf(val) + start;
return {
context: ctx,
line: lineno,
loc: {
start: { line: lineno, pos: start },
end: { line: lineno, pos: next }
start: { line: lineno, pos: pos },
end: { line: lineno, pos: pos + val.length }
},
value: codeLine.trim(),
value: val.trim()
};

@@ -39,0 +35,0 @@ }

'use strict';
function LineComment(str, i, end) {
var value = str.slice(i, end);
var lineno = str.slice(0, i).split('\n').length;
var rawLines = value.split('\n');
var linesLen = rawLines.length;
var utils = require('./utils');
/**
* Create a new LineComment with:
* - `str` the entire string
* - `idx` the starting index of the comment
* - `end` the ending index of the comment
* - `open` the opening character(s) of the comment (e.g. '//')
* - `close` the closing character(s) of the comment (e.g. '\n')
*/
function LineComment(str, idx, end, open, close) {
var lineno = utils.linesCount(str, idx);
var value = utils.restore(str.slice(idx, end));
this.type = 'line';
this.raw = value;
value = value.replace(/^\s*[\/\s]+/, '');
this.value = value.split(/\n\/\//).join('\n');
this.value = this.raw.replace(/^\s*[\/\s]+/, '');

@@ -17,6 +25,6 @@ this.loc = {

line: lineno,
pos: i
pos: idx
},
end: {
line: lineno + linesLen - 1,
line: lineno + utils.linesCount(value) - 1,
pos: end

@@ -23,0 +31,0 @@ }

@@ -5,6 +5,4 @@ 'use strict';

var bom = require('strip-bom-string');
var quotesRe = require('quoted-string-regex');
var repeat = require('repeat-string');
var range = require('to-regex-range');
var cache = {};
var quotesRegex = require('quoted-string-regex');
var nonchar = require('noncharacters');

@@ -35,2 +33,58 @@ /**

/**
* Get the total number of lines from the start
* of a string to the given index.
*/
utils.linesCount = function(str, i) {
if (typeof i === 'number') {
return str.slice(0, i).split('\n').length;
}
return str.split('\n').length;
};
/**
* Utility for getting a sequence of non-characters. The
* goal is to return a non-character string that is the
* same length as the characters we're replacing.
*
* http://www.unicode.org/faq/private_use.html#noncharacters
*/
function ch(num) {
return nonchar[num] + nonchar[num];
}
/**
* Escaped comment characters in quoted strings
*
* @param {String} str
* @return {String}
*/
utils.escapeQuoted = function(str) {
return str.replace(quotesRegex(), function(val) {
val = val.split('//').join(ch(0));
val = val.split('/*').join(ch(1));
val = val.split('*/').join(ch(2));
return val;
});
};
/**
* Restore comment characters in quoted strings
*
* @param {String} str
* @return {String}
*/
utils.restore = function(str) {
return str.replace(quotesRegex(), function(val) {
val = val.split(ch(0)).join('//');
val = val.split(ch(1)).join('/*');
val = val.split(ch(2)).join('*/');
return val;
});
};
/**
* Strip stars from the beginning of each comment line,

@@ -56,38 +110,1 @@ * and strip whitespace from the end of each line. We

};
utils.getRanges = function (str) {
if (cache[str]) return cache[str];
var re = quotesRe();
var ranges = [];
var m;
while (m = re.exec(str)) {
var regex = utils.toRange(m.index, m.index + m[0].length);
ranges.push({
regex: regex,
index: m.index,
match: m,
});
}
cache[str] = ranges;
return ranges;
};
utils.toRange = function (a, b) {
return new RegExp(range(a, b));
};
utils.isQuotedString = function (num, ranges) {
var len = ranges.length, i = -1;
if (len === 0) return false;
var m;
while (++i < len) {
var range = ranges[i];
var re = range.regex;
if (re.test(num.toString())) {
return range;
}
}
return false;
};
{
"name": "extract-comments",
"description": "Extract code comments from string or from a glob of files.",
"version": "0.8.4",
"version": "0.8.5",
"homepage": "https://github.com/jonschlinkert/extract-comments",
"author": "Jon Schlinkert (https://github.com/jonschlinkert)",
"repository": "jonschlinkert/extract-comments",
"bugs": {
"url": "https://github.com/jonschlinkert/extract-comments/issues"
},
"bugs": "https://github.com/jonschlinkert/extract-comments/issues",
"license": "MIT",

@@ -27,11 +25,13 @@ "files": [

"extend-shallow": "^2.0.1",
"noncharacters": "^1.1.0",
"parse-code-context": "^0.1.3",
"quoted-string-regex": "^0.1.1",
"repeat-string": "^1.5.2",
"strip-bom-string": "^0.1.2",
"to-regex-range": "^0.1.1"
"strip-bom-string": "^0.1.2"
},
"devDependencies": {
"code-context": "^0.5.0",
"gulp": "^3.9.0",
"gulp-eslint": "^1.0.0",
"gulp-istanbul": "^0.10.2",
"gulp-mocha": "^2.1.3",
"mocha": "*",
"parse-code-context": "^0.1.3",
"should": "*"

@@ -53,3 +53,2 @@ },

"related": {
"description": "",
"list": [

@@ -59,3 +58,4 @@ "parse-comments",

"esprima-extract-comments"
]
],
"description": ""
},

@@ -62,0 +62,0 @@ "deps": {

@@ -41,2 +41,62 @@ # extract-comments [![NPM version](https://badge.fury.io/js/extract-comments.svg)](http://badge.fury.io/js/extract-comments)

## API
### [comments](index.js#L20)
Extract comments from the given `string`.
**Params**
* `string` **{String}**
* `options` **{Object}**: Pass `first: true` to return after the first comment is found.
* `returns` **{String}**
**Example**
```js
extract(str, options);
```
### [block](index.js#L41)
Extract block comments from the given `string`.
**Params**
* `string` **{String}**
* `options` **{Object}**: Pass `first: true` to return after the first comment is found.
* `returns` **{String}**
**Example**
```js
extract.block(str, options);
```
### [line](index.js#L57)
Extract line comments from the given `string`.
**Params**
* `string` **{String}**
* `options` **{Object}**: Pass `first: true` to return after the first comment is found.
* `returns` **{String}**
**Example**
```js
extract.line(str, options);
```
### [first](index.js#L120)
Extract the first comment from the given `string`.
**Params**
* `string` **{String}**
* `options` **{Object}**: Pass `first: true` to return after the first comment is found.
* `returns` **{String}**
## Related

@@ -50,5 +110,5 @@

Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/extract-comments/issues/new).
Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](/new).
## Run tests
## Tests

@@ -61,2 +121,21 @@ Install dev dependencies:

### Run tests
Install dev dependencies:
```sh
$ npm i -d && npm test
```
### Coverage
As of November 04, 2015:
```sh
Statements : 100% (133/133)
Branches : 100% (32/32)
Functions : 100% (19/19)
Lines : 100% (132/132)
```
## Author

@@ -76,2 +155,2 @@

_This file was generated by [verb-cli](https://github.com/assemble/verb-cli) on November 02, 2015._
_This file was generated by [verb-cli](https://github.com/assemble/verb-cli) on November 04, 2015._
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc