updated app

This commit is contained in:
2012-05-30 23:00:06 -04:00
parent 6a753904b7
commit da6ad88d48
5545 changed files with 1101709 additions and 60 deletions

385
first-project/node_modules/derby/lib/Dom.js generated vendored Normal file
View File

@@ -0,0 +1,385 @@
var racer = require('racer')
, domShim = require('dom-shim')
, EventDispatcher = require('./EventDispatcher')
, escapeHtml = require('html-util').escapeHtml
, merge = racer.util.merge
, win = window
, doc = document
, markers = {}
, elements = {
$_win: win
, $_doc: doc
}
, addListener, removeListener;
module.exports = Dom;
function Dom(model) {
var dom = this
, fns = this.fns
// Map dom event name -> true
, listenerAdded = {}
, captureListenerAdded = {};
// DOM listener capturing allows blur and focus to be delegated
// http://www.quirksmode.org/blog/archives/2008/04/delegating_the.html
var events = this._events = new EventDispatcher({
onTrigger: onTrigger
, onBind: function(name, listener, eventName) {
if (!listenerAdded[eventName]) {
addListener(doc, eventName, trigger, true);
listenerAdded[eventName] = true;
}
}
});
var captureEvents = this._captureEvents = new EventDispatcher({
onTrigger: function(name, listener, e) {
var el = doc.getElementById(id)
, id = listener.id;
if (el.tagName === 'HTML' || el.contains(e.target)) {
onTrigger(name, listener, id, e, el);
}
}
, onBind: function(name, listener) {
if (!captureListenerAdded[name]) {
addListener(doc, name, captureTrigger, true);
captureListenerAdded[name] = true;
}
}
});
function onTrigger(name, listener, id, e, el, next) {
var delay = listener.delay
, finish = listener.fn;
if (!finish) {
// Update the model when the element's value changes
finish = function() {
var value = dom.getMethods[listener.method](el, listener.property)
, setValue = listener.setValue;
// Allow the listener to override the setting function
if (setValue) {
setValue(model, value);
return;
}
// Remove this listener if its path id is no longer registered
var path = model.__pathMap.paths[listener.pathId];
if (!path) return false;
// Set the value if changed
if (model.get(path) === value) return;
model.pass(e).set(path, value);
}
}
if (delay != null) {
setTimeout(finish, delay, e, el, next, dom);
} else {
finish(e, el, next, dom);
}
}
function trigger(e, el, noBubble, continued) {
if (!el) el = e.target;
var prefix = e.type + ':'
, id;
// Next can be called from a listener to continue bubbling
function next() {
trigger(e, el.parentNode, false, true);
}
next.firstTrigger = !continued;
if (noBubble && (id = el.id)) {
return events.trigger(prefix + id, id, e, el, next);
}
while (true) {
while (!(id = el.id)) {
if (!(el = el.parentNode)) return;
}
// Stop bubbling once the event is handled
if (events.trigger(prefix + id, id, e, el, next)) return;
if (!(el = el.parentNode)) return;
}
}
function captureTrigger(e) {
captureEvents.trigger(e.type, e);
}
this.trigger = trigger;
this.captureTrigger = captureTrigger;
this.addListener = addListener;
this.removeListener = removeListener;
this._componentListeners = [];
}
Dom.prototype = {
clear: function() {
this._events.clear();
this._captureEvents.clear();
var listeners = this._componentListeners
, i, listener;
for (i = listeners.length; i--;) {
listener = listeners[i];
removeListener(listener[0], listener[1], listener[2], listener[3]);
}
this._componentListeners = [];
markers = {};
}
, bind: function(eventName, id, listener) {
if (listener.capture) {
listener.id = id;
this._captureEvents.bind(eventName, listener);
} else {
this._events.bind("" + eventName + ":" + id, listener, eventName);
}
}
, update: function(el, method, ignore, value, property, index) {
// Don't do anything if the element is already up to date
if (value === this.getMethods[method](el, property)) return;
this.setMethods[method](el, ignore, value, property, index);
}
, item: function(id) {
return doc.getElementById(id) || elements[id] || getRange(id);
}
, componentDom: function() {
var componentListeners = this._componentListeners
, dom = Object.create(this);
dom.addListener = function(el, name, callback, captures) {
componentListeners.push(arguments);
addListener(el, name, callback, captures);
};
return dom;
}
, getMethods: {
attr: getAttr
, prop: getProp
, propPolite: getProp
, html: getHtml
// These methods return NaN, because it never equals anything else. Thus,
// when compared against the new value, the new value will always be set
, append: getNaN
, insert: getNaN
, remove: getNaN
, move: getNaN
}
, setMethods: {
attr: setAttr
, prop: setProp
, propPolite: setProp
, html: setHtml
, append: setAppend
, insert: setInsert
, remove: setRemove
, move: setMove
}
, fns: {
$forChildren: forChildren
, $forName: forName
}
}
function getAttr(el, attr) {
return el.getAttribute(attr);
}
function getProp(el, prop) {
return el[prop];
}
function getHtml(el) {
return el.innerHTML;
}
function getNaN() {
return NaN;
}
function setAttr(el, ignore, value, attr) {
if (ignore && el.id === ignore) return;
el.setAttribute(attr, value);
}
function setProp(el, ignore, value, prop) {
if (ignore && el.id === ignore) return;
el[prop] = value;
}
function propPolite(el, ignore, value, prop) {
if (ignore && el.id === ignore) return;
if (el !== doc.activeElement || !doc.hasFocus()) {
el[prop] = value;
}
}
function setHtml(obj, ignore, value, escape) {
if (escape) value = escapeHtml(value);
if (obj.nodeType) {
// Element
if (ignore && obj.id === ignore) return;
obj.innerHTML = value;
} else {
// Range
obj.deleteContents();
obj.insertNode(obj.createContextualFragment(value));
}
}
function setAppend(obj, ignore, value, escape) {
if (escape) value = escapeHtml(value);
if (obj.nodeType) {
// Element
obj.insertAdjacentHTML('beforeend', value);
} else {
// Range
var el = obj.endContainer
, ref = el.childNodes[obj.endOffset];
el.insertBefore(obj.createContextualFragment(value), ref);
}
}
function setInsert(obj, ignore, value, escape, index) {
if (escape) value = escapeHtml(value);
if (obj.nodeType) {
// Element
if (ref = obj.childNodes[index]) {
ref.insertAdjacentHTML('beforebegin', value);
} else {
obj.insertAdjacentHTML('beforeend', value);
}
} else {
// Range
var el = obj.startContainer
, ref = el.childNodes[obj.startOffset + index];
el.insertBefore(obj.createContextualFragment(value), ref);
}
}
function setRemove(el, ignore, index) {
if (!el.nodeType) {
// Range
index += el.startOffset;
el = el.startContainer;
}
var child = el.childNodes[index];
if (child) el.removeChild(child);
}
function setMove(el, ignore, from, to, howMany) {
var child, fragment, nextChild, offset, ref, toEl;
if (!el.nodeType) {
offset = el.startOffset;
from += offset;
to += offset;
el = el.startContainer;
}
child = el.childNodes[from];
// Don't move if the item at the destination is passed as the ignore
// option, since this indicates the intended item was already moved
// Also don't move if the child to move matches the ignore option
if (!child || ignore && (toEl = el.childNodes[to]) &&
toEl.id === ignore || child.id === ignore) return;
ref = el.childNodes[to > from ? to + howMany : to];
if (howMany > 1) {
fragment = document.createDocumentFragment();
while (howMany--) {
nextChild = child.nextSibling;
fragment.appendChild(child);
if (!(child = nextChild)) break;
}
el.insertBefore(fragment, ref);
return;
}
el.insertBefore(child, ref);
}
function forChildren(e, el, next, dom) {
// Prevent infinte emission
if (!next.firstTrigger) return;
// Re-trigger the event on all child elements
var children = el.childNodes;
for (var i = 0, len = children.length, child; i < len; i++) {
child = children[i];
if (child.nodeType !== 1) continue; // Node.ELEMENT_NODE
dom.trigger(e, child, true, true);
forChildren(e, child, next, dom);
}
}
function forName(e, el, next, dom) {
// Prevent infinte emission
if (!next.firstTrigger) return;
var name = el.getAttribute('name');
if (!name) return;
// Re-trigger the event on all other elements with
// the same 'name' attribute
var elements = doc.getElementsByName(name)
, len = elements.length;
if (!(len > 1)) return;
for (var i = 0, element; i < len; i++) {
element = elements[i];
if (element === el) continue;
dom.trigger(e, element, false, true);
}
}
function getRange(name) {
var start = markers[name]
, end = markers['$' + name]
, comment, commentIterator, range;
if (!(start && end)) {
// NodeFilter.SHOW_COMMENT == 128
commentIterator = doc.createTreeWalker(doc.body, 128, null, false);
while (comment = commentIterator.nextNode()) {
markers[comment.data] = comment;
}
start = markers[name];
end = markers['$' + name];
if (!(start && end)) return;
}
// Comment nodes may continue to exist even if they have been removed from
// the page. Thus, make sure they are still somewhere in the page body
if (!doc.body.contains(start)) {
delete markers[name];
delete markers['$' + name];
return;
}
range = doc.createRange();
range.setStartAfter(start);
range.setEndBefore(end);
return range;
}
if (doc.addEventListener) {
addListener = function(el, name, callback, captures) {
el.addEventListener(name, callback, captures || false);
};
removeListener = function(el, name, callback, captures) {
el.removeEventListener(name, callback, captures || false);
};
} else if (doc.attachEvent) {
addListener = function(el, name, callback) {
function listener() {
if (!event.target) event.target = event.srcElement;
callback(event);
}
callback.$derbyListener = listener;
el.attachEvent('on' + name, listener);
};
removeListener = function(el, name, callback) {
el.detachEvent('on' + name, callback.$derbyListener);
};
}

View File

@@ -0,0 +1,43 @@
function empty() {}
module.exports = EventDispatcher;
function EventDispatcher(options) {
if (options == null) options = {};
this._onTrigger = options.onTrigger || empty;
this._onBind = options.onBind || empty;
this.clear();
}
EventDispatcher.prototype = {
clear: function() {
this.names = {};
}
, bind: function(name, listener, arg0) {
this._onBind(name, listener, arg0);
var names = this.names
, obj = names[name] || {};
obj[JSON.stringify(listener)] = listener;
return names[name] = obj;
}
, trigger: function(name, value, arg0, arg1, arg2, arg3, arg4, arg5) {
var names = this.names
, listeners = names[name]
, onTrigger = this._onTrigger
, count = 0
, key, listener;
for (key in listeners) {
listener = listeners[key];
count++;
if (false !== onTrigger(name, listener, value, arg0, arg1, arg2, arg3, arg4, arg5)) {
continue;
}
delete listeners[key];
count--;
}
if (!count) delete names[name];
return count;
}
}

153
first-project/node_modules/derby/lib/PathMap.js generated vendored Normal file
View File

@@ -0,0 +1,153 @@
module.exports = PathMap
function PathMap() {
this.clear();
}
PathMap.prototype = {
clear: function() {
this.count = 0;
this.ids = {};
this.paths = {};
this.arrays = {};
}
, id: function(path) {
var id;
// Return the path for an id, or create a new id and index it
return this.ids[path] || (
id = ++this.count
, this.paths[id] = path
, this._indexArray(path, id)
, this.ids[path] = id
);
}
, _indexArray: function(path, id) {
var arr, index, match, nested, remainder, set, setArrays;
while (match = /^(.+)\.(\d+)(\*?(?:\..+|$))/.exec(path)) {
path = match[1];
index = +match[2];
remainder = match[3];
arr = this.arrays[path] || (this.arrays[path] = []);
set = arr[index] || (arr[index] = {});
if (nested) {
setArrays = set.arrays || (set.arrays = {});
setArrays[remainder] = true;
} else {
set[id] = remainder;
}
nested = true;
}
}
, _incrItems: function(path, map, start, end, byNum, oldArrays, oldPath) {
var arrayMap, arrayPath, arrayPathTo, i, id, ids, itemPath, remainder;
if (oldArrays == null) oldArrays = {};
for (i = start; i < end; i++) {
ids = map[i];
if (!ids) continue;
for (id in ids) {
remainder = ids[id];
if (id === 'arrays') {
for (remainder in ids[id]) {
arrayPath = (oldPath || path) + '.' + i + remainder;
arrayMap = oldArrays[arrayPath] || this.arrays[arrayPath];
if (arrayMap) {
arrayPathTo = path + '.' + (i + byNum) + remainder;
this.arrays[arrayPathTo] = arrayMap;
this._incrItems(arrayPathTo, arrayMap, 0, arrayMap.length, 0, oldArrays, arrayPath);
}
}
continue;
}
itemPath = path + '.' + (i + byNum) + remainder;
this.paths[id] = itemPath;
this.ids[itemPath] = +id;
}
}
}
, _delItems: function(path, map, start, end, len, oldArrays) {
var arrayLen, arrayMap, arrayPath, i, id, ids, itemPath, remainder;
if (oldArrays == null) oldArrays = {};
for (i = start; i < len; i++) {
ids = map[i];
if (!ids) continue;
for (id in ids) {
if (id === 'arrays') {
for (remainder in ids[id]) {
arrayPath = path + '.' + i + remainder;
if (arrayMap = this.arrays[arrayPath]) {
arrayLen = arrayMap.length;
this._delItems(arrayPath, arrayMap, 0, arrayLen, arrayLen, oldArrays);
oldArrays[arrayPath] = arrayMap;
delete this.arrays[arrayPath];
}
}
continue;
}
itemPath = this.paths[id];
delete this.ids[itemPath];
if (i > end) continue;
delete this.paths[id];
}
}
return oldArrays;
}
, onRemove: function(path, start, howMany) {
var map = this.arrays[path]
, end, len, oldArrays;
if (!map) return;
end = start + howMany;
len = map.length;
// Delete indicies for removed items
oldArrays = this._delItems(path, map, start, end + 1, len);
// Decrement indicies of later items
this._incrItems(path, map, end, len, -howMany, oldArrays);
map.splice(start, howMany);
}
, onInsert: function(path, start, howMany) {
var map = this.arrays[path]
, end, len, oldArrays;
if (!map) return;
end = start + howMany;
len = map.length;
// Delete indicies for items in inserted positions
oldArrays = this._delItems(path, map, start, end + 1, len);
// Increment indicies of later items
this._incrItems(path, map, start, len, howMany, oldArrays);
while (howMany--) {
map.splice(start, 0, {});
}
}
, onMove: function(path, from, to, howMany) {
var map = this.arrays[path]
, afterFrom, afterTo, items, oldArrays;
if (!map) return;
afterFrom = from + howMany;
afterTo = to + howMany;
// Adjust paths for items between from and to
if (from > to) {
oldArrays = this._delItems(path, map, to, afterFrom, afterFrom);
this._incrItems(path, map, to, from, howMany, oldArrays);
} else {
oldArrays = this._delItems(path, map, from, afterTo, afterTo);
this._incrItems(path, map, afterFrom, afterTo, -howMany, oldArrays);
}
// Adjust paths for the moved item(s)
this._incrItems(path, map, from, afterFrom, to - from, oldArrays);
// Fix the array index
items = map.splice(from, howMany);
map.splice.apply(map, [to, 0].concat(items));
}
}

1125
first-project/node_modules/derby/lib/View.js generated vendored Normal file

File diff suppressed because it is too large Load Diff

322
first-project/node_modules/derby/lib/View.server.js generated vendored Normal file
View File

@@ -0,0 +1,322 @@
var EventDispatcher = require('./EventDispatcher')
, racer = require('racer')
, Promise = racer.util.Promise
, isProduction = racer.util.isProduction
, merge = racer.util.merge
, finishAfter = racer.util.async.finishAfter
, Model = racer["protected"].Model
, uglify = require('racer/node_modules/uglify-js')
, files = require('./files')
, htmlUtil = require('html-util')
, escapeHtml = htmlUtil.escapeHtml
, trimLeading = htmlUtil.trimLeading
, refresh = require('./refresh.server')
, errorHtml = refresh.errorHtml
, cssError = refresh.cssError
, templateError = refresh.templateError
, View = module.exports = require('./View')
, emptyModel = new Model
, emptyRes = {
getHeader: empty
, setHeader: empty
, write: empty
, end: empty
}
, emptyPathMap = {
id: empty
}
, emptyEventDispatcher = {
bind: empty
}
emptyModel._commit = empty;
emptyModel.bundle = empty;
function empty() {}
function escapeInlineScript(s) {
return s.replace(/<\//g, '<\\/');
}
function loadTemplatesScript(requirePath, templates, instances, libraryData) {
return '(function() {\n' +
'var view = require("' + requirePath + '").view;\n' +
'view._makeAll(\n' +
JSON.stringify(templates, null, 2) + ', ' +
JSON.stringify(instances, null, 2) + ');\n' +
'view._makeComponents(\n' +
JSON.stringify(libraryData, null, 2) + ');\n' +
'})();';
}
View.prototype.isServer = true;
View.prototype.inline = function(fn) {
return this._inline += uglify("(" + fn + ")()") + ';';
};
View.prototype._load = function(isStatic, callback) {
var view = this
, appFilename, clientName, count, errors, finish, js, options
, promise, requirePath, root, libraries, fileInfo, loadTemplates;
if (isProduction) {
this._watch = false;
this._load = function(isStatic, callback) {
callback();
};
} else {
this._watch = true;
}
// Use a promise to avoid simultaneously loading multiple times
if (promise = this._loadPromise) {
return promise.on(callback);
}
promise = this._loadPromise = (new Promise).on(callback);
// Once loading is complete, make the files reload from disk the next time
promise.on(function() {
delete view._loadPromise;
});
errors = {};
if (isStatic) {
root = this._root;
clientName = this._clientName;
count = 2;
finish = function() {
if (--count) return;
promise.resolve();
};
} else {
appFilename = this._appFilename;
options = this._derbyOptions || {};
fileInfo = files.parseName(appFilename, options);
this._root = root = fileInfo.root;
this._requirePath = requirePath = fileInfo.require;
this._clientName = clientName = fileInfo.clientName;
if (!clientName) promise.resolve();
count = 3;
finish = function() {
if (--count) return;
// Templates are appended to the js bundle here so that it does
// not have to be regenerated if only the template files are modified
if (isProduction) loadTemplates = uglify(loadTemplates);
js += ';' + loadTemplates;
view._errors = errorHtml(errors) || '';
files.writeJs(root, js, options, function(err, jsFile, appHash) {
if (err) throw err;
view._jsFile = jsFile;
view._appHash = appHash;
promise.resolve();
});
};
if (this._js) {
js = this._js;
finish();
} else {
files.js(appFilename, function(err, value, inline) {
if (err) throw err;
js = value;
if (!isProduction) view._js = value;
if (inline) view.inline("function(){" + inline + "}");
finish();
});
}
}
this._loadCss(root, clientName, function(err, css) {
if (err) {
css = '<style id=$_css></style>';
errors['CSS'] = cssError(err);
} else {
css = css ? '<style id=$_css>' + css + '</style>' : '';
}
view._css = css;
finish();
});
libraries = this._libraries;
this._loadTemplates(root, clientName, function(err, templates, instances, libraryData) {
if (err) errors['Template'] = templateError(err);
loadTemplates = loadTemplatesScript(requirePath, templates, instances, libraryData);
view._makeAll(templates, instances);
view._makeComponents(libraryData);
finish();
});
};
View.prototype._loadCss = function(root, clientName, callback) {
files.css(root, clientName, isProduction, function(err, value) {
value = isProduction ? trimLeading(value) : '\n' + value;
callback(err, value);
});
};
View.prototype._loadTemplates = function(root, clientName, callback) {
var count = 1
, libraries = this._libraries
, libraryData = {}
, templates, instances, finish, libraryName, library
for (libraryName in libraries) count++;
finish = finishAfter(count, function(err) {
callback(err, templates, instances, libraryData);
});
files.templates(root, clientName, function(err, _templates, _instances) {
if (err) {
templates = {};
instances = {};
} else {
templates = _templates;
instances = _instances;
}
finish(err);
});
for (libraryName in libraries) {
library = libraries[libraryName];
files.library(library.root, function(err, components) {
if (err) return finish(err);
var libraryTemplates = {}
, libraryInstances = {}
, componentName, component;
for (componentName in components) {
component = components[componentName];
// TODO: Namespace component partials of each component
merge(libraryTemplates, component.templates);
merge(libraryInstances, component.instances);
}
libraryData[libraryName] = {
templates: libraryTemplates
, instances: libraryInstances
};
finish();
});
}
};
View.prototype.render = function(res) {
var view = this
, i, arg, ctx, isStatic, model, ns;
if (res == null) res = emptyRes;
for (i = 1; i <= 5; i++) {
arg = arguments[i];
if (arg instanceof Model) {
model = arg;
} else if (typeof arg === 'object') {
ctx = arg;
} else if (typeof arg === 'string') {
ns = arg;
} else if (typeof arg === 'number') {
res.statusCode = arg;
} else if (typeof arg === 'boolean') {
isStatic = arg;
}
}
if (model == null) model = emptyModel;
// Load templates, css, and scripts from files
this._load(isStatic, function() {
view._render(res, model, ns, ctx, isStatic);
});
};
View.prototype._init = function(model) {
// Initialize view & model for rendering
model.__events = emptyEventDispatcher;
model.__blockPaths = {};
model.__pathMap = emptyPathMap;
this.model = model;
this._idCount = 0;
var libraries = this._libraries
, name
for (name in libraries) {
libraries[name].view._init(model);
}
};
View.prototype._render = function(res, model, ns, ctx, isStatic) {
this._init(model);
if (!res.getHeader('content-type')) {
res.setHeader('Content-Type', 'text/html; charset=utf-8');
}
try {
// The view.get function renders and sets event listeners
var doctype = this.get('doctype', ns, ctx)
, root = this.get('root', ns, ctx)
, charset = this.get('charset', ns, ctx)
, title = escapeHtml(this.get('title$s', ns, ctx))
, head = this.get('head', ns, ctx)
, header = this.get('header', ns, ctx)
, view = this
, body, scripts, tail;
// The first chunk includes everything through header. Head should contain
// any meta tags and script tags, since it is included before CSS.
// If there is a small amount of header HTML that will display well by itself,
// it is a good idea to add this to the Header view so that it renders ASAP.
res.write(doctype + root + charset + "<title>" + title + "</title>" + head + this._css + header);
// Remaining HTML
body = this.get('body', ns, ctx) + this.get('footer', ns, ctx);
if (body.slice(0, 4) === '<!--') {
body = '&shy;' + body;
}
res.write(body);
} catch (err) {
var errText = templateError(err);
if (!this._errors) this._errors = errorHtml({Template: errText});
res.write('<!DOCTYPE html><meta charset=utf-8><title></title>' + this._css);
}
tail = this.get('tail', ns, ctx);
// Wait for transactions to finish and package up the racer model data
// TODO: There is a potential race condition with rendering based on the
// model before it is bundled. However, components may want to run init
// code that performs model mutations, so we can't bundle until after that.
// Figure out some solution to make sure that the client will have exactly
// the same model data when rendering to set up browser events, etc.
model.bundle(function(bundle) {
view._renderScripts(res, ns, ctx, isStatic, tail, bundle);
});
};
View.prototype._renderScripts = function(res, ns, ctx, isStatic, tail, bundle) {
var clientName = this._clientName;
// Inline scripts and external scripts
scripts = "<script>";
if (!isStatic) {
scripts += "function " + clientName + "(){" + clientName + "=1}";
}
scripts += escapeInlineScript(this._inline) + "</script>" + this.get('scripts', ns, ctx);
if (!isStatic) {
scripts += "<script defer async onload=" + clientName + "() src=" + this._jsFile + "></script>";
}
res.write(scripts);
// Initialization script and Tail
if (isStatic) return res.end(tail);
res.end("<script>(function(){function f(){setTimeout(function(){" + clientName +
"=require('" + this._requirePath + "')(" + escapeInlineScript(bundle) + ",'" +
this._appHash + "'," + (+this._watch) + ",'" + (ns || '') + "'" +
(ctx ? ',' + escapeInlineScript(JSON.stringify(ctx)) : '') + ")},0)}" +
clientName + "===1?f():" + clientName + "=f})()</script>" + tail + this._errors);
};

277
first-project/node_modules/derby/lib/derby.Model.js generated vendored Normal file
View File

@@ -0,0 +1,277 @@
var EventDispatcher = require('./EventDispatcher')
, PathMap = require('./PathMap')
, Model = require('racer')["protected"].Model
, arraySlice = [].slice;
exports.init = init;
// Add support for creating a model alias from a DOM node or jQuery object
Model.prototype.__at = Model.prototype.at;
Model.prototype.at = function(node, absolute) {
var isNode = node && (node.parentNode || node.jquery && (node = node[0]));
if (!isNode) return this.__at(node, absolute);
updateMarkers();
var blockPaths = this.__blockPaths
, pathMap = this.__pathMap
, child, i, id, isArray, last, path, pathId, children, len;
while (node) {
if (node.$derbyMarkerParent) {
node = last;
while (node = node.previousSibling) {
if (!(id = node.$derbyMarkerId)) continue;
pathId = blockPaths[id];
if (node.$derbyMarkerEnd || !pathId) break;
path = pathMap.paths[pathId];
if (pathMap.arrays[path] && last) {
i = 0;
while (node = node.nextSibling) {
if (node === last) {
path = path + '.' + i;
break;
}
i++;
}
}
return this.__at(path, absolute);
}
last = last.parentNode;
node = last.parentNode;
continue;
}
if ((id = node.id) && (pathId = blockPaths[id])) {
path = pathMap.paths[pathId];
isArray = pathMap.arrays[path] || Array.isArray(this.get(path));
if (isArray && last) {
children = node.childNodes;
for (i = 0, len = children.length; i < len; i++) {
child = children[i];
if (child === last) {
path = path + '.' + i;
break;
}
}
}
return this.__at(path, absolute);
}
last = node;
node = node.parentNode;
}
// Just return the model if a path can't be found
return this;
}
function updateMarkers() {
// NodeFilter.SHOW_COMMENT == 128
var commentIterator = document.createTreeWalker(document.body, 128, null, false)
, comment, id;
while (comment = commentIterator.nextNode()) {
if (comment.$derbyChecked) continue;
comment.$derbyChecked = true;
id = comment.data;
if (id.charAt(0) !== '$') continue;
if (id.charAt(1) === '$') {
comment.$derbyMarkerEnd = true;
id = id.slice(1);
}
comment.$derbyMarkerId = id;
comment.parentNode.$derbyMarkerParent = true;
}
}
function init(model, dom, view) {
var pathMap = model.__pathMap = new PathMap;
var events = model.__events = new EventDispatcher({
onTrigger: function(pathId, listener, type, local, options, value, index, arg) {
var id = listener[0]
, el = dom.item(id);
// Fail and remove the listener if the element can't be found
if (!el) return false;
var method = listener[1]
, property = listener[2]
, partial = listener.partial
, path = pathMap.paths[pathId]
, triggerId;
if (method === 'propPolite' && local) method = 'prop';
if (partial) {
triggerId = id;
if (method === 'html' && type) {
// Handle array updates
method = type;
if (type === 'append') {
path += '.' + (index = model.get(path).length - 1);
triggerId = null;
} else if (type === 'insert') {
path += '.' + index;
triggerId = null;
} else if (type === 'remove') {
partial = null;
} else if (type === 'move') {
partial = null;
property = arg;
}
}
}
if (listener.getValue) {
value = listener.getValue(model, path);
}
if (partial) {
value = partial(listener.ctx, model, path, triggerId, value, index, listener);
if (value == null) return;
}
dom.update(el, method, options && options.ignore, value, property, index);
}
});
// Derby's mutator listeners are added via unshift instead of model.on, because
// it needs to handle events in the same order that racer applies mutations.
// If there is a listener to an event that applies a mutation, event listeners
// later in the listeners queues could receive events in a different order
model.listeners('set').unshift(function(args, out, local, pass) {
var arrayPath, i, index, path, value;
model.emit('pre:set', args, out, local, pass);
path = args[0], value = args[1];
// For set operations on array items, also emit a remove and insert in case the
// array is bound
if (/\.\d+$/.test(path)) {
i = path.lastIndexOf('.');
arrayPath = path.slice(0, i);
index = path.slice(i + 1);
triggerEach(events, pathMap, arrayPath, 'remove', local, pass, index);
triggerEach(events, pathMap, arrayPath, 'insert', local, pass, value, index);
}
return triggerEach(events, pathMap, path, 'html', local, pass, value);
});
model.listeners('del').unshift(function(args, out, local, pass) {
model.emit('pre:del', args, out, local, pass);
var path = args[0];
return triggerEach(events, pathMap, path, 'html', local, pass);
});
model.listeners('push').unshift(function(args, out, local, pass) {
model.emit('pre:push', args, out, local, pass);
var path = args[0]
, values = arraySlice.call(args, 1);
for (var i = 0, len = values.length, value; i < len; i++) {
value = values[i];
triggerEach(events, pathMap, path, 'append', local, pass, value);
}
});
model.listeners('move').unshift(function(args, out, local, pass) {
model.emit('pre:move', args, out, local, pass);
var path = args[0]
, from = args[1]
, to = args[2]
, howMany = args[3]
, len = model.get(path).length;
from = refIndex(from);
to = refIndex(to);
if (from < 0) from += len;
if (to < 0) to += len;
if (from === to) return;
// Update indicies in pathMap
pathMap.onMove(path, from, to, howMany);
triggerEach(events, pathMap, path, 'move', local, pass, from, howMany, to);
});
model.listeners('unshift').unshift(function(args, out, local, pass) {
model.emit('pre:unshift', args, out, local, pass);
var path = args[0]
, values = arraySlice.call(args, 1);
insert(events, pathMap, path, 0, values, local, pass);
});
model.listeners('insert').unshift(function(args, out, local, pass) {
model.emit('pre:insert', args, out, local, pass);
var path = args[0]
, index = args[1]
, values = arraySlice.call(args, 2);
insert(events, pathMap, path, index, values, local, pass);
});
model.listeners('remove').unshift(function(args, out, local, pass) {
model.emit('pre:remove', args, out, local, pass);
var path = args[0]
, start = args[1]
, howMany = args[2];
remove(events, pathMap, path, start, howMany, local, pass);
});
model.listeners('pop').unshift(function(args, out, local, pass) {
model.emit('pre:pop', args, out, local, pass);
var path = args[0];
remove(events, pathMap, path, model.get(path).length, 1, local, pass);
});
model.listeners('shift').unshift(function(args, out, local, pass) {
model.emit('pre:shift', args, out, local, pass);
var path = args[0];
remove(events, pathMap, path, 0, 1, local, pass);
});
['connected', 'canConnect'].forEach(function(event) {
model.listeners(event).unshift(function(value) {
triggerEach(events, pathMap, event, null, true, null, value);
});
});
model.on('reInit', function() {
view.history.refresh();
});
return model;
}
function triggerEach(events, pathMap, path, arg0, arg1, arg2, arg3, arg4, arg5) {
var id = pathMap.ids[path]
, segments = path.split('.')
, i, pattern;
// Trigger an event on the path if it has a pathMap ID
if (id) events.trigger(id, arg0, arg1, arg2, arg3, arg4, arg5);
// Also trigger a pattern event for the path and each of its parent paths
// This is used by view helper functions to match updates on a path
// or any of its child segments
i = segments.length + 1;
while (--i) {
pattern = segments.slice(0, i).join('.') + '*';
if (id = pathMap.ids[pattern]) {
events.trigger(id, arg0, arg1, arg2, arg3, arg4, arg5);
}
}
}
// Get index if event was from refList id object
function refIndex(obj) {
return typeof obj === 'object' ? obj.index : +obj;
}
function insert(events, pathMap, path, start, values, local, pass) {
start = refIndex(start);
// Update indicies in pathMap
pathMap.onInsert(path, start, values.length);
for (var i = 0, len = values.length, value; i < len; i++) {
value = values[i];
triggerEach(events, pathMap, path, 'insert', local, pass, value, start + i);
}
}
function remove(events, pathMap, path, start, howMany, local, pass) {
start = refIndex(start);
var end = start + howMany;
// Update indicies in pathMap
pathMap.onRemove(path, start, howMany);
for (var i = start; i < end; i++) {
triggerEach(events, pathMap, path, 'remove', local, pass, start);
}
}

78
first-project/node_modules/derby/lib/derby.browser.js generated vendored Normal file
View File

@@ -0,0 +1,78 @@
var racer = require('racer')
, tracks = require('tracks')
, derbyModel = require('./derby.Model')
, Dom = require('./Dom')
, View = require('./View')
, autoRefresh = require('./refresh').autoRefresh;
module.exports = derbyBrowser;
function derbyBrowser(derby) {
derby.createApp = createApp;
}
derbyBrowser.decorate = 'derby';
derbyBrowser.useWith = {server: false, browser: true};
function createApp(appModule) {
var appExports = appModule.exports
, view, model;
appModule.exports = function(modelBundle, appHash, debug, ns, ctx) {
tracks.set('debug', debug);
// The init event is fired after the model data is initialized but
// before the socket object is set
racer.on('init', function(_model) {
model = view.model = _model;
var dom = view.dom = new Dom(model);
derbyModel.init(model, dom, view);
// Ignore errors thrown when rendering; these will also be thrown
// on the server, and throwing here causes the app not to connect
try {
// Render immediately upon initialization so that the page is in
// the same state it was when rendered on the server
view.render(model, ns, ctx, true);
} catch (err) {
console.error(err);
}
});
// The ready event is fired after the model data is initialized and
// the socket object is set
if (debug) {
racer.on('ready', function(model) {
autoRefresh(view, model, appHash);
});
}
racer.init(modelBundle);
return appExports;
};
// Expose methods on the application module. Note that view must added
// to both appModule.exports and appExports, since it is used before
// the initialization function to make templates
appModule.exports.view = appExports.view = view =
new View(this._libraries, appExports);
function createPage() {
return {
render: function(ns, ctx) {
view.render(model, ns, ctx);
}
};
}
function onRoute(callback, page, params, next, isTransitional) {
if (isTransitional) {
callback(model, params, next);
} else {
callback(page, model, params, next);
}
}
tracks.setup(appExports, createPage, onRoute);
view.history = appExports.history;
appExports.ready = function(fn) {
racer.on('ready', fn);
};
return appExports;
}

34
first-project/node_modules/derby/lib/derby.js generated vendored Normal file
View File

@@ -0,0 +1,34 @@
var path = require('path')
, racer = require('racer')
, View = require('./View')
, derby = module.exports = Object.create(racer)
, derbyPlugin = racer.util.isServer ?
__dirname + '/derby.server' : require('./derby.browser');
// Allow derby object to be targeted via plugin.decorate
racer._makePlugable('derby', derby);
// Shared methods for both server and browser
derby._libraries = {};
derby.createLibrary = createLibrary;
// Add appropriate server-side or browser-side methods
derby.use(derbyPlugin);
function createLibrary(filename, scripts, options) {
if (!options) options = {};
var root = path.dirname(filename)
, name = options.name || path.basename(root)
, view = new View;
// This is needed, since component names are all lowercased
for (scriptName in scripts) {
scripts[scriptName.toLowerCase()] = scripts[scriptName];
}
this._libraries[name] = {
root: root
, view: view
, scripts: scripts
};
}

166
first-project/node_modules/derby/lib/derby.server.js generated vendored Normal file
View File

@@ -0,0 +1,166 @@
var fs = require('fs')
, path = require('path')
, http = require('http')
, racer = require('racer')
, tracks = require('tracks')
, up = require('up')
, View = require('./View.server')
, autoRefresh = require('./refresh.server').autoRefresh
, util = racer.util
, merge = util.merge
, isProduction = util.isProduction
, proto;
module.exports = derbyServer;
function derbyServer(derby) {
merge(derby, proto);
Object.defineProperty(derby, 'version', {
get: function() {
return require('../package.json').version;
}
});
}
derbyServer.decorate = 'derby';
derbyServer.useWith = {server: true, browser: false};
proto = {
// TODO: Remove in lieu of get / set methods
options: {}
, run: function(file, port, options) {
var master, onMessage, server, upService;
// Resolve relative filenames
file = path.resolve(file);
if (port == null) port = isProduction ? 80 : 3000;
if (options == null) options = {numWorkers: 1};
try {
server = require(file);
} catch (e) {
console.error('Error requiring server module from `%s`', file);
throw e;
}
if (!(server instanceof http.Server)) {
throw new Error('`' + file + '` does not export a valid `http.Server`');
}
if (!isProduction) {
// TODO: This extends the internal API of Up. It would be better
// if Up supported workers being able to force a global reload
onMessage = up.Worker.prototype.onMessage;
up.Worker.prototype.onMessage = function(message) {
if (message.type === 'reload') {
return upService.reload();
}
onMessage.call(this, message);
};
}
master = http.createServer().listen(port);
upService = up(master, file, options);
process.on('SIGUSR2', function() {
console.log('SIGUSR2 signal detected - reloading');
upService.reload();
});
console.log('Starting cluster with %d workers in %s mode',
options.numWorkers, process.env.NODE_ENV);
console.log('`kill -s SIGUSR2 %s` to force cluster reload', process.pid);
console.log('Go to: http://localhost:%d/', port);
}
, createApp: function(appModule) {
var appExports = appModule.exports
, view = new View(this._libraries)
, options = this.options
, session, store;
view._derbyOptions = options;
view._appFilename = appModule.filename;
function setStore(_store) {
autoRefresh(_store, options, view);
if (session != null) session._setStore(_store);
return store = _store;
}
// Expose methods on the application module
function Page(model, res) {
this._model = model;
this._res = res;
}
Page.prototype.render = function(ns, ctx, status) {
view.render(this._res, this._model, ns, ctx, status);
};
function createPage(req, res) {
var model = req.model || store.createModel();
return new Page(model, res);
}
function onRoute(callback, page, params, next, isTransitional) {
if (isTransitional) {
callback(page._model, params, next);
} else {
callback(page, page._model, params, next);
}
}
tracks.setup(appExports, createPage, onRoute);
appExports._setStore = setStore;
appExports.view = view;
appExports.ready = function() {};
appExports.createStore = function(options) {
return setStore(racer.createStore(options));
};
appExports.session = function() {
return session = racer.session(store);
};
appExports.render = function(res, model, ns, ctx, status) {
return view.render(res, model, ns, ctx, status);
};
// Render immediately upon creating the app so that files
// will be cached for the first render
process.nextTick(function() {
view.render();
});
return appExports;
}
, createStatic: function(root) {
return new Static(root, this._libraries);
}
, createStore: function() {
var len = arguments.length
, last = arguments[len - 1]
, options, app, store;
// Last argument may be a createStore options object
if (!last.view) {
options = last;
len--;
}
store = racer.createStore(options);
for (var i = len; i--;) {
app = arguments[i];
app._setStore(store);
}
return store;
}
};
function Static(root, libraries) {
this.root = root;
this.libraries = libraries;
this.views = {};
}
Static.prototype.render = function(name, res, model, ns, ctx, status) {
var view = this.views[name];
if (!view) {
view = this.views[name] = new View(this.libraries);
view._root = this.root;
view._clientName = name;
}
view.render(res, model, ns, ctx, status, true);
};

109
first-project/node_modules/derby/lib/eventBinding.js generated vendored Normal file
View File

@@ -0,0 +1,109 @@
var util = require('racer').util
, lookup = require('racer/lib/path').lookup
, merge = util.merge
, viewPath = require('./viewPath')
, ctxPath = viewPath.ctxPath
, pathFnArgs = viewPath.pathFnArgs
, setBoundFn = viewPath.setBoundFn;
exports.splitEvents = splitEvents;
exports.containsEvent = containsEvent;
exports.addDomEvent = util.isServer ? empty : addDomEvent;
function splitEvents(eventNames) {
var pairs = eventNames.replace(/\s/g, '').split(',')
, eventList = []
, pair, segments, name, eventName, delay, fn;
for (var i = pairs.length; i--;) {
pair = pairs[i];
segments = pair.split(':');
name = segments[0].split('/');
eventName = name[0];
delay = name[1];
fn = segments[1] || '';
eventList.push([eventName, delay, fn]);
}
return eventList;
}
function containsEvent(eventNames, expected) {
var eventList = splitEvents(eventNames)
, eventName;
for (var i = eventList.length; i--;) {
eventName = eventList[i][0];
if (eventName === expected) return true;
}
return false;
}
function addDomEvent(events, attrs, eventNames, name, options) {
var eventList = splitEvents(eventNames)
, args;
if (name) {
if (~name.indexOf('(')) {
args = pathFnArgs(name);
if (!args.length) return;
events.push(function(ctx, modelEvents, dom, pathMap, view) {
var id = attrs._id || attrs.id
, paths = []
, arg, path, pathId, event, eventName, eventOptions, i, j;
options.setValue = function(model, value) {
return setBoundFn(view, ctx, model, name, value);
}
for (i = args.length; i--;) {
arg = args[i];
path = ctxPath(ctx, arg);
paths.push(path);
pathId = pathMap.id(path);
for (j = eventList.length; j--;) {
event = eventList[j];
eventName = event[0];
eventOptions = merge({pathId: pathId, delay: event[1]}, options);
dom.bind(eventName, id, eventOptions);
}
}
});
return;
}
events.push(function(ctx, modelEvents, dom, pathMap) {
var id = attrs._id || attrs.id
, pathId = pathMap.id(ctxPath(ctx, name))
, event, eventName, eventOptions, i;
for (i = eventList.length; i--;) {
event = eventList[i];
eventName = event[0];
eventOptions = merge({pathId: pathId, delay: event[1]}, options);
dom.bind(eventName, id, eventOptions);
}
});
return;
}
events.push(function(ctx, modelEvents, dom, pathMap, view) {
var id = attrs._id || attrs.id
, fnCtx = ctx.$fnCtx || view._appExports
, event, eventName, eventOptions, i, fnName;
for (i = eventList.length; i--;) {
event = eventList[i];
eventName = event[0];
eventOptions = fnListener(dom, fnCtx, event[1], event[2]);
merge(eventOptions, options);
dom.bind(eventName, id, eventOptions);
}
});
}
function fnListener(dom, fnCtx, delay, fnName) {
var listener = {
delay: delay
, fn: function() {
listener.fn = dom.fns[fnName] || fnCtx[fnName] || lookup(fnName, fnCtx);
listener.fn.apply(null, arguments);
}
};
return listener;
}
function empty() {}

460
first-project/node_modules/derby/lib/files.js generated vendored Normal file
View File

@@ -0,0 +1,460 @@
var pathUtil = require('path')
, dirname = pathUtil.dirname
, basename = pathUtil.basename
, join = pathUtil.join
, exists = pathUtil.exists
, relative = pathUtil.relative
, fs = require('fs')
, crypto = require('crypto')
, stylus = require('stylus')
, nib = require('nib')
, less = require('less')
, racer = require('racer')
, Promise = racer.util.Promise
, finishAfter = racer.util.async.finishAfter
, asyncForEach = racer.util.async.forEach
, htmlUtil = require('html-util')
, parseHtml = htmlUtil.parse
, minifyHtml = htmlUtil.minify
, styleCompilers = {
stylus: stylusCompiler
, less: lessCompiler
}
, onlyWhitespace = /^[\s\n]*$/;
exports.css = css;
exports.templates = templates;
exports.js = js;
exports.library = library;
exports.parseName = parseName;
exports.hashFile = hashFile;
exports.writeJs = writeJs;
exports.watch = watch;
function css(root, clientName, compress, callback) {
// TODO: Set default configuration options in a single place
var styles = require('./derby').settings.styles || ['less', 'stylus']
, compiled = []
, finish;
if (!Array.isArray(styles)) styles = [styles];
finish = finishAfter(styles.length, function(err) {
callback(err, compiled.join(''));
});
styles.forEach(function(style, i) {
var compiler = styleCompilers[style];
if (!compiler) finish(new Error('Unable to find compiler for: ' + style));
compiler(root, clientName, compress, function(err, value) {
compiled[i] = value || '';
finish(err);
});
});
}
function stylusCompiler(root, clientName, compress, callback) {
findPath(root + '/styles', clientName, '.styl', function(path) {
if (!path) return callback('');
fs.readFile(path, 'utf8', function(err, styl) {
if (err) return callback(err);
stylus(styl)
.use(nib())
.set('filename', path)
.set('compress', compress)
.render(callback);
});
});
}
function lessCompiler(root, clientName, compress, callback) {
findPath(root + '/styles', clientName, '.less', function(path) {
if (!path) return callback('');
fs.readFile(path, 'utf8', function(err, lessFile) {
if (err) return callback(err);
var parser = new less.Parser({
paths: [root + '/styles']
, filename: path
});
parser.parse(lessFile, function(err, tree) {
var compiled;
if (err) return callback(err);
try {
compiled = tree.toCSS({compress: compress});
} catch (err) {
return callback(err);
}
callback(null, compiled);
});
});
});
}
function templates(root, clientName, callback) {
loadTemplates(root + '/views', clientName, callback);
}
function js(parentFilename, options, callback) {
var finish, inline, inlineFile, js;
// Needed for tests
if (!parentFilename) return;
if (typeof options === 'function') {
callback = options;
options = {};
}
// TODO: Move this to config:
// Express will try to include mime, which won't work in the browser
// It doesn't actually need this for routing, so we just ignore it
if (options.ignore) {
options.ignore.push('mime');
} else {
options.ignore = ['mime'];
}
if (options.require) {
options.require.push(parentFilename);
} else {
options.require = [parentFilename];
}
inlineFile = join(dirname(parentFilename), 'inline.js');
finish = finishAfter(2, function(err) {
callback(err, js, inline);
});
racer.js(options, function(err, value) {
js = value;
finish(err);
});
fs.readFile(inlineFile, 'utf8', function(err, value) {
inline = value;
// Ignore file not found error
if (err && err.code === 'ENOENT') err = null;
finish(err);
});
}
function library(root, callback) {
var components = {};
fs.readdir(root, function(err, files) {
if (err) return callback(err);
asyncForEach(files, libraryFile, function(err) {
if (err) return callback(err);
callback(null, components);
});
});
function libraryFile(file, callback) {
var path = root + '/' + file
fs.stat(path, function(err, stats) {
if (err) return callback(err);
if (stats.isDirectory()) {
return addComponent(root, file, callback);
}
if (extensions['html'].test(file)) {
file = file.replace(extensions['html'], '');
return addComponent(root, file, callback);
}
callback();
});
}
function addComponent(root, name, callback) {
loadTemplates(root, name, function(err, templates, instances) {
components[name] = {
templates: templates
, instances: instances
};
callback(err);
});
}
}
function parseName(parentFilename, options) {
var parentDir = dirname(parentFilename)
, root = parentDir
, base = basename(parentFilename, '.js');
if (base === 'index') {
base = basename(parentDir);
root = dirname(dirname(parentDir));
} else if (basename(parentDir) === 'lib') {
root = dirname(parentDir);
}
return {
root: root
, clientName: options.name || base
, require: './' + basename(parentFilename)
};
}
function hashFile(file) {
var hash = crypto.createHash('md5').update(file).digest('base64');
// Base64 uses characters reserved in URLs and adds extra padding charcters.
// Replace "/" and "+" with the unreserved "-" and "_" and remove "=" padding
return hash.replace(/[\/\+=]/g, function(match) {
switch (match) {
case '/': return '-';
case '+': return '_';
case '=': return '';
}
});
}
function writeJs(root, js, options, callback) {
var staticRoot = options.staticRoot || join(root, 'public')
, staticDir = options.staticDir || 'gen'
, staticPath = join(staticRoot, staticDir)
, hash = hashFile(js)
, filename = hash + '.js'
, jsFile = join('/', staticDir, filename)
, filePath = join(staticPath, filename);
function finish() {
fs.writeFile(filePath, js, function(err) {
callback(err, jsFile, hash);
});
}
exists(staticPath, function(value) {
if (value) return finish();
exists(staticRoot, function(value) {
if (value) {
fs.mkdir(staticPath, '0777', function(err) {
finish();
})
return;
}
fs.mkdir(staticRoot, '0777', function(err) {
fs.mkdir(staticPath, '0777', function(err) {
finish();
});
});
});
});
}
function watch(dir, type, onChange) {
var extension = extensions[type]
, watchFn = fs.watch ? systemWatch : pollWatch;
files(dir, extension).forEach(watchFn);
function systemWatch(file) {
fs.watch(file, function() {
onChange(file);
});
}
function pollWatch(file) {
fs.watchFile(file, {interval: 100}, function(curr, prev) {
if (prev.mtime < curr.mtime) {
onChange(file);
}
});
}
}
function findPath(root, name, extension, callback) {
if (name.charAt(0) !== '/') {
name = join(root, name);
}
var path = name + extension;
exists(path, function(value) {
if (value) return callback(path);
path = join(name, 'index' + extension);
exists(path, function(value) {
callback(value ? path : null);
});
});
}
function loadTemplates(root, fileName, callback) {
var count = 0
, calls = {incr: incr, finish: finish};
function incr() {
count++;
}
function finish(err, templates, instances) {
if (err) {
calls.finish = function() {};
return callback(err);
}
--count || callback(null, templates, instances);
}
forTemplate(root, fileName, 'import', calls);
}
function forTemplate(root, fileName, get, calls, files, templates, instances, alias, currentNs) {
if (currentNs == null) currentNs = '';
calls.incr();
findPath(root, fileName, '.html', function(path) {
var getCount, got, matchesGet, promise;
if (path === null) {
if (!files) {
// Return without doing anything if the path isn't found, and this is the
// initial automatic lookup based on the clientName
return calls.finish(null, {}, {});
} else {
return calls.finish(new Error("Can't find file " + fileName));
}
}
files || (files = {});
templates || (templates = {});
instances || (instances = {});
got = false;
if (get === 'import') {
matchesGet = function() {
return got = true;
}
} else if (Array.isArray(get)) {
getCount = get.length;
matchesGet = function(name) {
--getCount || (got = true);
return ~get.indexOf(name);
}
} else {
matchesGet = function(name) {
got = true;
return get === name;
}
}
promise = files[path];
if (!promise) {
promise = files[path] = new Promise;
fs.readFile(path, 'utf8', function(err, file) {
promise.resolve(err, file);
});
}
promise.on(function(err, file) {
if (err) calls.finish(err);
parseTemplateFile(root, dirname(path), path, calls, files, templates, instances, alias, currentNs, matchesGet, file);
if (!got) {
calls.finish(new Error("Can't find template '" + get + "' in " + path));
}
calls.finish(null, templates, instances);
});
});
}
function parseTemplateFile(root, dir, path, calls, files, templates, instances, alias, currentNs, matchesGet, file) {
var relativePath = relative(root, path)
, as, importTemplates, name, ns, src, templateOptions;
parseHtml(file, {
// Force template tags to be treated as raw tags,
// meaning their contents are not parsed as HTML
rawTags: /^(?:[^\s=\/>]+:|style|script)$/i
, matchEnd: matchEnd
, start: start
, text: text
});
function matchEnd(tagName) {
if (tagName.slice(-1) === ':') {
return /<\/?[^\s=\/>]+:[\s>]/;
}
return new RegExp('</' + tagName, 'i');
}
function start(tag, tagName, attrs) {
var i = tagName.length - 1
, srcNs, template;
as, importTemplates, ns, src = null;
name = (tagName.charAt(i) === ':' ? tagName.slice(0, i) : '').toLowerCase();
if (name === 'import') {
src = attrs.src, ns = attrs.ns, as = attrs.as, template = attrs.template;
if (!src) {
calls.finish(new Error("Template import in " + path +
" must have a 'src' attribute"));
}
if (template) {
importTemplates = template.toLowerCase().split(' ');
if (importTemplates.length > 1 && (as != null)) {
calls.finish(new Error("Template import of '" + src + "' in " +
path + " can't specify multiple 'template' values with 'as'"));
}
}
if ('ns' in attrs) {
if (as) calls.finish(new Error("Template import of '" + src +
"' in " + path + " can't specifiy both 'ns' and 'as' attributes"));
// Import into the namespace specified via 'ns' underneath
// the current namespace
ns = ns
? currentNs ? currentNs + ':' + ns : ns
: currentNs;
} else if (as) {
// If 'as' is specified, import into the current namespace
ns = currentNs;
} else {
// If no namespace is specified, use the src as a namespace.
// Remove leading '.' and '/' characters
srcNs = src.replace(/^[.\/]*/, '');
ns = currentNs ? currentNs + ':' + srcNs : srcNs;
}
ns = ns.toLowerCase();
} else {
templateOptions = attrs;
}
}
function text(text, isRawText) {
var instanceName, templateName, toGet;
if (!matchesGet(name)) return;
if (src) {
if (!onlyWhitespace.test(text)) {
calls.finish(new Error("Template import of '" + src + "' in " +
path + " can't contain content: " + text));
}
toGet = importTemplates || 'import';
return forTemplate(root, join(dir, src), toGet, calls, files, templates, instances, as, ns);
}
templateName = relativePath + ':' + name;
instanceName = alias || name;
if (currentNs) {
instanceName = currentNs + ':' + instanceName;
}
instances[instanceName] = [templateName, templateOptions];
if (templates[templateName]) return;
if (!(name && isRawText)) {
if (onlyWhitespace.test(text)) return;
calls.finish(new Error("Can't read template in " + path +
" near the text: " + text));
}
templates[templateName] = minifyHtml(text);
}
}
// TODO: These should be set as configuration options
var extensions = {
html: /\.html$/i
, css: /\.styl$|\.css|\.less$/i
, js: /\.js$/i
};
var ignoreDirectories = ['node_modules', '.git', 'gen'];
function ignored(path) {
return ignoreDirectories.indexOf(path) === -1;
}
function files(dir, extension, out) {
if (out == null) out = [];
fs.readdirSync(dir).filter(ignored).forEach(function(p) {
p = join(dir, p);
if (fs.statSync(p).isDirectory()) {
files(p, extension, out);
} else if (extension.test(p)) {
out.push(p);
}
});
return out;
}

173
first-project/node_modules/derby/lib/markup.js generated vendored Normal file
View File

@@ -0,0 +1,173 @@
var eventBinding = require('./eventBinding')
, splitEvents = eventBinding.splitEvents
, containsEvent = eventBinding.containsEvent
, addDomEvent = eventBinding.addDomEvent
, TEXT_EVENTS = 'keyup,keydown,paste/0,dragover/0,blur'
, AUTOCOMPLETE_OFF = {
checkbox: true
, radio: true
}
, onBindA, onBindForm;
module.exports = {
bound: {
'value': {
'input': function(events, attrs, name) {
var type = attrs.type
, eventNames, method;
if (type === 'radio' || type === 'checkbox') return;
if (type === 'range' || 'x-blur' in attrs) {
// Only update after the element loses focus
delete attrs['x-blur'];
eventNames = 'change,blur';
} else {
// By default, update as the user types
eventNames = TEXT_EVENTS;
}
if ('x-ignore-focus' in attrs) {
// Update value regardless of focus
delete attrs['x-ignore-focus'];
method = 'prop';
} else {
// Update value unless window and element are focused
method = 'propPolite';
}
addDomEvent(events, attrs, eventNames, name, {
method: 'prop'
, property: 'value'
});
return {method: method};
}
}
, 'checked': {
'*': function(events,  attrs, name) {
addDomEvent(events, attrs, 'change', name, {
method: 'prop'
, property: 'checked'
});
return {method: 'prop'};
}
}
, 'selected': {
'*': function(events, attrs, name) {
addDomEvent(events, attrs, 'change', name, {
method: 'prop'
, property: 'selected'
});
return {method: 'prop'};
}
}
, 'disabled': {
'*': function() {
return {method: 'prop'};
}
}
}
, boundParent: {
'contenteditable': {
'*': function(events, attrs, name) {
addDomEvent(events, attrs, TEXT_EVENTS, name, {
method: 'html'
});
}
}
, '*': {
'textarea': function(events, attrs, name) {
addDomEvent(events, attrs, TEXT_EVENTS, name, {
method: 'prop'
, property: 'value'
});
return {method: 'prop', property: 'value'};
}
}
}
, element: {
'select': function(events, attrs) {
// Distribute change event to child nodes of select elements
addDomEvent(events, attrs, 'change:$forChildren');
return {addId: true};
}
, 'input': function(events, attrs) {
if (AUTOCOMPLETE_OFF[attrs.type] && !('autocomplete' in attrs)) {
attrs.autocomplete = 'off';
}
if (attrs.type === 'radio') {
// Distribute change events to other elements with the same name
addDomEvent(events, attrs, 'change:$forName');
}
}
}
, attr: {
'x-bind': {
'*': function(events, attrs, eventNames) {
addDomEvent(events, attrs, eventNames);
return {addId: true, del: true};
}
, 'a': onBindA = function(events, attrs, eventNames) {
if (containsEvent(eventNames, 'click') && !('href' in attrs)) {
attrs.href = '#';
if (!('onclick' in attrs)) {
attrs.onclick = 'return false';
}
}
}
, 'form': onBindForm = function(events, attrs, eventNames) {
if (containsEvent(eventNames, 'submit')) {
if (!('onsubmit' in attrs)) {
attrs.onsubmit = 'return false';
}
}
}
}
, 'x-capture': {
'*': function(events, attrs, eventNames) {
addDomEvent(events, attrs, eventNames, null, {capture: true});
return {addId: true, del: true};
}
, 'a': onBindA
, 'form': onBindForm
}
, 'x-as': {
'*': function(events, attrs, name) {
events.push(function(ctx) {
var elements = ctx.$elements || (ctx.$elements = {});
elements[name] = attrs._id || attrs.id;
});
return {addId: true, del: true}
}
}
, 'checked': {
'*': function() {
return {bool: true};
}
}
, 'selected': {
'*': function() {
return {bool: true};
}
}
, 'disabled': {
'*': function() {
return {bool: true};
}
}
}
, TEXT_EVENTS: TEXT_EVENTS
, AUTOCOMPLETE_OFF: AUTOCOMPLETE_OFF
};

70
first-project/node_modules/derby/lib/refresh.js generated vendored Normal file
View File

@@ -0,0 +1,70 @@
exports.errorHtml = errorHtml;
exports.autoRefresh = autoRefresh;
var errors = {};
function errorHtml(errors) {
var text = ''
, type, err;
for (type in errors) {
err = errors[type];
text += '<h3>' + type + ' Error</h3><pre>' + err + '</pre>';
}
if (!text) return;
return '<div id=$_derbyError style="position:absolute;background:rgba(0,0,0,.7);top:0;left:0;right:0;bottom:0;text-align:center">' +
'<div style="background:#fff;padding:20px 40px;margin:60px;display:inline-block;text-align:left">' +
text + '</div></div>';
}
function autoRefresh(view, model, appHash) {
var socket = model.socket;
model.on('connectionStatus', function(connected, canConnect) {
if (!canConnect) window.location.reload(true);
});
socket.on('connect', function() {
socket.emit('derbyClient', appHash, function(reload) {
if (reload) window.location.reload(true);
});
});
socket.on('refreshCss', function(err, css) {
var el = document.getElementById('$_css');
if (el) el.innerHTML = css;
updateError('CSS', err);
});
socket.on('refreshHtml', function(err, templates, instances, libraryData) {
view._makeAll(templates, instances);
view._makeComponents(libraryData);
try {
view.history.refresh();
} catch (_err) {
err || (err = _err.stack);
}
updateError('Template', err);
});
}
function updateError(type, err) {
if (err) {
errors[type] = err;
} else {
delete errors[type];
}
var el = document.getElementById('$_derbyError')
, html = errorHtml(errors)
, fragment, range;
if (html) {
if (el) {
el.outerHTML = html;
} else {
range = document.createRange();
range.selectNode(document.body);
fragment = range.createContextualFragment(html);
document.body.appendChild(fragment);
}
} else {
if (el) el.parentNode.removeChild(el);
}
}

75
first-project/node_modules/derby/lib/refresh.server.js generated vendored Normal file
View File

@@ -0,0 +1,75 @@
var isProduction = require('racer').util.isProduction
, files = require('./files')
, refresh = module.exports = require('./refresh');
refresh.cssError = cssError;
refresh.templateError = templateError;
refresh.autoRefresh = autoRefresh;
function cssError(err) {
if (err.stack) {
console.error('\nCSS PARSE ERROR\n' + err.stack);
return err.stack;
} else {
console.error('\nCSS PARSE ERROR\n' + err.message + '\n' + err.filename);
return err.message + '\n' + err.filename;
}
}
function templateError(err) {
console.error('\nTEMPLATE ERROR\n' + err.stack);
return err.stack;
}
function autoRefresh(store, options, view) {
if (isProduction || store._derbySocketsSetup) return;
store._derbySocketsSetup = true;
var listeners = {};
store.sockets.on('connection', function(socket) {
socket.on('derbyClient', function(appHash, callback) {
var appFilename, reload, sockets;
reload = appHash !== view._appHash;
callback(reload);
if (reload) return;
appFilename = view._appFilename;
if (listeners[appFilename]) {
return listeners[appFilename].push(socket);
}
sockets = listeners[appFilename] = [socket];
addWatches(appFilename, options, sockets, view);
});
});
}
function addWatches(appFilename, options, sockets, view) {
var parsed = files.parseName(appFilename, options)
, root = parsed.root
, clientName = parsed.clientName;
files.watch(root, 'css', function() {
view._loadCss(root, clientName, function(err, css) {
var errText;
if (err) errText = cssError(err);
for (var i = sockets.length; i--;) {
sockets[i].emit('refreshCss', errText, css);
}
});
});
files.watch(root, 'html', function() {
view._loadTemplates(root, clientName, function(err, templates, instances, libraryData) {
var errText;
if (err) errText = templateError(err);
for (var i = sockets.length; i--;) {
sockets[i].emit('refreshHtml', errText, templates, instances, libraryData);
}
});
});
files.watch(root, 'js', function() {
process.send({type: 'reload'});
});
}

269
first-project/node_modules/derby/lib/viewPath.js generated vendored Normal file
View File

@@ -0,0 +1,269 @@
var lookup = require('racer/lib/path').lookup
, trimLeading = require('html-util').trimLeading;
exports.wrapRemainder = wrapRemainder;
exports.extractPlaceholder = extractPlaceholder;
exports.pathFnArgs = pathFnArgs;
exports.ctxPath = ctxPath;
exports.dataValue = dataValue;
exports.setBoundFn = setBoundFn;
function wrapRemainder(tagName, remainder) {
if (!remainder) return false;
return !(new RegExp('^<\/' + tagName, 'i')).test(remainder);
}
var openPlaceholder = /^([\s\S]*?)(\{{1,3})([\s\S]*)/
, placeholderContent = /^\s*([\#\/]?)(?:(else\sif|if|else|unless|each|with|unescaped)(?!\())?\s*([^\s(>]*(?:\s*\([\s\S]*\))?)(?:\s+as\s+:([^\s>]+))?/;
function extractPlaceholder(text) {
var match = openPlaceholder.exec(text);
if (!match) return;
var pre = match[1]
, open = match[2]
, remainder = match[3]
, openLen = open.length
, bound = openLen === 1
, macro = openLen === 3
, end = matchBraces(remainder, openLen, 0, '{', '}')
, endInner = end - openLen
, inner = remainder.slice(0, endInner)
, post = remainder.slice(end)
, content = placeholderContent.exec(inner)
, escaped, name, type;
if (!content) return;
type = content[2];
escaped = true;
if (type === 'unescaped') {
escaped = false;
type = '';
}
name = content[3];
if (bound) name = name.replace(/\bthis\b/, '.');
if (macro && name === 'content') escaped = false;
return {
pre: trimLeading(pre)
, post: trimLeading(post)
, bound: bound
, macro: macro
, hash: content[1]
, escaped: escaped
, type: type
, name: name
, alias: content[4]
};
}
function matchBraces(text, num, i, openChar, closeChar) {
var close, hasClose, hasOpen, open;
i++;
while (num) {
close = text.indexOf(closeChar, i);
open = text.indexOf(openChar, i);
hasClose = ~close;
hasOpen = ~open;
if (hasClose && (!hasOpen || (close < open))) {
i = close + 1;
num--;
continue;
} else if (hasOpen) {
i = open + 1;
num++;
continue;
} else {
return;
}
}
return i;
}
var fnCall = /^([^(]+)\s*\(\s*([\s\S]*?)\s*\)\s*$/
, argSeparator = /\s*([,(])\s*/g
, notSeparator = /[^,\s]/g
, notPathArg = /(?:^['"\d\-[{])|(?:^null$)|(?:^true$)|(?:^false$)/;
function fnArgs(inner) {
var args = []
, lastIndex = 0
, match, end, last;
while (match = argSeparator.exec(inner)) {
if (match[1] === '(') {
end = matchBraces(inner, 1, argSeparator.lastIndex, '(', ')');
args.push(inner.slice(lastIndex, end));
notSeparator.lastIndex = end;
lastIndex = argSeparator.lastIndex =
notSeparator.test(inner) ? notSeparator.lastIndex - 1 : end;
continue;
}
args.push(inner.slice(lastIndex, match.index));
lastIndex = argSeparator.lastIndex;
}
last = inner.slice(lastIndex);
if (last) args.push(last);
return args;
}
function fnCallError(name) {
throw new Error('malformed view function call: ' + name);
}
function fnArgValue(view, ctx, model, name, macro, arg) {
if (arg === 'null') return null;
if (arg === 'true') return true;
if (arg === 'false') return false;
var firstChar = arg.charAt(0)
, match;
if (firstChar === "'") {
match = /^'(.*)'$/.exec(arg) || fnCallError(name);
return match[1];
}
if (firstChar === '"') {
match = /^"(.*)"$/.exec(arg) || fnCallError(name);
return match[1];
}
if (/^[\d\-]/.test(firstChar) && !isNaN(arg)) {
return +arg;
}
if (firstChar === '[' || firstChar === '{') {
throw new Error('object literals not supported in view function call: ' + name);
}
return dataValue(view, ctx, model, arg, macro);
}
function fnValue(view, ctx, model, name, macro) {
var match = fnCall.exec(name) || fnCallError(name)
, fnName = match[1]
, args = fnArgs(match[2])
, fn, fnName, i;
for (i = args.length; i--;) {
args[i] = fnArgValue(view, ctx, model, name, macro, args[i]);
}
if (!(fn = view.getFns[fnName])) {
throw new Error('view function "' + fnName + '" not found for call: ' + name);
}
return fn.apply(null, args);
}
function pathFnArgs(name, paths) {
var match = fnCall.exec(name) || fnCallError(name)
, args = fnArgs(match[2])
, i, arg;
if (paths == null) paths = [];
for (i = args.length; i--;) {
arg = args[i];
if (notPathArg.test(arg)) continue;
if (~arg.indexOf('(')) {
pathFnArgs(arg, paths);
continue;
}
paths.push(arg);
}
return paths;
}
function macroName(ctx, name, noReplace) {
var macroCtx = ctx.$macroCtx
, path = ctxPath(macroCtx, name, false, noReplace)
, segments = path.split('.')
, base = segments[0].toLowerCase()
, remainder = segments[1]
, value = lookup(base, macroCtx)
, macroVar = value && value.$macroVar;
if (!macroVar) return remainder ? base + '.' + remainder : base;
return remainder ?
(/\.+/.test(macroVar) ? macroVar.slice(1) : macroVar) + '.' + remainder :
macroVar;
}
function ctxPath(ctx, name, macro, noReplace) {
if (macro) name = macroName(ctx, name, noReplace);
var firstChar = name.charAt(0)
, i, aliasName, firstChar, indices;
if (firstChar === ':') {
if (~(i = name.indexOf('.'))) {
aliasName = name.slice(1, i);
name = name.slice(i);
} else {
aliasName = name.slice(1);
name = '';
}
i = ctx.$depth - ctx.$aliases[aliasName];
if (i !== i) throw new Error("Can't find alias for " + aliasName);
} else if (firstChar === '.') {
i = 0;
while (name.charAt(i) === '.') {
i++;
}
name = i === name.length ? '' : name.slice(i - 1);
}
if (i && (name = ctx.$paths[i - 1] + name) && !noReplace) {
indices = ctx.$indices;
i = indices.length;
name = name.replace(/\$#/g, function() {
return indices[--i];
});
}
return name.replace(/\[([^\]]+)\]/g, function(match, name) {
return lookup(name, ctx);
});
}
function dataValue(view, ctx, model, name, macro) {
var path, value;
if (~name.indexOf('(')) {
return fnValue(view, ctx, model, name, macro);
}
if (macro) {
// Get macro content sections
value = lookup(name.toLowerCase(), ctx.$macroCtx);
if (value && !value.$macroVar) {
return typeof value === 'function' ? value(ctx, model) : value;
}
}
path = ctxPath(ctx, name, macro);
value = lookup(path, ctx);
if (value !== void 0) return value;
value = model.get(path);
return value !== void 0 ? value : model[path];
}
function setBoundFn(view, ctx, model, name, value) {
var match = fnCall.exec(name) || fnCallError(name)
, fnName = match[1]
, args = fnArgs(match[2])
, get = view.getFns[fnName]
, set = view.setFns[fnName]
, macro = false
, numInputs = set.length - 1
, arg, i, inputs, out, path, len;
if (!(get && set)) {
throw new Error('view function "' + fnName + '" not found for binding to: ' + name);
}
if (numInputs) {
inputs = [value];
i = 0;
while (i < numInputs) {
inputs.push(fnArgValue(view, ctx, model, name, macro, args[i++]));
}
out = set.apply(null, inputs);
} else {
out = set(value);
}
if (!out) return;
for (i = 0, len = out.length; i < len; i++) {
value = out[i];
arg = args[i + numInputs];
if (~arg.indexOf('(')) {
setBoundFn(view, ctx, model, arg, value);
continue;
}
if (value === void 0 || notPathArg.test(arg)) continue;
path = ctxPath(ctx, arg);
if (model.get(path) === value) continue;
model.set(path, value);
}
}