Riorganizzato in cartelle e aggiunto tcp

This commit is contained in:
2020-04-16 18:41:44 +02:00
parent d97866933e
commit 2ea5fe3063
11 changed files with 1584 additions and 14 deletions
+332
View File
@@ -0,0 +1,332 @@
<script type="text/html" data-template-name="parser-consume">
<div class="form-row">
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
<input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
</div>
<div class="form-row">
<label for="node-input-property"><i class="fa fa-ellipsis-h"></i> <span data-i18n="switch.label.property"></span></label>
<input type="text" id="node-input-property" style="width: 70%"/>
<input type="hidden" id="node-input-outputs"/>
</div>
<div class="form-row node-input-rule-container-row">
<ol id="node-input-rule-container"></ol>
</div>
<!--<div class="form-row">
<label>&nbsp;</label>
<input type="checkbox" id="node-input-elsenode" placeholder="" style="display:inline-block; width:auto; vertical-align:top;">
<label for="node-input-elsenode" style="width:70%;">Add <code>else</code> output</label>
</div>-->
<div class="form-row">
<select id="node-input-checkall" style="width:100%; margin-right:5px;">
<option value="true" data-i18n="switch.checkall">All matches</option>
<option value="false" data-i18n="switch.stopfirst">First match</option>
</select>
</div>
</script>
<script type="text/javascript">
(function () {
var operators = [
{ v: "eq", t: "==", kind: 'V' },
{ v: "regex", t: "/regex/", kind: 'V' }
];
function clipValueLength(v) {
if (v.length > 15) {
return v.substring(0, 15) + "...";
}
return v;
}
function prop2name(key) {
var result = RED.utils.parseContextKey(key);
return result.key;
}
function getValueLabel(t, v) {
if (t === 'str') {
return '"' + clipValueLength(v) + '"';
} else if (t === 'msg') {
return t + "." + clipValueLength(v);
} else if (t === 'flow' || t === 'global') {
return t + "." + clipValueLength(prop2name(v));
}
return clipValueLength(v);
}
RED.nodes.registerType('parser-consume', {
color: "#77aadd",
category: 'function',
defaults: {
name: { value: "" },
property: { value: "payload", required: true, validate: RED.validators.typedInput("propertyType") },
propertyType: { value: "msg" },
rules: { value: [{ t: "eq", v: "", vt: "str" }] },
checkall: { value: "true", required: true },
outputs: { value: 1 },
elsenode: { value: false }
},
inputs: 1,
outputs: 1,
outputLabels: function (index) {
var rule = this.rules[index];
var label = "";
if (rule) {
label = rule.v;
if (label == "") {
return "(empty)";
}
return label;
}
},
icon: "switch.svg",
label: function () {
return this.name || "Consume token";
},
labelStyle: function () {
return this.name ? "node_label_italic" : "";
},
oneditprepare: function () {
var node = this;
var previousValueType = { value: "prev", label: this._("switch.previous"), hasValue: false };
$("#node-input-property").typedInput({ default: this.propertyType || 'msg', types: ['msg', 'flow', 'global', 'jsonata', 'env'] });
var outputCount = $("#node-input-outputs").val("{}");
var andLabel = this._("switch.and");
var caseLabel = this._("switch.ignorecase");
function resizeRule(rule) {
var newWidth = rule.width();
var selectField = rule.find("select");
var type = selectField.val() || "";
var valueField = rule.find(".node-input-rule-value");
var typeField = rule.find(".node-input-rule-type-value");
var numField = rule.find(".node-input-rule-num-value");
var expField = rule.find(".node-input-rule-exp-value");
var keyField = rule.find(".node-input-rule-key-value");
var btwnField1 = rule.find(".node-input-rule-btwn-value");
var btwnField2 = rule.find(".node-input-rule-btwn-value2");
var selectWidth;
if (type.length < 4) {
selectWidth = 60;
} else if (type === "regex") {
selectWidth = 147;
} else {
selectWidth = 120;
}
selectField.width(selectWidth);
valueField.typedInput("width", (newWidth - selectWidth - 70));
}
$("#node-input-rule-container").css('min-height', '150px').css('min-width', '450px').editableList({
addItem: function (container, i, opt) {
if (!opt.hasOwnProperty('r')) {
opt.r = {};
}
var rule = opt.r;
if (!rule.hasOwnProperty('t')) {
rule.t = 'eq';
}
if (!opt.hasOwnProperty('i')) {
opt._i = Math.floor((0x99999 - 0x10000) * Math.random()).toString();
}
container.css({
overflow: 'hidden',
whiteSpace: 'nowrap'
});
var row = $('<div/>').appendTo(container);
var row2 = $('<div/>').appendTo(container);
var row3 = $('<div/>').appendTo(container);
var selectField = $('<select/>', { style: "width:120px; margin-left: 5px; text-align: center;" }).appendTo(row);
var group0 = $('<optgroup/>', { label: "value rules" }).appendTo(selectField);
for (var d in operators) {
if (operators[d].kind === 'V') {
group0.append($("<option></option>").val(operators[d].v).text(/^switch/.test(operators[d].t) ? node._(operators[d].t) : operators[d].t));
}
}
function createValueField() {
return $('<input/>', { class: "node-input-rule-value", type: "text", style: "margin-left: 5px;" }).appendTo(row).typedInput({ default: 'str', types: ['str'] });
}
function createTypeValueField() {
return $('<input/>', { class: "node-input-rule-type-value", type: "text", style: "margin-left: 5px;" }).appendTo(row).typedInput({
default: 'string', types: [
{ value: "string", label: RED._("common.type.string"), hasValue: false, icon: "red/images/typedInput/az.png" },
]
});
}
var valueField = null;
var numValueField = null;
var expValueField = null;
var btwnAndLabel = null;
var btwnValueField = null;
var btwnValue2Field = null;
var typeValueField = null;
var finalspan = $('<span/>', { style: "float: right;margin-top: 6px;" }).appendTo(row);
var desc_label = $('<span/>', {style:"width:100px;display:inline-block;"}).text("Help:").appendTo(row2);
var desc = $('<input/>', { class: "node-input-rule-help", type: "text", style: "margin-left: 5px; width:250px", placeholder:"Help description" }).appendTo(row2);
desc.val(rule.help || "");
var desc_label = $('<span/>', {style:"width:100px;display:inline-block;"}).text("Variable:").appendTo(row3);
var match_name = $('<input/>', { class: "node-input-rule-match_name", type: "text", style: "margin-left: 5px; width: 250px;", placeholder:"Matched variable name" }).appendTo(row3);
match_name.val(rule.match_name || "");
if (rule.type !== "regex") {
row3.hide();
}
finalspan.append(' &#8594; <span class="node-input-rule-index">' + (i + 1) + '</span> ');
selectField.on("change", function () {
var type = selectField.val();
if (type == "regex") {
row3.show();
} else {
row3.hide();
}
valueField.typedInput('hide');
if (!valueField) {
valueField = createValueField();
}
valueField.typedInput('show');
resizeRule(container);
});
selectField.val(rule.t);
if (!valueField) {
valueField = createValueField();
}
valueField.typedInput('value', rule.v);
valueField.typedInput('type', 'str');
selectField.change();
var currentOutputs = JSON.parse(outputCount.val() || "{}");
currentOutputs[opt.hasOwnProperty('i') ? opt.i : opt._i] = i;
outputCount.val(JSON.stringify(currentOutputs));
},
removeItem: function (opt) {
var currentOutputs = JSON.parse(outputCount.val() || "{}");
if (opt.hasOwnProperty('i')) {
currentOutputs[opt.i] = -1;
} else {
delete currentOutputs[opt._i];
}
var rules = $("#node-input-rule-container").editableList('items');
rules.each(function (i) {
$(this).find(".node-input-rule-index").html(i + 1);
var data = $(this).data('data');
currentOutputs[data.hasOwnProperty('i') ? data.i : data._i] = i;
});
outputCount.val(JSON.stringify(currentOutputs));
},
resizeItem: resizeRule,
sortItems: function (rules) {
var currentOutputs = JSON.parse(outputCount.val() || "{}");
var rules = $("#node-input-rule-container").editableList('items');
rules.each(function (i) {
$(this).find(".node-input-rule-index").html(i + 1);
var data = $(this).data('data');
currentOutputs[data.hasOwnProperty('i') ? data.i : data._i] = i;
});
outputCount.val(JSON.stringify(currentOutputs));
},
sortable: true,
removable: true
});
for (var i = 0; i < this.rules.length; i++) {
var rule = this.rules[i];
$("#node-input-rule-container").editableList('addItem', { r: rule, i: i });
}
},
oneditsave: function () {
var rules = $("#node-input-rule-container").editableList('items');
var node = this;
node.rules = [];
rules.each(function (i) {
var ruleData = $(this).data('data');
var rule = $(this);
var type = rule.find("select").val();
var r = { t: type };
r.v = rule.find(".node-input-rule-value").typedInput('value');
r.vt = rule.find(".node-input-rule-value").typedInput('type');
r.help = rule.find(".node-input-rule-help").val();
if(r.t == 'regex') {
r.match_name = rule.find(".node-input-rule-match_name").val();
}
node.rules.push(r);
});
this.propertyType = $("#node-input-property").typedInput('type');
},
oneditresize: function (size) {
var rows = $("#dialog-form>div:not(.node-input-rule-container-row)");
var height = size.height;
for (var i = 0; i < rows.length; i++) {
height -= $(rows[i]).outerHeight(true);
}
var editorRow = $("#dialog-form>div.node-input-rule-container-row");
height -= (parseInt(editorRow.css("marginTop")) + parseInt(editorRow.css("marginBottom")));
height += 16;
$("#node-input-rule-container").editableList('height', height);
}
});
})();
</script>
<script type="text/html" data-template-name="parser-entry-point">
<div class="form-row">
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
<input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
</div>
<div class="form-row">
<label for="node-input-property"><i class="fa fa-ellipsis-h"></i> Property:</label>
<input type="text" id="node-input-property" style="width: 70%"/>
</div>
<div class="form-row">
<label for="node-input-help_keyword"><i class="fa fa-ellipsis-h"></i> Help keyword:</label>
<input type="text" id="node-input-help_keyword" style="width: 70%"/>
</div>
<div class="form-row node-text-editor-row">
<input type="hidden" id="node-input-help_text" autofocus="autofocus">
<div style="height: 250px; min-height:150px;" class="node-text-editor" id="node-input-help_text-editor"></div>
</div>
</script>
<script type="text/javascript">
RED.nodes.registerType('parser-entry-point',{
category: 'function',
color: "#77aadd",
defaults: {
property: { value: "payload", required: true, validate: RED.validators.typedInput("propertyType") },
name: { value: "" },
help_text: {value: ""},
help_keyword: {value: "help"},
},
inputs: 1,
outputs: 2,
label: function() {
return this.name || "parser entry point";
},
oneditprepare: function() {
var that = this;
this.editor = RED.editor.createEditor({
id: 'node-input-help_text-editor',
value: $("#node-input-help_text").val()
});
this.editor.focus();
},
oneditsave: function() {
$("#node-input-help_text").val(this.editor.getValue());
this.editor.destroy();
delete this.editor;
},
oneditcancel: function() {
this.editor.destroy();
delete this.editor;
},
});
</script>
+170
View File
@@ -0,0 +1,170 @@
module.exports = function (RED) {
"use strict";
function format_usage(usage, prefix) {
if (!prefix) {
prefix = [];
}
let out = "";
for (let k in usage) {
if (!usage.hasOwnProperty(k))
continue;
if(typeof usage[k] == "object"){
out += format_usage(usage[k], prefix.concat([k]));
} else {
let ext = k != "" ? [k] : [];
out += prefix.concat(ext).join(" ") + ": " + usage[k] + "\n";
}
}
return out;
}
function depth_first(n, path) {
if (!path) {
path = [n.id];
}
if (!n) {
return null;
}
let usage = {};
if (n.type == 'parser-consume') {
for (let r_idx in n.rules) {
let r = n.rules[r_idx];
let key;
if (r.t == "regex") {
if (r.match_name){
key = `[${r.match_name}]`;
} else {
key = `[espressione]`;
}
} else {
key = r.v;
}
if (r.help) {
usage[key] = r.help;
} else {
let sub_usage = {};
for (let wire of n.wires[r_idx]) {
if (path.indexOf(wire) === -1) {
let sub_n = RED.nodes.getNode(wire);
let tmp_sub_usage = depth_first(sub_n, path + [wire]);
if (tmp_sub_usage !== null) {
Object.assign(sub_usage, tmp_sub_usage);
}
}
}
usage[key] = sub_usage;
}
}
}
return usage;
}
function ParserEntryPoint(n) {
RED.nodes.createNode(this, n);
this.property = n.property;
this.help_text = n.help_text;
this.help_keyword = n.help_keyword;
this.genera_errore = function(msg) {
let out = "";
if (msg && msg.token_parser && msg.token_parser.consumed_tokens.length > 0) {
let offending_token = msg.token_parser.consumed_tokens[msg.token_parser.consumed_tokens.length - 1];
if (offending_token == "") {
offending_token = "(vuoto)";
}
out += msg.token_parser.consumed_tokens.slice(0, -1).join(" ") +`: comando non riconosciuto: ${offending_token}.\n`;
if (this.help_keyword) {
let help_command = msg.token_parser.consumed_tokens.slice(0, -1).concat([this.help_keyword]).join(" ");
out += `Usa '${help_command}' per la guida.\n`;
}
}
return out;
}
this.genera_help = function (root, msg) {
let usages = {};
if (!root) {
for (let wire of root.wires[0]) {
Object.assign(usages, depth_first(RED.nodes.getNode(wire)));
}
} else {
usages = depth_first(root);
}
return format_usage(usages, msg.token_parser.consumed_tokens.slice(0,-1));
};
this.on("input", msg => {
RED.util.evaluateNodeProperty(this.property, "msg", this, msg,
(err, value) => {
if (err) {
this.error(`Can't evaluate msg.${this.property}`);
} else {
let tokens = value.trim().toLowerCase().split(" ");
msg.regex_matches = {};
msg.token_parser = {
new_tokens: tokens,
consumed_tokens: [],
help_keyword: this.help_keyword,
on_error: (msg, maybe_error) => {
let err = maybe_error ? maybe_error : this.genera_errore(msg);
this.send([undefined, err]);
},
on_help: (help_node, msg) => {
let err = this.genera_help(help_node, msg);
this.send([undefined, err]);
}
};
this.send([msg, undefined]);
};
});
});
}
RED.nodes.registerType("parser-entry-point", ParserEntryPoint);
function ConsumaToken(n) {
RED.nodes.createNode(this, n);
this.rules = n.rules;
this.behavior = n.behavior;
this.checkall = n.checkall;
function check_rule(r, token) {
switch (r.t) {
case "eq":
return token == r.v.toLowerCase();
case "regex":
let reg = new RegExp(r.v);
return token.match(reg);
}
}
this.on("input", msg => {
let token = msg.token_parser.new_tokens.shift() || "";
msg.token_parser.consumed_tokens.push(token);
if(token == msg.token_parser.help_keyword) {
msg.token_parser.on_help(this, msg);
return;
}
let out = [];
let n_matches = 0;
for (let r of this.rules) {
let matches = check_rule(r, token);
if (matches === true || (matches != null && matches.length && matches.length > 0)) {
if (matches.length > 0) {
msg.regex_matches[r.match_name] = matches;
}
out.push(msg);
n_matches += 1;
if (!this.checkall) {
break;
}
} else {
out.push(undefined);
}
}
if (n_matches == 0) {
msg.token_parser.on_error(msg);
return;
}
this.send(out);
});
}
RED.nodes.registerType("parser-consume", ConsumaToken);
}