index.js 10 KB

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