UNPKG

dynamictemplate

Version:
391 lines (352 loc) 11.5 kB
(function() { var DOMElementType, HTMLCompiler, Tag, Template, copy_structure, deep_merge, example, example2, fs, hook, isArray, jQuery, jsonify, mask, match, new_tag, slim, slim_attrs, suitup, traverse, trim, util, _ref; var __slice = Array.prototype.slice; fs = require('fs'); jQuery = require('jquery'); isArray = Array.isArray; DOMElementType = { NORMAL: 1, TEXT: 3, CDATA: 4, FRAGMENT: 11 }; deep_merge = function() { var k, obj, objs, res, v, _i, _len; objs = 1 <= arguments.length ? __slice.call(arguments, 0) : []; if (isArray(objs[0])) objs = objs[0]; res = {}; for (_i = 0, _len = objs.length; _i < _len; _i++) { obj = objs[_i]; for (k in obj) { v = obj[k]; if (typeof v === 'object' && !isArray(v)) { res[k] = deep_merge(res[k] || {}, v); } else { res[k] = v; } } } return res; }; trim = function(str) { return str.replace(/^\s+|\s+$/g, ""); }; slim_attrs = function(el) { var attr, attrs, _i, _len, _ref, _ref2; attrs = {}; _ref2 = (_ref = el.attributes) != null ? _ref : []; for (_i = 0, _len = _ref2.length; _i < _len; _i++) { attr = _ref2[_i]; attrs[attr.name] = attr.value; } return attrs; }; slim = function(el) { return { name: el.nodeName.toLowerCase(), attrs: slim_attrs(el), children: traverse(el.childNodes) }; }; traverse = function(elems) { var el, res, _i, _len; if (elems == null) return []; res = []; for (_i = 0, _len = elems.length; _i < _len; _i++) { el = elems[_i]; if (el.nodeType === DOMElementType.NORMAL) { res.push(slim(el)); } else if (el.nodeType === DOMElementType.TEXT) { if (trim(el.value).length) res.push(el.value); } else { continue; } } return res; }; jsonify = function(elems) { var el, _i, _len, _ref, _results; _ref = elems != null ? elems : []; _results = []; for (_i = 0, _len = _ref.length; _i < _len; _i++) { el = _ref[_i]; _results.push(slim(el)); } return _results; }; copy_structure = function(tree) { var el, res, _i, _len, _ref; res = []; _ref = tree != null ? tree : []; for (_i = 0, _len = _ref.length; _i < _len; _i++) { el = _ref[_i]; if (typeof el === 'string' || typeof el === 'number') { res.push(el); continue; } res.push({ name: el.name, attrs: el.attrs, children: copy_structure(el.children) }); } return res; }; match = function(tag, el) { var key, value, _ref, _ref2; if (el == null) return true; if (tag.name !== el.name) return false; _ref = tag.attrs; for (key in _ref) { value = _ref[key]; if (el.attrs[key] !== value) { if (typeof value !== 'string' || (((_ref2 = el.attrs[key]) != null ? _ref2.indexOf(value) : void 0) || -1) === -1) { return false; } } } return true; }; new_tag = function(parent, el, callback) { var attrs; attrs = deep_merge(el.attrs); return parent.tag(el.name, attrs, function() { var child, _i, _len, _ref, _ref2; _ref2 = (_ref = el.children.slice()) != null ? _ref : []; for (_i = 0, _len = _ref2.length; _i < _len; _i++) { child = _ref2[_i]; if (typeof child === 'string' || typeof child === 'number') { this.text("" + child, { append: true }); } else { new_tag(this, child, function() { if (typeof callback === "function") callback(); return callback = null; }); } } this.end(); return typeof callback === "function" ? callback() : void 0; }); }; mask = function(tag, el) { if (el == null) return; tag.attr(el.attrs); return tag._elems = el.children; }; hook = function(tpl) { return tpl.xml.use(function(parent, tag, next) { var elems, repeat; elems = parent._elems; if (elems == null) return next(tag); repeat = function() { var el; el = elems[0]; if (typeof el === 'string' || typeof el === 'number') { console.log("text".blue, el); elems.shift(); if (typeof parent.text === "function") { parent.text(el, { append: true }); } return repeat(); } else if (match(tag, el)) { console.log("match".yellow, el != null ? el.name : void 0, el != null ? el.attrs : void 0); elems.shift(); mask(tag, el); return next(tag); } else { console.log("new".green, el != null ? el.name : void 0, el != null ? el.attrs : void 0, "(", tag.name, tag.attrs, ")"); console.log("WTF WTF WTF WTF".bold.red, tag.name, tag.attrs); return new_tag(parent, el, function() { console.log("repeat".red, tag.name, tag.attrs, "(", el != null ? el.name : void 0, el != null ? el.attrs : void 0, ")"); return repeat(); }); } }; return repeat(); }); }; suitup = function(rawtemplate, tree) { return function() { var args, elems, tpl; args = 1 <= arguments.length ? __slice.call(arguments, 0) : []; tpl = rawtemplate.apply(null, args); elems = copy_structure(tree); tpl.xml._elems = elems; hook(tpl); return tpl; }; }; HTMLCompiler = (function() { function HTMLCompiler() { this.$ = jQuery.create(); this.loadSync = this.open; } HTMLCompiler.prototype.read = function(filename, callback) { var _this = this; return fs.readFile(filename, function(err, data) { return callback != null ? callback.call(_this, err, data != null ? data.toString() : void 0) : void 0; }); }; HTMLCompiler.prototype.readSync = function(filename) { var _ref; return (_ref = fs.readFileSync(filename)) != null ? _ref.toString() : void 0; }; HTMLCompiler.prototype.parse = function(data) { return this.el = this.$(data); }; HTMLCompiler.prototype.select = function(from, to) { var el; el = this.el.find(from); el = el.clone(); el.find(to).remove(); return el; }; HTMLCompiler.prototype.use = function(data) { this.loaded = true; return this.parse(data); }; HTMLCompiler.prototype.load = function(filename, callback) { return this.read(filename, function(err, data) { if (err) return callback.call(this, err); this.use(data); return callback(null, this.el); }); }; HTMLCompiler.prototype.open = function(filename) { var data; data = this.readSync(filename); return this.use(data); }; HTMLCompiler.prototype.compile = function(rawtemplate, el) { var r, tree; if (!this.loaded) { throw new Error("no html file loaded or html string used."); } console.log("building data structure ..."); if (el == null) el = this.el; tree = jsonify(el); console.log("design is ready loaded. suiting up the template ..."); r = suitup(rawtemplate, tree); r.tree = tree; console.log("done."); return r; }; /*`<div id="channels" class="antiscroll-wrap"> <div class="antiscroll-inner scrollHolder"> <div class="channel selected"> <div class="avatar" style="background-image: url(public/avatars/user2.jpg)"> <span class="channelpost counter">2</span> </div> <div class="info"> <span class="owner">vera<span class="domain">@buddycloud.com</span></span> <span class="status">What a wonderful day</span> </div> </div>` */ return HTMLCompiler; })(); require('colors'); util = require('util'); util.orginspect = util.inspect; util.inspect = require('eyes').inspector({ stream: null, hexy: { format: 'fours' } }); _ref = require('./dynamictemplate'), Template = _ref.Template, Tag = _ref.Tag; example = function() { var channelsdesign, design, rawtemplate, streamshtml, template, _ref2; design = new HTMLCompiler; console.log("* loading html ..."); streamshtml = design.open('/home/dodo/code/arbyt/buddycloud/webclient/brunch/build/streams.html'); console.log("* selecting part of the html ..."); channelsdesign = streamshtml.select('#channels', '.channel'); console.log("S", (_ref2 = streamshtml.select('.channel')) != null ? _ref2.length : void 0); rawtemplate = function(ee) { return new Template({ schema: 5 }, function() { return this.$div({ id: 'channels' }, function() { return this.$div(function() { var _this = this; return ee != null ? ee.on('new:channel', function(channel) { return _this.$div({ "class": 'channel' }, function() { this.$div({ "class": 'avatar', style: "background-image:url(" + channel.avatar + ")" }, function() { return this.$span({ "class": 'counter' }, channel.counter); }); return this.$div({ "class": 'info' }, function() { var _ref3; this.$span({ "class": 'owner' }, function() { var jid, _ref3; jid = ((_ref3 = channel.get('jid')) != null ? _ref3.split('@') : void 0) || []; this.text("" + jid[0]); return this.$span({ "class": 'domain' }, "" + jid[1]); }); return this.$span({ "class": 'status' }, ((_ref3 = channel.nodes.get('status')) != null ? _ref3.last() : void 0) || ""); }); }); }) : void 0; }); }); }); }; console.log("* start compiling ..."); return template = design.compile(rawtemplate, channelsdesign); }; example2 = function() { var design, rawtemplate, template; design = new HTMLCompiler; console.log("* using html ..."); design.use("<div id=\"main\">\n <div class=\"logo\" id=\"big\">some <a href=\"#\">linked</a> logo</div>\n <div class=\"tor list\" id=\"zwiebel\">\n <div class=\"entry\">some random entry</div>\n </div>\n <span>impressum</span>\n</div>\n<script>alert('evil');</script>"); rawtemplate = function() { return new Template({ schema: 5 }, function() { return this.$div({ id: 'main' }, function() { this.$div({ "class": 'list' }, function() { return this.$div({ "class": 'entry' }, "specific text"); }); return this.$footer("stuff"); }); }); }; console.log("* start compiling ..."); template = design.compile(rawtemplate); template.design = design; return template; }; module.exports = { example: example, example2: example2, HTMLCompiler: HTMLCompiler, copy_structure: copy_structure }; }).call(this);