@extjs/sencha-cmd-linux-32
Version:
Productivity and performance optimization tool for building applications with Sencha Ext JS and Sencha Touch.
297 lines (250 loc) • 11.6 kB
JavaScript
"use strict";
var Fashion = require('../export/Base.js');
var FunctionCall = require('../export/type/FunctionCall.js');
var Literal = require('../export/type/Literal.js');
var Declaration = require('../type/Declaration.js');
var Ruleset = require('../type/Ruleset.js');
var SelectorList = require('../type/selectors/SelectorList.js');
var Preprocessor = require('../Preprocessor.js');
var Nodes = require('../parse/ast/Nodes.js');
var ExportBuilder = require('./ExportBuilder.js');
module.exports = {
init (runtime) {
// helper functions for creating new exported css variables from extension functions
runtime.register({
create_css_variable: function (name, value, base) {
while (base && base.$previousReference) {
base = base.$previousReference;
}
value.$referenceName = this.unbox(name);
value.$referenceBase = base || value;
return value;
},
name_of: function(refNode) {
while (refNode && refNode.$referenceBase) {
refNode = refNode.$referenceBase;
}
return refNode && refNode.$referenceName;
}
});
// detect css variable exports
runtime.registerProcessor({
enable: true,
execute: function (obj, ctx) {
var me = this,
config = runtime.context.getConfig('cssVars');
if (config) {
Fashion.apply(this, config);
}
if (me.enable) {
me.ctx = ctx;
ctx.exportedVariables = {};
ctx.exportRuleset = new Ruleset({
selectors: new SelectorList([
new Literal('html')
])
});
me.visit(obj);
if (me.export === 'all') {
me.exportAllGlobals(obj);
}
}
},
exportAllGlobals: function(css) {
var globals = runtime.getGlobalScope().getEntries(),
me = this,
exportRuleset = me.ctx.exportRuleset;
for (var key in globals) {
var entry = globals[key],
value = entry;
if (value && value.ast && value.$referenceName) {
var name = value.$referenceName,
jsName = Fashion.getJsName(name.replace(/^--/g, '$')),
varName = name.replace(/^\$/, ''),
dynamics = runtime._dynamics;
if (dynamics[jsName] && !entry.exported && varName.indexOf('include-') !== 0) {
exportRuleset.addDeclaration(new Declaration({
property: '--' + varName,
value: new Literal('export')
}));
entry.exported = true;
}
}
}
this.visit(exportRuleset);
},
declaration: function (decl) {
var name = decl.property,
val = decl.value,
exportedVariables = this.ctx.exportedVariables;
if (name.indexOf('--') == 0) {
if (val && val.$isFashionLiteral) {
if (val.value && val.value.trim() === 'export') {
var jsName = Fashion.getJsName(name.replace(/^--/g, '$')),
globals = runtime.getGlobalScope(),
dynamics = runtime._dynamics,
variable = globals.get(jsName),
baseName = name.replace(/^--/g, ''),
key = Fashion.getJsName(baseName),
exported = exportedVariables[key] || {
name: baseName,
rulesets: []
};
if (variable) {
if (!dynamics[jsName]) {
Fashion.log('cannot export ' + jsName + ' because it is not dynamic');
}
else {
if (val) {
val.visitTarget = variable.clone();
}
exported.declaration = decl;
exported.variable = variable;
variable.exported = true;
exported.rulesets.push(decl.ruleset);
exportedVariables[key] = exported;
}
}
}
}
}
this.visit(val);
}
});
// update rulesets to include new declarations w/o css variable references
runtime.registerProcessor({
currDecl: null,
referenceNodes: null,
enable: true,
execute: function (obj, ctx) {
var me = this,
config = runtime.context.getConfig('cssVars');
if (config) {
Fashion.apply(me, config);
}
if (me.enable) {
me.ctx = ctx;
me.visit(obj);
var exportedVariables = me.ctx.exportedVariables;
if (Object.getOwnPropertyNames(exportedVariables).length) {
var exportRuleset = me.ctx.exportRuleset,
builder = new ExportBuilder(exportRuleset);
builder.export = me.export;
var exportFn = builder.buildExportFunction(exportedVariables, runtime);
if (exportRuleset.declarations.length) {
obj.push(exportRuleset);
me.ctx.exportRuleset = new Ruleset({
selectors: new SelectorList([
new Literal('html')
])
});
}
if (exportFn) {
ctx.exportFn = exportFn;
}
}
}
},
visitItem: function (item) {
if (item.$referenceName) {
this.referenceNodes.push(item);
}
else {
item.doVisit(this);
}
},
declaration: function (decl) {
this.currDecl = decl;
this.referenceNodes = [];
var copy = decl.clone(),
refNodes = this.referenceNodes,
addNewDecl = false,
exportedVariables = this.ctx.exportedVariables;
this.visit(copy.value);
outer: for (var i = 0; i < refNodes.length; i++) {
var referenceNode = refNodes[i],
refNode = referenceNode,
refBase;
while (refNode) {
if (refNode.$referenceBase) {
refBase = refNode.$referenceBase;
break;
}
refNode = refNode.$previousReference;
}
if (refBase) {
// need to add the export declaration for this variable
var base = refBase,
baseName = base.$referenceName.replace(/^\$/, ''),
newName, exported, visitTarget, exDecl, keyName;
baseName = Fashion.getJsName(baseName);
newName = refNode.$referenceName.replace(/^\$/, '');
keyName = Fashion.getJsName(newName);
if (exportedVariables[baseName]) {
exported = exportedVariables[baseName];
exDecl = exported.declaration;
}
else {
exDecl = copy;
}
if (!exportedVariables[keyName]) {
var d = new Declaration({
property: '--' + newName,
value: refNode.clone()
});
exportedVariables[keyName] = {
declaration: d,
name: newName,
rulesets: [
exDecl.ruleset
],
variable: {
$isWrapper: true,
value: d.value
}
};
visitTarget = exDecl.visitTarget;
if (!visitTarget) {
exDecl.visitTarget = visitTarget = [
// don't clone here, since we need to
// preserve visitTargets
new Declaration({
property: exDecl.property,
important: exDecl.important,
sourceInfo: exDecl.sourceInfo,
value: exDecl.value
})
];
}
visitTarget.push(d);
}
}
refNode = referenceNode;
inner: while (refNode) {
var refName = refNode.$referenceName.replace(/^\$/, '');
var keyName = Fashion.getJsName(refName);
if (exportedVariables[keyName]) {
referenceNode.visitTarget = new FunctionCall('var', [
new Literal('--' + refName)
]);
addNewDecl = true;
break inner;
}
else if (refNode.$previousReference &&
refNode.$previousReference.$referenceName) {
refNode = refNode.$previousReference;
}
else {
refNode = null;
}
}
}
if (addNewDecl) {
decl.visitTarget = [decl.clone(), copy];
}
this.currDecl = null;
this.referenceNodes = null;
}
});
}
};