diff --git a/mix/qml.qrc b/mix/qml.qrc
index 47d9d3bb9..01074edb3 100644
--- a/mix/qml.qrc
+++ b/mix/qml.qrc
@@ -61,5 +61,7 @@
qml/js/ProjectModel.js
qml/js/QEtherHelper.js
qml/js/TransactionHelper.js
+ qml/js/Printer.js
+ qml/js/ansi2html.js
diff --git a/mix/qml/WebPreview.qml b/mix/qml/WebPreview.qml
index d2b52be65..26324c89a 100644
--- a/mix/qml/WebPreview.qml
+++ b/mix/qml/WebPreview.qml
@@ -423,6 +423,7 @@ Item {
id: resultTextArea
width: expressionPanel.width
wrapMode: Text.Wrap
+ textFormat: Text.RichText
font.family: webPreviewStyle.general.fontName
font.pointSize: appStyle.absoluteSize(-3)
backgroundVisible: true
diff --git a/mix/qml/html/WebContainer.html b/mix/qml/html/WebContainer.html
index dfce64979..9776f7633 100644
--- a/mix/qml/html/WebContainer.html
+++ b/mix/qml/html/WebContainer.html
@@ -3,6 +3,8 @@
+
+
diff --git a/mix/qml/js/Printer.js b/mix/qml/js/Printer.js
new file mode 100644
index 000000000..2c53fe573
--- /dev/null
+++ b/mix/qml/js/Printer.js
@@ -0,0 +1,90 @@
+var prettyPrint = (function () {
+ function pp(object, indent) {
+ try {
+ JSON.stringify(object, null, 2);
+ } catch (e) {
+ return pp(e, indent);
+ }
+
+ var str = "";
+ if(object instanceof Array) {
+ str += "[";
+ for(var i = 0, l = object.length; i < l; i++) {
+ str += pp(object[i], indent);
+ if(i < l-1) {
+ str += ", ";
+ }
+ }
+ str += " ]";
+ } else if (object instanceof Error) {
+ str += "\e[31m" + "Error:\e[0m " + object.message;
+ } else if (isBigNumber(object)) {
+ str += "\e[32m'" + object.toString(10) + "'";
+ } else if(typeof(object) === "object") {
+ str += "{\n";
+ indent += " ";
+ var last = getFields(object).pop()
+ getFields(object).forEach(function (k) {
+ str += indent + k + ": ";
+ try {
+ str += pp(object[k], indent);
+ } catch (e) {
+ str += pp(e, indent);
+ }
+ if(k !== last) {
+ str += ",";
+ }
+ str += "\n";
+ });
+ str += indent.substr(2, indent.length) + "}";
+ } else if(typeof(object) === "string") {
+ str += "\e[32m'" + object + "'";
+ } else if(typeof(object) === "undefined") {
+ str += "\e[1m\e[30m" + object;
+ } else if(typeof(object) === "number") {
+ str += "\e[31m" + object;
+ } else if(typeof(object) === "function") {
+ str += "\e[35m[Function]";
+ } else {
+ str += object;
+ }
+ str += "\e[0m";
+ return str;
+ }
+ var redundantFields = [
+ 'valueOf',
+ 'toString',
+ 'toLocaleString',
+ 'hasOwnProperty',
+ 'isPrototypeOf',
+ 'propertyIsEnumerable',
+ 'constructor',
+ '__defineGetter__',
+ '__defineSetter__',
+ '__lookupGetter__',
+ '__lookupSetter__',
+ '__proto__'
+ ];
+ var getFields = function (object) {
+ var result = Object.getOwnPropertyNames(object);
+ if (object.constructor && object.constructor.prototype) {
+ result = result.concat(Object.getOwnPropertyNames(object.constructor.prototype));
+ }
+ return result.filter(function (field) {
+ return redundantFields.indexOf(field) === -1;
+ });
+ };
+ var isBigNumber = function (object) {
+ return typeof BigNumber !== 'undefined' && object instanceof BigNumber;
+ };
+ function prettyPrintI(/* */) {
+ var args = arguments;
+ var ret = "";
+ for (var i = 0, l = args.length; i < l; i++) {
+ ret += pp(args[i], "") + "\n";
+ }
+ return ret;
+ }
+ return prettyPrintI;
+})();
+
diff --git a/mix/qml/js/ansi2html.js b/mix/qml/js/ansi2html.js
new file mode 100644
index 000000000..8f53fab24
--- /dev/null
+++ b/mix/qml/js/ansi2html.js
@@ -0,0 +1,106 @@
+var ansi2html = (function(){
+
+ function ansi2htmlI(str) {
+ // this lib do not support \e
+ str = str.replace(/e\[/g, '[');
+ // nor line breaks
+ str = '' + str.replace(/\n/g, '
') + '
';
+ var props = {}
+ , open = false
+
+ var stylemap =
+ { bold: "font-weight"
+ , underline: "text-decoration"
+ , color: "color"
+ , background: "background"
+ }
+
+ function style() {
+ var key, val, style = []
+ for (var key in props) {
+ val = props[key]
+ if (!val) continue
+ if (val == true) {
+ style.push(stylemap[key] + ':' + key)
+ } else {
+ style.push(stylemap[key] + ':' + val)
+ }
+ }
+ return style.join(';')
+ }
+
+
+ function tag(code) {
+ var i
+ , tag = ''
+ , n = ansi2htmlI.table[code]
+
+ if (open) tag += ''
+ open = false
+
+ if (n) {
+ for (i in n) props[i] = n[i]
+ tag += ''
+ open = true
+ } else {
+ props = {}
+ }
+
+ return tag
+ }
+
+ return str.replace(/\[(\d+;)?(\d+)*m/g, function(match, b1, b2) {
+ var i, code, res = ''
+ if (b2 == '' || b2 == null) b2 = '0'
+ for (i = 1; i < arguments.length - 2; i++) {
+ if (!arguments[i]) continue
+ code = parseInt(arguments[i])
+ res += tag(code)
+ }
+ return res
+ }) + tag()
+ }
+
+ /* not implemented:
+ * italic
+ * blink
+ * invert
+ * strikethrough
+ */
+ ansi2htmlI.table =
+ { 0: null
+ , 1: { bold: true }
+ , 3: { italic: true }
+ , 4: { underline: true }
+ , 5: { blink: true }
+ , 6: { blink: true }
+ , 7: { invert: true }
+ , 9: { strikethrough: true }
+ , 23: { italic: false }
+ , 24: { underline: false }
+ , 25: { blink: false }
+ , 27: { invert: false }
+ , 29: { strikethrough: false }
+ , 30: { color: 'black' }
+ , 31: { color: 'red' }
+ , 32: { color: 'green' }
+ , 33: { color: 'yellow' }
+ , 34: { color: 'blue' }
+ , 35: { color: 'magenta' }
+ , 36: { color: 'cyan' }
+ , 37: { color: 'white' }
+ , 39: { color: null }
+ , 40: { background: 'black' }
+ , 41: { background: 'red' }
+ , 42: { background: 'green' }
+ , 43: { background: 'yellow' }
+ , 44: { background: 'blue' }
+ , 45: { background: 'magenta' }
+ , 46: { background: 'cyan' }
+ , 47: { background: 'white' }
+ , 49: { background: null }
+ }
+
+ return ansi2htmlI;
+})();
+