',{class:"red-ui-search-result-node"}).appendTo(div);
if (object.type === "junction") {
nodeDiv.addClass("red-ui-palette-icon-junction");
+ } else if (/^_action_:/.test(object.type)) {
+ nodeDiv.addClass("red-ui-palette-icon-junction")
} else {
var colour = RED.utils.getNodeColor(object.type,def);
nodeDiv.css('backgroundColor',colour);
@@ -182,11 +186,14 @@ RED.typeSearch = (function() {
var iconContainer = $('
',{class:"red-ui-palette-icon-container"}).appendTo(nodeDiv);
RED.utils.createIconElement(icon_url, iconContainer, false);
- if (object.type !== "junction" && def.inputs > 0) {
- $('
',{class:"red-ui-search-result-node-port"}).appendTo(nodeDiv);
- }
- if (object.type !== "junction" && def.outputs > 0) {
- $('
',{class:"red-ui-search-result-node-port red-ui-search-result-node-output"}).appendTo(nodeDiv);
+
+ if (!/^_action_:/.test(object.type) && object.type !== "junction") {
+ if (def.inputs > 0) {
+ $('
',{class:"red-ui-search-result-node-port"}).appendTo(nodeDiv);
+ }
+ if (def.outputs > 0) {
+ $('
',{class:"red-ui-search-result-node-port red-ui-search-result-node-output"}).appendTo(nodeDiv);
+ }
}
var contentDiv = $('
',{class:"red-ui-search-result-description"}).appendTo(div);
@@ -207,7 +214,9 @@ RED.typeSearch = (function() {
}
function confirm(def) {
hide();
- typesUsed[def.type] = Date.now();
+ if (!/^_action_:/.test(def.type)) {
+ typesUsed[def.type] = Date.now();
+ }
addCallback(def.type);
}
@@ -316,6 +325,7 @@ RED.typeSearch = (function() {
function applyFilter(filter,type,def) {
return !filter ||
(
+ (!filter.spliceMultiple) &&
(!filter.type || type === filter.type) &&
(!filter.input || type === 'junction' || def.inputs > 0) &&
(!filter.output || type === 'junction' || def.outputs > 0)
@@ -330,6 +340,13 @@ RED.typeSearch = (function() {
'inject','debug','function','change','switch','junction'
].filter(function(t) { return applyFilter(opts.filter,t,RED.nodes.getType(t)); });
+ // if (opts.filter && opts.filter.input && opts.filter.output && !opts.filter.type) {
+ // if (opts.filter.spliceMultiple) {
+ // common.push('_action_:core:split-wires-with-junctions')
+ // }
+ // common.push('_action_:core:split-wire-with-link-nodes')
+ // }
+
var recentlyUsed = Object.keys(typesUsed);
recentlyUsed.sort(function(a,b) {
return typesUsed[b]-typesUsed[a];
@@ -354,6 +371,8 @@ RED.typeSearch = (function() {
var itemDef = RED.nodes.getType(common[i]);
if (common[i] === 'junction') {
itemDef = { inputs:1, outputs: 1, label: 'junction', type: 'junction'}
+ } else if (/^_action_:/.test(common[i]) ) {
+ itemDef = { inputs:1, outputs: 1, label: common[i], type: common[i]}
}
if (itemDef) {
item = {
diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/utils.js b/packages/node_modules/@node-red/editor-client/src/js/ui/utils.js
index c3ea0ddd1..2c4cdca6b 100644
--- a/packages/node_modules/@node-red/editor-client/src/js/ui/utils.js
+++ b/packages/node_modules/@node-red/editor-client/src/js/ui/utils.js
@@ -1032,6 +1032,8 @@ RED.utils = (function() {
return "font-awesome/fa-circle-o"
} else if (def.category === 'config') {
return RED.settings.apiRootUrl+"icons/node-red/cog.svg"
+ } else if ((node && /^_action_:/.test(node.type)) || /^_action_:/.test(def.type)) {
+ return "font-awesome/fa-cogs"
} else if (node && node.type === 'tab') {
return "red-ui-icons/red-ui-icons-flow"
// return RED.settings.apiRootUrl+"images/subflow_tab.svg"
diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/view-tools.js b/packages/node_modules/@node-red/editor-client/src/js/ui/view-tools.js
index 699e5f222..888fb4d7f 100644
--- a/packages/node_modules/@node-red/editor-client/src/js/ui/view-tools.js
+++ b/packages/node_modules/@node-red/editor-client/src/js/ui/view-tools.js
@@ -336,17 +336,17 @@ RED.view.tools = (function() {
}
- function addNode() {
- var selection = RED.view.selection();
- if (selection.nodes && selection.nodes.length === 1 && selection.nodes[0].outputs > 0) {
- var selectedNode = selection.nodes[0];
- RED.view.showQuickAddDialog([
- selectedNode.x + selectedNode.w + 50,selectedNode.y
- ])
- } else {
- RED.view.showQuickAddDialog();
- }
- }
+ // function addNode() {
+ // var selection = RED.view.selection();
+ // if (selection.nodes && selection.nodes.length === 1 && selection.nodes[0].outputs > 0) {
+ // var selectedNode = selection.nodes[0];
+ // RED.view.showQuickAddDialog([
+ // selectedNode.x + selectedNode.w + 50,selectedNode.y
+ // ])
+ // } else {
+ // RED.view.showQuickAddDialog();
+ // }
+ // }
function gotoNearestNode(direction) {
@@ -815,6 +815,9 @@ RED.view.tools = (function() {
*/
function splitWiresWithLinkNodes(wires) {
let wiresToSplit = wires || RED.view.selection().links;
+ if (!wiresToSplit) {
+ return
+ }
if (!Array.isArray(wiresToSplit)) {
wiresToSplit = [wiresToSplit];
}
@@ -1047,6 +1050,135 @@ RED.view.tools = (function() {
}
}
+ function addJunctionsToWires(wires) {
+ let wiresToSplit = wires || RED.view.selection().links;
+ if (!wiresToSplit) {
+ return
+ }
+ if (!Array.isArray(wiresToSplit)) {
+ wiresToSplit = [wiresToSplit];
+ }
+ if (wiresToSplit.length === 0) {
+ return;
+ }
+
+ var removedLinks = new Set()
+ var addedLinks = []
+ var addedJunctions = []
+
+ var groupedLinks = {}
+ wiresToSplit.forEach(function(l) {
+ var sourceId = l.source.id+":"+l.sourcePort
+ groupedLinks[sourceId] = groupedLinks[sourceId] || []
+ groupedLinks[sourceId].push(l)
+
+ groupedLinks[l.target.id] = groupedLinks[l.target.id] || []
+ groupedLinks[l.target.id].push(l)
+ });
+ var linkGroups = Object.keys(groupedLinks)
+ linkGroups.sort(function(A,B) {
+ return groupedLinks[B].length - groupedLinks[A].length
+ })
+ linkGroups.forEach(function(gid) {
+ var links = groupedLinks[gid]
+ var junction = {
+ _def: {defaults:{}},
+ type: 'junction',
+ z: RED.workspaces.active(),
+ id: RED.nodes.id(),
+ x: 0,
+ y: 0,
+ w: 0, h: 0,
+ outputs: 1,
+ inputs: 1,
+ dirty: true
+ }
+ links = links.filter(function(l) { return !removedLinks.has(l) })
+ if (links.length === 0) {
+ return
+ }
+ let pointCount = 0
+ links.forEach(function(l) {
+ if (l._sliceLocation) {
+ junction.x += l._sliceLocation.x
+ junction.y += l._sliceLocation.y
+ delete l._sliceLocation
+ pointCount++
+ } else {
+ junction.x += l.source.x + l.source.w/2 + l.target.x - l.target.w/2
+ junction.y += l.source.y + l.target.y
+ pointCount += 2
+ }
+ })
+ junction.x = Math.round(junction.x/pointCount)
+ junction.y = Math.round(junction.y/pointCount)
+ if (RED.view.snapGrid) {
+ let gridSize = RED.view.gridSize()
+ junction.x = (gridSize*Math.round(junction.x/gridSize));
+ junction.y = (gridSize*Math.round(junction.y/gridSize));
+ }
+
+ var nodeGroups = new Set()
+
+ RED.nodes.addJunction(junction)
+ addedJunctions.push(junction)
+ let newLink
+ if (gid === links[0].source.id+":"+links[0].sourcePort) {
+ newLink = {
+ source: links[0].source,
+ sourcePort: links[0].sourcePort,
+ target: junction
+ }
+ } else {
+ newLink = {
+ source: junction,
+ sourcePort: 0,
+ target: links[0].target
+ }
+ }
+ addedLinks.push(newLink)
+ RED.nodes.addLink(newLink)
+ links.forEach(function(l) {
+ removedLinks.add(l)
+ RED.nodes.removeLink(l)
+ let newLink
+ if (gid === l.target.id) {
+ newLink = {
+ source: l.source,
+ sourcePort: l.sourcePort,
+ target: junction
+ }
+ } else {
+ newLink = {
+ source: junction,
+ sourcePort: 0,
+ target: l.target
+ }
+ }
+ addedLinks.push(newLink)
+ RED.nodes.addLink(newLink)
+ nodeGroups.add(l.source.g || "__NONE__")
+ nodeGroups.add(l.target.g || "__NONE__")
+ })
+ if (nodeGroups.size === 1) {
+ var group = nodeGroups.values().next().value
+ if (group !== "__NONE__") {
+ RED.group.addToGroup(RED.nodes.group(group), junction)
+ }
+ }
+ })
+ if (addedJunctions.length > 0) {
+ RED.history.push({
+ t: 'add',
+ links: addedLinks,
+ junctions: addedJunctions,
+ removedLinks: Array.from(removedLinks)
+ })
+ RED.nodes.dirty(true)
+ }
+ RED.view.redraw(true);
+ }
+
return {
init: function() {
RED.actions.add("core:show-selected-node-labels", function() { setSelectedNodeLabelState(true); })
@@ -1109,6 +1241,7 @@ RED.view.tools = (function() {
RED.actions.add("core:wire-node-to-multiple", function() { wireNodeToMultiple() })
RED.actions.add("core:split-wire-with-link-nodes", function () { splitWiresWithLinkNodes() });
+ RED.actions.add("core:split-wires-with-junctions", function () { addJunctionsToWires() });
RED.actions.add("core:generate-node-names", generateNodeNames )
diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/view.js b/packages/node_modules/@node-red/editor-client/src/js/ui/view.js
index f1268f156..bca3f47a6 100755
--- a/packages/node_modules/@node-red/editor-client/src/js/ui/view.js
+++ b/packages/node_modules/@node-red/editor-client/src/js/ui/view.js
@@ -206,7 +206,15 @@ RED.view = (function() {
function init() {
chart = $("#red-ui-workspace-chart");
-
+ chart.on('contextmenu', function(evt) {
+ evt.preventDefault()
+ evt.stopPropagation()
+ RED.contextMenu.show({
+ x:evt.clientX-5,
+ y:evt.clientY-5
+ })
+ return false
+ })
outer = d3.select("#red-ui-workspace-chart")
.append("svg:svg")
.attr("width", space_width)
@@ -230,6 +238,7 @@ RED.view = (function() {
.on("mousedown", canvasMouseDown)
.on("mouseup", canvasMouseUp)
.on("mouseenter", function() {
+ d3.select(document).on('mouseup.red-ui-workspace-tracker', null)
if (lasso) {
if (d3.event.buttons !== 1) {
lasso.remove();
@@ -245,6 +254,7 @@ RED.view = (function() {
}
}
})
+ .on("mouseleave", canvasMouseLeave)
.on("touchend", function() {
d3.event.preventDefault();
clearTimeout(touchStartTime);
@@ -385,6 +395,9 @@ RED.view = (function() {
drag_lines = [];
RED.events.on("workspace:change",function(event) {
+ // Just in case the mouse left the workspace whilst doing an action,
+ // put us back into default mode so the refresh works
+ mouse_mode = 0
if (event.old !== 0) {
workspaceScrollPositions[event.old] = {
left:chart.scrollLeft(),
@@ -972,7 +985,7 @@ RED.view = (function() {
}
function canvasMouseDown() {
- if (RED.view.DEBUG) {
+ if (RED.view.DEBUG) {
console.warn("canvasMouseDown", { mouse_mode, point: d3.mouse(this), event: d3.event });
}
if (mouse_mode === RED.state.SELECTING_NODE) {
@@ -987,7 +1000,10 @@ RED.view = (function() {
scroll_position = [chart.scrollLeft(),chart.scrollTop()];
return;
}
- if (!mousedown_node && !mousedown_link && !mousedown_group) {
+ if (d3.event.button === 2) {
+ return
+ }
+ if (!mousedown_node && !mousedown_link && !mousedown_group && !d3.event.shiftKey) {
selectedLinks.clear();
updateSelection();
}
@@ -1041,6 +1057,7 @@ RED.view = (function() {
options = options || {};
var point = options.position || lastClickPosition;
var spliceLink = options.splice;
+ var spliceMultipleLinks = options.spliceMultiple
var targetGroup = options.group;
var touchTrigger = options.touchTrigger;
@@ -1053,6 +1070,10 @@ RED.view = (function() {
var ox = point[0];
var oy = point[1];
+ const offset = $("#red-ui-workspace-chart").offset()
+ var clientX = ox + offset.left
+ var clientY = oy + offset.top
+
if (RED.settings.get("editor").view['view-snap-grid']) {
// eventLayer.append("circle").attr("cx",point[0]).attr("cy",point[1]).attr("r","2").attr('fill','red')
point[0] = Math.round(point[0] / gridSize) * gridSize;
@@ -1104,8 +1125,12 @@ RED.view = (function() {
}
hideDragLines();
}
- if (spliceLink) {
- filter = {input:true, output:true}
+ if (spliceLink || spliceMultipleLinks) {
+ filter = {
+ input:true,
+ output:true,
+ spliceMultiple: spliceMultipleLinks
+ }
}
var rebuildQuickAddLink = function() {
@@ -1130,8 +1155,8 @@ RED.view = (function() {
var lastAddedWidth;
RED.typeSearch.show({
- x:d3.event.clientX-mainPos.left-node_width/2 - (ox-point[0]),
- y:d3.event.clientY-mainPos.top+ node_height/2 + 5 - (oy-point[1]),
+ x:clientX-mainPos.left-node_width/2 - (ox-point[0]),
+ y:clientY-mainPos.top+ node_height/2 + 5 - (oy-point[1]),
disableFocus: touchTrigger,
filter: filter,
move: function(dx,dy) {
@@ -1159,7 +1184,7 @@ RED.view = (function() {
hideDragLines();
redraw();
},
- add: function(type,keepAdding) {
+ add: function(type, keepAdding) {
if (touchTrigger) {
keepAdding = false;
resetMouseVars();
@@ -1167,7 +1192,13 @@ RED.view = (function() {
var nn;
var historyEvent;
- if (type === 'junction') {
+ if (/^_action_:/.test(type)) {
+ const actionName = type.substring(9)
+ quickAddActive = false;
+ ghostNode.remove();
+ RED.actions.invoke(actionName)
+ return
+ } else if (type === 'junction') {
nn = {
_def: {defaults:{}},
type: 'junction',
@@ -1733,10 +1764,17 @@ RED.view = (function() {
redraw();
}
}
-
+ function canvasMouseLeave() {
+ if (mouse_mode !== 0 && d3.event.buttons !== 0) {
+ d3.select(document).on('mouseup.red-ui-workspace-tracker', function() {
+ d3.select(document).on('mouseup.red-ui-workspace-tracker', null)
+ canvasMouseUp.call(this)
+ })
+ }
+ }
function canvasMouseUp() {
lastClickPosition = [d3.event.offsetX/scaleFactor,d3.event.offsetY/scaleFactor];
- if (RED.view.DEBUG) {
+ if (RED.view.DEBUG) {
console.warn("canvasMouseUp", { mouse_mode, point: d3.mouse(this), event: d3.event });
}
var i;
@@ -1832,8 +1870,20 @@ RED.view = (function() {
}
}
})
-
-
+ activeLinks.forEach(function(link) {
+ if (!link.selected) {
+ var sourceY = link.source.y
+ var targetY = link.target.y
+ var sourceX = link.source.x+(link.source.w/2) + 10
+ var targetX = link.target.x-(link.target.w/2) - 10
+ if (
+ sourceX > x && sourceX < x2 && sourceY > y && sourceY < y2 &&
+ targetX > x && targetX < x2 && targetY > y && targetY < y2
+ ) {
+ selectedLinks.add(link);
+ }
+ }
+ })
// var selectionChanged = false;
// do {
@@ -1881,114 +1931,118 @@ RED.view = (function() {
slicePath = null;
RED.view.redraw(true);
} else if (mouse_mode == RED.state.SLICING_JUNCTION) {
- var removedLinks = new Set()
- var addedLinks = []
- var addedJunctions = []
-
- var groupedLinks = {}
- selectedLinks.forEach(function(l) {
- var sourceId = l.source.id+":"+l.sourcePort
- groupedLinks[sourceId] = groupedLinks[sourceId] || []
- groupedLinks[sourceId].push(l)
-
- groupedLinks[l.target.id] = groupedLinks[l.target.id] || []
- groupedLinks[l.target.id].push(l)
- });
- var linkGroups = Object.keys(groupedLinks)
- linkGroups.sort(function(A,B) {
- return groupedLinks[B].length - groupedLinks[A].length
- })
- linkGroups.forEach(function(gid) {
- var links = groupedLinks[gid]
- var junction = {
- _def: {defaults:{}},
- type: 'junction',
- z: RED.workspaces.active(),
- id: RED.nodes.id(),
- x: 0,
- y: 0,
- w: 0, h: 0,
- outputs: 1,
- inputs: 1,
- dirty: true
- }
- links = links.filter(function(l) { return !removedLinks.has(l) })
- if (links.length === 0) {
- return
- }
- links.forEach(function(l) {
- junction.x += l._sliceLocation.x
- junction.y += l._sliceLocation.y
- })
- junction.x = Math.round(junction.x/links.length)
- junction.y = Math.round(junction.y/links.length)
- if (snapGrid) {
- junction.x = (gridSize*Math.round(junction.x/gridSize));
- junction.y = (gridSize*Math.round(junction.y/gridSize));
- }
-
- var nodeGroups = new Set()
-
- RED.nodes.addJunction(junction)
- addedJunctions.push(junction)
- let newLink
- if (gid === links[0].source.id+":"+links[0].sourcePort) {
- newLink = {
- source: links[0].source,
- sourcePort: links[0].sourcePort,
- target: junction
- }
- } else {
- newLink = {
- source: junction,
- sourcePort: 0,
- target: links[0].target
- }
- }
- addedLinks.push(newLink)
- RED.nodes.addLink(newLink)
- links.forEach(function(l) {
- removedLinks.add(l)
- RED.nodes.removeLink(l)
- let newLink
- if (gid === l.target.id) {
- newLink = {
- source: l.source,
- sourcePort: l.sourcePort,
- target: junction
- }
- } else {
- newLink = {
- source: junction,
- sourcePort: 0,
- target: l.target
- }
- }
- addedLinks.push(newLink)
- RED.nodes.addLink(newLink)
- nodeGroups.add(l.source.g || "__NONE__")
- nodeGroups.add(l.target.g || "__NONE__")
- })
- if (nodeGroups.size === 1) {
- var group = nodeGroups.values().next().value
- if (group !== "__NONE__") {
- RED.group.addToGroup(RED.nodes.group(group), junction)
- }
- }
- })
+ RED.actions.invoke("core:split-wires-with-junctions")
slicePath.remove();
slicePath = null;
- if (addedJunctions.length > 0) {
- RED.history.push({
- t: 'add',
- links: addedLinks,
- junctions: addedJunctions,
- removedLinks: Array.from(removedLinks)
- })
- RED.nodes.dirty(true)
- }
- RED.view.redraw(true);
+ // var removedLinks = new Set()
+ // var addedLinks = []
+ // var addedJunctions = []
+ //
+ // var groupedLinks = {}
+ // selectedLinks.forEach(function(l) {
+ // var sourceId = l.source.id+":"+l.sourcePort
+ // groupedLinks[sourceId] = groupedLinks[sourceId] || []
+ // groupedLinks[sourceId].push(l)
+ //
+ // groupedLinks[l.target.id] = groupedLinks[l.target.id] || []
+ // groupedLinks[l.target.id].push(l)
+ // });
+ // var linkGroups = Object.keys(groupedLinks)
+ // linkGroups.sort(function(A,B) {
+ // return groupedLinks[B].length - groupedLinks[A].length
+ // })
+ // linkGroups.forEach(function(gid) {
+ // var links = groupedLinks[gid]
+ // var junction = {
+ // _def: {defaults:{}},
+ // type: 'junction',
+ // z: RED.workspaces.active(),
+ // id: RED.nodes.id(),
+ // x: 0,
+ // y: 0,
+ // w: 0, h: 0,
+ // outputs: 1,
+ // inputs: 1,
+ // dirty: true
+ // }
+ // links = links.filter(function(l) { return !removedLinks.has(l) })
+ // if (links.length === 0) {
+ // return
+ // }
+ // links.forEach(function(l) {
+ // junction.x += l._sliceLocation.x
+ // junction.y += l._sliceLocation.y
+ // })
+ // junction.x = Math.round(junction.x/links.length)
+ // junction.y = Math.round(junction.y/links.length)
+ // if (snapGrid) {
+ // junction.x = (gridSize*Math.round(junction.x/gridSize));
+ // junction.y = (gridSize*Math.round(junction.y/gridSize));
+ // }
+ //
+ // var nodeGroups = new Set()
+ //
+ // RED.nodes.addJunction(junction)
+ // addedJunctions.push(junction)
+ // let newLink
+ // if (gid === links[0].source.id+":"+links[0].sourcePort) {
+ // newLink = {
+ // source: links[0].source,
+ // sourcePort: links[0].sourcePort,
+ // target: junction
+ // }
+ // } else {
+ // newLink = {
+ // source: junction,
+ // sourcePort: 0,
+ // target: links[0].target
+ // }
+ // }
+ // addedLinks.push(newLink)
+ // RED.nodes.addLink(newLink)
+ // links.forEach(function(l) {
+ // removedLinks.add(l)
+ // RED.nodes.removeLink(l)
+ // let newLink
+ // if (gid === l.target.id) {
+ // newLink = {
+ // source: l.source,
+ // sourcePort: l.sourcePort,
+ // target: junction
+ // }
+ // } else {
+ // newLink = {
+ // source: junction,
+ // sourcePort: 0,
+ // target: l.target
+ // }
+ // }
+ // addedLinks.push(newLink)
+ // RED.nodes.addLink(newLink)
+ // nodeGroups.add(l.source.g || "__NONE__")
+ // nodeGroups.add(l.target.g || "__NONE__")
+ // })
+ // if (nodeGroups.size === 1) {
+ // var group = nodeGroups.values().next().value
+ // if (group !== "__NONE__") {
+ // RED.group.addToGroup(RED.nodes.group(group), junction)
+ // }
+ // }
+ // })
+ // slicePath.remove();
+ // slicePath = null;
+ //
+ // if (addedJunctions.length > 0) {
+ // RED.history.push({
+ // t: 'add',
+ // links: addedLinks,
+ // junctions: addedJunctions,
+ // removedLinks: Array.from(removedLinks)
+ // })
+ // RED.nodes.dirty(true)
+ // }
+ // RED.view.redraw(true);
}
if (mouse_mode == RED.state.MOVING_ACTIVE) {
if (movingSet.length() > 0) {
@@ -3736,7 +3790,7 @@ RED.view = (function() {
function junctionMouseOutProxy(e) { junctionMouseOut(d3.select(this), this.__data__) }
function linkMouseDown(d) {
- if (RED.view.DEBUG) {
+ if (RED.view.DEBUG) {
console.warn("linkMouseDown", { mouse_mode, point: d3.mouse(this), event: d3.event });
}
if (mouse_mode === RED.state.SELECTING_NODE) {
@@ -5736,7 +5790,12 @@ RED.view = (function() {
node.dirty = true;
node.dirtyStatus = true;
node.changed = true;
- RED.events.emit("nodes:change",node);
+ if (node.type === "junction") {
+ RED.events.emit("junctions:change",node);
+ }
+ else {
+ RED.events.emit("nodes:change",node);
+ }
}
}
}
diff --git a/packages/node_modules/@node-red/editor-client/src/sass/dropdownMenu.scss b/packages/node_modules/@node-red/editor-client/src/sass/dropdownMenu.scss
index 98ab3bd3b..4104fd83e 100644
--- a/packages/node_modules/@node-red/editor-client/src/sass/dropdownMenu.scss
+++ b/packages/node_modules/@node-red/editor-client/src/sass/dropdownMenu.scss
@@ -46,7 +46,7 @@
& > li > a,
& > li > a:focus {
display: block;
- padding: 4px 12px 4px 32px;
+ padding: 4px 20px 4px 12px;
clear: both;
font-weight: normal;
line-height: 20px;
@@ -54,7 +54,10 @@
white-space: normal !important;
outline: none;
}
-
+ & > li.pull-left > a,
+ & > li.pull-left > a:focus {
+ padding: 4px 12px 4px 32px;
+ }
& > .active > a,
& > .active > a:hover,
& > .active > a:focus {
@@ -145,8 +148,8 @@
position: relative;
& > .red-ui-menu-dropdown {
top: 0;
- left: 100%;
- margin-top: -6px;
+ left: calc(100% - 5px);
+ margin-top: 0;
margin-left: -1px;
}
&.open > .red-ui-menu-dropdown,
@@ -175,10 +178,10 @@
}
}
-.red-ui-menu-dropdown-submenu>a:after {
+.red-ui-menu-dropdown-submenu.pull-left>a:after {
display: none;
}
-.red-ui-menu-dropdown-submenu>a:before {
+.red-ui-menu-dropdown-submenu.pull-left>a:before {
display: block;
float: left;
width: 0;
@@ -192,7 +195,25 @@
border-width: 5px 5px 5px 0;
content: " ";
}
-
+.red-ui-menu-dropdown-direction-right {
+ .red-ui-menu-dropdown-submenu>a:after {
+ display: none;
+ }
+ .red-ui-menu-dropdown-submenu>a:before {
+ display: block;
+ float: right;
+ width: 0;
+ height: 0;
+ margin-top: 5px;
+ margin-right: -15px;
+ /* Caret Arrow */
+ border-color: transparent;
+ border-left-color: $menuCaret;
+ border-style: solid;
+ border-width: 5px 0 5px 5px;
+ content: " ";
+ }
+}
.red-ui-menu-dropdown-submenu.disabled > a:before {
border-right-color: $menuCaret;
}
diff --git a/packages/node_modules/@node-red/editor-client/src/tours/images/context-menu.png b/packages/node_modules/@node-red/editor-client/src/tours/images/context-menu.png
new file mode 100644
index 000000000..1acaab48b
Binary files /dev/null and b/packages/node_modules/@node-red/editor-client/src/tours/images/context-menu.png differ
diff --git a/packages/node_modules/@node-red/editor-client/src/tours/welcome.js b/packages/node_modules/@node-red/editor-client/src/tours/welcome.js
index 219aaec7b..4b6f5f66d 100644
--- a/packages/node_modules/@node-red/editor-client/src/tours/welcome.js
+++ b/packages/node_modules/@node-red/editor-client/src/tours/welcome.js
@@ -1,15 +1,27 @@
export default {
- version: "3.0.0-beta.1",
+ version: "3.0.0-beta.3",
steps: [
{
titleIcon: "fa fa-map-o",
title: {
- "en-US": "Welcome to Node-RED 3.0 Beta 1!",
- "ja": "Node-RED 3.0 ベータ1へようこそ!"
+ "en-US": "Welcome to Node-RED 3.0 Beta 3!",
+ "ja": "Node-RED 3.0 ベータ3へようこそ!"
},
description: {
- "en-US": "
This is the first Beta release of Node-RED 3.0. It contains just about everything we have planned for the final release.
Let's take a moment to discover the new features in this release.
",
- "ja": "
これはNode-RED 3.0の最初のベータリリースです。これには、最終リリースで計画しているほぼ全ての機能が含まれています。
本リリースの新機能を見つけてみましょう。
"
+ "en-US": "
This is the final beta release of Node-RED 3.0.
Let's take a moment to discover the new features in this release.
",
+ // "ja": "
これはNode-RED 3.0の最初のベータリリースです。これには、最終リリースで計画しているほぼ全ての機能が含まれています。
本リリースの新機能を見つけてみましょう。
"
+ }
+ },
+ {
+ title: {
+ "en-US": "Context Menu"
+ },
+ image: 'images/context-menu.png',
+ description: {
+ "en-US": `
The editor now has its own context menu when you
+ right-click in the workspace.
+
This makes many of the built-in actions much easier
+ to access.
`
}
},
{
@@ -19,12 +31,13 @@ export default {
},
image: 'images/junction-slice.gif',
description: {
- "en-US": `
To make it easier to route wires around your flows, it is now possible to
- add junction nodes that give you more control.
-
Junctions can be added to wires by holding the Shift key, then click and drag with
- the right-hand mouse button across the wires.
`,
- "ja": `
フローのワイヤーの経路をより制御しやすくするために、分岐点ノードを追加できるようになりました。
-
シフトキーを押しながら、マウスの右ボタンをクリックし、ワイヤーを横切るようにドラッグすることで、分岐点を追加できます。
`
+ "en-US": `
To make it easier to route wires around your flows,
+ it is now possible to add junction nodes that give
+ you more control.
+
Junctions can be added to wires by holding the Alt key
+ then click and drag the mouse across the wires.
`,
+ // "ja": `
フローのワイヤーの経路をより制御しやすくするために、分岐点ノードを追加できるようになりました。
+ //
シフトキーを押しながら、マウスの右ボタンをクリックし、ワイヤーを横切るようにドラッグすることで、分岐点を追加できます。
`
},
},
{
diff --git a/packages/node_modules/@node-red/nodes/core/function/10-function.html b/packages/node_modules/@node-red/nodes/core/function/10-function.html
index 6309ae9ad..156abd29d 100644
--- a/packages/node_modules/@node-red/nodes/core/function/10-function.html
+++ b/packages/node_modules/@node-red/nodes/core/function/10-function.html
@@ -460,7 +460,7 @@
}
});
- var buildEditor = function(id, stateId, focus, value, defaultValue, extraLibs) {
+ var buildEditor = function(id, stateId, focus, value, defaultValue, extraLibs, offset) {
var editor = RED.editor.createEditor({
id: id,
mode: 'ace/mode/nrjavascript',
@@ -484,14 +484,14 @@
extraLibs: extraLibs
});
if (defaultValue && value === "") {
- editor.moveCursorTo(defaultValue.split("\n").length - 1, 0);
+ editor.moveCursorTo(defaultValue.split("\n").length +offset, 0);
}
editor.__stateId = stateId;
return editor;
}
- this.initEditor = buildEditor('node-input-init-editor', this.id + "/" + "initEditor", false, $("#node-input-initialize").val(), RED._("node-red:function.text.initialize"))
- this.editor = buildEditor('node-input-func-editor', this.id + "/" + "editor", true, $("#node-input-func").val(), undefined, that.libs || [])
- this.finalizeEditor = buildEditor('node-input-finalize-editor', this.id + "/" + "finalizeEditor", false, $("#node-input-finalize").val(), RED._("node-red:function.text.finalize"))
+ this.initEditor = buildEditor('node-input-init-editor', this.id + "/" + "initEditor", false, $("#node-input-initialize").val(), RED._("node-red:function.text.initialize"), undefined, 0);
+ this.editor = buildEditor('node-input-func-editor', this.id + "/" + "editor", true, $("#node-input-func").val(), undefined, that.libs || [], undefined, -1);
+ this.finalizeEditor = buildEditor('node-input-finalize-editor', this.id + "/" + "finalizeEditor", false, $("#node-input-finalize").val(), RED._("node-red:function.text.finalize"), undefined, 0);
RED.library.create({
url:"functions", // where to get the data from
diff --git a/packages/node_modules/@node-red/nodes/core/storage/10-file.html b/packages/node_modules/@node-red/nodes/core/storage/10-file.html
index b726b537d..6b19ebaa8 100755
--- a/packages/node_modules/@node-red/nodes/core/storage/10-file.html
+++ b/packages/node_modules/@node-red/nodes/core/storage/10-file.html
@@ -198,8 +198,8 @@
category: 'storage',
defaults: {
name: {value:""},
- filename: {value:"filename"},
- filenameType: {value:"msg"},
+ filename: {value:""},
+ filenameType: {value:"str"},
appendNewline: {value:true},
createDir: {value:false},
overwriteFile: {value:"false"},
@@ -236,8 +236,8 @@
label: node._("file.encoding.setbymsg")
}).text(label).appendTo(encSel);
$("#node-input-filename").typedInput({
- default: "msg",
- types: ["str", "msg", "jsonata", "env"],
+ default: "str",
+ types: [{label:RED._("node-red:file.label.path"), value:"str", icon:""}, "msg", "jsonata", "env"],
typeField: $("#node-input-filenameType")
});
if(typeof node.filenameType == 'undefined') {
@@ -297,8 +297,8 @@
category: 'storage',
defaults: {
name: {value:""},
- filename: {value:"filename"},
- filenameType: {value:"msg"},
+ filename: {value:""},
+ filenameType: {value:"str"},
format: {value:"utf8"},
chunk: {value:false},
sendError: {value: false},
@@ -341,8 +341,8 @@
label: label
}).text(label).appendTo(encSel);
$("#node-input-filename").typedInput({
- default: "msg",
- types: ["str", "msg", "jsonata", "env"],
+ default: "str",
+ types: [{label:RED._("node-red:file.label.path"), value:"str", icon:""}, "msg", "jsonata", "env"],
typeField: $("#node-input-filenameType")
});
if(typeof node.filenameType == 'undefined') {
diff --git a/packages/node_modules/@node-red/nodes/locales/en-US/messages.json b/packages/node_modules/@node-red/nodes/locales/en-US/messages.json
index 77d832abd..62d5f351f 100644
--- a/packages/node_modules/@node-red/nodes/locales/en-US/messages.json
+++ b/packages/node_modules/@node-red/nodes/locales/en-US/messages.json
@@ -928,6 +928,7 @@
"write": "write file",
"read": "read file",
"filename": "Filename",
+ "path": "path",
"action": "Action",
"addnewline": "Add newline (\\n) to each payload?",
"createdir": "Create directory if it doesn't exist?",
diff --git a/packages/node_modules/@node-red/nodes/package.json b/packages/node_modules/@node-red/nodes/package.json
index 2a0d7e7c1..8c9d5adf7 100644
--- a/packages/node_modules/@node-red/nodes/package.json
+++ b/packages/node_modules/@node-red/nodes/package.json
@@ -36,7 +36,7 @@
"js-yaml": "4.1.0",
"media-typer": "1.1.0",
"mqtt": "4.3.7",
- "multer": "1.4.4",
+ "multer": "1.4.5-lts.1",
"mustache": "4.2.0",
"node-watch": "0.7.3",
"on-headers": "1.0.2",
diff --git a/packages/node_modules/@node-red/registry/lib/localfilesystem.js b/packages/node_modules/@node-red/registry/lib/localfilesystem.js
index 62080b4a8..da4006ecc 100644
--- a/packages/node_modules/@node-red/registry/lib/localfilesystem.js
+++ b/packages/node_modules/@node-red/registry/lib/localfilesystem.js
@@ -88,9 +88,10 @@ function getLocalFile(file) {
/**
* Synchronously walks the directory looking for node files.
* @param dir the directory to search
+ * @param skipValidNodeRedModules a flag to skip lading icons & files if the directory a valid node-red module
* @return an array of fully-qualified paths to .js files
*/
-function getLocalNodeFiles(dir) {
+function getLocalNodeFiles(dir, skipValidNodeRedModules) {
dir = path.resolve(dir);
var result = [];
@@ -102,6 +103,14 @@ function getLocalNodeFiles(dir) {
return {files: [], icons: []};
}
files.sort();
+ // when loading local files, if the path is a valid node-red module
+ // dont include it (will be picked up in scanTreeForNodesModules)
+ if(skipValidNodeRedModules && files.indexOf("package.json") >= 0) {
+ const package = getPackageDetails(dir)
+ if(package.isNodeRedModule) {
+ return {files: [], icons: []};
+ }
+ }
files.forEach(function(fn) {
var stats = fs.statSync(path.join(dir,fn));
if (stats.isFile()) {
@@ -114,7 +123,7 @@ function getLocalNodeFiles(dir) {
} else if (stats.isDirectory()) {
// Ignore /.dirs/, /lib/ /node_modules/
if (!/^(\..*|lib|icons|node_modules|test|locales)$/.test(fn)) {
- var subDirResults = getLocalNodeFiles(path.join(dir,fn));
+ var subDirResults = getLocalNodeFiles(path.join(dir,fn), skipValidNodeRedModules);
result = result.concat(subDirResults.files);
icons = icons.concat(subDirResults.icons);
} else if (fn === "icons") {
@@ -126,21 +135,30 @@ function getLocalNodeFiles(dir) {
return {files: result, icons: icons}
}
-function scanDirForNodesModules(dir,moduleName) {
- var results = [];
- var scopeName;
+function scanDirForNodesModules(dir,moduleName,package) {
+ let results = [];
+ let scopeName;
+ let files
try {
- var files = fs.readdirSync(dir);
- if (moduleName) {
- var m = /^(?:(@[^/]+)[/])?([^@/]+)/.exec(moduleName);
- if (m) {
- scopeName = m[1];
- moduleName = m[2];
+ let isNodeRedModule = false
+ if(package) {
+ dir = path.join(package.moduleDir,'..')
+ files = [path.basename(package.moduleDir)]
+ moduleName = (package.package ? package.package.name : null) || moduleName
+ isNodeRedModule = package.isNodeRedModule
+ } else {
+ files = fs.readdirSync(dir);
+ if (moduleName) {
+ var m = /^(?:(@[^/]+)[/])?([^@/]+)/.exec(moduleName);
+ if (m) {
+ scopeName = m[1];
+ moduleName = m[2];
+ }
}
}
- for (var i=0;i
look for node_modules
+ 2. exist(package.json) && package.json.has(node-red) => load this only
+ 3. in original scan of nodesDir, ignore if:(exist(package.json) && package.json.has(node-red))
+ */
+ if (nodesDir) {
+ for (let dirIndex = 0; dirIndex < nodesDir.length; dirIndex++) {
+ const nodeDir = nodesDir[dirIndex];
+ const packageDetails = getPackageDetails(nodeDir)
+ if(packageDetails.isNodeRedModule) {
+ //we have found a node-red module, scan it
+ const nrModules = scanDirForNodesModules(nodeDir, packageDetails.package.name, packageDetails);
+ results = results.concat(nrModules);
+
+ } else if (packageDetails.has_node_modules) {
+ //If this dir has a `node_modues` dir, scan it
+ const nodeModulesDir = path.join(nodeDir, 'node_modules')
+ const nrModules = scanDirForNodesModules(nodeModulesDir, moduleName );
+ results = results.concat(nrModules);
+
+ } else {
+ //If this is not a node-red module AND it does NOT have a node_modules dir,
+ //it may be a directory of project directories or a node_modules dir?
+ //scan this instead
+ const nrModules = scanDirForNodesModules(nodeDir, moduleName);
+ results = results.concat(nrModules);
+ }
}
}
return results;
@@ -274,24 +328,26 @@ function getModuleNodeFiles(module) {
}
function getNodeFiles(disableNodePathScan) {
- var dir;
// Find all of the nodes to load
- var nodeFiles = [];
- var results;
-
- var dir;
- var iconList = [];
+ let results;
+ let nodesDir;
+ if(settings.nodesDir) {
+ nodesDir = Array.isArray(settings.nodesDir) ? settings.nodesDir : [settings.nodesDir]
+ }
+ let dir;
+ let nodeFiles = [];
+ let iconList = [];
if (settings.coreNodesDir) {
results = getLocalNodeFiles(path.resolve(settings.coreNodesDir));
nodeFiles = nodeFiles.concat(results.files);
iconList = iconList.concat(results.icons);
- var defaultLocalesPath = path.join(settings.coreNodesDir,"locales");
+ let defaultLocalesPath = path.join(settings.coreNodesDir,"locales");
i18n.registerMessageCatalog("node-red",defaultLocalesPath,"messages.json");
}
if (settings.userDir) {
dir = path.join(settings.userDir,"lib","icons");
- var icons = scanIconDir(dir);
+ let icons = scanIconDir(dir);
if (icons.length > 0) {
iconList.push({path:dir,icons:icons});
}
@@ -301,13 +357,9 @@ function getNodeFiles(disableNodePathScan) {
nodeFiles = nodeFiles.concat(results.files);
iconList = iconList.concat(results.icons);
}
- if (settings.nodesDir) {
- dir = settings.nodesDir;
- if (typeof settings.nodesDir == "string") {
- dir = [dir];
- }
- for (var i=0;i
diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir1/loose1.html b/test/unit/@node-red/registry/lib/resources/nodesDir1/loose1.html
new file mode 100644
index 000000000..8f392056c
--- /dev/null
+++ b/test/unit/@node-red/registry/lib/resources/nodesDir1/loose1.html
@@ -0,0 +1,5 @@
+
\ No newline at end of file
diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir1/loose1.js b/test/unit/@node-red/registry/lib/resources/nodesDir1/loose1.js
new file mode 100644
index 000000000..624cfe6d8
--- /dev/null
+++ b/test/unit/@node-red/registry/lib/resources/nodesDir1/loose1.js
@@ -0,0 +1,4 @@
+
+ (function() {
+ console.log("hello from loose1.js")
+ })()
diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir1/loose2/icons/loose2.svg b/test/unit/@node-red/registry/lib/resources/nodesDir1/loose2/icons/loose2.svg
new file mode 100644
index 000000000..04bebc370
--- /dev/null
+++ b/test/unit/@node-red/registry/lib/resources/nodesDir1/loose2/icons/loose2.svg
@@ -0,0 +1 @@
+
diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir1/loose2/icons/loose2b.svg b/test/unit/@node-red/registry/lib/resources/nodesDir1/loose2/icons/loose2b.svg
new file mode 100644
index 000000000..250348861
--- /dev/null
+++ b/test/unit/@node-red/registry/lib/resources/nodesDir1/loose2/icons/loose2b.svg
@@ -0,0 +1 @@
+
diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir1/loose2/loose2.html b/test/unit/@node-red/registry/lib/resources/nodesDir1/loose2/loose2.html
new file mode 100644
index 000000000..e23e2880a
--- /dev/null
+++ b/test/unit/@node-red/registry/lib/resources/nodesDir1/loose2/loose2.html
@@ -0,0 +1,5 @@
+
\ No newline at end of file
diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir1/loose2/loose2.js b/test/unit/@node-red/registry/lib/resources/nodesDir1/loose2/loose2.js
new file mode 100644
index 000000000..e1cde2a82
--- /dev/null
+++ b/test/unit/@node-red/registry/lib/resources/nodesDir1/loose2/loose2.js
@@ -0,0 +1,4 @@
+
+ (function() {
+ console.log("hello from loose2.js")
+ })()
diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir1/node-red-node-testnode/icons/test.svg b/test/unit/@node-red/registry/lib/resources/nodesDir1/node-red-node-testnode/icons/test.svg
new file mode 100644
index 000000000..04bebc370
--- /dev/null
+++ b/test/unit/@node-red/registry/lib/resources/nodesDir1/node-red-node-testnode/icons/test.svg
@@ -0,0 +1 @@
+
diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir1/node-red-node-testnode/main.js b/test/unit/@node-red/registry/lib/resources/nodesDir1/node-red-node-testnode/main.js
new file mode 100644
index 000000000..e2e0781d1
--- /dev/null
+++ b/test/unit/@node-red/registry/lib/resources/nodesDir1/node-red-node-testnode/main.js
@@ -0,0 +1,4 @@
+
+ (function() {
+ console.log("hello from regular module main.js")
+ })()
diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir1/node-red-node-testnode/package.json b/test/unit/@node-red/registry/lib/resources/nodesDir1/node-red-node-testnode/package.json
new file mode 100644
index 000000000..26d4151fb
--- /dev/null
+++ b/test/unit/@node-red/registry/lib/resources/nodesDir1/node-red-node-testnode/package.json
@@ -0,0 +1,19 @@
+{
+ "name": "node-red-node-testnode",
+ "version": "1.0.0",
+ "description": "A node-red node that does nothing other than exist",
+ "main": "main.js",
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "keywords": [
+ "node-red"
+ ],
+ "node-red": {
+ "nodes": {
+ "testnode": "index.js"
+ }
+ },
+ "author": "@testyMcTersterson",
+ "license": "MIT"
+}
diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir1/regular_module/icons/test.svg b/test/unit/@node-red/registry/lib/resources/nodesDir1/regular_module/icons/test.svg
new file mode 100644
index 000000000..04bebc370
--- /dev/null
+++ b/test/unit/@node-red/registry/lib/resources/nodesDir1/regular_module/icons/test.svg
@@ -0,0 +1 @@
+
diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir1/regular_module/main.js b/test/unit/@node-red/registry/lib/resources/nodesDir1/regular_module/main.js
new file mode 100644
index 000000000..e2e0781d1
--- /dev/null
+++ b/test/unit/@node-red/registry/lib/resources/nodesDir1/regular_module/main.js
@@ -0,0 +1,4 @@
+
+ (function() {
+ console.log("hello from regular module main.js")
+ })()
diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir1/regular_module/package.json b/test/unit/@node-red/registry/lib/resources/nodesDir1/regular_module/package.json
new file mode 100644
index 000000000..23cfd7e86
--- /dev/null
+++ b/test/unit/@node-red/registry/lib/resources/nodesDir1/regular_module/package.json
@@ -0,0 +1,14 @@
+{
+ "name": "regular_node",
+ "version": "1.0.0",
+ "description": "A regular node that does nothing other than exist",
+ "main": "main.js",
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "keywords": [
+ "test"
+ ],
+ "author": "@testyMcTersterson",
+ "license": "MIT"
+}
diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir2/@test/testnode/index.html b/test/unit/@node-red/registry/lib/resources/nodesDir2/@test/testnode/index.html
new file mode 100644
index 000000000..0e45b3007
--- /dev/null
+++ b/test/unit/@node-red/registry/lib/resources/nodesDir2/@test/testnode/index.html
@@ -0,0 +1,5 @@
+
\ No newline at end of file
diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir2/@test/testnode/index.js b/test/unit/@node-red/registry/lib/resources/nodesDir2/@test/testnode/index.js
new file mode 100644
index 000000000..1fe9d89a3
--- /dev/null
+++ b/test/unit/@node-red/registry/lib/resources/nodesDir2/@test/testnode/index.js
@@ -0,0 +1,4 @@
+
+ (function() {
+ console.log("hello from @test/testnode index.js")
+ })()
diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir2/@test/testnode/package.json b/test/unit/@node-red/registry/lib/resources/nodesDir2/@test/testnode/package.json
new file mode 100644
index 000000000..a32462631
--- /dev/null
+++ b/test/unit/@node-red/registry/lib/resources/nodesDir2/@test/testnode/package.json
@@ -0,0 +1,20 @@
+{
+ "name": "@test/testnode",
+ "version": "1.0.0",
+ "description": "A test node that does nothing other than exist",
+ "main": "index.js",
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "keywords": [
+ "node-red",
+ "test"
+ ],
+ "node-red": {
+ "nodes": {
+ "testnode": "index.js"
+ }
+ },
+ "author": "@testyMcTersterson",
+ "license": "MIT"
+}
diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir2/testnode2/index.html b/test/unit/@node-red/registry/lib/resources/nodesDir2/testnode2/index.html
new file mode 100644
index 000000000..5d9f2b0ec
--- /dev/null
+++ b/test/unit/@node-red/registry/lib/resources/nodesDir2/testnode2/index.html
@@ -0,0 +1,5 @@
+
\ No newline at end of file
diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir2/testnode2/index.js b/test/unit/@node-red/registry/lib/resources/nodesDir2/testnode2/index.js
new file mode 100644
index 000000000..0f0eba392
--- /dev/null
+++ b/test/unit/@node-red/registry/lib/resources/nodesDir2/testnode2/index.js
@@ -0,0 +1,4 @@
+
+ (function() {
+ console.log("hello from testnode2 index.js")
+ })()
diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir2/testnode2/package.json b/test/unit/@node-red/registry/lib/resources/nodesDir2/testnode2/package.json
new file mode 100644
index 000000000..f9e8aecbe
--- /dev/null
+++ b/test/unit/@node-red/registry/lib/resources/nodesDir2/testnode2/package.json
@@ -0,0 +1,20 @@
+{
+ "name": "testnode2",
+ "version": "1.0.0",
+ "description": "A test node that does nothing other than exist",
+ "main": "index.js",
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "keywords": [
+ "node-red",
+ "test"
+ ],
+ "node-red": {
+ "nodes": {
+ "testnode2": "index.js"
+ }
+ },
+ "author": "@testyMcTersterson",
+ "license": "MIT"
+}
diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir2/theme-plugin2/files/clientside.js b/test/unit/@node-red/registry/lib/resources/nodesDir2/theme-plugin2/files/clientside.js
new file mode 100644
index 000000000..fb2e22289
--- /dev/null
+++ b/test/unit/@node-red/registry/lib/resources/nodesDir2/theme-plugin2/files/clientside.js
@@ -0,0 +1,3 @@
+(function() {
+ console.log("Hi from test plugin client side")
+})()
diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir2/theme-plugin2/files/plugin.js b/test/unit/@node-red/registry/lib/resources/nodesDir2/theme-plugin2/files/plugin.js
new file mode 100644
index 000000000..3202aeb8b
--- /dev/null
+++ b/test/unit/@node-red/registry/lib/resources/nodesDir2/theme-plugin2/files/plugin.js
@@ -0,0 +1,14 @@
+module.exports = function (RED) {
+ RED.plugins.registerPlugin('test-theme', {
+ type: 'node-red-theme',
+ scripts: [
+ 'files/clientside.js'
+ ],
+ css: [
+ 'files/theme.css',
+ ],
+ monacoOptions: {
+ theme: "vs"
+ }
+ })
+}
diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir2/theme-plugin2/files/theme.css b/test/unit/@node-red/registry/lib/resources/nodesDir2/theme-plugin2/files/theme.css
new file mode 100644
index 000000000..872c93e10
--- /dev/null
+++ b/test/unit/@node-red/registry/lib/resources/nodesDir2/theme-plugin2/files/theme.css
@@ -0,0 +1 @@
+:root{--red-ui-primary-background: #f2f3fb;}
\ No newline at end of file
diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir2/theme-plugin2/package.json b/test/unit/@node-red/registry/lib/resources/nodesDir2/theme-plugin2/package.json
new file mode 100644
index 000000000..b8608c175
--- /dev/null
+++ b/test/unit/@node-red/registry/lib/resources/nodesDir2/theme-plugin2/package.json
@@ -0,0 +1,24 @@
+{
+ "name": "test-theme2",
+ "version": "0.0.1",
+ "description": "test theme for Node-RED",
+
+ "keywords": [
+ "node-red",
+ "plugin",
+ "theme"
+ ],
+ "author": {
+ "name": "testy-McTesterson"
+ },
+ "license": "MIT",
+ "node-red": {
+ "version": ">=2.2.0",
+ "plugins": {
+ "test-theme2": "files/plugin.js"
+ }
+ },
+ "engines": {
+ "node": ">=12.x"
+ }
+}
diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/testnode/index.html b/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/testnode/index.html
new file mode 100644
index 000000000..0e45b3007
--- /dev/null
+++ b/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/testnode/index.html
@@ -0,0 +1,5 @@
+
\ No newline at end of file
diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/testnode/index.js b/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/testnode/index.js
new file mode 100644
index 000000000..1fe9d89a3
--- /dev/null
+++ b/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/testnode/index.js
@@ -0,0 +1,4 @@
+
+ (function() {
+ console.log("hello from @test/testnode index.js")
+ })()
diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/testnode/package.json b/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/testnode/package.json
new file mode 100644
index 000000000..a32462631
--- /dev/null
+++ b/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/testnode/package.json
@@ -0,0 +1,20 @@
+{
+ "name": "@test/testnode",
+ "version": "1.0.0",
+ "description": "A test node that does nothing other than exist",
+ "main": "index.js",
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "keywords": [
+ "node-red",
+ "test"
+ ],
+ "node-red": {
+ "nodes": {
+ "testnode": "index.js"
+ }
+ },
+ "author": "@testyMcTersterson",
+ "license": "MIT"
+}
diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/theme-plugin3/files/clientside.js b/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/theme-plugin3/files/clientside.js
new file mode 100644
index 000000000..fb2e22289
--- /dev/null
+++ b/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/theme-plugin3/files/clientside.js
@@ -0,0 +1,3 @@
+(function() {
+ console.log("Hi from test plugin client side")
+})()
diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/theme-plugin3/files/plugin.js b/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/theme-plugin3/files/plugin.js
new file mode 100644
index 000000000..3202aeb8b
--- /dev/null
+++ b/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/theme-plugin3/files/plugin.js
@@ -0,0 +1,14 @@
+module.exports = function (RED) {
+ RED.plugins.registerPlugin('test-theme', {
+ type: 'node-red-theme',
+ scripts: [
+ 'files/clientside.js'
+ ],
+ css: [
+ 'files/theme.css',
+ ],
+ monacoOptions: {
+ theme: "vs"
+ }
+ })
+}
diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/theme-plugin3/files/theme.css b/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/theme-plugin3/files/theme.css
new file mode 100644
index 000000000..872c93e10
--- /dev/null
+++ b/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/theme-plugin3/files/theme.css
@@ -0,0 +1 @@
+:root{--red-ui-primary-background: #f2f3fb;}
\ No newline at end of file
diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/theme-plugin3/package.json b/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/theme-plugin3/package.json
new file mode 100644
index 000000000..56b1bfb6d
--- /dev/null
+++ b/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/theme-plugin3/package.json
@@ -0,0 +1,24 @@
+{
+ "name": "@test/test-theme3",
+ "version": "0.0.1",
+ "description": "test theme for Node-RED",
+
+ "keywords": [
+ "node-red",
+ "plugin",
+ "theme"
+ ],
+ "author": {
+ "name": "testy-McTesterson"
+ },
+ "license": "MIT",
+ "node-red": {
+ "version": ">=2.2.0",
+ "plugins": {
+ "test-theme3": "files/plugin.js"
+ }
+ },
+ "engines": {
+ "node": ">=12.x"
+ }
+}
diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/testnode3/index.html b/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/testnode3/index.html
new file mode 100644
index 000000000..a4034f340
--- /dev/null
+++ b/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/testnode3/index.html
@@ -0,0 +1,5 @@
+
\ No newline at end of file
diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/testnode3/index.js b/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/testnode3/index.js
new file mode 100644
index 000000000..855768ad8
--- /dev/null
+++ b/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/testnode3/index.js
@@ -0,0 +1,4 @@
+
+ (function() {
+ console.log("hello from testnode3 index.js")
+ })()
diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/testnode3/package.json b/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/testnode3/package.json
new file mode 100644
index 000000000..41e9bb8f8
--- /dev/null
+++ b/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/testnode3/package.json
@@ -0,0 +1,20 @@
+{
+ "name": "testnode3",
+ "version": "1.0.0",
+ "description": "A test node that does nothing other than exist",
+ "main": "index.js",
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "keywords": [
+ "node-red",
+ "test"
+ ],
+ "node-red": {
+ "nodes": {
+ "testnode3": "index.js"
+ }
+ },
+ "author": "@testyMcTersterson",
+ "license": "MIT"
+}