mirror of
https://github.com/node-red/node-red.git
synced 2025-03-01 10:36:34 +00:00
Compare commits
5 Commits
2.2.0-beta
...
link-effec
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b1a706f811 | ||
|
|
c27dd336d9 | ||
|
|
5e9ff98c49 | ||
|
|
50cb074172 | ||
|
|
510a09ecba |
2803
CHANGELOG.md
2803
CHANGELOG.md
File diff suppressed because it is too large
Load Diff
20
package.json
20
package.json
@@ -26,13 +26,13 @@
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"acorn": "8.7.0",
|
||||
"acorn": "8.6.0",
|
||||
"acorn-walk": "8.2.0",
|
||||
"ajv": "8.8.2",
|
||||
"async-mutex": "0.3.2",
|
||||
"basic-auth": "2.0.1",
|
||||
"bcryptjs": "2.4.3",
|
||||
"body-parser": "1.19.1",
|
||||
"body-parser": "1.19.0",
|
||||
"cheerio": "1.0.0-rc.10",
|
||||
"clone": "2.1.2",
|
||||
"content-type": "1.0.4",
|
||||
@@ -41,7 +41,7 @@
|
||||
"cors": "2.8.5",
|
||||
"cronosjs": "1.7.1",
|
||||
"denque": "2.0.1",
|
||||
"express": "4.17.2",
|
||||
"express": "4.17.1",
|
||||
"express-session": "1.17.2",
|
||||
"form-data": "4.0.0",
|
||||
"fs-extra": "10.0.0",
|
||||
@@ -50,7 +50,7 @@
|
||||
"hash-sum": "2.0.0",
|
||||
"hpagent": "0.1.2",
|
||||
"https-proxy-agent": "5.0.0",
|
||||
"i18next": "21.6.6",
|
||||
"i18next": "21.5.4",
|
||||
"iconv-lite": "0.6.3",
|
||||
"is-utf8": "0.2.1",
|
||||
"js-yaml": "3.14.1",
|
||||
@@ -61,21 +61,21 @@
|
||||
"memorystore": "1.6.6",
|
||||
"mime": "2.5.2",
|
||||
"moment-timezone": "0.5.34",
|
||||
"mqtt": "4.3.4",
|
||||
"mqtt": "4.2.8",
|
||||
"multer": "1.4.3",
|
||||
"mustache": "4.2.0",
|
||||
"node-red-admin": "^2.2.1",
|
||||
"nopt": "5.0.0",
|
||||
"oauth2orize": "1.11.1",
|
||||
"on-headers": "1.0.2",
|
||||
"passport": "0.5.2",
|
||||
"passport": "0.5.0",
|
||||
"passport-http-bearer": "1.0.1",
|
||||
"passport-oauth2-client-password": "0.1.2",
|
||||
"raw-body": "2.4.2",
|
||||
"semver": "7.3.5",
|
||||
"tar": "6.1.11",
|
||||
"tough-cookie": "4.0.0",
|
||||
"uglify-js": "3.14.5",
|
||||
"uglify-js": "3.14.4",
|
||||
"uuid": "8.3.2",
|
||||
"ws": "7.5.1",
|
||||
"xml2js": "0.4.23"
|
||||
@@ -84,7 +84,7 @@
|
||||
"bcrypt": "5.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"dompurify": "2.3.4",
|
||||
"dompurify": "2.3.3",
|
||||
"grunt": "1.4.1",
|
||||
"grunt-chmod": "~1.1.1",
|
||||
"grunt-cli": "~1.4.3",
|
||||
@@ -113,11 +113,11 @@
|
||||
"node-red-node-test-helper": "^0.2.7",
|
||||
"nodemon": "2.0.15",
|
||||
"proxy": "^1.0.2",
|
||||
"sass": "1.48.0",
|
||||
"sass": "1.44.0",
|
||||
"should": "13.2.3",
|
||||
"sinon": "11.1.2",
|
||||
"stoppable": "^1.1.0",
|
||||
"supertest": "6.2.1"
|
||||
"supertest": "6.1.6"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
|
||||
@@ -19,11 +19,11 @@
|
||||
"@node-red/util": "2.2.0-beta.1",
|
||||
"@node-red/editor-client": "2.2.0-beta.1",
|
||||
"bcryptjs": "2.4.3",
|
||||
"body-parser": "1.19.1",
|
||||
"body-parser": "1.19.0",
|
||||
"clone": "2.1.2",
|
||||
"cors": "2.8.5",
|
||||
"express-session": "1.17.2",
|
||||
"express": "4.17.2",
|
||||
"express": "4.17.1",
|
||||
"memorystore": "1.6.6",
|
||||
"mime": "2.5.2",
|
||||
"multer": "1.4.3",
|
||||
@@ -31,7 +31,7 @@
|
||||
"oauth2orize": "1.11.1",
|
||||
"passport-http-bearer": "1.0.1",
|
||||
"passport-oauth2-client-password": "0.1.2",
|
||||
"passport": "0.5.2",
|
||||
"passport": "0.5.0",
|
||||
"ws": "7.5.1"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
|
||||
@@ -594,7 +594,9 @@ RED.nodes = (function() {
|
||||
}
|
||||
allNodes.addNode(n);
|
||||
if (!nodeLinks[n.id]) {
|
||||
nodeLinks[n.id] = {in:[],out:[]};
|
||||
nodeLinks[n.id] = {
|
||||
inCount:[],outCount:[],in:[],out:[]
|
||||
};
|
||||
}
|
||||
}
|
||||
RED.events.emit('nodes:add',n);
|
||||
@@ -604,15 +606,19 @@ RED.nodes = (function() {
|
||||
if (l.source) {
|
||||
// Possible the node hasn't been added yet
|
||||
if (!nodeLinks[l.source.id]) {
|
||||
nodeLinks[l.source.id] = {in:[],out:[]};
|
||||
nodeLinks[l.source.id] = {inCount:[],outCount:[],in:[],out:[]};
|
||||
}
|
||||
nodeLinks[l.source.id].out.push(l);
|
||||
nodeLinks[l.source.id].outCount[l.sourcePort] = (nodeLinks[l.source.id].outCount[l.sourcePort] || 0) + 1
|
||||
l.source.dirty = true;
|
||||
}
|
||||
if (l.target) {
|
||||
if (!nodeLinks[l.target.id]) {
|
||||
nodeLinks[l.target.id] = {in:[],out:[]};
|
||||
nodeLinks[l.target.id] = {inCount:[],outCount:[],in:[],out:[]};
|
||||
}
|
||||
nodeLinks[l.target.id].in.push(l);
|
||||
nodeLinks[l.target.id].inCount[0] = (nodeLinks[l.target.id].inCount[0] || 0) + 1
|
||||
l.target.dirty = true;
|
||||
}
|
||||
if (l.source.z === l.target.z && linkTabMap[l.source.z]) {
|
||||
linkTabMap[l.source.z].push(l);
|
||||
@@ -761,15 +767,19 @@ RED.nodes = (function() {
|
||||
if (index != -1) {
|
||||
links.splice(index,1);
|
||||
if (l.source && nodeLinks[l.source.id]) {
|
||||
l.source.dirty = true;
|
||||
var sIndex = nodeLinks[l.source.id].out.indexOf(l)
|
||||
if (sIndex !== -1) {
|
||||
nodeLinks[l.source.id].out.splice(sIndex,1)
|
||||
nodeLinks[l.source.id].outCount[l.sourcePort]--
|
||||
}
|
||||
}
|
||||
if (l.target && nodeLinks[l.target.id]) {
|
||||
l.target.dirty = true;
|
||||
var tIndex = nodeLinks[l.target.id].in.indexOf(l)
|
||||
if (tIndex !== -1) {
|
||||
nodeLinks[l.target.id].in.splice(tIndex,1)
|
||||
nodeLinks[l.target.id].inCount[0]--
|
||||
}
|
||||
}
|
||||
if (l.source.z === l.target.z && linkTabMap[l.source.z]) {
|
||||
@@ -2706,6 +2716,20 @@ RED.nodes = (function() {
|
||||
}
|
||||
return [];
|
||||
},
|
||||
getNodeLinkCount: function(id,portType,index) {
|
||||
// We *could* just let callers use `getNodeLinks` and get the
|
||||
// the length for themselves. However, that function creates
|
||||
// a clone of the array - which is needless work if all you
|
||||
// want is the length
|
||||
if (nodeLinks[id]) {
|
||||
if (portType === 1) {
|
||||
return nodeLinks[id].inCount[index] || 0
|
||||
} else {
|
||||
return nodeLinks[id].outCount[index] || 0
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
},
|
||||
addWorkspace: addWorkspace,
|
||||
removeWorkspace: removeWorkspace,
|
||||
getWorkspaceOrder: function() { return workspacesOrder },
|
||||
|
||||
@@ -946,25 +946,28 @@ RED.clipboard = (function() {
|
||||
if (truncated) {
|
||||
msg += "_truncated";
|
||||
}
|
||||
navigator.clipboard.writeText(value).then(function () {
|
||||
if (element) {
|
||||
var popover = RED.popover.create({
|
||||
target: element,
|
||||
direction: 'left',
|
||||
size: 'small',
|
||||
content: RED._(msg)
|
||||
});
|
||||
setTimeout(function() {
|
||||
popover.close();
|
||||
},1000);
|
||||
popover.open();
|
||||
}
|
||||
if (currentFocus) {
|
||||
$(currentFocus).focus();
|
||||
}
|
||||
}).catch(err => { console.error("Failed to copy:",err) });
|
||||
$("#red-ui-clipboard-hidden").val(value).focus().select();
|
||||
var result = document.execCommand("copy");
|
||||
if (result && element) {
|
||||
var popover = RED.popover.create({
|
||||
target: element,
|
||||
direction: 'left',
|
||||
size: 'small',
|
||||
content: RED._(msg)
|
||||
});
|
||||
setTimeout(function() {
|
||||
popover.close();
|
||||
},1000);
|
||||
popover.open();
|
||||
}
|
||||
$("#red-ui-clipboard-hidden").val("");
|
||||
if (currentFocus) {
|
||||
$(currentFocus).focus();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
function importNodes(nodesStr,addFlow) {
|
||||
var newNodes = nodesStr;
|
||||
if (typeof nodesStr === 'string') {
|
||||
@@ -1239,6 +1242,8 @@ RED.clipboard = (function() {
|
||||
init: function() {
|
||||
setupDialogs();
|
||||
|
||||
$('<textarea type="text" id="red-ui-clipboard-hidden" tabIndex="-1">').appendTo("#red-ui-editor");
|
||||
|
||||
RED.actions.add("core:show-export-dialog",showExportNodes);
|
||||
RED.actions.add("core:show-import-dialog",showImportNodes);
|
||||
|
||||
|
||||
@@ -247,7 +247,7 @@
|
||||
var currentExpression = expressionEditor.getValue();
|
||||
var expr;
|
||||
var usesContext = false;
|
||||
var legacyMode = /(^|[^a-zA-Z0-9_'".])msg([^a-zA-Z0-9_'"]|$)/.test(currentExpression);
|
||||
var legacyMode = /(^|[^a-zA-Z0-9_'"])msg([^a-zA-Z0-9_'"]|$)/.test(currentExpression);
|
||||
$(".red-ui-editor-type-expression-legacy").toggle(legacyMode);
|
||||
try {
|
||||
expr = jsonata(currentExpression);
|
||||
|
||||
@@ -256,10 +256,6 @@ RED.tourGuide = (function() {
|
||||
}
|
||||
$('<div>').css("text-align","left").html(getLocaleText(step.description)).appendTo(stepDescription);
|
||||
|
||||
if (step.image) {
|
||||
$(`<img src="red/tours/${step.image}" />`).appendTo(stepDescription)
|
||||
}
|
||||
|
||||
var stepToolbar = $('<div>',{class:"red-ui-tourGuide-toolbar"}).appendTo(stepContent);
|
||||
|
||||
// var breadcrumbs = $('<div>',{class:"red-ui-tourGuide-breadcrumbs"}).appendTo(stepToolbar);
|
||||
|
||||
@@ -37,6 +37,8 @@ RED.view = (function() {
|
||||
node_height = 30,
|
||||
dblClickInterval = 650;
|
||||
|
||||
var ARROW_HEADS = false;
|
||||
|
||||
var touchLongPressTimeout = 1000,
|
||||
startTouchDistance = 0,
|
||||
startTouchCenter = [],
|
||||
@@ -835,8 +837,9 @@ RED.view = (function() {
|
||||
} else {
|
||||
scale = 0.4-0.2*(Math.max(0,(node_width-Math.min(Math.abs(dx),Math.abs(dy)))/node_width));
|
||||
}
|
||||
var result;
|
||||
if (dx*sc > 0) {
|
||||
return "M "+origX+" "+origY+
|
||||
result = "M "+origX+" "+origY+
|
||||
" C "+(origX+sc*(node_width*scale))+" "+(origY+scaleY*node_height)+" "+
|
||||
(destX-sc*(scale)*node_width)+" "+(destY-scaleY*node_height)+" "+
|
||||
destX+" "+destY
|
||||
@@ -877,7 +880,7 @@ RED.view = (function() {
|
||||
}
|
||||
cp[2][0] = topX;
|
||||
}
|
||||
return "M "+origX+" "+origY+
|
||||
result = "M "+origX+" "+origY+
|
||||
" C "+
|
||||
cp[0][0]+" "+cp[0][1]+" "+
|
||||
cp[1][0]+" "+cp[1][1]+" "+
|
||||
@@ -892,6 +895,7 @@ RED.view = (function() {
|
||||
cp[4][0]+" "+cp[4][1]+" "+
|
||||
destX+" "+destY
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function addNode(type,x,y) {
|
||||
@@ -4131,6 +4135,11 @@ RED.view = (function() {
|
||||
|
||||
}
|
||||
|
||||
node[0][0].__portGroup__ = document.createElementNS("http://www.w3.org/2000/svg","g");
|
||||
node[0][0].__portGroup__.__data__ = d;
|
||||
nodeContents.appendChild(node[0][0].__portGroup__);
|
||||
|
||||
|
||||
var mainRect = document.createElementNS("http://www.w3.org/2000/svg","rect");
|
||||
mainRect.__data__ = d;
|
||||
mainRect.setAttribute("class", "red-ui-flow-node "+(d.type == "unknown"?"red-ui-flow-node-unknown":""));
|
||||
@@ -4334,7 +4343,7 @@ RED.view = (function() {
|
||||
this.__textGroup__.setAttribute("transform", "translate(38,"+yp+")");
|
||||
}
|
||||
|
||||
var inputPorts = thisNode.selectAll(".red-ui-flow-port-input");
|
||||
var inputPorts = d3.select(this.__portGroup__).selectAll(".red-ui-flow-port-input");
|
||||
if ((!isLink || (showAllLinkPorts === -1 && !activeLinkNodes[d.id])) && d.inputs === 0 && !inputPorts.empty()) {
|
||||
inputPorts.each(function(d,i) {
|
||||
RED.hooks.trigger("viewRemovePort",{
|
||||
@@ -4345,8 +4354,9 @@ RED.view = (function() {
|
||||
portIndex: 0
|
||||
})
|
||||
}).remove();
|
||||
this.__inputs__ = [];
|
||||
} else if (((isLink && (showAllLinkPorts===PORT_TYPE_INPUT||activeLinkNodes[d.id]))|| d.inputs === 1) && inputPorts.empty()) {
|
||||
var inputGroup = thisNode.append("g").attr("class","red-ui-flow-port-input");
|
||||
var inputGroup = d3.select(this.__portGroup__).append("g").attr("class","red-ui-flow-port-input");
|
||||
var inputGroupPorts;
|
||||
|
||||
if (d.type === "link in") {
|
||||
@@ -4355,7 +4365,8 @@ RED.view = (function() {
|
||||
.attr("r",5)
|
||||
.attr("class","red-ui-flow-port red-ui-flow-link-port")
|
||||
} else {
|
||||
inputGroupPorts = inputGroup.append("rect").attr("class","red-ui-flow-port").attr("rx",3).attr("ry",3).attr("width",10).attr("height",10)
|
||||
inputGroupPorts = inputGroup.append("path").attr("class","red-ui-flow-port-background").attr("d","M5 -1.5 h -16 v 13 h 16 z")
|
||||
inputGroup.append("path").attr("class","red-ui-flow-port red-ui-flow-port-shape").attr("d","M5 0 h -3 c -4 0 -4 0 -4 4 v 2 c 0 4 0 4 4 4 h 3 z ")
|
||||
}
|
||||
inputGroup[0][0].__port__ = inputGroupPorts[0][0];
|
||||
inputGroupPorts[0][0].__data__ = this.__data__;
|
||||
@@ -4367,6 +4378,8 @@ RED.view = (function() {
|
||||
.on("touchend",function(d){portMouseUp(d,PORT_TYPE_INPUT,0);d3.event.preventDefault();} )
|
||||
.on("mouseover",function(d){portMouseOver(d3.select(this),d,PORT_TYPE_INPUT,0);})
|
||||
.on("mouseout",function(d) {portMouseOut(d3.select(this),d,PORT_TYPE_INPUT,0);});
|
||||
|
||||
this.__inputs__.push(inputGroup[0][0]);
|
||||
RED.hooks.trigger("viewAddPort",{node:d,el: this, port: inputGroup[0][0], portType: "input", portIndex: 0})
|
||||
}
|
||||
var numOutputs = d.outputs;
|
||||
@@ -4403,15 +4416,19 @@ RED.view = (function() {
|
||||
portPort.setAttribute("cy",5);
|
||||
portPort.setAttribute("r",5);
|
||||
portPort.setAttribute("class","red-ui-flow-port red-ui-flow-link-port");
|
||||
portGroup.appendChild(portPort);
|
||||
} else {
|
||||
portPort = document.createElementNS("http://www.w3.org/2000/svg","rect");
|
||||
portPort.setAttribute("rx",3);
|
||||
portPort.setAttribute("ry",3);
|
||||
portPort.setAttribute("width",10);
|
||||
portPort.setAttribute("height",10);
|
||||
portPort.setAttribute("class","red-ui-flow-port");
|
||||
|
||||
portPort = document.createElementNS("http://www.w3.org/2000/svg","path");
|
||||
portPort.setAttribute("d","M5 -1.5 h 16 v 13 h -16 z ");
|
||||
portPort.setAttribute("class","red-ui-flow-port-background");
|
||||
portGroup.appendChild(portPort);
|
||||
|
||||
var visiblePort = document.createElementNS("http://www.w3.org/2000/svg","path");
|
||||
visiblePort.setAttribute("d","M5 0 h 4 c 4 0 4 0 4 4 v 2 c 0 4 0 4 -4 4 h -4 z ");
|
||||
visiblePort.setAttribute("class","red-ui-flow-port red-ui-flow-port-shape");
|
||||
portGroup.appendChild(visiblePort);
|
||||
}
|
||||
portGroup.appendChild(portPort);
|
||||
portGroup.__port__ = portPort;
|
||||
portPort.__data__ = this.__data__;
|
||||
portPort.__portType__ = PORT_TYPE_OUTPUT;
|
||||
@@ -4423,7 +4440,7 @@ RED.view = (function() {
|
||||
portPort.addEventListener("mouseover", portMouseOverProxy);
|
||||
portPort.addEventListener("mouseout", portMouseOutProxy);
|
||||
|
||||
this.appendChild(portGroup);
|
||||
this.__portGroup__.appendChild(portGroup);
|
||||
this.__outputs__.push(portGroup);
|
||||
RED.hooks.trigger("viewAddPort",{node:d,el: this, port: portGroup, portType: "output", portIndex: portIndex})
|
||||
} else {
|
||||
@@ -4514,6 +4531,14 @@ RED.view = (function() {
|
||||
// });
|
||||
}
|
||||
|
||||
for (var i=0,l=this.__outputs__.length;i<l;i++) {
|
||||
this.__outputs__[i].classList.toggle("red-ui-flow-port-connected",RED.nodes.getNodeLinkCount(d.id,PORT_TYPE_OUTPUT,i) > 0 )
|
||||
}
|
||||
for (var i=0,l=this.__inputs__.length;i<l;i++) {
|
||||
this.__inputs__[i].classList.toggle("red-ui-flow-port-connected",RED.nodes.getNodeLinkCount(d.id,PORT_TYPE_INPUT,i) > 0 )
|
||||
}
|
||||
|
||||
|
||||
if (d.dirtyStatus) {
|
||||
redrawStatus(d,this);
|
||||
}
|
||||
@@ -4594,18 +4619,14 @@ RED.view = (function() {
|
||||
d.y1 = d.source.y+y;
|
||||
d.x2 = d.target.x-d.target.w/2;
|
||||
d.y2 = d.target.y;
|
||||
|
||||
// return "M "+d.x1+" "+d.y1+
|
||||
// " C "+(d.x1+scale*node_width)+" "+(d.y1+scaleY*node_height)+" "+
|
||||
// (d.x2-scale*node_width)+" "+(d.y2-scaleY*node_height)+" "+
|
||||
// d.x2+" "+d.y2;
|
||||
var path = generateLinkPath(d.x1,d.y1,d.x2,d.y2,1);
|
||||
var targetOffset = ARROW_HEADS?(d.link?16:13):0
|
||||
var path = generateLinkPath(d.x1+5,d.y1,d.x2-targetOffset,d.y2,1);
|
||||
if (/NaN/.test(path)) {
|
||||
path = ""
|
||||
}
|
||||
this.__pathBack__.setAttribute("d",path);
|
||||
this.__pathOutline__.setAttribute("d",path);
|
||||
this.__pathLine__.setAttribute("d",path);
|
||||
this.__pathLine__.setAttribute("d",path + (ARROW_HEADS?"m0 0, l 0 -2 l 3 2 l -3 2 z":""));
|
||||
this.__pathLine__.classList.toggle("red-ui-flow-node-disabled",!!(d.source.d || d.target.d));
|
||||
this.__pathLine__.classList.toggle("red-ui-flow-subflow-link", !d.link && activeSubflow);
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ RED.workspaces = (function() {
|
||||
var tabId = RED.nodes.id();
|
||||
do {
|
||||
workspaceIndex += 1;
|
||||
} while ($("#red-ui-workspace-tabs li[flowname='"+RED._('workspace.defaultName',{number:workspaceIndex})+"']").size() !== 0);
|
||||
} while ($("#red-ui-workspace-tabs a[title='"+RED._('workspace.defaultName',{number:workspaceIndex})+"']").size() !== 0);
|
||||
|
||||
ws = {
|
||||
type: "tab",
|
||||
@@ -79,15 +79,12 @@ RED.workspaces = (function() {
|
||||
};
|
||||
RED.nodes.addWorkspace(ws,targetIndex);
|
||||
workspace_tabs.addTab(ws,targetIndex);
|
||||
|
||||
workspace_tabs.activateTab(tabId);
|
||||
if (!skipHistoryEntry) {
|
||||
RED.history.push({t:'add',workspaces:[ws],dirty:RED.nodes.dirty()});
|
||||
RED.nodes.dirty(true);
|
||||
}
|
||||
}
|
||||
$("#red-ui-tab-"+(ws.id.replace(".","-"))).attr("flowname",ws.label)
|
||||
|
||||
RED.view.focus();
|
||||
return ws;
|
||||
}
|
||||
@@ -586,7 +583,7 @@ RED.workspaces = (function() {
|
||||
refresh: function() {
|
||||
RED.nodes.eachWorkspace(function(ws) {
|
||||
workspace_tabs.renameTab(ws.id,ws.label);
|
||||
$("#red-ui-tab-"+(ws.id.replace(".","-"))).attr("flowname",ws.label)
|
||||
|
||||
})
|
||||
RED.nodes.eachSubflow(function(sf) {
|
||||
if (workspace_tabs.contains(sf.id)) {
|
||||
|
||||
@@ -196,6 +196,12 @@ $view-background: $secondary-background;
|
||||
$view-select-mode-background: $secondary-background-selected;
|
||||
$view-grid-color: #eee;
|
||||
|
||||
$link-color: #999;
|
||||
$link-link-color: #aaa;
|
||||
$link-disabled-color: #ccc;
|
||||
$link-link-active-color: #ff7f0e;
|
||||
$link-unknown-color: #f00;
|
||||
|
||||
$node-label-color: #333;
|
||||
$node-port-label-color: #888;
|
||||
$node-border: #999;
|
||||
@@ -203,8 +209,13 @@ $node-border-unknown: #f33;
|
||||
$node-border-placeholder: #aaa;
|
||||
$node-background-placeholder: #eee;
|
||||
|
||||
$node-port-border: $node-border;
|
||||
$node-port-border-connected: $link-color;
|
||||
|
||||
$node-port-background: #d9d9d9;
|
||||
$node-port-background-hover: #eee;
|
||||
$node-port-background-connected: $link-color;
|
||||
|
||||
$node-icon-color: #fff;
|
||||
$node-icon-background-color: rgba(0,0,0,0.05);
|
||||
$node-icon-background-color-fill: #000;
|
||||
@@ -232,12 +243,6 @@ $node-status-colors: (
|
||||
$node-selected-color: #ff7f0e;
|
||||
$port-selected-color: #ff7f0e;
|
||||
|
||||
$link-color: #999;
|
||||
$link-link-color: #aaa;
|
||||
$link-disabled-color: #ccc;
|
||||
$link-link-active-color: #ff7f0e;
|
||||
$link-unknown-color: #f00;
|
||||
|
||||
$clipboard-textarea-background: #F3E7E7;
|
||||
|
||||
|
||||
|
||||
@@ -356,6 +356,10 @@ button.red-ui-button-small
|
||||
background: $secondary-background;
|
||||
}
|
||||
|
||||
#red-ui-clipboard-hidden {
|
||||
position: absolute;
|
||||
top: -3000px;
|
||||
}
|
||||
.form-row .red-ui-editor-node-label-form-row {
|
||||
margin: 5px 0 0 50px;
|
||||
label {
|
||||
|
||||
@@ -185,12 +185,29 @@
|
||||
}
|
||||
|
||||
.red-ui-flow-port {
|
||||
stroke: $node-border;
|
||||
stroke: $node-port-border;
|
||||
stroke-width: 1;
|
||||
fill: $node-port-background;
|
||||
cursor: crosshair;
|
||||
}
|
||||
|
||||
.red-ui-flow-port-background {
|
||||
opacity: 0;
|
||||
stroke: none;
|
||||
fill: #f00;
|
||||
cursor: crosshair;
|
||||
}
|
||||
.red-ui-flow-port-shape {
|
||||
pointer-events: none;
|
||||
cursor: crosshair;
|
||||
}
|
||||
|
||||
.red-ui-flow-port-connected .red-ui-flow-port {
|
||||
fill: $node-port-background-connected;
|
||||
stroke: $node-port-border-connected;
|
||||
}
|
||||
|
||||
|
||||
.red-ui-flow-node-error {
|
||||
fill: $node-status-error-background;
|
||||
stroke: $node-status-error-border;
|
||||
@@ -280,9 +297,10 @@ g.red-ui-flow-node-selected {
|
||||
text-anchor:start;
|
||||
}
|
||||
|
||||
.red-ui-flow-port-hovered {
|
||||
stroke: $port-selected-color;
|
||||
fill: $port-selected-color;
|
||||
.red-ui-flow-port-hovered:not(.red-ui-flow-port-background),
|
||||
.red-ui-flow-port-background.red-ui-flow-port-hovered + .red-ui-flow-port-shape {
|
||||
stroke: $port-selected-color !important;
|
||||
fill: $port-selected-color !important;
|
||||
}
|
||||
|
||||
.red-ui-flow-subflow-port {
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 29 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 70 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 81 KiB |
@@ -1,12 +1,12 @@
|
||||
export default {
|
||||
version: "2.2.0",
|
||||
version: "2.1.0",
|
||||
steps: [
|
||||
{
|
||||
titleIcon: "fa fa-map-o",
|
||||
title: {
|
||||
"en-US": "Welcome to Node-RED 2.2!",
|
||||
"ja": "Node-RED 2.2へようこそ!"
|
||||
},
|
||||
"en-US": "Welcome to Node-RED 2.1!",
|
||||
"ja": "Node-RED 2.1へようこそ!"
|
||||
},
|
||||
description: {
|
||||
"en-US": "Let's take a moment to discover the new features in this release.",
|
||||
"ja": "本リリースの新機能を見つけてみましょう。"
|
||||
@@ -14,84 +14,215 @@ export default {
|
||||
},
|
||||
{
|
||||
title: {
|
||||
"en-US": "Search history",
|
||||
"en-US": "A new Tour Guide",
|
||||
"ja": "新しいツアーガイド"
|
||||
},
|
||||
description: {
|
||||
"en-US": "<p>The Search dialog now keeps a history of your searches, making it easier to go back to a previous search.</p>"
|
||||
"en-US": "<p>First, as you've already found, we now have this tour of new features. We'll only show the tour the first time you open the editor for each new version of Node-RED.</p>" +
|
||||
"<p>You can choose not to see this tour in the future by disabling it under the View tab of User Settings.</p>",
|
||||
"ja": "<p>最初に、既に見つけている様に、新機能の本ツアーがあります。本ツアーは、新バージョンのNode-REDフローエディタを初めて開いた時のみ表示されます。</p>" +
|
||||
"<p>ユーザ設定の表示タブの中で、この機能を無効化することで、本ツアーを表示しないようにすることもできます。</p>"
|
||||
}
|
||||
},
|
||||
{
|
||||
title: {
|
||||
"en-US": "New Edit menu",
|
||||
"ja": "新しい編集メニュー"
|
||||
},
|
||||
element: "#red-ui-search .red-ui-searchBox-form",
|
||||
prepare(done) {
|
||||
RED.search.show();
|
||||
setTimeout(done,400);
|
||||
prepare() {
|
||||
$("#red-ui-header-button-sidemenu").trigger("click");
|
||||
$("#menu-item-edit-menu").parent().addClass("open");
|
||||
},
|
||||
complete() {
|
||||
RED.search.hide();
|
||||
$("#menu-item-edit-menu").parent().removeClass("open");
|
||||
},
|
||||
},
|
||||
{
|
||||
title: {
|
||||
"en-US": "New wiring actions",
|
||||
},
|
||||
// image: "images/",
|
||||
element: "#menu-item-edit-menu-submenu",
|
||||
interactive: false,
|
||||
direction: "left",
|
||||
description: {
|
||||
"en-US": `<p>A pair of new actions have been added to help with wiring nodes together:</p>
|
||||
<ul>
|
||||
<li><b><code>Wire Series Of Nodes</code></b> - adds a wire (if necessary) between each pair of nodes in the order they were selected.</li>
|
||||
<li><b><code>Wire Node To Multiple</code></b> - wires the first node selected to all of the other selected nodes.</li>
|
||||
</ul>
|
||||
<p>Actions can be accessed from the Action List in the main menu.</p>`
|
||||
},
|
||||
},
|
||||
{
|
||||
title: {
|
||||
"en-US": "Deleting nodes and reconnecting wires",
|
||||
},
|
||||
image: "images/delete-repair.gif",
|
||||
description: {
|
||||
"en-US": `<p>It is now possible to delete a selection of nodes and automatically repair the wiring behind them.</p>
|
||||
<p>This is really useful if you want to remove a node from the middle of the flow.</p>
|
||||
<p>Hold the Ctrl (or Cmd) key when you press Delete and the nodes will be gone and the wires repaired.</p>
|
||||
`
|
||||
"en-US": "<p>The main menu has been updated with a new 'Edit' section. This includes all of the familar options, like cut/paste and undo/redo.</p>" +
|
||||
"<p>The menu now displays keyboard shortcuts for the options.</p>",
|
||||
"ja": "<p>メインメニューに「編集」セクションが追加されました。本セクションには、切り取り/貼り付けや、変更操作を戻す/やり直しの様な使い慣れたオプションが含まれています。</p>" +
|
||||
"<p>本メニューには、オプションのためのキーボードショートカットも表示されるようになりました。</p>"
|
||||
}
|
||||
},
|
||||
{
|
||||
title: {
|
||||
"en-US": "Detaching nodes from a flow",
|
||||
"en-US": "Arranging nodes",
|
||||
"ja": "ノードの配置"
|
||||
},
|
||||
image: "images/detach-repair.gif",
|
||||
prepare() {
|
||||
$("#red-ui-header-button-sidemenu").trigger("click");
|
||||
$("#menu-item-arrange-menu").parent().addClass("open");
|
||||
},
|
||||
complete() {
|
||||
$("#menu-item-arrange-menu").parent().removeClass("open");
|
||||
},
|
||||
element: "#menu-item-arrange-menu-submenu",
|
||||
interactive: false,
|
||||
direction: "left",
|
||||
description: {
|
||||
"en-US": `<p>If you want to remove a node from a flow without deleting it,
|
||||
you can use the <b><code>Detach Selected Nodes</code></b> action.</p>
|
||||
<p>The nodes will be removed from their flow, the wiring repaired behind them, and then attached to the mouse
|
||||
so you can drop them wherever you want in the workspace.</p>
|
||||
<p>There isn't a default keyboard shortcut assigned for this new action, but
|
||||
you can add your own via the Keyboard pane of the main Settings dialog.</p>`
|
||||
"en-US": "<p>The new 'Arrange' section of the menu provides new options to help arrange your nodes. You can align them to a common edge, spread them out evenly or change their order.</p>",
|
||||
"ja": "<p>メニューの新しい「配置」セクションには、ノードの配置を助ける新しいオプションが提供されています。ノードの端を揃えたり、均等に配置したり、表示順序を変更したりできます。</p>"
|
||||
}
|
||||
},
|
||||
{
|
||||
title: {
|
||||
"en-US": "More wiring tricks",
|
||||
"en-US": "Hiding tabs",
|
||||
"ja": "タブの非表示"
|
||||
},
|
||||
image: "images/slice.gif",
|
||||
element: "#red-ui-workspace-tabs > li.active",
|
||||
description: {
|
||||
"en-US": `<p>A couple more wiring tricks to share.</p>
|
||||
<p>You can now select multiple wires by holding the Ctrl (or Cmd) key
|
||||
when clicking on a wire. This makes it easier to delete multiple wires in one go.</p>
|
||||
<p>If you hold the Ctrl (or Cmd) key, then click and drag with the right-hand mouse button,
|
||||
you can slice through wires to remove them.</p>`
|
||||
"en-US": '<p>Tabs can now be hidden by clicking their <i class="fa fa-eye-slash"></i> icon.</p><p>The Info Sidebar will still list all of your tabs, and tell you which ones are currently hidden.',
|
||||
"ja": '<p><i class="fa fa-eye-slash"></i> アイコンをクリックすることで、タブを非表示にできます。</p><p>情報サイドバーには、全てのタブが一覧表示されており、現在非表示になっているタブを確認できます。'
|
||||
},
|
||||
interactive: false,
|
||||
prepare() {
|
||||
$("#red-ui-workspace-tabs > li.active .red-ui-tab-close").css("display","block");
|
||||
},
|
||||
complete() {
|
||||
$("#red-ui-workspace-tabs > li.active .red-ui-tab-close").css("display","");
|
||||
}
|
||||
},
|
||||
{
|
||||
title: {
|
||||
"en-US": "Node Updates",
|
||||
"en-US": "Tab menu",
|
||||
"ja": "タブメニュー"
|
||||
},
|
||||
// image: "images/",
|
||||
element: "#red-ui-workspace-tabs-menu",
|
||||
description: {
|
||||
"en-US": `<ul>
|
||||
<li>The JSON node will now handle parsing Buffer payloads</li>
|
||||
<li>The TCP Client nodes support TLS connections</li>
|
||||
<li>The WebSocket node allows you to specify a sub-protocol when connecting</li>
|
||||
</ul>`
|
||||
"en-US": "<p>The new tab menu also provides lots of new options for your tabs.</p>",
|
||||
"ja": "<p>新しいタブメニューには、タブに関する沢山の新しいオプションが提供されています。</p>"
|
||||
},
|
||||
interactive: false,
|
||||
direction: "left",
|
||||
prepare() {
|
||||
$("#red-ui-workspace > .red-ui-tabs > .red-ui-tabs-menu a").trigger("click");
|
||||
},
|
||||
complete() {
|
||||
$(document).trigger("click");
|
||||
}
|
||||
},
|
||||
{
|
||||
title: {
|
||||
"en-US": "Flow and Group level environment variables",
|
||||
"ja": "フローとグループの環境変数"
|
||||
},
|
||||
element: "#red-ui-workspace-tabs > li.active",
|
||||
interactive: false,
|
||||
description: {
|
||||
"en-US": "<p>Flows and Groups can now have their own environment variables that can be referenced by nodes inside them.</p>",
|
||||
"ja": "<p>フローとグループには、内部のノードから参照できる環境変数を設定できるようになりました。</p>"
|
||||
}
|
||||
},
|
||||
{
|
||||
prepare(done) {
|
||||
RED.editor.editFlow(RED.nodes.workspace(RED.workspaces.active()),"editor-tab-envProperties");
|
||||
setTimeout(done,700);
|
||||
},
|
||||
element: "#red-ui-tab-editor-tab-envProperties-link-button",
|
||||
description: {
|
||||
"en-US": "<p>Their edit dialogs have a new Environment Variables section.</p>",
|
||||
"ja": "<p>編集ダイアログに環境変数セクションが追加されました。</p>"
|
||||
}
|
||||
},
|
||||
{
|
||||
element: ".node-input-env-container-row",
|
||||
direction: "left",
|
||||
description: {
|
||||
"en-US": '<p>The environment variables are listed in this table and new ones can be added by clicking the <i class="fa fa-plus"></i> button.</p>',
|
||||
"ja": '<p>この表に環境変数が一覧表示されており、<i class="fa fa-plus"></i>ボタンをクリックすることで新しい変数を追加できます。</p>'
|
||||
},
|
||||
complete(done) {
|
||||
$("#node-dialog-cancel").trigger("click");
|
||||
setTimeout(done,500);
|
||||
}
|
||||
},
|
||||
{
|
||||
title: {
|
||||
"en-US": "Link Call node added",
|
||||
"ja": "Link Callノードを追加"
|
||||
},
|
||||
prepare(done) {
|
||||
this.paletteWasClosed = $("#red-ui-main-container").hasClass("red-ui-palette-closed");
|
||||
RED.actions.invoke("core:toggle-palette",true)
|
||||
$('[data-palette-type="link call"]')[0].scrollIntoView({block:"center"})
|
||||
setTimeout(done,100);
|
||||
},
|
||||
element: '[data-palette-type="link call"]',
|
||||
direction: "right",
|
||||
description: {
|
||||
"en-US": "<p>The <code>Link Call</code> node lets you call another flow that begins with a <code>Link In</code> node and get the result back when the message reaches a <code>Link Out</code> node.</p>",
|
||||
"ja": "<p><code>Link Call</code>ノードを用いることで、<code>Link In</code>ノードから始まるフローを呼び出し、<code>Link Out</code>ノードに到達した時に、結果を取得できます。</p>"
|
||||
}
|
||||
},
|
||||
{
|
||||
title: {
|
||||
"en-US": "MQTT nodes support dynamic connections",
|
||||
"ja": "MQTTノードが動的接続をサポート"
|
||||
},
|
||||
prepare(done) {
|
||||
$('[data-palette-type="mqtt out"]')[0].scrollIntoView({block:"center"})
|
||||
setTimeout(done,100);
|
||||
},
|
||||
element: '[data-palette-type="mqtt out"]',
|
||||
direction: "right",
|
||||
description: {
|
||||
"en-US": '<p>The <code>MQTT</code> nodes now support creating their connections and subscriptions dynamically.</p>',
|
||||
"ja": '<p><code>MQTT</code>ノードは、動的な接続や購読ができるようになりました。</p>'
|
||||
},
|
||||
},
|
||||
{
|
||||
title: {
|
||||
"en-US": "File nodes renamed",
|
||||
"ja": "ファイルノードの名前変更"
|
||||
},
|
||||
prepare(done) {
|
||||
$('[data-palette-type="file"]')[0].scrollIntoView({block:"center"});
|
||||
setTimeout(done,100);
|
||||
},
|
||||
complete() {
|
||||
if (this.paletteWasClosed) {
|
||||
RED.actions.invoke("core:toggle-palette",false)
|
||||
}
|
||||
},
|
||||
element: '[data-palette-type="file"]',
|
||||
direction: "right",
|
||||
description: {
|
||||
"en-US": "<p>The file nodes have been renamed to make it clearer which node does what.</p>",
|
||||
"ja": "<p>fileノードの名前が変更され、どのノードが何を行うかが明確になりました。</p>"
|
||||
}
|
||||
},
|
||||
{
|
||||
title: {
|
||||
"en-US": "Deep copy option on Change node",
|
||||
"ja": "Changeノードのディープコピーオプション"
|
||||
},
|
||||
prepare(done) {
|
||||
var def = RED.nodes.getType('change');
|
||||
RED.editor.edit({id:"test",type:"change",rules:[{t:"set",p:"payload",pt:"msg", tot:"msg",to:"anotherProperty"}],_def:def, _:def._});
|
||||
setTimeout(done,700);
|
||||
},
|
||||
complete(done) {
|
||||
$("#node-dialog-cancel").trigger("click");
|
||||
setTimeout(done,500);
|
||||
},
|
||||
element: function() {
|
||||
return $(".node-input-rule-property-deepCopy").next();
|
||||
},
|
||||
description: {
|
||||
"en-US": "<p>The Set rule has a new option to create a deep copy of the value. This ensures a complete copy is made, rather than using a reference.</p>",
|
||||
"ja": "<p>値を代入に、値のディープコピーを作成するオプションが追加されました。これによって参照ではなく、完全なコピーが作成されます。</p>"
|
||||
}
|
||||
},
|
||||
{
|
||||
title: {
|
||||
"en-US": "And that's not all...",
|
||||
"ja": "これが全てではありません..."
|
||||
},
|
||||
description: {
|
||||
"en-US": "<p>There are many more smaller changes, including:</p><ul><li>Auto-complete suggestions in the <code>msg</code> TypedInput.</li><li>Support for <code>msg.resetTimeout</code> in the <code>Join</code> node.</li><li>Pushing messages to the front of the queue in the <code>Delay</code> node's rate limiting mode.</li><li>An optional second output on the <code>Delay</code> node for rate limited messages.</li></ul>",
|
||||
"ja": "<p>以下の様な小さな変更が沢山あります:</p><ul><li><code>msg</code> TypedInputの自動補完提案</li><li><code>Join</code>ノードで<code>msg.resetTimeout</code>のサポート</li><li><code>Delay</code>ノードの流量制御モードにおいて先頭メッセージをキューに追加</li><li><code>Delay</code>ノードで流量制限されたメッセージ向けの任意の2つ目の出力</li></ul>"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@@ -91,21 +91,21 @@
|
||||
<div id="func-tab-init" style="display:none">
|
||||
<div class="form-row node-text-editor-row" style="position:relative">
|
||||
<div style="height: 250px; min-height:150px;" class="node-text-editor" id="node-input-init-editor" ></div>
|
||||
<div style="position: absolute; right:0; bottom: calc(100% - 20px); z-Index: 10;"><button id="node-init-expand-js" class="red-ui-button red-ui-button-small"><i class="fa fa-expand"></i></button></div>
|
||||
<div style="position: absolute; right:0; bottom: calc(100% - 20px); z-Index: 5;"><button id="node-init-expand-js" class="red-ui-button red-ui-button-small"><i class="fa fa-expand"></i></button></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="func-tab-body" style="display:none">
|
||||
<div class="form-row node-text-editor-row" style="position:relative">
|
||||
<div style="height: 220px; min-height:150px;" class="node-text-editor" id="node-input-func-editor" ></div>
|
||||
<div style="position: absolute; right:0; bottom: calc(100% - 20px); z-Index: 10;"><button id="node-function-expand-js" class="red-ui-button red-ui-button-small"><i class="fa fa-expand"></i></button></div>
|
||||
<div style="position: absolute; right:0; bottom: calc(100% - 20px); z-Index: 5;"><button id="node-function-expand-js" class="red-ui-button red-ui-button-small"><i class="fa fa-expand"></i></button></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="func-tab-finalize" style="display:none">
|
||||
<div class="form-row node-text-editor-row" style="position:relative">
|
||||
<div style="height: 250px; min-height:150px;" class="node-text-editor" id="node-input-finalize-editor" ></div>
|
||||
<div style="position: absolute; right:0; bottom: calc(100% - 20px); z-Index: 10;"><button id="node-finalize-expand-js" class="red-ui-button red-ui-button-small"><i class="fa fa-expand"></i></button></div>
|
||||
<div style="position: absolute; right:0; bottom: calc(100% - 20px); z-Index: 5;"><button id="node-finalize-expand-js" class="red-ui-button red-ui-button-small"><i class="fa fa-expand"></i></button></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -111,24 +111,22 @@ module.exports = function(RED) {
|
||||
if (node.isServer) {
|
||||
node._clients[id] = socket;
|
||||
node.emit('opened',{count:Object.keys(node._clients).length,id:id});
|
||||
} else {
|
||||
if (node.heartbeat) {
|
||||
node.heartbeatInterval = setInterval(function() {
|
||||
if (socket.nrPendingHeartbeat) {
|
||||
// No pong received
|
||||
socket.terminate();
|
||||
socket.nrErrorHandler(new Error("timeout"));
|
||||
return;
|
||||
}
|
||||
socket.nrPendingHeartbeat = true;
|
||||
socket.ping();
|
||||
},node.heartbeat);
|
||||
}
|
||||
}
|
||||
socket.on('open',function() {
|
||||
if (!node.isServer) {
|
||||
if (node.heartbeat) {
|
||||
clearInterval(node.heartbeatInterval);
|
||||
node.heartbeatInterval = setInterval(function() {
|
||||
if (socket.nrPendingHeartbeat) {
|
||||
// No pong received
|
||||
socket.terminate();
|
||||
socket.nrErrorHandler(new Error("timeout"));
|
||||
return;
|
||||
}
|
||||
socket.nrPendingHeartbeat = true;
|
||||
try {
|
||||
socket.ping();
|
||||
} catch(err) {}
|
||||
},node.heartbeat);
|
||||
}
|
||||
node.emit('opened',{count:'',id:id});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -49,11 +49,7 @@ module.exports = function(RED) {
|
||||
}
|
||||
var value = RED.util.getMessageProperty(msg,node.property);
|
||||
if (value !== undefined) {
|
||||
if (typeof value === "string" || Buffer.isBuffer(value)) {
|
||||
// if (Buffer.isBuffer(value) && node.action !== "obj") {
|
||||
// node.warn(RED._("json.errors.dropped")); done();
|
||||
// }
|
||||
// else
|
||||
if (typeof value === "string") {
|
||||
if (node.action === "" || node.action === "obj") {
|
||||
try {
|
||||
RED.util.setMessageProperty(msg,node.property,JSON.parse(value));
|
||||
|
||||
@@ -15,10 +15,10 @@
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"acorn": "8.7.0",
|
||||
"acorn": "8.6.0",
|
||||
"acorn-walk": "8.2.0",
|
||||
"ajv": "8.8.2",
|
||||
"body-parser": "1.19.1",
|
||||
"body-parser": "1.19.0",
|
||||
"cheerio": "1.0.0-rc.10",
|
||||
"content-type": "1.0.4",
|
||||
"cookie-parser": "1.4.6",
|
||||
@@ -36,7 +36,7 @@
|
||||
"is-utf8": "0.2.1",
|
||||
"js-yaml": "3.14.1",
|
||||
"media-typer": "1.1.0",
|
||||
"mqtt": "4.3.4",
|
||||
"mqtt": "4.2.8",
|
||||
"multer": "1.4.3",
|
||||
"mustache": "4.2.0",
|
||||
"on-headers": "1.0.2",
|
||||
|
||||
@@ -21,6 +21,6 @@
|
||||
"fs-extra": "10.0.0",
|
||||
"semver": "7.3.5",
|
||||
"tar": "6.1.11",
|
||||
"uglify-js": "3.14.5"
|
||||
"uglify-js": "3.14.4"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
"@node-red/util": "2.2.0-beta.1",
|
||||
"async-mutex": "0.3.2",
|
||||
"clone": "2.1.2",
|
||||
"express": "4.17.2",
|
||||
"express": "4.17.1",
|
||||
"fs-extra": "10.0.0",
|
||||
"json-stringify-safe": "5.0.1"
|
||||
}
|
||||
|
||||
@@ -32,14 +32,8 @@ function wrapEventFunction(obj,func) {
|
||||
return function(eventName, listener) {
|
||||
if (deprecatedEvents.hasOwnProperty(eventName)) {
|
||||
const log = require("@node-red/util").log;
|
||||
|
||||
const stack = (new Error().stack).split("\n");
|
||||
let location = "(unknown)"
|
||||
// See https://github.com/node-red/node-red/issues/3292
|
||||
if (stack.length > 2) {
|
||||
location = stack[2].split("(")[1].slice(0,-1);
|
||||
}
|
||||
log.warn(`[RED.events] Deprecated use of "${eventName}" event from "${location}". Use "${deprecatedEvents[eventName]}" instead.`)
|
||||
const stack = (new Error().stack).split("\n")[2].split("(")[1].slice(0,-1);
|
||||
log.warn(`[RED.events] Deprecated use of "${eventName}" event from "${stack}". Use "${deprecatedEvents[eventName]}" instead.`)
|
||||
}
|
||||
return events["_"+func].call(events,eventName,listener)
|
||||
}
|
||||
|
||||
@@ -686,7 +686,7 @@ function prepareJSONataExpression(value,node) {
|
||||
return moment(arg1, arg2, arg3, arg4);
|
||||
});
|
||||
expr.registerFunction('clone', cloneMessage, '<(oa)-:o>');
|
||||
expr._legacyMode = /(^|[^a-zA-Z0-9_'".])msg([^a-zA-Z0-9_'"]|$)/.test(value);
|
||||
expr._legacyMode = /(^|[^a-zA-Z0-9_'"])msg([^a-zA-Z0-9_'"]|$)/.test(value);
|
||||
expr._node = node;
|
||||
return expr;
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"fs-extra": "10.0.0",
|
||||
"i18next": "21.6.6",
|
||||
"i18next": "21.5.4",
|
||||
"json-stringify-safe": "5.0.1",
|
||||
"jsonata": "1.8.5",
|
||||
"lodash.clonedeep": "^4.5.0",
|
||||
|
||||
2
packages/node_modules/node-red/package.json
vendored
2
packages/node_modules/node-red/package.json
vendored
@@ -37,7 +37,7 @@
|
||||
"@node-red/nodes": "2.2.0-beta.1",
|
||||
"basic-auth": "2.0.1",
|
||||
"bcryptjs": "2.4.3",
|
||||
"express": "4.17.2",
|
||||
"express": "4.17.1",
|
||||
"fs-extra": "10.0.0",
|
||||
"node-red-admin": "^2.2.1",
|
||||
"nopt": "5.0.0",
|
||||
|
||||
@@ -50,24 +50,6 @@ describe('JSON node', function() {
|
||||
});
|
||||
});
|
||||
|
||||
it('should convert a buffer of a valid json string to a javascript object', function(done) {
|
||||
var flow = [{id:"jn1",type:"json",action:"obj",wires:[["jn2"]]},
|
||||
{id:"jn2", type:"helper"}];
|
||||
helper.load(jsonNode, flow, function() {
|
||||
var jn1 = helper.getNode("jn1");
|
||||
var jn2 = helper.getNode("jn2");
|
||||
jn2.on("input", function(msg) {
|
||||
msg.should.have.property('topic', 'bar');
|
||||
msg.payload.should.have.property('employees');
|
||||
msg.payload.employees[0].should.have.property('firstName', 'John');
|
||||
msg.payload.employees[0].should.have.property('lastName', 'Smith');
|
||||
done();
|
||||
});
|
||||
var jsonString = Buffer.from('{"employees":[{"firstName":"John", "lastName":"Smith"}]}');
|
||||
jn1.receive({payload:jsonString,topic: "bar"});
|
||||
});
|
||||
});
|
||||
|
||||
it('should convert a javascript object to a json string', function(done) {
|
||||
var flow = [{id:"jn1",type:"json",wires:[["jn2"]]},
|
||||
{id:"jn2", type:"helper"}];
|
||||
@@ -184,55 +166,29 @@ describe('JSON node', function() {
|
||||
});
|
||||
});
|
||||
|
||||
it('should log an error if asked to parse an invalid json string in a buffer', function(done) {
|
||||
var flow = [{id:"jn1",type:"json",action:"obj",wires:[["jn2"]]},
|
||||
it('should log an error if asked to parse something thats not json or js', function(done) {
|
||||
var flow = [{id:"jn1",type:"json",wires:[["jn2"]]},
|
||||
{id:"jn2", type:"helper"}];
|
||||
helper.load(jsonNode, flow, function() {
|
||||
try {
|
||||
var jn1 = helper.getNode("jn1");
|
||||
var jn2 = helper.getNode("jn2");
|
||||
jn1.receive({payload:Buffer.from('{"name":foo}'),topic: "bar"});
|
||||
setTimeout(function() {
|
||||
try {
|
||||
var logEvents = helper.log().args.filter(function(evt) {
|
||||
return evt[0].type == "json";
|
||||
});
|
||||
logEvents.should.have.length(1);
|
||||
logEvents[0][0].should.have.a.property('msg');
|
||||
logEvents[0][0].msg.should.startWith("Unexpected token o");
|
||||
logEvents[0][0].should.have.a.property('level',helper.log().ERROR);
|
||||
done();
|
||||
} catch(err) { done(err) }
|
||||
},20);
|
||||
} catch(err) {
|
||||
done(err);
|
||||
}
|
||||
var jn1 = helper.getNode("jn1");
|
||||
var jn2 = helper.getNode("jn2");
|
||||
setTimeout(function() {
|
||||
try {
|
||||
var logEvents = helper.log().args.filter(function(evt) {
|
||||
return evt[0].type == "json";
|
||||
});
|
||||
logEvents.should.have.length(1);
|
||||
logEvents[0][0].should.have.a.property('msg');
|
||||
logEvents[0][0].msg.toString().should.eql('json.errors.dropped-object');
|
||||
done();
|
||||
} catch(err) {
|
||||
done(err);
|
||||
}
|
||||
},50);
|
||||
jn1.receive({payload:Buffer.from("a")});
|
||||
});
|
||||
});
|
||||
|
||||
// it('should log an error if asked to parse something thats not json or js and not in force object mode', function(done) {
|
||||
// var flow = [{id:"jn1",type:"json",wires:[["jn2"]]},
|
||||
// {id:"jn2", type:"helper"}];
|
||||
// helper.load(jsonNode, flow, function() {
|
||||
// var jn1 = helper.getNode("jn1");
|
||||
// var jn2 = helper.getNode("jn2");
|
||||
// setTimeout(function() {
|
||||
// try {
|
||||
// var logEvents = helper.log().args.filter(function(evt) {
|
||||
// return evt[0].type == "json";
|
||||
// });
|
||||
// logEvents.should.have.length(1);
|
||||
// logEvents[0][0].should.have.a.property('msg');
|
||||
// logEvents[0][0].msg.toString().should.eql('json.errors.dropped');
|
||||
// done();
|
||||
// } catch(err) {
|
||||
// done(err);
|
||||
// }
|
||||
// },50);
|
||||
// jn1.receive({payload:Buffer.from("abcd")});
|
||||
// });
|
||||
// });
|
||||
|
||||
it('should pass straight through if no payload set', function(done) {
|
||||
var flow = [{id:"jn1",type:"json",wires:[["jn2"]]},
|
||||
{id:"jn2", type:"helper"}];
|
||||
|
||||
Reference in New Issue
Block a user