mirror of
https://github.com/meteor/meteor.git
synced 2026-05-02 03:01:46 -04:00
seems to work (not fully tested)
This commit is contained in:
@@ -1,5 +1,9 @@
|
||||
|
||||
HTML.Special = function (value) {
|
||||
if (! (this instanceof HTML.Special))
|
||||
// called without `new`
|
||||
return new HTML.Special(value);
|
||||
|
||||
this.value = value;
|
||||
};
|
||||
HTML.Special.prototype.toJS = function (options) {
|
||||
|
||||
@@ -1,151 +0,0 @@
|
||||
// A Tag is an array of zero or more content items, with additional properties
|
||||
// `tagName` (String, required) and `attrs` (Object or `null`). In addition to
|
||||
// be arrays, Tags are `instanceof HTML.Tag`.
|
||||
//
|
||||
// An attribute value may be null, a string, a CharRef tag, or an array of
|
||||
// strings, CharRef tags, arrays, and nulls.
|
||||
//
|
||||
// Tags are created using tag functions, e.g. `DIV(P({id:'foo'}, "Hello"))`.
|
||||
// If a tag function is given a first argument that is an object and not a
|
||||
// Tag or an array, that object is used as element attributes (`attrs`).
|
||||
// The attrs argument may be of the form `{$attrs: function () { ... }}` in
|
||||
// which case the function becomes the `attrs` attribute of the tag.
|
||||
//
|
||||
// Tag functions for all known tags are available as `HTML.Tag.DIV`,
|
||||
// `HTML.Tag.SPAN`, etc., and you can define new ones with
|
||||
// `HTML.defineTag("FOO")`, which makes a tag function available at
|
||||
// `HTML.Tag.FOO` henceforth. You can also use `HTML.getTag("FOO")` to
|
||||
// define (if necessary) and return a tag function.
|
||||
|
||||
Tag = function (tagName, attrs) {
|
||||
this.tagName = tagName;
|
||||
this.attrs = attrs; // may be falsy
|
||||
};
|
||||
Tag.prototype = [];
|
||||
|
||||
makeTagFunc = function (name) {
|
||||
// Do a little dance so that tags print nicely in the Chrome console.
|
||||
// First make tag name suitable for insertion into evaluated JS code,
|
||||
// for security reasons mainly.
|
||||
var sanitizedName = String(name).replace(/^[^a-zA-Z_]|[^a-zA-Z_0-9]+/g,
|
||||
'') || 'Tag';
|
||||
// Generate a constructor function whose name is the tag name.
|
||||
// We try to choose generic-sounding variable names in case V8 infers
|
||||
// them as type names and they show up in the developer console.
|
||||
// HTMLTag is the constructor function for our specific tag type,
|
||||
// while Tag is the super constructor.
|
||||
var HTMLTag = (new Function('return function ' +
|
||||
sanitizedName +
|
||||
'(attrs) { this.attrs = attrs; };'))();
|
||||
HTMLTag.prototype = new Tag(name);
|
||||
|
||||
return function (optAttrs/*, children*/) {
|
||||
// see whether first argument is truthy and not an Array or Tag
|
||||
var attrsGiven = (optAttrs && (typeof optAttrs === 'object') &&
|
||||
(typeof optAttrs.splice !== 'function'));
|
||||
var attrs = (attrsGiven ? optAttrs : null);
|
||||
if (attrsGiven && (typeof attrs.$attrs === 'function'))
|
||||
attrs = attrs.$attrs;
|
||||
|
||||
var tag = new HTMLTag(attrs);
|
||||
tag.push.apply(tag, (attrsGiven ?
|
||||
Array.prototype.slice.call(arguments, 1) :
|
||||
arguments));
|
||||
return tag;
|
||||
};
|
||||
};
|
||||
|
||||
defineTag = function (name) {
|
||||
// XXX maybe sanity-check name? Like no whitespace.
|
||||
name = name.toUpperCase();
|
||||
Tag[name] = makeTagFunc(name);
|
||||
return Tag[name];
|
||||
};
|
||||
|
||||
getTag = function (name) {
|
||||
name = name.toUpperCase();
|
||||
return Tag[name] || defineTag(name);
|
||||
};
|
||||
|
||||
// checks that a pseudoDOM node with tagName "CharRef" is well-formed.
|
||||
var checkCharRef = function (charRef) {
|
||||
if (typeof charRef.attrs === 'function')
|
||||
throw new Error("Can't have a reactive character reference (CharRef)");
|
||||
|
||||
var attrs = charRef.attrs;
|
||||
if ((! attrs) || (typeof attrs.html !== 'string') ||
|
||||
(typeof attrs.str !== 'string') || (! attrs.html) || (! attrs.str))
|
||||
throw new Error("CharRef should have simple string attributes " +
|
||||
"`html` and `str`.");
|
||||
|
||||
if (charRef.length)
|
||||
throw new Error("CharRef should have no content");
|
||||
};
|
||||
|
||||
// checks that a pseudoDOM node with tagName "Comment" is well-formed.
|
||||
var checkComment = function (comment) {
|
||||
if (comment.attrs)
|
||||
throw new Error("Comment can't have attributes");
|
||||
if (comment.length !== 1 || (typeof comment[0] !== 'string'))
|
||||
throw new Error("Comment should have exactly one content item, a simple string");
|
||||
};
|
||||
|
||||
// checks that a pseudoDOM node with tagName "Raw" is well-formed.
|
||||
var checkRaw = function (raw) {
|
||||
if (raw.attrs)
|
||||
throw new Error("Raw can't have attributes");
|
||||
if (raw.length !== 1 || (typeof raw[0] !== 'string'))
|
||||
throw new Error("Raw should have exactly one content item, a simple string");
|
||||
};
|
||||
|
||||
// checks that a pseudoDOM node with tagName "Comment" is well-formed.
|
||||
var checkEmitCode = function (node) {
|
||||
if (node.attrs)
|
||||
throw new Error("EmitCode can't have attributes");
|
||||
if (node.length !== 1 || (typeof node[0] !== 'string'))
|
||||
throw new Error("EmitCode should have exactly one content item, a simple string");
|
||||
};
|
||||
|
||||
var checkSpecial = function (node) {
|
||||
if (! node.attrs)
|
||||
throw new Error("Special tag must have attributes");
|
||||
if (node.length > 0)
|
||||
throw new Error("Special tag must not have content");
|
||||
};
|
||||
|
||||
typeOf = function (node) {
|
||||
if (node && (typeof node === 'object') &&
|
||||
(typeof node.splice === 'function')) {
|
||||
// Tag or array
|
||||
if (node.tagName) {
|
||||
if (node.tagName === 'CharRef') {
|
||||
checkCharRef(node);
|
||||
return 'charref';
|
||||
} else if (node.tagName === 'Comment') {
|
||||
checkComment(node);
|
||||
return 'comment';
|
||||
} else if (node.tagName === 'EmitCode') {
|
||||
checkEmitCode(node);
|
||||
return 'emitcode';
|
||||
} else if (node.tagName === 'Special') {
|
||||
checkSpecial(node);
|
||||
return 'special';
|
||||
} else if (node.tagName === 'Raw') {
|
||||
checkRaw(node);
|
||||
return 'raw';
|
||||
} else {
|
||||
return 'tag';
|
||||
}
|
||||
} else {
|
||||
return 'array';
|
||||
}
|
||||
} else if (typeof node === 'string') {
|
||||
return 'string';
|
||||
} else if (typeof node === 'function') {
|
||||
return 'function';
|
||||
} else if (node == null) {
|
||||
return 'null';
|
||||
} else {
|
||||
throw new Error("Unexpected item in HTML tree: " + node);
|
||||
}
|
||||
};
|
||||
@@ -139,7 +139,7 @@ HTML.Raw = function (value) {
|
||||
HTML.EmitCode = function (value) {
|
||||
if (! (this instanceof HTML.EmitCode))
|
||||
// called without `new`
|
||||
return new HTML.Raw(value);
|
||||
return new HTML.EmitCode(value);
|
||||
|
||||
if (typeof value !== 'string')
|
||||
throw new Error('HTML.EmitCode must be constructed with a string');
|
||||
|
||||
@@ -448,7 +448,7 @@ var optimize = function (tree) {
|
||||
var pushRawHTML = function (array, html) {
|
||||
var N = array.length;
|
||||
if (N > 0 && (array[N-1] instanceof HTML.Raw)) {
|
||||
array[N-1][0] += html;
|
||||
array[N-1] = HTML.Raw(array[N-1].value + html);
|
||||
} else {
|
||||
array.push(HTML.Raw(html));
|
||||
}
|
||||
@@ -485,9 +485,9 @@ var optimize = function (tree) {
|
||||
// clean up unnecessary HTML.Raw wrappers around pure character data
|
||||
for (var j = 0; j < result.length; j++) {
|
||||
if ((result[j] instanceof HTML.Raw) &&
|
||||
isPureChars(result[j][0]))
|
||||
isPureChars(result[j].value))
|
||||
// replace HTML.Raw with simple string
|
||||
result[j] = result[j][0];
|
||||
result[j] = result[j].value;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
@@ -785,17 +785,14 @@ Spacebars._handleSpecialAttributes = function (oldAttrs) {
|
||||
//
|
||||
// If specials are found, sets `foundSpecials` to true.
|
||||
var convertSpecialToEmitCode = function (v) {
|
||||
var type = HTML.typeOf(v);
|
||||
if (type === 'null' || type === 'string' || type === 'charref') {
|
||||
return v;
|
||||
} else if (type === 'special') {
|
||||
if (v instanceof HTML.Special) {
|
||||
foundSpecials = true;
|
||||
return HTML.EmitCode('function () { return ' +
|
||||
codeGenMustache(v.attrs) + '; }');
|
||||
} else if (type === 'array') {
|
||||
codeGenMustache(v.value) + '; }');
|
||||
} else if (v instanceof Array) {
|
||||
return _.map(v, convertSpecialToEmitCode);
|
||||
} else {
|
||||
throw new Error("Unexpected node in attribute value: " + v);
|
||||
return v;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -165,7 +165,7 @@ html_scanner = {
|
||||
contents, { sourceName: "<body>" });
|
||||
|
||||
// We may be one of many `<body>` tags.
|
||||
results.js += "\nUI.body2.contentParts.push(UI.Component.extend({render: " + renderFuncCode + "}));\nMeteor.startup(function () { if (! UI.body2.INSTANTIATED) { UI.materialize(UI.body2, document.body); } });\n";
|
||||
results.js += "\nUI.body.contentParts.push(UI.Component.extend({render: " + renderFuncCode + "}));\nMeteor.startup(function () { if (! UI.body.INSTANTIATED) { UI.materialize(UI.body, document.body); } });\n";
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -26,7 +26,7 @@ Tinytest.add("templating - html scanner", function (test) {
|
||||
// where content is something simple like the string "Hello"
|
||||
// (passed in as a source string including the quotes).
|
||||
var simpleBody = function (content) {
|
||||
return "\nUI.body2.contentParts.push(UI.Component.extend({render: (function() {\n var self = this;\n return " + content + ";\n})}));\nMeteor.startup(function () { if (! UI.body2.INSTANTIATED) { UI.materialize(UI.body2, document.body); } });\n";
|
||||
return "\nUI.body.contentParts.push(UI.Component.extend({render: (function() {\n var self = this;\n return " + content + ";\n})}));\nMeteor.startup(function () { if (! UI.body.INSTANTIATED) { UI.materialize(UI.body, document.body); } });\n";
|
||||
};
|
||||
|
||||
// arguments are quoted strings like '"hello"'
|
||||
|
||||
@@ -213,11 +213,10 @@ var updateAttributes = function(elem, newAttrs, handlers) {
|
||||
for (var k in newAttrs) {
|
||||
var handler = null;
|
||||
var oldValue;
|
||||
var value = attributeValueToString(newAttrs[k]);
|
||||
var value = newAttrs[k];
|
||||
if ((! handlers) || (! handlers.hasOwnProperty(k))) {
|
||||
if (value !== null) {
|
||||
// make new handler
|
||||
checkAttributeName(k);
|
||||
handler = makeAttributeHandler(k, value);
|
||||
if (handlers)
|
||||
handlers[k] = handler;
|
||||
@@ -359,7 +358,7 @@ var materialize = function (node, parent, before, parentComponent) {
|
||||
// for example, maybe some of them go in the HTML package.
|
||||
UI.materialize = materialize;
|
||||
|
||||
UI.body2 = UI.Component.extend({
|
||||
UI.body = UI.Component.extend({
|
||||
kind: 'body',
|
||||
contentParts: [],
|
||||
render: function () {
|
||||
|
||||
Reference in New Issue
Block a user