PageRenderTime 36ms CodeModel.GetById 9ms RepoModel.GetById 0ms app.codeStats 0ms

/src/index.js

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