mirror of
https://github.com/node-red/node-red.git
synced 2025-03-01 10:36:34 +00:00
Merge branch 'master' of https://github.com/node-red/node-red
This commit is contained in:
@@ -100,7 +100,10 @@ function login(req,res) {
|
||||
}
|
||||
} else if (mergedAdminAuth.type === "strategy") {
|
||||
|
||||
var urlPrefix = (settings.httpAdminRoot==='/')?"":settings.httpAdminRoot;
|
||||
var urlPrefix = (settings.httpAdminRoot||"").replace(/\/$/,"");
|
||||
if (urlPrefix.length > 0) {
|
||||
urlPrefix += "/";
|
||||
}
|
||||
response = {
|
||||
"type":"strategy",
|
||||
"prompts":[{type:"button",label:mergedAdminAuth.strategy.label, url: urlPrefix + "auth/strategy"}]
|
||||
|
@@ -431,7 +431,7 @@ var RED = (function() {
|
||||
'<img width="50px" src="red/images/node-red-icon.svg" />'+
|
||||
'</div>';
|
||||
|
||||
RED.sidebar.info.set(aboutHeader+marked(data));
|
||||
RED.sidebar.info.set(aboutHeader+RED.utils.renderMarkdown(data));
|
||||
RED.sidebar.info.show();
|
||||
});
|
||||
}
|
||||
|
@@ -102,7 +102,7 @@
|
||||
var f = $(this).val();
|
||||
var args = RED._('jsonata:'+f+".args",{defaultValue:''});
|
||||
var title = "<h5>"+f+"("+args+")</h5>";
|
||||
var body = marked(RED._('jsonata:'+f+'.desc',{defaultValue:''}));
|
||||
var body = RED.utils.renderMarkdown(RED._('jsonata:'+f+'.desc',{defaultValue:''}));
|
||||
$("#red-ui-editor-type-expression-help").html(title+"<p>"+body+"</p>");
|
||||
|
||||
})
|
||||
|
@@ -107,7 +107,7 @@
|
||||
clearTimeout(changeTimer);
|
||||
changeTimer = setTimeout(function() {
|
||||
var currentScrollTop = $(".red-ui-editor-type-markdown-panel-preview").scrollTop();
|
||||
$(".red-ui-editor-type-markdown-panel-preview").html(marked(expressionEditor.getValue()));
|
||||
$(".red-ui-editor-type-markdown-panel-preview").html(RED.utils.renderMarkdown(expressionEditor.getValue()));
|
||||
$(".red-ui-editor-type-markdown-panel-preview").scrollTop(currentScrollTop);
|
||||
},200);
|
||||
})
|
||||
@@ -116,7 +116,7 @@
|
||||
}
|
||||
|
||||
if (value) {
|
||||
$(".red-ui-editor-type-markdown-panel-preview").html(marked(expressionEditor.getValue()));
|
||||
$(".red-ui-editor-type-markdown-panel-preview").html(RED.utils.renderMarkdown(expressionEditor.getValue()));
|
||||
}
|
||||
panels = RED.panels.create({
|
||||
id:"red-ui-editor-type-markdown-panels",
|
||||
|
@@ -269,7 +269,7 @@ RED.palette = (function() {
|
||||
RED.view.focus();
|
||||
var helpText;
|
||||
if (nt.indexOf("subflow:") === 0) {
|
||||
helpText = marked(RED.nodes.subflow(nt.substring(8)).info||"")||('<span class="red-ui-help-info-none">'+RED._("sidebar.info.none")+'</span>');
|
||||
helpText = RED.utils.renderMarkdown(RED.nodes.subflow(nt.substring(8)).info||"")||('<span class="red-ui-help-info-none">'+RED._("sidebar.info.none")+'</span>');
|
||||
} else {
|
||||
helpText = $("script[data-help-name='"+d.attr("data-palette-type")+"']").html()||('<span class="red-ui-help-info-none">'+RED._("sidebar.info.none")+'</span>');
|
||||
}
|
||||
@@ -370,7 +370,7 @@ RED.palette = (function() {
|
||||
RED.workspaces.show(nt.substring(8));
|
||||
e.preventDefault();
|
||||
});
|
||||
nodeInfo = marked(def.info||"");
|
||||
nodeInfo = RED.utils.renderMarkdown(def.info||"");
|
||||
}
|
||||
setLabel(nt,d,label,nodeInfo);
|
||||
|
||||
@@ -440,7 +440,7 @@ RED.palette = (function() {
|
||||
} else if (portOutput.length !== 0 && sf.out.length === 0) {
|
||||
portOutput.remove();
|
||||
}
|
||||
setLabel(sf.type+":"+sf.id,paletteNode,sf.name,marked(sf.info||""));
|
||||
setLabel(sf.type+":"+sf.id,paletteNode,sf.name,RED.utils.renderMarkdown(sf.info||""));
|
||||
setIcon(paletteNode,sf);
|
||||
|
||||
var currentCategory = paletteNode.data('category');
|
||||
|
@@ -158,7 +158,7 @@ RED.projects.settings = (function() {
|
||||
container.empty();
|
||||
var desc;
|
||||
if (activeProject.description) {
|
||||
desc = marked(activeProject.description);
|
||||
desc = RED.utils.renderMarkdown(activeProject.description);
|
||||
} else {
|
||||
desc = '<span class="red-ui-help-info-none">' + RED._("sidebar.project.noDescriptionAvailable") + '</span>';
|
||||
}
|
||||
|
@@ -15,17 +15,6 @@
|
||||
**/
|
||||
RED.sidebar.info = (function() {
|
||||
|
||||
marked.setOptions({
|
||||
renderer: new marked.Renderer(),
|
||||
gfm: true,
|
||||
tables: true,
|
||||
breaks: false,
|
||||
pedantic: false,
|
||||
sanitize: true,
|
||||
smartLists: true,
|
||||
smartypants: false
|
||||
});
|
||||
|
||||
var content;
|
||||
var sections;
|
||||
var propertiesSection;
|
||||
@@ -314,7 +303,7 @@ RED.sidebar.info = (function() {
|
||||
if (subflowNode && node.type !== "subflow") {
|
||||
// Selected a subflow instance node.
|
||||
// - The subflow template info goes into help
|
||||
helpText = (marked(subflowNode.info||"")||('<span class="red-ui-help-info-none">'+RED._("sidebar.info.none")+'</span>'));
|
||||
helpText = (RED.utils.renderMarkdown(subflowNode.info||"")||('<span class="red-ui-help-info-none">'+RED._("sidebar.info.none")+'</span>'));
|
||||
} else {
|
||||
helpText = $("script[data-help-name='"+node.type+"']").html()||('<span class="red-ui-help-info-none">'+RED._("sidebar.info.none")+'</span>');
|
||||
}
|
||||
@@ -326,10 +315,10 @@ RED.sidebar.info = (function() {
|
||||
if (node._def && node._def.info) {
|
||||
var info = node._def.info;
|
||||
var textInfo = (typeof info === "function" ? info.call(node) : info);
|
||||
infoText = infoText + marked(textInfo);
|
||||
infoText = infoText + RED.utils.renderMarkdown(textInfo);
|
||||
}
|
||||
if (node.info) {
|
||||
infoText = infoText + marked(node.info || "")
|
||||
infoText = infoText + RED.utils.renderMarkdown(node.info || "")
|
||||
}
|
||||
setInfoText(infoText, infoSection.content);
|
||||
|
||||
|
@@ -16,6 +16,28 @@
|
||||
|
||||
RED.utils = (function() {
|
||||
|
||||
window._marked = window.marked;
|
||||
window.marked = function(txt) {
|
||||
console.warn("Use of 'marked()' is deprecated. Use RED.utils.renderMarkdown() instead");
|
||||
return renderMarkdown(txt);
|
||||
}
|
||||
|
||||
_marked.setOptions({
|
||||
renderer: new _marked.Renderer(),
|
||||
gfm: true,
|
||||
tables: true,
|
||||
breaks: false,
|
||||
pedantic: false,
|
||||
smartLists: true,
|
||||
smartypants: false
|
||||
});
|
||||
|
||||
function renderMarkdown(txt) {
|
||||
var rendered = _marked(txt);
|
||||
var cleaned = DOMPurify.sanitize(rendered, {SAFE_FOR_JQUERY: true})
|
||||
return cleaned;
|
||||
}
|
||||
|
||||
function formatString(str) {
|
||||
return str.replace(/\r?\n/g,"↵").replace(/\t/g,"→");
|
||||
}
|
||||
@@ -1053,6 +1075,7 @@ RED.utils = (function() {
|
||||
decodeObject: decodeObject,
|
||||
parseContextKey: parseContextKey,
|
||||
createIconElement: createIconElement,
|
||||
sanitize: sanitize
|
||||
sanitize: sanitize,
|
||||
renderMarkdown: renderMarkdown
|
||||
}
|
||||
})();
|
||||
|
@@ -11,6 +11,7 @@
|
||||
var length = str.length;
|
||||
var start = 0;
|
||||
var inString = false;
|
||||
var inRegex = false;
|
||||
var inBox = false;
|
||||
var quoteChar;
|
||||
var list = [];
|
||||
@@ -24,8 +25,13 @@
|
||||
}
|
||||
for (var i=0;i<length;i++) {
|
||||
var c = str[i];
|
||||
if (!inString) {
|
||||
if (c === "'" || c === '"') {
|
||||
if (!inString && !inRegex) {
|
||||
if (c === "/") {
|
||||
inRegex = true;
|
||||
frame = {type:"regex",pos:i};
|
||||
list.push(frame);
|
||||
stack.push(frame);
|
||||
} else if (c === "'" || c === '"') {
|
||||
inString = true;
|
||||
quoteChar = c;
|
||||
frame = {type:"string",pos:i};
|
||||
@@ -37,6 +43,9 @@
|
||||
} else if (c === ",") {
|
||||
frame = {type:",",pos:i};
|
||||
list.push(frame);
|
||||
} else if (c === "&") {
|
||||
frame = {type:"&",pos:i};
|
||||
list.push(frame);
|
||||
} else if (/[\(\[\{]/.test(c)) {
|
||||
frame = {type:"open-block",char:c,pos:i};
|
||||
list.push(frame);
|
||||
@@ -44,7 +53,8 @@
|
||||
} else if (/[\}\)\]]/.test(c)) {
|
||||
var oldFrame = stack.pop();
|
||||
if (matchingBrackets[oldFrame.char] !== c) {
|
||||
//console.log("Stack frame mismatch",c,"at",i,"expected",matchingBrackets[oldFrame.char],"from",oldFrame.pos);
|
||||
// console.log("Stack frame mismatch",c,"at",i,"expected",matchingBrackets[oldFrame.char],"from",oldFrame.pos);
|
||||
// console.log(list);
|
||||
return str;
|
||||
}
|
||||
//console.log("Closing",c,"at",i,"compare",oldFrame.type,oldFrame.pos);
|
||||
@@ -53,19 +63,32 @@
|
||||
list.push(frame);
|
||||
}
|
||||
} else {
|
||||
if (c === quoteChar) {
|
||||
// Next char must be a ]
|
||||
inString = false;
|
||||
stack.pop();
|
||||
if (c === "\\") {
|
||||
// an escaped char - stay in current mode and skip the next char
|
||||
i++;
|
||||
}
|
||||
if (inString) {
|
||||
if (c === quoteChar) {
|
||||
// Next char must be a ]
|
||||
inString = false;
|
||||
var f = stack.pop();
|
||||
f.end = i;
|
||||
}
|
||||
} else if (inRegex) {
|
||||
if (c === "/") {
|
||||
inRegex = false;
|
||||
var f = stack.pop();
|
||||
f.end = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
// console.log(stack);
|
||||
// console.log("list",list);
|
||||
|
||||
var result = str;
|
||||
var indent = 0;
|
||||
var offset = 0;
|
||||
var pre,post,indented;
|
||||
var pre,post,indented,hasNewline;
|
||||
var longStack = [];
|
||||
list.forEach(function(f) {
|
||||
if (f.type === ";" || f.type === ",") {
|
||||
@@ -73,29 +96,51 @@
|
||||
pre = result.substring(0,offset+f.pos+1);
|
||||
post = result.substring(offset+f.pos+1);
|
||||
indented = indentLine(post,indent);
|
||||
result = pre+"\n"+indented;
|
||||
offset += indented.length-post.length+1;
|
||||
hasNewline = /\n$/.test(pre);
|
||||
// console.log("A§"+pre+"§\n§"+indented+"§",hasNewline);
|
||||
result = pre+(hasNewline?"":"\n")+indented;
|
||||
offset += indented.length-post.length+(hasNewline?0:1);
|
||||
}
|
||||
} else if (f.type === "&") {
|
||||
pre = result.substring(0,offset+f.pos+1);
|
||||
var lastLineBreak = pre.lastIndexOf("\n");
|
||||
var lineLength = pre.length - lastLineBreak;
|
||||
if (lineLength > 70) {
|
||||
post = result.substring(offset+f.pos+1);
|
||||
if (!/^\n/.test(post)) {
|
||||
indented = indentLine(post,indent);
|
||||
hasNewline = /\n$/.test(pre);
|
||||
result = pre+(hasNewline?"":"\n")+indented;
|
||||
offset += indented.length-post.length+(hasNewline?0:1);
|
||||
}
|
||||
}
|
||||
|
||||
} else if (f.type === "open-block") {
|
||||
if (f.width > 30) {
|
||||
if (f.width > 40) {
|
||||
longStack.push(true);
|
||||
indent += 4;
|
||||
pre = result.substring(0,offset+f.pos+1);
|
||||
post = result.substring(offset+f.pos+1);
|
||||
hasNewline = /\n$/.test(pre);
|
||||
indented = indentLine(post,indent);
|
||||
result = pre+"\n"+indented;
|
||||
offset += indented.length-post.length+1;
|
||||
result = pre+(hasNewline?"":"\n")+indented;
|
||||
offset += indented.length-post.length+(hasNewline?0:1);
|
||||
} else {
|
||||
longStack.push(false);
|
||||
}
|
||||
} else if (f.type === "close-block") {
|
||||
if (f.width > 30) {
|
||||
if (f.width > 40) {
|
||||
indent -= 4;
|
||||
pre = result.substring(0,offset+f.pos);
|
||||
post = result.substring(offset+f.pos);
|
||||
indented = indentLine(post,indent);
|
||||
result = pre+"\n"+indented;
|
||||
offset += indented.length-post.length+1;
|
||||
hasNewline = /\n *$/.test(pre);
|
||||
if (hasNewline) {
|
||||
result = pre + post;
|
||||
} else {
|
||||
result = pre+"\n"+indented;
|
||||
offset += indented.length-post.length+1;
|
||||
}
|
||||
}
|
||||
longStack.pop();
|
||||
}
|
||||
|
@@ -28,6 +28,11 @@ ace.define("ace/mode/jsonata",["require","exports","module","ace/lib/oop","ace/m
|
||||
}, "identifier");
|
||||
this.$rules = {
|
||||
"start" : [
|
||||
{
|
||||
token: "string.regexp",
|
||||
regex: "\\/",
|
||||
next: "regex"
|
||||
},
|
||||
{
|
||||
token : "string",
|
||||
regex : "'(?=.)",
|
||||
@@ -46,34 +51,35 @@ ace.define("ace/mode/jsonata",["require","exports","module","ace/lib/oop","ace/m
|
||||
token : "constant.numeric", // float
|
||||
regex : /[+-]?\d[\d_]*(?:(?:\.\d*)?(?:[eE][+-]?\d+)?)?\b/
|
||||
},
|
||||
{ token: "keyword",
|
||||
regex: /λ/
|
||||
},
|
||||
{
|
||||
token: "keyword",
|
||||
regex: jsonataFunctions
|
||||
},
|
||||
{
|
||||
token : keywordMapper,
|
||||
regex : "[a-zA-Z\\$_\u00a1-\uffff][a-zA-Z\\d\\$_\u00a1-\uffff]*"
|
||||
},
|
||||
{
|
||||
token : "punctuation.operator",
|
||||
regex : /[.](?![.])/
|
||||
},
|
||||
{
|
||||
token : "keyword.operator",
|
||||
regex : /\|\||<=|>=|\.\.|\*\*|!=|:=|[=<>`!$%&*+\-~\/^]/,
|
||||
next : "start"
|
||||
},
|
||||
{
|
||||
token : "punctuation.operator",
|
||||
regex : /[?:,;.]/,
|
||||
next : "start"
|
||||
},
|
||||
{
|
||||
token : "paren.lparen",
|
||||
regex : /[\[({]/,
|
||||
{
|
||||
token: "keyword",
|
||||
regex: /λ/
|
||||
},
|
||||
{
|
||||
token: "keyword",
|
||||
regex: jsonataFunctions
|
||||
},
|
||||
{
|
||||
token : keywordMapper,
|
||||
regex : "[a-zA-Z\\$_\u00a1-\uffff][a-zA-Z\\d\\$_\u00a1-\uffff]*"
|
||||
},
|
||||
{
|
||||
token : "punctuation.operator",
|
||||
regex : /[.](?![.])/
|
||||
},
|
||||
{
|
||||
token : "keyword.operator",
|
||||
regex : /\|\||<=|>=|\.\.|\*\*|!=|:=|[=<>`!$%&*+\-~\/^]/,
|
||||
next : "start"
|
||||
},
|
||||
{
|
||||
token : "punctuation.operator",
|
||||
regex : /[?:,;.]/,
|
||||
next : "start"
|
||||
},
|
||||
{
|
||||
token : "paren.lparen",
|
||||
regex : /[\[({]/,
|
||||
next : "start"
|
||||
},
|
||||
{
|
||||
@@ -86,7 +92,8 @@ ace.define("ace/mode/jsonata",["require","exports","module","ace/lib/oop","ace/m
|
||||
token : "string",
|
||||
regex : '"|$',
|
||||
next : "start"
|
||||
}, {
|
||||
},
|
||||
{
|
||||
defaultToken: "string"
|
||||
}
|
||||
],
|
||||
@@ -95,9 +102,24 @@ ace.define("ace/mode/jsonata",["require","exports","module","ace/lib/oop","ace/m
|
||||
token : "string",
|
||||
regex : "'|$",
|
||||
next : "start"
|
||||
}, {
|
||||
},
|
||||
{
|
||||
defaultToken: "string"
|
||||
}
|
||||
],
|
||||
"regex" : [
|
||||
{
|
||||
token: "string.regexp",
|
||||
regex: "\\\\/"
|
||||
},
|
||||
{
|
||||
token: "string.regexp",
|
||||
regex: "/[sxngimy]*",
|
||||
next: "start"
|
||||
},
|
||||
{
|
||||
defaultToken: "string.regexp"
|
||||
}
|
||||
]
|
||||
};
|
||||
};
|
||||
|
File diff suppressed because one or more lines are too long
@@ -27,7 +27,7 @@
|
||||
"fs-extra": "8.1.0",
|
||||
"fs.notify": "0.0.4",
|
||||
"hash-sum": "2.0.0",
|
||||
"https-proxy-agent": "2.2.4",
|
||||
"https-proxy-agent": "5.0.0",
|
||||
"is-utf8": "0.2.1",
|
||||
"js-yaml": "3.13.1",
|
||||
"media-typer": "1.1.0",
|
||||
|
@@ -57,6 +57,8 @@ var api = module.exports = {
|
||||
* Sets the current flow configuration
|
||||
* @param {Object} opts
|
||||
* @param {User} opts.user - the user calling the api
|
||||
* @param {Object} opts.flows - the flow configuration: `{flows: [..], credentials: {}}`
|
||||
* @param {Object} opts.deploymentType - the type of deployment - "full", "nodes", "flows", "reload"
|
||||
* @param {Object} opts.req - the request to log (optional)
|
||||
* @return {Promise<Flows>} - the active flow configuration
|
||||
* @memberof @node-red/runtime_flows
|
||||
@@ -83,7 +85,7 @@ var api = module.exports = {
|
||||
return reject(err);
|
||||
}
|
||||
}
|
||||
apiPromise = runtime.nodes.setFlows(flows.flows,deploymentType);
|
||||
apiPromise = runtime.nodes.setFlows(flows.flows,flows.credentials,deploymentType);
|
||||
}
|
||||
apiPromise.then(function(flowId) {
|
||||
return resolve({rev:flowId});
|
||||
|
@@ -106,15 +106,20 @@ function load(forceStart) {
|
||||
// This is a force reload from the API - disable safeMode
|
||||
delete settings.safeMode;
|
||||
}
|
||||
return setFlows(null,"load",false,forceStart);
|
||||
return setFlows(null,null,"load",false,forceStart);
|
||||
}
|
||||
|
||||
/*
|
||||
* _config - new node array configuration
|
||||
* _credentials - new credentials configuration (optional)
|
||||
* type - full/nodes/flows/load (default full)
|
||||
* muteLog - don't emit the standard log messages (used for individual flow api)
|
||||
*/
|
||||
function setFlows(_config,type,muteLog,forceStart) {
|
||||
function setFlows(_config,_credentials,type,muteLog,forceStart) {
|
||||
if (typeof _credentials === "string") {
|
||||
type = _credentials;
|
||||
_credentials = null;
|
||||
}
|
||||
type = type||"full";
|
||||
if (settings.safeMode) {
|
||||
if (type !== "load") {
|
||||
@@ -155,16 +160,27 @@ function setFlows(_config,type,muteLog,forceStart) {
|
||||
delete newFlowConfig.allNodes[id].credentials;
|
||||
}
|
||||
}
|
||||
var credsDirty;
|
||||
|
||||
// Allow the credential store to remove anything no longer needed
|
||||
credentials.clean(config);
|
||||
if (_credentials) {
|
||||
// A full set of credentials have been provided. Use those instead
|
||||
configSavePromise = credentials.load(_credentials);
|
||||
credsDirty = true;
|
||||
} else {
|
||||
// Allow the credential store to remove anything no longer needed
|
||||
credentials.clean(config);
|
||||
|
||||
// Remember whether credentials need saving or not
|
||||
var credsDirty = credentials.dirty();
|
||||
// Remember whether credentials need saving or not
|
||||
var credsDirty = credentials.dirty();
|
||||
|
||||
configSavePromise = Promise.resolve();
|
||||
}
|
||||
|
||||
// Get the latest credentials and ask storage to save them (if needed)
|
||||
// as well as the new flow configuration.
|
||||
configSavePromise = credentials.export().then(function(creds) {
|
||||
configSavePromise = configSavePromise.then(function() {
|
||||
return credentials.export()
|
||||
}).then(function(creds) {
|
||||
var saveConfig = {
|
||||
flows: config,
|
||||
credentialsDirty:credsDirty,
|
||||
@@ -515,7 +531,7 @@ function addFlow(flow) {
|
||||
var newConfig = clone(activeConfig.flows);
|
||||
newConfig = newConfig.concat(nodes);
|
||||
|
||||
return setFlows(newConfig,'flows',true).then(function() {
|
||||
return setFlows(newConfig,null,'flows',true).then(function() {
|
||||
log.info(log._("nodes.flows.added-flow",{label:(flow.label?flow.label+" ":"")+"["+flow.id+"]"}));
|
||||
return flow.id;
|
||||
});
|
||||
@@ -646,7 +662,7 @@ function updateFlow(id,newFlow) {
|
||||
}
|
||||
|
||||
newConfig = newConfig.concat(nodes);
|
||||
return setFlows(newConfig,'flows',true).then(function() {
|
||||
return setFlows(newConfig,null,'flows',true).then(function() {
|
||||
log.info(log._("nodes.flows.updated-flow",{label:(label?label+" ":"")+"["+id+"]"}));
|
||||
})
|
||||
}
|
||||
@@ -668,7 +684,7 @@ function removeFlow(id) {
|
||||
return node.z !== id && node.id !== id;
|
||||
});
|
||||
|
||||
return setFlows(newConfig,'flows',true).then(function() {
|
||||
return setFlows(newConfig,null,'flows',true).then(function() {
|
||||
log.info(log._("nodes.flows.removed-flow",{label:(flow.label?flow.label+" ":"")+"["+flow.id+"]"}));
|
||||
});
|
||||
}
|
||||
|
@@ -18,7 +18,7 @@
|
||||
"clone": "2.1.2",
|
||||
"i18next": "15.1.2",
|
||||
"json-stringify-safe": "5.0.1",
|
||||
"jsonata": "1.8.0",
|
||||
"jsonata": "1.8.1",
|
||||
"when": "3.7.8"
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user