UNPKG

@extjs/sencha-cmd-linux-32

Version:

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

655 lines (566 loc) 21.5 kB
"use strict"; var Fashion = require('./export/Base.js'), Base = Fashion.Base; var Env = require('./Env.js'); var Visitor = require('./Visitor.js'); var Runtime = require('./Runtime.js'); Fashion.currentFile = undefined; class SassFile extends Base { constructor(cfg) { super(cfg); this.readyListeners = []; this.state = 0; this.imports = {}; this.importedBy = {}; if (this.isJsExtension()) { this.loadExtension(); } else { this.loadSass(); } } getLoadPath() { var loadPath = this.loadPath; if (!loadPath) { loadPath = this.loadPath = this.path; } return loadPath; } loadExtension() { var me = this, loadPath = me.getLoadPath(); if (me.state < 5) { me.state = 5; if (me.state < 9) { me.state = 9; if (typeof System !== 'undefined') { try { me.info("importing " + loadPath); System.import(loadPath).then(function (extension) { extension.init(me.builder.context.runtime); me.state = 10; me.content = ''; me.info("file " + loadPath + " is loaded"); me.checkImports(); }, function (err) { me.error("file " + loadPath + " failed to load"); me.error((err.stack || err) + ''); me.checkImports(); }); } catch (err) { me.error("file " + loadPath + " failed to load"); me.error(err); me.error((err.stack || err) + ''); me.checkImports(); } } else { try { if (!/\.js$/.test(loadPath)) { loadPath += '.js'; } if (Env.isNode && loadPath.indexOf('/') !== 0 && loadPath.indexOf(':') !== 1) { loadPath = process.cwd() + '/' + loadPath; } // if (loadPath.indexOf('http') === 0) { // loadPath = loadPath.replace(/http(s)?:\/\/(.*?)(:\d{1,4})?\//, '') // } me.info("requiring " + loadPath); delete require.cache[require.resolve(loadPath)]; var extension = require(loadPath); extension.init(me.builder.context.runtime); me.state = 10; me.content = ''; me.info("file " + loadPath + " is loaded"); me.checkImports(); } catch (err) { me.error("file " + loadPath + " failed to load"); me.error((err.stack || err) + ''); me.checkImports(); } } } } } loadSass() { var me = this, loadPath; if (me.state < 5) { me.state = 5; if (me.state < 10) { loadPath = me.getLoadPath(); me.info("loading file " + loadPath); if (me.isSaveFile) { me.state = 10; me.content = ''; me.checkImports(); return; } Env.loadFile(loadPath, function (content) { me.state = 10; me.info("file " + loadPath + " is loaded"); me.content = content; me.checkImports(); }, function () { var idx = loadPath.lastIndexOf('/'), attempt = loadPath; if (idx > -1) { attempt = attempt.substring(0, idx + 1) + '_' + attempt.substring(idx + 1); } loadPath = me.loadPath = attempt; me.info("retrying with " + loadPath); Env.loadFile(loadPath, function (content) { me.state = 10; me.info("file " + loadPath + " is loaded"); me.content = content; me.checkImports(); }, function () { Fashion.error("failed to download path : " + loadPath); me.content = ""; me.checkImports(); }); }); } } } getAst() { var me = this, ast = me.ast, content = me.content, loadPath = me.getLoadPath(), parser; if (me.isJsExtension()) { return undefined; } if (!ast && content) { parser = me.builder.getParser(); me.debug("parsing file " + loadPath); try { ast = me.ast = parser.parse(content, loadPath); } catch (err) { Fashion.error("Error parsing file : " + loadPath + " => "); throw err; return undefined; } } return ast; } getSassFile(basePath, targetPath, origSource, importer) { return this.builder.getSassFile(basePath, targetPath, origSource, importer); } isJsExtension() { var loadPath = this.getLoadPath(); return loadPath.indexOf(".js") > 0; } getImportSource(source) { var imports = []; if ((source.type === 'List' || source.type === 'SelectorList') && source.separator && source.separator.indexOf(',') === 0) { imports = source.items; } else { imports.push(source); } imports = Fashion.convert(imports, (source) => { if (source && 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 && source.value) { return source.value; } return source; }); imports = Fashion.filter(imports, (source) => { if (!source) { return false; } if (!source.indexOf) { return false; } var idx = source.indexOf('.css'); if (idx > -1 && idx === (source.length - 4)) { return false; } idx = source.indexOf('http://'); if (idx === 0) { return false; } idx = source.indexOf('//'); if (idx === 0) { return false; } return true; }); return imports; } trimComment(comment) { if (comment.indexOf('//#') === 0) { comment = comment.substring(3); } if (comment.indexOf('//') === 0) { comment = comment.substring(2); } if (comment.indexOf('/*') === 0) { comment = comment.substring(2, comment.length - 3); } return comment.trim(); } dependsOn(path) { var me = this; if (me.imports[path]) { return true; } for (var loadPath in me.imports) { var dep = me.imports[loadPath]; if (dep.dependsOn(path)) { return true; } } return false; } checkImports() { var me = this, loadPath = me.getLoadPath(), sassFiles = [], missing, i; if (me.state < 15) { me.info("checking Imports for file " + loadPath); me.state = 15; // normal scss file if (!me.isJsExtension()) { if (me.isUiFile) { me.mixinCalls = []; } var vis = new Visitor({ skipBranching: true, loadJsExtension (source) { source = source.replace(/;$/, '') .replace(/^'/, '') .replace(/'$/, '') .replace(/\.js$/, '') .replace(/^js:\s*/, ''); if (source.indexOf(".") !== 0) { source = "./" + source; } var sassFile = me.getSassFile(me.path, source + ".js", source, me); if (sassFile === me) { Fashion.raise("file " + loadPath + " should not import itself"); } me.imports[sassFile.getLoadPath()] = sassFile; sassFile.importedBy[loadPath] = me; if (sassFile.state < 20) { sassFiles.push(sassFile); } }, //Comment (comment) { // if (comment.indexOf('//#') === 0) { // comment = me.trimComment(comment); // if (comment.indexOf('@require ') === 0) { // comment = comment.replace('@require ', ''); // this.loadJsExtension(comment); // } // } //}, FunctionCall (node) { var funcName = node.id || node.value; var handlers = this; if (funcName === 'require') { var sources = me.getImportSource(node.args); Fashion.warn("Use of 'require()' will be deprecated", node); Fashion.warn("Use @import instead"); sources.forEach((source) => { handlers.loadJsExtension(source); }); node.visitTarget = null; } }, Require(node) { var source = me.getImportSource(node.source)[0], isGlobal = this.nodeStack.length == 1; if (source.indexOf) { if (!isGlobal) { Fashion.raise('Cannot use require() "' + source + '" from non-file-scope location', node); } Fashion.warn("Use of '@require' has been deprecated", node); Fashion.warn("Use @import instead"); delete node.visitTarget; this.loadJsExtension(source); } }, Import(node) { delete node.visitTarget; delete node.nodeFiles; var handlers = this, source = me.getImportSource(node.source); source.forEach((source) => { if (/(^js[:])|(\.js$)/.test(source)) { handlers.loadJsExtension(source); } else { var sassFile = me.getSassFile(me.path, source, source); if (sassFile === me) { Fashion.raise("file " + loadPath + " should not import itself"); } if (sassFile.dependsOn(loadPath)) { me.importError = new Error("Import cycle detected between " + me.getLoadPath() + " and " + sassFile.getLoadPath()); } else { me.imports[sassFile.getLoadPath()] = sassFile; sassFile.importedBy[loadPath] = me; if (sassFile.state < 20) { sassFiles.push(sassFile); } } } }); }, Include (node) { if (me.isUiFile) { me.mixinCalls.push(node); } } }); vis.visit(me.getAst()); } // javascript extension file else if (Fashion && Env && Env.isRhino) { var content = me.content + "\n//# sourceURL=" + loadPath; eval(content); } // indicate that the state has passed out of checking imports me.state == 16; missing = sassFiles.length; if (!missing) { me.fireReady(); return; } for (i = 0; i < sassFiles.length; i++) { sassFiles[i].onReady(function () { missing--; if (missing === 0) { me.fireReady(); } else { me.debug("file " + loadPath + " still waiting for " + missing + " other files"); } }); } } } onReady(listener) { var me = this; if (me.state >= 20) { listener(me); } else { me.readyListeners.push(listener); if (me.state == 10) { me.checkImports(); } } } fireReady() { var me = this; if (me.state < 20) { me.info("file " + me.getLoadPath() + " is ready"); me.state = 20; var listener; while ((listener = me.readyListeners.shift()) != null) { listener(me); } } } getExpandedAst(stamp) { stamp = stamp || new Date().getTime(); var me = this, ast = me.getAst(); if (me.importError) { var err = me.importError; delete me.importError; throw err; } function addSourceInfo (vis) { if (vis.addSourceInfo) { vis.addSourceInfo(this.node); } } function createCallStackScope (vis) { if (vis.createCallStackScope) { vis.createCallStackScope(); } } function popCallStackScope (vis) { if (vis.popCallStackScope) { vis.popCallStackScope(); } } if (me.imported != stamp) { me.imported = stamp; if (!me.isJsExtension()) { me.debug("expanding ast for file " + me.getLoadPath()); var vis = new Visitor({ skipBranching: true, Import(node) { delete node.visitTarget; var source = me.getImportSource(node.source), visitTarget = []; source.forEach((source) => { if (source && source.indexOf && !/(^js[:])|(\.js$)/.test(source) && !node.skipSassImport) { var sassFile = me.getSassFile(me.path, source); sassFile.importing = true; var importAst = sassFile.getExpandedAst(stamp); if (me.builder.context.enableSymbols) { visitTarget.push({ node: node, doVisit: addSourceInfo }); visitTarget.push({ doVisit: createCallStackScope }); } visitTarget.push(importAst); if (me.builder.context.enableSymbols) { visitTarget.push({ doVisit: popCallStackScope }); } sassFile.importing = false; } }); if (visitTarget.length) { node.visitTarget = visitTarget; } } }); me.expanding = true; vis.visit(ast); me.expanding = false; return ast; } } return Runtime.allowMultipleImports ? ast : undefined; } invalidate() { var me = this; if (me.state >= 10) { me.info("invalidating file " + me.getLoadPath()); me.state = 0; delete me.ast; delete me.content; delete me.imported; for (var name in me.importedBy) { me.importedBy[name].unready(); } var loadPath = me.getLoadPath(); for (name in me.imports) { delete me.imports[name].importedBy[loadPath]; } me.imports = {}; if (me.isJsExtension()) { me.loadExtension(); } else { me.loadSass(); } } } unready() { this.state = 10; delete this.ast; for (var name in this.importedBy) { this.importedBy[name].unready(); } } debug(message) { // Fashion.log(message); } info(message) { // Fashion.log(message); } error(message) { Fashion.error(message); } getCustomUIs () { var me = this, mixinMap = {}, allUIs = {}, calls = me.mixinCalls, separator = ', ', node, mixinName, include, args, arg, argName, argMap, uiMap; allUIs[me.jsClassName] = mixinMap; for (var i = 0; i < calls.length; i++) { node = calls[i]; include = node.include; mixinName = include.id || include.value; uiMap = mixinMap[mixinName] || {}; args = include.args; if (args.isFashionListAst) { args = args.items; separator = args.separator; } if (!Array.isArray(args)) { args = [args]; } argMap = {}; for (var a = 0; a < args.length; a++) { arg = args[a]; argName = a; var value = arg.name || arg.value; if (arg.variable) { argName = arg.variable; } if (!value) { while(arg && arg.expr) { arg = arg.expr; } var converter = function(item) { item = (item && item.expr) || item; if (item.isFashionListAst) { var sep = item.separator || separator, items = Fashion.convert(item.items, converter), value = items.join(sep); if (items.length > 1) { value = '(' + value+ ')'; } return value; } return item.name || item.value; }; if (arg.isFashionListAst) { separator = arg.separator || separator; value = converter(arg); } else { value = arg.name || arg.value; } } argMap[argName] = value; } if (argMap.$ui) { var tmp = {}; tmp[argMap.$ui] = argMap; delete argMap.$ui; argMap = tmp; } Fashion.apply(uiMap, argMap); mixinMap[mixinName] = uiMap; } return allUIs; } } Fashion.apply(SassFile.prototype, { $isSassFile: true, expanding: false, readyListeners: null, state: null, imports: null, importedBy: null, loadPath: null, path: null, content: null, originalSource: null, ast: null, imported: null, importer: null, builder: null, isSaveFile: null, isUiFile: null, jsClassName: null, mixinCalls: null }); module.exports = SassFile;