-
Notifications
You must be signed in to change notification settings - Fork 0
/
html_scanner.js
89 lines (79 loc) · 3.31 KB
/
html_scanner.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
// XXX should allow <!-- --> comments at toplevel
var html_scanner = module.exports = {
scan: function (contents) {
var results = { head: '', body: '', js: '' };
while (contents)
contents = html_scanner._scanChunk(results, contents);
return results;
},
_scanChunk: function (results, contents) {
if (contents.match(/^\s*$/))
return '';
// XXX this is really terrible and buggy. it's just a proof of
// concept, and probably will fail in all kinds of edge
// cases. Shouldn't be too hard to clean up, though, and that's
// probably the easiest option if we don't require that the
// contents of a <template> block parse as valid HTML.
var found = false;
// XXX forEach should probably be _.each, but we don't have a good
// way to get underscore included in this file yet, since it's
// code that's run at bundle-time, and we can't yet eval packages
// at bundle-time yet
['template', 'head', 'body'].forEach(function (tag) {
if (found) return;
var re = new RegExp("^\\s*<" + tag + "([^>]*?)>([\\s\\S]*?)</" + tag + ">([\\s\\S]*)$", 'i');
var match = contents.match(re);
if (!match) return;
found = true;
var attrs = match[1];
var payload = match[2];
contents = match[3];
// clean up HTML-y whitespace around payload..
match = payload.match(/^[ \t]*[\r\n]+(.*)$/);
if (match)
payload = match[1];
match = payload.match(/^(.*)[\r\n]+\s*$/);
if (match)
payload = match[1];
if (tag === "head") {
results[tag] += payload;
return;
}
// Strip all of the whitespace around the payload. This is so
// that if you make a template that's supposed to be a <tr>, you
// really get just a <tr>, and not a whitespace node, a tr, and
// then another whitespace node. (Maybe browsers are robust to
// this, I don't know, but we have this code for historical
// reasons and I don't feel like rocking the boat today. Maybe
// it should go away.) => Hard to see how this matters, since
// {{#each foo}}{{> bar}}{{/each}} will typically end up
// introducing whitespace around the partial invocation anyway.
match = payload.match(/^\s*([\s\S]*)$/);
payload = match[1];
match = payload.match(/^([\s\S]*\S)\s*$/);
if (match)
payload = match[1];
var code = 'Handlebars.json_ast_to_func(' +
JSON.stringify(Handlebars.to_json_ast(payload)) + ')';
if (tag === "template") {
// XXX fails for attributes that contain whitespace, and
// probably lots of other stuff too..
match = attrs.match(/[$\s]name=["']?([^"'\s]+)["'\s]/);
if (!match)
// XXX improve error
throw new Error("Template missing id attribute, um, somewhere ...");
var id = match[1];
results.js += "Meteor._def_template(" + JSON.stringify(id) + "," + code +
");\n";
} else { // tag === "body"
results.js += "Meteor.startup(function(){document.body.appendChild(Meteor.ui.render(Meteor._def_template(null," + code + ")));});";
}
});
if (!found) {
// XXX how to report an error here?
// XXX improve error!!
throw new Error("Couldn't parse .. um .. some HTML file, on some line. sorry");
}
return contents;
}
};