PageRenderTime 45ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/src/index.js

https://github.com/timplourde/blanket
JavaScript | 217 lines | 198 code | 14 blank | 5 comment | 36 complexity | 75193e616680333672581e6e5d127d25 MD5 | raw file
Possible License(s): MIT
  1. var extend = require("xtend"),
  2. path = require('path'),
  3. join = path.join;
  4. var blanketNode = function (userOptions,cli){
  5. var fs = require("fs"),
  6. path = require("path"),
  7. configPath = process.cwd() + '/package.json',
  8. existsSync = fs.existsSync || path.existsSync,
  9. file = existsSync(configPath) ? JSON.parse((fs.readFileSync(configPath, 'utf8')||{})) : null,
  10. packageConfigs;
  11. if (file){
  12. var scripts = file.scripts,
  13. config = file.config;
  14. if (scripts && scripts.blanket){
  15. console.warn("BLANKET-" + path + ": `scripts[\"blanket\"]` is deprecated. Please migrate to `config[\"blanket\"]`.\n");
  16. packageConfigs = scripts.blanket;
  17. } else if (config && config.blanket){
  18. packageConfigs = config.blanket;
  19. }
  20. }
  21. var blanketConfigs = packageConfigs ? extend(packageConfigs,userOptions) : userOptions,
  22. pattern = blanketConfigs ?
  23. blanketConfigs.pattern :
  24. "src",
  25. blanket = require("./blanket").blanket,
  26. oldLoader = require.extensions['.js'],
  27. newLoader;
  28. function escapeRegExp(str) {
  29. return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
  30. }
  31. if (blanketConfigs){
  32. var newOptions={};
  33. Object.keys(blanketConfigs).forEach(function (option) {
  34. var optionValue = blanketConfigs[option];
  35. if(option === "data-cover-only" || option === "pattern"){
  36. newOptions.filter = optionValue;
  37. }
  38. if(option === "data-cover-never"){
  39. newOptions.antifilter = optionValue;
  40. }
  41. if (option === "data-cover-loader" || option === "loader"){
  42. newOptions.loader = optionValue;
  43. }
  44. if (option === "data-cover-timeout"){
  45. newOptions.timeout = optionValue;
  46. }
  47. if (option === "onlyCwd" && !!optionValue){
  48. newOptions.cwdRegex = new RegExp("^" + escapeRegExp(process.cwd()), "i");
  49. }
  50. if (option === "data-cover-customVariable"){
  51. newOptions.customVariable = optionValue;
  52. }
  53. if (option === "data-cover-flags"){
  54. newOptions.order = !optionValue.unordered;
  55. newOptions.ignoreScriptError = !!optionValue.ignoreError;
  56. newOptions.autoStart = !!optionValue.autoStart;
  57. newOptions.branchTracking = !!optionValue.branchTracking;
  58. newOptions.debug = !!optionValue.debug;
  59. newOptions.engineOnly = !!optionValue.engineOnly;
  60. }
  61. if (option === "data-cover-reporter-options"){
  62. newOptions.reporter_options = optionValue;
  63. }
  64. });
  65. blanket.options(newOptions);
  66. }
  67. //helper functions
  68. blanket.normalizeBackslashes = function (str) {
  69. return str.replace(/\\/g, '/');
  70. };
  71. blanket.restoreNormalLoader = function () {
  72. if (!blanket.options("engineOnly")){
  73. newLoader = require.extensions['.js'];
  74. require.extensions['.js'] = oldLoader;
  75. }
  76. };
  77. blanket.restoreBlanketLoader = function () {
  78. if (!blanket.options("engineOnly")){
  79. require.extensions['.js'] = newLoader;
  80. }
  81. };
  82. //you can pass in a string, a regex, or an array of files
  83. blanket.matchPattern = function (filename,pattern){
  84. var cwdRegex = blanket.options("cwdRegex");
  85. if (cwdRegex && !cwdRegex.test(filename)){
  86. return false;
  87. }
  88. if (typeof pattern === 'string'){
  89. if (pattern.indexOf("[") === 0){
  90. //treat as array
  91. var pattenArr = pattern.slice(1,pattern.length-1).split(",");
  92. return pattenArr.some(function(elem){
  93. return blanket.matchPattern(filename,blanket.normalizeBackslashes(elem.slice(1,-1)));
  94. });
  95. }else if ( pattern.indexOf("//") === 0){
  96. var ex = pattern.slice(2,pattern.lastIndexOf('/'));
  97. var mods = pattern.slice(pattern.lastIndexOf('/')+1);
  98. var regex = new RegExp(ex,mods);
  99. return regex.test(filename);
  100. }else{
  101. return filename.indexOf(blanket.normalizeBackslashes(pattern)) > -1;
  102. }
  103. }else if ( pattern instanceof Array ){
  104. return pattern.some(function(elem){
  105. return filename.indexOf(blanket.normalizeBackslashes(elem)) > -1;
  106. });
  107. }else if (pattern instanceof RegExp){
  108. return pattern.test(filename);
  109. }else if (typeof pattern === 'function'){
  110. return pattern(filename);
  111. }else{
  112. throw new Error("Bad file instrument indicator. Must be a string, regex, function, or array.");
  113. }
  114. };
  115. if (!blanket.options("engineOnly")){
  116. //instrument js files
  117. require.extensions['.js'] = function(localModule, filename) {
  118. var pattern = blanket.options("filter"),
  119. reporter_options = blanket.options("reporter_options"),
  120. originalFilename = filename;
  121. filename = blanket.normalizeBackslashes(filename);
  122. //we check the never matches first
  123. var antipattern = _blanket.options("antifilter");
  124. if (typeof antipattern !== "undefined" &&
  125. blanket.matchPattern(filename.replace(/\.js$/,""),antipattern)
  126. ){
  127. oldLoader(localModule,filename);
  128. if (_blanket.options("debug")) {console.log("BLANKET-File will never be instrumented:"+filename);}
  129. }else if (blanket.matchPattern(filename,pattern)){
  130. if (_blanket.options("debug")) {console.log("BLANKET-Attempting instrument of:"+filename);}
  131. var content = fs.readFileSync(filename, 'utf8');
  132. if (reporter_options && reporter_options.shortnames){
  133. filename = filename.replace(process.cwd(),"");
  134. }
  135. blanket.instrument({
  136. inputFile: content,
  137. inputFileName: filename
  138. },function(instrumented){
  139. var baseDirPath = blanket.normalizeBackslashes(path.dirname(filename))+'/.';
  140. try{
  141. instrumented = instrumented.replace(/require\s*\(\s*("|')\./g,'require($1'+baseDirPath);
  142. localModule._compile(instrumented, originalFilename);
  143. }
  144. catch(err){
  145. if (_blanket.options("ignoreScriptError")){
  146. //we can continue like normal if
  147. //we're ignoring script errors,
  148. //but otherwise we don't want
  149. //to completeLoad or the error might be
  150. //missed.
  151. if (_blanket.options("debug")) {console.log("BLANKET-There was an error loading the file:"+filename);}
  152. oldLoader(localModule,filename);
  153. }else{
  154. throw new Error("BLANKET-Error parsing instrumented code: "+err);
  155. }
  156. }
  157. });
  158. }else{
  159. oldLoader(localModule, originalFilename);
  160. }
  161. };
  162. }
  163. //if a loader is specified, use it
  164. if (blanket.options("loader")){
  165. require(blanket.options("loader"))(blanket);
  166. }
  167. newLoader = require.extensions['.js'];
  168. return blanket;
  169. };
  170. if ((process.env && process.env.BLANKET_COV===1) ||
  171. (process.ENV && process.ENV.BLANKET_COV)){
  172. module.exports = blanketNode({engineOnly:true},false);
  173. }else{
  174. var args = process.argv;
  175. var blanketRequired = false;
  176. for (var i = 0; i < args.length; i++) {
  177. if (['-r', '--require'].indexOf(args[i]) >= 0 &&
  178. args[i + 1] === 'blanket') {
  179. blanketRequired = true;
  180. }
  181. }
  182. if (args[0] === 'node' &&
  183. args[1].indexOf(join('node_modules','mocha','bin')) > -1 &&
  184. blanketRequired){
  185. //using mocha cli
  186. module.exports = blanketNode(null,true);
  187. }else{
  188. //not mocha cli
  189. module.exports = function(options){
  190. //we don't want to expose the cli option.
  191. return blanketNode(options,false);
  192. };
  193. }
  194. }