mirror of
https://github.com/meteor/meteor.git
synced 2026-05-02 03:01:46 -04:00
Port Spacebars' templating package to batch plugins
This commit is contained in:
@@ -9,14 +9,18 @@ Package.describe({
|
||||
// registry and a default templating system, ideally per-package.
|
||||
|
||||
Package.registerBuildPlugin({
|
||||
name: "compileTemplates",
|
||||
name: "compileTemplatesBatch",
|
||||
// minifiers is a weak dependency of spacebars-compiler; adding it here
|
||||
// ensures that the output is minified. (Having it as a weak dependency means
|
||||
// that we don't ship uglify etc with built apps just because
|
||||
// boilerplate-generator uses spacebars-compiler.)
|
||||
// XXX maybe uglify should be applied by this plugin instead of via magic
|
||||
// weak dependency.
|
||||
use: ['minifiers', 'spacebars-compiler'],
|
||||
use: [
|
||||
'minifiers',
|
||||
'spacebars-compiler',
|
||||
'compiler-plugin'
|
||||
],
|
||||
sources: [
|
||||
'plugin/html_scanner.js',
|
||||
'plugin/compile-templates.js'
|
||||
|
||||
@@ -1,52 +1,89 @@
|
||||
var path = Npm.require('path');
|
||||
|
||||
var doHTMLScanning = function (compileStep, htmlScanner) {
|
||||
// XXX the way we deal with encodings here is sloppy .. should get
|
||||
// religion on that
|
||||
var contents = compileStep.read().toString('utf8');
|
||||
function TemplateCompiler () {}
|
||||
TemplateCompiler.prototype.processFilesForTarget = function (files) {
|
||||
var bodyAttrs = {};
|
||||
var bodyAttrsOrigin = {};
|
||||
|
||||
files.forEach(function (file) {
|
||||
var scanned = doHTMLScanning(file, html_scanner);
|
||||
Object.keys(scanned.bodyAttrs).forEach(function (attr) {
|
||||
var val = scanned.bodyAttrs[attr];
|
||||
if (bodyAttrs.hasOwnProperty(attr) && bodyAttrs[attr] !== val) {
|
||||
// two conflicting attributes on <body> tags in two different template
|
||||
// files
|
||||
var conflictingFilesStr = [bodyAttrsOrigin[attr], file].map(function (f) {
|
||||
return f.getPathInPackage();
|
||||
}).join(', ');
|
||||
|
||||
file.error({
|
||||
message: [
|
||||
"<body> declarations have conflicting values for the '",
|
||||
attr,
|
||||
"' attribute in the following files: ",
|
||||
conflictingFilesStr,
|
||||
"."
|
||||
].join('')
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
bodyAttrs[attr] = val;
|
||||
bodyAttrsOrigin[attr] = file;
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
var doHTMLScanning = function (inputFile, htmlScanner) {
|
||||
var contents = inputFile.getContentsAsString();
|
||||
try {
|
||||
var results = htmlScanner.scan(contents, compileStep.inputPath);
|
||||
var results = htmlScanner.scan(contents, inputFile.getPathInPackage());
|
||||
} catch (e) {
|
||||
if (e instanceof htmlScanner.ParseError) {
|
||||
compileStep.error({
|
||||
if ((e instanceof htmlScanner.ParseError) || (e instanceof htmlScanner.BodyAttrsError)) {
|
||||
inputFile.error({
|
||||
message: e.message,
|
||||
sourcePath: compileStep.inputPath,
|
||||
line: e.line
|
||||
});
|
||||
return;
|
||||
} else
|
||||
return null;
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
if (results.head)
|
||||
compileStep.appendDocument({ section: "head", data: results.head });
|
||||
inputFile.addHtml({ section: "head", data: results.head });
|
||||
|
||||
if (results.body)
|
||||
compileStep.appendDocument({ section: "body", data: results.body });
|
||||
inputFile.addHtml({ section: "body", data: results.body });
|
||||
|
||||
if (results.js) {
|
||||
var path_part = path.dirname(compileStep.inputPath);
|
||||
if (path_part === '.')
|
||||
path_part = '';
|
||||
if (path_part.length && path_part !== path.sep)
|
||||
path_part = path_part + path.sep;
|
||||
var ext = path.extname(compileStep.inputPath);
|
||||
var basename = path.basename(compileStep.inputPath, ext);
|
||||
var filePath = inputFile.getPathInPackage();
|
||||
var pathPart = path.dirname(filePath);
|
||||
if (pathPart === '.')
|
||||
pathPart = '';
|
||||
if (pathPart.length && pathPart !== path.sep)
|
||||
pathPart = pathPart + path.sep;
|
||||
var ext = path.extname(filePath);
|
||||
var basename = path.basename(filePath, ext);
|
||||
|
||||
// XXX generate a source map
|
||||
|
||||
compileStep.addJavaScript({
|
||||
path: path.join(path_part, "template." + basename + ".js"),
|
||||
sourcePath: compileStep.inputPath,
|
||||
inputFile.addJavaScript({
|
||||
path: path.join(pathPart, "template." + basename + ".js"),
|
||||
data: results.js
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
bodyAttrs: results.bodyAttrs
|
||||
};
|
||||
};
|
||||
|
||||
// XXX BBP rewrite to registerCompiler
|
||||
Plugin.registerSourceHandler(
|
||||
"html", {isTemplate: true, archMatching: 'web'},
|
||||
function (compileStep) {
|
||||
doHTMLScanning(compileStep, html_scanner);
|
||||
}
|
||||
);
|
||||
Plugin.registerCompiler({
|
||||
extensions: ['html'],
|
||||
archMatching: 'web',
|
||||
isTemplate: true
|
||||
}, function () {
|
||||
return new TemplateCompiler();
|
||||
});
|
||||
|
||||
|
||||
@@ -7,10 +7,8 @@ html_scanner = {
|
||||
// and ignores top-level HTML comments.
|
||||
|
||||
// Has fields 'message', 'line', 'file'
|
||||
ParseError: function () {
|
||||
},
|
||||
|
||||
bodyAttributes : [],
|
||||
ParseError: function () {},
|
||||
BodyAttrsError: function () {},
|
||||
|
||||
scan: function (contents, source_name) {
|
||||
var rest = contents;
|
||||
@@ -21,14 +19,23 @@ html_scanner = {
|
||||
index += amount;
|
||||
};
|
||||
|
||||
var throwParseError = function (msg, overrideIndex) {
|
||||
var ret = new html_scanner.ParseError;
|
||||
ret.message = msg || "bad formatting in template file";
|
||||
var throwSpecialError = function (msg, errorClass, overrideIndex) {
|
||||
var ret = new errorClass;
|
||||
ret.message = msg;
|
||||
ret.file = source_name;
|
||||
var theIndex = (typeof overrideIndex === 'number' ? overrideIndex : index);
|
||||
ret.line = contents.substring(0, theIndex).split('\n').length;
|
||||
throw ret;
|
||||
};
|
||||
var throwParseError = function (msg, overrideIndex) {
|
||||
throwSpecialError(
|
||||
msg || "bad formatting in template file",
|
||||
html_scanner.ParseError,
|
||||
overrideIndex);
|
||||
};
|
||||
var throwBodyAttrsError = function (msg) {
|
||||
throwSpecialError(msg, html_scanner.BodyAttrsError);
|
||||
};
|
||||
|
||||
var results = html_scanner._initResults();
|
||||
var rOpenTag = /^((<(template|head|body)\b)|(<!--)|(<!DOCTYPE|{{!)|$)/i;
|
||||
@@ -101,6 +108,10 @@ html_scanner = {
|
||||
var tagContents = rest.slice(0, end.index);
|
||||
var contentsStartIndex = index;
|
||||
|
||||
if (tagName === 'body') {
|
||||
this._addBodyAttrs(results, tagAttribs, throwBodyAttrsError);
|
||||
}
|
||||
|
||||
// act on the tag
|
||||
html_scanner._handleTag(results, tagName, tagAttribs, tagContents,
|
||||
throwParseError, contentsStartIndex,
|
||||
@@ -118,9 +129,23 @@ html_scanner = {
|
||||
results.head = '';
|
||||
results.body = '';
|
||||
results.js = '';
|
||||
results.bodyAttrs = {};
|
||||
return results;
|
||||
},
|
||||
|
||||
_addBodyAttrs: function (results, attrs, throwBodyAttrsError) {
|
||||
Object.keys(attrs).forEach(function (attr) {
|
||||
var val = attrs[attr];
|
||||
|
||||
if (results.bodyAttrs.hasOwnProperty(attr) && results.bodyAttrs[attr] !== val) {
|
||||
throwBodyAttrsError(
|
||||
"<body> declarations have conflicting values for the '" + attr + "' attribute.");
|
||||
}
|
||||
|
||||
results.bodyAttrs[attr] = val;
|
||||
});
|
||||
},
|
||||
|
||||
_handleTag: function (results, tag, attribs, contents, throwParseError,
|
||||
contentsStartIndex, tagStartIndex) {
|
||||
|
||||
@@ -173,9 +198,6 @@ html_scanner = {
|
||||
} else {
|
||||
// <body>
|
||||
if (hasAttribs) {
|
||||
// XXX we would want to throw an error here if we have duplicate
|
||||
// attributes, but this is complex to do with the current build system
|
||||
// so we won't.
|
||||
results.js += "\nMeteor.startup(function() { $('body').attr(" + JSON.stringify(attribs) + "); });\n";
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user