funcunit
Version:
<!-- @hide title
1,552 lines (1,373 loc) • 295 kB
JavaScript
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
//
// browser.js - client-side engine
//
/*global window, document, location */
var logLevel = {
debug: 3,
info: 2,
errors: 1,
none: 0
};
var less;
function log(str, level) {
if (typeof(console) !== 'undefined' && less.logLevel >= level) {
console.log('less: ' + str);
}
}
/*
TODO - options is now hidden - we should expose it on the less object, but not have it "as" the less object
alternately even have it on environment
e.g. less.environment.options.fileAsync = true;
is it weird you do
less = { fileAsync: true }
then access as less.environment.options.fileAsync ?
*/
var isFileProtocol = /^(file|chrome(-extension)?|resource|qrc|app):/.test(location.protocol),
options = window.less,
environment = require("./environment/browser.js")(options, isFileProtocol, log, logLevel);
window.less = less = require('./non-node-index.js')(environment);
less.env = options.env || (location.hostname == '127.0.0.1' ||
location.hostname == '0.0.0.0' ||
location.hostname == 'localhost' ||
(location.port &&
location.port.length > 0) ||
isFileProtocol ? 'development'
: 'production');
// The amount of logging in the javascript console.
// 3 - Debug, information and errors
// 2 - Information and errors
// 1 - Errors
// 0 - None
// Defaults to 2
less.logLevel = typeof(options.logLevel) != 'undefined' ? options.logLevel : (less.env === 'development' ? logLevel.debug : logLevel.errors);
// Load styles asynchronously (default: false)
//
// This is set to `false` by default, so that the body
// doesn't start loading before the stylesheets are parsed.
// Setting this to `true` can result in flickering.
//
options.async = options.async || false;
options.fileAsync = options.fileAsync || false;
// Interval between watch polls
less.poll = less.poll || (isFileProtocol ? 1000 : 1500);
//Setup user functions
if (options.functions) {
less.functions.functionRegistry.addMultiple(options.functions);
}
var dumpLineNumbers = /!dumpLineNumbers:(comments|mediaquery|all)/.exec(location.hash);
if (dumpLineNumbers) {
less.dumpLineNumbers = dumpLineNumbers[1];
}
var typePattern = /^text\/(x-)?less$/;
var cache = null;
function extractId(href) {
return href.replace(/^[a-z-]+:\/+?[^\/]+/, '' ) // Remove protocol & domain
.replace(/^\//, '' ) // Remove root /
.replace(/\.[a-zA-Z]+$/, '' ) // Remove simple extension
.replace(/[^\.\w-]+/g, '-') // Replace illegal characters
.replace(/\./g, ':'); // Replace dots with colons(for valid id)
}
function errorConsole(e, rootHref) {
var template = '{line} {content}';
var filename = e.filename || rootHref;
var errors = [];
var content = (e.type || "Syntax") + "Error: " + (e.message || 'There is an error in your .less file') +
" in " + filename + " ";
var errorline = function (e, i, classname) {
if (e.extract[i] !== undefined) {
errors.push(template.replace(/\{line\}/, (parseInt(e.line, 10) || 0) + (i - 1))
.replace(/\{class\}/, classname)
.replace(/\{content\}/, e.extract[i]));
}
};
if (e.extract) {
errorline(e, 0, '');
errorline(e, 1, 'line');
errorline(e, 2, '');
content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':\n' +
errors.join('\n');
} else if (e.stack) {
content += e.stack;
}
log(content, logLevel.errors);
}
function createCSS(styles, sheet, lastModified) {
// Strip the query-string
var href = sheet.href || '';
// If there is no title set, use the filename, minus the extension
var id = 'less:' + (sheet.title || extractId(href));
// If this has already been inserted into the DOM, we may need to replace it
var oldCss = document.getElementById(id);
var keepOldCss = false;
// Create a new stylesheet node for insertion or (if necessary) replacement
var css = document.createElement('style');
css.setAttribute('type', 'text/css');
if (sheet.media) {
css.setAttribute('media', sheet.media);
}
css.id = id;
if (!css.styleSheet) {
css.appendChild(document.createTextNode(styles));
// If new contents match contents of oldCss, don't replace oldCss
keepOldCss = (oldCss !== null && oldCss.childNodes.length > 0 && css.childNodes.length > 0 &&
oldCss.firstChild.nodeValue === css.firstChild.nodeValue);
}
var head = document.getElementsByTagName('head')[0];
// If there is no oldCss, just append; otherwise, only append if we need
// to replace oldCss with an updated stylesheet
if (oldCss === null || keepOldCss === false) {
var nextEl = sheet && sheet.nextSibling || null;
if (nextEl) {
nextEl.parentNode.insertBefore(css, nextEl);
} else {
head.appendChild(css);
}
}
if (oldCss && keepOldCss === false) {
oldCss.parentNode.removeChild(oldCss);
}
// For IE.
// This needs to happen *after* the style element is added to the DOM, otherwise IE 7 and 8 may crash.
// See http://social.msdn.microsoft.com/Forums/en-US/7e081b65-878a-4c22-8e68-c10d39c2ed32/internet-explorer-crashes-appending-style-element-to-head
if (css.styleSheet) {
try {
css.styleSheet.cssText = styles;
} catch (e) {
throw new(Error)("Couldn't reassign styleSheet.cssText.");
}
}
// Don't update the local store if the file wasn't modified
if (lastModified && cache) {
log('saving ' + href + ' to cache.', logLevel.info);
try {
cache.setItem(href, styles);
cache.setItem(href + ':timestamp', lastModified);
} catch(e) {
//TODO - could do with adding more robust error handling
log('failed to save', logLevel.errors);
}
}
}
function postProcessCSS(styles) {
if (options.postProcessor && typeof options.postProcessor === 'function') {
styles = options.postProcessor.call(styles, styles) || styles;
}
return styles;
}
function errorHTML(e, rootHref) {
var id = 'less-error-message:' + extractId(rootHref || "");
var template = '<li><label>{line}</label><pre class="{class}">{content}</pre></li>';
var elem = document.createElement('div'), timer, content, errors = [];
var filename = e.filename || rootHref;
var filenameNoPath = filename.match(/([^\/]+(\?.*)?)$/)[1];
elem.id = id;
elem.className = "less-error-message";
content = '<h3>' + (e.type || "Syntax") + "Error: " + (e.message || 'There is an error in your .less file') +
'</h3>' + '<p>in <a href="' + filename + '">' + filenameNoPath + "</a> ";
var errorline = function (e, i, classname) {
if (e.extract[i] !== undefined) {
errors.push(template.replace(/\{line\}/, (parseInt(e.line, 10) || 0) + (i - 1))
.replace(/\{class\}/, classname)
.replace(/\{content\}/, e.extract[i]));
}
};
if (e.extract) {
errorline(e, 0, '');
errorline(e, 1, 'line');
errorline(e, 2, '');
content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':</p>' +
'<ul>' + errors.join('') + '</ul>';
} else if (e.stack) {
content += '<br/>' + e.stack.split('\n').slice(1).join('<br/>');
}
elem.innerHTML = content;
// CSS for error messages
createCSS([
'.less-error-message ul, .less-error-message li {',
'list-style-type: none;',
'margin-right: 15px;',
'padding: 4px 0;',
'margin: 0;',
'}',
'.less-error-message label {',
'font-size: 12px;',
'margin-right: 15px;',
'padding: 4px 0;',
'color: #cc7777;',
'}',
'.less-error-message pre {',
'color: #dd6666;',
'padding: 4px 0;',
'margin: 0;',
'display: inline-block;',
'}',
'.less-error-message pre.line {',
'color: #ff0000;',
'}',
'.less-error-message h3 {',
'font-size: 20px;',
'font-weight: bold;',
'padding: 15px 0 5px 0;',
'margin: 0;',
'}',
'.less-error-message a {',
'color: #10a',
'}',
'.less-error-message .error {',
'color: red;',
'font-weight: bold;',
'padding-bottom: 2px;',
'border-bottom: 1px dashed red;',
'}'
].join('\n'), { title: 'error-message' });
elem.style.cssText = [
"font-family: Arial, sans-serif",
"border: 1px solid #e00",
"background-color: #eee",
"border-radius: 5px",
"-webkit-border-radius: 5px",
"-moz-border-radius: 5px",
"color: #e00",
"padding: 15px",
"margin-bottom: 15px"
].join(';');
if (less.env == 'development') {
timer = setInterval(function () {
if (document.body) {
if (document.getElementById(id)) {
document.body.replaceChild(elem, document.getElementById(id));
} else {
document.body.insertBefore(elem, document.body.firstChild);
}
clearInterval(timer);
}
}, 10);
}
}
function error(e, rootHref) {
if (!options.errorReporting || options.errorReporting === "html") {
errorHTML(e, rootHref);
} else if (options.errorReporting === "console") {
errorConsole(e, rootHref);
} else if (typeof options.errorReporting === 'function') {
options.errorReporting("add", e, rootHref);
}
}
function removeErrorHTML(path) {
var node = document.getElementById('less-error-message:' + extractId(path));
if (node) {
node.parentNode.removeChild(node);
}
}
function removeErrorConsole(path) {
//no action
}
function removeError(path) {
if (!options.errorReporting || options.errorReporting === "html") {
removeErrorHTML(path);
} else if (options.errorReporting === "console") {
removeErrorConsole(path);
} else if (typeof options.errorReporting === 'function') {
options.errorReporting("remove", path);
}
}
function loadStyles(modifyVars) {
var styles = document.getElementsByTagName('style'),
style;
for (var i = 0; i < styles.length; i++) {
style = styles[i];
if (style.type.match(typePattern)) {
var env = new less.contexts.parseEnv(options),
lessText = style.innerHTML || '';
env.filename = document.location.href.replace(/#.*$/, '');
if (modifyVars || options.globalVars) {
env.useFileCache = true;
}
/*jshint loopfunc:true */
// use closure to store current value of i
var callback = (function(style) {
return function (e, cssAST) {
if (e) {
return error(e, "inline");
}
var css = cssAST.toCSS(options);
style.type = 'text/css';
if (style.styleSheet) {
style.styleSheet.cssText = css;
} else {
style.innerHTML = css;
}
};
})(style);
new(less.Parser)(env).parse(lessText, callback, {globalVars: options.globalVars, modifyVars: modifyVars});
}
}
}
function loadStyleSheet(sheet, callback, reload, remaining, modifyVars) {
var env = new less.contexts.parseEnv(options);
env.mime = sheet.type;
if (modifyVars || options.globalVars) {
env.useFileCache = true;
}
less.environment.loadFile(env, sheet.href, null, function loadInitialFileCallback(e, data, path, webInfo) {
var newFileInfo = {
currentDirectory: less.environment.getPath(env, path),
filename: path,
rootFilename: path,
relativeUrls: env.relativeUrls};
newFileInfo.entryPath = newFileInfo.currentDirectory;
newFileInfo.rootpath = env.rootpath || newFileInfo.currentDirectory;
if (webInfo) {
webInfo.remaining = remaining;
var css = cache && cache.getItem(path),
timestamp = cache && cache.getItem(path + ':timestamp');
if (!reload && timestamp && webInfo.lastModified &&
(new(Date)(webInfo.lastModified).valueOf() ===
new(Date)(timestamp).valueOf())) {
// Use local copy
createCSS(css, sheet);
webInfo.local = true;
callback(null, null, data, sheet, webInfo, path);
return;
}
}
//TODO add tests around how this behaves when reloading
removeError(path);
if (data) {
env.currentFileInfo = newFileInfo;
new(less.Parser)(env).parse(data, function (e, root) {
if (e) { return callback(e, null, null, sheet); }
try {
callback(e, root, data, sheet, webInfo, path);
} catch (e) {
callback(e, null, null, sheet);
}
}, {modifyVars: modifyVars, globalVars: options.globalVars});
} else {
callback(e, null, null, sheet, webInfo, path);
}
}, env, modifyVars);
}
function loadStyleSheets(callback, reload, modifyVars) {
for (var 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(function () {
if (less.watchMode) {
loadStyleSheets(function (e, root, _, sheet, env) {
if (e) {
error(e, sheet.href);
} else if (root) {
var styles = root.toCSS(less);
styles = postProcessCSS(styles);
createCSS(styles, sheet, env.lastModified);
}
});
}
}, 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; };
if (/!watch/.test(location.hash)) {
less.watch();
}
if (less.env != 'development') {
try {
cache = (typeof(window.localStorage) === 'undefined') ? null : window.localStorage;
} catch (_) {}
}
//
// Get all <link> tags with the 'rel' attribute set to "stylesheet/less"
//
var links = document.getElementsByTagName('link');
less.sheets = [];
for (var 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]);
}
}
//
// With this function, it's possible to alter variables and re-render
// CSS without reloading less-files
//
less.modifyVars = function(record) {
less.refresh(false, record);
};
less.refresh = function (reload, modifyVars) {
var startTime, endTime;
startTime = endTime = new Date();
loadStyleSheets(function (e, root, _, sheet, env) {
if (e) {
return error(e, sheet.href);
}
if (env.local) {
log("loading " + sheet.href + " from cache.", logLevel.info);
} else {
log("parsed " + sheet.href + " successfully.", logLevel.debug);
var styles = root.toCSS(options);
styles = postProcessCSS(styles);
createCSS(styles, sheet, env.lastModified);
}
log("css for " + sheet.href + " generated in " + (new Date() - endTime) + 'ms', logLevel.info);
if (env.remaining === 0) {
log("less has finished. css generated in " + (new Date() - startTime) + 'ms', logLevel.info);
}
endTime = new Date();
}, reload, modifyVars);
loadStyles(modifyVars);
};
less.refreshStyles = loadStyles;
less.refresh(less.env === 'development');
},{"./environment/browser.js":6,"./non-node-index.js":20}],2:[function(require,module,exports){
var contexts = {};
module.exports = contexts;
var copyFromOriginal = function copyFromOriginal(original, destination, propertiesToCopy) {
if (!original) { return; }
for(var i = 0; i < propertiesToCopy.length; i++) {
if (original.hasOwnProperty(propertiesToCopy[i])) {
destination[propertiesToCopy[i]] = original[propertiesToCopy[i]];
}
}
};
var parseCopyProperties = [
'paths', // option - unmodified - paths to search for imports on
'files', // list of files that have been imported, used for import-once
'contents', // map - filename to contents of all the files
'contentsIgnoredChars', // map - filename to lines at the begining of each file to ignore
'relativeUrls', // option - whether to adjust URL's to be relative
'rootpath', // option - rootpath to append to URL's
'strictImports', // option -
'insecure', // option - whether to allow imports from insecure ssl hosts
'dumpLineNumbers', // option - whether to dump line numbers
'compress', // option - whether to compress
'processImports', // option - whether to process imports. if false then imports will not be imported
'syncImport', // option - whether to import synchronously
'chunkInput', // option - whether to chunk input. more performant but causes parse issues.
'mime', // browser only - mime type for sheet import
'useFileCache', // browser only - whether to use the per file session cache
'currentFileInfo' // information about the current file - for error reporting and importing and making urls relative etc.
];
//currentFileInfo = {
// 'relativeUrls' - option - whether to adjust URL's to be relative
// 'filename' - full resolved filename of current file
// 'rootpath' - path to append to normal URLs for this node
// 'currentDirectory' - path to the current file, absolute
// 'rootFilename' - filename of the base file
// 'entryPath' - absolute path to the entry file
// 'reference' - whether the file should not be output and only output parts that are referenced
contexts.parseEnv = function(options) {
copyFromOriginal(options, this, parseCopyProperties);
if (!this.contents) { this.contents = {}; }
if (!this.contentsIgnoredChars) { this.contentsIgnoredChars = {}; }
if (!this.files) { this.files = {}; }
if (typeof this.paths === "string") { this.paths = [this.paths]; }
if (!this.currentFileInfo) {
var filename = (options && options.filename) || "input";
var entryPath = filename.replace(/[^\/\\]*$/, "");
if (options) {
options.filename = null;
}
this.currentFileInfo = {
filename: filename,
relativeUrls: this.relativeUrls,
rootpath: (options && options.rootpath) || "",
currentDirectory: entryPath,
entryPath: entryPath,
rootFilename: filename
};
}
};
var evalCopyProperties = [
'silent', // whether to swallow errors and warnings
'verbose', // whether to log more activity
'compress', // whether to compress
'yuicompress', // whether to compress with the outside tool yui compressor
'ieCompat', // whether to enforce IE compatibility (IE8 data-uri)
'strictMath', // whether math has to be within parenthesis
'strictUnits', // whether units need to evaluate correctly
'cleancss', // whether to compress with clean-css
'sourceMap', // whether to output a source map
'importMultiple', // whether we are currently importing multiple copies
'urlArgs', // whether to add args into url tokens
'javascriptEnabled'// option - whether JavaScript is enabled. if undefined, defaults to true
];
contexts.evalEnv = function(options, frames) {
copyFromOriginal(options, this, evalCopyProperties);
this.frames = frames || [];
};
contexts.evalEnv.prototype.inParenthesis = function () {
if (!this.parensStack) {
this.parensStack = [];
}
this.parensStack.push(true);
};
contexts.evalEnv.prototype.outOfParenthesis = function () {
this.parensStack.pop();
};
contexts.evalEnv.prototype.isMathOn = function () {
return this.strictMath ? (this.parensStack && this.parensStack.length) : true;
};
contexts.evalEnv.prototype.isPathRelative = function (path) {
return !/^(?:[a-z-]+:|\/)/.test(path);
};
contexts.evalEnv.prototype.normalizePath = function( path ) {
var
segments = path.split("/").reverse(),
segment;
path = [];
while (segments.length !== 0 ) {
segment = segments.pop();
switch( segment ) {
case ".":
break;
case "..":
if ((path.length === 0) || (path[path.length - 1] === "..")) {
path.push( segment );
} else {
path.pop();
}
break;
default:
path.push( segment );
break;
}
}
return path.join("/");
};
//todo - do the same for the toCSS env
//tree.toCSSEnv = function (options) {
//};
},{}],3:[function(require,module,exports){
module.exports = {
'aliceblue':'#f0f8ff',
'antiquewhite':'#faebd7',
'aqua':'#00ffff',
'aquamarine':'#7fffd4',
'azure':'#f0ffff',
'beige':'#f5f5dc',
'bisque':'#ffe4c4',
'black':'#000000',
'blanchedalmond':'#ffebcd',
'blue':'#0000ff',
'blueviolet':'#8a2be2',
'brown':'#a52a2a',
'burlywood':'#deb887',
'cadetblue':'#5f9ea0',
'chartreuse':'#7fff00',
'chocolate':'#d2691e',
'coral':'#ff7f50',
'cornflowerblue':'#6495ed',
'cornsilk':'#fff8dc',
'crimson':'#dc143c',
'cyan':'#00ffff',
'darkblue':'#00008b',
'darkcyan':'#008b8b',
'darkgoldenrod':'#b8860b',
'darkgray':'#a9a9a9',
'darkgrey':'#a9a9a9',
'darkgreen':'#006400',
'darkkhaki':'#bdb76b',
'darkmagenta':'#8b008b',
'darkolivegreen':'#556b2f',
'darkorange':'#ff8c00',
'darkorchid':'#9932cc',
'darkred':'#8b0000',
'darksalmon':'#e9967a',
'darkseagreen':'#8fbc8f',
'darkslateblue':'#483d8b',
'darkslategray':'#2f4f4f',
'darkslategrey':'#2f4f4f',
'darkturquoise':'#00ced1',
'darkviolet':'#9400d3',
'deeppink':'#ff1493',
'deepskyblue':'#00bfff',
'dimgray':'#696969',
'dimgrey':'#696969',
'dodgerblue':'#1e90ff',
'firebrick':'#b22222',
'floralwhite':'#fffaf0',
'forestgreen':'#228b22',
'fuchsia':'#ff00ff',
'gainsboro':'#dcdcdc',
'ghostwhite':'#f8f8ff',
'gold':'#ffd700',
'goldenrod':'#daa520',
'gray':'#808080',
'grey':'#808080',
'green':'#008000',
'greenyellow':'#adff2f',
'honeydew':'#f0fff0',
'hotpink':'#ff69b4',
'indianred':'#cd5c5c',
'indigo':'#4b0082',
'ivory':'#fffff0',
'khaki':'#f0e68c',
'lavender':'#e6e6fa',
'lavenderblush':'#fff0f5',
'lawngreen':'#7cfc00',
'lemonchiffon':'#fffacd',
'lightblue':'#add8e6',
'lightcoral':'#f08080',
'lightcyan':'#e0ffff',
'lightgoldenrodyellow':'#fafad2',
'lightgray':'#d3d3d3',
'lightgrey':'#d3d3d3',
'lightgreen':'#90ee90',
'lightpink':'#ffb6c1',
'lightsalmon':'#ffa07a',
'lightseagreen':'#20b2aa',
'lightskyblue':'#87cefa',
'lightslategray':'#778899',
'lightslategrey':'#778899',
'lightsteelblue':'#b0c4de',
'lightyellow':'#ffffe0',
'lime':'#00ff00',
'limegreen':'#32cd32',
'linen':'#faf0e6',
'magenta':'#ff00ff',
'maroon':'#800000',
'mediumaquamarine':'#66cdaa',
'mediumblue':'#0000cd',
'mediumorchid':'#ba55d3',
'mediumpurple':'#9370d8',
'mediumseagreen':'#3cb371',
'mediumslateblue':'#7b68ee',
'mediumspringgreen':'#00fa9a',
'mediumturquoise':'#48d1cc',
'mediumvioletred':'#c71585',
'midnightblue':'#191970',
'mintcream':'#f5fffa',
'mistyrose':'#ffe4e1',
'moccasin':'#ffe4b5',
'navajowhite':'#ffdead',
'navy':'#000080',
'oldlace':'#fdf5e6',
'olive':'#808000',
'olivedrab':'#6b8e23',
'orange':'#ffa500',
'orangered':'#ff4500',
'orchid':'#da70d6',
'palegoldenrod':'#eee8aa',
'palegreen':'#98fb98',
'paleturquoise':'#afeeee',
'palevioletred':'#d87093',
'papayawhip':'#ffefd5',
'peachpuff':'#ffdab9',
'peru':'#cd853f',
'pink':'#ffc0cb',
'plum':'#dda0dd',
'powderblue':'#b0e0e6',
'purple':'#800080',
'red':'#ff0000',
'rosybrown':'#bc8f8f',
'royalblue':'#4169e1',
'saddlebrown':'#8b4513',
'salmon':'#fa8072',
'sandybrown':'#f4a460',
'seagreen':'#2e8b57',
'seashell':'#fff5ee',
'sienna':'#a0522d',
'silver':'#c0c0c0',
'skyblue':'#87ceeb',
'slateblue':'#6a5acd',
'slategray':'#708090',
'slategrey':'#708090',
'snow':'#fffafa',
'springgreen':'#00ff7f',
'steelblue':'#4682b4',
'tan':'#d2b48c',
'teal':'#008080',
'thistle':'#d8bfd8',
'tomato':'#ff6347',
'turquoise':'#40e0d0',
'violet':'#ee82ee',
'wheat':'#f5deb3',
'white':'#ffffff',
'whitesmoke':'#f5f5f5',
'yellow':'#ffff00',
'yellowgreen':'#9acd32'
};
},{}],4:[function(require,module,exports){
module.exports = {
colors: require("./colors.js"),
unitConversions: require("./unit-conversions.js")
};
},{"./colors.js":3,"./unit-conversions.js":5}],5:[function(require,module,exports){
module.exports = {
length: {
'm': 1,
'cm': 0.01,
'mm': 0.001,
'in': 0.0254,
'px': 0.0254 / 96,
'pt': 0.0254 / 72,
'pc': 0.0254 / 72 * 12
},
duration: {
's': 1,
'ms': 0.001
},
angle: {
'rad': 1/(2*Math.PI),
'deg': 1/360,
'grad': 1/400,
'turn': 1
}
};
},{}],6:[function(require,module,exports){
/*global window, XMLHttpRequest */
module.exports = function(options, isFileProtocol, log, logLevel) {
var fileCache = {};
//TODOS - move log somewhere. pathDiff and doing something similar in node. use pathDiff in the other browser file for the initial load
// isFileProtocol is global
function getXMLHttpRequest() {
if (window.XMLHttpRequest && (window.location.protocol !== "file:" || !("ActiveXObject" in window))) {
return new XMLHttpRequest();
} else {
try {
/*global ActiveXObject */
return new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {
log("browser doesn't support AJAX.", logLevel.errors);
return null;
}
}
}
return {
// make generic but overriddable
warn: function warn(env, msg) {
console.warn(msg);
},
// make generic but overriddable
getPath: function getPath(env, filename) {
var j = filename.lastIndexOf('/');
if (j < 0) {
j = filename.lastIndexOf('\\');
}
if (j < 0) {
return "";
}
return filename.slice(0, j + 1);
},
// make generic but overriddable
isPathAbsolute: function isPathAbsolute(env, filename) {
return /^(?:[a-z-]+:|\/|\\)/i.test(filename);
},
alwaysMakePathsAbsolute: function alwaysMakePathsAbsolute() {
return true;
},
getCleanCSS: function () {
},
supportsDataURI: function() {
return false;
},
pathDiff: function pathDiff(url, baseUrl) {
// diff between two paths to create a relative path
var urlParts = this.extractUrlParts(url),
baseUrlParts = this.extractUrlParts(baseUrl),
i, max, urlDirectories, baseUrlDirectories, diff = "";
if (urlParts.hostPart !== baseUrlParts.hostPart) {
return "";
}
max = Math.max(baseUrlParts.directories.length, urlParts.directories.length);
for(i = 0; i < max; i++) {
if (baseUrlParts.directories[i] !== urlParts.directories[i]) { break; }
}
baseUrlDirectories = baseUrlParts.directories.slice(i);
urlDirectories = urlParts.directories.slice(i);
for(i = 0; i < baseUrlDirectories.length-1; i++) {
diff += "../";
}
for(i = 0; i < urlDirectories.length-1; i++) {
diff += urlDirectories[i] + "/";
}
return diff;
},
join: function join(basePath, laterPath) {
if (!basePath) {
return laterPath;
}
return this.extractUrlParts(laterPath, basePath).path;
},
// helper function, not part of API
extractUrlParts: function extractUrlParts(url, baseUrl) {
// urlParts[1] = protocol&hostname || /
// urlParts[2] = / if path relative to host base
// urlParts[3] = directories
// urlParts[4] = filename
// urlParts[5] = parameters
var urlPartsRegex = /^((?:[a-z-]+:)?\/+?(?:[^\/\?#]*\/)|([\/\\]))?((?:[^\/\\\?#]*[\/\\])*)([^\/\\\?#]*)([#\?].*)?$/i,
urlParts = url.match(urlPartsRegex),
returner = {}, directories = [], i, baseUrlParts;
if (!urlParts) {
throw new Error("Could not parse sheet href - '"+url+"'");
}
// Stylesheets in IE don't always return the full path
if (!urlParts[1] || urlParts[2]) {
baseUrlParts = baseUrl.match(urlPartsRegex);
if (!baseUrlParts) {
throw new Error("Could not parse page url - '"+baseUrl+"'");
}
urlParts[1] = urlParts[1] || baseUrlParts[1] || "";
if (!urlParts[2]) {
urlParts[3] = baseUrlParts[3] + urlParts[3];
}
}
if (urlParts[3]) {
directories = urlParts[3].replace(/\\/g, "/").split("/");
// extract out . before .. so .. doesn't absorb a non-directory
for(i = 0; i < directories.length; i++) {
if (directories[i] === ".") {
directories.splice(i, 1);
i -= 1;
}
}
for(i = 0; i < directories.length; i++) {
if (directories[i] === ".." && i > 0) {
directories.splice(i-1, 2);
i -= 2;
}
}
}
returner.hostPart = urlParts[1];
returner.directories = directories;
returner.path = urlParts[1] + directories.join("/");
returner.fileUrl = returner.path + (urlParts[4] || "");
returner.url = returner.fileUrl + (urlParts[5] || "");
return returner;
},
doXHR: function doXHR(url, type, callback, errback) {
var xhr = getXMLHttpRequest();
var async = isFileProtocol ? options.fileAsync : options.async;
if (typeof(xhr.overrideMimeType) === 'function') {
xhr.overrideMimeType('text/css');
}
log("XHR: Getting '" + url + "'", logLevel.debug);
xhr.open('GET', url, async);
xhr.setRequestHeader('Accept', type || 'text/x-less, text/css; q=0.9, */*; q=0.5');
xhr.send(null);
function handleResponse(xhr, callback, errback) {
if (xhr.status >= 200 && xhr.status < 300) {
callback(xhr.responseText,
xhr.getResponseHeader("Last-Modified"));
} else if (typeof(errback) === 'function') {
errback(xhr.status, url);
}
}
if (isFileProtocol && !options.fileAsync) {
if (xhr.status === 0 || (xhr.status >= 200 && xhr.status < 300)) {
callback(xhr.responseText);
} else {
errback(xhr.status, url);
}
} else if (async) {
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
handleResponse(xhr, callback, errback);
}
};
} else {
handleResponse(xhr, callback, errback);
}
},
loadFile: function loadFile(env, filename, currentDirectory, callback) {
if (currentDirectory && !this.isPathAbsolute(env, filename)) {
filename = currentDirectory + filename;
}
// sheet may be set to the stylesheet for the initial load or a collection of properties including
// some env variables for imports
var hrefParts = this.extractUrlParts(filename, window.location.href);
var href = hrefParts.url;
if (env.useFileCache && fileCache[href]) {
try {
var lessText = fileCache[href];
callback(null, lessText, href, { lastModified: new Date() });
} catch (e) {
callback(e, null, href);
}
return;
}
this.doXHR(href, env.mime, function doXHRCallback(data, lastModified) {
// per file cache
fileCache[href] = data;
// Use remote copy (re-parse)
callback(null, data, href, { lastModified: lastModified });
}, function doXHRError(status, url) {
callback({ type: 'File', message: "'" + url + "' wasn't found (" + status + ")" }, null, href);
});
}
};
};
},{}],7:[function(require,module,exports){
var Color = require("../tree/color.js"),
functionRegistry = require("./function-registry.js");
// Color Blending
// ref: http://www.w3.org/TR/compositing-1
function colorBlend(mode, color1, color2) {
var ab = color1.alpha, cb, // backdrop
as = color2.alpha, cs, // source
ar, cr, r = []; // result
ar = as + ab * (1 - as);
for (var i = 0; i < 3; i++) {
cb = color1.rgb[i] / 255;
cs = color2.rgb[i] / 255;
cr = mode(cb, cs);
if (ar) {
cr = (as * cs + ab * (cb -
as * (cb + cs - cr))) / ar;
}
r[i] = cr * 255;
}
return new(Color)(r, ar);
}
var colorBlendModeFunctions = {
multiply: function(cb, cs) {
return cb * cs;
},
screen: function(cb, cs) {
return cb + cs - cb * cs;
},
overlay: function(cb, cs) {
cb *= 2;
return (cb <= 1)
? colorBlendModeFunctions.multiply(cb, cs)
: colorBlendModeFunctions.screen(cb - 1, cs);
},
softlight: function(cb, cs) {
var d = 1, e = cb;
if (cs > 0.5) {
e = 1;
d = (cb > 0.25) ? Math.sqrt(cb)
: ((16 * cb - 12) * cb + 4) * cb;
}
return cb - (1 - 2 * cs) * e * (d - cb);
},
hardlight: function(cb, cs) {
return colorBlendModeFunctions.overlay(cs, cb);
},
difference: function(cb, cs) {
return Math.abs(cb - cs);
},
exclusion: function(cb, cs) {
return cb + cs - 2 * cb * cs;
},
// non-w3c functions:
average: function(cb, cs) {
return (cb + cs) / 2;
},
negation: function(cb, cs) {
return 1 - Math.abs(cb + cs - 1);
}
};
for (var f in colorBlendModeFunctions) {
if (colorBlendModeFunctions.hasOwnProperty(f)) {
colorBlend[f] = colorBlend.bind(null, colorBlendModeFunctions[f]);
}
}
functionRegistry.addMultiple(colorBlend);
},{"../tree/color.js":31,"./function-registry.js":12}],8:[function(require,module,exports){
var Dimension = require("../tree/dimension.js"),
Color = require("../tree/color.js"),
Quoted = require("../tree/quoted.js"),
Anonymous = require("../tree/anonymous.js"),
functionRegistry = require("./function-registry.js"),
colorFunctions;
function clamp(val) {
return Math.min(1, Math.max(0, val));
}
function hsla(color) {
return colorFunctions.hsla(color.h, color.s, color.l, color.a);
}
function number(n) {
if (n instanceof Dimension) {
return parseFloat(n.unit.is('%') ? n.value / 100 : n.value);
} else if (typeof(n) === 'number') {
return n;
} else {
throw {
error: "RuntimeError",
message: "color functions take numbers as parameters"
};
}
}
function scaled(n, size) {
if (n instanceof Dimension && n.unit.is('%')) {
return parseFloat(n.value * size / 100);
} else {
return number(n);
}
}
colorFunctions = {
rgb: function (r, g, b) {
return colorFunctions.rgba(r, g, b, 1.0);
},
rgba: function (r, g, b, a) {
var rgb = [r, g, b].map(function (c) { return scaled(c, 255); });
a = number(a);
return new(Color)(rgb, a);
},
hsl: function (h, s, l) {
return colorFunctions.hsla(h, s, l, 1.0);
},
hsla: function (h, s, l, a) {
function hue(h) {
h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h);
if (h * 6 < 1) { return m1 + (m2 - m1) * h * 6; }
else if (h * 2 < 1) { return m2; }
else if (h * 3 < 2) { return m1 + (m2 - m1) * (2/3 - h) * 6; }
else { return m1; }
}
h = (number(h) % 360) / 360;
s = clamp(number(s)); l = clamp(number(l)); a = clamp(number(a));
var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s;
var m1 = l * 2 - m2;
return colorFunctions.rgba(hue(h + 1/3) * 255,
hue(h) * 255,
hue(h - 1/3) * 255,
a);
},
hsv: function(h, s, v) {
return colorFunctions.hsva(h, s, v, 1.0);
},
hsva: function(h, s, v, a) {
h = ((number(h) % 360) / 360) * 360;
s = number(s); v = number(v); a = number(a);
var i, f;
i = Math.floor((h / 60) % 6);
f = (h / 60) - i;
var vs = [v,
v * (1 - s),
v * (1 - f * s),
v * (1 - (1 - f) * s)];
var perm = [[0, 3, 1],
[2, 0, 1],
[1, 0, 3],
[1, 2, 0],
[3, 1, 0],
[0, 1, 2]];
return colorFunctions.rgba(vs[perm[i][0]] * 255,
vs[perm[i][1]] * 255,
vs[perm[i][2]] * 255,
a);
},
hue: function (color) {
return new(Dimension)(color.toHSL().h);
},
saturation: function (color) {
return new(Dimension)(color.toHSL().s * 100, '%');
},
lightness: function (color) {
return new(Dimension)(color.toHSL().l * 100, '%');
},
hsvhue: function(color) {
return new(Dimension)(color.toHSV().h);
},
hsvsaturation: function (color) {
return new(Dimension)(color.toHSV().s * 100, '%');
},
hsvvalue: function (color) {
return new(Dimension)(color.toHSV().v * 100, '%');
},
red: function (color) {
return new(Dimension)(color.rgb[0]);
},
green: function (color) {
return new(Dimension)(color.rgb[1]);
},
blue: function (color) {
return new(Dimension)(color.rgb[2]);
},
alpha: function (color) {
return new(Dimension)(color.toHSL().a);
},
luma: function (color) {
return new(Dimension)(color.luma() * color.alpha * 100, '%');
},
luminance: function (color) {
var luminance =
(0.2126 * color.rgb[0] / 255)
+ (0.7152 * color.rgb[1] / 255)
+ (0.0722 * color.rgb[2] / 255);
return new(Dimension)(luminance * color.alpha * 100, '%');
},
saturate: function (color, amount) {
// filter: saturate(3.2);
// should be kept as is, so check for color
if (!color.rgb) {
return null;
}
var hsl = color.toHSL();
hsl.s += amount.value / 100;
hsl.s = clamp(hsl.s);
return hsla(hsl);
},
desaturate: function (color, amount) {
var hsl = color.toHSL();
hsl.s -= amount.value / 100;
hsl.s = clamp(hsl.s);
return hsla(hsl);
},
lighten: function (color, amount) {
var hsl = color.toHSL();
hsl.l += amount.value / 100;
hsl.l = clamp(hsl.l);
return hsla(hsl);
},
darken: function (color, amount) {
var hsl = color.toHSL();
hsl.l -= amount.value / 100;
hsl.l = clamp(hsl.l);
return hsla(hsl);
},
fadein: function (color, amount) {
var hsl = color.toHSL();
hsl.a += amount.value / 100;
hsl.a = clamp(hsl.a);
return hsla(hsl);
},
fadeout: function (color, amount) {
var hsl = color.toHSL();
hsl.a -= amount.value / 100;
hsl.a = clamp(hsl.a);
return hsla(hsl);
},
fade: function (color, amount) {
var hsl = color.toHSL();
hsl.a = amount.value / 100;
hsl.a = clamp(hsl.a);
return hsla(hsl);
},
spin: function (color, amount) {
var hsl = color.toHSL();
var hue = (hsl.h + amount.value) % 360;
hsl.h = hue < 0 ? 360 + hue : hue;
return hsla(hsl);
},
//
// Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein
// http://sass-lang.com
//
mix: function (color1, color2, weight) {
if (!weight) {
weight = new(Dimension)(50);
}
var p = weight.value / 100.0;
var w = p * 2 - 1;
var a = color1.toHSL().a - color2.toHSL().a;
var w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0;
var w2 = 1 - w1;
var rgb = [color1.rgb[0] * w1 + color2.rgb[0] * w2,
color1.rgb[1] * w1 + color2.rgb[1] * w2,
color1.rgb[2] * w1 + color2.rgb[2] * w2];
var alpha = color1.alpha * p + color2.alpha * (1 - p);
return new(Color)(rgb, alpha);
},
greyscale: function (color) {
return colorFunctions.desaturate(color, new(Dimension)(100));
},
contrast: function (color, dark, light, threshold) {
// filter: contrast(3.2);
// should be kept as is, so check for color
if (!color.rgb) {
return null;
}
if (typeof light === 'undefined') {
light = colorFunctions.rgba(255, 255, 255, 1.0);
}
if (typeof dark === 'undefined') {
dark = colorFunctions.rgba(0, 0, 0, 1.0);
}
//Figure out which is actually light and dark!
if (dark.luma() > light.luma()) {
var t = light;
light = dark;
dark = t;
}
if (typeof threshold === 'undefined') {
threshold = 0.43;
} else {
threshold = number(threshold);
}
if (color.luma() < threshold) {
return light;
} else {
return dark;
}
},
argb: function (color) {
return new(Anonymous)(color.toARGB());
},
color: function(c) {
if ((c instanceof Quoted) &&
(/^#([a-f0-9]{6}|[a-f0-9]{3})$/i.test(c.value))) {
return new(Color)(c.value.slice(1));
}
if ((c instanceof Color) || (c = Color.fromKeyword(c.value))) {
c.keyword = undefined;
return c;
}
throw {
type: "Argument",
message: "argument must be a color keyword or 3/6 digit hex e.g. #FFF"
};
},
tint: function(color, amount) {
return colorFunctions.mix(colorFunctions.rgb(255,255,255), color, amount);
},
shade: function(color, amount) {
return colorFunctions.mix(colorFunctions.rgb(0, 0, 0), color, amount);
}
};
functionRegistry.addMultiple(colorFunctions);
},{"../tree/anonymous.js":27,"../tree/color.js":31,"../tree/dimension.js":37,"../tree/quoted.js":54,"./function-registry.js":12}],9:[function(require,module,exports){
module.exports = function(environment) {
var Anonymous = require("../tree/anonymous.js"),
URL = require("../tree/url.js"),
functionRegistry = require("./function-registry.js");
functionRegistry.add("data-uri", function(mimetypeNode, filePathNode) {
if (!environment.supportsDataURI(this.env)) {
return new URL(filePathNode || mimetypeNode, this.currentFileInfo).eval(this.env);
}
var mimetype = mimetypeNode.value;
var filePath = (filePathNode && filePathNode.value);
var useBase64 = false;
if (arguments.length < 2) {
filePath = mimetype;
}
var fragmentStart = filePath.indexOf('#');
var fragment = '';
if (fragmentStart!==-1) {
fragment = filePath.slice(fragmentStart);
filePath = filePath.slice(0, fragmentStart);
}
if (this.env.isPathRelative(filePath)) {
if (this.currentFileInfo.relativeUrls) {
filePath = environment.join(this.currentFileInfo.currentDirectory, filePath);
} else {
filePath = environment.join(this.currentFileInfo.entryPath, filePath);
}
}
// detect the mimetype if not given
if (arguments.length < 2) {
mimetype = environment.mimeLookup(this.env, filePath);
// use base 64 unless it's an ASCII or UTF-8 format
var charset = environment.charsetLookup(this.env, mimetype);
useBase64 = ['US-ASCII', 'UTF-8'].indexOf(charset) < 0;
if (useBase64) { mimetype += ';base64'; }
}
else {
useBase64 = /;base64$/.test(mimetype);
}
var buf = environment.readFileSync(filePath);
// IE8 cannot handle a data-uri larger than 32KB. If this is exceeded
// and the --ieCompat flag is enabled, return a normal url() instead.
var DATA_URI_MAX_KB = 32,
fileSizeInKB = parseInt((buf.length / 1024), 10);
if (fileSizeInKB >= DATA_URI_MAX_KB) {
if (this.env.ieCompat !== false) {
if (!this.env.silent) {
console.warn("Skipped data-uri embedding of %s because its size (%dKB) exceeds IE8-safe %dKB!", filePath, fileSizeInKB, DATA_URI_MAX_KB);
}
return new URL(filePathNode || mimetypeNode, this.currentFileInfo).eval(this.env);
}
}
buf = useBase64 ? buf.toString('base64')
: encodeURIComponent(buf);
var uri = "\"data:" + mimetype + ',' + buf + fragment + "\"";
return new(URL)(new(Anonymous)(uri));
});
};
},{"../tree/anonymous.js":27,"../tree/url.js":61,"./function-registry.js":12}],10:[function(require,module,exports){
var Keyword = require("../tree/keyword.js"),
functionRegistry = require("./function-registry.js");
var defaultFunc = {
eval: function () {
var v = this.value_, e = this.error_;
if (e) {
throw e;
}
if (v != null) {
return v ? Keyword.True : Keyword.False;
}
},
value: function (v) {
this.value_ = v;
},
error: function (e) {
this.error_ = e;
},
reset: function () {
this.value_ = this.error_ = null;
}
};
functionRegistry.add("default", defaultFunc.eval.bind(defaultFunc));
module.exports = defaultFunc;
},{"../tree/keyword.js":46,"./function-registry.js":12}],11:[function(require,module,exports){
var functionRegistry = require("./function-registry.js");
var functionCaller = function(name, env, currentFileInfo) {
this.name = name.toLowerCase();
this.function = functionRegistry.get(this.name);
this.env = env;
this.currentFileInfo = currentFileInfo;
};
functionCaller.prototype.isValid = function() {
return Boolean(this.function);
};
functionCaller.prototype.call = function(args) {
return this.function.apply(this, args);
};
module.exports = functionCaller;
},{"./function-registry.js":12}],12:[function(require,module,exports){
module.exports = {
_data: {},
add: function(name, func) {
if (this._data.hasOwnProperty(name)) {
//TODO warn
}
this._data[name] = func;
},
addMultiple: function(functions) {
Object.keys(functions).forEach(
function(name) {
this.add(name, functions[name]);
}.bind(this));
},
get: function(name) {
return this._data[name];
}
};
},{}],13:[function(require,module,exports){
module.exports = function(environment) {
var functions = {
functionRegistry: require("./function-registry.js"),
functionCaller: require("./function-caller.js")
};
//register functions
require("./default.js");
require("./color.js");
require("./color-blending.js");
require("./data-uri.js")(environment);
require("./math.js");
require("./number.js");
require("./string.js");
require("./svg.js")(environment);
require("./types.js");
return functions;
};
},{"./color-blending.js":7,"./color.js":8,"./data-uri.js":9,"./default.js":10,"./function-caller.js":11,"./