From 20e3152dbad56ad3f83abaa66935c1bf3abedbb2 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Tue, 17 Jun 2014 00:31:02 +0200 Subject: [PATCH 01/15] Bump log.js --- assets/scripts/vendor/log.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/assets/scripts/vendor/log.js b/assets/scripts/vendor/log.js index 42c785db..45d41ee2 100644 --- a/assets/scripts/vendor/log.js +++ b/assets/scripts/vendor/log.js @@ -1,2 +1 @@ -minispade.register('log', "(function() {(function() {\n\n this.Log = function() {\n this.listeners = [];\n this.renderer = new Log.Renderer;\n this.children = new Log.Nodes(this);\n this.parts = {};\n this.folds = new Log.Folds;\n return this;\n };\n\n Log.extend = function(one, other) {\n var name;\n for (name in other) {\n one[name] = other[name];\n }\n return one;\n };\n\n Log.extend(Log, {\n DEBUG: true,\n SLICE: 500,\n TIMEOUT: 25,\n FOLD: /fold:(start|end):([\\w_\\-\\.]+)/,\n create: function(options) {\n var listener, log, _i, _len, _ref;\n options || (options = {});\n log = new Log();\n if (options.limit) {\n log.listeners.push(log.limit = new Log.Limit(options.limit));\n }\n _ref = options.listeners || [];\n for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n listener = _ref[_i];\n log.listeners.push(listener);\n }\n return log;\n }\n });\nminispade.require('log/nodes');\n\n Log.prototype = Log.extend(new Log.Node, {\n set: function(num, string) {\n if (this.parts[num]) {\n return console.log(\"part \" + num + \" exists\");\n } else {\n this.parts[num] = true;\n return Log.Part.create(this, num, string);\n }\n },\n insert: function(data, pos) {\n this.trigger('insert', data, pos);\n return this.renderer.insert(data, pos);\n },\n remove: function(node) {\n this.trigger('remove', node);\n return this.renderer.remove(node);\n },\n hide: function(node) {\n this.trigger('hide', node);\n return this.renderer.hide(node);\n },\n trigger: function() {\n var args, ix, listener, _i, _len, _ref, _results;\n args = [this].concat(Array.prototype.slice.apply(arguments));\n _ref = this.listeners;\n _results = [];\n for (ix = _i = 0, _len = _ref.length; _i < _len; ix = ++_i) {\n listener = _ref[ix];\n _results.push(listener.notify.apply(listener, args));\n }\n return _results;\n }\n });\n\n Log.Listener = function() {};\n\n Log.extend(Log.Listener.prototype, {\n notify: function(log, event) {\n if (this[event]) {\n return this[event].apply(this, [log].concat(Array.prototype.slice.call(arguments, 2)));\n }\n }\n });\nminispade.require('log/folds');\nminispade.require('log/deansi');\nminispade.require('log/limit');\nminispade.require('log/renderer');\n\n}).call(this);\n\n})();\n//@ sourceURL=log");minispade.register('log.old/buffer', "(function() {(function() {\n\n Log.Buffer = function(log, options) {\n this.start = 0;\n this.log = log;\n this.parts = [];\n this.options = $.extend({\n interval: 100,\n timeout: 500\n }, options || {});\n this.schedule();\n return this;\n };\n\n $.extend(Log.Buffer.prototype, {\n set: function(num, string) {\n return this.parts[num] = {\n string: string,\n time: (new Date).getTime()\n };\n },\n flush: function() {\n var num, part, _i, _len, _ref;\n _ref = this.parts;\n for (num = _i = 0, _len = _ref.length; _i < _len; num = ++_i) {\n part = _ref[num];\n if (!this.parts.hasOwnProperty(num)) {\n continue;\n }\n if (!part) {\n break;\n }\n delete this.parts[num];\n this.log.set(num, part.string);\n }\n return this.schedule();\n },\n schedule: function() {\n var _this = this;\n return setTimeout((function() {\n return _this.flush();\n }), this.options.interval);\n }\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=log.old/buffer");minispade.register('log.old/engine/chunks', "(function() {(function() {\n\n Log.Chunks = function(log) {\n this.log = log;\n this.parts = [];\n return this;\n };\n\n $.extend(Log.Chunks.prototype, {\n set: function(num, string) {\n var part;\n if (this.parts[num]) {\n return console.log(\"part \" + num + \" exists\");\n } else {\n part = new Log.Chunks.Part(this, num, string);\n this.parts[num] = part;\n return this.parts[num].insert();\n }\n },\n trigger: function() {\n return this.log.trigger.apply(this.log, arguments);\n }\n });\n\n Log.Chunks.Part = function(engine, num, string) {\n var chunk, ix, line, type;\n this.engine = engine;\n this.num = num;\n this.chunks = (function() {\n var _i, _len, _ref, _results;\n _ref = string.split(/^/m);\n _results = [];\n for (ix = _i = 0, _len = _ref.length; _i < _len; ix = ++_i) {\n chunk = _ref[ix];\n line = chunk[chunk.length - 1].match(/\\r|\\n/);\n type = line ? 'Line' : 'Chunk';\n _results.push(new Log.Chunks[type](this, ix, chunk));\n }\n return _results;\n }).call(this);\n return this;\n };\n\n $.extend(Log.Chunks.Part.prototype, {\n insert: function() {\n var chunk, _i, _len, _ref, _results;\n _ref = this.chunks;\n _results = [];\n for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n chunk = _ref[_i];\n _results.push(chunk.insert());\n }\n return _results;\n },\n prev: function() {\n var num, prev;\n num = this.num;\n while (!(prev || num < 0)) {\n prev = this.engine.parts[num -= 1];\n }\n return prev;\n },\n next: function() {\n var next, num;\n num = this.num;\n while (!(next || num >= this.engine.parts.length)) {\n next = this.engine.parts[num += 1];\n }\n return next;\n },\n trigger: function() {\n return this.engine.trigger.apply(this.engine, arguments);\n }\n });\n\n Log.Chunks.Chunk = function(part, num, string) {\n this.part = part;\n this.num = num;\n this.string = string;\n this.id = \"\" + (part != null ? part.num : void 0) + \"-\" + num;\n this.isFold = (string != null ? string.indexOf('fold') : void 0) !== -1;\n if (string) {\n this.nodes = this.parse();\n }\n return this;\n };\n\n $.extend(Log.Chunks.Chunk.prototype, {\n parse: function() {\n return [\n {\n type: 'span',\n id: \"\" + this.id + \"-0\",\n text: this.string\n }\n ];\n },\n insert: function() {\n var next, prev;\n if ((next = this.next()) && next.isLine) {\n return this.trigger('insert', this.nodes, {\n before: next.nodes[0].nodes[0].id\n });\n } else if (next) {\n return this.trigger('insert', this.nodes, {\n before: next.nodes[0].id\n });\n } else if ((prev = this.prev()) && !prev.isLine) {\n return this.trigger('insert', this.nodes, {\n after: prev.nodes[prev.nodes.length - 1].id\n });\n } else {\n return this.trigger('insert', [\n {\n type: 'paragraph',\n id: this.id,\n nodes: this.nodes\n }\n ], {\n before: void 0\n });\n }\n },\n remove: function() {\n var node, _i, _len, _ref, _results;\n _ref = this.nodes;\n _results = [];\n for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n node = _ref[_i];\n this.trigger('remove', this.id);\n if (node.nodes) {\n _results.push((function() {\n var _j, _len1, _ref1, _results1;\n _ref1 = node.nodes;\n _results1 = [];\n for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {\n node = _ref1[_j];\n _results1.push(this.trigger('remove', node.id));\n }\n return _results1;\n }).call(this));\n } else {\n _results.push(void 0);\n }\n }\n return _results;\n },\n reinsert: function() {\n this.remove();\n return this.insert();\n },\n prevLine: function() {\n var prev;\n prev = this.prev();\n while (prev && !prev.isLine) {\n prev = prev.prev();\n }\n return prev;\n },\n nextLine: function() {\n var next;\n next = this.next();\n while (next && !next.isLine) {\n next = next.next();\n }\n return next;\n },\n prev: function() {\n var chunk, _ref;\n chunk = this.part.chunks[this.num - 1];\n return chunk || ((_ref = this.part.prev()) != null ? _ref.chunks.slice(-1)[0] : void 0);\n },\n next: function() {\n var chunk, _ref;\n chunk = this.part.chunks[this.num + 1];\n return chunk || ((_ref = this.part.next()) != null ? _ref.chunks[0] : void 0);\n },\n trigger: function() {\n return this.part.trigger.apply(this.part, arguments);\n }\n });\n\n Log.Chunks.Line = function(part, num, string) {\n Log.Chunks.Chunk.call(this, part, num, string.slice(0, string.length - 1));\n this.isLine = true;\n return this;\n };\n\n Log.Chunks.Line.prototype = $.extend(new Log.Chunks.Chunk, {\n parse: function() {\n return [\n {\n type: 'paragraph',\n id: this.id,\n nodes: [\n {\n type: 'span',\n id: \"\" + this.id + \"-0\",\n text: this.string\n }\n ]\n }\n ];\n },\n insert: function() {\n var next, prev;\n if ((prev = this.prev()) && !prev.isLine) {\n this.trigger('insert', this.nodes[0].nodes, {\n after: prev.nodes[0].id\n });\n document.getElementById(this.nodes[0].nodes[0].id).parentNode.setAttribute('id', this.id);\n if (this.isLine && (next = this.next())) {\n return next.reinsert();\n }\n } else if (prev) {\n return this.trigger('insert', this.nodes, {\n after: prev.id\n });\n } else if (next = this.nextLine()) {\n return this.trigger('insert', this.nodes, {\n before: next.id\n });\n } else {\n return this.trigger('insert', this.nodes, {\n before: void 0\n });\n }\n }\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=log.old/engine/chunks");minispade.register('log.old/engine/dom', "(function() {(function() {\n\n Log.Dom = function(log) {\n this.log = log;\n this.parts = [];\n return this;\n };\n\n $.extend(Log.Dom.prototype, {\n set: function(num, string) {\n var part;\n if (this.parts[num]) {\n return console.log(\"part \" + num + \" exists\");\n } else {\n part = new Log.Dom.Part(this, num, string);\n this.parts[num] = part;\n return this.parts[num].insert();\n }\n },\n trigger: function() {\n return this.log.trigger.apply(this.log, arguments);\n }\n });\n\n Log.Dom.Part = function(engine, num, string) {\n this.engine = engine;\n this.num = num;\n this.string = string.replace(/\\r\\n/gm, '\\n');\n this.nodes = new Log.Dom.Nodes(this);\n return this;\n };\n\n $.extend(Log.Dom.Part.prototype, {\n SLICE: 500,\n insert: function() {\n var ix, lines, next, slices,\n _this = this;\n lines = this.string.split(/^/gm) || [];\n slices = ((function() {\n var _results;\n _results = [];\n while (lines.length > 0) {\n _results.push(lines.splice(0, this.SLICE));\n }\n return _results;\n }).call(this));\n ix = -1;\n next = function() {\n _this.insertSlice(slices.shift(), ix += 1);\n if (slices.length !== 0) {\n return setTimeout(next, 50);\n }\n };\n return next();\n },\n insertSlice: function(lines, start) {\n var ix, line, node, _i, _len, _ref, _ref1, _results;\n _ref = lines || [];\n _results = [];\n for (ix = _i = 0, _len = _ref.length; _i < _len; ix = ++_i) {\n line = _ref[ix];\n if ((_ref1 = this.engine.log.limit) != null ? _ref1.limited : void 0) {\n break;\n }\n node = Log.Dom.Node.create(this, start * this.SLICE + ix, line);\n _results.push(this.nodes.insert(node));\n }\n return _results;\n },\n remove: function() {\n return delete this.engine.parts[this.num];\n },\n trigger: function() {\n return this.engine.trigger.apply(this.engine, arguments);\n }\n });\n\n Log.Dom.Part.prototype.__defineGetter__('prev', function() {\n var num, prev;\n num = this.num;\n while (!(prev || num < 0)) {\n prev = this.engine.parts[num -= 1];\n }\n return prev;\n });\n\n Log.Dom.Part.prototype.__defineGetter__('next', function() {\n var next, num;\n num = this.num;\n while (!(next || num >= this.engine.parts.length)) {\n next = this.engine.parts[num += 1];\n }\n return next;\n });\n\n Log.Dom.Nodes = function(part) {\n this.part = part;\n this.nodes = [];\n return this;\n };\n\n $.extend(Log.Dom.Nodes.prototype, {\n at: function(ix) {\n return this.nodes[ix];\n },\n insert: function(node) {\n this.nodes[node.num] = node;\n return node.insert();\n },\n remove: function(node) {\n this.nodes.splice(node.num, 1);\n if (this.nodes.length === 0) {\n return this.part.remove();\n }\n }\n });\n\n Log.Dom.Nodes.prototype.__defineGetter__('length', function() {\n return this.nodes.length;\n });\n\n Log.Dom.Nodes.prototype.__defineGetter__('first', function() {\n return this.nodes[0];\n });\n\n Log.Dom.Nodes.prototype.__defineGetter__('last', function() {\n return this.nodes[this.nodes.length - 1];\n });\n\n Log.Dom.Node = function() {};\n\n $.extend(Log.Dom.Node, {\n FOLDS_PATTERN: /fold:(start|end):([\\w_\\-\\.]+)/,\n create: function(part, num, string) {\n var fold;\n if (fold = string.match(this.FOLDS_PATTERN)) {\n return new Log.Dom.Fold(part, num, fold[1], fold[2]);\n } else {\n return new Log.Dom.Paragraph(part, num, string);\n }\n },\n reinsert: function(nodes) {\n var node, _i, _j, _len, _len1;\n console.log(\"reinsert: \" + (nodes.map(function(node) {\n return node.id;\n }).join(', ')));\n for (_i = 0, _len = nodes.length; _i < _len; _i++) {\n node = nodes[_i];\n node.remove();\n }\n for (_j = 0, _len1 = nodes.length; _j < _len1; _j++) {\n node = nodes[_j];\n node.part.nodes.insert(node);\n }\n return console.log(document.firstChild.innerHTML.replace(/<\\/p>/gm, '

\\n') + '\\n');\n }\n });\n\n Log.Dom.Node.prototype.__defineGetter__('prev', function() {\n var num, prev, _ref;\n num = this.num;\n while (!(prev || num < 0)) {\n prev = this.part.nodes.at(num -= 1);\n }\n return prev || ((_ref = this.part.prev) != null ? _ref.nodes.last : void 0);\n });\n\n Log.Dom.Node.prototype.__defineGetter__('next', function() {\n var next, num, _ref;\n num = this.num;\n while (!(next || num >= this.part.nodes.length)) {\n next = this.part.nodes.at(num += 1);\n }\n return next || ((_ref = this.part.next) != null ? _ref.nodes.first : void 0);\n });\n\n Log.Dom.Fold = function(part, num, event, name) {\n this.part = part;\n this.ends = true;\n this.fold = true;\n this.num = num;\n this.id = \"fold-\" + event + \"-\" + name;\n this.data = {\n type: 'fold',\n id: this.id,\n event: event,\n name: name\n };\n return this;\n };\n\n Log.Dom.Fold.prototype = $.extend(new Log.Dom.Node, {\n insert: function() {\n return fail;\n },\n trigger: function() {\n return this.part.trigger.apply(this.part, arguments);\n }\n });\n\n Log.Dom.Paragraph = function(part, num, string) {\n var span, _ref;\n this.part = part;\n this.num = num;\n this.ends = !!((_ref = string[string.length - 1]) != null ? _ref.match(/\\n/) : void 0);\n this.spans = new Log.Dom.Spans(this, string.replace(/\\n$/, ''));\n this.data = {\n type: 'paragraph',\n num: this.part.num,\n hidden: this.hidden,\n nodes: (function() {\n var _i, _len, _ref1, _results;\n _ref1 = this.spans.content;\n _results = [];\n for (_i = 0, _len = _ref1.length; _i < _len; _i++) {\n span = _ref1[_i];\n _results.push(span.data);\n }\n return _results;\n }).call(this)\n };\n return this;\n };\n\n Log.Dom.Paragraph.prototype = $.extend(new Log.Dom.Node, {\n insert: function() {\n var next, prev, span, _i, _j, _len, _len1, _ref, _ref1, _ref2, _results;\n if ((prev = this.prev) && !prev.ends && !prev.fold) {\n if (Log.DEBUG) {\n console.log(\"P.1 - move \" + this.id + \"'s spans into prev\");\n }\n _ref = this.spans.content;\n for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n span = _ref[_i];\n prev.spans.append(span);\n }\n return this.part.nodes.remove(this);\n } else if ((next = this.next) && !this.ends && !next.fold) {\n if (Log.DEBUG) {\n console.log(\"P.2 - move \" + this.id + \"'s spans into next\");\n }\n _ref1 = this.spans.reverse();\n _results = [];\n for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {\n span = _ref1[_j];\n _results.push(next.prepend(span));\n }\n return _results;\n } else if ((prev != null ? prev.fold : void 0) && (prev != null ? (_ref2 = prev.element.getAttribute('class')) != null ? _ref2.match(' fold') : void 0 : void 0)) {\n if (Log.DEBUG) {\n console.log(\"P.3 - append \" + this.id + \" to fold \" + prev.id);\n }\n return this.element = this.trigger('insert', this.data, {\n after: prev.element.firstChild\n });\n } else if (prev) {\n if (Log.DEBUG) {\n console.log(\"P.4 - insert \" + this.id + \" after the parentNode of the last node of prev, id \" + prev.id);\n }\n return this.element = this.trigger('insert', this.data, {\n after: prev.element\n });\n } else if (next) {\n if (Log.DEBUG) {\n console.log(\"P.5 - insert \" + this.id + \" before the parentNode of the first node of next, id \" + next.id);\n }\n return this.element = this.trigger('insert', this.data, {\n before: next.element\n });\n } else {\n if (Log.DEBUG) {\n console.log(\"P.6 - insert \" + this.id + \" at the beginning of #log\");\n }\n return this.element = this.trigger('insert', this.data);\n }\n },\n remove: function() {\n var element, span, _i, _len, _ref;\n element = this.element;\n _ref = this.spans;\n for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n span = _ref[_i];\n this.trigger('remove', span.element);\n }\n if (!(element.childNodes.length > 1)) {\n this.trigger('remove', element);\n }\n return this.part.nodes.remove(this);\n },\n trigger: function() {\n return this.part.trigger.apply(this.part, arguments);\n }\n });\n\n Log.Dom.Paragraph.prototype.__defineGetter__('id', function() {\n return \"\" + this.part.num + \"-\" + this.num;\n });\n\n Log.Dom.Paragraph.prototype.__defineSetter__('element', function(element) {\n var child, span, _i, _len, _ref, _results;\n child = element.firstChild;\n _ref = this.spans.content;\n _results = [];\n for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n span = _ref[_i];\n _results.push(span.element = child = child.nextSibling);\n }\n return _results;\n });\n\n Log.Dom.Paragraph.prototype.__defineGetter__('element', function() {\n return this.spans.first.element.parentNode;\n });\n\n Log.Dom.Paragraph.prototype.__defineGetter__('tail', function() {\n var next, parent, tail, _ref;\n parent = this.element.parentNode;\n next = this;\n tail = [];\n while ((next = next.next) && !next.fold && ((_ref = next.element) != null ? _ref.parentNode : void 0) === parent) {\n tail.push(next);\n }\n return tail;\n });\n\n Log.Dom.Spans = function(parent, string) {\n this.parent = parent;\n this.content = this.parse(parent, string);\n return this;\n };\n\n $.extend(Log.Dom.Spans.prototype, {\n parse: function(parent, string) {\n var ix, span, _i, _len, _ref, _results;\n _ref = Log.Deansi.apply(string);\n _results = [];\n for (ix = _i = 0, _len = _ref.length; _i < _len; ix = ++_i) {\n span = _ref[ix];\n _results.push(new Log.Dom.Span(parent, ix, span));\n }\n return _results;\n },\n at: function(ix) {\n return this.content[ix];\n },\n indexOf: function(span) {\n return this.content.indexOf(span);\n },\n append: function(span) {\n span.parent.spans.remove(span);\n span.parent = this.parent;\n this.content.push(span);\n return span.insert();\n },\n prepend: function(span) {\n span.parent.spans.remove(span);\n span.parent = this.parent;\n this.content.unshift(span);\n return span.insert();\n },\n reverse: function() {\n return this.content.reverse();\n },\n remove: function(span) {\n return this.content.splice(this.content.indexOf(span), 1);\n }\n });\n\n Log.Dom.Spans.prototype.__defineGetter__('first', function() {\n return this.content[0];\n });\n\n Log.Dom.Spans.prototype.__defineGetter__('last', function() {\n return this.content[this.length - 1];\n });\n\n Log.Dom.Span = function(parent, num, data) {\n this.parent = parent;\n this.num = num;\n this.id = \"\" + parent.id + \"-\" + num;\n this.data = $.extend(data, {\n id: this.id\n });\n if (data.text.match(/\\r/)) {\n this.hidden = true;\n }\n this.data.text = data.text.replace(/^.*\\r/gm, '');\n if (this.hidden) {\n this.data[\"class\"] = ['hidden'];\n }\n return this;\n };\n\n $.extend(Log.Dom.Span.prototype, {\n insert: function() {\n var next, prev;\n if (prev = this.prev) {\n if (Log.DEBUG) {\n console.log(\"S.1 - insert \" + this.id + \" after prev \" + prev.id);\n }\n return this.insertAt({\n after: prev.element\n });\n } else if (next = this.next) {\n if (Log.DEBUG) {\n console.log(\"S.2 - insert \" + this.id + \" before next \" + next.id);\n }\n return this.insertAt({\n before: next.element\n });\n } else {\n if (Log.DEBUG) {\n console.log(\"S.2 - insert \" + this.id + \" into parent \" + this.parent.id);\n }\n return this.insertAt({\n into: this.parent.element\n });\n }\n },\n insertAt: function(pos) {\n var span, _i, _len, _ref, _results;\n this.element = this.trigger('insert', this.data, pos);\n if (this.hidden) {\n _ref = this.head;\n _results = [];\n for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n span = _ref[_i];\n _results.push(span.hide());\n }\n return _results;\n } else {\n if (this.tail.some(function(span) {\n return span.hidden;\n })) {\n return this.hide();\n }\n }\n },\n hide: function() {\n if (!this.hidden) {\n this.trigger('hide', this.id);\n }\n return this.hidden = true;\n },\n siblings: function(direction) {\n var siblings, span, _ref;\n siblings = [];\n span = this;\n while ((span = span[direction]) && ((_ref = span.element) != null ? _ref.parentNode : void 0) === this.element.parentNode) {\n siblings.unshift(span);\n }\n return siblings;\n },\n trigger: function() {\n return this.parent.trigger.apply(this.parent, arguments);\n }\n });\n\n Log.Dom.Span.prototype.__defineGetter__('head', function() {\n return this.siblings('prev');\n });\n\n Log.Dom.Span.prototype.__defineGetter__('tail', function() {\n return this.siblings('next');\n });\n\n Log.Dom.Span.prototype.__defineGetter__('prev', function() {\n var span, _ref, _ref1;\n span = this.parent.spans.at(this.parent.spans.indexOf(this) - 1);\n return span || ((_ref = this.parent.prev) != null ? (_ref1 = _ref.spans) != null ? _ref1.last : void 0 : void 0);\n });\n\n Log.Dom.Span.prototype.__defineGetter__('next', function() {\n var span, _ref, _ref1;\n span = this.parent.spans.at(this.parent.spans.indexOf(this) + 1);\n return span || ((_ref = this.parent.next) != null ? (_ref1 = _ref.spans) != null ? _ref1.first : void 0 : void 0);\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=log.old/engine/dom");minispade.register('log.old/engine/dom2', "(function() {(function() {\n\n Log.Dom = function(log) {\n this.log = log;\n this.parts = [];\n this.nodes = new Log.Dom.Nodes(this);\n return this;\n };\n\n $.extend(Log.Dom.prototype, {\n set: function(num, string) {\n if (this.parts[num]) {\n return console.log(\"part \" + num + \" exists\");\n } else {\n this.parts[num] = true;\n return this.insert(num, string);\n }\n },\n SLICE: 500,\n insert: function(num, string) {\n var ix, lines, next, slices,\n _this = this;\n lines = string.split(/^/gm) || [];\n slices = ((function() {\n var _results;\n _results = [];\n while (lines.length > 0) {\n _results.push(lines.splice(0, this.SLICE));\n }\n return _results;\n }).call(this));\n ix = -1;\n next = function() {\n _this.insertSlice(num, slices.shift(), ix += 1);\n if (slices.length !== 0) {\n return setTimeout(next, 50);\n }\n };\n return next();\n },\n insertSlice: function(num, lines, start) {\n var ix, line, _i, _len, _ref, _ref1, _results;\n _ref = lines || [];\n _results = [];\n for (ix = _i = 0, _len = _ref.length; _i < _len; ix = ++_i) {\n line = _ref[ix];\n if ((_ref1 = this.log.limit) != null ? _ref1.limited : void 0) {\n break;\n }\n _results.push(this.nodes.insert(Log.Dom.Node.create(this, [num, start * this.SLICE + ix], line)));\n }\n return _results;\n }\n });\n\n Log.Dom.Nodes = function(parent) {\n this.parent = parent;\n this.content = [];\n return this;\n };\n\n $.extend(Log.Dom.Nodes.prototype, {\n at: function(ix) {\n return this.content[ix];\n },\n insert: function(node) {\n return this.content[node.num] = node;\n },\n remove: function(node) {\n return this.content.splice(this.content.indexOf(node), 1);\n }\n });\n\n Log.Dom.Nodes.prototype.__defineGetter__('length', function() {\n return this.content.length;\n });\n\n Log.Dom.Nodes.prototype.__defineGetter__('first', function() {\n return this.content[0];\n });\n\n Log.Dom.Nodes.prototype.__defineGetter__('last', function() {\n return this.content[this.content.length - 1];\n });\n\n Log.Dom.Node = function() {};\n\n $.extend(Log.Dom.Node, {\n FOLDS_PATTERN: /fold:(start|end):([\\w_\\-\\.]+)/,\n create: function(parent, ids, string) {\n var fold;\n if (fold = string.match(this.FOLDS_PATTERN)) {\n return new Log.Dom.Fold(parent, ids, fold[1], fold[2]);\n } else {\n return new Log.Dom.Paragraph(parent, ids, string);\n }\n }\n });\n\n Log.Dom.Node.prototype.__defineGetter__('prev', function() {\n var num, prev, _ref;\n num = this.num;\n while (!(prev || num < 0)) {\n prev = this.parent.nodes.at(num -= 1);\n }\n return prev || ((_ref = this.parent.prev) != null ? _ref.nodes.last : void 0);\n });\n\n Log.Dom.Node.prototype.__defineGetter__('next', function() {\n var next, num, _ref;\n num = this.num;\n while (!(next || num >= this.parent.nodes.length)) {\n next = this.parent.nodes.at(num += 1);\n }\n return next || ((_ref = this.parent.next) != null ? _ref.nodes.first : void 0);\n });\n\n Log.Dom.Paragraph = function(parent, ids, string) {\n var _ref;\n this.parent = parent;\n this.ids = ids;\n this.id = ids.join('-');\n this.ends = !!((_ref = string[string.length - 1]) != null ? _ref.match(/\\n/) : void 0);\n this.spans = new Log.Dom.Spans(this, ids, string.replace(/\\n$/, ''));\n return this;\n };\n\n Log.Dom.Paragraph.prototype = $.extend(new Log.Dom.Node, {\n insert: function() {\n var next, prev,\n _this = this;\n if ((prev = this.prev) && !prev.ends && !prev.fold) {\n if (Log.DEBUG) {\n console.log(\"P.1 - move \" + this.id + \"'s spans into prev (\" + prev.id + \")\");\n }\n this.spans.content.slice().forEach(function(span) {\n return prev.spans.insert(span);\n });\n return this.remove();\n } else if ((next = this.next) && !this.ends && !next.fold) {\n if (Log.DEBUG) {\n console.log(\"P.2 - move next's (\" + next.id + \") spans into \" + this.id);\n }\n this.next.spans.content.slice().forEach(function(span) {\n return _this.spans.insert(span);\n });\n return next.remove();\n }\n },\n remove: function() {\n return this.parent.nodes.remove(this);\n }\n });\n\n Log.Dom.Paragraph.prototype.__defineGetter__('id', function() {\n return \"\" + this.parent.num + \"-\" + this.num;\n });\n\n Log.Dom.Spans = function(parent, ids, string) {\n this.parent = parent;\n this.content = this.parse(parent, ids, string);\n return this;\n };\n\n $.extend(Log.Dom.Spans.prototype, {\n parse: function(parent, ids, string) {\n var ix, span, _i, _len, _ref, _results;\n _ref = Log.Deansi.apply(string);\n _results = [];\n for (ix = _i = 0, _len = _ref.length; _i < _len; ix = ++_i) {\n span = _ref[ix];\n _results.push(new Log.Dom.Span(parent, ids.concat([ix]), span));\n }\n return _results;\n },\n at: function(ix) {\n return this.content[ix];\n },\n indexOf: function(span) {\n return this.content.indexOf(span);\n },\n insert: function(span) {\n var head, ix, prev;\n console.log('insert', span.id);\n span.parent.spans.remove(span);\n span.parent = this.parent;\n head = this.content.filter(function(s) {\n return s.id < span.id;\n });\n if (prev = head[head.length - 1]) {\n ix = this.content.indexOf(prev) + 1;\n }\n return this.content.splice(ix || 0, 0, span);\n },\n prepend: function(span) {\n span.parent.spans.remove(span);\n span.parent = this.parent;\n this.content.unshift(span);\n return span.insert();\n },\n remove: function(span) {\n return this.content.splice(this.content.indexof(span), 1);\n }\n });\n\n Log.Dom.Spans.prototype.__defineGetter__('first', function() {\n return this.content[0];\n });\n\n Log.Dom.Spans.prototype.__defineGetter__('last', function() {\n return this.content[this.content.length - 1];\n });\n\n Log.Dom.Span = function(parent, ids, data) {\n this.parent = parent;\n this.ids = ids;\n this.id = ids.join('-');\n this.data = $.extend(data, {\n id: this.id\n });\n if (data.text.match(/\\r/)) {\n this.hidden = true;\n }\n this.data.text = data.text.replace(/^.*\\r/gm, '');\n if (this.hidden) {\n this.data[\"class\"] = ['hidden'];\n }\n return this;\n };\n\n $.extend(Log.Dom.Span.prototype, {\n insert: function() {\n var next, prev;\n if (prev = this.prev) {\n if (Log.DEBUG) {\n console.log(\"S.1 - insert \" + this.id + \" after prev \" + prev.id);\n }\n return this.insertAt({\n after: prev.element\n });\n } else if (next = this.next) {\n if (Log.DEBUG) {\n console.log(\"S.2 - insert \" + this.id + \" before next \" + next.id);\n }\n return this.insertAt({\n before: next.element\n });\n } else {\n if (Log.DEBUG) {\n console.log(\"S.2 - insert \" + this.id + \" into parent \" + this.parent.id);\n }\n return this.insertAt({\n into: this.parent.element\n });\n }\n },\n insertAt: function(pos) {\n return this.element = this.trigger('insert', this.data, pos);\n }\n });\n\n Log.Dom.Span.prototype.__defineGetter__('prev', function() {\n var span, _ref, _ref1;\n console.log(this.num);\n span = this.parent.spans.at(this.num - 1);\n return span || ((_ref = this.parent.prev) != null ? (_ref1 = _ref.spans) != null ? _ref1.last : void 0 : void 0);\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=log.old/engine/dom2");minispade.register('log.old/engine/live', "(function() {(function() {\n\n Log.Live = function(log) {\n this.log = log;\n this.parts = [];\n return this;\n };\n\n $.extend(Log.Live.prototype, {\n set: function(num, string) {\n var part;\n if (this.parts[num]) {\n return console.log(\"part \" + num + \" exists\");\n } else {\n part = new Log.Live.Part(this, num, string);\n this.parts[num] = part;\n return this.parts[num].insert();\n }\n },\n trigger: function() {\n return this.log.trigger.apply(this.log, arguments);\n }\n });\n\n Log.Live.Part = function(log, num, string) {\n var ix, line;\n this.log = log;\n this.num = num;\n this.lines = (function() {\n var _i, _len, _ref, _results;\n _ref = string.split(/^/m);\n _results = [];\n for (ix = _i = 0, _len = _ref.length; _i < _len; ix = ++_i) {\n line = _ref[ix];\n _results.push(new Log.Live.Line(this, ix, line));\n }\n return _results;\n }).call(this);\n return this;\n };\n\n $.extend(Log.Live.Part.prototype, {\n insert: function() {\n return new Log.Live.Context(this.log, this).insert();\n },\n head: function() {\n var head, line;\n head = [];\n line = this.lines[0];\n while ((line = line != null ? line.prev() : void 0) && !line.isNewline()) {\n head.unshift(line);\n }\n return head;\n },\n tail: function() {\n var line, tail;\n tail = [];\n line = this.lines[this.lines.length - 1];\n while (line = line != null ? line.next() : void 0) {\n tail.push(line);\n if (line != null ? line.isNewline() : void 0) {\n break;\n }\n }\n return tail;\n },\n prev: function() {\n var num, prev;\n num = this.num;\n while (!(prev || num < 0)) {\n prev = this.log.parts[num -= 1];\n }\n return prev;\n },\n next: function() {\n var next, num;\n num = this.num;\n while (!(next || num >= this.log.parts.length)) {\n next = this.log.parts[num += 1];\n }\n return next;\n }\n });\n\n Log.Live.Line = function(part, num, string) {\n this.part = part;\n this.num = num;\n this.id = \"\" + part.num + \"-\" + num;\n this.string = string;\n return this;\n };\n\n $.extend(Log.Live.Line.prototype, {\n prev: function() {\n var line, _ref;\n line = this.part.lines[this.num - 1];\n return line || ((_ref = this.part.prev()) != null ? _ref.lines.slice(-1)[0] : void 0);\n },\n next: function() {\n var line, _ref;\n line = this.part.lines[this.num + 1];\n return line || ((_ref = this.part.next()) != null ? _ref.lines[0] : void 0);\n },\n isNewline: function() {\n return this.string[this.string.length - 1] === \"\\n\";\n },\n isFold: function() {\n return this.string.indexOf('fold') !== -1;\n },\n clone: function() {\n return new Log.Live.Line(this.part, this.num, this.string);\n }\n });\n\n Log.Live.Context = function(log, part) {\n this.log = log;\n this.part = part;\n this.head = part.head();\n this.tail = part.tail();\n this.lines = this.join(this.head.concat(part.lines).concat(this.tail));\n return this;\n };\n\n $.extend(Log.Live.Context.prototype, {\n insert: function() {\n var ids;\n ids = this.head.concat(this.tail).map(function(line) {\n return line.id;\n });\n if (ids.length !== 0) {\n this.log.trigger('remove', ids);\n }\n return this.log.trigger('insert', this.after(), this.nodes());\n },\n nodes: function() {\n var _this = this;\n return this.lines.map(function(line) {\n var fold, string;\n string = line.string;\n if (fold = _this.defold(string)) {\n return $.extend(fold, {\n id: line.id\n });\n } else {\n return {\n id: line.id,\n nodes: _this.deansi(string)\n };\n }\n });\n },\n join: function(all) {\n var line, lines;\n lines = [];\n while (line = all.pop()) {\n if (lines.length === 0 || line.isNewline()) {\n lines.unshift(line.clone());\n } else {\n lines[0].string = line.string + lines[0].string;\n }\n }\n return lines;\n },\n after: function() {\n var line, _ref;\n line = (_ref = this.part.lines[0]) != null ? _ref.prev() : void 0;\n while (line && !line.isNewline() && !line.isFold()) {\n line = line.prev();\n }\n return line != null ? line.id : void 0;\n },\n defold: function(string) {\n var matches;\n if (matches = string.match(/fold:(start|end):([\\w_\\-\\.]+)/)) {\n return {\n type: 'fold',\n event: matches[1],\n name: matches[2]\n };\n }\n },\n deansi: function(string) {\n return Log.Deansi.apply(string);\n }\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=log.old/engine/live");minispade.register('log.old/folds', "(function() {(function() {\n\n Log.Folds = function() {\n this.folds = {};\n return this;\n };\n\n Log.Folds.prototype = $.extend(new Log.Listener, {\n insert: function(log, data, pos) {\n var fold, _base, _name;\n if (data.type === 'fold') {\n fold = (_base = this.folds)[_name = data.name] || (_base[_name] = new Log.Folds.Fold);\n fold.receive(data);\n }\n return true;\n }\n });\n\n Log.Folds.Fold = function() {\n return this;\n };\n\n $.extend(Log.Folds.Fold.prototype, {\n receive: function(data) {\n this[data.event] = data.id;\n if (this.start && this.end && !this.active) {\n return this.activate();\n }\n },\n activate: function() {\n var node, _i, _len, _ref;\n console.log(\"F - activate \" + this.start);\n console.log(document.firstChild.innerHTML.replace(/

rcv \" + num + \" \" + (JSON.stringify(string)) + \"\");\n },\n insert: function(log, after, datas) {\n return this.log(\"ins \" + (datas.map(function(data) {\n return data.id;\n }).join(', ')) + \", after: \" + (after || '?') + \", \" + (JSON.stringify(datas)));\n },\n remove: function(log, id) {\n return this.log(\"rem \" + id);\n },\n log: function(line) {\n return $('#events').append(\"\" + line + \"\\n\");\n }\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=log.old/instrument");minispade.register('log.old/limit', "(function() {(function() {\n\n Log.Limit = function(max_lines) {\n this.max_lines = max_lines || 1000;\n return this;\n };\n\n Log.Limit.prototype = $.extend(new Log.Listener, {\n count: 0,\n insert: function(log, line, pos) {\n if (line.type === 'paragraph' && !line.hidden) {\n return this.count += 1;\n }\n }\n });\n\n Log.Limit.prototype.__defineGetter__('limited', function() {\n return this.count >= this.max_lines;\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=log.old/limit");minispade.register('log.old/renderer/inner_html', "(function() {(function() {\n\n Log.InnerHtmlRenderer = function() {\n this.frag = document.createDocumentFragment();\n this.div = document.createElement('div');\n return this;\n };\n\n Log.InnerHtmlRenderer.prototype = $.extend(new Log.Listener, {\n remove: function(log, ids) {\n var id, node, _i, _len, _ref, _results;\n _results = [];\n for (_i = 0, _len = ids.length; _i < _len; _i++) {\n id = ids[_i];\n node = document.getElementById(id);\n if (node && !((_ref = node.getAttribute('class')) != null ? _ref.match(/fold/) : void 0)) {\n _results.push(node.parentNode.removeChild(node));\n } else {\n _results.push(void 0);\n }\n }\n return _results;\n },\n insert: function(log, after, nodes) {\n var html;\n log = document.getElementById('log');\n html = this.render(nodes);\n if (log.childNodes.length === 0) {\n return log.innerHTML = html;\n } else if (after) {\n after = document.getElementById(after);\n return this.insertAfter(this.fragmentFrom(html), after);\n } else {\n log = document.getElementById('log');\n return log.insertBefore(this.fragmentFrom(html), log.firstChild);\n }\n },\n render: function(nodes) {\n var node;\n return ((function() {\n var _i, _len, _results;\n _results = [];\n for (_i = 0, _len = nodes.length; _i < _len; _i++) {\n node = nodes[_i];\n _results.push(this.renderNode(node));\n }\n return _results;\n }).call(this)).join('');\n },\n renderNode: function(node) {\n var type;\n node.type || (node.type = 'paragraph');\n type = node.type[0].toUpperCase() + node.type.slice(1);\n return this[\"render\" + type](node) || '';\n },\n renderParagraph: function(node) {\n var html, style;\n if (node.hidden) {\n style = ' style=\"display:none\"';\n }\n html = \"

\";\n html += ((function() {\n var _i, _len, _ref, _results;\n _ref = node.nodes;\n _results = [];\n for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n node = _ref[_i];\n _results.push(this.renderNode(node));\n }\n return _results;\n }).call(this)).join('');\n return html + '

';\n },\n renderFold: function(node) {\n if (!document.getElementById(node.id)) {\n return \"
\";\n }\n },\n renderSpan: function(node) {\n return \"\" + (this.clean(node.text)) + \"\";\n },\n renderText: function(node) {\n return this.clean(node.text);\n },\n clean: function(text) {\n return text.replace(/\\n/gm, '');\n },\n fragmentFrom: function(html) {\n var div, frag, node;\n frag = this.frag.cloneNode();\n div = this.div.cloneNode();\n div.innerHTML = html;\n while (node = div.firstChild) {\n frag.appendChild(node);\n }\n return frag;\n },\n insertAfter: function(node, after) {\n if (after.nextSibling) {\n return after.parentNode.insertBefore(node, after.nextSibling);\n } else {\n return after.parentNode.appendChild(node);\n }\n }\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=log.old/renderer/inner_html");minispade.register('log.old/renderer/jquery', "(function() {(function() {\n\n Log.JqueryRenderer = function() {};\n\n Log.JqueryRenderer.prototype = $.extend(new Log.Listener, {\n remove: function(log, ids) {\n var id, _i, _len, _results;\n _results = [];\n for (_i = 0, _len = ids.length; _i < _len; _i++) {\n id = ids[_i];\n _results.push($(\"#log #\" + id).remove());\n }\n return _results;\n },\n insert: function(log, after, datas) {\n var html,\n _this = this;\n html = datas.map(function(data) {\n return _this.render(data);\n });\n return after && $(\"#log #\" + after).after(html) || $('#log').prepend(html);\n },\n render: function(data) {\n var node, nodes, text;\n nodes = (function() {\n var _i, _len, _ref, _results;\n _ref = data.nodes;\n _results = [];\n for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n node = _ref[_i];\n text = node.text.replace(/\\n/gm, '');\n if (node.type === 'span') {\n text = \"\" + text + \"\";\n }\n _results.push(\"

\" + text + \"

\");\n }\n return _results;\n }).call(this);\n return nodes.join(\"\\n\");\n },\n style: function(data) {\n return data.hidden && 'display: none;' || '';\n }\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=log.old/renderer/jquery");minispade.register('log/deansi', "(function() {(function() {\n\n Log.Deansi = {\n CLEAR_ANSI: /(?:\\033)(?:\\[0?c|\\[[0356]n|\\[7[lh]|\\[\\?25[lh]|\\(B|H|\\[(?:\\d+(;\\d+){,2})?G|\\[(?:[12])?[JK]|[DM])/gm,\n apply: function(string) {\n var nodes,\n _this = this;\n if (!string) {\n return [];\n }\n string = string.replace(this.CLEAR_ANSI, '');\n nodes = ansiparse(string).map(function(part) {\n return _this.node(part);\n });\n if (nodes.length === 0) {\n nodes.push(this.node({\n text: ''\n }));\n }\n return nodes;\n },\n node: function(part) {\n var classes, node;\n node = {\n type: 'span',\n text: part.text\n };\n if (classes = this.classes(part)) {\n node[\"class\"] = classes.join(' ');\n }\n return node;\n },\n classes: function(part) {\n var result;\n result = [];\n result = result.concat(this.colors(part));\n if (result.length > 0) {\n return result;\n }\n },\n colors: function(part) {\n var colors;\n colors = [];\n if (part.foreground) {\n colors.push(part.foreground);\n }\n if (part.background) {\n colors.push(\"bg-\" + part.background);\n }\n if (part.bold) {\n colors.push('bold');\n }\n if (part.italic) {\n colors.push('italic');\n }\n if (part.underline) {\n colors.push('underline');\n }\n return colors;\n },\n hidden: function(part) {\n if (part.text.match(/\\r/)) {\n part.text = part.text.replace(/^.*\\r/gm, '');\n return true;\n }\n }\n };\n\n}).call(this);\n\n})();\n//@ sourceURL=log/deansi");minispade.register('log/folds', "(function() {(function() {\n\n Log.Folds = function() {\n this.folds = {};\n return this;\n };\n\n Log.extend(Log.Folds.prototype, {\n add: function(data) {\n var fold, _base, _name;\n fold = (_base = this.folds)[_name = data.name] || (_base[_name] = new Log.Folds.Fold);\n fold.receive(data);\n return fold.active;\n }\n });\n\n Log.Folds.Fold = function() {\n return this;\n };\n\n Log.extend(Log.Folds.Fold.prototype, {\n receive: function(data) {\n this[data.event] = data.id;\n if (this.start && this.end && !this.active) {\n return this.activate();\n }\n },\n activate: function() {\n var fragment, nextSibling, node, parentNode, toRemove, _i, _len, _ref;\n if (Log.DEBUG) {\n console.log(\"F - activate \" + this.start);\n }\n toRemove = this.fold.parentNode;\n parentNode = toRemove.parentNode;\n nextSibling = toRemove.nextSibling;\n parentNode.removeChild(toRemove);\n fragment = document.createDocumentFragment();\n _ref = this.nodes;\n for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n node = _ref[_i];\n fragment.appendChild(node);\n }\n this.fold.appendChild(fragment.cloneNode(true));\n parentNode.insertBefore(toRemove, nextSibling);\n this.fold.setAttribute('class', this.classes());\n return this.active = true;\n },\n classes: function() {\n var classes;\n classes = this.fold.getAttribute('class').split(' ');\n classes.push('fold');\n if (this.fold.childNodes.length > 2) {\n classes.push('active');\n }\n return classes.join(' ');\n }\n });\n\n Object.defineProperty(Log.Folds.Fold.prototype, 'fold', {\n get: function() {\n return this._fold || (this._fold = document.getElementById(this.start));\n }\n });\n\n Object.defineProperty(Log.Folds.Fold.prototype, 'nodes', {\n get: function() {\n var node, nodes;\n node = this.fold;\n nodes = [];\n while ((node = node.nextSibling) && node.id !== this.end) {\n nodes.push(node);\n }\n return nodes;\n }\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=log/folds");minispade.register('log/limit', "(function() {(function() {\n\n Log.Limit = function(max_lines) {\n this.max_lines = max_lines || 1000;\n return this;\n };\n\n Log.Limit.prototype = Log.extend(new Log.Listener, {\n count: 0,\n insert: function(log, node, pos) {\n if (node.type === 'paragraph' && !node.hidden) {\n return this.count += 1;\n }\n }\n });\n\n Object.defineProperty(Log.Limit.prototype, 'limited', {\n get: function() {\n return this.count >= this.max_lines;\n }\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=log/limit");minispade.register('log/nodes', "(function() {(function() {\n var newLineAtTheEndRegexp, newLineRegexp, rRegexp, removeCarriageReturns;\n\n Log.Node = function(id, num) {\n this.id = id;\n this.num = num;\n this.key = Log.Node.key(this.id);\n this.children = new Log.Nodes(this);\n return this;\n };\n\n Log.extend(Log.Node, {\n key: function(id) {\n if (id) {\n return id.split('-').map(function(i) {\n return '000000'.concat(i).slice(-6);\n }).join('');\n }\n }\n });\n\n Log.extend(Log.Node.prototype, {\n addChild: function(node) {\n return this.children.add(node);\n },\n remove: function() {\n this.log.remove(this.element);\n return this.parent.children.remove(this);\n }\n });\n\n Object.defineProperty(Log.Node.prototype, 'log', {\n get: function() {\n var _ref;\n return this._log || (this._log = ((_ref = this.parent) != null ? _ref.log : void 0) || this.parent);\n }\n });\n\n Object.defineProperty(Log.Node.prototype, 'firstChild', {\n get: function() {\n return this.children.first;\n }\n });\n\n Object.defineProperty(Log.Node.prototype, 'lastChild', {\n get: function() {\n return this.children.last;\n }\n });\n\n Log.Nodes = function(parent) {\n if (parent) {\n this.parent = parent;\n }\n this.items = [];\n this.index = {};\n return this;\n };\n\n Log.extend(Log.Nodes.prototype, {\n add: function(item) {\n var ix, next, prev, _ref, _ref1;\n ix = this.position(item) || 0;\n this.items.splice(ix, 0, item);\n if (this.parent) {\n item.parent = this.parent;\n }\n prev = function(item) {\n while (item && !item.children.last) {\n item = item.prev;\n }\n return item != null ? item.children.last : void 0;\n };\n next = function(item) {\n while (item && !item.children.first) {\n item = item.next;\n }\n return item != null ? item.children.first : void 0;\n };\n if (item.prev = this.items[ix - 1] || prev((_ref = this.parent) != null ? _ref.prev : void 0)) {\n item.prev.next = item;\n }\n if (item.next = this.items[ix + 1] || next((_ref1 = this.parent) != null ? _ref1.next : void 0)) {\n item.next.prev = item;\n }\n return item;\n },\n remove: function(item) {\n this.items.splice(this.items.indexOf(item), 1);\n if (item.next) {\n item.next.prev = item.prev;\n }\n if (item.prev) {\n item.prev.next = item.next;\n }\n if (this.items.length === 0) {\n return this.parent.remove();\n }\n },\n position: function(item) {\n var ix, _i, _ref;\n for (ix = _i = _ref = this.items.length - 1; _i >= 0; ix = _i += -1) {\n if (this.items[ix].key < item.key) {\n return ix + 1;\n }\n }\n },\n indexOf: function() {\n return this.items.indexOf.apply(this.items, arguments);\n },\n slice: function() {\n return this.items.slice.apply(this.items, arguments);\n },\n each: function(func) {\n return this.items.slice().forEach(func);\n },\n map: function(func) {\n return this.items.map(func);\n }\n });\n\n Object.defineProperty(Log.Nodes.prototype, 'first', {\n get: function() {\n return this.items[0];\n }\n });\n\n Object.defineProperty(Log.Nodes.prototype, 'last', {\n get: function() {\n return this.items[this.length - 1];\n }\n });\n\n Object.defineProperty(Log.Nodes.prototype, 'length', {\n get: function() {\n return this.items.length;\n }\n });\n\n Log.Part = function(id, num, string) {\n Log.Node.apply(this, arguments);\n this.string = string || '';\n this.string = this.string.replace(/\\033\\[1000D/gm, '\\r');\n this.string = this.string.replace(/\\r+\\n/gm, '\\n');\n this.strings = this.string.split(/^/gm) || [];\n this.slices = ((function() {\n var _results;\n _results = [];\n while (this.strings.length > 0) {\n _results.push(this.strings.splice(0, Log.SLICE));\n }\n return _results;\n }).call(this));\n return this;\n };\n\n Log.extend(Log.Part, {\n create: function(log, num, string) {\n var part;\n part = new Log.Part(num.toString(), num, string);\n log.addChild(part);\n return part.process(0, -1);\n }\n });\n\n Log.Part.prototype = Log.extend(new Log.Node, {\n remove: function() {},\n process: function(slice, num) {\n var node, span, spans, string, _i, _j, _len, _len1, _ref, _ref1, _ref2,\n _this = this;\n _ref = this.slices[slice] || [];\n for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n string = _ref[_i];\n if ((_ref1 = this.log.limit) != null ? _ref1.limited : void 0) {\n return;\n }\n spans = [];\n _ref2 = Log.Deansi.apply(string);\n for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) {\n node = _ref2[_j];\n span = Log.Span.create(this, \"\" + this.id + \"-\" + (num += 1), num, node.text, node[\"class\"]);\n span.render();\n spans.push(span);\n }\n if (spans[0] && spans[0].line.cr) {\n spans[0].line.clear();\n }\n }\n if (!(slice >= this.slices.length - 1)) {\n return setTimeout((function() {\n return _this.process(slice + 1, num);\n }), Log.TIMEOUT);\n }\n }\n });\n\n newLineAtTheEndRegexp = new RegExp(\"\\n$\");\n\n newLineRegexp = new RegExp(\"\\n\");\n\n rRegexp = new RegExp(\"\\r\");\n\n removeCarriageReturns = function(string) {\n var index;\n index = string.lastIndexOf(\"\\r\");\n if (index === -1) {\n return string;\n }\n return string.substr(index + 1);\n };\n\n Log.Span = function(id, num, text, classes) {\n var fold, _ref;\n Log.Node.apply(this, arguments);\n if (fold = text.match(Log.FOLD)) {\n this.fold = true;\n this.event = fold[1];\n this.text = this.name = fold[2];\n } else {\n this.text = text;\n this.text = removeCarriageReturns(this.text);\n this.text = this.text.replace(newLineAtTheEndRegexp, '');\n this.nl = !!((_ref = text[text.length - 1]) != null ? _ref.match(newLineRegexp) : void 0);\n this.cr = !!text.match(rRegexp);\n this[\"class\"] = this.cr && ['clears'] || classes;\n }\n return this;\n };\n\n Log.extend(Log.Span, {\n create: function(parent, id, num, text, classes) {\n var span;\n span = new Log.Span(id, num, text, classes);\n parent.addChild(span);\n return span;\n },\n render: function(parent, id, num, text, classes) {\n var span;\n span = this.create(parent, id, num, text, classes);\n return span.render();\n }\n });\n\n Log.Span.prototype = Log.extend(new Log.Node, {\n render: function() {\n var tail;\n if (!this.fold && this.prev && !this.prev.fold && !this.prev.nl) {\n if (Log.DEBUG) {\n console.log(\"S.1 insert \" + this.id + \" after prev \" + this.prev.id);\n }\n this.log.insert(this.data, {\n after: this.prev.element\n });\n this.line = this.prev.line;\n } else if (!this.fold && this.next && !this.next.fold) {\n if (Log.DEBUG) {\n console.log(\"S.2 insert \" + this.id + \" before next \" + this.next.id);\n }\n this.log.insert(this.data, {\n before: this.next.element\n });\n this.line = this.next.line;\n } else {\n this.line = Log.Line.create(this.log, [this]);\n this.line.render();\n }\n if (this.nl && (tail = this.tail).length > 0) {\n return this.split(tail);\n }\n },\n remove: function() {\n Log.Node.prototype.remove.apply(this);\n if (this.line) {\n return this.line.remove(this);\n }\n },\n split: function(spans) {\n var line, span, _i, _len;\n if (Log.DEBUG) {\n console.log(\"S.3 split [\" + (spans.map(function(span) {\n return span.id;\n }).join(', ')) + \"]\");\n }\n for (_i = 0, _len = spans.length; _i < _len; _i++) {\n span = spans[_i];\n this.log.remove(span.element);\n }\n line = Log.Line.create(this.log, spans);\n line.render();\n if (line.cr) {\n return line.clear();\n }\n },\n clear: function() {\n if (this.prev && this.isSibling(this.prev) && this.isSequence(this.prev)) {\n this.prev.clear();\n return this.prev.remove();\n }\n },\n isSequence: function(other) {\n return this.parent.num - other.parent.num === this.log.children.indexOf(this.parent) - this.log.children.indexOf(other.parent);\n },\n isSibling: function(other) {\n var _ref, _ref1;\n return ((_ref = this.element) != null ? _ref.parentNode : void 0) === ((_ref1 = other.element) != null ? _ref1.parentNode : void 0);\n },\n siblings: function(type) {\n var siblings, span;\n siblings = [];\n while ((span = (span || this)[type]) && this.isSibling(span)) {\n siblings.push(span);\n }\n return siblings;\n }\n });\n\n Object.defineProperty(Log.Span.prototype, 'data', {\n get: function() {\n return {\n id: this.id,\n type: 'span',\n text: this.text,\n \"class\": this[\"class\"]\n };\n }\n });\n\n Object.defineProperty(Log.Span.prototype, 'line', {\n get: function() {\n return this._line;\n },\n set: function(line) {\n if (this.line) {\n this.line.remove(this);\n }\n this._line = line;\n return this.line.add(this);\n }\n });\n\n Object.defineProperty(Log.Span.prototype, 'element', {\n get: function() {\n return document.getElementById(this.id);\n }\n });\n\n Object.defineProperty(Log.Span.prototype, 'head', {\n get: function() {\n return this.siblings('prev').reverse();\n }\n });\n\n Object.defineProperty(Log.Span.prototype, 'tail', {\n get: function() {\n return this.siblings('next');\n }\n });\n\n Log.Line = function(log) {\n this.log = log;\n this.spans = [];\n return this;\n };\n\n Log.extend(Log.Line, {\n create: function(log, spans) {\n var line, span, _i, _len;\n if ((span = spans[0]) && span.fold) {\n line = new Log.Fold(log, span.event, span.name);\n } else {\n line = new Log.Line(log);\n }\n for (_i = 0, _len = spans.length; _i < _len; _i++) {\n span = spans[_i];\n span.line = line;\n }\n return line;\n }\n });\n\n Log.extend(Log.Line.prototype, {\n add: function(span) {\n var ix;\n if (span.cr) {\n this.cr = true;\n }\n if (this.spans.indexOf(span) > -1) {\n\n } else if ((ix = this.spans.indexOf(span.prev)) > -1) {\n return this.spans.splice(ix + 1, 0, span);\n } else if ((ix = this.spans.indexOf(span.next)) > -1) {\n return this.spans.splice(ix, 0, span);\n } else {\n return this.spans.push(span);\n }\n },\n remove: function(span) {\n var ix;\n if ((ix = this.spans.indexOf(span)) > -1) {\n return this.spans.splice(ix, 1);\n }\n },\n render: function() {\n var fold;\n if ((fold = this.prev) && fold.event === 'start' && fold.active) {\n if (Log.DEBUG) {\n console.log(\"L.0 insert \" + this.id + \" into fold \" + fold.id);\n }\n fold = this.log.folds.folds[fold.name].fold;\n return this.element = this.log.insert(this.data, {\n into: fold\n });\n } else if (this.prev) {\n if (Log.DEBUG) {\n console.log(\"L.1 insert \" + this.spans[0].id + \" after prev \" + this.prev.id);\n }\n return this.element = this.log.insert(this.data, {\n after: this.prev.element\n });\n } else if (this.next) {\n if (Log.DEBUG) {\n console.log(\"L.2 insert \" + this.spans[0].id + \" before next \" + this.next.id);\n }\n return this.element = this.log.insert(this.data, {\n before: this.next.element\n });\n } else {\n if (Log.DEBUG) {\n console.log(\"L.3 insert \" + this.spans[0].id + \" into #log\");\n }\n return this.element = this.log.insert(this.data);\n }\n },\n clear: function() {\n var cr, _i, _len, _ref, _results;\n _ref = this.crs;\n _results = [];\n for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n cr = _ref[_i];\n _results.push(cr.clear());\n }\n return _results;\n }\n });\n\n Object.defineProperty(Log.Line.prototype, 'id', {\n get: function() {\n var _ref;\n return (_ref = this.spans[0]) != null ? _ref.id : void 0;\n }\n });\n\n Object.defineProperty(Log.Line.prototype, 'data', {\n get: function() {\n return {\n type: 'paragraph',\n nodes: this.nodes\n };\n }\n });\n\n Object.defineProperty(Log.Line.prototype, 'nodes', {\n get: function() {\n return this.spans.map(function(span) {\n return span.data;\n });\n }\n });\n\n Object.defineProperty(Log.Line.prototype, 'prev', {\n get: function() {\n var _ref;\n return (_ref = this.spans[0].prev) != null ? _ref.line : void 0;\n }\n });\n\n Object.defineProperty(Log.Line.prototype, 'next', {\n get: function() {\n var _ref;\n return (_ref = this.spans[this.spans.length - 1].next) != null ? _ref.line : void 0;\n }\n });\n\n Object.defineProperty(Log.Line.prototype, 'crs', {\n get: function() {\n return this.spans.filter(function(span) {\n return span.cr;\n });\n }\n });\n\n Log.Fold = function(log, event, name) {\n Log.Line.apply(this, arguments);\n this.fold = true;\n this.event = event;\n this.name = name;\n return this;\n };\n\n Log.Fold.prototype = Log.extend(new Log.Line, {\n render: function() {\n var element, _ref;\n if (this.prev) {\n if (Log.DEBUG) {\n console.log(\"F.1 insert \" + this.id + \" after prev \" + this.prev.id);\n }\n element = this.prev.element || this.prev.element.parentNode;\n this.element = this.log.insert(this.data, {\n after: element\n });\n } else if (this.next) {\n if (Log.DEBUG) {\n console.log(\"F.2 insert \" + this.id + \" before next \" + this.next.id);\n }\n element = this.next.element || this.next.element.parentNode;\n this.element = this.log.insert(this.data, {\n before: element\n });\n } else {\n if (Log.DEBUG) {\n console.log(\"F.3 insert \" + this.id);\n }\n this.element = this.log.insert(this.data);\n }\n if (this.span.next && ((_ref = this.span.prev) != null ? _ref.isSibling(this.span.next) : void 0)) {\n this.span.prev.split([this.span.next].concat(this.span.next.tail));\n }\n return this.active = this.log.folds.add(this.data);\n }\n });\n\n Object.defineProperty(Log.Fold.prototype, 'id', {\n get: function() {\n return \"fold-\" + this.event + \"-\" + this.name;\n }\n });\n\n Object.defineProperty(Log.Fold.prototype, 'span', {\n get: function() {\n return this.spans[0];\n }\n });\n\n Object.defineProperty(Log.Fold.prototype, 'data', {\n get: function() {\n return {\n type: 'fold',\n id: this.id,\n event: this.event,\n name: this.name\n };\n }\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=log/nodes");minispade.register('log/renderer', "(function() {(function() {\n\n Log.Renderer = function() {\n this.frag = document.createDocumentFragment();\n this.para = this.createParagraph();\n this.span = this.createSpan();\n this.text = document.createTextNode('');\n this.fold = this.createFold();\n return this;\n };\n\n Log.extend(Log.Renderer.prototype, {\n insert: function(data, pos) {\n var after, before, into, node;\n node = this.render(data);\n if (into = pos != null ? pos.into : void 0) {\n if (typeof into === 'String') {\n into = document.getElementById(pos != null ? pos.into : void 0);\n }\n this.appendTo(node, into);\n } else if (after = pos != null ? pos.after : void 0) {\n if (typeof after === 'String') {\n after = document.getElementById(pos);\n }\n this.insertAfter(node, after);\n } else if (before = pos != null ? pos.before : void 0) {\n if (typeof before === 'String') {\n before = document.getElementById(pos != null ? pos.before : void 0);\n }\n this.insertBefore(node, before);\n } else {\n this.insertBefore(node);\n }\n return node;\n },\n hide: function(node) {\n node.setAttribute('class', this.addClass(node.getAttribute('class'), 'hidden'));\n return node;\n },\n remove: function(node) {\n if (node) {\n node.parentNode.removeChild(node);\n }\n return node;\n },\n render: function(data) {\n var frag, node, type, _i, _len;\n if (data instanceof Array) {\n frag = this.frag.cloneNode(true);\n for (_i = 0, _len = data.length; _i < _len; _i++) {\n node = data[_i];\n node = this.render(node);\n if (node) {\n frag.appendChild(node);\n }\n }\n return frag;\n } else {\n data.type || (data.type = 'paragraph');\n type = data.type[0].toUpperCase() + data.type.slice(1);\n return this[\"render\" + type](data);\n }\n },\n renderParagraph: function(data) {\n var node, para, type, _i, _len, _ref;\n para = this.para.cloneNode(true);\n if (data.id) {\n para.setAttribute('id', data.id);\n }\n if (data.hidden) {\n para.setAttribute('style', 'display: none;');\n }\n _ref = data.nodes || [];\n for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n node = _ref[_i];\n type = node.type[0].toUpperCase() + node.type.slice(1);\n node = this[\"render\" + type](node);\n para.appendChild(node);\n }\n return para;\n },\n renderFold: function(data) {\n var fold;\n fold = this.fold.cloneNode(true);\n fold.setAttribute('id', data.id || (\"fold-\" + data.event + \"-\" + data.name));\n fold.setAttribute('class', \"fold-\" + data.event);\n if (data.event === 'start') {\n fold.lastChild.lastChild.nodeValue = data.name;\n } else {\n fold.removeChild(fold.lastChild);\n }\n return fold;\n },\n renderSpan: function(data) {\n var span;\n span = this.span.cloneNode(true);\n if (data.id) {\n span.setAttribute('id', data.id);\n }\n if (data[\"class\"]) {\n span.setAttribute('class', data[\"class\"]);\n }\n span.lastChild.nodeValue = data.text;\n return span;\n },\n renderText: function(data) {\n var text;\n text = this.text.cloneNode(true);\n text.nodeValue = data.text;\n return text;\n },\n createParagraph: function() {\n var para;\n para = document.createElement('p');\n para.appendChild(document.createElement('a'));\n return para;\n },\n createFold: function() {\n var fold;\n fold = document.createElement('div');\n fold.appendChild(this.createSpan());\n fold.lastChild.setAttribute('class', 'fold-name');\n return fold;\n },\n createSpan: function() {\n var span;\n span = document.createElement('span');\n span.appendChild(document.createTextNode(' '));\n return span;\n },\n insertBefore: function(node, other) {\n var log;\n if (other) {\n return other.parentNode.insertBefore(node, other);\n } else {\n log = document.getElementById('log');\n return log.insertBefore(node, log.firstChild);\n }\n },\n insertAfter: function(node, other) {\n if (other.nextSibling) {\n return this.insertBefore(node, other.nextSibling);\n } else {\n return this.appendTo(node, other.parentNode);\n }\n },\n appendTo: function(node, other) {\n return other.appendChild(node);\n },\n addClass: function(classes, string) {\n if (classes != null ? classes.indexOf(string) : void 0) {\n return;\n }\n if (classes) {\n return \"\" + classes + \" \" + string;\n } else {\n return string;\n }\n }\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=log/renderer"); - +minispade.register('log', "(function() {(function() {\n\n this.Log = function() {\n this.autoCloseFold = true;\n this.listeners = [];\n this.renderer = new Log.Renderer;\n this.children = new Log.Nodes(this);\n this.parts = {};\n this.folds = new Log.Folds(this);\n return this;\n };\n\n Log.extend = function(one, other) {\n var name;\n for (name in other) {\n one[name] = other[name];\n }\n return one;\n };\n\n Log.extend(Log, {\n DEBUG: true,\n SLICE: 500,\n TIMEOUT: 25,\n FOLD: /fold:(start|end):([\\w_\\-\\.]+)/,\n create: function(options) {\n var listener, log, _i, _len, _ref;\n options || (options = {});\n log = new Log();\n if (options.limit) {\n log.listeners.push(log.limit = new Log.Limit(options.limit));\n }\n _ref = options.listeners || [];\n for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n listener = _ref[_i];\n log.listeners.push(listener);\n }\n return log;\n }\n });\nminispade.require('log/nodes');\n\n Log.prototype = Log.extend(new Log.Node, {\n set: function(num, string) {\n if (this.parts[num]) {\n return console.log(\"part \" + num + \" exists\");\n } else {\n this.parts[num] = true;\n return Log.Part.create(this, num, string);\n }\n },\n insert: function(data, pos) {\n this.trigger('insert', data, pos);\n return this.renderer.insert(data, pos);\n },\n remove: function(node) {\n this.trigger('remove', node);\n return this.renderer.remove(node);\n },\n hide: function(node) {\n this.trigger('hide', node);\n return this.renderer.hide(node);\n },\n trigger: function() {\n var args, ix, listener, _i, _len, _ref, _results;\n args = [this].concat(Array.prototype.slice.apply(arguments));\n _ref = this.listeners;\n _results = [];\n for (ix = _i = 0, _len = _ref.length; _i < _len; ix = ++_i) {\n listener = _ref[ix];\n _results.push(listener.notify.apply(listener, args));\n }\n return _results;\n }\n });\n\n Log.Listener = function() {};\n\n Log.extend(Log.Listener.prototype, {\n notify: function(log, event) {\n if (this[event]) {\n return this[event].apply(this, [log].concat(Array.prototype.slice.call(arguments, 2)));\n }\n }\n });\nminispade.require('log/folds');\nminispade.require('log/deansi');\nminispade.require('log/limit');\nminispade.require('log/renderer');\n\n}).call(this);\n\n})();\n//@ sourceURL=log");minispade.register('log/deansi', "(function() {(function() {\n\n Log.Deansi = {\n CLEAR_ANSI: /(?:\\033)(?:\\[0?c|\\[[0356]n|\\[7[lh]|\\[\\?25[lh]|\\(B|H|\\[(?:\\d+(;\\d+){,2})?G|\\[(?:[12])?[JK]|[DM])/gm,\n apply: function(string) {\n var nodes,\n _this = this;\n if (!string) {\n return [];\n }\n string = string.replace(this.CLEAR_ANSI, '');\n nodes = ansiparse(string).map(function(part) {\n return _this.node(part);\n });\n if (nodes.length === 0) {\n nodes.push(this.node({\n text: ''\n }));\n }\n return nodes;\n },\n node: function(part) {\n var classes, node;\n node = {\n type: 'span',\n text: part.text\n };\n if (classes = this.classes(part)) {\n node[\"class\"] = classes.join(' ');\n }\n return node;\n },\n classes: function(part) {\n var result;\n result = [];\n result = result.concat(this.colors(part));\n if (result.length > 0) {\n return result;\n }\n },\n colors: function(part) {\n var colors;\n colors = [];\n if (part.foreground) {\n colors.push(part.foreground);\n }\n if (part.background) {\n colors.push(\"bg-\" + part.background);\n }\n if (part.bold) {\n colors.push('bold');\n }\n if (part.italic) {\n colors.push('italic');\n }\n if (part.underline) {\n colors.push('underline');\n }\n return colors;\n },\n hidden: function(part) {\n if (part.text.match(/\\r/)) {\n part.text = part.text.replace(/^.*\\r/gm, '');\n return true;\n }\n }\n };\n\n}).call(this);\n\n})();\n//@ sourceURL=log/deansi");minispade.register('log/folds', "(function() {(function() {\n\n Log.Folds = function(log) {\n this.log = log;\n this.folds = {};\n return this;\n };\n\n Log.extend(Log.Folds.prototype, {\n add: function(data) {\n var fold, _base, _name;\n fold = (_base = this.folds)[_name = data.name] || (_base[_name] = new Log.Folds.Fold);\n fold.receive(data, {\n autoCloseFold: this.log.autoCloseFold\n });\n return fold.active;\n }\n });\n\n Log.Folds.Fold = function() {\n return this;\n };\n\n Log.extend(Log.Folds.Fold.prototype, {\n receive: function(data, options) {\n this[data.event] = data.id;\n if (this.start && this.end && !this.active) {\n return this.activate(options);\n }\n },\n activate: function(options) {\n var fragment, nextSibling, node, parentNode, toRemove, _i, _len, _ref;\n options || (options = {});\n if (Log.DEBUG) {\n console.log(\"F - activate \" + this.start);\n }\n toRemove = this.fold.parentNode;\n parentNode = toRemove.parentNode;\n nextSibling = toRemove.nextSibling;\n parentNode.removeChild(toRemove);\n fragment = document.createDocumentFragment();\n _ref = this.nodes;\n for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n node = _ref[_i];\n fragment.appendChild(node);\n }\n this.fold.appendChild(fragment);\n parentNode.insertBefore(toRemove, nextSibling);\n this.fold.setAttribute('class', this.classes(options['autoCloseFold']));\n return this.active = true;\n },\n classes: function(autoCloseFold) {\n var classes;\n classes = this.fold.getAttribute('class').split(' ');\n classes.push('fold');\n if (!autoCloseFold) {\n classes.push('open');\n }\n if (this.fold.childNodes.length > 2) {\n classes.push('active');\n }\n return classes.join(' ');\n }\n });\n\n Object.defineProperty(Log.Folds.Fold.prototype, 'fold', {\n get: function() {\n return this._fold || (this._fold = document.getElementById(this.start));\n }\n });\n\n Object.defineProperty(Log.Folds.Fold.prototype, 'nodes', {\n get: function() {\n var node, nodes;\n node = this.fold;\n nodes = [];\n while ((node = node.nextSibling) && node.id !== this.end) {\n nodes.push(node);\n }\n return nodes;\n }\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=log/folds");minispade.register('log/limit', "(function() {(function() {\n\n Log.Limit = function(max_lines) {\n this.max_lines = max_lines || 1000;\n return this;\n };\n\n Log.Limit.prototype = Log.extend(new Log.Listener, {\n count: 0,\n insert: function(log, node, pos) {\n if (node.type === 'paragraph' && !node.hidden) {\n return this.count += 1;\n }\n }\n });\n\n Object.defineProperty(Log.Limit.prototype, 'limited', {\n get: function() {\n return this.count >= this.max_lines;\n }\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=log/limit");minispade.register('log/nodes', "(function() {(function() {\n var newLineAtTheEndRegexp, newLineRegexp, rRegexp, removeCarriageReturns;\n\n Log.Node = function(id, num) {\n this.id = id;\n this.num = num;\n this.key = Log.Node.key(this.id);\n this.children = new Log.Nodes(this);\n return this;\n };\n\n Log.extend(Log.Node, {\n key: function(id) {\n if (id) {\n return id.split('-').map(function(i) {\n return '000000'.concat(i).slice(-6);\n }).join('');\n }\n }\n });\n\n Log.extend(Log.Node.prototype, {\n addChild: function(node) {\n return this.children.add(node);\n },\n remove: function() {\n this.log.remove(this.element);\n return this.parent.children.remove(this);\n }\n });\n\n Object.defineProperty(Log.Node.prototype, 'log', {\n get: function() {\n var _ref;\n return this._log || (this._log = ((_ref = this.parent) != null ? _ref.log : void 0) || this.parent);\n }\n });\n\n Object.defineProperty(Log.Node.prototype, 'firstChild', {\n get: function() {\n return this.children.first;\n }\n });\n\n Object.defineProperty(Log.Node.prototype, 'lastChild', {\n get: function() {\n return this.children.last;\n }\n });\n\n Log.Nodes = function(parent) {\n if (parent) {\n this.parent = parent;\n }\n this.items = [];\n this.index = {};\n return this;\n };\n\n Log.extend(Log.Nodes.prototype, {\n add: function(item) {\n var ix, next, prev, _ref, _ref1;\n ix = this.position(item) || 0;\n this.items.splice(ix, 0, item);\n if (this.parent) {\n item.parent = this.parent;\n }\n prev = function(item) {\n while (item && !item.children.last) {\n item = item.prev;\n }\n return item != null ? item.children.last : void 0;\n };\n next = function(item) {\n while (item && !item.children.first) {\n item = item.next;\n }\n return item != null ? item.children.first : void 0;\n };\n if (item.prev = this.items[ix - 1] || prev((_ref = this.parent) != null ? _ref.prev : void 0)) {\n item.prev.next = item;\n }\n if (item.next = this.items[ix + 1] || next((_ref1 = this.parent) != null ? _ref1.next : void 0)) {\n item.next.prev = item;\n }\n return item;\n },\n remove: function(item) {\n this.items.splice(this.items.indexOf(item), 1);\n if (item.next) {\n item.next.prev = item.prev;\n }\n if (item.prev) {\n item.prev.next = item.next;\n }\n if (this.items.length === 0) {\n return this.parent.remove();\n }\n },\n position: function(item) {\n var ix, _i, _ref;\n for (ix = _i = _ref = this.items.length - 1; _i >= 0; ix = _i += -1) {\n if (this.items[ix].key < item.key) {\n return ix + 1;\n }\n }\n },\n indexOf: function() {\n return this.items.indexOf.apply(this.items, arguments);\n },\n slice: function() {\n return this.items.slice.apply(this.items, arguments);\n },\n each: function(func) {\n return this.items.slice().forEach(func);\n },\n map: function(func) {\n return this.items.map(func);\n }\n });\n\n Object.defineProperty(Log.Nodes.prototype, 'first', {\n get: function() {\n return this.items[0];\n }\n });\n\n Object.defineProperty(Log.Nodes.prototype, 'last', {\n get: function() {\n return this.items[this.length - 1];\n }\n });\n\n Object.defineProperty(Log.Nodes.prototype, 'length', {\n get: function() {\n return this.items.length;\n }\n });\n\n Log.Part = function(id, num, string) {\n Log.Node.apply(this, arguments);\n this.string = string || '';\n this.string = this.string.replace(/\\033\\[1000D/gm, '\\r');\n this.string = this.string.replace(/\\r+\\n/gm, '\\n');\n this.strings = this.string.split(/^/gm) || [];\n this.slices = ((function() {\n var _results;\n _results = [];\n while (this.strings.length > 0) {\n _results.push(this.strings.splice(0, Log.SLICE));\n }\n return _results;\n }).call(this));\n return this;\n };\n\n Log.extend(Log.Part, {\n create: function(log, num, string) {\n var part;\n part = new Log.Part(num.toString(), num, string);\n log.addChild(part);\n return part.process(0, -1);\n }\n });\n\n Log.Part.prototype = Log.extend(new Log.Node, {\n remove: function() {},\n process: function(slice, num) {\n var node, span, spans, string, _i, _j, _len, _len1, _ref, _ref1, _ref2,\n _this = this;\n _ref = this.slices[slice] || [];\n for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n string = _ref[_i];\n if ((_ref1 = this.log.limit) != null ? _ref1.limited : void 0) {\n return;\n }\n spans = [];\n _ref2 = Log.Deansi.apply(string);\n for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) {\n node = _ref2[_j];\n span = Log.Span.create(this, \"\" + this.id + \"-\" + (num += 1), num, node.text, node[\"class\"]);\n span.render();\n spans.push(span);\n }\n if (spans[0] && spans[0].line.cr) {\n spans[0].line.clear();\n }\n }\n if (!(slice >= this.slices.length - 1)) {\n return setTimeout((function() {\n return _this.process(slice + 1, num);\n }), Log.TIMEOUT);\n }\n }\n });\n\n newLineAtTheEndRegexp = new RegExp(\"\\n$\");\n\n newLineRegexp = new RegExp(\"\\n\");\n\n rRegexp = new RegExp(\"\\r\");\n\n removeCarriageReturns = function(string) {\n var index;\n index = string.lastIndexOf(\"\\r\");\n if (index === -1) {\n return string;\n }\n return string.substr(index + 1);\n };\n\n Log.Span = function(id, num, text, classes) {\n var fold, _ref;\n Log.Node.apply(this, arguments);\n if (fold = text.match(Log.FOLD)) {\n this.fold = true;\n this.event = fold[1];\n this.text = this.name = fold[2];\n } else {\n this.text = text;\n this.text = removeCarriageReturns(this.text);\n this.text = this.text.replace(newLineAtTheEndRegexp, '');\n this.nl = !!((_ref = text[text.length - 1]) != null ? _ref.match(newLineRegexp) : void 0);\n this.cr = !!text.match(rRegexp);\n this[\"class\"] = this.cr && ['clears'] || classes;\n }\n return this;\n };\n\n Log.extend(Log.Span, {\n create: function(parent, id, num, text, classes) {\n var span;\n span = new Log.Span(id, num, text, classes);\n parent.addChild(span);\n return span;\n },\n render: function(parent, id, num, text, classes) {\n var span;\n span = this.create(parent, id, num, text, classes);\n return span.render();\n }\n });\n\n Log.Span.prototype = Log.extend(new Log.Node, {\n render: function() {\n var tail;\n if (!this.fold && this.prev && !this.prev.fold && !this.prev.nl) {\n if (Log.DEBUG) {\n console.log(\"S.1 insert \" + this.id + \" after prev \" + this.prev.id);\n }\n this.log.insert(this.data, {\n after: this.prev.element\n });\n this.line = this.prev.line;\n } else if (!this.fold && this.next && !this.next.fold) {\n if (Log.DEBUG) {\n console.log(\"S.2 insert \" + this.id + \" before next \" + this.next.id);\n }\n this.log.insert(this.data, {\n before: this.next.element\n });\n this.line = this.next.line;\n } else {\n this.line = Log.Line.create(this.log, [this]);\n this.line.render();\n }\n if (this.nl && (tail = this.tail).length > 0) {\n return this.split(tail);\n }\n },\n remove: function() {\n Log.Node.prototype.remove.apply(this);\n if (this.line) {\n return this.line.remove(this);\n }\n },\n split: function(spans) {\n var line, span, _i, _len;\n if (Log.DEBUG) {\n console.log(\"S.3 split [\" + (spans.map(function(span) {\n return span.id;\n }).join(', ')) + \"]\");\n }\n for (_i = 0, _len = spans.length; _i < _len; _i++) {\n span = spans[_i];\n this.log.remove(span.element);\n }\n line = Log.Line.create(this.log, spans);\n line.render();\n if (line.cr) {\n return line.clear();\n }\n },\n clear: function() {\n if (this.prev && this.isSibling(this.prev) && this.isSequence(this.prev)) {\n this.prev.clear();\n return this.prev.remove();\n }\n },\n isSequence: function(other) {\n return this.parent.num - other.parent.num === this.log.children.indexOf(this.parent) - this.log.children.indexOf(other.parent);\n },\n isSibling: function(other) {\n var _ref, _ref1;\n return ((_ref = this.element) != null ? _ref.parentNode : void 0) === ((_ref1 = other.element) != null ? _ref1.parentNode : void 0);\n },\n siblings: function(type) {\n var siblings, span;\n siblings = [];\n while ((span = (span || this)[type]) && this.isSibling(span)) {\n siblings.push(span);\n }\n return siblings;\n }\n });\n\n Object.defineProperty(Log.Span.prototype, 'data', {\n get: function() {\n return {\n id: this.id,\n type: 'span',\n text: this.text,\n \"class\": this[\"class\"]\n };\n }\n });\n\n Object.defineProperty(Log.Span.prototype, 'line', {\n get: function() {\n return this._line;\n },\n set: function(line) {\n if (this.line) {\n this.line.remove(this);\n }\n this._line = line;\n return this.line.add(this);\n }\n });\n\n Object.defineProperty(Log.Span.prototype, 'element', {\n get: function() {\n return document.getElementById(this.id);\n }\n });\n\n Object.defineProperty(Log.Span.prototype, 'head', {\n get: function() {\n return this.siblings('prev').reverse();\n }\n });\n\n Object.defineProperty(Log.Span.prototype, 'tail', {\n get: function() {\n return this.siblings('next');\n }\n });\n\n Log.Line = function(log) {\n this.log = log;\n this.spans = [];\n return this;\n };\n\n Log.extend(Log.Line, {\n create: function(log, spans) {\n var line, span, _i, _len;\n if ((span = spans[0]) && span.fold) {\n line = new Log.Fold(log, span.event, span.name);\n } else {\n line = new Log.Line(log);\n }\n for (_i = 0, _len = spans.length; _i < _len; _i++) {\n span = spans[_i];\n span.line = line;\n }\n return line;\n }\n });\n\n Log.extend(Log.Line.prototype, {\n add: function(span) {\n var ix;\n if (span.cr) {\n this.cr = true;\n }\n if (this.spans.indexOf(span) > -1) {\n\n } else if ((ix = this.spans.indexOf(span.prev)) > -1) {\n return this.spans.splice(ix + 1, 0, span);\n } else if ((ix = this.spans.indexOf(span.next)) > -1) {\n return this.spans.splice(ix, 0, span);\n } else {\n return this.spans.push(span);\n }\n },\n remove: function(span) {\n var ix;\n if ((ix = this.spans.indexOf(span)) > -1) {\n return this.spans.splice(ix, 1);\n }\n },\n render: function() {\n var fold;\n if ((fold = this.prev) && fold.event === 'start' && fold.active) {\n if (Log.DEBUG) {\n console.log(\"L.0 insert \" + this.id + \" into fold \" + fold.id);\n }\n fold = this.log.folds.folds[fold.name].fold;\n return this.element = this.log.insert(this.data, {\n into: fold\n });\n } else if (this.prev) {\n if (Log.DEBUG) {\n console.log(\"L.1 insert \" + this.spans[0].id + \" after prev \" + this.prev.id);\n }\n return this.element = this.log.insert(this.data, {\n after: this.prev.element\n });\n } else if (this.next) {\n if (Log.DEBUG) {\n console.log(\"L.2 insert \" + this.spans[0].id + \" before next \" + this.next.id);\n }\n return this.element = this.log.insert(this.data, {\n before: this.next.element\n });\n } else {\n if (Log.DEBUG) {\n console.log(\"L.3 insert \" + this.spans[0].id + \" into #log\");\n }\n return this.element = this.log.insert(this.data);\n }\n },\n clear: function() {\n var cr, _i, _len, _ref, _results;\n _ref = this.crs;\n _results = [];\n for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n cr = _ref[_i];\n _results.push(cr.clear());\n }\n return _results;\n }\n });\n\n Object.defineProperty(Log.Line.prototype, 'id', {\n get: function() {\n var _ref;\n return (_ref = this.spans[0]) != null ? _ref.id : void 0;\n }\n });\n\n Object.defineProperty(Log.Line.prototype, 'data', {\n get: function() {\n return {\n type: 'paragraph',\n nodes: this.nodes\n };\n }\n });\n\n Object.defineProperty(Log.Line.prototype, 'nodes', {\n get: function() {\n return this.spans.map(function(span) {\n return span.data;\n });\n }\n });\n\n Object.defineProperty(Log.Line.prototype, 'prev', {\n get: function() {\n var _ref;\n return (_ref = this.spans[0].prev) != null ? _ref.line : void 0;\n }\n });\n\n Object.defineProperty(Log.Line.prototype, 'next', {\n get: function() {\n var _ref;\n return (_ref = this.spans[this.spans.length - 1].next) != null ? _ref.line : void 0;\n }\n });\n\n Object.defineProperty(Log.Line.prototype, 'crs', {\n get: function() {\n return this.spans.filter(function(span) {\n return span.cr;\n });\n }\n });\n\n Log.Fold = function(log, event, name) {\n Log.Line.apply(this, arguments);\n this.fold = true;\n this.event = event;\n this.name = name;\n return this;\n };\n\n Log.Fold.prototype = Log.extend(new Log.Line, {\n render: function() {\n var element, _ref;\n if (this.prev) {\n if (Log.DEBUG) {\n console.log(\"F.1 insert \" + this.id + \" after prev \" + this.prev.id);\n }\n element = this.prev.element || this.prev.element.parentNode;\n this.element = this.log.insert(this.data, {\n after: element\n });\n } else if (this.next) {\n if (Log.DEBUG) {\n console.log(\"F.2 insert \" + this.id + \" before next \" + this.next.id);\n }\n element = this.next.element || this.next.element.parentNode;\n this.element = this.log.insert(this.data, {\n before: element\n });\n } else {\n if (Log.DEBUG) {\n console.log(\"F.3 insert \" + this.id);\n }\n this.element = this.log.insert(this.data);\n }\n if (this.span.next && ((_ref = this.span.prev) != null ? _ref.isSibling(this.span.next) : void 0)) {\n this.span.prev.split([this.span.next].concat(this.span.next.tail));\n }\n return this.active = this.log.folds.add(this.data);\n }\n });\n\n Object.defineProperty(Log.Fold.prototype, 'id', {\n get: function() {\n return \"fold-\" + this.event + \"-\" + this.name;\n }\n });\n\n Object.defineProperty(Log.Fold.prototype, 'span', {\n get: function() {\n return this.spans[0];\n }\n });\n\n Object.defineProperty(Log.Fold.prototype, 'data', {\n get: function() {\n return {\n type: 'fold',\n id: this.id,\n event: this.event,\n name: this.name\n };\n }\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=log/nodes");minispade.register('log/renderer', "(function() {(function() {\n\n Log.Renderer = function() {\n this.frag = document.createDocumentFragment();\n this.para = this.createParagraph();\n this.span = this.createSpan();\n this.text = document.createTextNode('');\n this.fold = this.createFold();\n return this;\n };\n\n Log.extend(Log.Renderer.prototype, {\n insert: function(data, pos) {\n var after, before, into, node;\n node = this.render(data);\n if (into = pos != null ? pos.into : void 0) {\n if (typeof into === 'String') {\n into = document.getElementById(pos != null ? pos.into : void 0);\n }\n this.appendTo(node, into);\n } else if (after = pos != null ? pos.after : void 0) {\n if (typeof after === 'String') {\n after = document.getElementById(pos);\n }\n this.insertAfter(node, after);\n } else if (before = pos != null ? pos.before : void 0) {\n if (typeof before === 'String') {\n before = document.getElementById(pos != null ? pos.before : void 0);\n }\n this.insertBefore(node, before);\n } else {\n this.insertBefore(node);\n }\n return node;\n },\n hide: function(node) {\n node.setAttribute('class', this.addClass(node.getAttribute('class'), 'hidden'));\n return node;\n },\n remove: function(node) {\n if (node) {\n node.parentNode.removeChild(node);\n }\n return node;\n },\n render: function(data) {\n var frag, node, type, _i, _len;\n if (data instanceof Array) {\n frag = this.frag.cloneNode(true);\n for (_i = 0, _len = data.length; _i < _len; _i++) {\n node = data[_i];\n node = this.render(node);\n if (node) {\n frag.appendChild(node);\n }\n }\n return frag;\n } else {\n data.type || (data.type = 'paragraph');\n type = data.type[0].toUpperCase() + data.type.slice(1);\n return this[\"render\" + type](data);\n }\n },\n renderParagraph: function(data) {\n var node, para, type, _i, _len, _ref;\n para = this.para.cloneNode(true);\n if (data.id) {\n para.setAttribute('id', data.id);\n }\n if (data.hidden) {\n para.setAttribute('style', 'display: none;');\n }\n _ref = data.nodes || [];\n for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n node = _ref[_i];\n type = node.type[0].toUpperCase() + node.type.slice(1);\n node = this[\"render\" + type](node);\n para.appendChild(node);\n }\n return para;\n },\n renderFold: function(data) {\n var fold;\n fold = this.fold.cloneNode(true);\n fold.setAttribute('id', data.id || (\"fold-\" + data.event + \"-\" + data.name));\n fold.setAttribute('class', \"fold-\" + data.event);\n if (data.event === 'start') {\n fold.lastChild.lastChild.nodeValue = data.name;\n } else {\n fold.removeChild(fold.lastChild);\n }\n return fold;\n },\n renderSpan: function(data) {\n var span;\n span = this.span.cloneNode(true);\n if (data.id) {\n span.setAttribute('id', data.id);\n }\n if (data[\"class\"]) {\n span.setAttribute('class', data[\"class\"]);\n }\n span.lastChild.nodeValue = data.text;\n return span;\n },\n renderText: function(data) {\n var text;\n text = this.text.cloneNode(true);\n text.nodeValue = data.text;\n return text;\n },\n createParagraph: function() {\n var para;\n para = document.createElement('p');\n para.appendChild(document.createElement('a'));\n return para;\n },\n createFold: function() {\n var fold;\n fold = document.createElement('div');\n fold.appendChild(this.createSpan());\n fold.lastChild.setAttribute('class', 'fold-name');\n return fold;\n },\n createSpan: function() {\n var span;\n span = document.createElement('span');\n span.appendChild(document.createTextNode(' '));\n return span;\n },\n insertBefore: function(node, other) {\n var log;\n if (other) {\n return other.parentNode.insertBefore(node, other);\n } else {\n log = document.getElementById('log');\n return log.insertBefore(node, log.firstChild);\n }\n },\n insertAfter: function(node, other) {\n if (other.nextSibling) {\n return this.insertBefore(node, other.nextSibling);\n } else {\n return this.appendTo(node, other.parentNode);\n }\n },\n appendTo: function(node, other) {\n return other.appendChild(node);\n },\n addClass: function(classes, string) {\n if (classes != null ? classes.indexOf(string) : void 0) {\n return;\n }\n if (classes) {\n return \"\" + classes + \" \" + string;\n } else {\n return string;\n }\n }\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=log/renderer"); \ No newline at end of file From 43e9af77d59e556fb68e9f9741b28a50b6a397c1 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Tue, 17 Jun 2014 00:50:01 +0200 Subject: [PATCH 02/15] Don't close folds when following logs --- assets/scripts/app/tailing.coffee | 3 +++ assets/scripts/app/views/log.coffee | 1 + 2 files changed, 4 insertions(+) diff --git a/assets/scripts/app/tailing.coffee b/assets/scripts/app/tailing.coffee index d85ae12f..39f10452 100644 --- a/assets/scripts/app/tailing.coffee +++ b/assets/scripts/app/tailing.coffee @@ -60,6 +60,9 @@ class @Travis.Tailing @tail().addClass('active') @run() + isActive: -> + @tail().hasClass('active') + stop: -> @tail().removeClass('active') diff --git a/assets/scripts/app/views/log.coffee b/assets/scripts/app/views/log.coffee index 72557b37..e7cc47db 100644 --- a/assets/scripts/app/views/log.coffee +++ b/assets/scripts/app/views/log.coffee @@ -76,6 +76,7 @@ Travis.reopen toggleTailing: -> Travis.tailing.toggle() + @engine.autoCloseFold = !Travis.tailing.isActive() event.preventDefault() actions: From 00ccb07a4965edc08664a888bfc24e4964601d06 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Tue, 17 Jun 2014 16:39:21 +0200 Subject: [PATCH 03/15] Fix sync button --- assets/scripts/app/controllers/account.coffee | 7 +++++++ assets/scripts/app/controllers/profile.coffee | 3 --- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/assets/scripts/app/controllers/account.coffee b/assets/scripts/app/controllers/account.coffee index d8cc6838..36fe2bae 100644 --- a/assets/scripts/app/controllers/account.coffee +++ b/assets/scripts/app/controllers/account.coffee @@ -1,5 +1,7 @@ Travis.AccountController = Ember.ObjectController.extend allHooks: [] + needs: ['currentUser'] + userBinding: 'controllers.currentUser' init: -> @_super.apply this, arguments @@ -33,3 +35,8 @@ Travis.AccountController = Ember.ObjectController.extend showPublicReposHint: (-> Travis.config.show_repos_hint == 'public' ) .property() + + actions: + sync: -> + @get('user').sync() + diff --git a/assets/scripts/app/controllers/profile.coffee b/assets/scripts/app/controllers/profile.coffee index 65a52dce..a2498206 100644 --- a/assets/scripts/app/controllers/profile.coffee +++ b/assets/scripts/app/controllers/profile.coffee @@ -5,9 +5,6 @@ Travis.ProfileController = Travis.Controller.extend userBinding: 'controllers.currentUser' accountBinding: 'controllers.account' - sync: -> - @get('user').sync() - activate: (action, params) -> this["view#{$.camelize(action)}"]() From 2fd1af29ec2facd3d20c2c1e9d4d397dccd47774 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Wed, 18 Jun 2014 15:36:23 +0200 Subject: [PATCH 04/15] Unfold lines before trying to scroll (closes travis-ci/travis-ci#1501) --- assets/scripts/app/views/log.coffee | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/assets/scripts/app/views/log.coffee b/assets/scripts/app/views/log.coffee index e7cc47db..61e9e3cd 100644 --- a/assets/scripts/app/views/log.coffee +++ b/assets/scripts/app/views/log.coffee @@ -46,12 +46,16 @@ Travis.reopen createEngine: -> console.log 'log view: create engine' if Log.DEBUG - @scroll = new Log.Scroll + @scroll = new Log.Scroll beforeScroll: => + @unfoldHighlight() @engine = Log.create(limit: Log.LIMIT, listeners: [@scroll]) @logFolder = new Travis.LogFolder(@$().find('#log')) @lineSelector = new Travis.LinesSelector(@$().find('#log'), @scroll, @logFolder) @observeParts() + unfoldHighlight: -> + @lineSelector.unfoldLines() + observeParts: -> parts = @get('log.parts') parts.addArrayObserver(@, didChange: 'partsDidChange', willChange: 'noop') @@ -85,7 +89,10 @@ Travis.reopen noop: -> # TODO required? -Log.Scroll = -> +Log.Scroll = (options) -> + options ||= {} + @beforeScroll = options.beforeScroll + this Log.Scroll.prototype = $.extend new Log.Listener, insert: (log, data, pos) -> @tryScroll() if @numbers @@ -93,6 +100,8 @@ Log.Scroll.prototype = $.extend new Log.Listener, tryScroll: -> if element = $("#log p:visible.highlight:first") + if @beforeScroll + @beforeScroll() $('#main').scrollTop(0) $('html, body').scrollTop(element.offset()?.top - (window.innerHeight / 3)) # weird, html works in chrome, body in firefox From a64c800423abee269ddda808ef210cb2e0cc2970 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Thu, 19 Jun 2014 14:32:48 +0200 Subject: [PATCH 05/15] Bring back refreshUserData when setting user data User data needs to be refreshed on sign in, otherwise we don't have fresh data regarding isSyncing property and other fields which can change between refreshing page. --- assets/scripts/app/auth.coffee | 1 + 1 file changed, 1 insertion(+) diff --git a/assets/scripts/app/auth.coffee b/assets/scripts/app/auth.coffee index bbd15705..da574729 100644 --- a/assets/scripts/app/auth.coffee +++ b/assets/scripts/app/auth.coffee @@ -64,6 +64,7 @@ window.Auth = Ember.Object.extend @set('state', 'signed-in') Travis.trigger('user:signed_in', data.user) @sendToApp('afterSignIn') + @refreshUserData(data.user) refreshUserData: (user) -> Travis.ajax.get "/users/#{user.id}", (data) => From e0865756d11c1b64b12ae7bf05f7521543f07f72 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Thu, 19 Jun 2014 14:39:12 +0200 Subject: [PATCH 06/15] Start running poll whenever isSyncing changes This ensures that timing is not important, ie. if user data is refreshed later, we can still start running poll() if user is syncing. --- assets/scripts/app/models/user.coffee | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/assets/scripts/app/models/user.coffee b/assets/scripts/app/models/user.coffee index 8f57f53f..bd2468a3 100644 --- a/assets/scripts/app/models/user.coffee +++ b/assets/scripts/app/models/user.coffee @@ -20,11 +20,10 @@ require 'travis/model' value ).property('login', '_name') - init: -> - @_super() - + isSyncingDidChange: (-> Ember.run.next this, -> @poll() if @get('isSyncing') + ).observes('isSyncing') urlGithub: (-> "https://github.com/#{@get('login')}" @@ -66,7 +65,6 @@ require 'travis/model' self = this Travis.ajax.post('/users/sync', {}, -> self.setWithSession('isSyncing', true) - self.poll() ) poll: -> From e045ab7481f2a0d5964a1b0aae27d71ffcfe54a6 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Fri, 20 Jun 2014 15:47:37 +0200 Subject: [PATCH 07/15] Remove check of model state in DurationCalculation We no longer need this check, because it was only relevant with Ember Data. Additionally it was a cause of a travis-ci/travis-ci#1992, because of wrong syntax: unless someFunction false or true will only check for a result of someFunction with an argument being the result of `or` expression. --- assets/scripts/app/models/extensions.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/scripts/app/models/extensions.coffee b/assets/scripts/app/models/extensions.coffee index 013da4f5..c94679b9 100644 --- a/assets/scripts/app/models/extensions.coffee +++ b/assets/scripts/app/models/extensions.coffee @@ -7,6 +7,6 @@ Travis.DurationCalculations = Ember.Mixin.create ).property('_duration', 'finishedAt', 'startedAt') updateTimes: -> - unless ['rootState.loaded.reloading', 'rootState.loading'].contains @get('stateManager.currentState.path') or @get('isFinished') + unless @get('isFinished') @notifyPropertyChange '_duration' @notifyPropertyChange 'finished_at' From 6cb866408dfd0f3349e0dab8bb47219366b0a47e Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Fri, 20 Jun 2014 16:03:41 +0200 Subject: [PATCH 08/15] Don't return finishedAt, startedAt, duration for not started jobs/builds --- assets/scripts/app/models/build.coffee | 18 ++++++++++++++++-- assets/scripts/app/models/extensions.coffee | 4 +++- assets/scripts/app/models/job.coffee | 18 ++++++++++++++++-- 3 files changed, 35 insertions(+), 5 deletions(-) diff --git a/assets/scripts/app/models/build.coffee b/assets/scripts/app/models/build.coffee index ce24bd8f..35571212 100644 --- a/assets/scripts/app/models/build.coffee +++ b/assets/scripts/app/models/build.coffee @@ -10,8 +10,8 @@ require 'travis/model' message: Ember.attr('string') _duration: Ember.attr(Number, key: 'duration') _config: Ember.attr('object', key: 'config') - startedAt: Ember.attr('string') - finishedAt: Ember.attr('string') + _startedAt: Ember.attr('string', key: 'started_at') + _finishedAt: Ember.attr('string', key: 'finished_at') pullRequest: Ember.attr('boolean') pullRequestTitle: Ember.attr('string') pullRequestNumber: Ember.attr(Number) @@ -36,6 +36,20 @@ require 'travis/model' @get('state') in ['passed', 'failed', 'errored', 'canceled'] ).property('state') + notStarted: (-> + @get('state') in ['queued', 'created'] + ).property('state') + + startedAt: (-> + unless @get('notStarted') + @get('_startedAt') + ).property('_startedAt') + + finishedAt: (-> + unless @get('notStarted') + @get('_finishedAt') + ).property('_finishedAt') + requiredJobs: (-> @get('jobs').filter (data) -> !data.get('allowFailure') ).property('jobs.@each.allowFailure') diff --git a/assets/scripts/app/models/extensions.coffee b/assets/scripts/app/models/extensions.coffee index c94679b9..e265ede8 100644 --- a/assets/scripts/app/models/extensions.coffee +++ b/assets/scripts/app/models/extensions.coffee @@ -1,6 +1,8 @@ Travis.DurationCalculations = Ember.Mixin.create duration: (-> - if duration = @get('_duration') + if @get('notStarted') + null + else if duration = @get('_duration') duration else Travis.Helpers.durationFrom(@get('startedAt'), @get('finishedAt')) diff --git a/assets/scripts/app/models/job.coffee b/assets/scripts/app/models/job.coffee index fe5bd4ce..515033d5 100644 --- a/assets/scripts/app/models/job.coffee +++ b/assets/scripts/app/models/job.coffee @@ -9,8 +9,8 @@ require 'travis/model' queue: Ember.attr('string') state: Ember.attr('string') number: Ember.attr('string') - startedAt: Ember.attr('string') - finishedAt: Ember.attr('string') + _startedAt: Ember.attr('string', key: 'started_at') + _finishedAt: Ember.attr('string', key: 'finished_at') allowFailure: Ember.attr('boolean') repositorySlug: Ember.attr('string') @@ -27,6 +27,16 @@ require 'travis/model' Travis.Log.create(job: this) ).property() + startedAt: (-> + unless @get('notStarted') + @get('_startedAt') + ).property('_startedAt') + + finishedAt: (-> + unless @get('notStarted') + @get('_finishedAt') + ).property('_finishedAt') + repoSlug: (-> @get('repositorySlug') ).property('repositorySlug') @@ -39,6 +49,10 @@ require 'travis/model' @get('state') in ['passed', 'failed', 'errored', 'canceled'] ).property('state') + notStarted: (-> + @get('state') in ['queued', 'created'] + ).property('state') + clearLog: -> # This is needed if we don't want to fetch log just to clear it if @get('isLogAccessed') From 1238caf3186cc430aced02e58820910284dae669 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Mon, 23 Jun 2014 15:15:40 +0200 Subject: [PATCH 09/15] Fix signing out on failed try to update user data A while ago I introduced a change to auth code which signs out user on failed try to get user data. The problem with it was it signed out on all kind of errors, like network error. I changed the code to log out on 401 status, but I haven't tested it properly, we actually return 403 on unauthenticated queries for user data. --- assets/scripts/app/auth.coffee | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/scripts/app/auth.coffee b/assets/scripts/app/auth.coffee index da574729..43b88517 100644 --- a/assets/scripts/app/auth.coffee +++ b/assets/scripts/app/auth.coffee @@ -74,8 +74,8 @@ window.Auth = Ember.Object.extend data.user.token = user.token @storeData(data, Travis.sessionStorage) @storeData(data, Travis.storage) - , (data, status, xhr) => - @signOut() if xhr.status == 401 + , (status, xhr) => + @signOut() if status == 403 signedIn: (-> @get('state') == 'signed-in' From 3d45696f9a0e4b360dc75341c8a50a96f5220a41 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Thu, 26 Jun 2014 13:54:08 +0200 Subject: [PATCH 10/15] Extract commit data on all build events if it's available --- assets/scripts/app/app.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/scripts/app/app.coffee b/assets/scripts/app/app.coffee index c4608eb1..87fe5a2a 100644 --- a/assets/scripts/app/app.coffee +++ b/assets/scripts/app/app.coffee @@ -55,7 +55,7 @@ unless window.TravisApplication type = Ember.get(Travis, 'mappings')[name] - if event == 'build:started' && data.build.commit + if name == 'build' && data.build.commit # TODO: commit should be a sideload record on build, not mixed with it build = data.build commit = { From 412baaa79c292920ebba3c0a3109408b26eeaf0f Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Thu, 26 Jun 2014 18:01:34 +0200 Subject: [PATCH 11/15] Specify proper dependencies in job's and build's properties --- assets/scripts/app/models/build.coffee | 4 ++-- assets/scripts/app/models/job.coffee | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/assets/scripts/app/models/build.coffee b/assets/scripts/app/models/build.coffee index 35571212..a5c0a78c 100644 --- a/assets/scripts/app/models/build.coffee +++ b/assets/scripts/app/models/build.coffee @@ -43,11 +43,11 @@ require 'travis/model' startedAt: (-> unless @get('notStarted') @get('_startedAt') - ).property('_startedAt') + ).property('_startedAt', 'notStarted') finishedAt: (-> unless @get('notStarted') - @get('_finishedAt') + @get('_finishedAt', 'notStarted') ).property('_finishedAt') requiredJobs: (-> diff --git a/assets/scripts/app/models/job.coffee b/assets/scripts/app/models/job.coffee index 515033d5..4a90d3b0 100644 --- a/assets/scripts/app/models/job.coffee +++ b/assets/scripts/app/models/job.coffee @@ -30,12 +30,12 @@ require 'travis/model' startedAt: (-> unless @get('notStarted') @get('_startedAt') - ).property('_startedAt') + ).property('_startedAt', 'notStarted') finishedAt: (-> unless @get('notStarted') @get('_finishedAt') - ).property('_finishedAt') + ).property('_finishedAt', 'notStarted') repoSlug: (-> @get('repositorySlug') From 23035306c7aff503e5841daf307d40fd389edab0 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Thu, 26 Jun 2014 18:09:28 +0200 Subject: [PATCH 12/15] Oh gaaawwd, really fix the dependencies --- assets/scripts/app/models/build.coffee | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/scripts/app/models/build.coffee b/assets/scripts/app/models/build.coffee index a5c0a78c..21ba175e 100644 --- a/assets/scripts/app/models/build.coffee +++ b/assets/scripts/app/models/build.coffee @@ -47,8 +47,8 @@ require 'travis/model' finishedAt: (-> unless @get('notStarted') - @get('_finishedAt', 'notStarted') - ).property('_finishedAt') + @get('_finishedAt') + ).property('_finishedAt', 'notStarted') requiredJobs: (-> @get('jobs').filter (data) -> !data.get('allowFailure') From ef4b827d3cfd79a8c982e0881b5bb676f6a687da Mon Sep 17 00:00:00 2001 From: Justine Arreche Date: Fri, 4 Jul 2014 10:53:15 +0200 Subject: [PATCH 13/15] styling switches --- assets/styles/components/travis-switch.sass | 19 ++++++++++++------- assets/styles/main/annotations.sass | 2 +- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/assets/styles/components/travis-switch.sass b/assets/styles/components/travis-switch.sass index 9cde88e8..65b3a753 100644 --- a/assets/styles/components/travis-switch.sass +++ b/assets/styles/components/travis-switch.sass @@ -7,12 +7,14 @@ float: left width: 60px height: 18px - margin: 0 10px 0 15px - padding: 0 10px 0 0 - border: 1px solid #bdbdbd + margin: 20px 0 50px 0 + padding: 5px 18px 5px 18px + background-color: #607A83 + border: 1px solid #E3E1E1 + border-radius: 4px line-height: 19px font-size: 11px - color: #999 + color: #999999 cursor: pointer text-align: right &:before @@ -27,11 +29,14 @@ .travis-switch.active width: 56px - padding: 0 0 0 14px - background: #40454f + padding: 5px 18px 5px 18px + background: #f5f5f5 border: 1px solid #bdbdbd - color: #fff + border-radius: 3px + color: #ffffff + font-weight: 600 text-align: left &:before left: auto right: -1px + width: 30px \ No newline at end of file diff --git a/assets/styles/main/annotations.sass b/assets/styles/main/annotations.sass index 9efbb002..7fd355e7 100644 --- a/assets/styles/main/annotations.sass +++ b/assets/styles/main/annotations.sass @@ -1,7 +1,7 @@ @import "_mixins/all" #annotations - margin: 0 0 0 12px + margin: 8px 0 25px 12px padding: 12px 0 0 0 @include clearfix From 7eb0b2b43644bed07d26408ae7dd2161969732d1 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Fri, 4 Jul 2014 11:22:05 +0200 Subject: [PATCH 14/15] Show both labels on travis-switch --- assets/scripts/app/templates/components/travis-switch.hbs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/assets/scripts/app/templates/components/travis-switch.hbs b/assets/scripts/app/templates/components/travis-switch.hbs index 18617602..dbed063c 100644 --- a/assets/scripts/app/templates/components/travis-switch.hbs +++ b/assets/scripts/app/templates/components/travis-switch.hbs @@ -1,5 +1,6 @@ -{{#if _active}} + ON -{{else}} + + OFF -{{/if}} + From 570709d8dc8d9420a59fb1aab49be9a623d8029a Mon Sep 17 00:00:00 2001 From: Justine Arreche Date: Fri, 11 Jul 2014 17:25:23 +0200 Subject: [PATCH 15/15] complete fix of all switch updated styles --- assets/styles/components/travis-switch.sass | 42 +++++++++++++++------ 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/assets/styles/components/travis-switch.sass b/assets/styles/components/travis-switch.sass index 65b3a753..ccf1f16a 100644 --- a/assets/styles/components/travis-switch.sass +++ b/assets/styles/components/travis-switch.sass @@ -1,6 +1,12 @@ .settings-row margin-top: 20px +a.travis-switch + margin: 0 10px 0 0 + +p.settings-row + line-height: 30px + .travis-switch position: relative display: inline-block @@ -9,7 +15,7 @@ height: 18px margin: 20px 0 50px 0 padding: 5px 18px 5px 18px - background-color: #607A83 + background-color: #F5F5F5 border: 1px solid #E3E1E1 border-radius: 4px line-height: 19px @@ -20,23 +26,35 @@ &:before content: "" position: absolute - top: -1px - left: -1px - width: 28px - height: 18px + top: 1px + left: 1px + width: 42px + height: 24px background: #e9e9e7 - border: 1px solid #bdbdbd + border: 1px solid #d7d4d4 + border-radius: 2px .travis-switch.active - width: 56px + width: 60px padding: 5px 18px 5px 18px - background: #f5f5f5 - border: 1px solid #bdbdbd - border-radius: 3px + background-color: #607A83 + border-radius: 4px color: #ffffff font-weight: 600 text-align: left &:before left: auto - right: -1px - width: 30px \ No newline at end of file + right: 1px + width: 42px + height: 24px + border: 1px solid #9cafb5 + +span.on + background-color: #607A83 + color: #fff + font-weight: 800 + border-radius: 3px + float: left + +span.off + float: right