UNPKG

@extjs/sencha-cmd-linux-32

Version:

Productivity and performance optimization tool for building applications with Sencha Ext JS and Sencha Touch.

1,583 lines (1,394 loc) 50.5 kB
"use strict"; var Fashion = require('./export/Base.js'); var Visitor = require('./Visitor.js'); var Preprocessor = require('./Preprocessor.js'); var Output = require('./export/Output.js'); var Parser = require('./parse/Parser.js'); var Scanner = require('./parse/Scanner.js'); var Color = require('./export/type/Color.js'); var Runtime = require('./Runtime.js'); var Nodes = require('./parse/ast/Nodes.js'), List = Nodes.List, SelectorList = Nodes.SelectorList, Constant = Nodes.Constant, FunctionCall = Nodes.FunctionCall, Variable = Nodes.Variable, VariableAssignment = Nodes.VariableAssignment; class StringCache { constructor() { this.array = []; this.map = {}; } addString(string) { var idx = this.map[string]; if (typeof idx === 'undefined') { idx = this.array.length; this.array.push(string); this.map[string] = idx; } return idx; } get(id) { return this.array[id]; } } class ObjCache { constructor() { this.array = []; } addObj(obj) { var idx = this.array.length; this.array.push(obj); return idx; } get(id) { return this.array[id]; } } class Transpiler extends Visitor { reset() { this.output = new Output(); this.currentScope = { __suffix: '', __isGlobal: true }; this.globalScope = this.currentScope; this.globalVars = {}; this.errors = 0; this.warnings = 0; this.stringCache = new StringCache(); this.docCache = new ObjCache(); this.nodeCache = new ObjCache(); } createScope(parent) { parent = parent || this.currentScope; var scope = Fashion.chain(parent); scope.__suffix = scope.__suffix + '$'; return scope; } getScopeName(name, scope) { //scope = scope || this.currentScope; // //if(scope.hasOwnProperty(name)) { // return scope[name]; //} return Fashion.getJsName(name); } getVariableName(node) { return node.variable || node.name || node.value || node; } handleInlineExpression(expr) { try { var outwas = this.output, output = new Output(), parser = this.inlineParser || (this.inlineParser = new Parser()), tree; if (this.isSelector) { parser.scanner = new Scanner(expr); tree = parser.parseSequence(); } else { tree = parser.parse('$foobar: ' + expr + ';'); tree = tree[0].value; } this.output = output; this.handleStatement(tree); this.output = outwas; return output.get().trim(); } catch (error) { Fashion.log("failed to evaluate inline expression : " + expr); throw error; } } handleInlineExpressions(text, start, skipEscape) { text = text + ''; start = start || 0; var out = [], level = 0, outwas, i, ch, ch2; outer: for (i = start; i < text.length; i++) { ch = text.charAt(i); ch2 = (i < text.length - 1) ? text.charAt(i + 1) : undefined; switch (ch) { case '\\': if (!outwas && !skipEscape) { out.push('\\\\'); } else { out.push(ch); } break; case '"': if (!outwas && !skipEscape) { out.push('\\"'); } else { out.push(ch); } break; case '#': if (ch2 === '{') { level++; if (level < 2) { outwas = out; out = []; i++; } else { out.push(ch); } } else { out.push(ch); } break; case '}': level--; if (!level) { outwas.push('" + __rt_unquote('); outwas.push(this.handleInlineExpression(out.join(''))); outwas.push(') + "'); out = outwas; outwas = undefined; } else { out.push(ch); } break; default: out.push(ch); break } } return out.join(''); } addSourceInfo(item) { if (!this.symbols) { return; } item = item || this.nodeStack[this.nodeStack.length - 1]; if (item && (item.lineNumber || item.file)) { this.output.add("__rt_pushSourceInfo([" + "" + item.lineNumber + ", '" + (item.file || "source-code") + "'])"); this.output.add(';'); } } createCallStackScope() { if (!this.symbols) { return; } this.output.addln("__rt_createCallStackScope();"); } popCallStackScope() { if (!this.symbols) { return; } this.output.addln("__rt_popCallStackScope();"); } handleStatements(statements) { if (this.symbols) { this.addSourceInfo(); } this.visit(statements); } handleStatement(statement) { if (statement && statement.hasOwnProperty('visitTarget')) { statement = statement.visitTarget; if (statement && Array.isArray(statement)) { this.handleStatements(statement); } } if (statement) { if (statement instanceof Array) { statement = new List(null, statement, ','); } this.visit(statement); } } createDefaultScopeMap(args, isMixin) { args = this.loadArgsArray(args); var output = this.output, defaulted = 0, arg, a, varName, jsName, name; this.isSignatureDeclaration = true; this.generateGets = true; for (a = 0; a < args.length; a++) { arg = args[a]; if (arg) { varName = (arg.variable || arg.name); name = varName; jsName = this.getScopeName(varName); this.currentScope[jsName] = { name: jsName, param: true }; varName = jsName; if (arg.varArgs) { output.addln(varName + ' = __rt_sliceArgs(arguments, ' + (isMixin ? a + 1 : a) + ');'); defaulted++; } else if (arg.type !== 'Variable' || arg.variable !== undefined) { output.addln('var ' + varName + ' = ' + varName + ' || '); this.handleStatement(arg); output.add(';'); defaulted++; } else { output.addln('var ' + varName + ' = ' + varName + ' || __Null;'); } output.addln('__rt_set("' + jsName + '", ' + varName + ', true);'); } } this.generateGets = false; this.isSignatureDeclaration = false; return defaulted; } getRegisteredDeclarationsMap(declaredParameters) { var map = {}, param; for (var d = 0; d < declaredParameters.length; d++) { param = declaredParameters[d]; map[param.name] = param; } return map; } createCallArray(args, defaults, id, convertName, addComma) { args = this.loadArgsArray(args); if (defaults.parameters) { defaults = defaults.parameters; } var me = this, output = me.output, len = args.length > defaults.length ? args.length : defaults.length, declaredMap = me.getRegisteredDeclarationsMap(defaults), actual = new Array(len), arg, a, position; for (var a = 0; a < args.length; a++) { arg = args[a]; position = a; if (arg && arg.variable) { var argName = arg.variable; if (convertName) { if (argName.indexOf("$") == 0) { argName = argName.substr(1); } argName = argName.replace(/\-/g, '_'); } if (!declaredMap[argName]) { var params = []; for (var pName in declaredMap) { params.push(pName); } Fashion.warn("function or mixin '" + id + "' had no parameter named " + argName + " : params were : " + params.join(", ")); // if a named parameter didn't match a parameter from the // call signature, skip it and let the default value be used continue; } else { position = declaredMap[argName].position; } } actual[position] = arg; } for (a = 0; a < actual.length; a++) { arg = actual[a]; if (addComma || (a > 0)) { output.add(','); output.space(); } if (arg) { output.addln(); if (arg.varArgs) { output.add('__rt_applySpread('); me.handleStatement(arg); output.add(')'); } else { me.handleStatement(arg); } } else { output.addln("__udf"); } } return actual.length; } escapeString(str) { return str && str.replace(/\\/g, "\\\\").replace(/"/g, '\\"'); } //<editor-fold desc="visitor methods"> Each(statement) { if (statement.isMap) { var me = this, output = me.output, arg = statement.variable, names = statement.variable.items; me.eachCount = me.eachCount || 1; var jsNames = Fashion.convert(names, (name) => me.getScopeName(name)), jsItrName = '__each_itr_' + me.eachCount, jsListName = '__each__list'; names.forEach((name, i) => this.currentScope[jsNames[i]] = jsNames[i]); output.addln("var " + jsListName + " = "); me.handleStatement(statement.list); output.add(";"); output.addln("for(var " + jsItrName + " = 0; " + jsItrName + " < " + jsListName + ".items.length - 1; " + jsItrName + "+=2) {"); output.indent(); output.addln('__rt_set("' + jsNames[0] + '", ' + jsListName + ".items[" + jsItrName + "]);"); output.addln('__rt_set("' + jsNames[1] + '", ' + jsListName + ".items[" + jsItrName + " + 1]);"); me.handleStatements(statement.statements); output.unindentln("}"); } else { var me = this, output = me.output, arg = statement.variable, name = me.getVariableName(arg), jsName = me.getScopeName(name), jsListName = jsName + "__list", jsItrName = jsName + "__itr"; this.currentScope[jsItrName] = jsItrName; this.currentScope[jsListName] = jsListName; this.currentScope[jsName] = jsName; output.addln("var " + jsListName + " = "); me.handleStatement(statement.list); output.add(";"); output.addln("for(var " + jsItrName + " = 0; " + jsItrName + " < " + jsListName + ".items.length; " + jsItrName + "++) {"); output.indent(); output.addln('__rt_set("' + jsName + '", ' + jsListName + ".items[" + jsItrName + "]);"); me.handleStatements(statement.statements); output.unindentln("}"); } return false; } For(statement) { var me = this, output = me.output, arg = statement.variable, name = me.getVariableName(arg), jsName = me.getScopeName(name), jsItrName = jsName + "__itr"; this.currentScope[jsName] = jsName; output.addln('for(var ' + jsItrName + ' = __rt_unbox('); me.handleStatement(statement.start); output.add('), end = (__rt_unbox('); me.handleStatement(statement.end); output.add(')'); if (!!statement.inclusive) { output.add(' + 1'); } output.add('); ' + jsItrName + ' < end; '+ jsItrName + '++){'); output.indent(); output.addln('var ' + jsName + ' = ' + jsItrName); output.addln('__rt_set("' + jsName + '", ' + jsItrName + ', true);'); me.handleStatements(statement.statements); output.unindentln('};'); return false; } While(statement) { var output = this.output; output.addln("while(__rt_unbox("); this.handleStatement(statement.condition); output.add(")) {"); output.indent(); this.handleStatements(statement.statements); output.unindentln("};"); return false; } Function(statement) { var me = this, output = me.output, func = statement.func, jsName = Fashion.getJsName(func.id || func.value); if (jsName === 'dynamic') { me.error("Cannot define function named 'dynamic'", statement); } if (jsName === 'require') { me.error("Cannot define function named 'require'", statement); } me.nestedDocs = true; var scopeWas = me.currentScope; me.currentScope = me.createScope(); output.addln('function ' + jsName + '__fn('); var args = me.loadArgsArray(func.args || []); for (var i = 0; i < args.length; i++) { var arg = args[i]; var varName = (arg.variable || arg.name); varName = me.getScopeName(varName); if (i > 0) { output.add(','); output.space(); } output.add(varName); } output.add(') {'); output.indent(); // load the defaults output.addln('__rt_createScope(__rt_functions.' + jsName + ' && __rt_functions.' + jsName + '.createdScope);'); if (this.symbols) { me.createCallStackScope(); } if (this.symbols) { this.addSourceInfo(); } me.createDefaultScopeMap(func.args); this.popScope = true; // Handle all the statements within this function if (statement.statements.length) { me.handleStatements(statement.statements); } me.currentScope = scopeWas; if (this.popScope) { if (this.symbols) { me.popCallStackScope(); } output.addln("__rt_popScope();"); this.popScope = false; } output.unindentln('};'); output.addln('__rt_functions.' + jsName + ' = ' + jsName + '__fn;'); output.addln('__rt_functions.' + jsName + '.createdScope = __rt_getCurrentScope();'); me.nestedDocs = false; return false; } Ruleset(statement, fnName) { fnName = fnName || '__rt_ruleset'; var me = this, output = me.output, isGlobal = me.nodeStack.length === 1, newScope = false, docIdx = -1, blockDocIdx = -1, hasBlock = !!statement.statements; output.addln(fnName + '('); this.isSelector = statement.selectors; this.handleStatement(statement.selectors); this.isSelector = null; if (statement.file) { var fileIdx = this.stringCache.addString(statement.file); output.add(",__rt_getString(" + fileIdx + ") + \":" + statement.lineNumber + "\""); } else { output.add(', null'); } if (statement.docs && statement.docs.length) { docIdx = this.docCache.addObj(statement.docs); output.add(',__rt_getDocs(' + docIdx + ')'); } else { output.add(', null'); } if (statement.blockDocs && statement.blockDocs.length) { blockDocIdx = this.docCache.addObj(statement.blockDocs); output.add(',__rt_getDocs(' + blockDocIdx + ')'); } else { output.add(', null'); } output.add(', ' + hasBlock); output.add(");"); if (isGlobal && Runtime.uniqueScopesForGlobalRulesets) { newScope = true; } if (Runtime.uniqueScopesForAllRulesets) { newScope = true; } if (newScope) { var scopeWas = me.currentScope; me.currentScope = me.createScope(); output.addln("__rt_createScope();") me.handleStatements(statement.statements); output.addln("__rt_popScope();") me.currentScope = scopeWas; } else { me.handleStatements(statement.statements); } output.addln("__rt_rulesetDone();"); me.nestedDocs = false; } Mixin(statement) { var me = this, output = me.output, name = statement.name, jsName = Fashion.getJsName(name.id || name.value), args, arg, varName, scopeWas, i; me.nestedDocs = true; me.processingMixin = true; scopeWas = me.currentScope; me.currentScope = me.createScope(); output.addln('__rt.mixins.' + jsName + '= function('); args = me.loadArgsArray(name.args || []); output.add('$$content'); for (i = 0; i < args.length; i++) { arg = args[i]; varName = (arg.variable || arg.name); varName = me.getScopeName(varName); output.add(','); output.space(); output.add(varName); } output.add(') {'); output.indent(); // load the defaults output.addln('__rt_createScope(__rt.mixins.' + jsName + ' && __rt.mixins.' + jsName + '.createdScope);'); if (this.symbols) { me.createCallStackScope(); } if (this.symbols) { this.addSourceInfo(); } me.createDefaultScopeMap(name.args, true); me.handleStatements(statement.statements); me.currentScope = scopeWas; if (this.symbols) { me.popCallStackScope(); } output.addln("__rt_popScope();") output.unindentln('};'); output.addln('__rt.mixins.' + jsName + '.createdScope = __rt_getCurrentScope();'); me.nestedDocs = false; me.processingMixin = false; return false; } Content(statement) { if (!this.processingMixin) { this.error("@content may only be used within a mixin declaration"); } this.output.addln("$$content && $$content();"); return false; } Include(statement) { var me = this, output = me.output, include = statement.include, id = include.id || include.value, jsId = Fashion.getJsName(id), args = me.loadArgsArray(include.args || []); if (this.symbols) { me.addSourceInfo(); output.add(';'); output.addln(); } if (jsId == "fashion_defer_content") { output.addln("__rt.defer("); if (args[0]) { output.add("__rt.unbox("); me.handleStatement(args[0]); output.add(")"); } else { output.add("null"); } output.add(", "); output.addln('(function(scope) { return function(){'); output.indent(); output.addln("__rt_createScope(scope);"); if (this.symbols) { me.createCallStackScope(); } me.handleStatements(statement.content.statements); if (this.symbols) { me.popCallStackScope(); } output.addln("__rt_popScope();"); output.unindent(); output.addln("}})(__rt_getCurrentScope())"); output.add(");"); } else if (jsId == 'fashion_inject_content') { output.addln("__rt.runDeferred("); if (args[0]) { output.add("__rt.unbox("); me.handleStatement(args[0]); output.add(")"); } output.add(");"); } else if (!me.mixinDeclarations[jsId]) { me.error("unknown definition for mixin named " + id + " : " + statement.file + ":" + statement.lineNumber); } else { output.addln('(__rt.mixins.' + jsId + ' || ' + jsId + '__mix).apply(__rt.mixins, __rt_applySpreadArgs(['); output.indent(); if (statement.content) { output.addln('(function(scope) { return function(){'); output.indent(); output.addln("__rt_createScope(scope);"); if (this.symbols) { me.createCallStackScope(); } if (this.symbols) { this.addSourceInfo(); } me.handleStatements(statement.content.statements); if (this.symbols) { me.popCallStackScope(); } output.addln("__rt_popScope();"); output.unindent(); output.addln("}})(__rt_getCurrentScope())"); } else { output.add('__udf'); } me.createCallArray(args, me.mixinDeclarations[jsId], id, false, true); output.unindent(); output.add('], "' + jsId + '"));'); } return false; } Declaration(statement) { var me = this, output = me.output, namespacedRulesets = [], props = [], separator = ' ', docIdx = -1, val = statement.value, i, nsRuleset; if (val.type === 'List') { separator = val.separator; val = val.items; } else if (!Array.isArray(val)) { val = [val] } for (i = 0; i < val.length; i++) { var prop = val[i]; if (prop.type !== 'Ruleset') { props.push(prop); } else { namespacedRulesets.push(prop); } } if (props.length) { if (this.symbols) { this.addSourceInfo(); } output.addln('__rt_declare("' + me.handleInlineExpressions(statement.property) + '", '); if (statement.property === 'font') { me.isFontDecl = statement; } me.handleStatement(new List(null, props, separator)); output.add(','); output.space(); output.add(!!statement.important + ''); if (statement.file) { var fileIdx = this.stringCache.addString(statement.file); output.add(",__rt_getString(" + fileIdx + ") + \":" + statement.lineNumber + "\""); } else { output.add(', null'); } if (statement.docs && statement.docs.length) { docIdx = this.docCache.addObj(statement.docs); output.add(',__rt_getDocs(' + docIdx + ')'); } else { output.add(', null'); } output.add(');'); } if (namespacedRulesets.length) { for (i = 0; i < namespacedRulesets.length; i++) { nsRuleset = namespacedRulesets[i]; nsRuleset.selectors = new SelectorList({ items: [new Constant({ dataType: 'Literal', value: statement.property })], separator: ', ' }); me.Ruleset(nsRuleset, '__rt_namespacedRuleset'); delete nsRuleset.selectors; } } me.isFontDecl = undefined; return false; } VariableAssignment(statement) { var me = this, output = me.output, name = statement.name, bangGlobal = !!statement.global ? 1 : 0, bangDynamic = !!statement.dynamic ? 1 : 0, bangDefault = !!statement.default ? 1 : 0, isGlobalVar = me.nodeStack.length === 1 ? 1 : 0, jsName = me.getScopeName(name), exists = me.currentScope[jsName], createLocal = (!isGlobalVar && (!exists || !exists.param)) ? 1 : 0, variable = me.dynamicVariables[jsName], failDynamicAssignment = false, processed = me.processedVariables, isDynamic = false, replaceMap = this.preprocessor.replacesMap; if (this.symbols) { this.addSourceInfo(); } if (bangDynamic && !isGlobalVar) { failDynamicAssignment = true; } if (!bangDynamic && variable && !isGlobalVar && (me.currentScope === me.globalScope)) { // cannot reassign dynamic vars inside control logic failDynamicAssignment = true; } if (bangGlobal && !bangDynamic && !isGlobalVar && variable) { // cannot reassign dynamic vars inside control logic using !global failDynamicAssignment = true; } if (failDynamicAssignment) { this.error(["Dynamic variable ", name, " can only be assigned at file scope " ].join('')); Fashion.error(' at ', statement); var v = variable; while (v && v.elevationCause) { Fashion.error([ '\t', v.name, ' elevated by ', v.elevationCause.name, ' at ' ].join(''), v.elevationCause.getNode()); v = v.elevationCause; } } if (isGlobalVar && variable && processed[jsName]) { return false; } if (variable) { if (!exists || (!exists.param && bangGlobal)) { isDynamic = true; } } if (exists) { if (bangGlobal) { createLocal = 0; } else if (!variable && Runtime.allowSetScopedVariables) { // do not allow re-assingments of dynamic variables // from a non-global scope createLocal = 0; } } else if (bangGlobal) { createLocal = 0; } if (createLocal) { me.currentScope[jsName] = { name: jsName }; } else if (bangGlobal) { jsName = me.getScopeName(name, me.globalScope); } if (isGlobalVar) { me.globalScope[jsName] = jsName; } var setArgs = []; if (isDynamic) { output.addln('__rt_setDynamic("' + name + '", '); output.add('__rt_getGlobalDefault("' + jsName + '") || '); var idx = this.nodeCache.addObj(statement.value); setArgs.push(idx); } else if (bangGlobal) { output.addln('__rt_setGlobal("' + jsName + '", '); if (bangDefault) { output.add('__rt_getGlobalDefault("' + jsName + '") || '); } var idx = this.nodeCache.addObj(statement.value); setArgs.push(idx); } else if (createLocal) { output.addln('__rt_set("' + jsName + '", '); if (bangDefault) { output.add('__rt_getLocalDefault("' + jsName + '") || '); } } else { output.addln('__rt_setScoped("' + jsName + '", '); if (bangDefault) { output.add('__rt_getLocalDefault("' + jsName + '") || '); } } me.handleStatement(statement.value); if (setArgs.length) { output.add(', ' + setArgs.join(', ')); } output.add(');'); if (variable) { processed[jsName] = true; } if (variable && variable.replaces) { var assignment = new VariableAssignment(null, variable.replaces, new Variable(null, name)); assignment.deprecatedAssignment = true; me.nodeStack.pop(); me.handleStatement(assignment); me.nodeStack.push(statement); } return false; } If(statement) { var output = this.output; output.addln('if(__rt_unbox('); this.handleStatement(statement.condition); output.add(')) {'); output.indent(); this.handleStatements(statement.statements); output.unindentln('}'); return false; } Else(statement) { var output = this.output; if (statement.condition) { output.addln('else if(__rt_unbox('); this.handleStatement(statement.condition); output.add(')) {'); output.indent(); } else { output.indentln('else {'); } this.handleStatements(statement.statements); output.unindentln('}'); return false; } Return(statement) { var isFunc = false, stack = this.nodeStack; for (var i = stack.length - 1; i >= 0; i--) { if (stack[i].type == 'Function') { isFunc = true; break; } } if (isFunc) { this.popScope = false; this.output.addln('var $$$r = '); this.handleStatement(statement.expr); this.output.add(';'); if (this.symbols) { this.popCallStackScope(); } this.output.addln("__rt_popScope();"); this.output.addln('return $$$r;') } else { Fashion.warn('Ingnored @return => ', statement); } return false; } BinaryExpression(statement) { var me = this, output = me.output, suffix = ''; if ((statement.operator == '-' || statement.operator == '+') && statement.left === undefined) { statement.left = new Constant({ dataType: 'Number', value: 0 }); } var divider = ', ', prefix = '__rt'; switch (statement.operator) { case '+': case '-': case '*': case '%': case '**': case '==': case '!=': case '>': case '<': case '>=': case '<=': divider = '.operate("' + statement.operator + '",'; // output.add('__rt_operate("' + statement.operator + '", '); break; case 'and': output.add('__rt_and('); divider = ''; prefix = ''; break; case 'or': output.add('__rt_or('); divider = ''; prefix = ''; break; case '/': var doOperator = true, isDeclaration = false, isParenthetical = false, isFunctionCall = false, stack = this.nodeStack, parent; for (var p = stack.length - 1; p >= 0; p--) { parent = stack[p]; switch (parent.type) { case 'Declaration': isDeclaration = true; break; case 'ParentheticalExpression': isParenthetical = true; break; case 'FunctionCall': isFunctionCall = true; default: break; } } doOperator = (!isDeclaration || !me.isFontDecl || isParenthetical || isFunctionCall); if (!doOperator) { output.add('new __Literal('); me.handleStatement(statement.left); output.add(' + "/" + '); me.handleStatement(statement.right); output.add(')'); return false; } else { divider = '.operate("' + statement.operator + '",'; // output.add('__rt_operate("' + statement.operator + '", '); } break; default: Fashion.log('Unrecognized binary expression operator: ' + statement.operator); break; } output.add(prefix); output.add(divider); me.handleStatement(statement.left); output.add(", "); me.handleStatement(statement.right); output.add(')'); output.add(suffix); return false; } UnaryExpression(statement) { var output = this.output; switch (statement.operator) { case 'not': output.add('__rt_not('); this.handleStatement(statement.expr); output.add(')'); break; default: Fashion.log('Unrecognized unary expression operator ' + statement.operator); } return false; } Variable(statement) { var name = statement.name, jsName = this.getScopeName(name); if (name == "$__filename") { this.output.add('new __Text("' + statement.file + '")'); return; } else if (name == "$__dirname") { var fileName = statement.file.replace("\\", '/'); var dirName = fileName.indexOf('/') > -1 ? statement.file.substring(0, fileName.lastIndexOf('/')) : statement.file; this.output.add('new __Text("' + dirName + '")'); return; } if (!this.skipWarning && !(jsName in this.currentScope) && !(jsName in this.variables)) { this.warn([ "Reference to undeclared variable ", name, " => ", statement.file, ":", statement.lineNumber ].join('')); } this.output.add('__rt_get("' + jsName + '")'); return false; } Constant(statement) { var me = this, output = me.output, value = statement.value, regex; if (statement.jsonEncoded) { var tmp = JSON.parse(value); value = tmp.value; value = me.handleInlineExpressions(JSON.stringify(value), null, true); } else { value = me.handleInlineExpressions(value); } switch (statement.dataType) { case 'Length': case 'Time': case 'Angle': regex = /([0-9\.\-]+)([\w]+)$/i; value = value.match(regex); output.add('new __Numeric(' + value[1] + ', ' + '"' + value[2] + '")'); break; case 'Number': var s = value + ''; if (s.indexOf(".") === 0) { s = '0' + s; } value = s; output.add('new __Numeric(' + value + ')'); break; case 'Percentage': var s = value + ''; if (s.indexOf(".") === 0) { s = '0' + s; } value = s; output.add('new __Numeric(' + value.replace('%', '').replace(/\\/g, "") + ', "%")'); break; case 'String': output.add('new __Text("' + value + '", "' + me.escapeString(statement.quoteChar) + '")'); break; case 'Literal': if (me.booleans.hasOwnProperty(value.toLowerCase())) { if (value.toLowerCase() === 'true') { output.add('__True'); } else { output.add('__False'); } } else if (me.colors.hasOwnProperty(value.toLowerCase())) { output.add('__rt_color("' + value + '")'); } else if (value == 'null') { output.add('__Null'); } else if (value == 'none') { output.add('__None'); } else { if (statement.jsonEncoded) { output.add('new __Literal(' + value + ')'); } else { output.add('new __Literal("' + value + '")'); } } break; case 'Color': output.add('__ColorRGBA.fromHex("' + value + '")'); break; default: //Fashion.log(statement.dataType, value); output.add('"' + value + '"'); } return false; } FunctionCall(statement) { var me = this, output = me.output, args = statement.args, id = statement.id || statement.value, jsId, reserved = { 'if': true, 'else': true }; id = reserved[id] ? '__' + id : id; jsId = Fashion.getJsName(id); if (jsId === '__if') { var args = me.loadArgsArray(statement.args), skipWarning = this.skipWarning; output.add("(__rt_test("); me.handleStatement(args[0]); output.add(") ? "); this.skipWarning = true; me.handleStatement(args[1]); output.add(" : "); me.handleStatement(args[2]); output.add(")"); this.skipWarning = skipWarning; } else if (me.functionDeclarations[jsId]) { output.add('__rt_box((__rt.functions.' + jsId + ' || ' + jsId + '__fn).apply(__rt.functions, __rt_applySpreadArgs(['); output.indent(); me.createCallArray(statement.args, me.functionDeclarations[jsId], id); output.unindent(); output.add('])))'); } else if (me.registeredDeclarations[jsId]) { output.add('__rt_box(__rt.registered.' + jsId + '.apply(__rt.registered, __rt_applySpreadArgs(['); output.indent(); me.createCallArray(statement.args, me.registeredDeclarations[jsId], id, true); output.unindent(); output.add('])))'); } else { args = this.loadArgsArray(args); output.add('new __FunctionCall("'); output.add(me.handleInlineExpressions(id)); output.add('", new __List(['); output.indent(); output.addln(); for (var a = 0; a < args.length; a++) { var arg = args[a]; me.handleStatement(arg); if (a < (args.length - 1)) { output.add(','); output.space(); } } output.unindentln('], ","))'); } return false; } Extend(statement) { this.output.addln('__rt_extendSelector('); this.handleStatement(statement.selector); this.output.add(');'); return false; } ParentheticalExpression(statement) { if (this.isSelector) { this.output.addln('new __ParentheticalExpression('); this.handleStatement(statement.expr); this.output.add(')'); } else if (statement.expr) { this.handleStatement(statement.expr); } else { this.output.add("new __List([], ', ')"); } return false; } List(statement) { var output = this.output, isMap = false; if (statement.items.length && statement.items[0].isKVP) { isMap = true; } if (!isMap) { output.add('new __List(['); for (var i = 0; i < statement.items.length; i++) { var item = statement.items[i]; this.handleStatement(item); if (i < (statement.items.length - 1)) { output.add(','); output.space(); } } output.add('], "' + statement.separator + '")'); } else { output.add('new __Map(['); for (var i = 0; i < statement.items.length; i++) { var item = statement.items[i]; this.handleStatement(item.variable); output.add(','); output.space(); this.handleStatement(item); if (i < (statement.items.length - 1)) { output.add(','); output.space(); } } output.add('])'); } return false; } Warn(statement) { // ignore this.addSourceInfo(); this.output.addln("__rt_warn(__rt_unbox("); this.handleStatement(statement.expr); this.output.add('));'); return false; } Error(statement) { // ignore this.addSourceInfo(); this.output.addln("__rt_error(__rt_unbox("); this.handleStatement(statement.expr); this.output.add('));'); return false; } Debugger(statement) { this.output.addln("debugger;"); return false; } Import(statement) { var me = this, output = me.output, source = statement.source; if ((source.type === 'List' || source.type === 'SelectorList') && source.separator && source.separator.indexOf(',') === 0) { source = source.items; } else { source = [source]; } this.isSelector = statement.source; source.forEach((source) => { if (source && !/(^js[:])|(\.js$)/.test(source.value)) { output.addln('__rt_addDirectiveRuleset("@import", '); if (source.type === 'MultiPartSelector' && source.items.length === 1) { source = source.items[0]; } if (source && source.type === 'CompoundSelector' && source.items.length === 1) { source = source.items[0]; } if (!source.type || source.dataType === 'String' || source.dataType === 'Literal') { if (!source.type) { source = new Constant({ value: source, dataType: 'String', quoteChar: '"' }); } if (source.value.indexOf('http://') !== 0 && source.value.indexOf('//') !== 0) { source = new FunctionCall(null, 'url',[ new FunctionCall(null, 'unquote',[ source ]) ]); } this.handleStatement(source); } else { this.handleStatement(source); } output.add(');'); } }); this.isSelector = null; return false; } Require(statement) { return false; } Assignment(statement) { this.output.addln('new __Literal(["'); this.output.add(this.handleInlineExpressions(statement.id)); this.output.add(statement.operator + '", '); this.handleStatement(statement.expr); this.output.add('].join(""))'); return false; } Debug(statement) { this.output.addln("__rt_debug(__rt_unbox("); this.handleStatement(statement.expr); this.output.add("));"); } Charset(statement) { //var output = this.output; //if (statement.charset) { // output.addln('__rt_addDirectiveRuleset("@charset", \''); // output.add('"' + statement.charset + '"'); // output.add('\');'); //} return false; } SelectorPart(statement) { var output = this.output; output.add('new __SelectorPart('); this.handleStatement(statement.value); output.add(', "' + statement.selectorType + '")'); return false; } CompoundSelector(statement) { var output = this.output; output.add('new __CompoundSelector(['); for (var i = 0; i < statement.items.length; i++) { var item = statement.items[i]; this.handleStatement(item); if (i < (statement.items.length - 1)) { output.add(','); output.space(); } } output.add('], true)'); return false; } MultiPartSelector(statement) { var output = this.output; output.add('new __MultiPartSelector(['); for (var i = 0; i < statement.items.length; i++) { var item = statement.items[i]; this.handleStatement(item); if (i < (statement.items.length - 1)) { output.add(','); output.space(); } } output.add('])'); return false; } SelectorList(statement) { var output = this.output; output.add('new __SelectorList(['); for (var i = 0; i < statement.items.length; i++) { var item = statement.items[i]; this.handleStatement(item); if (i < (statement.items.length - 1)) { output.add(','); output.space(); } } output.add('])'); return false; } SelectorProperty(statement) { var output = this.output; output.add('new __SelectorProperty('); this.handleStatement(statement.property); output.add(', '); this.handleStatement(statement.value); output.add(')'); return false; } Default(statement) { this.warn('Unrecognized statement type: ' + statement.type + " , " + JSON.stringify(statement, null, 4)); } //</editor-fold> error(message, data) { Fashion.error(message, data); this.errors++; } warn(message, data) { Fashion.warn(message, data); this.warnings++; } transpile(ast, disableGetter) { var me = this, preprocessor = this.preprocessor, sortedAst; me.reset(); if (!preprocessor) { preprocessor = new Preprocessor(); preprocessor.preprocess(ast); } this.preprocessor = preprocessor; me.functionDeclarations = preprocessor.functionDeclarations; me.mixinDeclarations = preprocessor.mixinDeclarations; me.registeredDeclarations = preprocessor.registeredDeclarations; me.variables = preprocessor.getVariables(); me.dynamicVariables = preprocessor.getDynamicsMap(); me.processedVariables = {}; sortedAst = preprocessor.getSortedDynamicAstNodes(); if (Array.isArray(ast)) { sortedAst.push.apply(sortedAst, ast); } else { sortedAst.push(ast); } me.nestedDocs = false; me.handleStatements(sortedAst); if (me.warnings) { Fashion.warn("Sass compilation encountered " + me.warnings + " warning(s)"); } if (me.errors) { Fashion.raise("Sass compilation encountered " + me.errors + " error(s)"); } return me.output.get().trim(); } } Fashion.apply(Transpiler.prototype, { errors: 0, warnings: 0, preprocessor: undefined, output: undefined, currentScope: undefined, globalScope: undefined, globalVars: undefined, isSignatureDeclaration: undefined, nestedDocs: undefined, processingMixin: undefined, functionDeclarations: undefined, mixinDeclarations: undefined, registeredDeclarations: undefined, isFontDecl: undefined, isSelector: undefined, variables: undefined, dynamicVariables: undefined, stringCache: undefined, docCache: undefined, nodeCache: undefined, eachCount: undefined, popScope: undefined, generateGets: undefined, processedVariables: undefined, skipWarning: undefi