loader.js 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  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. 'cjs': null,
  27. 'coffee': function () {
  28. try {
  29. let cs = require('coffeescript');
  30. if (typeof cs.register == 'function') {
  31. cs.register();
  32. }
  33. }
  34. catch(e) {
  35. throw new Error('You have a CoffeeScript Jakefile, but have not installed CoffeeScript');
  36. }
  37. },
  38. 'ls': function () {
  39. try {
  40. require('livescript');
  41. }
  42. catch (e) {
  43. throw new Error('You have a LiveScript Jakefile, but have not installed LiveScript');
  44. }
  45. },
  46. 'ts': function () {
  47. try {
  48. require('ts-node/register/transpile-only');
  49. }
  50. catch (e) {
  51. throw new Error('You have a TypeScript Jakefile, but have not installed TypeScript and ts-node');
  52. }
  53. }
  54. };
  55. const IMPLICIT_JAKEFILE_NAMES = [
  56. 'Jakefile',
  57. 'Gulpfile'
  58. ];
  59. let Loader = function () {
  60. // Load a Jakefile, running the code inside -- this may result in
  61. // tasks getting defined using the original Jake API, e.g.,
  62. // `task('foo' ['bar', 'baz']);`, or can also auto-create tasks
  63. // from any functions exported from the file
  64. function loadFile(filePath) {
  65. let exported = require(filePath);
  66. for (let [key, value] of Object.entries(exported)) {
  67. let t;
  68. if (typeof value == 'function') {
  69. t = jake.task(key, value);
  70. t.description = '(Exported function)';
  71. }
  72. }
  73. }
  74. function fileExists(name) {
  75. let nameWithExt = null;
  76. // Support no file extension as well
  77. let exts = Object.keys(SUPPORTED_EXTENSIONS).concat(['']);
  78. exts.some((ext) => {
  79. let fname = ext ? `${name}.${ext}` : name;
  80. if (existsSync(fname)) {
  81. nameWithExt = fname;
  82. return true;
  83. }
  84. });
  85. return nameWithExt;
  86. }
  87. // Recursive
  88. function findImplicitJakefile() {
  89. let cwd = process.cwd();
  90. let names = IMPLICIT_JAKEFILE_NAMES;
  91. let found = null;
  92. names.some((name) => {
  93. let n;
  94. // Prefer all-lowercase
  95. n = name.toLowerCase();
  96. if ((found = fileExists(n))) {
  97. return found;
  98. }
  99. // Check mixed-case as well
  100. n = name;
  101. if ((found = fileExists(n))) {
  102. return found;
  103. }
  104. });
  105. if (found) {
  106. return found;
  107. }
  108. else {
  109. process.chdir("..");
  110. // If we've walked all the way up the directory tree,
  111. // bail out with no result
  112. if (cwd === process.cwd()) {
  113. return null;
  114. }
  115. return findImplicitJakefile();
  116. }
  117. }
  118. this.loadFile = function (fileSpecified) {
  119. let jakefile;
  120. let origCwd = process.cwd();
  121. if (fileSpecified) {
  122. if (existsSync(fileSpecified)) {
  123. jakefile = fileSpecified;
  124. }
  125. }
  126. else {
  127. jakefile = findImplicitJakefile();
  128. }
  129. if (jakefile) {
  130. let ext = jakefile.split('.')[1];
  131. let loaderFunc = SUPPORTED_EXTENSIONS[ext];
  132. loaderFunc && loaderFunc();
  133. loadFile(utils.file.absolutize(jakefile));
  134. return true;
  135. }
  136. else {
  137. if (!fileSpecified) {
  138. // Restore the working directory on failure
  139. process.chdir(origCwd);
  140. }
  141. return false;
  142. }
  143. };
  144. this.loadDirectory = function (d) {
  145. let dirname = d || 'jakelib';
  146. let dirlist;
  147. dirname = utils.file.absolutize(dirname);
  148. if (existsSync(dirname)) {
  149. dirlist = fs.readdirSync(dirname);
  150. dirlist.forEach(function (filePath) {
  151. if (JAKELIB_FILE_PAT.test(filePath)) {
  152. loadFile(path.join(dirname, filePath));
  153. }
  154. });
  155. return true;
  156. }
  157. return false;
  158. };
  159. };
  160. module.exports = function () {
  161. return new Loader();
  162. };