This commit is contained in:
Kevin Ngo 2014-10-06 14:29:02 -07:00
Родитель 49e6271589
Коммит 58802b87a3
2 изменённых файлов: 19 добавлений и 480 удалений

Просмотреть файл

@ -1,86 +1,5 @@
var fs = require('fs');
var path = require('path');
var utils = require('./utils.js');
var blacklist = [
'assert.js',
'require.js',
'localforage.js',
'settings_inferno.js',
'settings_local.js',
'settings_travis.js',
'tests.js',
'splash.styl.css',
'templates.js', // Generated dynamically.
'include.js',
'include.css',
'splash.css'
];
var re_blacklist = [
/^settings_package_/
];
function concatJS(src_dir, callback) {
var output = '';
// Render the HTML for the templates.
compileHTML(src_dir, function(html_data) {
output += html_data;
// Now include the rest of the JS.
utils.globEach(
path.resolve(src_dir, 'media', 'js'),
'.js',
function(file) {
// Don't include blacklisted files.
if (blacklist.indexOf(path.basename(file)) !== -1) {
return;
}
for (var i = 0; i < re_blacklist.length; i++) {
if (path.basename(file).match(re_blacklist[i])) {
return;
}
}
// Automatically name anonymous modules.
var module_name = path.basename(file).replace('.js', '');
var js = fs.readFileSync(file).toString();
js = js.replace('define([', "define('" + module_name + "', [");
js = js.replace('define(function', "define('" + module_name + "', [], function");
output += js + '\n';
}, function() {
callback(output);
}
);
});
}
function compileStylus(source_path, callback) {
var stylus = require('stylus');
fs.readFile(source_path, function(err, data) {
if (err) {
console.error('Could not read stylus file: ' + source_path);
callback(err);
return;
}
stylus(data.toString())
.set('filename', source_path + '.css')
.set('include css', true)
.include(path.dirname(source_path))
.render(function(err, css) {
if (err) {
console.error('Error compiling stylus file: ' + source_path);
callback(err);
return;
}
callback(null, css);
});
});
}
function fix_urls(img_urls, css_dir, src_dir, url_pattern, data) {
var has_origin = false;
@ -127,152 +46,3 @@ function fix_urls(img_urls, css_dir, src_dir, url_pattern, data) {
return 'url(' + url + ')';
});
}
function minifyCSS(src_dir, src, callback) {
var css_pattern = new RegExp('href=".+' + src + '"', 'g');
var url_pattern = /url\(([^)]+)\)/g;
var img_urls = [];
var css_dir = path.resolve(src_dir, 'media/css');
var imgurls_fn = path.resolve(src_dir, 'media/imgurls.txt');
var index_html = fs.readFile(path.resolve(src_dir, 'index.html'), function(err, data) {
if (err) {
console.error('Could not read `index.html`.', err);
return;
}
var match;
var files = [];
data = data.toString();
while (match = css_pattern.exec(data)) {
files.push(path.resolve(src_dir + match[1]));
}
var output = '';
compileStylus(path.resolve(src_dir, src).replace('.styl.css', '.styl'), function(err, data) {
if (err) {
console.warn(err);
} else {
output = fix_urls(img_urls, css_dir, src_dir, url_pattern, data + '\n');
}
fs.appendFile(imgurls_fn, img_urls.join('\n') + '\n', function(err) {
if (err) {
console.error('Error writing `imgurls.txt` to disk.');
return;
}
console.log('Created ' + imgurls_fn);
});
callback(output);
});
});
}
function concatCSS(src_dir, callback) {
var css_pattern = /href="(\/media\/css\/.+\.styl\.css)"/g;
var url_pattern = /url\(([^)]+)\)/g;
var img_urls = [];
var css_dir = path.resolve(src_dir, 'media/css');
var imgurls_fn = path.resolve(src_dir, 'media/imgurls.txt');
var has_origin = false;
var index_html = fs.readFile(path.resolve(src_dir, 'index.html'), function(err, data) {
if (err) {
console.error('Could not read `index.html`.', err);
return;
}
var match;
var files = [];
data = data.toString();
while (match = css_pattern.exec(data)) {
if (blacklist.indexOf(path.basename(match[1])) === -1) {
files.push(path.resolve(src_dir + match[1]));
}
}
var output = [];
var remaining = files.length;
files.forEach(function(v, index) {
v = v.replace('.styl.css', '.styl');
compileStylus(v, function(err, data) {
if (err) {
console.warn(err);
} else {
output[index] = fix_urls(img_urls, css_dir, src_dir, url_pattern, data + '\n');
}
remaining--;
if (!remaining) {
fs.writeFile(imgurls_fn, img_urls.join('\n') + '\n', function(err) {
if (err) {
console.error('Error writing `imgurls.txt` to disk.');
return;
}
console.log('Created ' + imgurls_fn);
});
callback(output.join('\n'));
}
});
});
});
}
function compileHTML(src_dir, callback) {
var compiler = require('nunjucks').compiler;
var parser = require('nunjucks').parser;
var optimizer = require('./template_optimizer');
var extensions = require('./deferparser').extensions || [];
var template_dir = path.resolve(src_dir, 'templates');
if (template_dir.substr(-1) !== '/') {
template_dir += '/';
}
var template_data = [];
utils.globEach(template_dir, '.html', function(template) {
var name = template.replace(template_dir, '');
var output = 'templates[' + JSON.stringify(name) + '] = (function() {';
try {
var src = fs.readFileSync(template, 'utf-8');
var cinst = new compiler.Compiler(extensions);
// Parse
var parsed = parser.parse(src, extensions);
var optimized = optimizer.optimize(parsed);
// Compile
optimizer.monkeypatch(cinst);
cinst.compile(parsed);
// Output
output += cinst.getCode();
} catch(e) {
output += [
'return {root: function() {',
'throw new Error("' + name + ' failed to compile. Check the damper for details.");',
'}}'
].join('\n');
console.error(e);
}
template_data.push(output + '})();\n');
}, function() {
callback(
'(function() {' +
'var templates = {};\n' +
template_data.join('\n') +
'define("templates", ["nunjucks", "helpers"], function(nunjucks) {\n' +
' nunjucks.env = new nunjucks.Environment([], {autoescape: true});\n' +
' nunjucks.env.cache = nunjucks.templates = templates;\n' +
' console.log("Templates loaded");\n' +
' return nunjucks;\n' +
'});\n' +
'})();'
);
});
}
module.exports.js = concatJS;
module.exports.stylus = compileStylus;
module.exports.css = concatCSS;
module.exports.cssMinify = minifyCSS;
module.exports.html = compileHTML;

Просмотреть файл

@ -9,57 +9,6 @@ var check_version = info.check_version;
var noop = function() {};
function clean(src_dir, callback) {
callback = callback || noop;
src_dir = src_dir || info.src_dir();
check_version(src_dir, undefined, undefined, function() {
console.error('No Commonplace installation found.');
process.exit(1);
});
var started = 1; // Start at 1 so we don't trigger it too early.
function completed() {
started--;
if (started) return;
callback();
}
var targets = [
'_tmp',
'templates.js',
'media/build_id.txt',
'media/imgurls.txt',
'media/css/splash.css',
'media/css/include.css',
'media/js/include.js',
'media/locales/',
'locales/'
];
targets.forEach(function(filePath) {
filePath = path.resolve(src_dir, filePath);
if (!fs.existsSync(filePath)) return;
var data = fs.statSync(filePath);
started++;
if (data && data.isDirectory()) {
utils.rmdirRecursive(filePath, completed);
} else {
utils.removeFile(filePath, completed);
}
});
var css_dir = path.resolve(src_dir, 'media', 'css');
if (!fs.existsSync(css_dir)) {
console.warn('CSS directory does not exist.');
return;
}
utils.globEach(css_dir, '.styl.css', function(filepath) {
started++;
utils.removeFile(filepath, completed);
});
// Decrement `started` in case everything somehow already finished.
completed();
}
function generate_langpacks() {
var process_file = require('./generate_langpacks').process_file;
@ -189,200 +138,6 @@ function extract_l10n() {
});
}
function compile(options) {
var src_dir = info.src_dir();
if (!options || !options.silent) {
check_version(src_dir, undefined, function() {
console.warn('Found different commonplace version.');
console.warn('Generated includes may not work as expected.');
}, function() {
console.error('No Commonplace installation found.');
process.exit(1);
});
}
var build = require('./build.js');
var todo = (options && options.only) || ['stylus', 'nunjucks'];
var remaining = todo.length;
todo.forEach(function(v) {
switch (v) {
case 'stylus':
utils.globEach(src_dir, '.styl', function(file) {
// For every stylus file, increase the pending operation count.
// That way, the callback won't fire until everything is done.
remaining++;
build.stylus(file, function(err, css) {
if (err) {
console.error(err);
return;
}
fs.writeFile(file + '.css', css, function(err) {
if (err) {
console.error('Error writing CSS file: ' + file + '.css');
console.error(err);
return;
}
remaining--;
if (!remaining && options && options.callback) options.callback();
});
});
}, function() {
remaining--;
if (!remaining && options && options.callback) options.callback();
});
break;
case 'nunjucks':
build.html(src_dir, function(data) {
fs.writeFile(path.resolve(src_dir, 'templates.js'), data, function(err) {
if (err) {
console.error('Error writing templates file.', err);
return;
}
remaining--;
if (!remaining && options && options.callback) options.callback();
});
});
}
});
}
function build_includes(src_dir, callback) {
callback = callback || noop;
src_dir = src_dir || info.src_dir();
var raw = utils.opts().raw;
check_version(src_dir, undefined, function() {
console.warn('Found different commonplace version.');
console.warn('Generated includes may not work as expected.');
}, function() {
console.error('No Commonplace installation found.');
process.exit(1);
});
var started = 3;
function completed() {
started--;
if (started) return;
var build_id_file = path.resolve(src_dir, 'media', 'build_id.txt');
fs.writeFile(build_id_file, new Date().getTime(), function(err) {
if (err) {
console.error('Error writing `build_id.txt` to disk.');
} else {
console.log('Created ' + build_id_file);
}
callback();
});
}
var build = require('./build.js');
(function read_almond_js() {
// Read assets/almond.js into a string to build.
fs.readFile(path.resolve(__dirname, 'assets', 'almond.js'), function(err, almond_js) {
// Load in almond.js.
if (err) {
console.warn('Error reading `almond.js`.', err);
return;
}
try {
almond_js = require('uglify-js').minify(
almond_js.toString(), {screw_ie8: true, fromString: true}).code;
} catch(e) {
console.error('Error during minification.', e);
return;
}
read_init_js(almond_js);
});
})();
function read_init_js(almond_code) {
// Read assets/init.js (it ```require```s the main module).
// Passes the require.js/require-config.js code and itself to build.
fs.readFile(path.resolve(__dirname, 'assets', 'init.js'), function(err, init_js) {
// Load in require-config.js.
if (err) {
console.warn('Error reading `init.js`.', err);
return;
}
build_js(almond_code, init_js.toString());
});
}
function build_js(prefix_code, suffix_code) {
// Build include.js.
// Prefixes include.js with prefix_code (require.js code).
// Suffixes include.js with suffix_code (initialize main module code).
build.js(src_dir, function(data) {
if (!raw) {
try {
data = [
prefix_code,
require('uglify-js').minify(
data, {screw_ie8: true, fromString: true}).code,
suffix_code
].join('');
} catch(e) {
console.error('Error during minification.', e);
}
}
var include_js = path.resolve(src_dir, 'media', 'js', 'include.js');
fs.writeFile(include_js, data, function(err) {
if (err) {
console.error('Error writing `include.js` to disk.');
return;
}
console.log('Created ' + include_js);
completed();
});
});
}
var cleancss = (new (require('clean-css')));
build.css(src_dir, function(data) {
if (!raw) {
data = cleancss.minify(data);
}
var include_css = path.resolve(src_dir, 'media', 'css', 'include.css');
fs.writeFile(include_css, data, function(err) {
if (err) {
console.error('Error writing `include.css` to disk.');
return;
}
console.log('Created ' + include_css);
completed();
});
});
// The stylesheet used for the splash screen needs to happen after the
// other files have been processed (because of the `imgurls.txt` file).
fs.exists(path.resolve(src_dir, 'media', 'css', 'splash.styl'), function (exists) {
if (!exists) {
return completed();
}
build.cssMinify(src_dir, 'media/css/splash.styl.css', function(data) {
if (!raw) {
data = cleancss.minify(data);
}
var splash_css = path.resolve(src_dir, 'media', 'css', 'splash.css');
fs.writeFile(splash_css, data, function(err) {
if (err) {
console.error('Error writing `splash.css` to disk.');
return;
}
console.log('Created ' + splash_css);
completed();
});
});
});
}
function lint() {
var jshint = require('jshint').JSHINT;
@ -496,6 +251,19 @@ function fiddle() {
});
}
function run_make_build(name, callback) {
// Runs make build which builds the project.
var make_init = spawn('make', ['build'],
{cwd: path.resolve(projects_target, name)});
make_init.stderr.pipe(process.stderr);
make_init.on('close', function(code) {
if (code !== 0) {
console.error('`make build` on project "' + name + '" failed with non-zero exit code.');
}
callback();
});
}
function make_symlinks(name, data, callback) {
if (!data.symlinks) {
callback();
@ -544,7 +312,7 @@ function fiddle() {
function callback_init() {
// Compile the assets for the project.
build_includes(proj_src, callback_includes);
run_make_build(data.name, callback_includes);
}
function callback_includes() {
@ -573,11 +341,12 @@ function wrap(func) {
};
}
module.exports.config = require('./config');
module.exports.clean = wrap(clean);
module.exports.generate_langpacks = wrap(generate_langpacks);
module.exports.extract_l10n = wrap(extract_l10n);
module.exports.compile = wrap(compile);
module.exports.build_includes = wrap(build_includes);
module.exports.lint = lint;
module.exports.fiddle = wrap(fiddle);
module.exports.config = require('./config');
module.exports.template_optimizer = require('./template_optimizer');
module.exports.deferparser = require('./deferparser');