loader.js 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. /*
  2. * Jake JavaScript build tool
  3. * Copyright 2112 Matthew Eernisse (mde@fleegix.org)
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. *
  17. */
  18. let path = require('path');
  19. let fs = require('fs');
  20. let existsSync = fs.existsSync;
  21. let utils = require('./utils');
  22. // Files like jakelib/foobar.jake.js
  23. const JAKELIB_FILE_PAT = /\.jake$|\.js$/;
  24. const SUPPORTED_EXTENSIONS = {
  25. 'js': null,
  26. 'coffee': function () {
  27. try {
  28. let cs = require('coffeescript');
  29. if (typeof cs.register == 'function') {
  30. cs.register();
  31. }
  32. }
  33. catch(e) {
  34. throw new Error('You have a CoffeeScript Jakefile, but have not installed CoffeeScript');
  35. }
  36. },
  37. 'ls': function () {
  38. try {
  39. require('livescript');
  40. }
  41. catch (e) {
  42. throw new Error('You have a LiveScript Jakefile, but have not installed LiveScript');
  43. }
  44. },
  45. 'ts': function () {
  46. try {
  47. require('ts-node/register/transpile-only');
  48. }
  49. catch (e) {
  50. throw new Error('You have a TypeScript Jakefile, but have not installed TypeScript and ts-node');
  51. }
  52. }
  53. };
  54. const IMPLICIT_JAKEFILE_NAMES = [
  55. 'Jakefile',
  56. 'Gulpfile'
  57. ];
  58. let Loader = function () {
  59. // Load a Jakefile, running the code inside -- this may result in
  60. // tasks getting defined using the original Jake API, e.g.,
  61. // `task('foo' ['bar', 'baz']);`, or can also auto-create tasks
  62. // from any functions exported from the file
  63. function loadFile(filePath) {
  64. let exported = require(filePath);
  65. for (let [key, value] of Object.entries(exported)) {
  66. let t;
  67. if (typeof value == 'function') {
  68. t = jake.task(key, value);
  69. t.description = '(Exported function)';
  70. }
  71. }
  72. }
  73. function fileExists(name) {
  74. let nameWithExt = null;
  75. // Support no file extension as well
  76. let exts = Object.keys(SUPPORTED_EXTENSIONS).concat(['']);
  77. exts.some((ext) => {
  78. let fname = ext ? `${name}.${ext}` : name;
  79. if (existsSync(fname)) {
  80. nameWithExt = fname;
  81. return true;
  82. }
  83. });
  84. return nameWithExt;
  85. }
  86. // Recursive
  87. function findImplicitJakefile() {
  88. let cwd = process.cwd();
  89. let names = IMPLICIT_JAKEFILE_NAMES;
  90. let found = null;
  91. names.some((name) => {
  92. let n;
  93. // Prefer all-lowercase
  94. n = name.toLowerCase();
  95. if ((found = fileExists(n))) {
  96. return found;
  97. }
  98. // Check mixed-case as well
  99. n = name;
  100. if ((found = fileExists(n))) {
  101. return found;
  102. }
  103. });
  104. if (found) {
  105. return found;
  106. }
  107. else {
  108. process.chdir("..");
  109. // If we've walked all the way up the directory tree,
  110. // bail out with no result
  111. if (cwd === process.cwd()) {
  112. return null;
  113. }
  114. return findImplicitJakefile();
  115. }
  116. }
  117. this.loadFile = function (fileSpecified) {
  118. let jakefile;
  119. let origCwd = process.cwd();
  120. if (fileSpecified) {
  121. if (existsSync(fileSpecified)) {
  122. jakefile = fileSpecified;
  123. }
  124. }
  125. else {
  126. jakefile = findImplicitJakefile();
  127. }
  128. if (jakefile) {
  129. let ext = jakefile.split('.')[1];
  130. let loaderFunc = SUPPORTED_EXTENSIONS[ext];
  131. loaderFunc && loaderFunc();
  132. loadFile(utils.file.absolutize(jakefile));
  133. return true;
  134. }
  135. else {
  136. if (!fileSpecified) {
  137. // Restore the working directory on failure
  138. process.chdir(origCwd);
  139. }
  140. return false;
  141. }
  142. };
  143. this.loadDirectory = function (d) {
  144. let dirname = d || 'jakelib';
  145. let dirlist;
  146. dirname = utils.file.absolutize(dirname);
  147. if (existsSync(dirname)) {
  148. dirlist = fs.readdirSync(dirname);
  149. dirlist.forEach(function (filePath) {
  150. if (JAKELIB_FILE_PAT.test(filePath)) {
  151. loadFile(path.join(dirname, filePath));
  152. }
  153. });
  154. return true;
  155. }
  156. return false;
  157. };
  158. };
  159. module.exports = function () {
  160. return new Loader();
  161. };