@extjs/sencha-cmd-linux-32
Version:
Productivity and performance optimization tool for building applications with Sencha Ext JS and Sencha Touch.
295 lines (254 loc) • 10.6 kB
JavaScript
"use strict";
var Fashion = require('../export/Base.js');
var Env = require('../Env.js');
var Literal = require('../export/type/Literal.js');
var FunctionCall = require('../export/type/FunctionCall.js');
module.exports = {
init (runtime) {
var mimeTypeMap = {
otf: 'font-opentype',
eot: 'application/vnd.ms-fontobject',
ttf: 'font/truetype',
svg: 'image/svg+xml',
woff: 'application/x-font-woff',
woff2: 'application/x-font-woff2',
gif: 'image/gif',
png: 'image/png'
},
report = false,
excludes = [],
includes = [],
maxItemSize = -1;
runtime.registerProcessor({
getSourceFromCall (obj) {
var args = obj.args,
source;
if (args.items) {
args = args.items;
}
if (!Array.isArray(args)) {
args = [args];
}
if (args.length === 1) {
source = args[0];
}
if (source.value) {
source = source.value;
} else {
source = source.toString();
}
return source;
},
getSubstring (source, char) {
var idx = source.indexOf(char);
if (idx > -1) {
source = source.substring(0, idx);
}
return source
},
detectExtension (source) {
source = this.getSubstring(source, '#');
source = this.getSubstring(source, '?');
var idx = source.lastIndexOf('.'),
extension = source.substring(idx + 1);
return extension;
},
detectMimeType (source) {
var extension = this.detectExtension(source),
mapped = mimeTypeMap[extension];
return mapped || 'application/octet-stream';
},
encodeBytes (bytes) {
if (Env.isNode) {
return bytes.toString('base64');
}
var str = '';
for (var i = 0; i < bytes.length; i++) {
str += String.fromCharCode(bytes[i]);
}
return btoa(str);
},
isMatch (source, filters) {
for (var f = 0; f < filters.length; f++) {
if (filters[f].test(source)) {
return true;
}
}
return false;
},
isExcluded (source) {
return this.isMatch(source, excludes);
},
isIncluded (source) {
return this.isMatch(source, includes);
},
inlineUrl (obj, mimeType, charset) {
var me = this,
context = me.context,
cache = context.cache || (context.cache = {}),
source = me.getSourceFromCall(obj),
url, queue, extension, inlineTag, inlineExtensionTag, skip;
if (!source) {
return;
}
mimeType = mimeType || me.detectMimeType(source);
charset = charset || "UTF-8";
url = me.basePath + '/' + source;
extension = this.detectExtension(url);
inlineTag = obj.hasTag('inline');
inlineExtensionTag = obj.hasTag('inline\\:' + extension);
skip = false;
if (this.isExcluded(source)) {
skip = true;
} else if (this.isIncluded(source)) {
skip = false;
} else if (inlineExtensionTag === false) {
skip = true;
} else if (inlineExtensionTag === null && inlineTag === false) {
skip = true;
}
if (skip) {
return;
}
queue = cache[url] || function () {
var token = {
nodes: [],
url: url
};
function inlineData (bytes) {
var data, arg, optNode;
try {
// 'getBinaryData' method provided on xhr by doRequest
data = me.encodeBytes(bytes);
arg = new Literal(encodeURI([
"data:",
mimeType,
charset ? ';charset=' + charset : '',
';base64',
',',
data
].join('')));
Fashion.debug("creating inline data node for : " + url);
optNode = new FunctionCall('url', [arg]);
} catch (e) {
Fashion.error(e);
}
if (maxItemSize > -1) {
if (arg.value.length > maxItemSize) {
// if we exceeded the limit, disable the optimization node
optNode = null;
}
}
if (optNode && report) {
var size = data.length,
num = token.nodes.length;
Fashion.log(num + " * " + size + " bytes for " + url + ".");
}
// loop over all nodes in the nodes array
// using the visitTarget property to override
// the node and call context.ready.unblock()
for (var n = 0; n < token.nodes.length; n++) {
if (optNode) {
var node = token.nodes[n];
node.visitTarget = optNode;
}
context.ready.unblock();
}
}
if (!Env.isBrowser) {
var fs = Env.fs;
fs.readFile(url, function(err, data){
if (!err) {
inlineData(data);
}
else {
Fashion.error(err);
context.ready.unblock();
}
});
}
else {
Env.doRequest({
url: url,
async: true,
binary: true,
params: {
_dc: new Date().getTime()
},
onComplete (options, xhr) {
try {
inlineData(xhr.getBinaryData());
} catch (err) {
Fashion.error(err);
}
},
onError (options, xhr) {
for (var n = 0; n < token.nodes.length; n++) {
context.ready.unblock();
}
}
});
}
return token;
}();
queue.nodes.push(obj);
context.ready.block();
},
functioncall (obj) {
var name = obj.name;
if (name === 'url') {
if (this.fontFace) {
this.inlineUrl(obj);
}
else if (this.currDeclaration) {
var name = this.currDeclaration.property;
if (name === 'background-image') {
this.inlineUrl(obj);
}
}
}
},
declaration (obj) {
var declWas = this.declaration;
this.currDeclaration = obj;
obj.descend(this);
this.currDeclaration = declWas
},
ruleset (obj) {
var ffWas = this.fontFace,
rulesetWas = this.currRuleset;
this.currRuleset = obj;
if (obj.isAtRule()) {
if (obj.getFirstSelectorStr() === '@font-face') {
this.fontFace = obj;
}
}
obj.descend(this);
this.currRuleset = rulesetWas;
this.fontFace = ffWas;
},
execute (obj, ctx) {
this.context = ctx;
this.basePath = runtime.context.getConfig('basePath');
var config = runtime.context.getConfig('inliner');
if (config && config.enable) {
if (config.report) {
report = config.report;
}
if (config.excludes) {
for (var i = 0; i < config.excludes.length; i++) {
excludes.push(new RegExp(config.excludes[i]));
}
}
if (config.includes) {
for (var i = 0; i < config.includes.length; i++) {
includes.push(new RegExp(config.includes[i]));
}
}
maxItemSize = config.maxItemSize || -1;
this.visit(obj);
}
}
});
}
};