first commit
This commit is contained in:
284
node_modules/less/lib/less-browser/index.js
generated
vendored
Normal file
284
node_modules/less/lib/less-browser/index.js
generated
vendored
Normal file
@@ -0,0 +1,284 @@
|
||||
//
|
||||
// index.js
|
||||
// Should expose the additional browser functions on to the less object
|
||||
//
|
||||
import {addDataAttr} from './utils.js';
|
||||
import lessRoot from '../less/index.js';
|
||||
import browser from './browser.js';
|
||||
import FM from './file-manager.js';
|
||||
import PluginLoader from './plugin-loader.js';
|
||||
import LogListener from './log-listener.js';
|
||||
import ErrorReporting from './error-reporting.js';
|
||||
import Cache from './cache.js';
|
||||
import ImageSize from './image-size.js';
|
||||
import pkg from '../../package.json';
|
||||
|
||||
/**
|
||||
* @param {Window} window
|
||||
* @param {Object} options
|
||||
*/
|
||||
export default (window, options) => {
|
||||
const document = window.document;
|
||||
const less = lessRoot(undefined, undefined, pkg.version);
|
||||
|
||||
less.options = options;
|
||||
const environment = less.environment;
|
||||
const FileManager = FM(options, less.logger);
|
||||
const fileManager = new FileManager();
|
||||
environment.addFileManager(fileManager);
|
||||
less.FileManager = FileManager;
|
||||
less.PluginLoader = PluginLoader;
|
||||
|
||||
LogListener(less, options);
|
||||
const errors = ErrorReporting(window, less, options);
|
||||
const cache = less.cache = options.cache || Cache(window, options, less.logger);
|
||||
ImageSize(less.environment);
|
||||
|
||||
// Setup user functions - Deprecate?
|
||||
if (options.functions) {
|
||||
less.functions.functionRegistry.addMultiple(options.functions);
|
||||
}
|
||||
|
||||
const typePattern = /^text\/(x-)?less$/;
|
||||
|
||||
function clone(obj) {
|
||||
const cloned = {};
|
||||
for (const prop in obj) {
|
||||
if (Object.prototype.hasOwnProperty.call(obj, prop)) {
|
||||
cloned[prop] = obj[prop];
|
||||
}
|
||||
}
|
||||
return cloned;
|
||||
}
|
||||
|
||||
function loadStyles(modifyVars) {
|
||||
const styles = document.getElementsByTagName('style');
|
||||
|
||||
for (let style of styles) {
|
||||
if (style.type.match(typePattern)) {
|
||||
const instanceOptions = {
|
||||
...clone(options),
|
||||
modifyVars,
|
||||
filename: document.location.href.replace(/#.*$/, '')
|
||||
}
|
||||
|
||||
const lessText = style.innerHTML || '';
|
||||
|
||||
/* jshint loopfunc:true */
|
||||
less.render(lessText, instanceOptions, (err, result) => {
|
||||
if (err) {
|
||||
errors.add(err, 'inline');
|
||||
} else {
|
||||
style.type = 'text/css';
|
||||
if (style.styleSheet) {
|
||||
style.styleSheet.cssText = result.css;
|
||||
} else {
|
||||
style.innerHTML = result.css;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function loadStyleSheet(sheet, callback, reload, remaining, modifyVars) {
|
||||
|
||||
const instanceOptions = clone(options);
|
||||
addDataAttr(instanceOptions, sheet);
|
||||
instanceOptions.mime = sheet.type;
|
||||
|
||||
if (modifyVars) {
|
||||
instanceOptions.modifyVars = modifyVars;
|
||||
}
|
||||
|
||||
function loadInitialFileCallback(loadedFile) {
|
||||
const data = loadedFile.contents;
|
||||
const path = loadedFile.filename;
|
||||
const webInfo = loadedFile.webInfo;
|
||||
|
||||
const newFileInfo = {
|
||||
currentDirectory: fileManager.getPath(path),
|
||||
filename: path,
|
||||
rootFilename: path,
|
||||
rewriteUrls: instanceOptions.rewriteUrls
|
||||
};
|
||||
|
||||
newFileInfo.entryPath = newFileInfo.currentDirectory;
|
||||
newFileInfo.rootpath = instanceOptions.rootpath || newFileInfo.currentDirectory;
|
||||
|
||||
if (webInfo) {
|
||||
webInfo.remaining = remaining;
|
||||
|
||||
const css = cache.getCSS(path, webInfo, instanceOptions.modifyVars);
|
||||
if (!reload && css) {
|
||||
webInfo.local = true;
|
||||
callback(null, css, data, sheet, webInfo, path);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// TODO add tests around how this behaves when reloading
|
||||
errors.remove(path);
|
||||
|
||||
instanceOptions.rootFileInfo = newFileInfo;
|
||||
less.render(data, instanceOptions, (e, result) => {
|
||||
if (e) {
|
||||
e.href = path;
|
||||
callback(e);
|
||||
} else {
|
||||
cache.setCSS(sheet.href, webInfo.lastModified, instanceOptions.modifyVars, result.css);
|
||||
callback(null, result.css, data, sheet, webInfo, path);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fileManager.loadFile(sheet.href, null, instanceOptions, environment)
|
||||
.then(loadedFile => {
|
||||
loadInitialFileCallback(loadedFile);
|
||||
}).catch(err => {
|
||||
console.log(err);
|
||||
callback(err);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function loadStyleSheets(callback, reload, modifyVars) {
|
||||
for (let i = 0; i < less.sheets.length; i++) {
|
||||
loadStyleSheet(less.sheets[i], callback, reload, less.sheets.length - (i + 1), modifyVars);
|
||||
}
|
||||
}
|
||||
|
||||
function initRunningMode() {
|
||||
if (less.env === 'development') {
|
||||
less.watchTimer = setInterval(() => {
|
||||
if (less.watchMode) {
|
||||
fileManager.clearFileCache();
|
||||
/**
|
||||
* @todo remove when this is typed with JSDoc
|
||||
*/
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
loadStyleSheets((e, css, _, sheet, webInfo) => {
|
||||
if (e) {
|
||||
errors.add(e, e.href || sheet.href);
|
||||
} else if (css) {
|
||||
browser.createCSS(window.document, css, sheet);
|
||||
}
|
||||
});
|
||||
}
|
||||
}, options.poll);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Watch mode
|
||||
//
|
||||
less.watch = function () {
|
||||
if (!less.watchMode ) {
|
||||
less.env = 'development';
|
||||
initRunningMode();
|
||||
}
|
||||
this.watchMode = true;
|
||||
return true;
|
||||
};
|
||||
|
||||
less.unwatch = function () {clearInterval(less.watchTimer); this.watchMode = false; return false; };
|
||||
|
||||
//
|
||||
// Synchronously get all <link> tags with the 'rel' attribute set to
|
||||
// "stylesheet/less".
|
||||
//
|
||||
less.registerStylesheetsImmediately = () => {
|
||||
const links = document.getElementsByTagName('link');
|
||||
less.sheets = [];
|
||||
|
||||
for (let i = 0; i < links.length; i++) {
|
||||
if (links[i].rel === 'stylesheet/less' || (links[i].rel.match(/stylesheet/) &&
|
||||
(links[i].type.match(typePattern)))) {
|
||||
less.sheets.push(links[i]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// Asynchronously get all <link> tags with the 'rel' attribute set to
|
||||
// "stylesheet/less", returning a Promise.
|
||||
//
|
||||
less.registerStylesheets = () => new Promise((resolve) => {
|
||||
less.registerStylesheetsImmediately();
|
||||
resolve();
|
||||
});
|
||||
|
||||
//
|
||||
// With this function, it's possible to alter variables and re-render
|
||||
// CSS without reloading less-files
|
||||
//
|
||||
less.modifyVars = record => less.refresh(true, record, false);
|
||||
|
||||
less.refresh = (reload, modifyVars, clearFileCache) => {
|
||||
if ((reload || clearFileCache) && clearFileCache !== false) {
|
||||
fileManager.clearFileCache();
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
let startTime;
|
||||
let endTime;
|
||||
let totalMilliseconds;
|
||||
let remainingSheets;
|
||||
startTime = endTime = new Date();
|
||||
|
||||
// Set counter for remaining unprocessed sheets
|
||||
remainingSheets = less.sheets.length;
|
||||
|
||||
if (remainingSheets === 0) {
|
||||
|
||||
endTime = new Date();
|
||||
totalMilliseconds = endTime - startTime;
|
||||
less.logger.info('Less has finished and no sheets were loaded.');
|
||||
resolve({
|
||||
startTime,
|
||||
endTime,
|
||||
totalMilliseconds,
|
||||
sheets: less.sheets.length
|
||||
});
|
||||
|
||||
} else {
|
||||
// Relies on less.sheets array, callback seems to be guaranteed to be called for every element of the array
|
||||
loadStyleSheets((e, css, _, sheet, webInfo) => {
|
||||
if (e) {
|
||||
errors.add(e, e.href || sheet.href);
|
||||
reject(e);
|
||||
return;
|
||||
}
|
||||
if (webInfo.local) {
|
||||
less.logger.info(`Loading ${sheet.href} from cache.`);
|
||||
} else {
|
||||
less.logger.info(`Rendered ${sheet.href} successfully.`);
|
||||
}
|
||||
browser.createCSS(window.document, css, sheet);
|
||||
less.logger.info(`CSS for ${sheet.href} generated in ${new Date() - endTime}ms`);
|
||||
|
||||
// Count completed sheet
|
||||
remainingSheets--;
|
||||
|
||||
// Check if the last remaining sheet was processed and then call the promise
|
||||
if (remainingSheets === 0) {
|
||||
totalMilliseconds = new Date() - startTime;
|
||||
less.logger.info(`Less has finished. CSS generated in ${totalMilliseconds}ms`);
|
||||
resolve({
|
||||
startTime,
|
||||
endTime,
|
||||
totalMilliseconds,
|
||||
sheets: less.sheets.length
|
||||
});
|
||||
}
|
||||
endTime = new Date();
|
||||
}, reload, modifyVars);
|
||||
}
|
||||
|
||||
loadStyles(modifyVars);
|
||||
});
|
||||
};
|
||||
|
||||
less.refreshStyles = loadStyles;
|
||||
return less;
|
||||
};
|
||||
Reference in New Issue
Block a user