mirror of
https://github.com/node-red/node-red.git
synced 2025-03-01 10:36:34 +00:00
Compare commits
32 Commits
4396-fix-g
...
4456-fix-g
Author | SHA1 | Date | |
---|---|---|---|
|
fb54c05d9f | ||
|
a55554193b | ||
|
d2a8338d4a | ||
|
e945deeab6 | ||
|
3dec609459 | ||
|
e73b9f646d | ||
|
3cea6400d1 | ||
|
c6a8eee73d | ||
|
74d431ea36 | ||
|
409a559a13 | ||
|
6829535350 | ||
|
6488111f79 | ||
|
923339c1d8 | ||
|
3f4d96f4cd | ||
|
c52985d245 | ||
|
88e6c71aa0 | ||
|
4d08e297c4 | ||
|
ad2b30691f | ||
|
369bad01b8 | ||
|
b6ecc6d9ea | ||
|
0117df0960 | ||
|
6ac905f264 | ||
|
e5307f6604 | ||
|
8d9b6dd859 | ||
|
01821ead0f | ||
|
1451fb9e2f | ||
|
245751bb23 | ||
|
f07519c705 | ||
|
fae3a5c26a | ||
|
1a52c0adfc | ||
|
44c0bbc61e | ||
|
5ac50fae3a |
@@ -64,7 +64,7 @@
|
||||
"mqtt": "4.3.7",
|
||||
"multer": "1.4.5-lts.1",
|
||||
"mustache": "4.2.0",
|
||||
"node-red-admin": "^3.1.0",
|
||||
"node-red-admin": "^3.1.1",
|
||||
"node-watch": "0.7.4",
|
||||
"nopt": "5.0.0",
|
||||
"oauth2orize": "1.11.1",
|
||||
|
@@ -339,6 +339,8 @@ module.exports = {
|
||||
}
|
||||
theme.codeEditor = theme.codeEditor || {}
|
||||
theme.codeEditor.options = Object.assign({}, themePlugin.monacoOptions, theme.codeEditor.options);
|
||||
|
||||
theme.mermaid = Object.assign({}, themePlugin.mermaid, theme.mermaid)
|
||||
}
|
||||
activeThemeInitialised = true;
|
||||
}
|
||||
|
@@ -2198,6 +2198,12 @@ RED.nodes = (function() {
|
||||
}
|
||||
node._config.x = node.x;
|
||||
node._config.y = node.y;
|
||||
if (n.hasOwnProperty('w')) {
|
||||
node.w = n.w
|
||||
}
|
||||
if (n.hasOwnProperty('h')) {
|
||||
node.h = n.h
|
||||
}
|
||||
} else if (n.type.substring(0,7) === "subflow") {
|
||||
var parentId = n.type.split(":")[1];
|
||||
var subflow = subflow_denylist[parentId]||subflow_map[parentId]||getSubflow(parentId);
|
||||
|
@@ -498,6 +498,15 @@ var RED = (function() {
|
||||
]
|
||||
}
|
||||
}
|
||||
} else if (notificationId === 'restart-required') {
|
||||
options.buttons = [
|
||||
{
|
||||
text: RED._("common.label.close"),
|
||||
click: function() {
|
||||
persistentNotifications[notificationId].hideNotification();
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
if (!persistentNotifications.hasOwnProperty(notificationId)) {
|
||||
persistentNotifications[notificationId] = RED.notify(text,options);
|
||||
|
@@ -182,7 +182,9 @@
|
||||
valueLabel: contextLabel
|
||||
},
|
||||
str: {value:"str",label:"string",icon:"red/images/typedInput/az.svg"},
|
||||
num: {value:"num",label:"number",icon:"red/images/typedInput/09.svg",validate:/^[+-]?[0-9]*\.?[0-9]*([eE][-+]?[0-9]+)?$/},
|
||||
num: {value:"num",label:"number",icon:"red/images/typedInput/09.svg",validate: function(v) {
|
||||
return (true === RED.utils.validateTypedProperty(v, "num"));
|
||||
} },
|
||||
bool: {value:"bool",label:"boolean",icon:"red/images/typedInput/bool.svg",options:["true","false"]},
|
||||
json: {
|
||||
value:"json",
|
||||
|
@@ -121,7 +121,7 @@
|
||||
var i=0,l=bufferBinValue.length;
|
||||
var c = 0;
|
||||
for(i=0;i<l;i++) {
|
||||
var d = parseInt(bufferBinValue[i]);
|
||||
var d = parseInt(Number(bufferBinValue[i]));
|
||||
if (!isString && (isNaN(d) || d < 0 || d > 255)) {
|
||||
valid = false;
|
||||
break;
|
||||
|
@@ -966,12 +966,10 @@ RED.editor.codeEditor.monaco = (function() {
|
||||
|
||||
//Unbind ctrl-Enter (default action is to insert a newline in editor) This permits the shortcut to close the tray.
|
||||
try {
|
||||
ed._standaloneKeybindingService.addDynamicKeybinding(
|
||||
'-editor.action.insertLineAfter', // command ID prefixed by '-'
|
||||
null, // keybinding
|
||||
() => {} // need to pass an empty handler
|
||||
);
|
||||
} catch (error) { }
|
||||
monaco.editor.addKeybindingRule({keybinding: 0, command: "-editor.action.insertLineAfter"});
|
||||
} catch (error) {
|
||||
console.warn(error)
|
||||
}
|
||||
|
||||
ed.nodered = {
|
||||
refreshModuleLibs: refreshModuleLibs //expose this for function node externalModules refresh
|
||||
|
@@ -15,7 +15,8 @@ RED.editor.mermaid = (function () {
|
||||
'vendor/mermaid/mermaid.min.js',
|
||||
function (data, stat, jqxhr) {
|
||||
mermaid.initialize({
|
||||
startOnLoad: false
|
||||
startOnLoad: false,
|
||||
theme: RED.settings.get('mermaid', {}).theme
|
||||
})
|
||||
loaded = true
|
||||
while(pendingEvals.length > 0) {
|
||||
|
@@ -323,7 +323,7 @@ RED.typeSearch = (function() {
|
||||
}
|
||||
}
|
||||
function applyFilter(filter,type,def) {
|
||||
return !filter ||
|
||||
return !def || !filter ||
|
||||
(
|
||||
(!filter.spliceMultiple) &&
|
||||
(!filter.type || type === filter.type) &&
|
||||
|
@@ -921,7 +921,7 @@ RED.utils = (function() {
|
||||
error = RED._("validator.errors.invalid-prop")
|
||||
}
|
||||
} else if (propertyType === 'num') {
|
||||
if (!/^[+-]?[0-9]*\.?[0-9]*([eE][-+]?[0-9]+)?$/.test(propertyValue)) {
|
||||
if (!/^NaN$|^[+-]?[0-9]*\.?[0-9]*([eE][-+]?[0-9]+)?$|^[+-]?(0b|0B)[01]+$|^[+-]?(0o|0O)[0-7]+$|^[+-]?(0x|0X)[0-9a-fA-F]+$/.test(propertyValue)) {
|
||||
error = RED._("validator.errors.invalid-num")
|
||||
}
|
||||
} else if (propertyType === 'jsonata') {
|
||||
|
@@ -4187,7 +4187,7 @@ RED.view = (function() {
|
||||
nodeEl.__statusGroup__.style.display = "none";
|
||||
} else {
|
||||
nodeEl.__statusGroup__.style.display = "inline";
|
||||
let backgroundWidth = 12
|
||||
let backgroundWidth = 15
|
||||
var fill = status_colours[d.status.fill]; // Only allow our colours for now
|
||||
if (d.status.shape == null && fill == null) {
|
||||
backgroundWidth = 0
|
||||
@@ -4207,7 +4207,11 @@ RED.view = (function() {
|
||||
nodeEl.__statusLabel__.textContent = "";
|
||||
}
|
||||
const textSize = nodeEl.__statusLabel__.getBBox()
|
||||
nodeEl.__statusBackground__.setAttribute('width', backgroundWidth + textSize.width + 6)
|
||||
backgroundWidth += textSize.width
|
||||
if (backgroundWidth > 0 && textSize.width > 0) {
|
||||
backgroundWidth += 6
|
||||
}
|
||||
nodeEl.__statusBackground__.setAttribute('width', backgroundWidth)
|
||||
}
|
||||
delete d.dirtyStatus;
|
||||
}
|
||||
@@ -4619,8 +4623,8 @@ RED.view = (function() {
|
||||
statusBackground.setAttribute("y",-1);
|
||||
statusBackground.setAttribute("width",200);
|
||||
statusBackground.setAttribute("height",13);
|
||||
statusBackground.setAttribute("rx",1);
|
||||
statusBackground.setAttribute("ry",1);
|
||||
statusBackground.setAttribute("rx",2);
|
||||
statusBackground.setAttribute("ry",2);
|
||||
|
||||
statusEl.appendChild(statusBackground);
|
||||
node[0][0].__statusBackground__ = statusBackground;
|
||||
|
@@ -17,6 +17,8 @@
|
||||
|
||||
RED.workspaces = (function() {
|
||||
|
||||
const documentTitle = document.title;
|
||||
|
||||
var activeWorkspace = 0;
|
||||
var workspaceIndex = 0;
|
||||
|
||||
@@ -339,12 +341,18 @@ RED.workspaces = (function() {
|
||||
$("#red-ui-workspace-chart").show();
|
||||
activeWorkspace = tab.id;
|
||||
window.location.hash = 'flow/'+tab.id;
|
||||
if (tab.label) {
|
||||
document.title = `${documentTitle} : ${tab.label}`
|
||||
} else {
|
||||
document.title = documentTitle
|
||||
}
|
||||
$("#red-ui-workspace").toggleClass("red-ui-workspace-disabled", !!tab.disabled);
|
||||
$("#red-ui-workspace").toggleClass("red-ui-workspace-locked", !!tab.locked);
|
||||
} else {
|
||||
$("#red-ui-workspace-chart").hide();
|
||||
activeWorkspace = 0;
|
||||
window.location.hash = '';
|
||||
document.title = documentTitle
|
||||
}
|
||||
event.workspace = activeWorkspace;
|
||||
RED.events.emit("workspace:change",event);
|
||||
|
@@ -320,7 +320,7 @@
|
||||
}
|
||||
// but replace with repeat one if set to repeat
|
||||
if ((this.repeat && this.repeat != 0) || this.crontab) {
|
||||
suffix = " ↻";
|
||||
suffix = "\t↻";
|
||||
}
|
||||
if (this.name) {
|
||||
return this.name+suffix;
|
||||
|
@@ -109,9 +109,8 @@ module.exports = function(RED) {
|
||||
}
|
||||
const p = props.shift()
|
||||
const property = p.p;
|
||||
const value = p.v ? p.v : '';
|
||||
const valueType = p.vt ? p.vt : 'str';
|
||||
|
||||
const value = p.v !== undefined ? p.v : '';
|
||||
const valueType = p.vt !== undefined ? p.vt : 'str';
|
||||
if (property) {
|
||||
if (valueType === "jsonata") {
|
||||
if (p.v) {
|
||||
|
@@ -86,7 +86,7 @@
|
||||
},
|
||||
label: function() {
|
||||
var suffix = "";
|
||||
if (this.console === true || this.console === "true") { suffix = " ⇲"; }
|
||||
if (this.console === true || this.console === "true") { suffix = "\t⇲"; }
|
||||
if (this.targetType === "jsonata") {
|
||||
return (this.name || "JSONata") + suffix;
|
||||
}
|
||||
|
@@ -104,6 +104,7 @@ module.exports = function(RED) {
|
||||
* @returns `true` if it is a valid topic
|
||||
*/
|
||||
function isValidPublishTopic(topic) {
|
||||
if (topic.length === 0) return false;
|
||||
return !/[\+#\b\f\n\r\t\v\0]/.test(topic);
|
||||
}
|
||||
|
||||
@@ -219,8 +220,8 @@ module.exports = function(RED) {
|
||||
*/
|
||||
function subscriptionHandler(node, datatype ,topic, payload, packet) {
|
||||
const msg = {topic:topic, payload:null, qos:packet.qos, retain:packet.retain};
|
||||
const v5 = (node && node.brokerConn)
|
||||
? node.brokerConn.v5()
|
||||
const v5 = (node && node.brokerConn)
|
||||
? node.brokerConn.v5()
|
||||
: Object.prototype.hasOwnProperty.call(packet, "properties");
|
||||
if(v5 && packet.properties) {
|
||||
setStrProp(packet.properties, msg, "responseTopic");
|
||||
@@ -451,7 +452,7 @@ module.exports = function(RED) {
|
||||
|
||||
/**
|
||||
* Perform the disconnect action
|
||||
* @param {MQTTInNode|MQTTOutNode} node
|
||||
* @param {MQTTInNode|MQTTOutNode} node
|
||||
* @param {Function} done
|
||||
*/
|
||||
function handleDisconnectAction(node, done) {
|
||||
@@ -865,7 +866,7 @@ module.exports = function(RED) {
|
||||
* Call end and wait for the client to end (or timeout)
|
||||
* @param {mqtt.MqttClient} client The broker client
|
||||
* @param {number} ms The time to wait for the client to end
|
||||
* @returns
|
||||
* @returns
|
||||
*/
|
||||
let waitEnd = (client, ms) => {
|
||||
return new Promise( (resolve, reject) => {
|
||||
@@ -905,7 +906,7 @@ module.exports = function(RED) {
|
||||
node.subid = 1;
|
||||
|
||||
//typedef for subscription object:
|
||||
/**
|
||||
/**
|
||||
* @typedef {Object} Subscription
|
||||
* @property {String} topic - topic to subscribe to
|
||||
* @property {Object} [options] - options object
|
||||
@@ -933,7 +934,7 @@ module.exports = function(RED) {
|
||||
const ref = _ref || 0;
|
||||
let options
|
||||
let qos = 1 // default to QoS 1 (AWS and several other brokers don't support QoS 2)
|
||||
|
||||
|
||||
// if options is an object, then clone it
|
||||
if (typeof _options == "object") {
|
||||
options = RED.util.cloneMessage(_options || {})
|
||||
@@ -947,7 +948,7 @@ module.exports = function(RED) {
|
||||
if (typeof qos === "number" && qos >= 0 && qos <= 2) {
|
||||
options.qos = qos;
|
||||
}
|
||||
|
||||
|
||||
subscription.topic = _topic;
|
||||
subscription.qos = qos;
|
||||
subscription.options = RED.util.cloneMessage(options);
|
||||
@@ -957,16 +958,16 @@ module.exports = function(RED) {
|
||||
}
|
||||
|
||||
/**
|
||||
* If topic is a subscription object, then use that, otherwise look up the topic in
|
||||
* If topic is a subscription object, then use that, otherwise look up the topic in
|
||||
* the subscriptions object. If the topic is not found, then create a new subscription
|
||||
* object and add it to the subscriptions object.
|
||||
* @param {Subscription|String} topic
|
||||
* @param {*} options
|
||||
* @param {*} callback
|
||||
* @param {*} ref
|
||||
* @param {Subscription|String} topic
|
||||
* @param {*} options
|
||||
* @param {*} callback
|
||||
* @param {*} ref
|
||||
*/
|
||||
node.subscribe = function (topic, options, callback, ref) {
|
||||
/** @type {Subscription} */
|
||||
/** @type {Subscription} */
|
||||
let subscription
|
||||
let doCompare = false
|
||||
let changesFound = false
|
||||
@@ -1004,7 +1005,7 @@ module.exports = function(RED) {
|
||||
_brokerConn.unsubscribe(sub.topic, sub.ref, true)
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
// if subscription is found (or sent in as a parameter), then check for changes.
|
||||
// if there are any changes requested, tidy up the old subscription
|
||||
if (subscription) {
|
||||
@@ -1091,7 +1092,7 @@ module.exports = function(RED) {
|
||||
delete sub[ref]
|
||||
}
|
||||
}
|
||||
// if instructed to remove the actual MQTT client subscription
|
||||
// if instructed to remove the actual MQTT client subscription
|
||||
if (unsub) {
|
||||
// if there are no more subscriptions for the topic, then remove the topic
|
||||
if (Object.keys(sub).length === 0) {
|
||||
|
@@ -143,6 +143,12 @@ function loadModuleFiles(modules) {
|
||||
return loadNodeSetList(pluginList);
|
||||
}).then(function() {
|
||||
return loadNodeSetList(nodeList);
|
||||
}).then(function () {
|
||||
if (settings.available()) {
|
||||
return registry.saveNodeList();
|
||||
} else {
|
||||
return
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -436,7 +442,7 @@ async function loadPlugin(plugin) {
|
||||
return plugin;
|
||||
}
|
||||
}
|
||||
|
||||
let invocation = 0
|
||||
function loadNodeSetList(nodes) {
|
||||
var promises = [];
|
||||
nodes.forEach(function(node) {
|
||||
@@ -451,13 +457,7 @@ function loadNodeSetList(nodes) {
|
||||
}
|
||||
});
|
||||
|
||||
return Promise.all(promises).then(function() {
|
||||
if (settings.available()) {
|
||||
return registry.saveNodeList();
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
});
|
||||
return Promise.all(promises)
|
||||
}
|
||||
|
||||
function addModule(module) {
|
||||
|
@@ -99,6 +99,9 @@ var api = module.exports = {
|
||||
safeSettings.markdownEditor = runtime.settings.editorTheme.markdownEditor || {};
|
||||
safeSettings.markdownEditor.mermaid = safeSettings.markdownEditor.mermaid || { enabled: true };
|
||||
}
|
||||
if (runtime.settings.editorTheme.mermaid) {
|
||||
safeSettings.mermaid = runtime.settings.editorTheme.mermaid
|
||||
}
|
||||
}
|
||||
safeSettings.libraries = runtime.library.getLibraries();
|
||||
if (util.isArray(runtime.settings.paletteCategories)) {
|
||||
|
@@ -73,9 +73,20 @@ class Subflow extends Flow {
|
||||
id: subflowInstance.id,
|
||||
configs: {},
|
||||
nodes: {},
|
||||
groups: {},
|
||||
subflows: {}
|
||||
}
|
||||
|
||||
if (subflowDef.groups) {
|
||||
// Clone all of the subflow group definitions and give them new IDs
|
||||
for (i in subflowDef.groups) {
|
||||
if (subflowDef.groups.hasOwnProperty(i)) {
|
||||
node = createNodeInSubflow(subflowInstance.id,subflowDef.groups[i]);
|
||||
node_map[node._alias] = node;
|
||||
subflowInternalFlowConfig.groups[node.id] = node;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (subflowDef.configs) {
|
||||
// Clone all of the subflow config node definitions and give them new IDs
|
||||
for (i in subflowDef.configs) {
|
||||
|
@@ -57,18 +57,20 @@ var EnvVarPropertyRE = /^\${(\S+)}$/;
|
||||
|
||||
|
||||
function mapEnvVarProperties(obj,prop,flow,config) {
|
||||
var v = obj[prop];
|
||||
const v = obj[prop];
|
||||
if (Buffer.isBuffer(v)) {
|
||||
return;
|
||||
} else if (Array.isArray(v)) {
|
||||
for (var i=0;i<v.length;i++) {
|
||||
for (let i=0;i<v.length;i++) {
|
||||
mapEnvVarProperties(v,i,flow,config);
|
||||
}
|
||||
} else if (typeof obj[prop] === 'string') {
|
||||
if (obj[prop][0] === "$" && (EnvVarPropertyRE_old.test(v) || EnvVarPropertyRE.test(v)) ) {
|
||||
var envVar = v.substring(2,v.length-1);
|
||||
var r = redUtil.getSetting(config, envVar, flow);
|
||||
obj[prop] = r ? r : obj[prop];
|
||||
const envVar = v.substring(2,v.length-1);
|
||||
const r = redUtil.getSetting(config, envVar, flow);
|
||||
if (r !== undefined && r !== '') {
|
||||
obj[prop] = r
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (var p in v) {
|
||||
|
2
packages/node_modules/node-red/package.json
vendored
2
packages/node_modules/node-red/package.json
vendored
@@ -39,7 +39,7 @@
|
||||
"bcryptjs": "2.4.3",
|
||||
"express": "4.18.2",
|
||||
"fs-extra": "11.1.1",
|
||||
"node-red-admin": "^3.1.0",
|
||||
"node-red-admin": "^3.1.1",
|
||||
"nopt": "5.0.0",
|
||||
"semver": "7.5.4"
|
||||
},
|
||||
|
Reference in New Issue
Block a user