import-manager.js 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. var tslib_1 = require("tslib");
  4. var contexts_1 = tslib_1.__importDefault(require("./contexts"));
  5. var parser_1 = tslib_1.__importDefault(require("./parser/parser"));
  6. var less_error_1 = tslib_1.__importDefault(require("./less-error"));
  7. var utils = tslib_1.__importStar(require("./utils"));
  8. var logger_1 = tslib_1.__importDefault(require("./logger"));
  9. function default_1(environment) {
  10. // FileInfo = {
  11. // 'rewriteUrls' - option - whether to adjust URL's to be relative
  12. // 'filename' - full resolved filename of current file
  13. // 'rootpath' - path to append to normal URLs for this node
  14. // 'currentDirectory' - path to the current file, absolute
  15. // 'rootFilename' - filename of the base file
  16. // 'entryPath' - absolute path to the entry file
  17. // 'reference' - whether the file should not be output and only output parts that are referenced
  18. var ImportManager = /** @class */ (function () {
  19. function ImportManager(less, context, rootFileInfo) {
  20. this.less = less;
  21. this.rootFilename = rootFileInfo.filename;
  22. this.paths = context.paths || []; // Search paths, when importing
  23. this.contents = {}; // map - filename to contents of all the files
  24. this.contentsIgnoredChars = {}; // map - filename to lines at the beginning of each file to ignore
  25. this.mime = context.mime;
  26. this.error = null;
  27. this.context = context;
  28. // Deprecated? Unused outside of here, could be useful.
  29. this.queue = []; // Files which haven't been imported yet
  30. this.files = {}; // Holds the imported parse trees.
  31. }
  32. /**
  33. * Add an import to be imported
  34. * @param path - the raw path
  35. * @param tryAppendExtension - whether to try appending a file extension (.less or .js if the path has no extension)
  36. * @param currentFileInfo - the current file info (used for instance to work out relative paths)
  37. * @param importOptions - import options
  38. * @param callback - callback for when it is imported
  39. */
  40. ImportManager.prototype.push = function (path, tryAppendExtension, currentFileInfo, importOptions, callback) {
  41. var importManager = this, pluginLoader = this.context.pluginManager.Loader;
  42. this.queue.push(path);
  43. var fileParsedFunc = function (e, root, fullPath) {
  44. importManager.queue.splice(importManager.queue.indexOf(path), 1); // Remove the path from the queue
  45. var importedEqualsRoot = fullPath === importManager.rootFilename;
  46. if (importOptions.optional && e) {
  47. callback(null, { rules: [] }, false, null);
  48. logger_1.default.info("The file " + fullPath + " was skipped because it was not found and the import was marked optional.");
  49. }
  50. else {
  51. // Inline imports aren't cached here.
  52. // If we start to cache them, please make sure they won't conflict with non-inline imports of the
  53. // same name as they used to do before this comment and the condition below have been added.
  54. if (!importManager.files[fullPath] && !importOptions.inline) {
  55. importManager.files[fullPath] = { root: root, options: importOptions };
  56. }
  57. if (e && !importManager.error) {
  58. importManager.error = e;
  59. }
  60. callback(e, root, importedEqualsRoot, fullPath);
  61. }
  62. };
  63. var newFileInfo = {
  64. rewriteUrls: this.context.rewriteUrls,
  65. entryPath: currentFileInfo.entryPath,
  66. rootpath: currentFileInfo.rootpath,
  67. rootFilename: currentFileInfo.rootFilename
  68. };
  69. var fileManager = environment.getFileManager(path, currentFileInfo.currentDirectory, this.context, environment);
  70. if (!fileManager) {
  71. fileParsedFunc({ message: "Could not find a file-manager for " + path });
  72. return;
  73. }
  74. var loadFileCallback = function (loadedFile) {
  75. var plugin;
  76. var resolvedFilename = loadedFile.filename;
  77. var contents = loadedFile.contents.replace(/^\uFEFF/, '');
  78. // Pass on an updated rootpath if path of imported file is relative and file
  79. // is in a (sub|sup) directory
  80. //
  81. // Examples:
  82. // - If path of imported file is 'module/nav/nav.less' and rootpath is 'less/',
  83. // then rootpath should become 'less/module/nav/'
  84. // - If path of imported file is '../mixins.less' and rootpath is 'less/',
  85. // then rootpath should become 'less/../'
  86. newFileInfo.currentDirectory = fileManager.getPath(resolvedFilename);
  87. if (newFileInfo.rewriteUrls) {
  88. newFileInfo.rootpath = fileManager.join((importManager.context.rootpath || ''), fileManager.pathDiff(newFileInfo.currentDirectory, newFileInfo.entryPath));
  89. if (!fileManager.isPathAbsolute(newFileInfo.rootpath) && fileManager.alwaysMakePathsAbsolute()) {
  90. newFileInfo.rootpath = fileManager.join(newFileInfo.entryPath, newFileInfo.rootpath);
  91. }
  92. }
  93. newFileInfo.filename = resolvedFilename;
  94. var newEnv = new contexts_1.default.Parse(importManager.context);
  95. newEnv.processImports = false;
  96. importManager.contents[resolvedFilename] = contents;
  97. if (currentFileInfo.reference || importOptions.reference) {
  98. newFileInfo.reference = true;
  99. }
  100. if (importOptions.isPlugin) {
  101. plugin = pluginLoader.evalPlugin(contents, newEnv, importManager, importOptions.pluginArgs, newFileInfo);
  102. if (plugin instanceof less_error_1.default) {
  103. fileParsedFunc(plugin, null, resolvedFilename);
  104. }
  105. else {
  106. fileParsedFunc(null, plugin, resolvedFilename);
  107. }
  108. }
  109. else if (importOptions.inline) {
  110. fileParsedFunc(null, contents, resolvedFilename);
  111. }
  112. else {
  113. // import (multiple) parse trees apparently get altered and can't be cached.
  114. // TODO: investigate why this is
  115. if (importManager.files[resolvedFilename]
  116. && !importManager.files[resolvedFilename].options.multiple
  117. && !importOptions.multiple) {
  118. fileParsedFunc(null, importManager.files[resolvedFilename].root, resolvedFilename);
  119. }
  120. else {
  121. new parser_1.default(newEnv, importManager, newFileInfo).parse(contents, function (e, root) {
  122. fileParsedFunc(e, root, resolvedFilename);
  123. });
  124. }
  125. }
  126. };
  127. var loadedFile;
  128. var promise;
  129. var context = utils.clone(this.context);
  130. if (tryAppendExtension) {
  131. context.ext = importOptions.isPlugin ? '.js' : '.less';
  132. }
  133. if (importOptions.isPlugin) {
  134. context.mime = 'application/javascript';
  135. if (context.syncImport) {
  136. loadedFile = pluginLoader.loadPluginSync(path, currentFileInfo.currentDirectory, context, environment, fileManager);
  137. }
  138. else {
  139. promise = pluginLoader.loadPlugin(path, currentFileInfo.currentDirectory, context, environment, fileManager);
  140. }
  141. }
  142. else {
  143. if (context.syncImport) {
  144. loadedFile = fileManager.loadFileSync(path, currentFileInfo.currentDirectory, context, environment);
  145. }
  146. else {
  147. promise = fileManager.loadFile(path, currentFileInfo.currentDirectory, context, environment, function (err, loadedFile) {
  148. if (err) {
  149. fileParsedFunc(err);
  150. }
  151. else {
  152. loadFileCallback(loadedFile);
  153. }
  154. });
  155. }
  156. }
  157. if (loadedFile) {
  158. if (!loadedFile.filename) {
  159. fileParsedFunc(loadedFile);
  160. }
  161. else {
  162. loadFileCallback(loadedFile);
  163. }
  164. }
  165. else if (promise) {
  166. promise.then(loadFileCallback, fileParsedFunc);
  167. }
  168. };
  169. return ImportManager;
  170. }());
  171. return ImportManager;
  172. }
  173. exports.default = default_1;
  174. //# sourceMappingURL=import-manager.js.map