Skip to content

Instantly share code, notes, and snippets.

@iamnoah
Created September 14, 2013 04:50
Show Gist options
  • Save iamnoah/6558898 to your computer and use it in GitHub Desktop.
Save iamnoah/6558898 to your computer and use it in GitHub Desktop.
Convert stealJS modules to AMD modules
/**
* Shaper for cleaning up steal 3.2 declarations. Multiple calls are collapsed into a single
* wrapped call and non-dependant arguments are sorted.
*/
if (typeof define !== 'function') { var define = require('amdefine')(module); }
define(['../shaper', '../fmt', '../ref', '../tkn'], function(Shaper, Fmt, Ref, tkn) {
"use strict"; "use restrict";
var args = process.argv,
dir = args[2].replace(process.env.SRC_ROOT, "").replace(/(^\/|\/$)/, "").split("/").slice(0, -1).join("/") + "/";
var EXT = /\.[^\/]+$/i,
DOT_JS = /\.js$/i;
function fixPath(path, i) {
// a steal module is "name" (directory), but an AMD module is "name/name" (file - .js)
var p = path.value;
if (p.indexOf("//") === 0) {
p = path.value = p.substring(2);
}
if (path.type === tkn.FUNCTION) {
throw new Error("argument " + i + " is a function! "+ path.getSrc());
}
if (p.indexOf("./") === 0) {
p = path.value = dir + path.value.substring(2);
// relative paths are always to a file, not a module, so must have an extension
if (!p.match(EXT)) {
// if there wasn't one, it was js
p = path.value = path.value + ".js";
}
}
if (p.match(/\.mustache$/i)) {
path.value = "r/mustache!" + path.value;
} else {
if (p.match(DOT_JS)) {
// the .js is no longer necessary and seems to make require think
// it's an absolute path
path.value = p.replace(DOT_JS, "");
} else {
// if it's a steal "module", we need to append the name again to
// match require's concept of a module
var parts = p.split("/");
path.value += "/" + parts[parts.length - 1];
}
}
return Shaper.parse(JSON.stringify(path.value));
}
new Shaper("amdify", function(root) {
return Shaper.traverse(root, {
pre: function(node, ref) {
var replacement;
// TODO 6 thens is silly, but this could be more generic
if (Shaper.match("steal($$).then($$).then($$).then($$).then($$)", node) ||
Shaper.match("steal($$).then($$).then($$).then($$)", node) ||
Shaper.match("steal($$).then($$).then($$)", node) ||
Shaper.match("steal($$).then($$)", node)) {
var kids = [],
srcs = [];
var n = node;
var func;
while(n) {
// XXX since this is pre-order, the first set of steals we get to is the last
// but we don't want to mess up the function arguments, so they need to go first
if (kids.length) {
srcs.push(",\n\t");
} else {
// the first steals we encounter may include the function
var firstKids = n.children[1].children;
if (firstKids[firstKids.length - 1].type === tkn.FUNCTION) {
func = firstKids.pop();
}
}
kids.push.apply(kids, n.children[1].children);
srcs.push.apply(srcs, n.children[1].srcs.slice(1, -1));
if (n.children[0].type === tkn.DOT) {
n = n.children[0].children[0];
} else {
n = null;
}
}
srcs.unshift("skip");
replacement = {
fn: func,
list: {
children: kids,
srcs: srcs
}
};
} else if (Shaper.match("steal($$);", node)) {
replacement = {
semi: true,
list: node.expression.children[1]
};
} else if (Shaper.match("steal.then($$)", node)) {
replacement = {
list: node.children[1]
};
} else if (Shaper.match("steal($$)", node)) {
// XXX for some reason, the above doesn't always match...
replacement = {
list: node.children[1]
};
}
if (Shaper.match("steal.plugins", node)) {
ref.set(Shaper.parse("false"));
}
if (replacement) {
var list = replacement.list;
var args = list.children;
var fn = replacement.fn || args.pop();
if (fn.type !== tkn.FUNCTION) {
args.push(fn);
fn = null;
}
// recreate the list as an array, using the same commas and spacing
var deps = Shaper.replace.apply(Shaper,
["["+ args.map(function(arg, i) {
return "$" + (i < args.length - 1 ? list.srcs[i + 1] : "");
}).join("") + "]"].concat(args.map(fixPath)));
if (fn) {
ref.set(Shaper.replace("define($,\n$)" + (replacement.semi ? ";" : ""), deps, fn));
} else {
ref.set(Shaper.replace("require($)" + (replacement.semi ? ";" : ""), deps));
}
return "break";
}
}
});
});
return Shaper.get("amdify");
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment