@node-red/editor-client 3.1.0-beta.2 → 3.1.0-beta.3

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.
Files changed (43) hide show
  1. package/locales/en-US/editor.json +1 -0
  2. package/locales/ja/editor.json +2 -1
  3. package/package.json +1 -1
  4. package/public/red/about +35 -0
  5. package/public/red/red.js +194 -125
  6. package/public/red/red.min.js +3 -3
  7. package/public/red/style.min.css +1 -1
  8. package/public/red/tours/welcome.js +30 -11
  9. package/public/types/node/crypto.d.ts +13 -6
  10. package/public/types/node/dns.d.ts +1 -1
  11. package/public/types/node/globals.d.ts +1 -1
  12. package/public/types/node/stream.d.ts +99 -0
  13. package/public/types/node/test.d.ts +2 -2
  14. package/public/types/node-red/func.d.ts +2 -3
  15. package/public/vendor/mermaid/mermaid.min.js +713 -417
  16. package/public/vendor/monaco/dist/css.worker.js +1 -1
  17. package/public/vendor/monaco/dist/css.worker.js.LICENSE.txt +1 -1
  18. package/public/vendor/monaco/dist/editor.js +29 -1
  19. package/public/vendor/monaco/dist/editor.js.LICENSE.txt +1 -1
  20. package/public/vendor/monaco/dist/editor.worker.js +1 -1
  21. package/public/vendor/monaco/dist/fa2cc0ab9f0bec2b3365.ttf +0 -0
  22. package/public/vendor/monaco/dist/html.worker.js +1 -1
  23. package/public/vendor/monaco/dist/html.worker.js.LICENSE.txt +1 -1
  24. package/public/vendor/monaco/dist/json.worker.js +1 -1
  25. package/public/vendor/monaco/dist/json.worker.js.LICENSE.txt +1 -1
  26. package/public/vendor/monaco/dist/locale/cs.js +100 -39
  27. package/public/vendor/monaco/dist/locale/de.js +100 -39
  28. package/public/vendor/monaco/dist/locale/es.js +100 -39
  29. package/public/vendor/monaco/dist/locale/fr.js +100 -39
  30. package/public/vendor/monaco/dist/locale/it.js +100 -39
  31. package/public/vendor/monaco/dist/locale/ja.js +101 -40
  32. package/public/vendor/monaco/dist/locale/ko.js +100 -39
  33. package/public/vendor/monaco/dist/locale/pl.js +100 -39
  34. package/public/vendor/monaco/dist/locale/pt-br.js +102 -41
  35. package/public/vendor/monaco/dist/locale/qps-ploc.js +100 -39
  36. package/public/vendor/monaco/dist/locale/ru.js +100 -39
  37. package/public/vendor/monaco/dist/locale/tr.js +100 -39
  38. package/public/vendor/monaco/dist/locale/zh-hans.js +101 -40
  39. package/public/vendor/monaco/dist/locale/zh-hant.js +100 -39
  40. package/public/vendor/monaco/dist/theme/forge-dark.json +213 -0
  41. package/public/vendor/monaco/dist/theme/forge-light.json +227 -0
  42. package/public/vendor/monaco/dist/ts.worker.js +6 -1
  43. package/public/vendor/vendor.js +2 -2
package/public/red/red.js CHANGED
@@ -354,6 +354,7 @@ var RED = (function() {
354
354
  setTimeout(() => {
355
355
  RED.view.reveal(nodeToShow.id)
356
356
  window.location.hash = currentHash
357
+ RED.view.select(nodeToShow.id)
357
358
  if (showEditDialog) {
358
359
  RED.editor.edit(nodeToShow)
359
360
  }
@@ -364,6 +365,7 @@ var RED = (function() {
364
365
  if (nodeToShow) {
365
366
  RED.view.reveal(nodeToShow.id)
366
367
  window.location.hash = currentHash
368
+ RED.view.select(nodeToShow.id)
367
369
  if (showEditDialog) {
368
370
  RED.editor.editGroup(nodeToShow)
369
371
  }
@@ -1380,8 +1382,8 @@ RED.settings = (function () {
1380
1382
  if (!hasLocalStorage()) {
1381
1383
  return;
1382
1384
  }
1383
- if (key === "auth-tokens") {
1384
- localStorage.setItem(key, JSON.stringify(value));
1385
+ if (key.startsWith("auth-tokens")) {
1386
+ localStorage.setItem(key+this.authTokensSuffix, JSON.stringify(value));
1385
1387
  } else {
1386
1388
  RED.utils.setMessageProperty(userSettings,key,value);
1387
1389
  saveUserSettings();
@@ -1399,8 +1401,8 @@ RED.settings = (function () {
1399
1401
  if (!hasLocalStorage()) {
1400
1402
  return undefined;
1401
1403
  }
1402
- if (key === "auth-tokens") {
1403
- return JSON.parse(localStorage.getItem(key));
1404
+ if (key.startsWith("auth-tokens")) {
1405
+ return JSON.parse(localStorage.getItem(key+this.authTokensSuffix));
1404
1406
  } else {
1405
1407
  var v;
1406
1408
  try { v = RED.utils.getMessageProperty(userSettings,key); } catch(err) {}
@@ -1418,8 +1420,8 @@ RED.settings = (function () {
1418
1420
  if (!hasLocalStorage()) {
1419
1421
  return;
1420
1422
  }
1421
- if (key === "auth-tokens") {
1422
- localStorage.removeItem(key);
1423
+ if (key.startsWith("auth-tokens")) {
1424
+ localStorage.removeItem(key+this.authTokensSuffix);
1423
1425
  } else {
1424
1426
  delete userSettings[key];
1425
1427
  saveUserSettings();
@@ -1446,6 +1448,8 @@ RED.settings = (function () {
1446
1448
 
1447
1449
  var init = function (options, done) {
1448
1450
  var accessTokenMatch = /[?&]access_token=(.*?)(?:$|&)/.exec(window.location.search);
1451
+ var path=window.location.pathname.slice(0,-1);
1452
+ RED.settings.authTokensSuffix=path.replace(/\//g, '-');
1449
1453
  if (accessTokenMatch) {
1450
1454
  var accessToken = accessTokenMatch[1];
1451
1455
  RED.settings.set("auth-tokens",{access_token: accessToken});
@@ -5160,7 +5164,7 @@ RED.nodes = (function() {
5160
5164
  }
5161
5165
  }
5162
5166
  if (node.type !== "subflow") {
5163
- var convertedNode = RED.nodes.convertNode(node);
5167
+ var convertedNode = RED.nodes.convertNode(node, { credentials: false });
5164
5168
  for (var d in node._def.defaults) {
5165
5169
  if (node._def.defaults[d].type) {
5166
5170
  var nodeList = node[d];
@@ -5193,7 +5197,7 @@ RED.nodes = (function() {
5193
5197
  nns = nns.concat(createExportableNodeSet(node.nodes, exportedIds, exportedSubflows, exportedConfigNodes));
5194
5198
  }
5195
5199
  } else {
5196
- var convertedSubflow = convertSubflow(node);
5200
+ var convertedSubflow = convertSubflow(node, { credentials: false });
5197
5201
  nns.push(convertedSubflow);
5198
5202
  }
5199
5203
  }
@@ -5893,16 +5897,27 @@ RED.nodes = (function() {
5893
5897
  } else if (n.type.substring(0,7) === "subflow") {
5894
5898
  var parentId = n.type.split(":")[1];
5895
5899
  var subflow = subflow_denylist[parentId]||subflow_map[parentId]||getSubflow(parentId);
5896
- if (createNewIds || options.importMap[n.id] === "copy") {
5897
- parentId = subflow.id;
5898
- node.type = "subflow:"+parentId;
5899
- node._def = registry.getNodeType(node.type);
5900
- delete node.i;
5901
- }
5902
- node.name = n.name;
5903
- node.outputs = subflow.out.length;
5904
- node.inputs = subflow.in.length;
5905
- node.env = n.env;
5900
+ if (!subflow){
5901
+ node._def = {
5902
+ color:"#fee",
5903
+ defaults: {},
5904
+ label: "unknown: "+n.type,
5905
+ labelStyle: "red-ui-flow-node-label-italic",
5906
+ outputs: n.outputs|| (n.wires && n.wires.length) || 0,
5907
+ set: registry.getNodeSet("node-red/unknown")
5908
+ }
5909
+ } else {
5910
+ if (createNewIds || options.importMap[n.id] === "copy") {
5911
+ parentId = subflow.id;
5912
+ node.type = "subflow:"+parentId;
5913
+ node._def = registry.getNodeType(node.type);
5914
+ delete node.i;
5915
+ }
5916
+ node.name = n.name;
5917
+ node.outputs = subflow.out.length;
5918
+ node.inputs = subflow.in.length;
5919
+ node.env = n.env;
5920
+ }
5906
5921
  } else if (n.type === 'junction') {
5907
5922
  node._def = {defaults:{}}
5908
5923
  node._config.x = node.x
@@ -19150,7 +19165,11 @@ RED.keyboard = (function() {
19150
19165
  okButton.attr("disabled",!valid);
19151
19166
  });
19152
19167
 
19153
- var scopeSelect = $('<select><option value="*" data-i18n="keyboard.global"></option><option value="red-ui-workspace" data-i18n="keyboard.workspace"></option></select>').appendTo(scope);
19168
+ var scopeSelect = $('<select>'+
19169
+ '<option value="*" data-i18n="keyboard.global"></option>'+
19170
+ '<option value="red-ui-workspace" data-i18n="keyboard.workspace"></option>'+
19171
+ '<option value="red-ui-editor-stack" data-i18n="keyboard.editor"></option>'+
19172
+ '</select>').appendTo(scope);
19154
19173
  scopeSelect.i18n();
19155
19174
  if (object.scope === "workspace") {
19156
19175
  object.scope = "red-ui-workspace";
@@ -19407,7 +19426,11 @@ RED.keyboard = (function() {
19407
19426
  var new_env = [];
19408
19427
  var items = list.editableList('items');
19409
19428
  var credentials = gconf ? gconf.credentials : null;
19410
-
19429
+ if (!gconf && list.editableList('length') === 0) {
19430
+ // No existing global-config node and nothing in the list,
19431
+ // so no need to do anything more
19432
+ return
19433
+ }
19411
19434
  if (!credentials) {
19412
19435
  credentials = {
19413
19436
  _ : {},
@@ -19435,6 +19458,12 @@ RED.keyboard = (function() {
19435
19458
  if (gconf === null) {
19436
19459
  gconf = getGlobalConf(true);
19437
19460
  }
19461
+ if (!gconf.credentials) {
19462
+ gconf.credentials = {
19463
+ _ : {},
19464
+ map: {}
19465
+ };
19466
+ }
19438
19467
  if ((JSON.stringify(new_env) !== JSON.stringify(gconf.env)) ||
19439
19468
  (JSON.stringify(credentials) !== JSON.stringify(gconf.credentials))) {
19440
19469
  gconf.env = new_env;
@@ -20679,7 +20708,13 @@ RED.view = (function() {
20679
20708
  set.unshift(...removed)
20680
20709
  }
20681
20710
  },
20682
- find: function(func) { return set.find(func) }
20711
+ find: function(func) { return set.find(func) },
20712
+ dump: function () {
20713
+ console.log('MovingSet Contents')
20714
+ api.forEach((n, i) => {
20715
+ console.log(`${i+1}\t${n.n.id}\t${n.n.type}`)
20716
+ })
20717
+ }
20683
20718
  }
20684
20719
  return api;
20685
20720
  })();
@@ -20716,6 +20751,63 @@ RED.view = (function() {
20716
20751
  return api
20717
20752
  })();
20718
20753
 
20754
+ const selectedGroups = (function() {
20755
+ let groups = new Set()
20756
+ const api = {
20757
+ add: function(g, includeNodes, addToMovingSet) {
20758
+ groups.add(g)
20759
+ if (!g.selected) {
20760
+ g.selected = true;
20761
+ g.dirty = true;
20762
+ }
20763
+ if (addToMovingSet !== false) {
20764
+ movingSet.add(g);
20765
+ }
20766
+ if (includeNodes) {
20767
+ var currentSet = new Set(movingSet.nodes());
20768
+ var allNodes = RED.group.getNodes(g,true);
20769
+ allNodes.forEach(function(n) {
20770
+ if (!currentSet.has(n)) {
20771
+ movingSet.add(n)
20772
+ }
20773
+ n.dirty = true;
20774
+ })
20775
+ }
20776
+ selectedLinks.clearUnselected()
20777
+ },
20778
+ remove: function(g) {
20779
+ groups.delete(g)
20780
+ if (g.selected) {
20781
+ g.selected = false;
20782
+ g.dirty = true;
20783
+ }
20784
+ const allNodes = RED.group.getNodes(g,true);
20785
+ const nodeSet = new Set(allNodes);
20786
+ nodeSet.add(g);
20787
+ for (let i = movingSet.length()-1; i >= 0; i -= 1) {
20788
+ const msn = movingSet.get(i);
20789
+ if (nodeSet.has(msn.n) || msn.n === g) {
20790
+ msn.n.selected = false;
20791
+ msn.n.dirty = true;
20792
+ movingSet.remove(msn.n,i)
20793
+ }
20794
+ }
20795
+ selectedLinks.clearUnselected()
20796
+ },
20797
+ length: () => groups.length,
20798
+ forEach: (func) => { groups.forEach(func) },
20799
+ toArray: () => [...groups],
20800
+ clear: function () {
20801
+ groups.forEach(g => {
20802
+ g.selected = false
20803
+ g.dirty = true
20804
+ })
20805
+ groups.clear()
20806
+ }
20807
+ }
20808
+ return api
20809
+ })()
20810
+
20719
20811
 
20720
20812
  function init() {
20721
20813
 
@@ -21620,7 +21712,7 @@ RED.view = (function() {
21620
21712
  var touchTrigger = options.touchTrigger;
21621
21713
 
21622
21714
  if (targetGroup) {
21623
- selectGroup(targetGroup,false);
21715
+ selectedGroups.add(targetGroup,false);
21624
21716
  RED.view.redraw();
21625
21717
  }
21626
21718
 
@@ -21946,7 +22038,7 @@ RED.view = (function() {
21946
22038
  clearSelection();
21947
22039
  nn.selected = true;
21948
22040
  if (targetGroup) {
21949
- selectGroup(targetGroup,false);
22041
+ selectedGroups.add(targetGroup,false);
21950
22042
  }
21951
22043
  movingSet.add(nn);
21952
22044
  updateActiveNodes();
@@ -22410,10 +22502,7 @@ RED.view = (function() {
22410
22502
  if (!movingSet.has(n) && !n.selected) {
22411
22503
  // group entirely within lasso
22412
22504
  if (n.x > x && n.y > y && n.x + n.w < x2 && n.y + n.h < y2) {
22413
- n.selected = true
22414
- n.dirty = true
22415
- var groupNodes = RED.group.getNodes(n,true);
22416
- groupNodes.forEach(gn => movingSet.add(gn))
22505
+ selectedGroups.add(n, true)
22417
22506
  }
22418
22507
  }
22419
22508
  })
@@ -22763,7 +22852,7 @@ RED.view = (function() {
22763
22852
  clearSelection();
22764
22853
  activeGroups.forEach(function(g) {
22765
22854
  if (!g.g) {
22766
- selectGroup(g, true);
22855
+ selectedGroups.add(g, true);
22767
22856
  if (!g.selected) {
22768
22857
  g.selected = true;
22769
22858
  g.dirty = true;
@@ -22833,10 +22922,7 @@ RED.view = (function() {
22833
22922
  }
22834
22923
  movingSet.clear();
22835
22924
  selectedLinks.clear();
22836
- activeGroups.forEach(function(g) {
22837
- g.selected = false;
22838
- g.dirty = true;
22839
- })
22925
+ selectedGroups.clear();
22840
22926
  }
22841
22927
 
22842
22928
  var lastSelection = null;
@@ -23093,6 +23179,16 @@ RED.view = (function() {
23093
23179
  var result = RED.nodes.removeJunction(node)
23094
23180
  removedJunctions.push(node);
23095
23181
  removedLinks = removedLinks.concat(result.links);
23182
+ if (node.g) {
23183
+ var group = RED.nodes.group(node.g);
23184
+ if (selectedGroups.indexOf(group) === -1) {
23185
+ // Don't use RED.group.removeFromGroup as that emits
23186
+ // a change event on the node - but we're deleting it
23187
+ var index = group.nodes.indexOf(node);
23188
+ group.nodes.splice(index,1);
23189
+ RED.group.markDirty(group);
23190
+ }
23191
+ }
23096
23192
  } else {
23097
23193
  if (node.direction === "out") {
23098
23194
  removedSubflowOutputs.push(node);
@@ -23915,7 +24011,7 @@ RED.view = (function() {
23915
24011
  if (!groupNodeSelectPrimed && !d.selected && d.g && RED.nodes.group(d.g).selected) {
23916
24012
  clearSelection();
23917
24013
 
23918
- selectGroup(RED.nodes.group(d.g), false);
24014
+ selectedGroups.add(RED.nodes.group(d.g), false);
23919
24015
 
23920
24016
  mousedown_node.selected = true;
23921
24017
  movingSet.add(mousedown_node);
@@ -24336,14 +24432,14 @@ RED.view = (function() {
24336
24432
  lastClickNode = g;
24337
24433
 
24338
24434
  if (g.selected && (d3.event.ctrlKey||d3.event.metaKey)) {
24339
- deselectGroup(g);
24435
+ selectedGroups.remove(g);
24340
24436
  d3.event.stopPropagation();
24341
24437
  } else {
24342
24438
  if (!g.selected) {
24343
24439
  if (!d3.event.ctrlKey && !d3.event.metaKey) {
24344
24440
  clearSelection();
24345
24441
  }
24346
- selectGroup(g,true);//!wasSelected);
24442
+ selectedGroups.add(g,true);//!wasSelected);
24347
24443
  }
24348
24444
 
24349
24445
  if (d3.event.button != 2) {
@@ -24359,45 +24455,6 @@ RED.view = (function() {
24359
24455
  d3.event.stopPropagation();
24360
24456
  }
24361
24457
 
24362
- function selectGroup(g, includeNodes, addToMovingSet) {
24363
- if (!g.selected) {
24364
- g.selected = true;
24365
- g.dirty = true;
24366
- }
24367
- if (addToMovingSet !== false) {
24368
- movingSet.add(g);
24369
- }
24370
- if (includeNodes) {
24371
- var currentSet = new Set(movingSet.nodes());
24372
- var allNodes = RED.group.getNodes(g,true);
24373
- allNodes.forEach(function(n) {
24374
- if (!currentSet.has(n)) {
24375
- movingSet.add(n)
24376
- }
24377
- n.dirty = true;
24378
- })
24379
- }
24380
- selectedLinks.clearUnselected()
24381
- }
24382
-
24383
- function deselectGroup(g) {
24384
- if (g.selected) {
24385
- g.selected = false;
24386
- g.dirty = true;
24387
- }
24388
- const allNodes = RED.group.getNodes(g,true);
24389
- const nodeSet = new Set(allNodes);
24390
- nodeSet.add(g);
24391
- for (let i = movingSet.length()-1; i >= 0; i -= 1) {
24392
- const msn = movingSet.get(i);
24393
- if (nodeSet.has(msn.n) || msn.n === g) {
24394
- msn.n.selected = false;
24395
- msn.n.dirty = true;
24396
- movingSet.remove(msn.n,i)
24397
- }
24398
- }
24399
- selectedLinks.clearUnselected()
24400
- }
24401
24458
  function getGroupAt(x, y, ignoreSelected) {
24402
24459
  // x,y expected to be in node-co-ordinate space
24403
24460
  var candidateGroups = {};
@@ -24836,6 +24893,7 @@ RED.view = (function() {
24836
24893
  this.__port__.setAttribute("transform","translate(-5,"+((d.h/2)-5)+")");
24837
24894
  this.__outputOutput__.setAttribute("transform","translate(20,"+((d.h/2)-8)+")");
24838
24895
  this.__outputNumber__.setAttribute("transform","translate(20,"+((d.h/2)+7)+")");
24896
+ this.__outputNumber__.textContent = d.i+1;
24839
24897
  }
24840
24898
  d.dirty = false;
24841
24899
  }
@@ -26378,11 +26436,10 @@ RED.view = (function() {
26378
26436
  if (movingSet.length() > 0) {
26379
26437
  movingSet.forEach(function(n) {
26380
26438
  if (n.n.type !== 'group') {
26381
- allNodes.add(n.n);
26439
+ allNodes.add(n.n);
26382
26440
  }
26383
26441
  });
26384
26442
  }
26385
- var selectedGroups = activeGroups.filter(function(g) { return g.selected });
26386
26443
  selectedGroups.forEach(function(g) {
26387
26444
  var groupNodes = RED.group.getNodes(g,true);
26388
26445
  groupNodes.forEach(function(n) {
@@ -26576,6 +26633,13 @@ RED.view = (function() {
26576
26633
  selectedNode.dirty = true;
26577
26634
  movingSet.clear();
26578
26635
  movingSet.add(selectedNode);
26636
+ } else {
26637
+ selectedNode = RED.nodes.group(selection);
26638
+ if (selectedNode) {
26639
+ movingSet.clear();
26640
+ selectedGroups.clear()
26641
+ selectedGroups.add(selectedNode)
26642
+ }
26579
26643
  }
26580
26644
  } else if (selection) {
26581
26645
  if (selection.nodes) {
@@ -26591,7 +26655,7 @@ RED.view = (function() {
26591
26655
  n.dirty = true;
26592
26656
  movingSet.add(n);
26593
26657
  } else {
26594
- selectGroup(n,true);
26658
+ selectedGroups.add(n,true);
26595
26659
  }
26596
26660
  })
26597
26661
  }
@@ -26759,8 +26823,12 @@ RED.view = (function() {
26759
26823
  })
26760
26824
  },
26761
26825
  scroll: function(x,y) {
26762
- chart.scrollLeft(chart.scrollLeft()+x);
26763
- chart.scrollTop(chart.scrollTop()+y)
26826
+ if (x !== undefined && y !== undefined) {
26827
+ chart.scrollLeft(chart.scrollLeft()+x);
26828
+ chart.scrollTop(chart.scrollTop()+y)
26829
+ } else {
26830
+ return [chart.scrollLeft(), chart.scrollTop()]
26831
+ }
26764
26832
  },
26765
26833
  clickNodeButton: function(n) {
26766
26834
  if (n._def.button) {
@@ -28946,23 +29014,15 @@ RED.palette = (function() {
28946
29014
  }
28947
29015
  metaData += type;
28948
29016
 
29017
+ const safeType = type.replace(/'/g,"\\'");
29018
+ const searchType = type.indexOf(' ') > -1 ? '&quot;' + type + '&quot;' : type
29019
+
28949
29020
  if (/^subflow:/.test(type)) {
28950
29021
  $('<button type="button" onclick="RED.workspaces.show(\''+type.substring(8).replace(/'/g,"\\'")+'\'); return false;" class="red-ui-button red-ui-button-small" style="float: right; margin-left: 5px;"><i class="fa fa-pencil"></i></button>').appendTo(popOverContent)
28951
29022
  }
28952
29023
 
28953
- const safeType = type.replace(/'/g,"\\'");
28954
- const wrapStr = function (str) {
28955
- if(str.indexOf(' ') >= 0) {
28956
- return '"' + str + '"'
28957
- }
28958
- return str
28959
- }
29024
+ $('<button type="button" onclick="RED.search.show(\'type:'+searchType+'\'); return false;" class="red-ui-button red-ui-button-small" style="float: right; margin-left: 5px;"><i class="fa fa-search"></i></button>').appendTo(popOverContent)
28960
29025
 
28961
- $('<button type="button"; return false;" class="red-ui-button red-ui-button-small" style="float: right; margin-left: 5px;"><i class="fa fa-search"></i></button>')
28962
- .appendTo(popOverContent)
28963
- .on('click', function() {
28964
- RED.search.show('type:' + wrapStr(safeType))
28965
- })
28966
29026
  $('<button type="button" onclick="RED.sidebar.help.show(\''+safeType+'\'); return false;" class="red-ui-button red-ui-button-small" style="float: right; margin-left: 5px;"><i class="fa fa-book"></i></button>').appendTo(popOverContent)
28967
29027
 
28968
29028
  $('<p>',{style:"font-size: 0.8em"}).text(metaData).appendTo(popOverContent);
@@ -33339,11 +33399,13 @@ RED.editor = (function() {
33339
33399
  var hasChanged;
33340
33400
  if (node.type.indexOf("subflow:")===0) {
33341
33401
  subflow = RED.nodes.subflow(node.type.substring(8));
33342
- isValid = subflow.valid;
33343
- hasChanged = subflow.changed;
33344
- if (isValid === undefined) {
33345
- isValid = validateNode(subflow);
33402
+ if (subflow){
33403
+ isValid = subflow.valid;
33346
33404
  hasChanged = subflow.changed;
33405
+ if (isValid === undefined) {
33406
+ isValid = validateNode(subflow);
33407
+ hasChanged = subflow.changed;
33408
+ }
33347
33409
  }
33348
33410
  validationErrors = validateNodeProperties(node, node._def.defaults, node);
33349
33411
  node.valid = isValid && validationErrors.length === 0;
@@ -37975,7 +38037,7 @@ RED.editor = (function() {
37975
38037
  }
37976
38038
 
37977
38039
  try {
37978
- expr.evaluate(legacyMode?{msg:parsedData}:parsedData, (err, result) => {
38040
+ expr.evaluate(legacyMode?{msg:parsedData}:parsedData, null, (err, result) => {
37979
38041
  if (err) {
37980
38042
  testResultEditor.setValue(RED._("expressionEditor.errors.eval",{message:err.message}),-1);
37981
38043
  } else {
@@ -39621,7 +39683,7 @@ RED.editor.codeEditor.monaco = (function() {
39621
39683
  "node-red-util": {package: "node-red", module: "util", path: "node-red/util.d.ts" },
39622
39684
  "node-red-func": {package: "node-red", module: "func", path: "node-red/func.d.ts" },
39623
39685
  }
39624
- const defaultServerSideTypes = [ knownModules["node-red-util"], knownModules["node-red-func"], knownModules["globals"], knownModules["console"], knownModules["buffer"] , knownModules["util"] ];
39686
+ const defaultServerSideTypes = [ knownModules["node-red-util"], knownModules["node-red-func"], knownModules["globals"], knownModules["console"], knownModules["buffer"], knownModules["timers"] , knownModules["util"] ];
39625
39687
 
39626
39688
  const modulesCache = {};
39627
39689
 
@@ -40681,19 +40743,19 @@ RED.editor.codeEditor.monaco = (function() {
40681
40743
  // Warning: 4
40682
40744
  // Error: 8
40683
40745
  ed.getAnnotations = function getAnnotations() {
40684
- var aceCompatibleMarkers = [];
40746
+ let aceCompatibleMarkers;
40685
40747
  try {
40686
- var _model = ed.getModel();
40748
+ const _model = ed.getModel();
40687
40749
  if (_model !== null) {
40688
- var id = _model._languageId; // e.g. javascript
40689
- var ra = _model._associatedResource.authority; //e.g. model
40690
- var rp = _model._associatedResource.path; //e.g. /18
40691
- var rs = _model._associatedResource.scheme; //e.g. inmemory
40692
- var modelMarkers = monaco.editor.getModelMarkers(_model) || [];
40693
- var thisEditorsMarkers = modelMarkers.filter(function (marker) {
40694
- var _ra = marker.resource.authority; //e.g. model
40695
- var _rp = marker.resource.path; //e.g. /18
40696
- var _rs = marker.resource.scheme; //e.g. inmemory
40750
+ const id = _model.getLanguageId(); // e.g. javascript
40751
+ const ra = _model.uri.authority; // e.g. model
40752
+ const rp = _model.uri.path; // e.g. /18
40753
+ const rs = _model.uri.scheme; // e.g. inmemory
40754
+ const modelMarkers = monaco.editor.getModelMarkers(_model) || [];
40755
+ const thisEditorsMarkers = modelMarkers.filter(function (marker) {
40756
+ const _ra = marker.resource.authority; // e.g. model
40757
+ const _rp = marker.resource.path; // e.g. /18
40758
+ const _rs = marker.resource.scheme; // e.g. inmemory
40697
40759
  return marker.owner == id && _ra === ra && _rp === rp && _rs === rs;
40698
40760
  })
40699
40761
  aceCompatibleMarkers = thisEditorsMarkers.map(function (marker) {
@@ -41469,13 +41531,13 @@ RED.clipboard = (function() {
41469
41531
  // IE11 workaround
41470
41532
  // IE does not support data uri scheme for downloading data
41471
41533
  var blob = new Blob([data], {
41472
- type: "data:text/plain;charset=utf-8"
41534
+ type: "data:application/json;charset=utf-8"
41473
41535
  });
41474
41536
  navigator.msSaveBlob(blob, file);
41475
41537
  }
41476
41538
  else {
41477
41539
  var element = document.createElement('a');
41478
- element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(data));
41540
+ element.setAttribute('href', 'data:application/json;charset=utf-8,' + encodeURIComponent(data));
41479
41541
  element.setAttribute('download', file);
41480
41542
  element.style.display = 'none';
41481
41543
  document.body.appendChild(element);
@@ -42163,7 +42225,7 @@ RED.clipboard = (function() {
42163
42225
  nodes.unshift(parentNode);
42164
42226
  nodes = RED.nodes.createExportableNodeSet(nodes);
42165
42227
  } else if (type === 'full') {
42166
- nodes = RED.nodes.createCompleteNodeSet(false);
42228
+ nodes = RED.nodes.createCompleteNodeSet({ credentials: false });
42167
42229
  }
42168
42230
  if (nodes !== null) {
42169
42231
  if (format === "red-ui-clipboard-dialog-export-fmt-full") {
@@ -44942,7 +45004,7 @@ RED.actionList = (function() {
44942
45004
  var searchDiv = $("<div>",{class:"red-ui-search-container"}).appendTo(dialog);
44943
45005
  searchInput = $('<input type="text" data-i18n="[placeholder]keyboard.filterActions">').appendTo(searchDiv).searchBox({
44944
45006
  change: function() {
44945
- filterTerm = $(this).val().trim();
45007
+ filterTerm = $(this).val().trim().toLowerCase();
44946
45008
  filterTerms = filterTerm.split(" ");
44947
45009
  searchResults.editableList('filter');
44948
45010
  searchResults.find("li.selected").removeClass("selected");
@@ -45595,7 +45657,9 @@ RED.subflow = (function() {
45595
45657
  '</script>';
45596
45658
 
45597
45659
  function findAvailableSubflowIOPosition(subflow,isInput) {
45598
- var pos = {x:50,y:30};
45660
+ const scrollPos = RED.view.scroll()
45661
+ const scaleFactor = RED.view.scale()
45662
+ var pos = { x: (scrollPos[0]/scaleFactor)+50, y: (scrollPos[1]/scaleFactor)+30 };
45599
45663
  if (!isInput) {
45600
45664
  pos.x += 110;
45601
45665
  }
@@ -46230,24 +46294,23 @@ RED.subflow = (function() {
46230
46294
  var candidateOutputs = [];
46231
46295
  var candidateInputNodes = {};
46232
46296
 
46233
- var boundingBox = [nodeList[0].x,
46234
- nodeList[0].y,
46235
- nodeList[0].x,
46236
- nodeList[0].y];
46297
+ var boundingBox = [nodeList[0].x-(nodeList[0].w/2),
46298
+ nodeList[0].y-(nodeList[0].h/2),
46299
+ nodeList[0].x+(nodeList[0].w/2),
46300
+ nodeList[0].y+(nodeList[0].h/2)];
46237
46301
 
46238
46302
  for (i=0;i<nodeList.length;i++) {
46239
46303
  n = nodeList[i];
46240
46304
  nodes[n.id] = {n:n,outputs:{}};
46241
46305
  boundingBox = [
46242
- Math.min(boundingBox[0],n.x),
46243
- Math.min(boundingBox[1],n.y),
46244
- Math.max(boundingBox[2],n.x),
46245
- Math.max(boundingBox[3],n.y)
46306
+ Math.min(boundingBox[0],n.x-(n.w/2)),
46307
+ Math.min(boundingBox[1],n.y-(n.h/2)),
46308
+ Math.max(boundingBox[2],n.x+(n.w/2)),
46309
+ Math.max(boundingBox[3],n.y+(n.h/2))
46246
46310
  ]
46247
46311
  }
46248
- var offsetX = snapToGrid(boundingBox[0] - 200);
46249
- var offsetY = snapToGrid(boundingBox[1] - 80);
46250
-
46312
+ var offsetX = snapToGrid(boundingBox[0] - 140);
46313
+ var offsetY = snapToGrid(boundingBox[1] - 60);
46251
46314
 
46252
46315
  var center = [
46253
46316
  snapToGrid((boundingBox[2]+boundingBox[0]) / 2),
@@ -47315,7 +47378,7 @@ RED.group = (function() {
47315
47378
  }
47316
47379
  }
47317
47380
  var existingGroup;
47318
-
47381
+ var mergedEnv = {}
47319
47382
  // Second pass, ungroup any groups in the selection and add their contents
47320
47383
  // to the selection
47321
47384
  for (var i=0; i<selection.nodes.length; i++) {
@@ -47324,6 +47387,11 @@ RED.group = (function() {
47324
47387
  if (!existingGroup) {
47325
47388
  existingGroup = n;
47326
47389
  }
47390
+ if (n.env && n.env.length > 0) {
47391
+ n.env.forEach(env => {
47392
+ mergedEnv[env.name] = env
47393
+ })
47394
+ }
47327
47395
  ungroupHistoryEvent.groups.push(n);
47328
47396
  nodes = nodes.concat(ungroup(n));
47329
47397
  } else {
@@ -47341,6 +47409,7 @@ RED.group = (function() {
47341
47409
  group.style = existingGroup.style;
47342
47410
  group.name = existingGroup.name;
47343
47411
  }
47412
+ group.env = Object.values(mergedEnv)
47344
47413
  RED.view.select({nodes:[group]})
47345
47414
  }
47346
47415
  historyEvent.events.push({