Skip to content

Commit

Permalink
used urlfinder.js in jscollect.js
Browse files Browse the repository at this point in the history
  • Loading branch information
Anton Drachev committed Dec 25, 2012
1 parent 69e6dda commit 49556ee
Showing 1 changed file with 11 additions and 161 deletions.
172 changes: 11 additions & 161 deletions lib/jscollect.js
Expand Up @@ -29,88 +29,14 @@ var crypto = require("crypto");
var fs = require("fs");
var path = require("path");

/*=========================================================================*/

var makeParsed = function(items, content) {
var result = [];
var lastInd = 0;
items.forEach(function(item) {
if (lastInd > item.range[0])
throw "unexpected index";
if (lastInd < item.range[0])
result.push(new Buffer(content.substring(lastInd, item.range[0]), "utf-8"));
result.push(item);
lastInd = item.range[1] + 1;
});
if (lastInd < content.length)
result.push(new Buffer(content.substring(lastInd), "utf-8"));
return result;
}
var urlfinder = require("./urlfinder");

/*=========================================================================*/

var jsFile = (function() {
// js is parsed using a real parser:
var esprima = require("esprima");

function traverseTree(item, calls) {
if (!item) {
return;
}
switch (item.type) {
case "AssignmentExpression":
traverseTree(item.right, calls);
break;
case "CallExpression":
if (item.callee.type === "Identifier" && item.callee.name === "include") {
var args = item.arguments;
if (args.length !== 1 && args[0].type !== "Literal")
throw args;
calls.push({ func: item.callee.name, arg: args[0].value, range: item.range });
}
break;
case "ExpressionStatement":
traverseTree(item.expression, calls);
break;
case "VariableDeclaration":
item.declarations.forEach(function(node) {
traverseTree(node.init, calls);
});
break;
case "ForStatement":
case "WhileStatement":
case "FunctionExpression":
case "FunctionDeclaration":
traverseTree(item.body, calls);
break;
case "IfStatement":
traverseTree(item.consequent, calls);
traverseTree(item.alternate, calls);
break;
case "SwitchStatement":
item.cases.forEach(function(nodes) {
nodes.consequent.forEach(function(node) {
traverseTree(node, calls);
});
});
break;
case "Program":
case "BlockStatement":
if (item.body) {
item.body.forEach(function(node) {
traverseTree(node, calls);
});
}
break;
}
return calls;
}

return {
parse: function(content) {
var parsed = esprima.parse(content, { range: true });
var calls = traverseTree(parsed, []);
return makeParsed(calls, content);
parse: function(fPath) {
return urlfinder.getParsed(fPath);
},
process: function(fPath, item, context) {
processFile(path.resolve(path.dirname(fPath), item.arg), context);
Expand All @@ -121,51 +47,19 @@ var jsFile = (function() {
/*=========================================================================*/

var cssFile = (function() {
// but css is parsed with regexes...
var stringPat = "(?:(?:'[^'\\r\\n]*')|(?:\"[^\"\\r\\n]*\"))";
var urlPat = "(?:(?:url\\(\\s*" + stringPat + "\\s*\\))|(?:url\\(\\s*[^\\s\\r\\n'\"]*\\s*\\)))";
var commentPat = "(?:/\\*[^*]*\\*+(?:[^/][^*]*\\*+)*/)";
var importPat = "(?:\\@import\\s+(" + urlPat + "|" + stringPat + ");?)";
var allRx = new RegExp(commentPat + "|" + importPat + "|" + urlPat, "g");
var urlRx = new RegExp("^" + urlPat + "$");

function parseUrl(url) {
if (url.lastIndexOf("url(", 0) === 0)
url = url.replace(/^url\(\s*/, "").replace(/\s*\)$/, "");
if (url.charAt(0) === "'" || url.charAt(0) === '"')
url = url.substr(1, url.length - 2);
// todo: handle escape and unicode http://www.w3.org/TR/css3-syntax/
return url;
}

function canHandle(url) {
return !((url.lastIndexOf("//", 0) === 0) || /^\w+:/.test(url));
return url && !((url.lastIndexOf("//", 0) === 0) || /^\w+:/.test(url));
}

return {
parse: function(content) {
var found = [];
var m;
while (m = allRx.exec(content)) {
if (m[0].lastIndexOf("/*", 0) === 0) {
// skip comment
} else if (m[0].charAt(0) === "@") {
// @import
var url = parseUrl(m[1]);
if (canHandle(url))
found.push({ type: "import", url: url, range: [ m.index, allRx.lastIndex - 1 ] });
} else if (urlRx.test(m[0])) {
// url(...)
var url = parseUrl(m[0]);
if (canHandle(url))
found.push({ type: "url", url: url, range: [ m.index, allRx.lastIndex - 1] });
} else {
console.error({ match: m[0] });
}
}
return makeParsed(found, content);
parse: function(fPath) {
return urlfinder.getParsed(fPath);
},
process: function(fPath, item, context) {
if (!canHandle(item.url)) {
context.write(item.raw, "utf-8");
return;
}
var dir = path.dirname(fPath);
var url = item.url;
url = url.charAt(0) === "/" ? path.resolve(context.root, url.substr(1)) : path.resolve(dir, url);
Expand All @@ -183,41 +77,16 @@ var cssFile = (function() {

/*=========================================================================*/

var pathToMetadata = {};
var shaToContent = {};

function processFile(fPath, context) {
if (context.included[fPath])
return;
context.included[fPath] = true;

// checking in `pathToMetadata`
var meta = pathToMetadata[fPath];
var mTime = fs.statSync(fPath).mtime.getTime();
var binContent;
if (!meta || meta.mTime !== mTime) {
var sha1sum = crypto.createHash("sha1");
binContent = fs.readFileSync(fPath);
sha1sum.update(binContent);
meta = pathToMetadata[fPath] = { sha: sha1sum.digest("hex"), mTime: mTime };
//console.log("meta " + JSON.stringify(meta));
//watchDir(dir);
}

// checking in `shaToContent`
var parsedFile = shaToContent[meta.sha];
if (!parsedFile) {
if (!binContent) {
//throw "no binary content";
binContent = fs.readFileSync(fPath);
}
shaToContent[meta.sha] = parsedFile = context.filetype.parse(binContent.toString("utf-8"));
}

var relPath = path.relative(context.root, fPath);
context.write("/* " + relPath + ": begin [depth " + context.includeStack.length + "] */\n", "utf-8");
context.includeStack.push(relPath);

var parsedFile = context.filetype.parse(fPath);
parsedFile.forEach(function(item) {
if (Buffer.isBuffer(item)) {
context.write(item);
Expand Down Expand Up @@ -248,22 +117,3 @@ exports.process = function(filePath, context) {
context.write("/* root: " + context.root + " */\n", "utf-8");
processFile(filePath, context);
}

/*=========================================================================*/

//var watchers = {};

//function watchDir(dir) {
// if (watchers[dir])
// return;
// console.error("watchDir: " + dir);
// watchers[dir] = fs.watch(dir, function(event, filename) {
// watcherCallback(event, path.resolve(dir, filename));
// });
//}

//function watcherCallback(event, filename) {
// delete pathToSha[filename];
//}

/*=========================================================================*/

0 comments on commit 49556ee

Please sign in to comment.