UNPKG

funcunit

Version:
1,552 lines (1,373 loc) 295 kB
(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,"./