raptor
Version:
RaptorJS provides an AMD module loader that works in Node, Rhino and the web browser. It also includes various sub-modules to support building optimized web applications.
230 lines (180 loc) • 8.26 kB
JavaScript
/*
* Copyright 2011 eBay Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
define.Class(
"raptor/packaging/Dependency_less",
"raptor/packaging/Dependency",
['raptor'],
function(raptor, require, exports, module) {
"use strict";
var resources = require('raptor/resources');
var File = require('raptor/files/File');
var promises = require('raptor/promises');
var createLessImporter = function(dependency, context, oldImporter) {
var Parser = require('less').Parser;
return function (path, paths, callback, env) {
if (!path.startsWith('/')) {
return oldImporter.apply(this, arguments);
}
var lessSrc,
foundPath,
resource;
resource = resources.findResource(path);
if (resource.exists()) {
if (!resource.isFileResource()) {
throw new Error("Only file resources are supported for LESS. Resource: " + resource);
}
foundPath = resource.getFilePath();
lessSrc = resource.readAsString("UTF-8");
}
if (foundPath) {
try
{
new Parser({
paths: paths,
filename: foundPath
}).parse(lessSrc, function (e, root) {
callback(e, root, lessSrc);
});
}
catch(e) {
callback(e);
}
} else {
if (typeof(env.errback) === "function") {
env.errback(path, paths, callback);
} else {
callback({ type: 'File', message: "'" + path + "' wasn't found.\n" });
}
}
};
}; //End createLessImporter
var Dependency_less = function() {
Dependency_less.superclass.constructor.apply(this, arguments);
this.addProperty("path", {
type: "string"
});
};
Dependency_less.prototype = {
getKey: function(context) {
return "less:" + this.resolvePathKey(this.path, context);
},
toString: function(dependency) {
return this.getResource().getPath();
},
getContentType: function() {
return "text/css";
},
getResourcePath: function() {
return this.path;
},
_addLessImports: function(imports, context) {
if (this.imports) {
this.imports.forEach(function(importPath) {
var importResource = this.resolveResource(importPath, context);
if (importResource.exists()) {
imports.add(importResource);
}
else {
throw new Error('Import not found with path "' + importPath + '" (' + importResource.getURL() + ')');
}
}, this);
}
},
_addLessResources: function(resources, context) {
this._addLessImports(resources, context);
},
_getLessResources: function(context) {
var resources = [];
var resourceList = {
add: function(resource, source) {
resources.push({
resource: resource,
source: source
});
}
};
var resource = this.getResource(context);
this._addLessResources(resourceList, context);
resourceList.add(resource);
return resources;
},
hasModifiedChecksum: function(context) {
return true;
},
getModifiedChecksum: function(context) {
var crypto = require('crypto');
var resources = this._getLessResources(context);
var shasum = crypto.createHash('sha1');
resources.forEach(function(resourceInfo) {
var resource = resourceInfo.resource;
shasum.update(resource.getURL() + resource.lastModified());
});
var checksum = shasum.digest('hex');
return checksum.substring(0, 8);
},
getCode: function(context) {
var deferred = promises.defer();
function onError(e) {
deferred.reject(e);
}
var Parser = require('less').Parser;
var oldImporter = Parser.importer;
try
{
var resource = this.getResource(context);
var resources = this._getLessResources(context);
var lessSource = resources.map(function(resourceInfo) {
var source = resourceInfo.source || resourceInfo.resource.readAsString();
return source;
}).join('\n');
var result;
if (!resource.isFileResource()) {
throw new Error("Only file resources are supported for LESS. Resource: " + resource);
}
var file = resource.getFile();
Parser.importer = createLessImporter(this, context, oldImporter);
var parser = new Parser({
paths: [file.getParent()], // search paths for @import directives
filename: file.getAbsolutePath()
});
parser.parse(lessSource, function (e, root) {
if (e) {
onError(raptor.createError(new Error('Unable to parse Less file at path "' + resource.getURL() + '". Exception: ' + e.message), e));
} else {
try {
result = root.toCSS();
deferred.resolve(result);
}
catch(e) {
onError(raptor.createError(new Error('Unable to generate CSS code for Less file at path "' + resource.getURL() + '". Exception: ' + e.message), e));
}
}
});
}
catch(e) {
onError(raptor.createError(new Error('Unable to parse Less file at path "' + resource.getURL() + '". Exception: ' + e.message), e));
}
finally {
Parser.importer = oldImporter;
}
return deferred.promise;
},
isCompiled: function() {
return true;
}
};
return Dependency_less;
});