diff --git a/.travis.yml b/.travis.yml index 328a85ef7..054edefba 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,7 @@ matrix: include: - node_js: "10" script: - - istanbul cover ./node_modules/.bin/grunt --report lcovonly && istanbul report text && ( cat coverage/lcov.info | $(npm get prefix)/bin/coveralls || true ) && rm -rf coverage + - ./node_modules/.bin/grunt && istanbul report text && ( cat coverage/lcov.info | $(npm get prefix)/bin/coveralls || true ) && rm -rf coverage before_script: - npm install -g istanbul coveralls - node_js: "8" diff --git a/CHANGELOG.md b/CHANGELOG.md index 1d6cccb65..2a73106c4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,20 @@ +#### 0.18.7: Maintenance Release + +Editor Fixes + + - Do not trim wires if node declares outputs in defaults but misses value Fixes #1737 + +Node Fixes + + - Relax twitter node version ready for major version bump + - Pass Date into the Function node sandbox to fix instanceof tests + - let TCP in node report remote ip and port when in single packet mode + - typo fix in node help (#1735) + +Other Fixes + - Tidy up default grunt task and fixup test break due to reorder Fixes #1738 + - Bump jsonata version + #### 0.18.6: Maintenance Release Editor Fixes diff --git a/Gruntfile.js b/Gruntfile.js index 1c01aa618..fb609c992 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -55,7 +55,7 @@ module.exports = function(grunt) { reportFormats: ['lcov','html'], print: 'both' }, - all: { src: ['test/**/*_spec.js'] }, + all: { src: ["test/_spec.js","test/red/**/*_spec.js","test/nodes/**/*_spec.js"] }, core: { src: ["test/_spec.js","test/red/**/*_spec.js"]}, nodes: { src: ["test/nodes/**/*_spec.js"]} }, @@ -495,7 +495,7 @@ module.exports = function(grunt) { grunt.registerTask('default', 'Builds editor content then runs code style checks and unit tests on all components', - ['build','test-core','test-editor','test-nodes']); + ['build','jshint:editor','mocha_istanbul:all']); grunt.registerTask('test-core', 'Runs code style check and unit tests on core runtime code', diff --git a/editor/js/nodes.js b/editor/js/nodes.js index 0a2fe7268..433e400a2 100644 --- a/editor/js/nodes.js +++ b/editor/js/nodes.js @@ -1033,15 +1033,31 @@ RED.nodes = (function() { node.type = "unknown"; } if (node._def.category != "config") { - node.inputs = n.inputs||node._def.inputs; - node.outputs = n.outputs||node._def.outputs; - // If 'wires' is longer than outputs, clip wires + if (n.hasOwnProperty('inputs')) { + node.inputs = n.inputs; + node._config.inputs = JSON.stringify(n.inputs); + } else { + node.inputs = node._def.inputs; + } + if (n.hasOwnProperty('outputs')) { + node.outputs = n.outputs; + node._config.outputs = JSON.stringify(n.outputs); + } else { + node.outputs = node._def.outputs; + } if (node.hasOwnProperty('wires') && node.wires.length > node.outputs) { - console.log("Warning: node.wires longer than node.outputs - trimming wires:",node.id," wires:",node.wires.length," outputs:",node.outputs); - node.wires = node.wires.slice(0,node.outputs); + if (!node._def.defaults.hasOwnProperty("outputs") || !isNaN(parseInt(n.outputs))) { + // If 'wires' is longer than outputs, clip wires + console.log("Warning: node.wires longer than node.outputs - trimming wires:",node.id," wires:",node.wires.length," outputs:",node.outputs); + node.wires = node.wires.slice(0,node.outputs); + } else { + // The node declares outputs in its defaults, but has not got a valid value + // Defer to the length of the wires array + node.outputs = node.wires.length; + } } for (d in node._def.defaults) { - if (node._def.defaults.hasOwnProperty(d)) { + if (node._def.defaults.hasOwnProperty(d) && d !== 'inputs' && d !== 'outputs') { node[d] = n[d]; node._config[d] = JSON.stringify(n[d]); } diff --git a/editor/js/red.js b/editor/js/red.js index fa6f62083..8acf93d67 100644 --- a/editor/js/red.js +++ b/editor/js/red.js @@ -176,13 +176,13 @@ var RED = (function() { loadFlows(function() { var project = RED.projects.getActiveProject(); var message = { - "change-branch":"Change to local branch '"+project.git.branches.local+"'", - "merge-abort":"Git merge aborted", - "loaded":"Project '"+msg.project+"' loaded", - "updated":"Project '"+msg.project+"' updated", - "pull":"Project '"+msg.project+"' reloaded", - "revert": "Project '"+msg.project+"' reloaded", - "merge-complete":"Git merge completed" + "change-branch": RED._("notification.project.change-branch", {project: project.git.branches.local}), + "merge-abort": RED._("notification.project.merge-abort"), + "loaded": RED._("notification.project.loaded", {project: msg.project}), + "updated": RED._("notification.project.updated", {project: msg.project}), + "pull": RED._("notification.project.pull", {project: msg.project}), + "revert": RED._("notification.project.revert", {project: msg.project}), + "merge-complete": RED._("notification.project.merge-complete") }[msg.action]; RED.notify("
"+message+"
"); RED.sidebar.info.refresh() @@ -206,7 +206,7 @@ var RED = (function() { if (!!RED.projects.getActiveProject()) { options.buttons = [ { - text: "Manage project dependencies", + text: RED._("notification.label.manage-project-dep"), click: function() { persistentNotifications[notificationId].hideNotification(); RED.projects.settings.show('deps'); @@ -217,7 +217,7 @@ var RED = (function() { } else { options.buttons = [ { - text: "Close", + text: RED._("common.label.close"), click: function() { persistentNotifications[notificationId].hideNotification(); } diff --git a/editor/js/ui/diff.js b/editor/js/ui/diff.js index 4a305eb6c..eb822df1e 100644 --- a/editor/js/ui/diff.js +++ b/editor/js/ui/diff.js @@ -1233,7 +1233,7 @@ RED.diff = (function() { // currentDiff = diff; var trayOptions = { - title: options.title||"Review Changes", //TODO: nls + title: options.title||RED._("diff.reviewChanges"), width: Infinity, overlay: true, buttons: [ @@ -1416,7 +1416,7 @@ RED.diff = (function() { function showTextDiff(textA,textB) { var trayOptions = { - title: "Compare Changes", //TODO: nls + title: RED._("diff.compareChanges"), width: Infinity, overlay: true, buttons: [ @@ -1747,7 +1747,7 @@ RED.diff = (function() { try { commonFlow = JSON.parse(commonVersion.content||"[]"); } catch(err) { - console.log("Common Version doesn't contain valid JSON:",commonVersionUrl); + console.log(RED._("diff.commonVersionError"),commonVersionUrl); console.log(err); return; } @@ -1755,7 +1755,7 @@ RED.diff = (function() { try { oldFlow = JSON.parse(oldVersion.content||"[]"); } catch(err) { - console.log("Old Version doesn't contain valid JSON:",oldVersionUrl); + console.log(RED._("diff.oldVersionError"),oldVersionUrl); console.log(err); return; } @@ -1765,7 +1765,7 @@ RED.diff = (function() { try { newFlow = JSON.parse(newVersion.content||"[]"); } catch(err) { - console.log("New Version doesn't contain valid JSON:",newFlow); + console.log(RED._("diff.newVersionError"),newFlow); console.log(err); return; } @@ -1797,11 +1797,11 @@ RED.diff = (function() { if (isBinary) { var diffBinaryRow = $('You Git client is not configured with a username/email.
",{ + notification = RED.notify(""+RED._("projects.errors.no-username-email")+"
",{ fixed: true, type:'error', buttons: [ { - text: "Cancel", + text: RED._("common.label.cancel"), click: function() { notification.close(); } }, { - text: "Configure Git client", + text: RED._("projects.config-git"), click: function() { RED.userSettings.show('gitconfig'); notification.close(); @@ -43,13 +43,13 @@ RED.projects = (function() { }) } else { console.log(error); - notification = RED.notify("An unexpected error occurred:
"+error.message+"
code: "+error.error+"",{ + notification = RED.notify(""+RED._("projects.errors.unexpected")+":
"+error.message+"
"+RED._("projects.errors.code")+": "+error.error+"",{ fixed: true, modal: true, type: 'error', buttons: [ { - text: "Close", + text: RED._("common.label.close"), click: function() { notification.close(); } @@ -75,14 +75,14 @@ RED.projects = (function() { migrateProjectHeader.appendTo(container); var body = $('').appendTo(container); - $('').text("Hello! We have introduced 'projects' to Node-RED.").appendTo(body); - $('
').text("This is a new way for you to manage your flow files and includes version control of your flows.").appendTo(body); - $('
').text("To get started you can create your first project or clone an existing project from a git repository.").appendTo(body); - $('
').text("If you are not sure, you can skip this for now. You will still be able to create your first project from the 'Projects' menu at any time.").appendTo(body); + $('
').text(RED._("projects.welcome.hello")).appendTo(body); + $('
').text(RED._("projects.welcome.desc0")).appendTo(body); + $('
').text(RED._("projects.welcome.desc1")).appendTo(body); + $('
').text(RED._("projects.welcome.desc2")).appendTo(body); var row = $('
').appendTo(body); - var createAsEmpty = $('').appendTo(row); - var createAsClone = $('').appendTo(row); + var createAsEmpty = $('').appendTo(row); + var createAsClone = $('').appendTo(row); createAsEmpty.click(function(e) { e.preventDefault(); @@ -105,7 +105,7 @@ RED.projects = (function() { buttons: [ { // id: "clipboard-dialog-cancel", - text: "Not right now", + text: RED._("projects.welcome.not-right-now"), click: function() { createProjectOptions = {}; $( this ).dialog( "close" ); @@ -139,23 +139,23 @@ RED.projects = (function() { migrateProjectHeader.appendTo(container); var body = $('').appendTo(container); - $('').text("Setup your version control client").appendTo(body); - $('
').text("Node-RED uses the open source tool Git for version control. It tracks changes to your project files and lets you push them to remote repositories.").appendTo(body); - $('
').text("When you commit a set of changes, Git records who made the changes with a username and email address. The Username can be anything you want - it does not need to be your real name.").appendTo(body); + $('
').text(RED._("projects.git-config.setup")).appendTo(body); + $('
').text(RED._("projects.git-config.desc0")).appendTo(body); + $('
').text(RED._("projects.git-config.desc1")).appendTo(body); if (isGlobalConfig) { - $('
').text("Your Git client is already configured with the details below.").appendTo(body); + $('
').text(RED._("projects.git-config.desc2")).appendTo(body); } - $('
').text("You can change these settings later under the 'Git config' tab of the settings dialog.").appendTo(body); + $('
').text(RED._("projects.git-config.desc3")).appendTo(body); var row = $('
').appendTo(body); - $('').appendTo(row); + $('').appendTo(row); gitUsernameInput = $('').val((existingGitSettings&&existingGitSettings.name)||"").appendTo(row); // $('').text("This does not need to be your real name").appendTo(row); gitUsernameInput.on("change keyup paste",validateForm); row = $('').appendTo(body); - $('').appendTo(row); + $('').appendTo(row); gitEmailInput = $('').val((existingGitSettings&&existingGitSettings.email)||"").appendTo(row); gitEmailInput.on("change keyup paste",validateForm); // $('').text("Something something email").appendTo(row); @@ -168,14 +168,14 @@ RED.projects = (function() { buttons: [ { // id: "clipboard-dialog-cancel", - text: "Back", + text: RED._("common.label.back"), click: function() { show('welcome'); } }, { id: "projects-dialog-git-config", - text: "Next", // TODO: nls + text: RED._("common.label.next"), class: "primary", click: function() { var currentGitSettings = RED.settings.get('git') || {}; @@ -216,10 +216,10 @@ RED.projects = (function() { migrateProjectHeader.appendTo(container); var body = $('').appendTo(container); - $('').text("Create your project").appendTo(body); - $('
').text("A project is maintained as a Git repository. It makes it much easier to share your flows with others and to collaborate on them.").appendTo(body); - $('
').text("You can create multiple projects and quickly switch between them from the editor.").appendTo(body); - $('
').text("To begin, your project needs a name and an optional description.").appendTo(body); + $('
').text(RED._("projects.project-details.create")).appendTo(body); + $('
').text(RED._("projects.project-details.desc0")).appendTo(body); + $('
').text(RED._("projects.project-details.desc1")).appendTo(body); + $('
').text(RED._("projects.project-details.desc2")).appendTo(body); var validateForm = function() { var projectName = projectNameInput.val(); @@ -236,14 +236,14 @@ RED.projects = (function() { projectNameValid = false; valid = false; if (projectList[projectName]) { - projectNameSublabel.text("Project already exists"); + projectNameSublabel.text(RED._("projects.project-details.already-exists")); } else { - projectNameSublabel.text("Must contain only A-Z 0-9 _ -"); + projectNameSublabel.text(RED._("projects.project-details.must-contain")); } } else { projectNameInput.removeClass("input-error"); $('').appendTo(projectNameStatus); - projectNameSublabel.text("Must contain only A-Z 0-9 _ -"); + projectNameSublabel.text(RED._("projects.project-details.must-contain")); projectNameValid = true; } projectNameLastChecked = projectName; @@ -253,7 +253,7 @@ RED.projects = (function() { } var row = $('
').appendTo(body); - $('').appendTo(row); + $('').appendTo(row); var subrow = $('').appendTo(row); projectNameInput = $('').val(createProjectOptions.name||"").appendTo(subrow); @@ -283,13 +283,13 @@ RED.projects = (function() { checkProjectName = null; },300) }); - projectNameSublabel = $('').appendTo(row).find("small"); + projectNameSublabel = $('').appendTo(row).find("small"); // Empty Project row = $('').appendTo(body); - $('').appendTo(row); + $('').appendTo(row); projectSummaryInput = $('').val(createProjectOptions.summary||"").appendTo(row); - $('').appendTo(row); + $('').appendTo(row); setTimeout(function() { projectNameInput.focus(); @@ -300,7 +300,7 @@ RED.projects = (function() { buttons: function(options) { return [ { - text: "Back", + text: RED._("common.label.back"), click: function() { show('git-config'); } @@ -308,7 +308,7 @@ RED.projects = (function() { { id: "projects-dialog-create-name", disabled: true, - text: "Next", // TODO: nls + text: RED._("common.label.next"), class: "primary disabled", click: function() { createProjectOptions.name = projectNameInput.val(); @@ -344,8 +344,8 @@ RED.projects = (function() { var container = $(''); migrateProjectHeader.appendTo(container); var body = $('').appendTo(container); - $('').text("Clone a project").appendTo(body); - $('
').text("If you already have a git repository containing a project, you can clone it to get started.").appendTo(body); + $('
').text(RED._("projects.clone-project.clone")).appendTo(body); + $('
').text(RED._("projects.clone-project.desc0")).appendTo(body); var projectList = null; var pendingFormValidation = false; @@ -376,14 +376,14 @@ RED.projects = (function() { projectNameValid = false; valid = false; if (projectList[projectName]) { - projectNameSublabel.text("Project already exists"); + projectNameSublabel.text(RED._("projects.clone-project.already-exists")); } else { - projectNameSublabel.text("Must contain only A-Z 0-9 _ -"); + projectNameSublabel.text(RED._("projects.clone-project.must-contain")); } } else { projectNameInput.removeClass("input-error"); $('').appendTo(projectNameStatus); - projectNameSublabel.text("Must contain only A-Z 0-9 _ -"); + projectNameSublabel.text(RED._("projects.clone-project.must-contain")); projectNameValid = true; } projectNameLastChecked = projectName; @@ -395,7 +395,7 @@ RED.projects = (function() { // var validRepo = /^(?:file|git|ssh|https?|[\d\w\.\-_]+@[\w\.]+):(?:\/\/)?[\w\.@:\/~_-]+(?:\/?|\#[\d\w\.\-_]+?)$/.test(repo); var validRepo = repo.length > 0 && !/\s/.test(repo); if (/^https?:\/\/[^/]+@/i.test(repo)) { - $("#projects-dialog-screen-create-project-repo-label small").text("Do not include the username/password in the url"); + $("#projects-dialog-screen-create-project-repo-label small").text(RED._("projects.clone-project.no-info-in-url")); validRepo = false; } if (!validRepo) { @@ -426,7 +426,7 @@ RED.projects = (function() { var row; row = $('
').appendTo(body); - $('').appendTo(row); + $('').appendTo(row); var subrow = $('').appendTo(row); projectNameInput = $('').appendTo(subrow); @@ -456,19 +456,19 @@ RED.projects = (function() { checkProjectName = null; },300) }); - projectNameSublabel = $('').appendTo(row).find("small"); + projectNameSublabel = $('').appendTo(row).find("small"); row = $('').appendTo(body); - $('').appendTo(row); + $('').appendTo(row); projectRepoInput = $('').appendTo(row); - $('').appendTo(row); + $('').appendTo(row); var projectRepoChanged = false; var lastProjectRepo = ""; projectRepoInput.on("change keyup paste",function() { projectRepoChanged = true; var repo = $(this).val(); if (lastProjectRepo !== repo) { - $("#projects-dialog-screen-create-project-repo-label small").text("https://, ssh:// or file://"); + $("#projects-dialog-screen-create-project-repo-label small").text(RED._("projects.clone-project.protocols")); } lastProjectRepo = repo; @@ -486,24 +486,24 @@ RED.projects = (function() { var cloneAuthRows = $('').appendTo(body); row = $('').hide().appendTo(cloneAuthRows); - $('