Permalink
Browse files

[lib/dist] second pass

  • Loading branch information...
1 parent b430a41 commit 90abd5ab0c791a6a246ebb4ae7ef4aeaf99b4ad8 Paolo Fragomeni committed Jan 11, 2012
View
@@ -2,7 +2,7 @@
## Synopsys
-Plates (short for templates) binds data to markup. There's NO special syntax. It works in the browser and in node.js! The right way to do this is with a DOM. Unfortunately, at the moment, the DOM is slow. On the server, it is quite slow. So Plates implements a very loose HTML parser.
+Plates (short for templates) binds data to markup. There's NO special syntax. It works in the browser and in `Node.js`. The right way to do this is with a DOM. Unfortunately, at the moment, the DOM is slow. On the server, it is quite slow.
## Motivation
@@ -18,7 +18,7 @@ Plates (short for templates) binds data to markup. There's NO special syntax. It
Install the library using npm or add it to your `package.json` file as a dependancy.
```bash
- $npm install plates
+ npm install plates
```
Take some markup, some data, bind them, done.
View
Binary file not shown.
View
@@ -1,5 +1,5 @@
-;var Plates = function main(undefined) {
+;var Plates = function Plates(undefined) {
var Merge = function Merge() {};
@@ -8,13 +8,13 @@
tag: new RegExp(
[
'(<',
- '(/?)', // 1 - is closing
- '([-:\\w]+)', // 2 - name
+ '(/?)', // 2 - is closing
+ '([-:\\w]+)', // 3 - name
'((?:\\s+[-\\w]+(?:', '=', '(?:' +
'\\w+|' +
'"[^"]*"|' +
- '\'[^\']*\'))?)*)', // 3 - attributes
- '(/?)', // 4 - is self-closing
+ '\'[^\']*\'))?)*)', // 4 - attributes
+ '(/?)', // 5 - is self-closing
'>)(.*)'
].join('\\s*')
),
@@ -27,182 +27,144 @@
bind: function bind(html, data, map) {
- var that = this,
- out = '',
- pos = 0,
- openers = 0,
- updates = [],
- matchmode = false,
- createmode = false,
- insert = true;
+ data = data || {};
if (map) {
map = map.mappings;
}
- while (html) {
- html.replace(that.tag, function (body, match, closing, tag, attributes, selfclosing, remainder, index) {
+ var that = this;
+ var str = html;
+ var buffer = '';
- //
- // search for the next tag, so we know
- // where and how to slice and dice the html.
- //
- var next = remainder.search(that.tag);
+ var matchmode = false;
+ var openers = 0;
+
+ var right = 0, left = 0;
+ var match, tag, text;
+
+ do {
+
+ tag = '', text = '';
+ left = right;
+ match = this.tag.exec(str); // test
+ str = match && match[6]; // next
+
+ if (match) {
+
+ right += match.index + match[1].length;
//
- // its a closing tag
+ // get the prior text to the left of the tag that was found.
+ // if it is a self closing tag, it will never have text.
//
+
if (matchmode) {
- if (!!closing) {
- if(openers === 0) {
- insert = true;
+
+ //
+ // and its a closing.
+ //
+ if (!!match[2]) {
+ if(openers <= 0) {
matchmode = false;
}
else {
--openers;
}
}
//
- // its not a closing tag!
+ // and its not a closing tag!
//
- else if (!selfclosing) {
+ else if (!match[5]) {
++openers;
- insert = false;
}
+
+ }
+ else if (!match[5]) {
+
+ text = html.slice(left, right - match[1].length);
}
//
- // we're at the end of the line.
+ // get the next tag from the stream.
//
- if (next === -1) {
- out += match + remainder;
- html = null;
- }
+ tag = html.slice(left + match.index, right);
+
//
- // we have a section, let's copy it over to
- // the output buffer and then disgard the rest.
+ // if there is a map, we may want to replace the value
+ // in an attribute or replace the body of the tag based
+ // on a specified attribute value. Closing tags are ignored.
//
- else {
+ if (map && !match[2]) {
- pos = next + (index + match.length);
+ for (var i = map.length - 1; i >= 0; i--) {
- //
- // find out if there is a match with either the map
- // or the data that was provided to the bind method.
- //
- !matchmode && match.replace(that.attr, function (attr, key, value, idx) {
-
- if (map) {
-
- //
- // if the map specifies a replacement to be made,
- // but there is no matching key found in the attributes
- // of the tag, we should create the attribute and then
- // popuate it.
- //
- createmode = false;
-
- //
- // look at all of the items in the map and try to apply
- // the mappings for all of the values that have been spec'd.
- //
-
- for (var i = map.length - 1; i >= 0; i--) {
-
- //
- // There may be an exact match for the key
- // that the map wants to replace.
- //
- if (map[i].replace === key && data[map[i].dataKey]) {
- updates.push({
- data: data[map[i].dataKey],
- insertion: {
- start: idx,
- end: attr.length
- }
- });
- continue;
- }
+ tag = tag.replace(
+ this.attr,
+ function (attr, key, value, idx) {
+
+ console.log(key, !map[i].replace, map[i].attribute === key, map[i].value, value)
+
+ if (map[i].replace === key) {
- //
- // find out if this tag is the target by looking at an
- // arbitrary attribute that the user has provided.
- //
- if (map[i].attribute === key && !map[i].replace &&
- (map[i].value === value || key === 'class' && that.hasClass(value))) {
- updates.push({ data: data[map[i].dataKey] });
+ //
+ // if there is data intended to replace the attribute, use that
+ // otherwise look at the data structure and try to use that.
+ //
+ var newdata = map[i].dataKey ? data[map[i].dataKey] : data[key];
+ return key + '="' + (newdata || '') + '"';
+ }
+ else if (!map[i].replace && map[i].attribute === key && map[i].value === value) {
+
+ buffer += text + tag + data[map[i].dataKey];
matchmode = true;
+ return attr;
}
- }
- }
- else {
+ else {
- //
- // find out if this tag is the target by checking the data
- // object and looking for this attribute value as an object key.
- //
- if (key === 'id' && data[value]) {
- updates.push({ data: data[value] });
- matchmode = true;
+ return attr;
+ }
}
- }
- });
+ );
+
+ console.log(tag);
+ }
+ }
+ else if (!match[5]) { // cant be self closing to have text in the body.
//
- // should we write data?
+ // if there is no map, we are just looking to match
+ // the specified id to a data key in the data object.
//
- if (updates.length > 0) {
-
- //
- // there may be multiple updates from the map
- //
-
- var update = null;
- while(update = updates.pop()) {
-
- //
- // position the new content
- //
-
- if (update.insertion) {
-
- //
- // in some cases the content goes inside the tag.
- //
- var i = update.insertion;
- var start = ~(index + i.start + i.end + 1);
- var value = html.slice(0, start);
-
- value += update.data + '"';
- value += html.slice(i.start + i.end);
- out += value;
- }
- else {
- //
- // in other cases, it goes inside the tag body.
- //
- out += html.slice(0, index + match.length) + update.data;
+ tag.replace(
+ this.attr,
+ function (attr, key, value, idx) {
+ if (key === 'id' && data[value]) {
+ buffer += text + tag + data[value];
+ matchmode = true;
}
}
- }
- else if (insert) {
- //
- // if there are no updates and we are not in the middle of a
- // match, just grab the next slice and add it to our buffer.
- //
- out += html.slice(0, pos);
- }
+ );
+ }
- //
- // reduce the initial html from existence.
- //
- html = html.substr(pos);
+ if (!matchmode) {
+ buffer += (text || '') + (tag || '');
}
- });
+ }
+ }
+ while (str);
+
+ //
+ // write anything that is leftover, as it will
+ // be arbitrary bites leftover from the stream.
+ //
+ if (html) {
+ buffer += html.slice(right);
}
- return out;
+ return buffer;
+
}
};
@@ -237,21 +199,15 @@
}
};
- return ({
- bind: function (html, data, map) {
- var merge = new Merge();
- return merge.bind(html, data, map);
- },
- Map: Mapper
- });
+ var host = (typeof process !== 'undefined' && process.title === 'node' ? exports : Plates);
-}();
-
-if (typeof module !== 'undefined') {
- exports.bind = function() {
- return Plates.bind.apply(this, arguments);
- };
- exports.Map = function() {
- return Paltes.Map.apply(this, arguments);
+ host.bind = function (html, data, map) {
+ var merge = new Merge();
+ return merge.bind(html, data, map);
};
-}
+
+ host.Map = Mapper;
+
+ return host;
+
+}();
Oops, something went wrong.

0 comments on commit 90abd5a

Please sign in to comment.