').appendTo(parent);
- buildMessageElement(data[i],""+i,false,false,path+"["+i+"]").appendTo(row);
+ buildMessageElement(data[i],""+i,false,false,path+"["+i+"]",sourceId,rootPath,expandPaths).appendTo(row);
}
}
- })());
+ })(),checkExpanded(strippedKey,expandPaths,minRange,Math.min(fullLength-1,(minRange+9))));
$('').html("["+minRange+" … "+Math.min(fullLength-1,(minRange+9))+"]").appendTo(header);
}
if (fullLength < originalLength) {
$('['+fullLength+' … '+originalLength+']
').appendTo(arrayRows);
}
}
- });
+ },checkExpanded(strippedKey,expandPaths));
}
if (key) {
headerHead = $('').html(typeHint||(type+'['+originalLength+']')).appendTo(entryObj);
@@ -270,12 +347,12 @@ RED.utils = (function() {
} else {
newPath += "[\""+keys[i].replace(/"/,"\\\"")+"\"]"
}
- buildMessageElement(obj[keys[i]],keys[i],false,false,newPath).appendTo(row);
+ buildMessageElement(obj[keys[i]],keys[i],false,false,newPath,sourceId,rootPath,expandPaths).appendTo(row);
}
if (keys.length === 0) {
$('').text("empty").appendTo(element);
}
- });
+ },checkExpanded(strippedKey,expandPaths));
}
if (key) {
$('').html('object').appendTo(entryObj);
@@ -305,14 +382,15 @@ RED.utils = (function() {
return element;
}
- function validatePropertyExpression(str) {
- // This must be kept in sync with normalisePropertyExpression
- // in red/runtime/util.js
+ function normalisePropertyExpression(str) {
+ // This must be kept in sync with validatePropertyExpression
+ // in editor/js/ui/utils.js
var length = str.length;
if (length === 0) {
- return false;
+ throw new Error("Invalid property expression: zero-length");
}
+ var parts = [];
var start = 0;
var inString = false;
var inBox = false;
@@ -323,58 +401,75 @@ RED.utils = (function() {
if (!inString) {
if (c === "'" || c === '"') {
if (i != start) {
- return false;
+ throw new Error("Invalid property expression: unexpected "+c+" at position "+i);
}
inString = true;
quoteChar = c;
start = i+1;
} else if (c === '.') {
- if (i===0 || i===length-1) {
- return false;
+ if (i===0) {
+ throw new Error("Invalid property expression: unexpected . at position 0");
+ }
+ if (start != i) {
+ v = str.substring(start,i);
+ if (/^\d+$/.test(v)) {
+ parts.push(parseInt(v));
+ } else {
+ parts.push(v);
+ }
+ }
+ if (i===length-1) {
+ throw new Error("Invalid property expression: unterminated expression");
}
// Next char is first char of an identifier: a-z 0-9 $ _
if (!/[a-z0-9\$\_]/i.test(str[i+1])) {
- return false;
+ throw new Error("Invalid property expression: unexpected "+str[i+1]+" at position "+(i+1));
}
start = i+1;
} else if (c === '[') {
if (i === 0) {
- return false;
+ throw new Error("Invalid property expression: unexpected "+c+" at position "+i);
+ }
+ if (start != i) {
+ parts.push(str.substring(start,i));
}
if (i===length-1) {
- return false;
+ throw new Error("Invalid property expression: unterminated expression");
}
// Next char is either a quote or a number
if (!/["'\d]/.test(str[i+1])) {
- return false;
+ throw new Error("Invalid property expression: unexpected "+str[i+1]+" at position "+(i+1));
}
start = i+1;
inBox = true;
} else if (c === ']') {
if (!inBox) {
- return false;
+ throw new Error("Invalid property expression: unexpected "+c+" at position "+i);
}
if (start != i) {
v = str.substring(start,i);
- if (!/^\d+$/.test(v)) {
- return false;
+ if (/^\d+$/.test(v)) {
+ parts.push(parseInt(v));
+ } else {
+ throw new Error("Invalid property expression: unexpected array expression at position "+start);
}
}
start = i+1;
inBox = false;
} else if (c === ' ') {
- return false;
+ throw new Error("Invalid property expression: unexpected ' ' at position "+i);
}
} else {
if (c === quoteChar) {
if (i-start === 0) {
- return false;
+ throw new Error("Invalid property expression: zero-length string at position "+start);
}
- // Next char must be a ]
+ parts.push(str.substring(start,i));
+ // If inBox, next char must be a ]. Otherwise it may be [ or .
if (inBox && !/\]/.test(str[i+1])) {
- return false;
+ throw new Error("Invalid property expression: unexpected array expression at position "+start);
} else if (!inBox && i+1!==length && !/[\[\.]/.test(str[i+1])) {
- return false;
+ throw new Error("Invalid property expression: unexpected "+str[i+1]+" expression at position "+(i+1));
}
start = i+1;
inString = false;
@@ -383,9 +478,44 @@ RED.utils = (function() {
}
if (inBox || inString) {
+ throw new Error("Invalid property expression: unterminated expression");
+ }
+ if (start < length) {
+ parts.push(str.substring(start));
+ }
+ return parts;
+ }
+
+ function validatePropertyExpression(str) {
+ try {
+ var parts = normalisePropertyExpression(str);
+ return true;
+ } catch(err) {
return false;
}
- return true;
+ }
+
+ function getMessageProperty(msg,expr) {
+ var result = null;
+ var msgPropParts;
+
+ if (typeof expr === 'string') {
+ if (expr.indexOf('msg.')===0) {
+ expr = expr.substring(4);
+ }
+ msgPropParts = normalisePropertyExpression(expr);
+ } else {
+ msgPropParts = expr;
+ }
+ var m;
+ msgPropParts.reduce(function(obj, key) {
+ result = (typeof obj[key] !== "undefined" ? obj[key] : undefined);
+ if (result === undefined && obj.hasOwnProperty('type') && obj.hasOwnProperty('data')&& obj.hasOwnProperty('length')) {
+ result = (typeof obj.data[key] !== "undefined" ? obj.data[key] : undefined);
+ }
+ return result;
+ }, msg);
+ return result;
}
function getNodeIcon(def,node) {
@@ -424,6 +554,8 @@ RED.utils = (function() {
return {
createObjectElement: buildMessageElement,
+ getMessageProperty: getMessageProperty,
+ normalisePropertyExpression: normalisePropertyExpression,
validatePropertyExpression: validatePropertyExpression,
getNodeIcon: getNodeIcon,
getNodeLabel: getNodeLabel,
diff --git a/editor/sass/debug.scss b/editor/sass/debug.scss
index 17ed3e5ab..ca30ab7f9 100644
--- a/editor/sass/debug.scss
+++ b/editor/sass/debug.scss
@@ -51,25 +51,56 @@
border-left: 8px solid #eee;
border-right: 8px solid #eee;
padding: 2px;
+ &>.debug-message-meta .debug-message-tools {
+ display: none;
+ }
+
&.debug-message-hover {
border-right-color: #999;
&>.debug-message-meta .debug-message-tools {
display: inline-block;
}
}
- .debug-message-row:hover {
- background: #f3f3f3;
- &>.debug-message-tools {
+ .debug-message-row {
+ .debug-message-tools-pin {
+ display: none;
+ }
+ &.debug-message-row-pinned .debug-message-tools-pin {
display: inline-block;
}
+ &:hover {
+ background: #f3f3f3;
+ &>.debug-message-tools {
+ .debug-message-tools-copy {
+ display: inline-block;
+ }
+ .debug-message-tools-pin {
+ display: inline-block;
+ }
+ }
+ }
}
}
-.debug-message-row .debug-message-tools .editor-button-small {
- height: 16px;
- line-height: 14px;
- font-size: 8px;
- border-radius: 1px;
- padding: 0 3px;
+.debug-message-row .debug-message-tools {
+ .button-group:not(:last-child) {
+ margin-right: 3px;
+ }
+ .editor-button-small {
+ height: 16px;
+ line-height: 14px;
+ font-size: 8px;
+ border-radius: 1px;
+ padding: 0 3px;
+ min-width: 18px;
+ i.fa-terminal {
+ // terminal icon is a bit thin, so darken its color for better contrast
+ color: darken($editor-button-color, 30%) !important;
+ }
+ &.selected {
+ color: darken($workspace-button-color-selected, 10%) !important;
+ background: darken($workspace-button-background-active,10%);
+ }
+ }
}
.debug-message-meta {
@@ -92,7 +123,9 @@
position: absolute;
top: 3px;
right: 1px;
- display: none;
+ .debug-message-tools-copy {
+ display: none;
+ }
}
.debug-message-payload {
display: block;
@@ -183,6 +216,9 @@
display: block;
padding: 4px 2px 2px;
position: relative;
+ &.debug-message-row-pinned {
+ background: #f6f6f6;
+ }
}
.debug-message-expandable {
cursor: pointer;
diff --git a/nodes/core/core/lib/debug/debug-utils.js b/nodes/core/core/lib/debug/debug-utils.js
index 0b6f384bf..e4bd6b537 100644
--- a/nodes/core/core/lib/debug/debug-utils.js
+++ b/nodes/core/core/lib/debug/debug-utils.js
@@ -251,7 +251,7 @@ RED.debug = (function() {
}
var el = $('').appendTo(msg);
var path = (o.property?'msg.'+property:'msg');
- RED.utils.createObjectElement(payload,/*true*/null,format,false,path).appendTo(el);
+ RED.utils.createObjectElement(payload,/*true*/null,format,false,path,sourceNode&&sourceNode.id,path).appendTo(el);
var atBottom = (sbc.scrollHeight-messageList.height()-sbc.scrollTop) < 5;
var m = {
el: msg