UNPKG

linenumber

Version:

Get the line number of one or more matches in a file

145 lines (129 loc) 3.93 kB
(function() { // Decide what environment we're running in var isNode = typeof module !== 'undefined' && this.module !== module; /* istanbul ignore next */ var fs = isNode ? require('fs') : {}; var loader; var defaults = { sync: fs.readFileSync, async: fs.readFile, args: [{ encoding: 'utf8' }], context: fs }; var find = function(contents, query, file) { // Create a regex for the query if it's not one already var regex = query instanceof RegExp ? query : new RegExp(query, 'g'); // For performance, make sure the contents actual contain the pattern // before we parse them. if (!regex.test(contents)) { return null; } else { // regex.test advances the search index, so we need to reset it regex.lastIndex = 0; var match; var matches = []; // Iterate over the matches while ((match = regex.exec(contents)) !== null) { // and construct an object of the matches that includes // line and the string that matches, as well as the file // name if there is one. var matchObj = { line: contents.substring(0, match.index).split('\n').length, match: match[0] }; if (file) { matchObj.file = file; } matches.push(matchObj); } return matches; } }; var linenumber = function(file, query, cb) { var process = function() { var matches = find.apply(null, arguments); if (cb && cb.length === 1) { cb(matches); } else if (cb) { cb(null, matches); } else { return matches; } }; // If "file" looks like a filename if (file.indexOf('\n') === -1 && file.indexOf('.') > -1) { // If we have a callback and an async loading mechanism if (cb && loader.async) { // Invoke the loader with the supplied context and any additional args, but wrap the callback loader.async.apply(loader.context, [file].concat(loader.args).concat(function(err, contents) { // If the callback expects a single argument, that means "err" // is not an error, but the actual file contents if (cb.length === 1) { cb(find(err, query, file)); } // If the length is greater than 1, do normal node signature stuff else if (err) { cb(err); } else { cb(null, find(contents, query, file)); } })); } else { var contents = loader.sync.apply(loader.context, [file].concat(loader.args)); return process(contents, query, file); } } else { // "file" is actually the contents to parse return process(file, query); } }; var _loader = function(fn, args, context) { if (fn.constructor.name === 'Array') { loader = { sync: fn[0], async: fn[1], args: args, context: context }; } else if (fn.constructor.name === 'Object') { loader = { sync: fn.sync, async: fn.async, args: args, context: context }; } }; linenumber.loader = function(fn) { var args = [].slice.call(arguments, 1); if (typeof fn === 'function') { _loader({ async: fn }, args, this); } else { _loader(fn, args, this); } }; linenumber.loaderSync = function(fn) { var args = [].slice.call(arguments, 1); if (typeof fn === 'function') { _loader({ sync: fn }, args, this); } else { _loader(fn, args, this); } }; linenumber.reset = function() { loader = { sync: defaults.sync, async: defaults.async, args: defaults.args, context: defaults.context }; }; // Initialize loader and args linenumber.reset(); /* istanbul ignore else */ if (isNode) { module.exports = linenumber; } else { window.linenumber = linenumber; } })();