index.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. var tslib_1 = require("tslib");
  4. //
  5. // index.js
  6. // Should expose the additional browser functions on to the less object
  7. //
  8. var utils_1 = require("./utils");
  9. var less_1 = tslib_1.__importDefault(require("../less"));
  10. var browser_1 = tslib_1.__importDefault(require("./browser"));
  11. var file_manager_1 = tslib_1.__importDefault(require("./file-manager"));
  12. var plugin_loader_1 = tslib_1.__importDefault(require("./plugin-loader"));
  13. var log_listener_1 = tslib_1.__importDefault(require("./log-listener"));
  14. var error_reporting_1 = tslib_1.__importDefault(require("./error-reporting"));
  15. var cache_1 = tslib_1.__importDefault(require("./cache"));
  16. var image_size_1 = tslib_1.__importDefault(require("./image-size"));
  17. exports.default = (function (window, options) {
  18. var document = window.document;
  19. var less = less_1.default();
  20. less.options = options;
  21. var environment = less.environment;
  22. var FileManager = file_manager_1.default(options, less.logger);
  23. var fileManager = new FileManager();
  24. environment.addFileManager(fileManager);
  25. less.FileManager = FileManager;
  26. less.PluginLoader = plugin_loader_1.default;
  27. log_listener_1.default(less, options);
  28. var errors = error_reporting_1.default(window, less, options);
  29. var cache = less.cache = options.cache || cache_1.default(window, options, less.logger);
  30. image_size_1.default(less.environment);
  31. // Setup user functions - Deprecate?
  32. if (options.functions) {
  33. less.functions.functionRegistry.addMultiple(options.functions);
  34. }
  35. var typePattern = /^text\/(x-)?less$/;
  36. function clone(obj) {
  37. var cloned = {};
  38. for (var prop in obj) {
  39. if (Object.prototype.hasOwnProperty.call(obj, prop)) {
  40. cloned[prop] = obj[prop];
  41. }
  42. }
  43. return cloned;
  44. }
  45. // only really needed for phantom
  46. function bind(func, thisArg) {
  47. var curryArgs = Array.prototype.slice.call(arguments, 2);
  48. return function () {
  49. var args = curryArgs.concat(Array.prototype.slice.call(arguments, 0));
  50. return func.apply(thisArg, args);
  51. };
  52. }
  53. function loadStyles(modifyVars) {
  54. var styles = document.getElementsByTagName('style');
  55. var style;
  56. for (var i = 0; i < styles.length; i++) {
  57. style = styles[i];
  58. if (style.type.match(typePattern)) {
  59. var instanceOptions = clone(options);
  60. instanceOptions.modifyVars = modifyVars;
  61. var lessText = style.innerHTML || '';
  62. instanceOptions.filename = document.location.href.replace(/#.*$/, '');
  63. /* jshint loopfunc:true */
  64. // use closure to store current style
  65. less.render(lessText, instanceOptions, bind(function (style, e, result) {
  66. if (e) {
  67. errors.add(e, 'inline');
  68. }
  69. else {
  70. style.type = 'text/css';
  71. if (style.styleSheet) {
  72. style.styleSheet.cssText = result.css;
  73. }
  74. else {
  75. style.innerHTML = result.css;
  76. }
  77. }
  78. }, null, style));
  79. }
  80. }
  81. }
  82. function loadStyleSheet(sheet, callback, reload, remaining, modifyVars) {
  83. var instanceOptions = clone(options);
  84. utils_1.addDataAttr(instanceOptions, sheet);
  85. instanceOptions.mime = sheet.type;
  86. if (modifyVars) {
  87. instanceOptions.modifyVars = modifyVars;
  88. }
  89. function loadInitialFileCallback(loadedFile) {
  90. var data = loadedFile.contents;
  91. var path = loadedFile.filename;
  92. var webInfo = loadedFile.webInfo;
  93. var newFileInfo = {
  94. currentDirectory: fileManager.getPath(path),
  95. filename: path,
  96. rootFilename: path,
  97. rewriteUrls: instanceOptions.rewriteUrls
  98. };
  99. newFileInfo.entryPath = newFileInfo.currentDirectory;
  100. newFileInfo.rootpath = instanceOptions.rootpath || newFileInfo.currentDirectory;
  101. if (webInfo) {
  102. webInfo.remaining = remaining;
  103. var css = cache.getCSS(path, webInfo, instanceOptions.modifyVars);
  104. if (!reload && css) {
  105. webInfo.local = true;
  106. callback(null, css, data, sheet, webInfo, path);
  107. return;
  108. }
  109. }
  110. // TODO add tests around how this behaves when reloading
  111. errors.remove(path);
  112. instanceOptions.rootFileInfo = newFileInfo;
  113. less.render(data, instanceOptions, function (e, result) {
  114. if (e) {
  115. e.href = path;
  116. callback(e);
  117. }
  118. else {
  119. cache.setCSS(sheet.href, webInfo.lastModified, instanceOptions.modifyVars, result.css);
  120. callback(null, result.css, data, sheet, webInfo, path);
  121. }
  122. });
  123. }
  124. fileManager.loadFile(sheet.href, null, instanceOptions, environment)
  125. .then(function (loadedFile) {
  126. loadInitialFileCallback(loadedFile);
  127. }).catch(function (err) {
  128. console.log(err);
  129. callback(err);
  130. });
  131. }
  132. function loadStyleSheets(callback, reload, modifyVars) {
  133. for (var i = 0; i < less.sheets.length; i++) {
  134. loadStyleSheet(less.sheets[i], callback, reload, less.sheets.length - (i + 1), modifyVars);
  135. }
  136. }
  137. function initRunningMode() {
  138. if (less.env === 'development') {
  139. less.watchTimer = setInterval(function () {
  140. if (less.watchMode) {
  141. fileManager.clearFileCache();
  142. /**
  143. * @todo remove when this is typed with JSDoc
  144. */
  145. // eslint-disable-next-line no-unused-vars
  146. loadStyleSheets(function (e, css, _, sheet, webInfo) {
  147. if (e) {
  148. errors.add(e, e.href || sheet.href);
  149. }
  150. else if (css) {
  151. browser_1.default.createCSS(window.document, css, sheet);
  152. }
  153. });
  154. }
  155. }, options.poll);
  156. }
  157. }
  158. //
  159. // Watch mode
  160. //
  161. less.watch = function () {
  162. if (!less.watchMode) {
  163. less.env = 'development';
  164. initRunningMode();
  165. }
  166. this.watchMode = true;
  167. return true;
  168. };
  169. less.unwatch = function () { clearInterval(less.watchTimer); this.watchMode = false; return false; };
  170. //
  171. // Synchronously get all <link> tags with the 'rel' attribute set to
  172. // "stylesheet/less".
  173. //
  174. less.registerStylesheetsImmediately = function () {
  175. var links = document.getElementsByTagName('link');
  176. less.sheets = [];
  177. for (var i = 0; i < links.length; i++) {
  178. if (links[i].rel === 'stylesheet/less' || (links[i].rel.match(/stylesheet/) &&
  179. (links[i].type.match(typePattern)))) {
  180. less.sheets.push(links[i]);
  181. }
  182. }
  183. };
  184. //
  185. // Asynchronously get all <link> tags with the 'rel' attribute set to
  186. // "stylesheet/less", returning a Promise.
  187. //
  188. less.registerStylesheets = function () { return new Promise(function (resolve) {
  189. less.registerStylesheetsImmediately();
  190. resolve();
  191. }); };
  192. //
  193. // With this function, it's possible to alter variables and re-render
  194. // CSS without reloading less-files
  195. //
  196. less.modifyVars = function (record) { return less.refresh(true, record, false); };
  197. less.refresh = function (reload, modifyVars, clearFileCache) {
  198. if ((reload || clearFileCache) && clearFileCache !== false) {
  199. fileManager.clearFileCache();
  200. }
  201. return new Promise(function (resolve, reject) {
  202. var startTime;
  203. var endTime;
  204. var totalMilliseconds;
  205. var remainingSheets;
  206. startTime = endTime = new Date();
  207. // Set counter for remaining unprocessed sheets
  208. remainingSheets = less.sheets.length;
  209. if (remainingSheets === 0) {
  210. endTime = new Date();
  211. totalMilliseconds = endTime - startTime;
  212. less.logger.info('Less has finished and no sheets were loaded.');
  213. resolve({
  214. startTime: startTime,
  215. endTime: endTime,
  216. totalMilliseconds: totalMilliseconds,
  217. sheets: less.sheets.length
  218. });
  219. }
  220. else {
  221. // Relies on less.sheets array, callback seems to be guaranteed to be called for every element of the array
  222. loadStyleSheets(function (e, css, _, sheet, webInfo) {
  223. if (e) {
  224. errors.add(e, e.href || sheet.href);
  225. reject(e);
  226. return;
  227. }
  228. if (webInfo.local) {
  229. less.logger.info("Loading " + sheet.href + " from cache.");
  230. }
  231. else {
  232. less.logger.info("Rendered " + sheet.href + " successfully.");
  233. }
  234. browser_1.default.createCSS(window.document, css, sheet);
  235. less.logger.info("CSS for " + sheet.href + " generated in " + (new Date() - endTime) + "ms");
  236. // Count completed sheet
  237. remainingSheets--;
  238. // Check if the last remaining sheet was processed and then call the promise
  239. if (remainingSheets === 0) {
  240. totalMilliseconds = new Date() - startTime;
  241. less.logger.info("Less has finished. CSS generated in " + totalMilliseconds + "ms");
  242. resolve({
  243. startTime: startTime,
  244. endTime: endTime,
  245. totalMilliseconds: totalMilliseconds,
  246. sheets: less.sheets.length
  247. });
  248. }
  249. endTime = new Date();
  250. }, reload, modifyVars);
  251. }
  252. loadStyles(modifyVars);
  253. });
  254. };
  255. less.refreshStyles = loadStyles;
  256. return less;
  257. });
  258. //# sourceMappingURL=index.js.map