perkins 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.DS_Store +0 -0
- data/.env.example +4 -0
- data/.gitignore +19 -0
- data/.pryrc +3 -0
- data/.rspec +2 -0
- data/Gemfile +18 -0
- data/LICENSE.txt +22 -0
- data/README.md +71 -0
- data/Rakefile +28 -0
- data/TODO.md +4 -0
- data/bin/perkins +6 -0
- data/db/migrate/20150130143030_create_repo.rb +18 -0
- data/db/migrate/20150130143050_create_builds.rb +20 -0
- data/db/schema.rb +38 -0
- data/examples/config.rb +12 -0
- data/examples/database.yml +17 -0
- data/examples/mongo.yml +13 -0
- data/lib/core_ext/hash/compact.rb +8 -0
- data/lib/core_ext/hash/deep_merge.rb +15 -0
- data/lib/core_ext/hash/deep_symbolize_keys.rb +20 -0
- data/lib/core_ext/object/false.rb +5 -0
- data/lib/core_ext/string/indent.rb +5 -0
- data/lib/core_ext/string/unindent.rb +5 -0
- data/lib/perkins/.DS_Store +0 -0
- data/lib/perkins/application.rb +40 -0
- data/lib/perkins/assets/images/github.svg +4 -0
- data/lib/perkins/assets/images/spinner.svg +23 -0
- data/lib/perkins/assets/javascripts/app.js +9 -0
- data/lib/perkins/assets/javascripts/log_view.js.coffee +95 -0
- data/lib/perkins/assets/javascripts/perkings.js.coffee +40 -0
- data/lib/perkins/assets/javascripts/vendor/ansiparse.js +187 -0
- data/lib/perkins/assets/javascripts/vendor/jquery.timeago.js +189 -0
- data/lib/perkins/assets/javascripts/vendor/log.js +2 -0
- data/lib/perkins/assets/javascripts/vendor/minispade.js +55 -0
- data/lib/perkins/assets/stylesheets/app.css +2 -0
- data/lib/perkins/assets/stylesheets/log.css.scss +115 -0
- data/lib/perkins/assets/stylesheets/styles.css.scss +199 -0
- data/lib/perkins/auth/github.rb +181 -0
- data/lib/perkins/build/data/env.rb +84 -0
- data/lib/perkins/build/data/var.rb +60 -0
- data/lib/perkins/build/data.rb +167 -0
- data/lib/perkins/build/script/bundler.rb +76 -0
- data/lib/perkins/build/script/go.rb +100 -0
- data/lib/perkins/build/script/helpers.rb +39 -0
- data/lib/perkins/build/script/jdk.rb +43 -0
- data/lib/perkins/build/script/ruby.rb +31 -0
- data/lib/perkins/build/script/rvm.rb +73 -0
- data/lib/perkins/build/script/stages.rb +28 -0
- data/lib/perkins/build/script/templates/footer.sh +3 -0
- data/lib/perkins/build/script/templates/header.sh +201 -0
- data/lib/perkins/build/script/templates/xcode.sh +21 -0
- data/lib/perkins/build/script.rb +167 -0
- data/lib/perkins/build/shell/dsl.rb +104 -0
- data/lib/perkins/build/shell/node.rb +121 -0
- data/lib/perkins/build/shell.rb +16 -0
- data/lib/perkins/build.rb +27 -0
- data/lib/perkins/build_report.rb +11 -0
- data/lib/perkins/cli.rb +42 -0
- data/lib/perkins/commit.rb +30 -0
- data/lib/perkins/dsl/app_proxy.rb +23 -0
- data/lib/perkins/dsl.rb +12 -0
- data/lib/perkins/listener.rb +38 -0
- data/lib/perkins/logger.rb +12 -0
- data/lib/perkins/notifier.rb +5 -0
- data/lib/perkins/repo.rb +145 -0
- data/lib/perkins/runner.rb +124 -0
- data/lib/perkins/server.rb +314 -0
- data/lib/perkins/thor_utils.rb +79 -0
- data/lib/perkins/version.rb +3 -0
- data/lib/perkins/views/401.haml +1 -0
- data/lib/perkins/views/builds.haml +46 -0
- data/lib/perkins/views/index.haml +6 -0
- data/lib/perkins/views/layout.haml +53 -0
- data/lib/perkins/views/menu.haml +18 -0
- data/lib/perkins/views/orgs.haml +101 -0
- data/lib/perkins/views/profile.haml +31 -0
- data/lib/perkins/views/readme.md +20 -0
- data/lib/perkins/views/repos/config.haml +72 -0
- data/lib/perkins/views/repos/github.haml +76 -0
- data/lib/perkins/views/repos/menu.haml +17 -0
- data/lib/perkins/views/repos/repo.haml +64 -0
- data/lib/perkins/views/repos/spinner.haml +3 -0
- data/lib/perkins/webhooks/github.rb +12 -0
- data/lib/perkins/worker.rb +33 -0
- data/lib/perkins.rb +36 -0
- data/perkins.gemspec +52 -0
- data/spec/fixtures/.travis.yml +8 -0
- data/spec/fixtures/config.yml +6 -0
- data/spec/lib/build/build_spec.rb +58 -0
- data/spec/lib/commit_spec.rb +6 -0
- data/spec/lib/dsl_spec.rb +17 -0
- data/spec/lib/listener_spec.rb +30 -0
- data/spec/lib/repo_spec.rb +110 -0
- data/spec/lib/runner_spec.rb +76 -0
- data/spec/lib/server_spec.rb +108 -0
- data/spec/spec_helper.rb +67 -0
- data/spec/support/auth.rb +30 -0
- data/spec/support/github_api.rb +177 -0
- metadata +503 -0
@@ -0,0 +1,187 @@
|
|
1
|
+
//https://raw.githubusercontent.com/mmalecki/ansiparse/master/lib/ansiparse.js
|
2
|
+
ansiparse = function (str) {
|
3
|
+
//
|
4
|
+
// I'm terrible at writing parsers.
|
5
|
+
//
|
6
|
+
var matchingControl = null,
|
7
|
+
matchingData = null,
|
8
|
+
matchingText = '',
|
9
|
+
ansiState = [],
|
10
|
+
result = [],
|
11
|
+
state = {},
|
12
|
+
eraseChar;
|
13
|
+
|
14
|
+
//
|
15
|
+
// General workflow for this thing is:
|
16
|
+
// \033\[33mText
|
17
|
+
// | | |
|
18
|
+
// | | matchingText
|
19
|
+
// | matchingData
|
20
|
+
// matchingControl
|
21
|
+
//
|
22
|
+
// In further steps we hope it's all going to be fine. It usually is.
|
23
|
+
//
|
24
|
+
|
25
|
+
//
|
26
|
+
// Erases a char from the output
|
27
|
+
//
|
28
|
+
eraseChar = function () {
|
29
|
+
var index, text;
|
30
|
+
if (matchingText.length) {
|
31
|
+
matchingText = matchingText.substr(0, matchingText.length - 1);
|
32
|
+
}
|
33
|
+
else if (result.length) {
|
34
|
+
index = result.length - 1;
|
35
|
+
text = result[index].text;
|
36
|
+
if (text.length === 1) {
|
37
|
+
//
|
38
|
+
// A result bit was fully deleted, pop it out to simplify the final output
|
39
|
+
//
|
40
|
+
result.pop();
|
41
|
+
}
|
42
|
+
else {
|
43
|
+
result[index].text = text.substr(0, text.length - 1);
|
44
|
+
}
|
45
|
+
}
|
46
|
+
};
|
47
|
+
|
48
|
+
for (var i = 0; i < str.length; i++) {
|
49
|
+
if (matchingControl != null) {
|
50
|
+
if (matchingControl == '\033' && str[i] == '\[') {
|
51
|
+
//
|
52
|
+
// We've matched full control code. Lets start matching formating data.
|
53
|
+
//
|
54
|
+
|
55
|
+
//
|
56
|
+
// "emit" matched text with correct state
|
57
|
+
//
|
58
|
+
if (matchingText) {
|
59
|
+
state.text = matchingText;
|
60
|
+
result.push(state);
|
61
|
+
state = {};
|
62
|
+
matchingText = "";
|
63
|
+
}
|
64
|
+
|
65
|
+
matchingControl = null;
|
66
|
+
matchingData = '';
|
67
|
+
}
|
68
|
+
else {
|
69
|
+
//
|
70
|
+
// We failed to match anything - most likely a bad control code. We
|
71
|
+
// go back to matching regular strings.
|
72
|
+
//
|
73
|
+
matchingText += matchingControl + str[i];
|
74
|
+
matchingControl = null;
|
75
|
+
}
|
76
|
+
continue;
|
77
|
+
}
|
78
|
+
else if (matchingData != null) {
|
79
|
+
if (str[i] == ';') {
|
80
|
+
//
|
81
|
+
// `;` separates many formatting codes, for example: `\033[33;43m`
|
82
|
+
// means that both `33` and `43` should be applied.
|
83
|
+
//
|
84
|
+
// TODO: this can be simplified by modifying state here.
|
85
|
+
//
|
86
|
+
ansiState.push(matchingData);
|
87
|
+
matchingData = '';
|
88
|
+
}
|
89
|
+
else if (str[i] == 'm') {
|
90
|
+
//
|
91
|
+
// `m` finished whole formatting code. We can proceed to matching
|
92
|
+
// formatted text.
|
93
|
+
//
|
94
|
+
ansiState.push(matchingData);
|
95
|
+
matchingData = null;
|
96
|
+
matchingText = '';
|
97
|
+
|
98
|
+
//
|
99
|
+
// Convert matched formatting data into user-friendly state object.
|
100
|
+
//
|
101
|
+
// TODO: DRY.
|
102
|
+
//
|
103
|
+
ansiState.forEach(function (ansiCode) {
|
104
|
+
if (ansiparse.foregroundColors[ansiCode]) {
|
105
|
+
state.foreground = ansiparse.foregroundColors[ansiCode];
|
106
|
+
}
|
107
|
+
else if (ansiparse.backgroundColors[ansiCode]) {
|
108
|
+
state.background = ansiparse.backgroundColors[ansiCode];
|
109
|
+
}
|
110
|
+
else if (ansiCode == 39) {
|
111
|
+
delete state.foreground;
|
112
|
+
}
|
113
|
+
else if (ansiCode == 49) {
|
114
|
+
delete state.background;
|
115
|
+
}
|
116
|
+
else if (ansiparse.styles[ansiCode]) {
|
117
|
+
state[ansiparse.styles[ansiCode]] = true;
|
118
|
+
}
|
119
|
+
else if (ansiCode == 22) {
|
120
|
+
state.bold = false;
|
121
|
+
}
|
122
|
+
else if (ansiCode == 23) {
|
123
|
+
state.italic = false;
|
124
|
+
}
|
125
|
+
else if (ansiCode == 24) {
|
126
|
+
state.underline = false;
|
127
|
+
}
|
128
|
+
});
|
129
|
+
ansiState = [];
|
130
|
+
}
|
131
|
+
else {
|
132
|
+
matchingData += str[i];
|
133
|
+
}
|
134
|
+
continue;
|
135
|
+
}
|
136
|
+
|
137
|
+
if (str[i] == '\033') {
|
138
|
+
matchingControl = str[i];
|
139
|
+
}
|
140
|
+
else if (str[i] == '\u0008') {
|
141
|
+
eraseChar();
|
142
|
+
}
|
143
|
+
else {
|
144
|
+
matchingText += str[i];
|
145
|
+
}
|
146
|
+
}
|
147
|
+
|
148
|
+
if (matchingText) {
|
149
|
+
state.text = matchingText + (matchingControl ? matchingControl : '');
|
150
|
+
result.push(state);
|
151
|
+
}
|
152
|
+
return result;
|
153
|
+
}
|
154
|
+
|
155
|
+
ansiparse.foregroundColors = {
|
156
|
+
'30': 'black',
|
157
|
+
'31': 'red',
|
158
|
+
'32': 'green',
|
159
|
+
'33': 'yellow',
|
160
|
+
'34': 'blue',
|
161
|
+
'35': 'magenta',
|
162
|
+
'36': 'cyan',
|
163
|
+
'37': 'white',
|
164
|
+
'90': 'grey'
|
165
|
+
};
|
166
|
+
|
167
|
+
ansiparse.backgroundColors = {
|
168
|
+
'40': 'black',
|
169
|
+
'41': 'red',
|
170
|
+
'42': 'green',
|
171
|
+
'43': 'yellow',
|
172
|
+
'44': 'blue',
|
173
|
+
'45': 'magenta',
|
174
|
+
'46': 'cyan',
|
175
|
+
'47': 'white'
|
176
|
+
};
|
177
|
+
|
178
|
+
ansiparse.styles = {
|
179
|
+
'1': 'bold',
|
180
|
+
'3': 'italic',
|
181
|
+
'4': 'underline'
|
182
|
+
};
|
183
|
+
|
184
|
+
if (typeof module == "object" && typeof window == "undefined") {
|
185
|
+
module.exports = ansiparse;
|
186
|
+
}
|
187
|
+
|
@@ -0,0 +1,189 @@
|
|
1
|
+
/**
|
2
|
+
* Timeago is a jQuery plugin that makes it easy to support automatically
|
3
|
+
* updating fuzzy timestamps (e.g. "4 minutes ago" or "about 1 day ago").
|
4
|
+
*
|
5
|
+
* @name timeago
|
6
|
+
* @version 1.2.0
|
7
|
+
* @requires jQuery v1.2.3+
|
8
|
+
* @author Ryan McGeary
|
9
|
+
* @license MIT License - http://www.opensource.org/licenses/mit-license.php
|
10
|
+
*
|
11
|
+
* For usage and examples, visit:
|
12
|
+
* http://timeago.yarp.com/
|
13
|
+
*
|
14
|
+
* Copyright (c) 2008-2013, Ryan McGeary (ryan -[at]- mcgeary [*dot*] org)
|
15
|
+
*/
|
16
|
+
|
17
|
+
(function (factory) {
|
18
|
+
if (typeof define === 'function' && define.amd) {
|
19
|
+
// AMD. Register as an anonymous module.
|
20
|
+
define(['jquery'], factory);
|
21
|
+
} else {
|
22
|
+
// Browser globals
|
23
|
+
factory(jQuery);
|
24
|
+
}
|
25
|
+
}(function ($) {
|
26
|
+
$.timeago = function(timestamp) {
|
27
|
+
if (timestamp instanceof Date) {
|
28
|
+
return inWords(timestamp);
|
29
|
+
} else if (typeof timestamp === "string") {
|
30
|
+
return inWords($.timeago.parse(timestamp));
|
31
|
+
} else if (typeof timestamp === "number") {
|
32
|
+
return inWords(new Date(timestamp));
|
33
|
+
} else {
|
34
|
+
return inWords($.timeago.datetime(timestamp));
|
35
|
+
}
|
36
|
+
};
|
37
|
+
var $t = $.timeago;
|
38
|
+
|
39
|
+
$.extend($.timeago, {
|
40
|
+
settings: {
|
41
|
+
refreshMillis: 60000,
|
42
|
+
allowFuture: false,
|
43
|
+
localeTitle: false,
|
44
|
+
cutoff: 0,
|
45
|
+
strings: {
|
46
|
+
prefixAgo: null,
|
47
|
+
prefixFromNow: null,
|
48
|
+
suffixAgo: "ago",
|
49
|
+
suffixFromNow: "from now",
|
50
|
+
seconds: "less than a minute",
|
51
|
+
minute: "about a minute",
|
52
|
+
minutes: "%d minutes",
|
53
|
+
hour: "about an hour",
|
54
|
+
hours: "about %d hours",
|
55
|
+
day: "a day",
|
56
|
+
days: "%d days",
|
57
|
+
month: "about a month",
|
58
|
+
months: "%d months",
|
59
|
+
year: "about a year",
|
60
|
+
years: "%d years",
|
61
|
+
wordSeparator: " ",
|
62
|
+
numbers: []
|
63
|
+
}
|
64
|
+
},
|
65
|
+
inWords: function(distanceMillis) {
|
66
|
+
var $l = this.settings.strings;
|
67
|
+
var prefix = $l.prefixAgo;
|
68
|
+
var suffix = $l.suffixAgo;
|
69
|
+
if (this.settings.allowFuture) {
|
70
|
+
if (distanceMillis < 0) {
|
71
|
+
prefix = $l.prefixFromNow;
|
72
|
+
suffix = $l.suffixFromNow;
|
73
|
+
}
|
74
|
+
}
|
75
|
+
|
76
|
+
var seconds = Math.abs(distanceMillis) / 1000;
|
77
|
+
var minutes = seconds / 60;
|
78
|
+
var hours = minutes / 60;
|
79
|
+
var days = hours / 24;
|
80
|
+
var years = days / 365;
|
81
|
+
|
82
|
+
function substitute(stringOrFunction, number) {
|
83
|
+
var string = $.isFunction(stringOrFunction) ? stringOrFunction(number, distanceMillis) : stringOrFunction;
|
84
|
+
var value = ($l.numbers && $l.numbers[number]) || number;
|
85
|
+
return string.replace(/%d/i, value);
|
86
|
+
}
|
87
|
+
|
88
|
+
var words = seconds < 45 && substitute($l.seconds, Math.round(seconds)) ||
|
89
|
+
seconds < 90 && substitute($l.minute, 1) ||
|
90
|
+
minutes < 45 && substitute($l.minutes, Math.round(minutes)) ||
|
91
|
+
minutes < 90 && substitute($l.hour, 1) ||
|
92
|
+
hours < 24 && substitute($l.hours, Math.round(hours)) ||
|
93
|
+
hours < 42 && substitute($l.day, 1) ||
|
94
|
+
days < 30 && substitute($l.days, Math.round(days)) ||
|
95
|
+
days < 45 && substitute($l.month, 1) ||
|
96
|
+
days < 365 && substitute($l.months, Math.round(days / 30)) ||
|
97
|
+
years < 1.5 && substitute($l.year, 1) ||
|
98
|
+
substitute($l.years, Math.round(years));
|
99
|
+
|
100
|
+
var separator = $l.wordSeparator || "";
|
101
|
+
if ($l.wordSeparator === undefined) { separator = " "; }
|
102
|
+
return $.trim([prefix, words, suffix].join(separator));
|
103
|
+
},
|
104
|
+
parse: function(iso8601) {
|
105
|
+
var s = $.trim(iso8601);
|
106
|
+
s = s.replace(/\.\d+/,""); // remove milliseconds
|
107
|
+
s = s.replace(/-/,"/").replace(/-/,"/");
|
108
|
+
s = s.replace(/T/," ").replace(/Z/," UTC");
|
109
|
+
s = s.replace(/([\+\-]\d\d)\:?(\d\d)/," $1$2"); // -04:00 -> -0400
|
110
|
+
return new Date(s);
|
111
|
+
},
|
112
|
+
datetime: function(elem) {
|
113
|
+
var iso8601 = $t.isTime(elem) ? $(elem).attr("datetime") : $(elem).attr("title");
|
114
|
+
return $t.parse(iso8601);
|
115
|
+
},
|
116
|
+
isTime: function(elem) {
|
117
|
+
// jQuery's `is()` doesn't play well with HTML5 in IE
|
118
|
+
return $(elem).get(0).tagName.toLowerCase() === "time"; // $(elem).is("time");
|
119
|
+
}
|
120
|
+
});
|
121
|
+
|
122
|
+
// functions that can be called via $(el).timeago('action')
|
123
|
+
// init is default when no action is given
|
124
|
+
// functions are called with context of a single element
|
125
|
+
var functions = {
|
126
|
+
init: function(){
|
127
|
+
var refresh_el = $.proxy(refresh, this);
|
128
|
+
refresh_el();
|
129
|
+
var $s = $t.settings;
|
130
|
+
if ($s.refreshMillis > 0) {
|
131
|
+
setInterval(refresh_el, $s.refreshMillis);
|
132
|
+
}
|
133
|
+
},
|
134
|
+
update: function(time){
|
135
|
+
$(this).data('timeago', { datetime: $t.parse(time) });
|
136
|
+
refresh.apply(this);
|
137
|
+
}
|
138
|
+
};
|
139
|
+
|
140
|
+
$.fn.timeago = function(action, options) {
|
141
|
+
var fn = action ? functions[action] : functions.init;
|
142
|
+
if(!fn){
|
143
|
+
throw new Error("Unknown function name '"+ action +"' for timeago");
|
144
|
+
}
|
145
|
+
// each over objects here and call the requested function
|
146
|
+
this.each(function(){
|
147
|
+
fn.call(this, options);
|
148
|
+
});
|
149
|
+
return this;
|
150
|
+
};
|
151
|
+
|
152
|
+
function refresh() {
|
153
|
+
var data = prepareData(this);
|
154
|
+
var $s = $t.settings;
|
155
|
+
|
156
|
+
if (!isNaN(data.datetime)) {
|
157
|
+
if ( $s.cutoff == 0 || distance(data.datetime) < $s.cutoff) {
|
158
|
+
$(this).text(inWords(data.datetime));
|
159
|
+
}
|
160
|
+
}
|
161
|
+
return this;
|
162
|
+
}
|
163
|
+
|
164
|
+
function prepareData(element) {
|
165
|
+
element = $(element);
|
166
|
+
if (!element.data("timeago")) {
|
167
|
+
element.data("timeago", { datetime: $t.datetime(element) });
|
168
|
+
var text = $.trim(element.text());
|
169
|
+
if ($t.settings.localeTitle) {
|
170
|
+
element.attr("title", element.data('timeago').datetime.toLocaleString());
|
171
|
+
} else if (text.length > 0 && !($t.isTime(element) && element.attr("title"))) {
|
172
|
+
element.attr("title", text);
|
173
|
+
}
|
174
|
+
}
|
175
|
+
return element.data("timeago");
|
176
|
+
}
|
177
|
+
|
178
|
+
function inWords(date) {
|
179
|
+
return $t.inWords(distance(date));
|
180
|
+
}
|
181
|
+
|
182
|
+
function distance(date) {
|
183
|
+
return (new Date().getTime() - date.getTime());
|
184
|
+
}
|
185
|
+
|
186
|
+
// fix for IE6 suckage
|
187
|
+
document.createElement("abbr");
|
188
|
+
document.createElement("time");
|
189
|
+
}));
|
@@ -0,0 +1,2 @@
|
|
1
|
+
minispade.register('log', "(function() {(function() {\n\n this.Log = function() {\n this.autoCloseFold = true;\n this.listeners = [];\n this.renderer = new Log.Renderer;\n this.children = new Log.Nodes(this);\n this.parts = {};\n this.folds = new Log.Folds(this);\n this.times = new Log.Times(this);\n return this;\n };\n\n Log.extend = function(one, other) {\n var name;\n for (name in other) {\n one[name] = other[name];\n }\n return one;\n };\n\n Log.extend(Log, {\n DEBUG: true,\n SLICE: 500,\n TIMEOUT: 25,\n FOLD: /fold:(start|end):([\\w_\\-\\.]+)/,\n TIME: /time:(start|end):([\\w_\\-\\.]+):?([\\w_\\-\\.\\=\\,]*)/,\n create: function(options) {\n var listener, log, _i, _len, _ref;\n options || (options = {});\n log = new Log();\n if (options.limit) {\n log.listeners.push(log.limit = new Log.Limit(options.limit));\n }\n _ref = options.listeners || [];\n for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n listener = _ref[_i];\n log.listeners.push(listener);\n }\n return log;\n }\n });\nminispade.require('log/nodes');\n\n Log.prototype = Log.extend(new Log.Node, {\n set: function(num, string) {\n if (this.parts[num]) {\n return console.log(\"part \" + num + \" exists\");\n } else {\n this.parts[num] = true;\n return Log.Part.create(this, num, string);\n }\n },\n insert: function(data, pos) {\n this.trigger('insert', data, pos);\n return this.renderer.insert(data, pos);\n },\n remove: function(node) {\n this.trigger('remove', node);\n return this.renderer.remove(node);\n },\n hide: function(node) {\n this.trigger('hide', node);\n return this.renderer.hide(node);\n },\n trigger: function() {\n var args, ix, listener, _i, _len, _ref, _results;\n args = [this].concat(Array.prototype.slice.apply(arguments));\n _ref = this.listeners;\n _results = [];\n for (ix = _i = 0, _len = _ref.length; _i < _len; ix = ++_i) {\n listener = _ref[ix];\n _results.push(listener.notify.apply(listener, args));\n }\n return _results;\n }\n });\n\n Log.Listener = function() {};\n\n Log.extend(Log.Listener.prototype, {\n notify: function(log, event) {\n if (this[event]) {\n return this[event].apply(this, [log].concat(Array.prototype.slice.call(arguments, 2)));\n }\n }\n });\nminispade.require('log/folds');\nminispade.require('log/times');\nminispade.require('log/deansi');\nminispade.require('log/limit');\nminispade.require('log/renderer');\n\n}).call(this);\n\n})();\n//@ sourceURL=log");minispade.register('log/deansi', "(function() {(function() {\n\n Log.Deansi = {\n CLEAR_ANSI: /(?:\\033)(?:\\[0?c|\\[[0356]n|\\[7[lh]|\\[\\?25[lh]|\\(B|H|\\[(?:\\d+(;\\d+){,2})?G|\\[(?:[12])?[JK]|[DM]|\\[0K)/gm,\n apply: function(string) {\n var nodes,\n _this = this;\n if (!string) {\n return [];\n }\n string = string.replace(this.CLEAR_ANSI, '');\n nodes = ansiparse(string).map(function(part) {\n return _this.node(part);\n });\n return nodes;\n },\n node: function(part) {\n var classes, node;\n node = {\n type: 'span',\n text: part.text\n };\n if (classes = this.classes(part)) {\n node[\"class\"] = classes.join(' ');\n }\n return node;\n },\n classes: function(part) {\n var result;\n result = [];\n result = result.concat(this.colors(part));\n if (result.length > 0) {\n return result;\n }\n },\n colors: function(part) {\n var colors;\n colors = [];\n if (part.foreground) {\n colors.push(part.foreground);\n }\n if (part.background) {\n colors.push(\"bg-\" + part.background);\n }\n if (part.bold) {\n colors.push('bold');\n }\n if (part.italic) {\n colors.push('italic');\n }\n if (part.underline) {\n colors.push('underline');\n }\n return colors;\n },\n hidden: function(part) {\n if (part.text.match(/\\r/)) {\n part.text = part.text.replace(/^.*\\r/gm, '');\n return true;\n }\n }\n };\n\n}).call(this);\n\n})();\n//@ sourceURL=log/deansi");minispade.register('log/folds', "(function() {(function() {\n\n Log.Folds = function(log) {\n this.log = log;\n this.folds = {};\n return this;\n };\n\n Log.extend(Log.Folds.prototype, {\n add: function(data) {\n var fold, _base, _name;\n fold = (_base = this.folds)[_name = data.name] || (_base[_name] = new Log.Folds.Fold);\n fold.receive(data, {\n autoCloseFold: this.log.autoCloseFold\n });\n return fold.active;\n }\n });\n\n Log.Folds.Fold = function() {\n return this;\n };\n\n Log.extend(Log.Folds.Fold.prototype, {\n receive: function(data, options) {\n this[data.event] = data.id;\n if (this.start && this.end && !this.active) {\n return this.activate(options);\n }\n },\n activate: function(options) {\n var fragment, nextSibling, node, parentNode, toRemove, _i, _len, _ref;\n options || (options = {});\n if (Log.DEBUG) {\n console.log(\"F.n - activate \" + this.start);\n }\n toRemove = this.fold.parentNode;\n parentNode = toRemove.parentNode;\n nextSibling = toRemove.nextSibling;\n parentNode.removeChild(toRemove);\n fragment = document.createDocumentFragment();\n _ref = this.nodes;\n for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n node = _ref[_i];\n fragment.appendChild(node);\n }\n this.fold.appendChild(fragment);\n parentNode.insertBefore(toRemove, nextSibling);\n this.fold.setAttribute('class', this.classes(options['autoCloseFold']));\n return this.active = true;\n },\n classes: function(autoCloseFold) {\n var classes;\n classes = this.fold.getAttribute('class').split(' ');\n classes.push('fold');\n if (!autoCloseFold) {\n classes.push('open');\n }\n if (this.fold.childNodes.length > 2) {\n classes.push('active');\n }\n return classes.join(' ');\n }\n });\n\n Object.defineProperty(Log.Folds.Fold.prototype, 'fold', {\n get: function() {\n return this._fold || (this._fold = document.getElementById(this.start));\n }\n });\n\n Object.defineProperty(Log.Folds.Fold.prototype, 'nodes', {\n get: function() {\n var node, nodes;\n node = this.fold;\n nodes = [];\n while ((node = node.nextSibling) && node.id !== this.end) {\n nodes.push(node);\n }\n return nodes;\n }\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=log/folds");minispade.register('log/limit', "(function() {(function() {\n\n Log.Limit = function(max_lines) {\n this.max_lines = max_lines || 1000;\n return this;\n };\n\n Log.Limit.prototype = Log.extend(new Log.Listener, {\n count: 0,\n insert: function(log, node, pos) {\n if (node.type === 'paragraph' && !node.hidden) {\n return this.count += 1;\n }\n }\n });\n\n Object.defineProperty(Log.Limit.prototype, 'limited', {\n get: function() {\n return this.count >= this.max_lines;\n }\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=log/limit");minispade.register('log/nodes', "(function() {(function() {\n var newLineAtTheEndRegexp, newLineRegexp, rRegexp, removeCarriageReturns;\n\n Log.Node = function(id, num) {\n this.id = id;\n this.num = num;\n this.key = Log.Node.key(this.id);\n this.children = new Log.Nodes(this);\n return this;\n };\n\n Log.extend(Log.Node, {\n key: function(id) {\n if (id) {\n return id.split('-').map(function(i) {\n return '000000'.concat(i).slice(-6);\n }).join('');\n }\n }\n });\n\n Log.extend(Log.Node.prototype, {\n addChild: function(node) {\n return this.children.add(node);\n },\n remove: function() {\n this.log.remove(this.element);\n return this.parent.children.remove(this);\n }\n });\n\n Object.defineProperty(Log.Node.prototype, 'log', {\n get: function() {\n var _ref;\n return this._log || (this._log = ((_ref = this.parent) != null ? _ref.log : void 0) || this.parent);\n }\n });\n\n Object.defineProperty(Log.Node.prototype, 'firstChild', {\n get: function() {\n return this.children.first;\n }\n });\n\n Object.defineProperty(Log.Node.prototype, 'lastChild', {\n get: function() {\n return this.children.last;\n }\n });\n\n Log.Nodes = function(parent) {\n if (parent) {\n this.parent = parent;\n }\n this.items = [];\n this.index = {};\n return this;\n };\n\n Log.extend(Log.Nodes.prototype, {\n add: function(item) {\n var ix, next, prev, _ref, _ref1;\n ix = this.position(item) || 0;\n this.items.splice(ix, 0, item);\n if (this.parent) {\n item.parent = this.parent;\n }\n prev = function(item) {\n while (item && !item.children.last) {\n item = item.prev;\n }\n return item != null ? item.children.last : void 0;\n };\n next = function(item) {\n while (item && !item.children.first) {\n item = item.next;\n }\n return item != null ? item.children.first : void 0;\n };\n if (item.prev = this.items[ix - 1] || prev((_ref = this.parent) != null ? _ref.prev : void 0)) {\n item.prev.next = item;\n }\n if (item.next = this.items[ix + 1] || next((_ref1 = this.parent) != null ? _ref1.next : void 0)) {\n item.next.prev = item;\n }\n return item;\n },\n remove: function(item) {\n this.items.splice(this.items.indexOf(item), 1);\n if (item.next) {\n item.next.prev = item.prev;\n }\n if (item.prev) {\n item.prev.next = item.next;\n }\n if (this.items.length === 0) {\n return this.parent.remove();\n }\n },\n position: function(item) {\n var ix, _i, _ref;\n for (ix = _i = _ref = this.items.length - 1; _i >= 0; ix = _i += -1) {\n if (this.items[ix].key < item.key) {\n return ix + 1;\n }\n }\n },\n indexOf: function() {\n return this.items.indexOf.apply(this.items, arguments);\n },\n slice: function() {\n return this.items.slice.apply(this.items, arguments);\n },\n each: function(func) {\n return this.items.slice().forEach(func);\n },\n map: function(func) {\n return this.items.map(func);\n }\n });\n\n Object.defineProperty(Log.Nodes.prototype, 'first', {\n get: function() {\n return this.items[0];\n }\n });\n\n Object.defineProperty(Log.Nodes.prototype, 'last', {\n get: function() {\n return this.items[this.length - 1];\n }\n });\n\n Object.defineProperty(Log.Nodes.prototype, 'length', {\n get: function() {\n return this.items.length;\n }\n });\n\n Log.Part = function(id, num, string) {\n Log.Node.apply(this, arguments);\n this.string = string || '';\n this.string = this.string.replace(/\\033\\[1000D/gm, '\\r');\n this.string = this.string.replace(/\\r+\\n/gm, '\\n');\n this.strings = this.string.split(/^/gm) || [];\n this.slices = ((function() {\n var _results;\n _results = [];\n while (this.strings.length > 0) {\n _results.push(this.strings.splice(0, Log.SLICE));\n }\n return _results;\n }).call(this));\n return this;\n };\n\n Log.extend(Log.Part, {\n create: function(log, num, string) {\n var part;\n part = new Log.Part(num.toString(), num, string);\n log.addChild(part);\n return part.process(0, -1);\n }\n });\n\n Log.Part.prototype = Log.extend(new Log.Node, {\n remove: function() {},\n process: function(slice, num) {\n var node, span, spans, string, _i, _j, _len, _len1, _ref, _ref1, _ref2, _ref3, _ref4,\n _this = this;\n _ref = this.slices[slice] || [];\n for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n string = _ref[_i];\n if ((_ref1 = this.log.limit) != null ? _ref1.limited : void 0) {\n return;\n }\n spans = [];\n _ref2 = Log.Deansi.apply(string);\n for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) {\n node = _ref2[_j];\n span = Log.Span.create(this, \"\" + this.id + \"-\" + (num += 1), num, node.text, node[\"class\"]);\n span.render();\n spans.push(span);\n }\n if ((_ref3 = spans[0]) != null ? (_ref4 = _ref3.line) != null ? _ref4.cr : void 0 : void 0) {\n spans[0].line.clear();\n }\n }\n if (!(slice >= this.slices.length - 1)) {\n return setTimeout((function() {\n return _this.process(slice + 1, num);\n }), Log.TIMEOUT);\n }\n }\n });\n\n newLineAtTheEndRegexp = new RegExp(\"\\n$\");\n\n newLineRegexp = new RegExp(\"\\n\");\n\n rRegexp = new RegExp(\"\\r\");\n\n removeCarriageReturns = function(string) {\n var index;\n index = string.lastIndexOf(\"\\r\");\n if (index === -1) {\n return string;\n }\n return string.substr(index + 1);\n };\n\n Log.Span = function(id, num, text, classes) {\n var fold, time, _ref;\n Log.Node.apply(this, arguments);\n if (fold = text.match(Log.FOLD)) {\n this.fold = true;\n this.event = fold[1];\n this.text = this.name = fold[2];\n } else if (time = text.match(Log.TIME)) {\n this.time = true;\n this.event = time[1];\n this.name = time[2];\n this.stats = time[3];\n } else {\n this.text = text;\n this.text = removeCarriageReturns(this.text);\n this.text = this.text.replace(newLineAtTheEndRegexp, '');\n this.nl = !!((_ref = text[text.length - 1]) != null ? _ref.match(newLineRegexp) : void 0);\n this.cr = !!text.match(rRegexp);\n this[\"class\"] = this.cr && ['clears'] || classes;\n }\n return this;\n };\n\n Log.extend(Log.Span, {\n create: function(parent, id, num, text, classes) {\n var span;\n span = new Log.Span(id, num, text, classes);\n parent.addChild(span);\n return span;\n },\n render: function(parent, id, num, text, classes) {\n var span;\n span = this.create(parent, id, num, text, classes);\n return span.render();\n }\n });\n\n Log.Span.prototype = Log.extend(new Log.Node, {\n render: function() {\n var tail;\n if (this.time && this.event === 'end' && this.prev) {\n if (Log.DEBUG) {\n console.log(\"S.0 insert \" + this.id + \" after prev \" + this.prev.id);\n }\n this.nl = this.prev.nl;\n this.log.insert(this.data, {\n after: this.prev.element\n });\n this.line = this.prev.line;\n } else if (!this.fold && this.prev && !this.prev.fold && !this.prev.nl) {\n if (Log.DEBUG) {\n console.log(\"S.1 insert \" + this.id + \" after prev \" + this.prev.id);\n }\n this.log.insert(this.data, {\n after: this.prev.element\n });\n this.line = this.prev.line;\n } else if (!this.fold && this.next && !this.next.fold && !this.next.time) {\n if (Log.DEBUG) {\n console.log(\"S.2 insert \" + this.id + \" before next \" + this.next.id);\n }\n this.log.insert(this.data, {\n before: this.next.element\n });\n this.line = this.next.line;\n } else {\n this.line = Log.Line.create(this.log, [this]);\n this.line.render();\n }\n if (this.nl && (tail = this.tail).length > 0) {\n this.split(tail);\n }\n if (this.time) {\n return this.log.times.add(this);\n }\n },\n remove: function() {\n Log.Node.prototype.remove.apply(this);\n if (this.line) {\n return this.line.remove(this);\n }\n },\n split: function(spans) {\n var line, span, _i, _len;\n if (Log.DEBUG) {\n console.log(\"S.4 split [\" + (spans.map(function(span) {\n return span.id;\n }).join(', ')) + \"]\");\n }\n for (_i = 0, _len = spans.length; _i < _len; _i++) {\n span = spans[_i];\n this.log.remove(span.element);\n }\n line = Log.Line.create(this.log, spans);\n line.render();\n if (line.cr) {\n return line.clear();\n }\n },\n clear: function() {\n if (this.prev && this.isSibling(this.prev) && this.isSequence(this.prev)) {\n this.prev.clear();\n return this.prev.remove();\n }\n },\n isSequence: function(other) {\n return this.parent.num - other.parent.num === this.log.children.indexOf(this.parent) - this.log.children.indexOf(other.parent);\n },\n isSibling: function(other) {\n var _ref, _ref1;\n return ((_ref = this.element) != null ? _ref.parentNode : void 0) === ((_ref1 = other.element) != null ? _ref1.parentNode : void 0);\n },\n siblings: function(type) {\n var siblings, span;\n siblings = [];\n while ((span = (span || this)[type]) && this.isSibling(span)) {\n siblings.push(span);\n }\n return siblings;\n }\n });\n\n Object.defineProperty(Log.Span.prototype, 'data', {\n get: function() {\n return {\n id: this.id,\n type: 'span',\n text: this.text,\n \"class\": this[\"class\"],\n time: this.time\n };\n }\n });\n\n Object.defineProperty(Log.Span.prototype, 'line', {\n get: function() {\n return this._line;\n },\n set: function(line) {\n if (this.line) {\n this.line.remove(this);\n }\n this._line = line;\n if (this.line) {\n return this.line.add(this);\n }\n }\n });\n\n Object.defineProperty(Log.Span.prototype, 'element', {\n get: function() {\n return document.getElementById(this.id);\n }\n });\n\n Object.defineProperty(Log.Span.prototype, 'head', {\n get: function() {\n return this.siblings('prev').reverse();\n }\n });\n\n Object.defineProperty(Log.Span.prototype, 'tail', {\n get: function() {\n return this.siblings('next');\n }\n });\n\n Log.Line = function(log) {\n this.log = log;\n this.spans = [];\n return this;\n };\n\n Log.extend(Log.Line, {\n create: function(log, spans) {\n var line, span, _i, _len;\n if ((span = spans[0]) && span.fold) {\n line = new Log.Fold(log, span.event, span.name);\n } else {\n line = new Log.Line(log);\n }\n for (_i = 0, _len = spans.length; _i < _len; _i++) {\n span = spans[_i];\n span.line = line;\n }\n return line;\n }\n });\n\n Log.extend(Log.Line.prototype, {\n add: function(span) {\n var ix;\n if (span.cr) {\n this.cr = true;\n }\n if (this.spans.indexOf(span) > -1) {\n\n } else if ((ix = this.spans.indexOf(span.prev)) > -1) {\n return this.spans.splice(ix + 1, 0, span);\n } else if ((ix = this.spans.indexOf(span.next)) > -1) {\n return this.spans.splice(ix, 0, span);\n } else {\n return this.spans.push(span);\n }\n },\n remove: function(span) {\n var ix;\n if ((ix = this.spans.indexOf(span)) > -1) {\n return this.spans.splice(ix, 1);\n }\n },\n render: function() {\n var fold;\n if ((fold = this.prev) && fold.event === 'start' && fold.active) {\n if (this.next && !this.next.fold) {\n if (Log.DEBUG) {\n console.log(\"L.0 insert \" + this.id + \" before next \" + this.next.id);\n }\n return this.element = this.log.insert(this.data, {\n before: this.next.element\n });\n } else {\n if (Log.DEBUG) {\n console.log(\"L.0 insert \" + this.id + \" into fold \" + fold.id);\n }\n fold = this.log.folds.folds[fold.name].fold;\n return this.element = this.log.insert(this.data, {\n into: fold\n });\n }\n } else if (this.prev) {\n if (Log.DEBUG) {\n console.log(\"L.1 insert \" + this.spans[0].id + \" after prev \" + this.prev.id);\n }\n return this.element = this.log.insert(this.data, {\n after: this.prev.element\n });\n } else if (this.next) {\n if (Log.DEBUG) {\n console.log(\"L.2 insert \" + this.spans[0].id + \" before next \" + this.next.id);\n }\n return this.element = this.log.insert(this.data, {\n before: this.next.element\n });\n } else {\n if (Log.DEBUG) {\n console.log(\"L.3 insert \" + this.spans[0].id + \" into #log\");\n }\n return this.element = this.log.insert(this.data);\n }\n },\n clear: function() {\n var cr, _i, _len, _ref, _results;\n _ref = this.crs;\n _results = [];\n for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n cr = _ref[_i];\n _results.push(cr.clear());\n }\n return _results;\n }\n });\n\n Object.defineProperty(Log.Line.prototype, 'id', {\n get: function() {\n var _ref;\n return (_ref = this.spans[0]) != null ? _ref.id : void 0;\n }\n });\n\n Object.defineProperty(Log.Line.prototype, 'data', {\n get: function() {\n return {\n type: 'paragraph',\n nodes: this.nodes\n };\n }\n });\n\n Object.defineProperty(Log.Line.prototype, 'nodes', {\n get: function() {\n return this.spans.map(function(span) {\n return span.data;\n });\n }\n });\n\n Object.defineProperty(Log.Line.prototype, 'prev', {\n get: function() {\n var _ref;\n return (_ref = this.spans[0].prev) != null ? _ref.line : void 0;\n }\n });\n\n Object.defineProperty(Log.Line.prototype, 'next', {\n get: function() {\n var _ref;\n return (_ref = this.spans[this.spans.length - 1].next) != null ? _ref.line : void 0;\n }\n });\n\n Object.defineProperty(Log.Line.prototype, 'crs', {\n get: function() {\n return this.spans.filter(function(span) {\n return span.cr;\n });\n }\n });\n\n Log.Fold = function(log, event, name) {\n Log.Line.apply(this, arguments);\n this.fold = true;\n this.event = event;\n this.name = name;\n return this;\n };\n\n Log.Fold.prototype = Log.extend(new Log.Line, {\n render: function() {\n var element, _ref;\n if (this.prev && this.prev.element) {\n if (Log.DEBUG) {\n console.log(\"F.1 insert \" + this.id + \" after prev \" + this.prev.id);\n }\n element = this.prev.element;\n this.element = this.log.insert(this.data, {\n after: element\n });\n } else if (this.next) {\n if (Log.DEBUG) {\n console.log(\"F.2 insert \" + this.id + \" before next \" + this.next.id);\n }\n element = this.next.element || this.next.element.parentNode;\n this.element = this.log.insert(this.data, {\n before: element\n });\n } else {\n if (Log.DEBUG) {\n console.log(\"F.3 insert \" + this.id);\n }\n this.element = this.log.insert(this.data);\n }\n if (this.span.next && ((_ref = this.span.prev) != null ? _ref.isSibling(this.span.next) : void 0)) {\n this.span.prev.split([this.span.next].concat(this.span.next.tail));\n }\n return this.active = this.log.folds.add(this.data);\n }\n });\n\n Object.defineProperty(Log.Fold.prototype, 'id', {\n get: function() {\n return \"fold-\" + this.event + \"-\" + this.name;\n }\n });\n\n Object.defineProperty(Log.Fold.prototype, 'span', {\n get: function() {\n return this.spans[0];\n }\n });\n\n Object.defineProperty(Log.Fold.prototype, 'data', {\n get: function() {\n return {\n type: 'fold',\n id: this.id,\n event: this.event,\n name: this.name\n };\n }\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=log/nodes");minispade.register('log/renderer', "(function() {(function() {\n\n Log.Renderer = function() {\n this.frag = document.createDocumentFragment();\n this.para = this.createParagraph();\n this.span = this.createSpan();\n this.text = document.createTextNode('');\n this.fold = this.createFold();\n return this;\n };\n\n Log.extend(Log.Renderer.prototype, {\n insert: function(data, pos) {\n var after, before, into, node;\n node = this.render(data);\n if (into = pos != null ? pos.into : void 0) {\n if (typeof into === 'String') {\n into = document.getElementById(pos != null ? pos.into : void 0);\n }\n if (pos != null ? pos.prepend : void 0) {\n this.prependTo(node, into);\n } else {\n this.appendTo(node, into);\n }\n } else if (after = pos != null ? pos.after : void 0) {\n if (typeof after === 'String') {\n after = document.getElementById(pos);\n }\n this.insertAfter(node, after);\n } else if (before = pos != null ? pos.before : void 0) {\n if (typeof before === 'String') {\n before = document.getElementById(pos != null ? pos.before : void 0);\n }\n this.insertBefore(node, before);\n } else {\n this.insertBefore(node);\n }\n return node;\n },\n hide: function(node) {\n node.setAttribute('class', this.addClass(node.getAttribute('class'), 'hidden'));\n return node;\n },\n remove: function(node) {\n if (node) {\n node.parentNode.removeChild(node);\n }\n return node;\n },\n render: function(data) {\n var frag, node, type, _i, _len;\n if (data instanceof Array) {\n frag = this.frag.cloneNode(true);\n for (_i = 0, _len = data.length; _i < _len; _i++) {\n node = data[_i];\n node = this.render(node);\n if (node) {\n frag.appendChild(node);\n }\n }\n return frag;\n } else {\n data.type || (data.type = 'paragraph');\n type = data.type[0].toUpperCase() + data.type.slice(1);\n return this[\"render\" + type](data);\n }\n },\n renderParagraph: function(data) {\n var node, para, type, _i, _len, _ref;\n para = this.para.cloneNode(true);\n if (data.id) {\n para.setAttribute('id', data.id);\n }\n if (data.hidden) {\n para.setAttribute('style', 'display: none;');\n }\n _ref = data.nodes || [];\n for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n node = _ref[_i];\n type = node.type[0].toUpperCase() + node.type.slice(1);\n node = this[\"render\" + type](node);\n para.appendChild(node);\n }\n return para;\n },\n renderFold: function(data) {\n var fold;\n fold = this.fold.cloneNode(true);\n fold.setAttribute('id', data.id || (\"fold-\" + data.event + \"-\" + data.name));\n fold.setAttribute('class', \"fold-\" + data.event);\n if (data.event === 'start') {\n fold.lastChild.lastChild.nodeValue = data.name;\n } else {\n fold.removeChild(fold.lastChild);\n }\n return fold;\n },\n renderSpan: function(data) {\n var span;\n span = this.span.cloneNode(true);\n if (data.id) {\n span.setAttribute('id', data.id);\n }\n if (data[\"class\"]) {\n span.setAttribute('class', data[\"class\"]);\n }\n span.lastChild.nodeValue = data.text || '';\n return span;\n },\n renderText: function(data) {\n var text;\n text = this.text.cloneNode(true);\n text.nodeValue = data.text;\n return text;\n },\n createParagraph: function() {\n var para;\n para = document.createElement('p');\n para.appendChild(document.createElement('a'));\n return para;\n },\n createFold: function() {\n var fold;\n fold = document.createElement('div');\n fold.appendChild(this.createSpan());\n fold.lastChild.setAttribute('class', 'fold-name');\n return fold;\n },\n createSpan: function() {\n var span;\n span = document.createElement('span');\n span.appendChild(document.createTextNode(' '));\n return span;\n },\n insertBefore: function(node, other) {\n var log;\n if (other) {\n return other.parentNode.insertBefore(node, other);\n } else {\n log = document.getElementById('log');\n return log.insertBefore(node, log.firstChild);\n }\n },\n insertAfter: function(node, other) {\n if (other.nextSibling) {\n return this.insertBefore(node, other.nextSibling);\n } else {\n return this.appendTo(node, other.parentNode);\n }\n },\n prependTo: function(node, other) {\n if (other.firstChild) {\n return other.insertBefore(node, other.firstChild);\n } else {\n return appendTo(node, other);\n }\n },\n appendTo: function(node, other) {\n return other.appendChild(node);\n },\n addClass: function(classes, string) {\n if (classes != null ? classes.indexOf(string) : void 0) {\n return;\n }\n if (classes) {\n return \"\" + classes + \" \" + string;\n } else {\n return string;\n }\n }\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=log/renderer");minispade.register('log/times', "(function() {(function() {\n\n Log.Times = function(log) {\n this.log = log;\n this.times = {};\n return this;\n };\n\n Log.extend(Log.Times.prototype, {\n add: function(node) {\n var time, _base, _name;\n time = (_base = this.times)[_name = node.name] || (_base[_name] = new Log.Times.Time);\n return time.receive(node);\n },\n duration: function(name) {\n if (this.times[name]) {\n return this.times[name].duration;\n }\n }\n });\n\n Log.Times.Time = function() {\n return this;\n };\n\n Log.extend(Log.Times.Time.prototype, {\n receive: function(node) {\n this[node.event] = node;\n if (Log.DEBUG) {\n console.log(\"T.0 - \" + node.event + \" \" + node.name);\n }\n if (this.start && this.end) {\n return this.finish();\n }\n },\n finish: function() {\n var element;\n if (Log.DEBUG) {\n console.log(\"T.1 - finish \" + this.start.name);\n }\n element = document.getElementById(this.start.id);\n if (element) {\n return this.update(element);\n }\n },\n update: function(element) {\n element.setAttribute('class', 'duration');\n element.setAttribute('title', \"This command finished after \" + this.duration + \" seconds.\");\n return element.lastChild.nodeValue = \"\" + this.duration + \"s\";\n }\n });\n\n Object.defineProperty(Log.Times.Time.prototype, 'duration', {\n get: function() {\n var duration;\n duration = this.stats.duration / 1000 / 1000 / 1000;\n return duration.toFixed(2);\n }\n });\n\n Object.defineProperty(Log.Times.Time.prototype, 'stats', {\n get: function() {\n var stat, stats, _i, _len, _ref;\n if (!(this.end && this.end.stats)) {\n return {};\n }\n stats = {};\n _ref = this.end.stats.split(',');\n for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n stat = _ref[_i];\n stat = stat.split('=');\n stats[stat[0]] = stat[1];\n }\n return stats;\n }\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=log/times");
|
2
|
+
|
@@ -0,0 +1,55 @@
|
|
1
|
+
/*jshint evil:true*/
|
2
|
+
|
3
|
+
minispade = {
|
4
|
+
root: null,
|
5
|
+
modules: {},
|
6
|
+
loaded: {},
|
7
|
+
|
8
|
+
globalEval: function(data) {
|
9
|
+
if ( data ) {
|
10
|
+
// We use execScript on Internet Explorer
|
11
|
+
// We use an anonymous function so that context is window
|
12
|
+
// rather than jQuery in Firefox
|
13
|
+
( window.execScript || function( data ) {
|
14
|
+
window[ "eval" ].call( window, data );
|
15
|
+
} )( data );
|
16
|
+
}
|
17
|
+
},
|
18
|
+
|
19
|
+
require: function(name) {
|
20
|
+
var loaded = minispade.loaded[name];
|
21
|
+
var mod = minispade.modules[name];
|
22
|
+
|
23
|
+
if (!loaded) {
|
24
|
+
if (mod) {
|
25
|
+
minispade.loaded[name] = true;
|
26
|
+
|
27
|
+
if (typeof mod === "string") {
|
28
|
+
this.globalEval(mod);
|
29
|
+
} else {
|
30
|
+
mod();
|
31
|
+
}
|
32
|
+
} else {
|
33
|
+
if (minispade.root && name.substr(0,minispade.root.length) !== minispade.root) {
|
34
|
+
return minispade.require(minispade.root+name);
|
35
|
+
} else {
|
36
|
+
throw "The module '" + name + "' could not be found";
|
37
|
+
}
|
38
|
+
}
|
39
|
+
}
|
40
|
+
|
41
|
+
return loaded;
|
42
|
+
},
|
43
|
+
|
44
|
+
requireAll: function(regex) {
|
45
|
+
for (var module in this.modules) {
|
46
|
+
if (!this.modules.hasOwnProperty(module)) { continue; }
|
47
|
+
if (regex && !regex.test(module)) { continue; }
|
48
|
+
minispade.require(module);
|
49
|
+
}
|
50
|
+
},
|
51
|
+
|
52
|
+
register: function(name, callback) {
|
53
|
+
minispade.modules[name] = callback;
|
54
|
+
}
|
55
|
+
};
|
@@ -0,0 +1,115 @@
|
|
1
|
+
#metrics {
|
2
|
+
position: absolute;
|
3
|
+
top: 15px;
|
4
|
+
right: 15px;
|
5
|
+
text-align: right;
|
6
|
+
}
|
7
|
+
p {
|
8
|
+
margin: 0;
|
9
|
+
}
|
10
|
+
#log {
|
11
|
+
//float: left;
|
12
|
+
//width: 59%;
|
13
|
+
padding: 15px 0;
|
14
|
+
min-height: 12px;
|
15
|
+
line-height: 18px;
|
16
|
+
color: #fff;
|
17
|
+
font-family: monospace;
|
18
|
+
white-space: normal;
|
19
|
+
background-color: #333;
|
20
|
+
border: 1px solid #ddd;
|
21
|
+
-webkit-border-radius: 4px;
|
22
|
+
-moz-border-radius: 4px;
|
23
|
+
border-radius: 4px;
|
24
|
+
overflow-x: scroll;
|
25
|
+
}
|
26
|
+
#log {
|
27
|
+
position: relative;
|
28
|
+
counter-reset: line-numbering;
|
29
|
+
}
|
30
|
+
#log p {
|
31
|
+
margin: 0;
|
32
|
+
padding: 0 15px 0 50px;
|
33
|
+
text-indent: -25px;
|
34
|
+
}
|
35
|
+
#log p::nth-line {
|
36
|
+
color: yellow !important;
|
37
|
+
}
|
38
|
+
#log {
|
39
|
+
counter-reset: line-numbering;
|
40
|
+
}
|
41
|
+
#log p a::before {
|
42
|
+
content: counter(line-numbering);
|
43
|
+
counter-increment: line-numbering;
|
44
|
+
padding-right: 1em;
|
45
|
+
text-align: right;
|
46
|
+
color: #fff;
|
47
|
+
opacity: 0.33;
|
48
|
+
}
|
49
|
+
#log a {
|
50
|
+
display: inline-block;
|
51
|
+
width: 35px;
|
52
|
+
margin-left: -10px;
|
53
|
+
text-align: right;
|
54
|
+
cursor: pointer;
|
55
|
+
text-decoration: none;
|
56
|
+
}
|
57
|
+
|
58
|
+
pre#log .duration {
|
59
|
+
background-color: #666666;
|
60
|
+
border-radius: 7px;
|
61
|
+
color: #bbbbbb;
|
62
|
+
display: block;
|
63
|
+
float: right;
|
64
|
+
font-size: 10px;
|
65
|
+
line-height: 10px;
|
66
|
+
padding: 6px 7px 4px;
|
67
|
+
text-indent: 0;
|
68
|
+
}
|
69
|
+
|
70
|
+
#log .fold {
|
71
|
+
cursor: pointer;
|
72
|
+
background-color: #444;
|
73
|
+
}
|
74
|
+
#log .fold:not(.open) p {
|
75
|
+
visibility: hidden;
|
76
|
+
height: 0;
|
77
|
+
min-height: 0;
|
78
|
+
}
|
79
|
+
#log .fold:not(.open) p:first-of-type {
|
80
|
+
visibility: visible;
|
81
|
+
height: auto;
|
82
|
+
min-height: 16px;
|
83
|
+
}
|
84
|
+
#log .fold-start:not(.fold),
|
85
|
+
#log .fold-end {
|
86
|
+
display: none;
|
87
|
+
}
|
88
|
+
#log .fold span.fold-name {
|
89
|
+
position: absolute;
|
90
|
+
display: block;
|
91
|
+
right: 20px;
|
92
|
+
margin-top: 3px;
|
93
|
+
padding: 0px 5px 2px 5px;
|
94
|
+
line-height: 10px;
|
95
|
+
font-size: 10px;
|
96
|
+
background-color: #999;
|
97
|
+
border-radius: 4px;
|
98
|
+
color: #eee;
|
99
|
+
}
|
100
|
+
|
101
|
+
.green {
|
102
|
+
color: lime;
|
103
|
+
}
|
104
|
+
.red {
|
105
|
+
color: red;
|
106
|
+
}
|
107
|
+
.yellow {
|
108
|
+
color: yellow;
|
109
|
+
}
|
110
|
+
|
111
|
+
#events {
|
112
|
+
float: right;
|
113
|
+
width: 40%;
|
114
|
+
overflow-x: scroll;
|
115
|
+
}
|