From c0a4fed8365b5519b815f4555f70b91838170744 Mon Sep 17 00:00:00 2001 From: Sven Fuchs Date: Wed, 13 Mar 2013 01:16:55 +0100 Subject: [PATCH] use travis-web-log/sf-dom --- assets/scripts/app/views/log.coffee | 274 +++++++--------------------- assets/scripts/vendor/log.js | 2 +- assets/styles/app/misc.sass | 3 + 3 files changed, 71 insertions(+), 208 deletions(-) diff --git a/assets/scripts/app/views/log.coffee b/assets/scripts/app/views/log.coffee index 1fab0507..4b231d9a 100644 --- a/assets/scripts/app/views/log.coffee +++ b/assets/scripts/app/views/log.coffee @@ -3,170 +3,12 @@ require 'travis/ordered_log' Log.DEBUG = true -Travis.UnorderedLogEngineMixin = Ember.Mixin.create - setupEngine: -> - console.log 'log view: create engine' if Log.DEBUG - @limit = new Log.Limit - @scroll = new Log.Scroll - @engine = Log.create(listeners: [new Log.FragmentRenderer, new Log.Folds, @scroll]) - @observeParts() - @numberLineOnHover() - - destroyEngine: -> - parts = @get('log.parts') - parts.removeArrayObserver(@, didChange: 'partsDidChange', willChange: 'noop') - - observeParts: -> - parts = @get('log.parts') - parts.addArrayObserver(@, didChange: 'partsDidChange', willChange: 'noop') - parts = parts.slice(0) - @partsDidChange(parts, 0, null, parts.length) - - partsDidChange: (parts, start, _, added) -> - console.log 'log view: parts did change' if Log.DEBUG - for part, i in parts.slice(start, start + added) - # console.log "limit in log view: #{@get('limited')}" - break if @get('limited') - @engine.set(part.number, part.content) - @propertyDidChange('limited') - - lineNumberDidChange: (-> - @scroll.set(number) if !@get('isDestroyed') && number = @get('controller.lineNumber') - ).observes('controller.lineNumber') - - limited: (-> - @limit && @limit.limited - ).property() - -Travis.OrderedLogEngineMixin = Ember.Mixin.create - setupEngine: -> - @set('logManager', Travis.OrderedLog.create(target: this)) - - @get('logManager').append @get('log.parts') - - @get('log.parts').addArrayObserver this, - didChange: 'partsDidChange' - willChange: 'noop' - - destroyEngine: (view) -> - @get('logManager').destroy() - @get('log.parts').removeArrayObserver this, - didChange: 'partsDidChange' - willChange: 'noop' - - partsDidChange: (parts, index, removedCount, addedCount) -> - addedParts = parts.slice(index, index + addedCount) - @get('logManager').append addedParts - - lineNumberDidChange: (-> - if number = @get('controller.lineNumber') - @tryScrollingToHashLineNumber(number) - ).observes('controller.lineNumber') - - scrollTo: (id) -> - # and this is even more weird, when changing hash in URL in firefox - # to other value, for example #L10, it actually scrolls just #main - # element... this is probably some CSS issue, I don't have time to - # investigate at the moment - # TODO: fix this - $('#main').scrollTop 0 - - # weird, html works in chrome, body in firefox - $('html,body').scrollTop $(id).offset().top - - @set 'controller.lineNumber', null - - tryScrollingToHashLineNumber: (number) -> - id = "#L#{number}" - checker = => - return if @get('isDestroyed') - - if $(id).length - @scrollTo(id) - else - setTimeout checker, 100 - - checker() - - appendLog: (payloads) -> - url = @get('logUrl') - - leftOut = [] - cut = false - fragment = document.createDocumentFragment() - - # TODO: refactor this loop, it's getting messy - for payload in payloads - line = payload.content - number = payload.number - - if payload.logWasCut - cut = true - else - unless payload.append - pathWithNumber = "#{url}#L#{number}" - p = document.createElement('p') - p.innerHTML = "#{line}" - line = p - - if payload.fold && !payload.foldContinuation - div = document.createElement('div') - div.appendChild line - div.className = "fold #{payload.fold} show-first-line" - line = div - - if payload.replace - if link = fragment.querySelector("#L#{number}") - link.parentElement.innerHTML = line.innerHTML - else - this.$("#L#{number}").parent().replaceWith line - else if payload.append - if link = fragment.querySelector("#L#{number}") - link.parentElement.innerHTML += line - else - this.$("#L#{number}").parent().append line - else if payload.foldContinuation - folds = fragment.querySelectorAll(".fold.#{payload.fold}") - if fold = folds[folds.length - 1] - fold.appendChild line - else - this.$("#log .fold.#{payload.fold}:last").append line - else - fragment.appendChild(line) - - if payload.openFold - folds = fragment.querySelectorAll(".fold.#{payload.openFold}") - if fold = folds[folds.length - 1] - fold = $(fold) - else - fold = this.$(".fold.#{payload.openFold}:last") - - fold.removeClass('show-first-line').addClass('open') - - if payload.foldEnd - folds = fragment.querySelectorAll(".fold.#{payload.fold}") - if fold = folds[folds.length - 1] - fold = $(fold) - else - fold = this.$(".fold.#{payload.fold}:last") - - fold.removeClass('show-first-line') - - this.$('#log')[0].appendChild fragment - if cut - url = Travis.Urls.plainTextLog(@get('log.id')) - this.$("#log").append $("

Log was too long to display. Download the the raw version to get the full log.

") - Travis.reopen LogView: Travis.View.extend templateName: 'jobs/log' logBinding: 'job.log' contextBinding: 'job' - didInsertElement: -> - job = @get('job') - job.subscribe() if job && !job.get('isFinished') - willDestroyElement: -> job = @get('job') job.unsubscribe() if job @@ -180,12 +22,13 @@ Travis.reopen didInsertElement: -> console.log 'log view: did insert' if Log.DEBUG @_super.apply this, arguments - @setupEngine() + @createEngine() @lineNumberDidChange() willDestroyElement: -> console.log 'log view: will destroy' if Log.DEBUG - @destroyEngine() + parts = @get('log.parts') + parts.removeArrayObserver(@, didChange: 'partsDidChange', willChange: 'noop') versionDidChange: (-> @rerender() if @get('inDOM') @@ -196,6 +39,36 @@ Travis.reopen @rerender() if @get('inDOM') ).observes('log') + createEngine: -> + console.log 'log view: create engine' if Log.DEBUG + # @limit = new Log.Limit + # @scroll = new Log.Scroll + # @engine = Log.create(listeners: [new Log.FragmentRenderer, new Log.Folds, @scroll]) + @engine = new Log + @observeParts() + @numberLineOnHover() + + observeParts: -> + parts = @get('log.parts') + parts.addArrayObserver(@, didChange: 'partsDidChange', willChange: 'noop') + parts = parts.slice(0) + @partsDidChange(parts, 0, null, parts.length) + + partsDidChange: (parts, start, _, added) -> + console.log 'log view: parts did change' if Log.DEBUG + for part, i in parts.slice(start, start + added) + # console.log "limit in log view: #{@get('limited')}" + break if @get('limited') + @engine.set(part.number, part.content) + @propertyDidChange('limited') + + lineNumberDidChange: (-> + # @scroll.set(number) if !@get('isDestroyed') && number = @get('controller.lineNumber') + ).observes('controller.lineNumber') + + limited: (-> + @limit && @limit.limited + ).property() plainTextLogUrl: (-> Travis.Urls.plainTextLog(id) if id = @get('log.job.id') @@ -218,55 +91,42 @@ Travis.reopen target = $(event.target) target.closest('.fold').toggleClass('open') - logUrl: (-> - if item = @get('controller.currentItem') - if repo = item.get('repo') - name = if item.constructor == Travis.Build - 'build' - else - 'job' - - Travis.__container__.lookup('router:main').generate(name, repo, item) - ).property('controller.currentItem.repo', 'controller.currentItem') - lineNumberClicked: (number) -> - path = @get('logUrl') + "#L#{number}" - window.history.replaceState({ path: path }, null, path); + window.history.pushState(null, null, "#{window.location.pathname}#L#{number}"); @set('controller.lineNumber', number) noop: -> # TODO required? - }) -Log.Scroll = -> -Log.Scroll.prototype = $.extend new Log.Listener, - set: (number) -> - return unless number - @number = number - @tryScroll() - - insert: (log, line, pos) -> - @tryScroll() if @number - true - - tryScroll: -> - if element = $("#log p:visible")[@number - 1] - $('#main').scrollTop(0) - $('html, body').scrollTop($(element).offset()?.top) # weird, html works in chrome, body in firefox - @highlight(element) - @number = undefined - - highlight: (element) -> - $('#log p.highlight').removeClass('highlight') - $(element).addClass('highlight') - -Log.Logger = -> -Log.Logger.prototype = $.extend new Log.Listener, - receive: (log, num, string) -> - @log("rcv #{num} #{JSON.stringify(string)}") - true - insert: (log, element, pos) -> - @log("ins #{element.id}, #{if pos.before then 'before' else 'after'}: #{pos.before || pos.after || '?'}, #{JSON.stringify(element)}") - remove: (log, element) -> - @log("rem #{element.id}") - log: (line) -> - console.log(line) +# Log.Scroll = -> +# Log.Scroll.prototype = $.extend new Log.Listener, +# set: (number) -> +# return unless number +# @number = number +# @tryScroll() +# +# insert: (log, line, pos) -> +# @tryScroll() if @number +# true +# +# tryScroll: -> +# if element = $("#log p:visible")[@number - 1] +# $('#main').scrollTop(0) +# $('html, body').scrollTop($(element).offset()?.top) # weird, html works in chrome, body in firefox +# @highlight(element) +# @number = undefined +# +# highlight: (element) -> +# $('#log p.highlight').removeClass('highlight') +# $(element).addClass('highlight') +# +# Log.Logger = -> +# Log.Logger.prototype = $.extend new Log.Listener, +# receive: (log, num, string) -> +# @log("rcv #{num} #{JSON.stringify(string)}") +# true +# insert: (log, element, pos) -> +# @log("ins #{element.id}, #{if pos.before then 'before' else 'after'}: #{pos.before || pos.after || '?'}, #{JSON.stringify(element)}") +# remove: (log, element) -> +# @log("rem #{element.id}") +# log: (line) -> +# console.log(line) diff --git a/assets/scripts/vendor/log.js b/assets/scripts/vendor/log.js index 87969c7b..6d1b733e 100644 --- a/assets/scripts/vendor/log.js +++ b/assets/scripts/vendor/log.js @@ -1 +1 @@ -minispade.register('log', "(function() {(function() {\n\n this.Log = function(engine) {\n this.listeners = [];\n this.engine = new (engine || Log.Dom)(this);\n return this;\n };\n\n $.extend(Log, {\n DEBUG: true,\n create: function(options) {\n var listener, log, _i, _len, _ref;\n log = new Log(options.engine);\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 });\n\n $.extend(Log.prototype, {\n trigger: function() {\n var args, element, event, ix, listener, result, _i, _len, _ref;\n args = Array.prototype.slice.apply(arguments);\n event = args[0];\n _ref = this.listeners;\n for (ix = _i = 0, _len = _ref.length; _i < _len; ix = ++_i) {\n listener = _ref[ix];\n result = listener.notify.apply(listener, [this].concat(args));\n if (result != null ? result.hasChildNodes : void 0) {\n element = result;\n }\n }\n return element;\n },\n set: function(num, string) {\n return this.engine.set(num, string);\n }\n });\n\n Log.Listener = function() {};\n\n $.extend(Log.Listener.prototype, {\n notify: function(log, event, num) {\n if (this[event]) {\n return this[event].apply(this, [log].concat(Array.prototype.slice.call(arguments, 2)));\n }\n }\n });\nminispade.require('log/deansi');\nminispade.require('log/engine/dom');\nminispade.require('log/folds');\nminispade.require('log/instrument');\nminispade.require('log/limit');\nminispade.require('log/renderer/fragment');\n\n}).call(this);\n\n})();\n//@ sourceURL=log");minispade.register('log/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/buffer");minispade.register('log/deansi', "(function() {(function() {\n\n Log.Deansi = {\n apply: function(string) {\n var nodes,\n _this = this;\n string = string.replace(/\\e\\[K/g, '');\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;\n if (classes = this.classes(part)) {\n return {\n type: 'span',\n \"class\": classes,\n text: part.text\n };\n } else {\n return {\n type: 'span',\n text: part.text\n };\n }\n },\n classes: function(part) {\n var result;\n result = [];\n if (part.foreground) {\n result.push(part.foreground);\n }\n if (part.background) {\n result.push(\"bg-\" + part.background);\n }\n if (part.bold) {\n result.push('bold');\n }\n if (part.italic) {\n result.push('italic');\n }\n if (result.length > 0) {\n return result;\n }\n }\n };\n\n}).call(this);\n\n})();\n//@ sourceURL=log/deansi");minispade.register('log/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/engine/chunks");minispade.register('log/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 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 return this.nodes.splice(node.num, 1);\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.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.Line(part, num, string);\n }\n },\n reinsert: function(nodes) {\n var node, _i, _j, _len, _len1, _results;\n for (_i = 0, _len = nodes.length; _i < _len; _i++) {\n node = nodes[_i];\n node.remove();\n }\n _results = [];\n for (_j = 0, _len1 = nodes.length; _j < _len1; _j++) {\n node = nodes[_j];\n _results.push(node.part.nodes.insert(node));\n }\n return _results;\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 var next, prev;\n return this.element = (prev = this.prev) ? (Log.DEBUG ? console.log(\"F - insert \" + this.id + \" after \" + prev.element.id) : void 0, this.trigger('insert', this.data, {\n after: prev.element\n })) : (next = this.next) ? (Log.DEBUG ? console.log(\"F - insert \" + this.id + \" before \" + next.element.id) : void 0, this.trigger('insert', this.data, {\n before: next.element\n })) : (Log.DEBUG ? console.log(\"F - insert \" + this.id) : void 0, this.trigger('insert', this.data));\n },\n trigger: function() {\n return this.part.trigger.apply(this.part, arguments);\n }\n });\n\n Log.Dom.Line = function(part, num, line) {\n var chunk, _ref;\n this.part = part;\n this.num = num;\n this.id = \"\" + this.part.num + \"-\" + this.num;\n this.ends = !!((_ref = line[line.length - 1]) != null ? _ref.match(/\\r|\\n/) : void 0);\n this.hidden = !!line.match(/\\r/);\n this.chunks = new Log.Dom.Chunks(this, line.replace(/\\n$/, '').replace(/\\r/g, ''));\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.chunks;\n _results = [];\n for (_i = 0, _len = _ref1.length; _i < _len; _i++) {\n chunk = _ref1[_i];\n _results.push(chunk.data);\n }\n return _results;\n }).call(this)\n };\n return this;\n };\n\n Log.Dom.Line.prototype = $.extend(new Log.Dom.Node, {\n insert: function() {\n var after, before, chunk, next, prev, _i, _j, _len, _len1, _ref, _ref1, _results;\n if ((prev = this.prev) && !prev.ends && !prev.fold) {\n after = prev.chunks.last.element;\n if (Log.DEBUG) {\n console.log(\"1 - insert \" + this.id + \"'s chunks after the last node of prev, id \" + after.id);\n }\n _ref = this.chunks.slice().reverse();\n for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n chunk = _ref[_i];\n chunk.element = this.trigger('insert', chunk.data, {\n after: after\n });\n }\n if (this.ends) {\n return Log.Dom.Node.reinsert(this.tail);\n }\n } else if ((next = this.next) && !this.ends && !next.fold) {\n before = next.chunks.first.element;\n if (Log.DEBUG) {\n console.log(\"2 - insert \" + this.id + \"'s chunks before the first node of next, id \" + before.id);\n }\n _ref1 = this.chunks;\n _results = [];\n for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {\n chunk = _ref1[_j];\n _results.push(chunk.element = this.trigger('insert', chunk.data, {\n before: before\n }));\n }\n return _results;\n } else if (prev) {\n if (Log.DEBUG) {\n console.log(\"3 - 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(\"4 - 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(\"5 - 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 chunk, element, _i, _len, _ref;\n element = this.element;\n _ref = this.chunks;\n for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n chunk = _ref[_i];\n this.trigger('remove', chunk.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.Line.prototype.__defineSetter__('element', function(element) {\n var child, chunk, _i, _len, _ref, _results;\n child = element.firstChild;\n _ref = this.chunks;\n _results = [];\n for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n chunk = _ref[_i];\n _results.push(chunk.element = child = child.nextSibling);\n }\n return _results;\n });\n\n Log.Dom.Line.prototype.__defineGetter__('element', function() {\n return this.chunks.first.element.parentNode;\n });\n\n Log.Dom.Line.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.Chunks = function(parent, line) {\n return this.push.apply(this, this.parse(parent, line));\n };\n\n Log.Dom.Chunks.prototype = $.extend(new Array, {\n parse: function(parent, string) {\n var chunk, ix, _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 chunk = _ref[ix];\n _results.push(new Log.Dom.Chunk(parent, ix, chunk));\n }\n return _results;\n }\n });\n\n Log.Dom.Chunks.prototype.__defineGetter__('first', function() {\n return this[0];\n });\n\n Log.Dom.Chunks.prototype.__defineGetter__('last', function() {\n return this[this.length - 1];\n });\n\n Log.Dom.Chunk = function(line, num, data) {\n this.line = line;\n this.num = num;\n this.id = \"\" + line.part.num + \"-\" + line.num + \"-\" + num;\n this.data = $.extend(data, {\n id: this.id\n });\n return this;\n };\n\n $.extend(Log.Dom.Chunk.prototype, {\n prev: function() {\n var chunk, _ref;\n chunk = this.line.chunks[this.num - 1];\n return chunk || ((_ref = this.line.prev()) != null ? _ref.chunks.slice(-1)[0] : void 0);\n },\n next: function() {\n var chunk, _ref;\n chunk = this.line.chunks[this.num + 1];\n return chunk || ((_ref = this.line.next()) != null ? _ref.chunks[0] : void 0);\n }\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=log/engine/dom");minispade.register('log/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/engine/live");minispade.register('log/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 fold, next, node, nodes, _i, _len, _ref;\n fold = node = document.getElementById(this.start);\n next = node.nextSibling;\n if (!((next != null ? next.id : void 0) === this.end || (next != null ? (_ref = next.nextSibling) != null ? _ref.id : void 0 : void 0) === this.end)) {\n nodes = [];\n while ((node = node.nextSibling) && node.id !== this.end) {\n nodes.push(node);\n }\n for (_i = 0, _len = nodes.length; _i < _len; _i++) {\n node = nodes[_i];\n fold.appendChild(node);\n }\n fold.setAttribute('class', fold.getAttribute('class') + ' fold');\n }\n return this.active = true;\n }\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=log/folds");minispade.register('log/instrument', "(function() {(function() {\n\n Log.Metrics = function() {\n this.values = {};\n return this;\n };\n\n $.extend(Log.Metrics.prototype, {\n start: function(name) {\n return this.started = (new Date).getTime();\n },\n stop: function(name) {\n var _base;\n (_base = this.values)[name] || (_base[name] = []);\n return this.values[name].push((new Date).getTime() - this.started);\n },\n summary: function() {\n var metrics, name, values, _ref;\n metrics = {};\n _ref = this.values;\n for (name in _ref) {\n values = _ref[name];\n metrics[name] = {\n avg: values.reduce(function(a, b) {\n return a + b;\n }) / values.length,\n count: values.length\n };\n }\n return metrics;\n }\n });\n\n Log.Instrumenter = function() {};\n\n Log.Instrumenter.prototype = $.extend(new Log.Listener, {\n start: function(log, event) {\n log.metrics || (log.metrics = new Log.Metrics);\n return log.metrics.start(event);\n },\n stop: function(log, event) {\n return log.metrics.stop(event);\n }\n });\n\n Log.Log = function() {};\n\n Log.Log.prototype = $.extend(new Log.Listener, {\n receive: function(log, num, string) {\n return this.log(\"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/instrument");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 = $.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/limit");minispade.register('log/renderer/fragment', "(function() {(function() {\n\n Log.FragmentRenderer = 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.FragmentRenderer.prototype = $.extend(new Log.Listener, {\n remove: function(log, node) {\n if (node) {\n return node.parentNode.removeChild(node);\n }\n },\n insert: function(log, data, pos) {\n var after, before, node;\n node = this.render(data);\n 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 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.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 if (document.getElementById(data.id)) {\n return;\n }\n fold = this.fold.cloneNode(true);\n fold.setAttribute('id', data.id);\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 other.parentNode.appendChild(node);\n }\n }\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=log/renderer/fragment");minispade.register('log/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/renderer/inner_html");minispade.register('log/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/renderer/jquery"); \ No newline at end of file +minispade.register('log', "(function() {(function() {\n\n this.Log = function() {\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 });\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.toString(), string);\n }\n }\n });\nminispade.require('log/folds');\nminispade.require('log/deansi');\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 apply: function(string) {\n var nodes,\n _this = this;\n if (!string) {\n return [];\n }\n string = string.replace(/\\e\\[K/gm, '').replace(/\\033\\[K/gm, '').replace(/\\033\\[\\d+G/g, '');\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;\n }\n if (this.hidden(part)) {\n node.hidden = true;\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 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 return fold.receive(data);\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 node, _i, _len, _ref;\n console.log(\"F - activate \" + this.start);\n _ref = this.nodes;\n for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n node = _ref[_i];\n this.fold.appendChild(node);\n }\n this.fold.setAttribute('class', this.fold.getAttribute('class') + ' fold');\n return this.active = true;\n }\n });\n\n Log.Folds.Fold.prototype.__defineGetter__('fold', function() {\n return this._fold || (this._fold = document.getElementById(this.start));\n });\n\n Log.Folds.Fold.prototype.__defineGetter__('nodes', 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}).call(this);\n\n})();\n//@ sourceURL=log/folds");minispade.register('log/nodes', "(function() {(function() {\n\n Log.Node = function(id) {\n this.id = id;\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 });\n\n Log.Node.prototype.__defineGetter__('log', function() {\n var _ref;\n return this._log || (this._log = ((_ref = this.parent) != null ? _ref.log : void 0) || this.parent);\n });\n\n Log.Node.prototype.__defineGetter__('renderer', function() {\n if (this.log) {\n return this.log._renderer;\n }\n });\n\n Log.Node.prototype.__defineGetter__('firstChild', function() {\n return this.children.first;\n });\n\n Log.Node.prototype.__defineGetter__('lastChild', function() {\n return this.children.last;\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, _ref, _ref1, _ref2, _ref3;\n ix = this.position(item) || 0;\n this.items.splice(ix, 0, item);\n if (this.parent) {\n item.parent = this.parent;\n }\n if (item.prev = this.items[ix - 1] || ((_ref = this.parent) != null ? (_ref1 = _ref.prev) != null ? _ref1.children.last : void 0 : void 0)) {\n item.prev.next = item;\n }\n if (item.next = this.items[ix + 1] || ((_ref2 = this.parent) != null ? (_ref3 = _ref2.next) != null ? _ref3.children.first : void 0 : void 0)) {\n item.next.prev = item;\n }\n return item;\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 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 Log.Nodes.prototype.__defineGetter__('first', function() {\n return this.items[0];\n });\n\n Log.Nodes.prototype.__defineGetter__('last', function() {\n return this.items[this.length - 1];\n });\n\n Log.Nodes.prototype.__defineGetter__('length', function() {\n return this.items.length;\n });\n\n Log.Part = function(id, string) {\n Log.Node.apply(this, arguments);\n this.string = string;\n return this;\n };\n\n Log.extend(Log.Part, {\n create: function(parent, id, string) {\n var fold, ix, line, part, _i, _len, _ref, _results;\n part = new Log.Part(id, string);\n parent.addChild(part);\n _ref = string.replace(/\\r\\n/gm, '\\n').split(/^/gm) || [];\n _results = [];\n for (ix = _i = 0, _len = _ref.length; _i < _len; ix = ++_i) {\n line = _ref[ix];\n if (fold = line.match(Log.Fold.PATTERN)) {\n _results.push(Log.Fold.create(part, \"\" + id + \"-\" + ix, fold[1], fold[2]));\n } else {\n _results.push(Log.Line.create(part, \"\" + id + \"-\" + ix, line));\n }\n }\n return _results;\n }\n });\n\n Log.Part.prototype = Log.extend(new Log.Node);\n\n Log.Fold = function(id, event, name) {\n Log.Node.apply(this, arguments);\n this.fold = true;\n this.id = id;\n this.data = {\n type: 'fold',\n id: id,\n event: event,\n name: name\n };\n return this;\n };\n\n Log.extend(Log.Fold, {\n PATTERN: /fold:(start|end):([\\w_\\-\\.]+)/,\n create: function(parent, id, event, name) {\n var fold;\n fold = new Log.Fold(id, event, name);\n parent.addChild(fold);\n fold.render();\n return parent.log.folds.add(fold.data);\n }\n });\n\n Log.Fold.prototype = Log.extend(new Log.Node, {\n render: function() {\n if (this.prev) {\n if (Log.DEBUG) {\n console.log(\"F.1 insert \" + this.id + \" after prev \" + this.prev.id);\n }\n return this.renderer.insert(this.data, {\n after: this.prev.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 return this.renderer.insert(this.data, {\n before: this.next.element\n });\n } else {\n if (Log.DEBUG) {\n console.log(\"F.3 insert \" + this.id);\n }\n return this.renderer.insert(this.data);\n }\n }\n });\n\n Log.Fold.prototype.__defineGetter__('element', function() {\n return document.getElementById(this.id);\n });\n\n Log.Line = function(id, string) {\n Log.Node.apply(this, arguments);\n this.string = string;\n return this;\n };\n\n Log.extend(Log.Line, {\n create: function(parent, id, string) {\n var ix, line, span, _i, _len, _ref, _results;\n line = new Log.Line(id, string);\n parent.addChild(line);\n if (string) {\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(Log.Span.create(line, \"\" + id + \"-\" + ix, span));\n }\n return _results;\n }\n }\n });\n\n Log.Line.prototype = Log.extend(new Log.Node, {\n render: function() {\n if (this.prev) {\n if (Log.DEBUG) {\n console.log(\"P.1 insert \" + this.id + \" after prev \" + this.prev.id);\n }\n return this.renderer.insert(this.data, {\n after: this.prev.element\n });\n } else if (this.next) {\n if (Log.DEBUG) {\n console.log(\"P.2 insert \" + this.id + \" before next \" + this.next.id);\n }\n return this.renderer.insert(this.data, {\n before: this.next.element\n });\n } else {\n if (Log.DEBUG) {\n console.log(\"P.3 insert \" + this.id);\n }\n return this.renderer.insert(this.data);\n }\n }\n });\n\n Log.Line.prototype.__defineGetter__('data', function() {\n return {\n type: 'paragraph',\n nodes: this.children.map(function(node) {\n return node.data;\n })\n };\n });\n\n Log.Line.prototype.__defineGetter__('element', function() {\n return this.children.first.element.parentNode;\n });\n\n Log.Span = function(id, data) {\n var _ref;\n Log.Node.apply(this, arguments);\n this.data = $.extend(data, {\n id: id\n });\n this.ends = !!((_ref = data.text[data.text.length - 1]) != null ? _ref.match(/\\n/) : void 0);\n this.hidden = !!data.text.match(/\\r/);\n this.data.text = data.text.replace(/\\r/gm, '').replace(/\\n$/, '');\n if (this.hidden) {\n this.data[\"class\"] = ['hidden'];\n }\n return this;\n };\n\n Log.extend(Log.Span, {\n create: function(parent, id, data) {\n var span;\n span = new Log.Span(id, data);\n parent.addChild(span);\n return span.render();\n }\n });\n\n Log.Span.prototype = Log.extend(new Log.Node, {\n render: function() {\n var span, tail, _i, _len, _ref, _results;\n if (this.prev && !this.prev.ends) {\n if (Log.DEBUG) {\n console.log(\"S.1 insert \" + this.id + \" after prev \" + this.prev.id);\n }\n this.renderer.insert(this.data, {\n after: this.prev.element\n });\n } else if (this.next && !this.ends) {\n if (Log.DEBUG) {\n console.log(\"S.2 insert \" + this.id + \" before next \" + this.next.id);\n }\n this.renderer.insert(this.data, {\n before: this.next.element\n });\n } else {\n this.parent.render();\n }\n if (this.ends && (tail = this.tail).length > 0) {\n this.split(tail);\n }\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 if (this.tail.some(function(span) {\n return span.hidden;\n })) {\n return this.hide();\n }\n },\n hide: function() {\n if (!this.hidden) {\n this.renderer.hide(this.id);\n }\n return this.hidden = true;\n },\n split: function(spans) {\n var first, span, _i, _j, _len, _len1, _results;\n console.log(\"S.3 split \" + (spans.map(function(span) {\n return span.id;\n }).join(', ')));\n for (_i = 0, _len = spans.length; _i < _len; _i++) {\n span = spans[_i];\n this.renderer.remove(span.element);\n }\n if (first = spans.shift()) {\n first.parent.render();\n }\n _results = [];\n for (_j = 0, _len1 = spans.length; _j < _len1; _j++) {\n span = spans[_j];\n _results.push(span.render());\n }\n return _results;\n },\n isSibling: function(other) {\n return this.element.parentNode === other.element.parentNode;\n },\n siblings: function(type) {\n var siblings, span;\n siblings = [];\n span = this;\n while ((span = span[type]) && this.isSibling(span)) {\n siblings.push(span);\n }\n return siblings;\n }\n });\n\n Log.Span.prototype.__defineGetter__('element', function() {\n return document.getElementById(this.id);\n });\n\n Log.Span.prototype.__defineGetter__('head', function() {\n return this.siblings('prev').reverse();\n });\n\n Log.Span.prototype.__defineGetter__('tail', function() {\n return this.siblings('next');\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 remove: function(node) {\n if (node) {\n return node.parentNode.removeChild(node);\n }\n },\n insert: function(data, pos) {\n var after, before, node;\n node = this.render(data);\n 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(id) {\n var node;\n node = document.getElementById(id);\n node.setAttribute('class', this.addClass(node.getAttribute('class'), 'hidden'));\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 if (document.getElementById(data.id)) {\n return;\n }\n fold = this.fold.cloneNode(true);\n fold.setAttribute('id', data.id);\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 other.parentNode.appendChild(node);\n }\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 diff --git a/assets/styles/app/misc.sass b/assets/styles/app/misc.sass index f7a0ef11..f1db9710 100644 --- a/assets/styles/app/misc.sass +++ b/assets/styles/app/misc.sass @@ -6,6 +6,9 @@ .display-inline display: inline-block !important +.hidden + display: none + .emoji vertical-align: middle width: 20px