mirror of
https://github.com/meteor/meteor.git
synced 2026-05-02 03:01:46 -04:00
106 lines
4.0 KiB
JavaScript
106 lines
4.0 KiB
JavaScript
var fs = Npm.require('fs');
|
|
var path = Npm.require('path');
|
|
var coffee = Npm.require('coffee-script');
|
|
var _ = Npm.require('underscore');
|
|
|
|
var stripExportedVars = function (source, exports) {
|
|
if (!exports || _.isEmpty(exports))
|
|
return source;
|
|
var lines = source.split("\n");
|
|
|
|
// We make the following assumptions, based on the output of CoffeeScript
|
|
// 1.6.3.
|
|
// - The var declaration in question is not indented and is the first such
|
|
// var declaration. (CoffeeScript only produces one var line at each
|
|
// scope and there's only one top-level scope.) All relevant variables
|
|
// are actually on this line.
|
|
// - The user hasn't used a ###-comment containing a line that looks like
|
|
// a var line, to produce something like
|
|
// /* bla
|
|
// var foo;
|
|
// */
|
|
// before an actual var line. (ie, we do NOT attempt to figure out if
|
|
// we're inside a /**/ comment, which is produced by ### comments.)
|
|
// - The var in question is not assigned to in the declaration, nor are any
|
|
// other vars on this line. (CoffeeScript does produce some assignments
|
|
// but only for internal helpers generated by CoffeeScript, and they end
|
|
// up on subsequent lines.)
|
|
// XXX relax these assumptions by doing actual JS parsing (eg with jsparse).
|
|
// I'd do this now, but there's no easy way to "unparse" a jsparse AST.
|
|
|
|
var foundVarLine = false;
|
|
lines = _.map(lines, function (line) {
|
|
if (foundVarLine)
|
|
return line;
|
|
var match = /^var (.+)([,;])$/.exec(line);
|
|
if (!match)
|
|
return line;
|
|
foundVarLine = true;
|
|
|
|
// If there's an assignment on this line, we assume that there are ONLY
|
|
// assignments and that the var we are looking for is not declared. (Part
|
|
// of our strong assumption about the layout of this code.)
|
|
if (match[1].indexOf('=') !== -1)
|
|
return line;
|
|
|
|
var vars = match[1].split(', ');
|
|
vars = _.difference(vars, exports);
|
|
if (!_.isEmpty(vars))
|
|
return "var " + vars.join(', ') + match[2];
|
|
// We got rid of all the vars on this line. Drop the whole line if this
|
|
// didn't continue to the next line, otherwise keep just the 'var '.
|
|
return match[2] === ';' ? '' : 'var';
|
|
});
|
|
return lines.join('\n');
|
|
};
|
|
|
|
var addSharedHeader = function (source) {
|
|
// We want the symbol "share" to be visible to all CoffeeScript files in the
|
|
// package (and shared between them), but not visible to JavaScript
|
|
// files. (That's because we don't want to introduce two competing ways to
|
|
// make package-local variables into JS ("share" vs assigning to non-var
|
|
// variables).) The following hack accomplishes that: "__coffeescriptShare"
|
|
// will be visible at the package level and "share" at the file level. This
|
|
// should work both in "package" mode where __coffeescriptShare will be added
|
|
// as a var in the package closure, and in "app" mode where it will end up as
|
|
// a global.
|
|
return ("__coffeescriptShare = typeof __coffeescriptShare === 'object' ? " +
|
|
"__coffeescriptShare : {}; " +
|
|
"var share = __coffeescriptShare;" +
|
|
source);
|
|
};
|
|
|
|
var handler = function (compileStep) {
|
|
var source = compileStep.read().toString('utf8');
|
|
var options = {
|
|
bare: true,
|
|
filename: compileStep.inputPath,
|
|
literate: path.extname(compileStep.inputPath) === '.litcoffee'
|
|
};
|
|
|
|
try {
|
|
var output = coffee.compile(source, options);
|
|
} catch (e) {
|
|
// XXX better error handling, once the Plugin interface support it
|
|
throw new Error(
|
|
compileStep.inputPath + ':' +
|
|
(e.location ? (e.location.first_line + ': ') : ' ') +
|
|
e.message
|
|
);
|
|
}
|
|
|
|
compileStep.addJavaScript({
|
|
path: compileStep.inputPath + ".js",
|
|
sourcePath: compileStep.inputPath,
|
|
data: output,
|
|
lineForLine: false,
|
|
linkerUnitTransform: function (source, exports) {
|
|
return addSharedHeader(stripExportedVars(source, exports));
|
|
}
|
|
});
|
|
};
|
|
|
|
Plugin.registerSourceHandler("coffee", handler);
|
|
Plugin.registerSourceHandler("litcoffee", handler);
|
|
|