1
0
mirror of https://github.com/node-red/node-red.git synced 2023-10-10 13:36:53 +02:00

Merge pull request #3205 from node-red/dev

Node-RED 2.1.0
This commit is contained in:
Nick O'Leary 2021-10-21 09:13:09 +01:00 committed by GitHub
commit fa51b06c46
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
196 changed files with 25299 additions and 4511 deletions

View File

@ -1,3 +1,93 @@
#### 2.1.0: Milestone Release
Editor
- Position popover properly on a scrolled page
- Fixes from 2.1.0-beta.2 (#3202) @knolleary
Nodes
- Link Out: Fix saving link out node links (#3201) @knolleary
- Switch: Refix #3170 - copy switch rule type when adding new rule
- TCP Request: Add string option to TCP request node output (#3204) @dceejay
#### 2.1.0-beta.2: Beta Release
Editor
- Fix switching projects (#3199) @knolleary
- Use locale setting when installing/enabling node (#3198) @knolleary
- Do not show projects-wecome dialog until welcome tour completes (#3197) @knolleary
- Fix converting selection to subflow (#3196) @knolleary
- Avoid conflicts with native browser cmd-ctrl type shortcuts (#3195) @knolleary
- Ensure message tools stay attached to top-level entry in Debug/Context (#3186) @knolleary
- Ensure tab state updates properly when toggling enable state (#3175) @knolleary
- Improve handling of long labels in TreeList (#3176) @knolleary
- Shift-click tab scroll arrows to jump to start/end (#3177) @knolleary
Runtime
- Update package dependencies
- Update to latest node-red-admin
Nodes
- Dynamic MQTT connections (#3189)
- Link: Filter out Link Out Return nodes in Link In edit dialog Fixes #3187
- Link: Fix link call label (#3200) @knolleary
- Debug: Redesign debug filter options and make them persistant (#3183) @knolleary
- Inject: Widen Inject interval box for >1 digit (#3184) @knolleary
- Switch: Fix rule focus when switch 'otherwise' rule is used (#3185) @knolleary
#### 2.1.0-beta.1: Beta Release
Editor
- Add Tour Guide component (#3136) @knolleary
- Allow tabs to be hidden (#3120) @knolleary
- Add align actions to editor (#3110) @knolleary
- Add support of environment variable for tab & group (#3112) @HiroyasuNishiyama
- Add autoComplete widget and add to TypedInput for msg. props (#3171) @knolleary
- Render node documentation to node-red style guide when written in markdown. (#3169) @Steve-Mcl
- Allow colouring of tab icon svg (#3140) @harmonic7
- Restore tab selection after merging conflicts (#3151) @GerwinvBeek
- Fix serving of theme files on Windows (#3154) @knolleary
- Ensure config-node select inherits width properly from input (#3155) @knolleary
- Do better remembering TypedInput values whilst switching types (#3159) @knolleary
- Update monaco to 0.28.1 (#3153) @knolleary
- Improve themeing of tourGuide (#3161) @knolleary
- Allow a node to specify a filter for the config nodes it can pick from (#3160) @knolleary
- Allow RED.notify.update to modify any notification setting (#3163) @knolleary
- Fix typo in ko editor.json Fixes #3119
- Improve RED.actions api to ensure actions cannot be overridden
- Ensure treeList row has suitable min-height when no content Fixes #3109
- Refactor edit dialogs to use separate edit panes
- Ensure type select button is not focussable when TypedInput only has one type
- Place close tab link in front of fade
Runtime
- Improve error reporting with oauth login strategies (#3148) @knolleary
- Add allowUpdate feature to externalModules.palette (#3143) @knolleary
- Improve node install error reporting (#3158) @knolleary
- Improve unit test coverage (#3168) @knolleary
- Allow coreNodesDir to be set to false (#3149) @hardillb
- Update package dependencies
- uncaughtException debug improvements (#3146) @renatojuniorrs
Nodes
- Change: Add option to deep-clone properties in Change node (#3156) @knolleary
- Delay: Add push to front of rate limit queue. (#3069) @dceejay
- File: Add paletteLabel to file nodes to make read/write more obvious (#3157) @knolleary
- HTTP Request: Extend HTTP request node to log detailed timing information (#3116) @k-toumura
- HTTP Response: Fix sizing of HTTP Response header fields (#3164) @knolleary
- Join: Support for msg.restartTimeout (#3121) @magma1447
- Link Call: Add Link Call node (#3152) @knolleary
- Switch: Copy previous rule type when adding rule to switch node (#3170) @knolleary
- Delay node: add option to send intermediate messages on separate output (#3166) @knolleary
- Typo in http request set method translation (#3173) @mailsvb
#### 2.0.6: Maintenance Release #### 2.0.6: Maintenance Release
Editor Editor

View File

@ -162,7 +162,7 @@ module.exports = function(grunt) {
"packages/node_modules/@node-red/editor-client/src/js/ui/common/stack.js", "packages/node_modules/@node-red/editor-client/src/js/ui/common/stack.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/common/typedInput.js", "packages/node_modules/@node-red/editor-client/src/js/ui/common/typedInput.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/common/toggleButton.js", "packages/node_modules/@node-red/editor-client/src/js/ui/common/toggleButton.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/common/colorPicker.js", "packages/node_modules/@node-red/editor-client/src/js/ui/common/autoComplete.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/actions.js", "packages/node_modules/@node-red/editor-client/src/js/ui/actions.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/deploy.js", "packages/node_modules/@node-red/editor-client/src/js/ui/deploy.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/diff.js", "packages/node_modules/@node-red/editor-client/src/js/ui/diff.js",
@ -182,6 +182,7 @@ module.exports = function(grunt) {
"packages/node_modules/@node-red/editor-client/src/js/ui/tab-context.js", "packages/node_modules/@node-red/editor-client/src/js/ui/tab-context.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/palette-editor.js", "packages/node_modules/@node-red/editor-client/src/js/ui/palette-editor.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/editor.js", "packages/node_modules/@node-red/editor-client/src/js/ui/editor.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/editors/panes/*.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/editors/*.js", "packages/node_modules/@node-red/editor-client/src/js/ui/editors/*.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/editors/code-editors/*.js", "packages/node_modules/@node-red/editor-client/src/js/ui/editors/code-editors/*.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/event-log.js", "packages/node_modules/@node-red/editor-client/src/js/ui/event-log.js",
@ -199,7 +200,8 @@ module.exports = function(grunt) {
"packages/node_modules/@node-red/editor-client/src/js/ui/projects/projectSettings.js", "packages/node_modules/@node-red/editor-client/src/js/ui/projects/projectSettings.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/projects/projectUserSettings.js", "packages/node_modules/@node-red/editor-client/src/js/ui/projects/projectUserSettings.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/projects/tab-versionControl.js", "packages/node_modules/@node-red/editor-client/src/js/ui/projects/tab-versionControl.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/touch/radialMenu.js" "packages/node_modules/@node-red/editor-client/src/js/ui/touch/radialMenu.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/tour/*.js"
], ],
dest: "packages/node_modules/@node-red/editor-client/public/red/red.js" dest: "packages/node_modules/@node-red/editor-client/public/red/red.js"
}, },
@ -326,6 +328,12 @@ module.exports = function(grunt) {
], ],
tasks: ['jsonlint:keymaps','copy:build'] tasks: ['jsonlint:keymaps','copy:build']
}, },
tours: {
files: [
'packages/node_modules/@node-red/editor-client/src/tours/**/*.js'
],
tasks: ['copy:build']
},
misc: { misc: {
files: [ files: [
'CHANGELOG.md' 'CHANGELOG.md'
@ -423,6 +431,12 @@ module.exports = function(grunt) {
src: '**', src: '**',
expand: true, expand: true,
dest: 'packages/node_modules/@node-red/editor-client/public/vendor/ace/' dest: 'packages/node_modules/@node-red/editor-client/public/vendor/ace/'
},
{
cwd: 'packages/node_modules/@node-red/editor-client/src/tours',
src: '**',
expand: true,
dest: 'packages/node_modules/@node-red/editor-client/public/red/tours/'
} }
] ]
} }

View File

@ -1,6 +1,6 @@
{ {
"name": "node-red", "name": "node-red",
"version": "2.0.6", "version": "2.1.0",
"description": "Low-code programming for event-driven applications", "description": "Low-code programming for event-driven applications",
"homepage": "http://nodered.org", "homepage": "http://nodered.org",
"license": "Apache-2.0", "license": "Apache-2.0",
@ -26,9 +26,9 @@
} }
], ],
"dependencies": { "dependencies": {
"acorn": "8.4.1", "acorn": "8.5.0",
"acorn-walk": "8.1.1", "acorn-walk": "8.2.0",
"ajv": "8.6.2", "ajv": "8.6.3",
"async-mutex": "0.3.2", "async-mutex": "0.3.2",
"basic-auth": "2.0.1", "basic-auth": "2.0.1",
"bcryptjs": "2.4.3", "bcryptjs": "2.4.3",
@ -40,7 +40,7 @@
"cookie-parser": "1.4.5", "cookie-parser": "1.4.5",
"cors": "2.8.5", "cors": "2.8.5",
"cronosjs": "1.7.1", "cronosjs": "1.7.1",
"denque": "1.5.0", "denque": "2.0.1",
"express": "4.17.1", "express": "4.17.1",
"express-session": "1.17.2", "express-session": "1.17.2",
"form-data": "4.0.0", "form-data": "4.0.0",
@ -48,9 +48,9 @@
"fs.notify": "0.0.4", "fs.notify": "0.0.4",
"got": "11.8.2", "got": "11.8.2",
"hash-sum": "2.0.0", "hash-sum": "2.0.0",
"hpagent": "^0.1.2", "hpagent": "0.1.2",
"https-proxy-agent": "5.0.0", "https-proxy-agent": "5.0.0",
"i18next": "20.3.2", "i18next": "21.3.1",
"iconv-lite": "0.6.3", "iconv-lite": "0.6.3",
"is-utf8": "0.2.1", "is-utf8": "0.2.1",
"js-yaml": "3.14.1", "js-yaml": "3.14.1",
@ -64,18 +64,18 @@
"mqtt": "4.2.8", "mqtt": "4.2.8",
"multer": "1.4.3", "multer": "1.4.3",
"mustache": "4.2.0", "mustache": "4.2.0",
"node-red-admin": "^2.2.0", "node-red-admin": "^2.2.1",
"nopt": "5.0.0", "nopt": "5.0.0",
"oauth2orize": "1.11.0", "oauth2orize": "1.11.0",
"on-headers": "1.0.2", "on-headers": "1.0.2",
"passport": "0.4.1", "passport": "0.5.0",
"passport-http-bearer": "1.0.1", "passport-http-bearer": "1.0.1",
"passport-oauth2-client-password": "0.1.2", "passport-oauth2-client-password": "0.1.2",
"raw-body": "2.4.1", "raw-body": "2.4.1",
"semver": "7.3.5", "semver": "7.3.5",
"tar": "6.1.11", "tar": "6.1.11",
"tough-cookie": "4.0.0", "tough-cookie": "4.0.0",
"uglify-js": "3.14.1", "uglify-js": "3.14.2",
"uuid": "8.3.2", "uuid": "8.3.2",
"ws": "7.5.1", "ws": "7.5.1",
"xml2js": "0.4.23" "xml2js": "0.4.23"
@ -84,7 +84,7 @@
"bcrypt": "5.0.1" "bcrypt": "5.0.1"
}, },
"devDependencies": { "devDependencies": {
"dompurify": "2.3.1", "dompurify": "2.3.3",
"grunt": "1.4.1", "grunt": "1.4.1",
"grunt-chmod": "~1.1.1", "grunt-chmod": "~1.1.1",
"grunt-cli": "~1.4.3", "grunt-cli": "~1.4.3",
@ -93,7 +93,7 @@
"grunt-contrib-compress": "2.0.0", "grunt-contrib-compress": "2.0.0",
"grunt-contrib-concat": "~1.0.1", "grunt-contrib-concat": "~1.0.1",
"grunt-contrib-copy": "~1.0.0", "grunt-contrib-copy": "~1.0.0",
"grunt-contrib-jshint": "3.0.0", "grunt-contrib-jshint": "3.1.1",
"grunt-contrib-uglify": "5.0.1", "grunt-contrib-uglify": "5.0.1",
"grunt-contrib-watch": "~1.1.0", "grunt-contrib-watch": "~1.1.0",
"grunt-jsdoc": "2.4.1", "grunt-jsdoc": "2.4.1",
@ -104,16 +104,16 @@
"grunt-sass": "~3.1.0", "grunt-sass": "~3.1.0",
"grunt-simple-mocha": "~0.4.1", "grunt-simple-mocha": "~0.4.1",
"grunt-simple-nyc": "^3.0.1", "grunt-simple-nyc": "^3.0.1",
"i18next-http-backend": "1.2.6", "i18next-http-backend": "1.3.1",
"jquery-i18next": "1.2.1", "jquery-i18next": "1.2.1",
"jsdoc-nr-template": "github:node-red/jsdoc-nr-template", "jsdoc-nr-template": "github:node-red/jsdoc-nr-template",
"marked": "2.1.3", "marked": "3.0.7",
"minami": "1.2.3", "minami": "1.2.3",
"mocha": "9.1.1", "mocha": "9.1.2",
"node-red-node-test-helper": "^0.2.7", "node-red-node-test-helper": "^0.2.7",
"nodemon": "2.0.12", "nodemon": "2.0.13",
"proxy": "^1.0.2", "proxy": "^1.0.2",
"sass": "1.39.0", "sass": "1.43.2",
"should": "13.2.3", "should": "13.2.3",
"sinon": "11.1.2", "sinon": "11.1.2",
"stoppable": "^1.1.0", "stoppable": "^1.1.0",

View File

@ -199,8 +199,12 @@ function genericStrategy(adminApp,strategy) {
passport.use(new strategy.strategy(options, verify)); passport.use(new strategy.strategy(options, verify));
adminApp.get('/auth/strategy', adminApp.get('/auth/strategy',
passport.authenticate(strategy.name, {session:false, failureRedirect: settings.httpAdminRoot }), passport.authenticate(strategy.name, {session:false,
completeGenerateStrategyAuth failureMessage: true,
failureRedirect: settings.httpAdminRoot
}),
completeGenerateStrategyAuth,
handleStrategyError
); );
var callbackMethodFunc = adminApp.get; var callbackMethodFunc = adminApp.get;
@ -208,8 +212,13 @@ function genericStrategy(adminApp,strategy) {
callbackMethodFunc = adminApp.post; callbackMethodFunc = adminApp.post;
} }
callbackMethodFunc.call(adminApp,'/auth/strategy/callback', callbackMethodFunc.call(adminApp,'/auth/strategy/callback',
passport.authenticate(strategy.name, {session:false, failureRedirect: settings.httpAdminRoot }), passport.authenticate(strategy.name, {
completeGenerateStrategyAuth session:false,
failureMessage: true,
failureRedirect: settings.httpAdminRoot
}),
completeGenerateStrategyAuth,
handleStrategyError
); );
} }
@ -219,6 +228,13 @@ function completeGenerateStrategyAuth(req,res) {
// Successful authentication, redirect home. // Successful authentication, redirect home.
res.redirect(settings.httpAdminRoot + '?access_token='+tokens.accessToken); res.redirect(settings.httpAdminRoot + '?access_token='+tokens.accessToken);
} }
function handleStrategyError(err, req, res, next) {
if (res.headersSent) {
return next(err)
}
log.audit({event: "auth.login.fail.oauth",error:err.toString()});
res.redirect(settings.httpAdminRoot + '?session_message='+err.toString());
}
module.exports = { module.exports = {
init: init, init: init,

View File

@ -18,14 +18,6 @@ var apiUtils = require("../util");
var express = require("express"); var express = require("express");
var runtimeAPI; var runtimeAPI;
function getUsername(userObj) {
var username = '__default';
if ( userObj && userObj.name ) {
username = userObj.name;
}
return username;
}
module.exports = { module.exports = {
init: function(_runtimeAPI) { init: function(_runtimeAPI) {
runtimeAPI = _runtimeAPI; runtimeAPI = _runtimeAPI;

View File

@ -24,15 +24,18 @@ var defaultContext = {
page: { page: {
title: "Node-RED", title: "Node-RED",
favicon: "favicon.ico", favicon: "favicon.ico",
tabicon: "red/images/node-red-icon-black.svg" tabicon: {
icon: "red/images/node-red-icon-black.svg",
colour: "#8f0000"
}
}, },
header: { header: {
title: "Node-RED", title: "Node-RED",
image: "red/images/node-red.svg" image: "red/images/node-red.svg"
}, },
asset: { asset: {
red: (process.env.NODE_ENV == "development")? "red/red.js":"red/red.min.js", red: "red/red.min.js",
main: (process.env.NODE_ENV == "development")? "red/main.js":"red/main.min.js", main: "red/main.min.js",
vendorMonaco: "" vendorMonaco: ""
} }
}; };
@ -74,7 +77,7 @@ function serveFilesFromTheme(themeValue, themeApp, directory, baseDirectory) {
let fullPath = array[i]; let fullPath = array[i];
if (baseDirectory) { if (baseDirectory) {
fullPath = path.resolve(baseDirectory,array[i]); fullPath = path.resolve(baseDirectory,array[i]);
if (fullPath.indexOf(baseDirectory) !== 0) { if (fullPath.indexOf(path.resolve(baseDirectory)) !== 0) {
continue; continue;
} }
} }
@ -91,6 +94,10 @@ module.exports = {
init: function(settings, _runtimeAPI) { init: function(settings, _runtimeAPI) {
runtimeAPI = _runtimeAPI; runtimeAPI = _runtimeAPI;
themeContext = clone(defaultContext); themeContext = clone(defaultContext);
if (process.env.NODE_ENV == "development") {
themeContext.asset.red = "red/red.js";
themeContext.asset.main = "red/main.js";
}
themeSettings = null; themeSettings = null;
theme = settings.editorTheme || {}; theme = settings.editorTheme || {};
themeContext.asset.vendorMonaco = ((theme.codeEditor || {}).lib === "monaco") ? "vendor/monaco/monaco-bootstrap.js" : ""; themeContext.asset.vendorMonaco = ((theme.codeEditor || {}).lib === "monaco") ? "vendor/monaco/monaco-bootstrap.js" : "";
@ -123,9 +130,13 @@ module.exports = {
} }
if (theme.page.tabicon) { if (theme.page.tabicon) {
url = serveFile(themeApp,"/tabicon/",theme.page.tabicon) let icon = theme.page.tabicon.icon || theme.page.tabicon
url = serveFile(themeApp,"/tabicon/", icon)
if (url) { if (url) {
themeContext.page.tabicon = url; themeContext.page.tabicon.icon = url;
}
if (theme.page.tabicon.colour) {
themeContext.page.tabicon.colour = theme.page.tabicon.colour
} }
} }
@ -246,6 +257,9 @@ module.exports = {
theme.page = theme.page || {_:{}} theme.page = theme.page || {_:{}}
theme.page._.scripts = scriptFiles.concat(theme.page._.scripts || []) theme.page._.scripts = scriptFiles.concat(theme.page._.scripts || [])
} }
if(theme.codeEditor) {
theme.codeEditor.options = Object.assign({}, themePlugin.monacoOptions, theme.codeEditor.options);
}
} }
activeThemeInitialised = true; activeThemeInitialised = true;
} }

View File

@ -91,7 +91,16 @@ module.exports = {
}, },
editor: async function(req,res) { editor: async function(req,res) {
res.send(Mustache.render(editorTemplate,await theme.context()));
let sessionMessages;
if (req.session && req.session.messages) {
sessionMessages = JSON.stringify(req.session.messages);
delete req.session.messages
}
res.send(Mustache.render(editorTemplate,{
sessionMessages,
...await theme.context()
}));
}, },
editorResources: express.static(path.join(editorClientDir,'public')) editorResources: express.static(path.join(editorClientDir,'public'))
}; };

View File

@ -1,6 +1,6 @@
{ {
"name": "@node-red/editor-api", "name": "@node-red/editor-api",
"version": "2.0.6", "version": "2.1.0",
"license": "Apache-2.0", "license": "Apache-2.0",
"main": "./lib/index.js", "main": "./lib/index.js",
"repository": { "repository": {
@ -16,8 +16,8 @@
} }
], ],
"dependencies": { "dependencies": {
"@node-red/util": "2.0.6", "@node-red/util": "2.1.0",
"@node-red/editor-client": "2.0.6", "@node-red/editor-client": "2.1.0",
"bcryptjs": "2.4.3", "bcryptjs": "2.4.3",
"body-parser": "1.19.0", "body-parser": "1.19.0",
"clone": "2.1.2", "clone": "2.1.2",
@ -31,7 +31,7 @@
"oauth2orize": "1.11.0", "oauth2orize": "1.11.0",
"passport-http-bearer": "1.0.1", "passport-http-bearer": "1.0.1",
"passport-oauth2-client-password": "0.1.2", "passport-oauth2-client-password": "0.1.2",
"passport": "0.4.1", "passport": "0.5.0",
"ws": "7.5.1" "ws": "7.5.1"
}, },
"optionalDependencies": { "optionalDependencies": {

View File

@ -53,8 +53,15 @@
"confirmDelete": "Confirm delete", "confirmDelete": "Confirm delete",
"delete": "Are you sure you want to delete '__label__'?", "delete": "Are you sure you want to delete '__label__'?",
"dropFlowHere": "Drop the flow here", "dropFlowHere": "Drop the flow here",
"addFlow": "Add Flow", "addFlow": "Add flow",
"listFlows": "List Flows", "addFlowToRight": "Add flow to the right",
"hideFlow": "Hide flow",
"hideOtherFlows": "Hide other flows",
"showAllFlows": "Show all flows",
"hideAllFlows": "Hide all flows",
"showLastHiddenFlow": "Show last hidden flow",
"listFlows": "List flows",
"listSubflows": "List subflows",
"status": "Status", "status": "Status",
"enabled": "Enabled", "enabled": "Enabled",
"disabled":"Disabled", "disabled":"Disabled",
@ -105,6 +112,7 @@
"editPalette":"Manage palette", "editPalette":"Manage palette",
"other": "Other", "other": "Other",
"showTips": "Show tips", "showTips": "Show tips",
"showWelcomeTours": "Show guided tours for new versions",
"help": "Node-RED website", "help": "Node-RED website",
"projects": "Projects", "projects": "Projects",
"projects-new": "New", "projects-new": "New",
@ -116,7 +124,20 @@
"groupSelection": "Group selection", "groupSelection": "Group selection",
"ungroupSelection": "Ungroup selection", "ungroupSelection": "Ungroup selection",
"groupMergeSelection": "Merge selection", "groupMergeSelection": "Merge selection",
"groupRemoveSelection": "Remove from group" "groupRemoveSelection": "Remove from group",
"arrange":"Arrange",
"alignLeft":"Align to left",
"alignCenter":"Align to center",
"alignRight":"Align to right",
"alignTop":"Align to top",
"alignMiddle":"Align to middle",
"alignBottom":"Align to bottom",
"distributeHorizontally":"Distribute horizontally",
"distributeVertically":"Distribute vertically",
"moveToBack":"Move to back",
"moveToFront":"Move to front",
"moveBackwards":"Move backwards",
"moveForwards":"Move forwards"
} }
}, },
"actions": { "actions": {
@ -450,8 +471,9 @@
"unassigned": "Unassigned", "unassigned": "Unassigned",
"global": "global", "global": "global",
"workspace": "workspace", "workspace": "workspace",
"selectAll": "Select all nodes", "selectAll": "Select all",
"selectAllConnected": "Select all connected nodes", "selectNone": "Select none",
"selectAllConnected": "Select connected",
"addRemoveNode": "Add/remove node from selection", "addRemoveNode": "Add/remove node from selection",
"editSelected": "Edit selected node", "editSelected": "Edit selected node",
"deleteSelected": "Delete selected nodes or link", "deleteSelected": "Delete selected nodes or link",
@ -464,7 +486,10 @@
"copyNode": "Copy selected nodes", "copyNode": "Copy selected nodes",
"cutNode": "Cut selected nodes", "cutNode": "Cut selected nodes",
"pasteNode": "Paste nodes", "pasteNode": "Paste nodes",
"undoChange": "Undo the last change performed", "copyGroupStyle": "Copy group style",
"pasteGroupStyle": "Paste group style",
"undoChange": "Undo",
"redoChange": "Redo",
"searchBox": "Open search box", "searchBox": "Open search box",
"managePalette": "Manage palette", "managePalette": "Manage palette",
"actionList":"Action list" "actionList":"Action list"
@ -519,7 +544,8 @@
"nodeEnabled_plural": "Nodes enabled:", "nodeEnabled_plural": "Nodes enabled:",
"nodeDisabled": "Node disabled:", "nodeDisabled": "Node disabled:",
"nodeDisabled_plural": "Nodes disabled:", "nodeDisabled_plural": "Nodes disabled:",
"nodeUpgraded": "Node module __module__ upgraded to version __version__" "nodeUpgraded": "Node module __module__ upgraded to version __version__",
"unknownNodeRegistered": "Error loading node: <ul><li>__type__<br>__error__</li></ul>"
}, },
"editor": { "editor": {
"title": "Manage palette", "title": "Manage palette",
@ -1108,6 +1134,10 @@
"preview": "UI Preview", "preview": "UI Preview",
"defaultValue": "Default value" "defaultValue": "Default value"
}, },
"tourGuide": {
"start": "Start",
"next": "Next"
},
"languages" : { "languages" : {
"de": "German", "de": "German",
"en-US": "English", "en-US": "English",

View File

@ -1,6 +1,6 @@
{ {
"name": "@node-red/editor-client", "name": "@node-red/editor-client",
"version": "2.0.6", "version": "2.1.0",
"license": "Apache-2.0", "license": "Apache-2.0",
"repository": { "repository": {
"type": "git", "type": "git",

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" height="512" width="512"><g transform="translate(0 -540.36)"><path fill="#8f0000" color="#000" d="M0 540.36h512v392H0z"/><rect ry="0" height="108.23" width="500.23" stroke="#fff" y="938.25" x="5.89" stroke-width="11.77" fill="#fff"/><path style="text-decoration-color:#000;isolation:auto;mix-blend-mode:normal;solid-color:#000;block-progression:tb;text-decoration-line:none;white-space:normal;text-indent:0;text-transform:none;text-decoration-style:solid" d="M122.88 305.82a4.46 4.46 0 0 0-4.38 4.42v.78c-2.23.1-4.04.54-5.33 1.43a10.5 10.5 0 0 0-3.18 3.87c-.71 1.3-1.3 2.41-2.15 3.2-.72.66-1.8 1.12-3.45 1.32a4.37 4.37 0 0 0-4.3-3.95H82.91a4.43 4.43 0 0 0-4.42 4.35v4.24a4.43 4.43 0 0 0 4.42 4.36h17.16a4.4 4.4 0 0 0 4.4-4.36v-1.6c9.72.14 12.46 2.6 15.59 5.33 3 2.62 6.66 5.38 15.43 5.5v.73a4.49 4.49 0 0 0 4.46 4.38h17.09c2.38 0 4.45-2 4.45-4.38v-4.24a4.49 4.49 0 0 0-4.45-4.38h-17.1c-2.38 0-4.45 2-4.45 4.38v.58c-8.1-.06-10.48-2.15-13.5-4.79-2.5-2.19-5.64-4.58-11.94-5.58 1.17-1.18 1.88-2.52 2.51-3.66.68-1.23 1.29-2.2 2.27-2.88.76-.52 1.98-.84 3.66-.94v.55c0 2.39 2 4.34 4.38 4.34h17.24a4.39 4.39 0 0 0 4.38-4.34v-4.24c0-2.38-2-4.42-4.38-4.42zm0 3h17.24c.8 0 1.38.62 1.38 1.42v4.24c0 .81-.57 1.34-1.38 1.34h-17.24c-.8 0-1.38-.53-1.38-1.34v-4.24c0-.8.57-1.42 1.38-1.42zm-39.96 11.02h17.16c.81 0 1.42.6 1.42 1.4v4.24c0 .81-.61 1.41-1.42 1.41H82.92c-.8 0-1.42-.6-1.42-1.4v-4.25c0-.8.61-1.4 1.42-1.4zm57.04 9.98h17.09c.8 0 1.45.57 1.45 1.38v4.17c0 .8-.65 1.45-1.45 1.45h-17.1c-.8 0-1.45-.65-1.45-1.45v-4.17c0-.8.65-1.38 1.46-1.38z" fill="#fff" color="#000" transform="matrix(4 0 0 4 -162 -450.91)"/><g fill="#8f0000"><path d="M91 954.34v8.45l-8 1.45v60.07H69.03l-28.53-47.1-.5.05v37.2l8 1.44v8.41H19v-8.4l7.45-1.45v-50.22L19 962.79v-8.46h21.48l28.37 47.1.15-.04v-37.15l-7-1.45v-8.45h29zM95 997.83q0-11.63 6.49-19.03 6.53-7.45 18.02-7.45 11.53 0 18.02 7.4 6.54 7.4 6.54 19.08v1q0 11.74-6.54 19.14-6.49 7.35-17.93 7.35-11.58 0-18.11-7.35-6.5-7.4-6.5-19.13v-1.01zm14.03 1q0 7.12 2.5 11.45 2.5 4.28 8.08 4.28 5.43 0 7.93-4.33 2.54-4.33 2.54-11.4v-1q0-6.92-2.54-11.3-2.55-4.37-8.03-4.37t-7.98 4.37-2.5 11.3v1zM184.48 1017.96a17.15 17.15 0 0 1-5.82 5.48 15.17 15.17 0 0 1-7.59 1.88c-6.4 0-11.4-2.35-14.95-7.03-3.52-4.67-5.13-10.86-5.13-18.55v-1c0-8.21 1.62-14.83 5.18-19.86 3.56-5.03 8.56-7.54 15-7.54 2.6 0 4.93.57 7.01 1.73a17.94 17.94 0 0 1 5.81 4.8v-18.64l-8-1.45v-8.46h22v65.13l6 1.44v8.43h-18.45l-1.06-6.36zm-19.49-18.22c0 4.55.63 8.14 2.14 10.77 1.54 2.6 4.04 3.9 7.5 3.9 2.05 0 3.83-.43 5.33-1.26 1.5-.83 3.07-2.03 4.03-3.6v-22.06a11.27 11.27 0 0 0-4.03-3.85 9.62 9.62 0 0 0-5.24-1.4c-3.43 0-5.92 1.53-7.5 4.57s-2.23 7.02-2.23 11.92v1.01zM233.7 1025.28c-7.5 0-13.5-2.4-17.98-7.21-4.48-4.81-6.73-10.91-6.73-18.32v-1.92c0-7.72 2.12-14.08 6.35-19.08 4.26-5 9.96-7.46 17.1-7.43 7.03 0 12.47 2.1 16.35 6.33a23.46 23.46 0 0 1 6.2 17.15v7.52h-31.43l-.1.41c.26 3.43 1.4 6.25 3.41 8.46 2.05 2.21 4.83 3.32 8.32 3.32 3.1 0 5.69-.3 7.74-.91 2.05-.64 4.29-1.64 6.73-2.98l3.8 8.65a27.59 27.59 0 0 1-8.37 4.28 35.28 35.28 0 0 1-11.4 1.73zm-1.25-43.16c-2.6 0-4.65.99-6.15 2.98s-2.44 4.6-2.8 7.83l.15.4H241v-1.41c0-2.98-.84-5.35-2.25-7.11-1.37-1.8-3.47-2.7-6.3-2.7zM291.99 1000.32h-27v-11h27zM331.88 954.34c7.95 0 14.18 1.82 18.7 5.47 4.52 3.63 6.4 8.64 6.4 15.05 0 3.52-.57 6.58-2.46 9.18-1.89 2.6-4.66 4.7-8.31 6.3 4.13 1.21 7.1 3.25 8.89 6.1a19.02 19.02 0 0 1 2.89 10.52v3.56c0 1.54.15 2.74.76 3.6.6.84 1.62 1.34 3.03 1.5l1.2.24v8.46h-6.73c-4.58 0-7.8-1.24-9.66-3.7s-2.6-5.66-2.6-9.57v-3.99c0-3.4-1.1-6.05-2.93-7.98-1.8-1.95-4.34-2.98-7.64-3.07H322v18.45l7 1.44v8.42h-29v-8.42l8-1.44v-50.22l-8-1.44v-8.46h31.89zm-9.95 30.85h9.71c3.91 0 6.84-.83 8.8-2.5s2.93-4.07 2.93-7.2c0-3.15-.98-5.65-2.93-7.5-1.92-1.9-4.78-2.84-8.56-2.84h-9.9v20.04zM412.99 993.32h-23v20h22.21l.63-8h10.2v18.99H368v-8.42l8-1.44v-50.22l-8-1.44v-8.47h54.95v19h-10.3l-.63-8H390v17h23v11zM462.48 954.36c8.55 0 15.6 2.71 21.14 8.19 5.55 5.45 8.36 12.42 8.36 20.98v11.58c0 8.59-2.81 15.63-8.36 21.08-5.54 5.41-12.59 8.12-21.14 8.12h-31.5v-8.41l7-1.52v-50.22l-7-1.37v-8.43l7.46-.08 24.04.08zm-10.5 10.76v48.4l9.77.02c5.03.02 8.98-1.7 11.83-5.1 2.85-3.39 4.4-7.8 4.4-13.28v-11.68c0-5.42-1.55-9.84-4.4-13.24-2.85-3.4-6.8-5.1-11.83-5.1l-9.77-.02z"/></g></g></svg>

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@ -558,11 +558,22 @@ RED.history = (function() {
} else if (ev.t == "reorder") { } else if (ev.t == "reorder") {
inverseEv = { inverseEv = {
t: 'reorder', t: 'reorder',
order: RED.nodes.getWorkspaceOrder(),
dirty: RED.nodes.dirty() dirty: RED.nodes.dirty()
}; };
if (ev.order) { if (ev.workspaces) {
RED.workspaces.order(ev.order); inverseEv.workspaces = {
from: ev.workspaces.to,
to: ev.workspaces.from
}
RED.workspaces.order(ev.workspaces.from);
}
if (ev.nodes) {
inverseEv.nodes = {
z: ev.nodes.z,
from: ev.nodes.to,
to: ev.nodes.from
}
RED.nodes.setNodeOrder(ev.nodes.z,ev.nodes.from);
} }
} else if (ev.t == "createGroup") { } else if (ev.t == "createGroup") {
inverseEv = { inverseEv = {
@ -658,6 +669,8 @@ RED.history = (function() {
push: function(ev) { push: function(ev) {
undoHistory.push(ev); undoHistory.push(ev);
redoHistory = []; redoHistory = [];
RED.menu.setDisabled("menu-item-edit-undo", false);
RED.menu.setDisabled("menu-item-edit-redo", true);
}, },
pop: function() { pop: function() {
var ev = undoHistory.pop(); var ev = undoHistory.pop();
@ -665,6 +678,8 @@ RED.history = (function() {
if (rev) { if (rev) {
redoHistory.push(rev); redoHistory.push(rev);
} }
RED.menu.setDisabled("menu-item-edit-undo", undoHistory.length === 0);
RED.menu.setDisabled("menu-item-edit-redo", redoHistory.length === 0);
}, },
peek: function() { peek: function() {
return undoHistory[undoHistory.length-1]; return undoHistory[undoHistory.length-1];
@ -672,6 +687,8 @@ RED.history = (function() {
clear: function() { clear: function() {
undoHistory = []; undoHistory = [];
redoHistory = []; redoHistory = [];
RED.menu.setDisabled("menu-item-edit-undo", true);
RED.menu.setDisabled("menu-item-edit-redo", true);
}, },
redo: function() { redo: function() {
var ev = redoHistory.pop(); var ev = redoHistory.pop();
@ -681,6 +698,8 @@ RED.history = (function() {
undoHistory.push(uev); undoHistory.push(uev);
} }
} }
RED.menu.setDisabled("menu-item-edit-undo", undoHistory.length === 0);
RED.menu.setDisabled("menu-item-edit-redo", redoHistory.length === 0);
} }
} }

View File

@ -27,6 +27,7 @@ RED.i18n = (function() {
apiRootUrl = options.apiRootUrl||""; apiRootUrl = options.apiRootUrl||"";
var preferredLanguage = localStorage.getItem("editor-language") || detectLanguage(); var preferredLanguage = localStorage.getItem("editor-language") || detectLanguage();
var opts = { var opts = {
compatibilityJSON: 'v3',
backend: { backend: {
loadPath: apiRootUrl+'locales/__ns__?lng=__lng__', loadPath: apiRootUrl+'locales/__ns__?lng=__lng__',
}, },

View File

@ -25,7 +25,9 @@
"ctrl-alt-o": "core:open-project", "ctrl-alt-o": "core:open-project",
"ctrl-g v": "core:show-version-control-tab", "ctrl-g v": "core:show-version-control-tab",
"ctrl-shift-l": "core:show-event-log", "ctrl-shift-l": "core:show-event-log",
"ctrl-shift-p":"core:show-action-list" "ctrl-shift-p":"core:show-action-list",
"alt-w": "core:hide-flow",
"alt-shift-w": "core:show-last-hidden-flow"
}, },
"red-ui-sidebar-node-config": { "red-ui-sidebar-node-config": {
"backspace": "core:delete-config-selection", "backspace": "core:delete-config-selection",
@ -77,6 +79,15 @@
"right": "core:go-to-nearest-node-on-right", "right": "core:go-to-nearest-node-on-right",
"left": "core:go-to-nearest-node-on-left", "left": "core:go-to-nearest-node-on-left",
"up": "core:go-to-nearest-node-above", "up": "core:go-to-nearest-node-above",
"down": "core:go-to-nearest-node-below" "down": "core:go-to-nearest-node-below",
"alt-a g": "core:align-selection-to-grid",
"alt-a l": "core:align-selection-to-left",
"alt-a r": "core:align-selection-to-right",
"alt-a t": "core:align-selection-to-top",
"alt-a b": "core:align-selection-to-bottom",
"alt-a m": "core:align-selection-to-middle",
"alt-a c": "core:align-selection-to-center",
"alt-a h": "core:distribute-selection-horizontally",
"alt-a v": "core:distribute-selection-vertically"
} }
} }

View File

@ -16,8 +16,6 @@
RED.nodes = (function() { RED.nodes = (function() {
var node_defs = {}; var node_defs = {};
var nodes = {};
var nodeTabMap = {};
var linkTabMap = {}; var linkTabMap = {};
var configNodes = {}; var configNodes = {};
@ -41,6 +39,7 @@ RED.nodes = (function() {
RED.events.emit("workspace:dirty",{dirty:dirty}); RED.events.emit("workspace:dirty",{dirty:dirty});
} }
// The registry holds information about all node types.
var registry = (function() { var registry = (function() {
var moduleList = {}; var moduleList = {};
var nodeList = []; var nodeList = [];
@ -53,7 +52,8 @@ RED.nodes = (function() {
defaults: { defaults: {
label: {value:""}, label: {value:""},
disabled: {value: false}, disabled: {value: false},
info: {value: ""} info: {value: ""},
env: {value: []}
} }
}; };
@ -142,9 +142,21 @@ RED.nodes = (function() {
RED.events.emit("registry:node-set-disabled",ns); RED.events.emit("registry:node-set-disabled",ns);
}, },
registerNodeType: function(nt,def) { registerNodeType: function(nt,def) {
nodeDefinitions[nt] = def;
def.type = nt;
if (nt.substring(0,8) != "subflow:") { if (nt.substring(0,8) != "subflow:") {
if (!nodeSets[typeToId[nt]]) {
var error = "";
var fullType = nt;
if (RED._loadingModule) {
fullType = "["+RED._loadingModule+"] "+nt;
if (nodeSets[RED._loadingModule]) {
error = nodeSets[RED._loadingModule].err || "";
} else {
error = "Unknown error";
}
}
RED.notify(RED._("palette.event.unknownNodeRegistered",{type:fullType, error:error}), "error");
return;
}
def.set = nodeSets[typeToId[nt]]; def.set = nodeSets[typeToId[nt]];
nodeSets[typeToId[nt]].added = true; nodeSets[typeToId[nt]].added = true;
nodeSets[typeToId[nt]].enabled = true; nodeSets[typeToId[nt]].enabled = true;
@ -167,9 +179,13 @@ RED.nodes = (function() {
} }
return result; return result;
} }
// TODO: too tightly coupled into palette UI // TODO: too tightly coupled into palette UI
} }
def.type = nt;
nodeDefinitions[nt] = def;
if (def.defaults) { if (def.defaults) {
for (var d in def.defaults) { for (var d in def.defaults) {
if (def.defaults.hasOwnProperty(d)) { if (def.defaults.hasOwnProperty(d)) {
@ -209,6 +225,285 @@ RED.nodes = (function() {
return exports; return exports;
})(); })();
// allNodes holds information about the Flow nodes.
var allNodes = (function() {
var nodes = {};
var tabMap = {};
var api = {
addTab: function(id) {
tabMap[id] = [];
},
hasTab: function(z) {
return tabMap.hasOwnProperty(z)
},
removeTab: function(id) {
delete tabMap[id];
},
addNode: function(n) {
nodes[n.id] = n;
if (tabMap.hasOwnProperty(n.z)) {
tabMap[n.z].push(n);
} else {
console.warn("Node added to unknown tab/subflow:",n);
tabMap["_"] = tabMap["_"] || [];
tabMap["_"].push(n);
}
},
removeNode: function(n) {
delete nodes[n.id]
if (tabMap.hasOwnProperty(n.z)) {
var i = tabMap[n.z].indexOf(n);
if (i > -1) {
tabMap[n.z].splice(i,1);
}
}
},
hasNode: function(id) {
return nodes.hasOwnProperty(id);
},
getNode: function(id) {
return nodes[id]
},
moveNode: function(n, newZ) {
api.removeNode(n);
n.z = newZ;
api.addNode(n)
},
moveNodesForwards: function(nodes) {
var result = [];
if (!Array.isArray(nodes)) {
nodes = [nodes]
}
// Can only do this for nodes on the same tab.
// Use nodes[0] to get the z
var tabNodes = tabMap[nodes[0].z];
var toMove = new Set(nodes.filter(function(n) { return n.type !== "group" && n.type !== "subflow" }));
var moved = new Set();
for (var i = tabNodes.length-1; i >= 0; i--) {
if (toMove.size === 0) {
break;
}
var n = tabNodes[i];
if (toMove.has(n)) {
// This is a node to move.
if (i < tabNodes.length-1 && !moved.has(tabNodes[i+1])) {
// Remove from current position
tabNodes.splice(i,1);
// Add it back one position higher
tabNodes.splice(i+1,0,n);
n._reordered = true;
result.push(n);
}
toMove.delete(n);
moved.add(n);
}
}
if (result.length > 0) {
RED.events.emit('nodes:reorder',{
z: nodes[0].z,
nodes: result
});
}
return result;
},
moveNodesBackwards: function(nodes) {
var result = [];
if (!Array.isArray(nodes)) {
nodes = [nodes]
}
// Can only do this for nodes on the same tab.
// Use nodes[0] to get the z
var tabNodes = tabMap[nodes[0].z];
var toMove = new Set(nodes.filter(function(n) { return n.type !== "group" && n.type !== "subflow" }));
var moved = new Set();
for (var i = 0; i < tabNodes.length; i++) {
if (toMove.size === 0) {
break;
}
var n = tabNodes[i];
if (toMove.has(n)) {
// This is a node to move.
if (i > 0 && !moved.has(tabNodes[i-1])) {
// Remove from current position
tabNodes.splice(i,1);
// Add it back one position lower
tabNodes.splice(i-1,0,n);
n._reordered = true;
result.push(n);
}
toMove.delete(n);
moved.add(n);
}
}
if (result.length > 0) {
RED.events.emit('nodes:reorder',{
z: nodes[0].z,
nodes: result
});
}
return result;
},
moveNodesToFront: function(nodes) {
var result = [];
if (!Array.isArray(nodes)) {
nodes = [nodes]
}
// Can only do this for nodes on the same tab.
// Use nodes[0] to get the z
var tabNodes = tabMap[nodes[0].z];
var toMove = new Set(nodes.filter(function(n) { return n.type !== "group" && n.type !== "subflow" }));
var target = tabNodes.length-1;
for (var i = tabNodes.length-1; i >= 0; i--) {
if (toMove.size === 0) {
break;
}
var n = tabNodes[i];
if (toMove.has(n)) {
// This is a node to move.
if (i < target) {
// Remove from current position
tabNodes.splice(i,1);
tabNodes.splice(target,0,n);
n._reordered = true;
result.push(n);
}
target--;
toMove.delete(n);
}
}
if (result.length > 0) {
RED.events.emit('nodes:reorder',{
z: nodes[0].z,
nodes: result
});
}
return result;
},
moveNodesToBack: function(nodes) {
var result = [];
if (!Array.isArray(nodes)) {
nodes = [nodes]
}
// Can only do this for nodes on the same tab.
// Use nodes[0] to get the z
var tabNodes = tabMap[nodes[0].z];
var toMove = new Set(nodes.filter(function(n) { return n.type !== "group" && n.type !== "subflow" }));
var target = 0;
for (var i = 0; i < tabNodes.length; i++) {
if (toMove.size === 0) {
break;
}
var n = tabNodes[i];
if (toMove.has(n)) {
// This is a node to move.
if (i > target) {
// Remove from current position
tabNodes.splice(i,1);
// Add it back one position lower
tabNodes.splice(target,0,n);
n._reordered = true;
result.push(n);
}
target++;
toMove.delete(n);
}
}
if (result.length > 0) {
RED.events.emit('nodes:reorder',{
z: nodes[0].z,
nodes: result
});
}
return result;
},
getNodes: function(z) {
return tabMap[z];
},
clear: function() {
nodes = {};
tabMap = {};
},
eachNode: function(cb) {
var nodeList,i,j;
for (i in subflows) {
if (subflows.hasOwnProperty(i)) {
nodeList = tabMap[i];
for (j = 0; j < nodeList.length; j++) {
if (cb(nodeList[j]) === false) {
return;
}
}
}
}
for (i = 0; i < workspacesOrder.length; i++) {
nodeList = tabMap[workspacesOrder[i]];
for (j = 0; j < nodeList.length; j++) {
if (cb(nodeList[j]) === false) {
return;
}
}
}
// Flow nodes that do not have a valid tab/subflow
if (tabMap["_"]) {
nodeList = tabMap["_"];
for (j = 0; j < nodeList.length; j++) {
if (cb(nodeList[j]) === false) {
return;
}
}
}
},
filterNodes: function(filter) {
var result = [];
var searchSet = null;
var doZFilter = false;
if (filter.hasOwnProperty("z")) {
if (tabMap.hasOwnProperty(filter.z)) {
searchSet = tabMap[filter.z];
} else {
doZFilter = true;
}
}
var objectLookup = false;
if (searchSet === null) {
searchSet = Object.keys(nodes);
objectLookup = true;
}
for (var n=0;n<searchSet.length;n++) {
var node = searchSet[n];
if (objectLookup) {
node = nodes[node];
}
if (filter.hasOwnProperty("type") && node.type !== filter.type) {
continue;
}
if (doZFilter && node.z !== filter.z) {
continue;
}
result.push(node);
}
return result;
},
getNodeOrder: function(z) {
return tabMap[z].map(function(n) { return n.id })
},
setNodeOrder: function(z, order) {
var orderMap = {};
order.forEach(function(id,i) {
orderMap[id] = i;
})
tabMap[z].sort(function(A,B) {
A._reordered = true;
B._reordered = true;
return orderMap[A.id] - orderMap[B.id];
})
}
}
return api;
})()
function getID() { function getID() {
var bytes = []; var bytes = [];
for (var i=0;i<8;i++) { for (var i=0;i<8;i++) {
@ -294,15 +589,10 @@ RED.nodes = (function() {
}); });
n.i = nextId+1; n.i = nextId+1;
} }
nodes[n.id] = n; allNodes.addNode(n);
if (!nodeLinks[n.id]) { if (!nodeLinks[n.id]) {
nodeLinks[n.id] = {in:[],out:[]}; nodeLinks[n.id] = {in:[],out:[]};
} }
if (nodeTabMap[n.z]) {
nodeTabMap[n.z][n.id] = n;
} else {
console.warn("Node added to unknown tab/subflow:",n);
}
} }
RED.events.emit('nodes:add',n); RED.events.emit('nodes:add',n);
} }
@ -330,10 +620,8 @@ RED.nodes = (function() {
function getNode(id) { function getNode(id) {
if (id in configNodes) { if (id in configNodes) {
return configNodes[id]; return configNodes[id];
} else if (id in nodes) {
return nodes[id];
} }
return null; return allNodes.getNode(id);
} }
function removeNode(id) { function removeNode(id) {
@ -345,13 +633,10 @@ RED.nodes = (function() {
delete configNodes[id]; delete configNodes[id];
RED.events.emit('nodes:remove',node); RED.events.emit('nodes:remove',node);
RED.workspaces.refresh(); RED.workspaces.refresh();
} else if (id in nodes) { } else if (allNodes.hasNode(id)) {
node = nodes[id]; node = allNodes.getNode(id);
delete nodes[id] allNodes.removeNode(node);
delete nodeLinks[id]; delete nodeLinks[id];
if (nodeTabMap[node.z]) {
delete nodeTabMap[node.z][node.id];
}
removedLinks = links.filter(function(l) { return (l.source === node) || (l.target === node); }); removedLinks = links.filter(function(l) { return (l.source === node) || (l.target === node); });
removedLinks.forEach(removeLink); removedLinks.forEach(removeLink);
var updatedConfigNode = false; var updatedConfigNode = false;
@ -409,40 +694,54 @@ RED.nodes = (function() {
return {links:removedLinks,nodes:removedNodes}; return {links:removedLinks,nodes:removedNodes};
} }
function moveNodesForwards(nodes) {
return allNodes.moveNodesForwards(nodes);
}
function moveNodesBackwards(nodes) {
return allNodes.moveNodesBackwards(nodes);
}
function moveNodesToFront(nodes) {
return allNodes.moveNodesToFront(nodes);
}
function moveNodesToBack(nodes) {
return allNodes.moveNodesToBack(nodes);
}
function getNodeOrder(z) {
return allNodes.getNodeOrder(z);
}
function setNodeOrder(z, order) {
allNodes.setNodeOrder(z,order);
}
function moveNodeToTab(node, z) { function moveNodeToTab(node, z) {
if (node.type === "group") { if (node.type === "group") {
moveGroupToTab(node,z); moveGroupToTab(node,z);
return; return;
} }
if (nodeTabMap[node.z]) { var oldZ = node.z;
delete nodeTabMap[node.z][node.id]; allNodes.moveNode(node,z);
}
if (!nodeTabMap[z]) {
nodeTabMap[z] = {};
}
nodeTabMap[z][node.id] = node;
var nl = nodeLinks[node.id]; var nl = nodeLinks[node.id];
if (nl) { if (nl) {
nl.in.forEach(function(l) { nl.in.forEach(function(l) {
var idx = linkTabMap[node.z].indexOf(l); var idx = linkTabMap[oldZ].indexOf(l);
if (idx != -1) { if (idx != -1) {
linkTabMap[node.z].splice(idx, 1); linkTabMap[oldZ].splice(idx, 1);
} }
if ((l.source.z === z) && linkTabMap[z]) { if ((l.source.z === z) && linkTabMap[z]) {
linkTabMap[z].push(l); linkTabMap[z].push(l);
} }
}); });
nl.out.forEach(function(l) { nl.out.forEach(function(l) {
var idx = linkTabMap[node.z].indexOf(l); var idx = linkTabMap[oldZ].indexOf(l);
if (idx != -1) { if (idx != -1) {
linkTabMap[node.z].splice(idx, 1); linkTabMap[oldZ].splice(idx, 1);
} }
if ((l.target.z === z) && linkTabMap[z]) { if ((l.target.z === z) && linkTabMap[z]) {
linkTabMap[z].push(l); linkTabMap[z].push(l);
} }
}); });
} }
node.z = z;
RED.events.emit("nodes:change",node); RED.events.emit("nodes:change",node);
} }
function moveGroupToTab(group, z) { function moveGroupToTab(group, z) {
@ -482,7 +781,7 @@ RED.nodes = (function() {
function addWorkspace(ws,targetIndex) { function addWorkspace(ws,targetIndex) {
workspaces[ws.id] = ws; workspaces[ws.id] = ws;
nodeTabMap[ws.id] = {}; allNodes.addTab(ws.id);
linkTabMap[ws.id] = []; linkTabMap[ws.id] = [];
ws._def = RED.nodes.getType('tab'); ws._def = RED.nodes.getType('tab');
@ -506,19 +805,14 @@ RED.nodes = (function() {
var removedGroups = []; var removedGroups = [];
if (ws) { if (ws) {
delete workspaces[id]; delete workspaces[id];
delete nodeTabMap[id]; allNodes.removeTab(id);
delete linkTabMap[id]; delete linkTabMap[id];
workspacesOrder.splice(workspacesOrder.indexOf(id),1); workspacesOrder.splice(workspacesOrder.indexOf(id),1);
var i; var i;
var node; var node;
// TODO: this should use nodeTabMap
for (i in nodes) { if (allNodes.hasTab(id)) {
if (nodes.hasOwnProperty(i)) { removedNodes = allNodes.getNodes(id).slice()
node = nodes[i];
if (node.z == id) {
removedNodes.push(node);
}
}
} }
for (i in configNodes) { for (i in configNodes) {
if (configNodes.hasOwnProperty(i)) { if (configNodes.hasOwnProperty(i)) {
@ -572,7 +866,7 @@ RED.nodes = (function() {
sf.name = subflowName; sf.name = subflowName;
} }
subflows[sf.id] = sf; subflows[sf.id] = sf;
nodeTabMap[sf.id] = {}; allNodes.addTab(sf.id);
linkTabMap[sf.id] = []; linkTabMap[sf.id] = [];
RED.nodes.registerType("subflow:"+sf.id, { RED.nodes.registerType("subflow:"+sf.id, {
@ -591,18 +885,18 @@ RED.nodes = (function() {
inputLabels: function(i) { return sf.inputLabels?sf.inputLabels[i]:null }, inputLabels: function(i) { return sf.inputLabels?sf.inputLabels[i]:null },
outputLabels: function(i) { return sf.outputLabels?sf.outputLabels[i]:null }, outputLabels: function(i) { return sf.outputLabels?sf.outputLabels[i]:null },
oneditprepare: function() { oneditprepare: function() {
if (this.type !== 'subflow') {
// A subflow instance node
RED.subflow.buildEditForm("subflow",this); RED.subflow.buildEditForm("subflow",this);
RED.subflow.buildPropertiesForm(this); } else {
// A subflow template node
RED.subflow.buildEditForm("subflow-template", this);
}
}, },
oneditresize: function(size) { oneditresize: function(size) {
// var rows = $(".dialog-form>div:not(.node-input-env-container-row)"); if (this.type === 'subflow') {
var height = size.height; $("#node-input-env-container").editableList('height',size.height - 80);
// for (var i=0; i<rows.size(); i++) { }
// height -= $(rows[i]).outerHeight(true);
// }
// var editorRow = $("#dialog-form>div.node-input-env-container-row");
// height -= (parseInt(editorRow.css("marginTop"))+parseInt(editorRow.css("marginBottom")));
$("ol.red-ui-editor-subflow-env-list").editableList('height',height);
}, },
set:{ set:{
module: "node-red" module: "node-red"
@ -618,17 +912,16 @@ RED.nodes = (function() {
function removeSubflow(sf) { function removeSubflow(sf) {
if (subflows[sf.id]) { if (subflows[sf.id]) {
delete subflows[sf.id]; delete subflows[sf.id];
delete nodeTabMap[sf.id]; allNodes.removeTab(sf.id);
registry.removeNodeType("subflow:"+sf.id); registry.removeNodeType("subflow:"+sf.id);
RED.events.emit("subflows:remove",sf); RED.events.emit("subflows:remove",sf);
} }
} }
function subflowContains(sfid,nodeid) { function subflowContains(sfid,nodeid) {
for (var i in nodes) { var sfNodes = allNodes.getNodes(sfid);
if (nodes.hasOwnProperty(i)) { for (var i = 0; i<sfNodes.length; i++) {
var node = nodes[i]; var node = sfNodes[i];
if (node.z === sfid) {
var m = /^subflow:(.+)$/.exec(node.type); var m = /^subflow:(.+)$/.exec(node.type);
if (m) { if (m) {
if (m[1] === nodeid) { if (m[1] === nodeid) {
@ -641,8 +934,6 @@ RED.nodes = (function() {
} }
} }
} }
}
}
return false; return false;
} }
@ -681,7 +972,13 @@ RED.nodes = (function() {
} }
function convertWorkspace(n) { function convertWorkspace(n,opts) {
var exportCreds = true;
if (opts) {
if (opts.hasOwnProperty("credentials")) {
exportCreds = opts.credentials;
}
}
var node = {}; var node = {};
node.id = n.id; node.id = n.id;
node.type = n.type; node.type = n.type;
@ -690,6 +987,23 @@ RED.nodes = (function() {
node[d] = n[d]; node[d] = n[d];
} }
} }
if (exportCreds) {
var credentialSet = {};
if (n.credentials) {
for (var tabCred in n.credentials) {
if (n.credentials.hasOwnProperty(tabCred)) {
if (!n.credentials._ ||
n.credentials["has_"+tabCred] != n.credentials._["has_"+tabCred] ||
(n.credentials["has_"+tabCred] && n.credentials[tabCred])) {
credentialSet[tabCred] = n.credentials[tabCred];
}
}
}
if (Object.keys(credentialSet).length > 0) {
node.credentials = credentialSet;
}
}
}
return node; return node;
} }
/** /**
@ -710,7 +1024,7 @@ RED.nodes = (function() {
} }
if (n.type === 'tab') { if (n.type === 'tab') {
return convertWorkspace(n); return convertWorkspace(n, { credentials: exportCreds });
} }
var node = {}; var node = {};
node.id = n.id; node.id = n.id;
@ -739,8 +1053,10 @@ RED.nodes = (function() {
} }
if (exportCreds) { if (exportCreds) {
var credentialSet = {}; var credentialSet = {};
if (/^subflow:/.test(node.type) && n.credentials) { if ((/^subflow:/.test(node.type) ||
// A subflow instance node can have arbitrary creds (node.type === "group")) &&
n.credentials) {
// A subflow instance/group node can have arbitrary creds
for (var sfCred in n.credentials) { for (var sfCred in n.credentials) {
if (n.credentials.hasOwnProperty(sfCred)) { if (n.credentials.hasOwnProperty(sfCred)) {
if (!n.credentials._ || if (!n.credentials._ ||
@ -824,8 +1140,8 @@ RED.nodes = (function() {
} }
} }
if ((!n._def.defaults || !n._def.defaults.hasOwnProperty("l")) && n.hasOwnProperty('l')) { if ((!n._def.defaults || !n._def.defaults.hasOwnProperty("l")) && n.hasOwnProperty('l')) {
var isLink = /^link (in|out)$/.test(node.type); var showLabel = n._def.hasOwnProperty("showLabel")?n._def.showLabel:true;
if (isLink == n.l) { if (showLabel != n.l) {
node.l = n.l; node.l = n.l;
} }
} }
@ -934,11 +1250,15 @@ RED.nodes = (function() {
function createExportableSubflow(id) { function createExportableSubflow(id) {
var sf = getSubflow(id); var sf = getSubflow(id);
var nodeSet = [sf]; var nodeSet;
var sfNodeIds = Object.keys(nodeTabMap[sf.id]||{}); var sfNodes = allNodes.getNodes(sf.id);
for (var i=0, l=sfNodeIds.length; i<l; i++) { if (sfNodes) {
nodeSet.push(nodeTabMap[sf.id][sfNodeIds[i]]); nodeSet = sfNodes.slice();
nodeSet.unshift(sf);
} else {
nodeSet = [sf];
} }
console.log(nodeSet);
return createExportableNodeSet(nodeSet); return createExportableNodeSet(nodeSet);
} }
/** /**
@ -965,12 +1285,9 @@ RED.nodes = (function() {
if (!exportedSubflows[subflowId]) { if (!exportedSubflows[subflowId]) {
exportedSubflows[subflowId] = true; exportedSubflows[subflowId] = true;
var subflow = getSubflow(subflowId); var subflow = getSubflow(subflowId);
var subflowSet = [subflow]; var subflowSet = allNodes.getNodes(subflowId).slice();
RED.nodes.eachNode(function(n) { subflowSet.unshift(subflow);
if (n.z == subflowId) {
subflowSet.push(n);
}
});
RED.nodes.eachConfig(function(n) { RED.nodes.eachConfig(function(n) {
if (n.z == subflowId) { if (n.z == subflowId) {
subflowSet.push(n); subflowSet.push(n);
@ -1030,7 +1347,7 @@ RED.nodes = (function() {
var i; var i;
for (i=0;i<workspacesOrder.length;i++) { for (i=0;i<workspacesOrder.length;i++) {
if (workspaces[workspacesOrder[i]].type == "tab") { if (workspaces[workspacesOrder[i]].type == "tab") {
nns.push(convertWorkspace(workspaces[workspacesOrder[i]])); nns.push(convertWorkspace(workspaces[workspacesOrder[i]], opts));
} }
} }
for (i in subflows) { for (i in subflows) {
@ -1048,11 +1365,9 @@ RED.nodes = (function() {
nns.push(convertNode(configNodes[i], opts)); nns.push(convertNode(configNodes[i], opts));
} }
} }
for (i in nodes) { RED.nodes.eachNode(function(n) {
if (nodes.hasOwnProperty(i)) { nns.push(convertNode(n, opts));
nns.push(convertNode(nodes[i], opts)); })
}
}
return nns; return nns;
} }
@ -1149,7 +1464,7 @@ RED.nodes = (function() {
var nodeZ = n.z || "__global__"; var nodeZ = n.z || "__global__";
imported.zMap[nodeZ] = imported.zMap[nodeZ] || []; imported.zMap[nodeZ] = imported.zMap[nodeZ] || [];
imported.zMap[nodeZ].push(n) imported.zMap[nodeZ].push(n)
if (nodes[n.id] || configNodes[n.id] || workspaces[n.id] || subflows[n.id] || groups[n.id]) { if (allNodes.hasNode(n.id) || configNodes[n.id] || workspaces[n.id] || subflows[n.id] || groups[n.id]) {
imported.conflicted[n.id] = n; imported.conflicted[n.id] = n;
} }
}) })
@ -1157,7 +1472,6 @@ RED.nodes = (function() {
} }
/** /**
* Replace the provided nodes. * Replace the provided nodes.
* This must contain complete Subflow defs or complete Flow Tabs. * This must contain complete Subflow defs or complete Flow Tabs.
@ -1316,7 +1630,7 @@ RED.nodes = (function() {
if (!options.generateIds) { if (!options.generateIds) {
if (!options.importMap[id]) { if (!options.importMap[id]) {
// No conflict resolution for this node // No conflict resolution for this node
var existing = nodes[id] || configNodes[id] || workspaces[id] || subflows[id] || groups[id]; var existing = allNodes.getNode(id) || configNodes[id] || workspaces[id] || subflows[id] || groups[id];
if (existing) { if (existing) {
existingNodes.push({existing:existing, imported:n}); existingNodes.push({existing:existing, imported:n});
} }
@ -1387,7 +1701,8 @@ RED.nodes = (function() {
type: "tab", type: "tab",
disabled: false, disabled: false,
label: RED._("clipboard.recoveredNodes"), label: RED._("clipboard.recoveredNodes"),
info: RED._("clipboard.recoveredNodesInfo") info: RED._("clipboard.recoveredNodesInfo"),
env: []
} }
addWorkspace(recoveryWorkspace); addWorkspace(recoveryWorkspace);
RED.workspaces.add(recoveryWorkspace); RED.workspaces.add(recoveryWorkspace);
@ -1518,7 +1833,7 @@ RED.nodes = (function() {
// Add a tab if there isn't one there already // Add a tab if there isn't one there already
if (defaultWorkspace == null) { if (defaultWorkspace == null) {
defaultWorkspace = { type:"tab", id:getID(), disabled: false, info:"", label:RED._('workspace.defaultName',{number:1})}; defaultWorkspace = { type:"tab", id:getID(), disabled: false, info:"", label:RED._('workspace.defaultName',{number:1}), env:[]};
addWorkspace(defaultWorkspace); addWorkspace(defaultWorkspace);
RED.workspaces.add(defaultWorkspace); RED.workspaces.add(defaultWorkspace);
new_workspaces.push(defaultWorkspace); new_workspaces.push(defaultWorkspace);
@ -1979,32 +2294,9 @@ RED.nodes = (function() {
// TODO: supports filter.z|type // TODO: supports filter.z|type
function filterNodes(filter) { function filterNodes(filter) {
var result = []; return allNodes.filterNodes(filter);
var searchSet = null;
var doZFilter = false;
if (filter.hasOwnProperty("z")) {
if (nodeTabMap.hasOwnProperty(filter.z)) {
searchSet = Object.keys(nodeTabMap[filter.z]);
} else {
doZFilter = true;
}
}
if (searchSet === null) {
searchSet = Object.keys(nodes);
} }
for (var n=0;n<searchSet.length;n++) {
var node = nodes[searchSet[n]];
if (filter.hasOwnProperty("type") && node.type !== filter.type) {
continue;
}
if (doZFilter && node.z !== filter.z) {
continue;
}
result.push(node);
}
return result;
}
function filterLinks(filter) { function filterLinks(filter) {
var result = []; var result = [];
var candidateLinks = []; var candidateLinks = [];
@ -2092,9 +2384,7 @@ RED.nodes = (function() {
} }
function clear() { function clear() {
nodes = {};
links = []; links = [];
nodeTabMap = {};
linkTabMap = {}; linkTabMap = {};
nodeLinks = {}; nodeLinks = {};
configNodes = {}; configNodes = {};
@ -2114,6 +2404,8 @@ RED.nodes = (function() {
initialLoad = null; initialLoad = null;
workspaces = {}; workspaces = {};
allNodes.clear();
RED.nodes.dirty(false); RED.nodes.dirty(false);
RED.view.redraw(true, true); RED.view.redraw(true, true);
RED.palette.refresh(); RED.palette.refresh();
@ -2186,10 +2478,7 @@ RED.nodes = (function() {
if (configNodes.hasOwnProperty(n.id)) { if (configNodes.hasOwnProperty(n.id)) {
delete configNodes[n.id]; delete configNodes[n.id];
} else { } else {
delete nodes[n.id]; allNodes.removeNode(n);
if (nodeTabMap[n.z]) {
delete nodeTabMap[n.z][n.id];
}
} }
reimportList.push(convertNode(n)); reimportList.push(convertNode(n));
RED.events.emit('nodes:remove',n); RED.events.emit('nodes:remove',n);
@ -2246,6 +2535,13 @@ RED.nodes = (function() {
remove: removeNode, remove: removeNode,
clear: clear, clear: clear,
moveNodesForwards: moveNodesForwards,
moveNodesBackwards: moveNodesBackwards,
moveNodesToFront: moveNodesToFront,
moveNodesToBack: moveNodesToBack,
getNodeOrder: getNodeOrder,
setNodeOrder: setNodeOrder,
moveNodeToTab: moveNodeToTab, moveNodeToTab: moveNodeToTab,
addLink: addLink, addLink: addLink,
@ -2265,16 +2561,10 @@ RED.nodes = (function() {
addGroup: addGroup, addGroup: addGroup,
removeGroup: removeGroup, removeGroup: removeGroup,
group: function(id) { return groups[id] }, group: function(id) { return groups[id] },
groups: function(z) { return groupsByZ[z]||[] }, groups: function(z) { return groupsByZ[z]?groupsByZ[z].slice():[] },
eachNode: function(cb) { eachNode: function(cb) {
for (var id in nodes) { allNodes.eachNode(cb);
if (nodes.hasOwnProperty(id)) {
if (cb(nodes[id]) === false) {
break;
}
}
}
}, },
eachLink: function(cb) { eachLink: function(cb) {
for (var l=0;l<links.length;l++) { for (var l=0;l<links.length;l++) {

View File

@ -201,6 +201,7 @@ var RED = (function() {
RED.projects.refresh(function(activeProject) { RED.projects.refresh(function(activeProject) {
loadFlows(function() { loadFlows(function() {
RED.sidebar.info.refresh() RED.sidebar.info.refresh()
var showProjectWelcome = false;
if (!activeProject) { if (!activeProject) {
// Projects enabled but no active project // Projects enabled but no active project
RED.menu.setDisabled('menu-item-projects-open',true); RED.menu.setDisabled('menu-item-projects-open',true);
@ -208,10 +209,10 @@ var RED = (function() {
if (activeProject === false) { if (activeProject === false) {
// User previously decline the migration to projects. // User previously decline the migration to projects.
} else { // null/undefined } else { // null/undefined
RED.projects.showStartup(); showProjectWelcome = true;
} }
} }
completeLoad(); completeLoad(showProjectWelcome);
}); });
}); });
} else { } else {
@ -251,6 +252,9 @@ var RED = (function() {
if (/^#flow\/.+$/.test(currentHash)) { if (/^#flow\/.+$/.test(currentHash)) {
RED.workspaces.show(currentHash.substring(6),true); RED.workspaces.show(currentHash.substring(6),true);
} }
if (RED.workspaces.active() === 0 && RED.workspaces.count() > 0) {
RED.workspaces.show(RED.nodes.getWorkspaceOrder()[0])
}
} catch(err) { } catch(err) {
console.warn(err); console.warn(err);
RED.notify( RED.notify(
@ -267,7 +271,7 @@ var RED = (function() {
}); });
} }
function completeLoad() { function completeLoad(showProjectWelcome) {
var persistentNotifications = {}; var persistentNotifications = {};
RED.comms.subscribe("notification/#",function(topic,msg) { RED.comms.subscribe("notification/#",function(topic,msg) {
var parts = topic.split("/"); var parts = topic.split("/");
@ -477,8 +481,17 @@ var RED = (function() {
RED.nodes.addNodeSet(m); RED.nodes.addNodeSet(m);
addedTypes = addedTypes.concat(m.types); addedTypes = addedTypes.concat(m.types);
RED.i18n.loadNodeCatalog(id, function() { RED.i18n.loadNodeCatalog(id, function() {
$.get('nodes/'+id, function(data) { var lang = localStorage.getItem("editor-language")||RED.i18n.detectLanguage();
$.ajax({
headers: {
"Accept":"text/html",
"Accept-Language": lang
},
cache: false,
url: 'nodes/'+id,
success: function(data) {
appendNodeConfig(data); appendNodeConfig(data);
}
}); });
}); });
}); });
@ -505,10 +518,19 @@ var RED = (function() {
typeList = "<ul><li>"+msg.types.map(RED.utils.sanitize).join("</li><li>")+"</li></ul>"; typeList = "<ul><li>"+msg.types.map(RED.utils.sanitize).join("</li><li>")+"</li></ul>";
RED.notify(RED._("palette.event.nodeEnabled", {count:msg.types.length})+typeList,"success"); RED.notify(RED._("palette.event.nodeEnabled", {count:msg.types.length})+typeList,"success");
} else { } else {
$.get('nodes/'+msg.id, function(data) { var lang = localStorage.getItem("editor-language")||RED.i18n.detectLanguage();
$.ajax({
headers: {
"Accept":"text/html",
"Accept-Language": lang
},
cache: false,
url: 'nodes/'+msg.id,
success: function(data) {
appendNodeConfig(data); appendNodeConfig(data);
typeList = "<ul><li>"+msg.types.map(RED.utils.sanitize).join("</li><li>")+"</li></ul>"; typeList = "<ul><li>"+msg.types.map(RED.utils.sanitize).join("</li><li>")+"</li></ul>";
RED.notify(RED._("palette.event.nodeAdded", {count:msg.types.length})+typeList,"success"); RED.notify(RED._("palette.event.nodeAdded", {count:msg.types.length})+typeList,"success");
}
}); });
} }
} }
@ -535,19 +557,24 @@ var RED = (function() {
setTimeout(function() { setTimeout(function() {
loader.end(); loader.end();
checkFirstRun(function() {
if (showProjectWelcome) {
RED.projects.showStartup();
}
});
},100); },100);
} }
function showAbout() { function checkFirstRun(done) {
$.get('red/about', function(data) { if (RED.settings.theme("tours") === false) {
// data will be strictly markdown. Any HTML should be escaped. done();
data = RED.utils.sanitize(data); return;
var aboutHeader = '<div style="text-align:center;">'+ }
'<img width="50px" src="red/images/node-red-icon.svg" />'+ if (!RED.settings.get("editor.view.view-show-welcome-tours", true)) {
'</div>'; done();
return;
RED.sidebar.help.set(aboutHeader+RED.utils.renderMarkdown(data)); }
}); RED.actions.invoke("core:show-welcome-tour", RED.settings.get("editor.tours.welcome"), done);
} }
function buildMainMenu() { function buildMainMenu() {
@ -559,6 +586,22 @@ var RED = (function() {
{id:"menu-item-projects-settings",label:RED._("menu.label.projects-settings"),disabled:false,onselect:"core:show-project-settings"} {id:"menu-item-projects-settings",label:RED._("menu.label.projects-settings"),disabled:false,onselect:"core:show-project-settings"}
]}); ]});
} }
menuOptions.push({id:"menu-item-edit-menu", label:"Edit", options: [
{id: "menu-item-edit-undo", label:RED._("keyboard.undoChange"), disabled: true, onselect: "core:undo"},
{id: "menu-item-edit-redo", label:RED._("keyboard.redoChange"), disabled: true, onselect: "core:redo"},
null,
{id: "menu-item-edit-cut", label:RED._("keyboard.cutNode"), onselect: "core:cut-selection-to-internal-clipboard"},
{id: "menu-item-edit-copy", label:RED._("keyboard.copyNode"), onselect: "core:copy-selection-to-internal-clipboard"},
{id: "menu-item-edit-paste", label:RED._("keyboard.pasteNode"), disabled: true, onselect: "core:paste-from-internal-clipboard"},
null,
{id: "menu-item-edit-copy-group-style", label:RED._("keyboard.copyGroupStyle"), onselect: "core:copy-group-style"},
{id: "menu-item-edit-paste-group-style", label:RED._("keyboard.pasteGroupStyle"), disabled: true, onselect: "core:paste-group-style"},
null,
{id: "menu-item-edit-select-all", label:RED._("keyboard.selectAll"), onselect: "core:select-all-nodes"},
{id: "menu-item-edit-select-connected", label:RED._("keyboard.selectAllConnected"), onselect: "core:select-connected-nodes"},
{id: "menu-item-edit-select-none", label:RED._("keyboard.selectNone"), onselect: "core:select-none"}
]});
menuOptions.push({id:"menu-item-view-menu",label:RED._("menu.label.view.view"),options:[ menuOptions.push({id:"menu-item-view-menu",label:RED._("menu.label.view.view"),options:[
{id:"menu-item-palette",label:RED._("menu.label.palette.show"),toggle:true,onselect:"core:toggle-palette", selected: true}, {id:"menu-item-palette",label:RED._("menu.label.palette.show"),toggle:true,onselect:"core:toggle-palette", selected: true},
{id:"menu-item-sidebar",label:RED._("menu.label.sidebar.show"),toggle:true,onselect:"core:toggle-sidebar", selected: true}, {id:"menu-item-sidebar",label:RED._("menu.label.sidebar.show"),toggle:true,onselect:"core:toggle-sidebar", selected: true},
@ -566,6 +609,25 @@ var RED = (function() {
{id:"menu-item-action-list",label:RED._("keyboard.actionList"),onselect:"core:show-action-list"}, {id:"menu-item-action-list",label:RED._("keyboard.actionList"),onselect:"core:show-action-list"},
null null
]}); ]});
menuOptions.push({id:"menu-item-arrange-menu", label:RED._("menu.label.arrange"), options: [
{id: "menu-item-view-tools-move-to-back", label:RED._("menu.label.moveToBack"), disabled: true, onselect: "core:move-selection-to-back"},
{id: "menu-item-view-tools-move-to-front", label:RED._("menu.label.moveToFront"), disabled: true, onselect: "core:move-selection-to-front"},
{id: "menu-item-view-tools-move-backwards", label:RED._("menu.label.moveBackwards"), disabled: true, onselect: "core:move-selection-backwards"},
{id: "menu-item-view-tools-move-forwards", label:RED._("menu.label.moveForwards"), disabled: true, onselect: "core:move-selection-forwards"},
null,
{id: "menu-item-view-tools-align-left", label:RED._("menu.label.alignLeft"), disabled: true, onselect: "core:align-selection-to-left"},
{id: "menu-item-view-tools-align-center", label:RED._("menu.label.alignCenter"), disabled: true, onselect: "core:align-selection-to-center"},
{id: "menu-item-view-tools-align-right", label:RED._("menu.label.alignRight"), disabled: true, onselect: "core:align-selection-to-right"},
null,
{id: "menu-item-view-tools-align-top", label:RED._("menu.label.alignTop"), disabled: true, onselect: "core:align-selection-to-top"},
{id: "menu-item-view-tools-align-middle", label:RED._("menu.label.alignMiddle"), disabled: true, onselect: "core:align-selection-to-middle"},
{id: "menu-item-view-tools-align-bottom", label:RED._("menu.label.alignBottom"), disabled: true, onselect: "core:align-selection-to-bottom"},
null,
{id: "menu-item-view-tools-distribute-horizontally", label:RED._("menu.label.distributeHorizontally"), disabled: true, onselect: "core:distribute-selection-horizontally"},
{id: "menu-item-view-tools-distribute-veritcally", label:RED._("menu.label.distributeVertically"), disabled: true, onselect: "core:distribute-selection-vertically"}
]});
menuOptions.push(null); menuOptions.push(null);
if (RED.settings.theme("menu.menu-item-import-library", true)) { if (RED.settings.theme("menu.menu-item-import-library", true)) {
menuOptions.push({id: "menu-item-import", label: RED._("menu.label.import"), onselect: "core:show-import-dialog"}); menuOptions.push({id: "menu-item-import", label: RED._("menu.label.import"), onselect: "core:show-import-dialog"});
@ -626,7 +688,6 @@ var RED = (function() {
RED.user.init(); RED.user.init();
RED.notifications.init(); RED.notifications.init();
RED.library.init(); RED.library.init();
RED.keyboard.init();
RED.palette.init(); RED.palette.init();
RED.eventLog.init(); RED.eventLog.init();
@ -655,16 +716,13 @@ var RED = (function() {
RED.deploy.init(RED.settings.theme("deployButton",null)); RED.deploy.init(RED.settings.theme("deployButton",null));
buildMainMenu(); RED.keyboard.init(buildMainMenu);
RED.nodes.init(); RED.nodes.init();
RED.comms.connect(); RED.comms.connect();
$("#red-ui-main-container").show(); $("#red-ui-main-container").show();
RED.actions.add("core:show-about", showAbout);
loadPluginList(); loadPluginList();
} }

View File

@ -19,7 +19,6 @@ RED.settings = (function () {
var loadedSettings = {}; var loadedSettings = {};
var userSettings = {}; var userSettings = {};
var settingsDirty = false;
var pendingSave; var pendingSave;
var hasLocalStorage = function () { var hasLocalStorage = function () {
@ -220,6 +219,16 @@ RED.settings = (function () {
return defaultValue; return defaultValue;
} }
} }
function getLocal(key) {
return localStorage.getItem(key)
}
function setLocal(key, value) {
localStorage.setItem(key, value);
}
function removeLocal(key) {
localStorage.removeItem(key)
}
return { return {
init: init, init: init,
@ -228,6 +237,9 @@ RED.settings = (function () {
set: set, set: set,
get: get, get: get,
remove: remove, remove: remove,
theme: theme theme: theme,
setLocal: setLocal,
getLocal: getLocal,
removeLocal: removeLocal
} }
})(); })();

View File

@ -4,6 +4,12 @@ RED.actions = (function() {
} }
function addAction(name,handler) { function addAction(name,handler) {
if (typeof handler !== 'function') {
throw new Error("Action handler not a function");
}
if (actions[name]) {
throw new Error("Cannot override existing action");
}
actions[name] = handler; actions[name] = handler;
} }
function removeAction(name) { function removeAction(name) {
@ -12,9 +18,11 @@ RED.actions = (function() {
function getAction(name) { function getAction(name) {
return actions[name]; return actions[name];
} }
function invokeAction(name,args) { function invokeAction() {
var args = Array.prototype.slice.call(arguments);
var name = args.shift();
if (actions.hasOwnProperty(name)) { if (actions.hasOwnProperty(name)) {
actions[name](args); actions[name].apply(null, args);
} }
} }
function listActions() { function listActions() {

View File

@ -498,6 +498,13 @@ RED.clipboard = (function() {
$("#red-ui-clipboard-dialog-import-text").on("keyup", validateImport); $("#red-ui-clipboard-dialog-import-text").on("keyup", validateImport);
$("#red-ui-clipboard-dialog-import-text").on('paste',function() { setTimeout(validateImport,10)}); $("#red-ui-clipboard-dialog-import-text").on('paste',function() { setTimeout(validateImport,10)});
if (RED.workspaces.active() === 0) {
$("#red-ui-clipboard-dialog-import-opt-current").addClass('disabled').removeClass("selected");
$("#red-ui-clipboard-dialog-import-opt-new").addClass("selected");
} else {
$("#red-ui-clipboard-dialog-import-opt-current").removeClass('disabled').addClass("selected");
$("#red-ui-clipboard-dialog-import-opt-new").removeClass("selected");
}
$("#red-ui-clipboard-dialog-import-opt > a").on("click", function(evt) { $("#red-ui-clipboard-dialog-import-opt > a").on("click", function(evt) {
evt.preventDefault(); evt.preventDefault();
if ($(this).hasClass('disabled') || $(this).hasClass('selected')) { if ($(this).hasClass('disabled') || $(this).hasClass('selected')) {
@ -611,9 +618,6 @@ RED.clipboard = (function() {
activeLibraries[tabId] = browser; activeLibraries[tabId] = browser;
}) })
$("#red-ui-clipboard-dialog-tab-library-name").on("keyup", validateExportFilename); $("#red-ui-clipboard-dialog-tab-library-name").on("keyup", validateExportFilename);
$("#red-ui-clipboard-dialog-tab-library-name").on('paste',function() { setTimeout(validateExportFilename,10)}); $("#red-ui-clipboard-dialog-tab-library-name").on('paste',function() { setTimeout(validateExportFilename,10)});
$("#red-ui-clipboard-dialog-export").button("enable"); $("#red-ui-clipboard-dialog-export").button("enable");
@ -636,7 +640,6 @@ RED.clipboard = (function() {
label: RED._("editor.types.json") label: RED._("editor.types.json")
}); });
var previewList = $("#red-ui-clipboard-dialog-export-tab-clipboard-preview-list").css({position:"absolute",top:0,right:0,bottom:0,left:0}).treeList({ var previewList = $("#red-ui-clipboard-dialog-export-tab-clipboard-preview-list").css({position:"absolute",top:0,right:0,bottom:0,left:0}).treeList({
data: [] data: []
}) })
@ -738,6 +741,11 @@ RED.clipboard = (function() {
$("#red-ui-clipboard-dialog-export").hide(); $("#red-ui-clipboard-dialog-export").hide();
$("#red-ui-clipboard-dialog-import-conflict").hide(); $("#red-ui-clipboard-dialog-import-conflict").hide();
if (RED.workspaces.active() === 0) {
$("#red-ui-clipboard-dialog-export-rng-selected").addClass('disabled').removeClass('selected');
$("#red-ui-clipboard-dialog-export-rng-flow").addClass('disabled').removeClass('selected');
$("#red-ui-clipboard-dialog-export-rng-full").trigger("click");
} else {
var selection = RED.workspaces.selection(); var selection = RED.workspaces.selection();
if (selection.length > 0) { if (selection.length > 0) {
$("#red-ui-clipboard-dialog-export-rng-selected").trigger("click"); $("#red-ui-clipboard-dialog-export-rng-selected").trigger("click");
@ -750,6 +758,7 @@ RED.clipboard = (function() {
$("#red-ui-clipboard-dialog-export-rng-flow").trigger("click"); $("#red-ui-clipboard-dialog-export-rng-flow").trigger("click");
} }
} }
}
if (format === "red-ui-clipboard-dialog-export-fmt-full") { if (format === "red-ui-clipboard-dialog-export-fmt-full") {
$("#red-ui-clipboard-dialog-export-fmt-full").trigger("click"); $("#red-ui-clipboard-dialog-export-fmt-full").trigger("click");
} else { } else {

View File

@ -0,0 +1,115 @@
(function($) {
/**
* Attach to an <input type="text"> to provide auto-complete
*
* $("#node-red-text").autoComplete({
* search: function(value) { return ['a','b','c'] }
* })
*
* options:
*
* search : function(value, [done])
* A function that is passed the current contents of the input whenever
* it changes.
* The function must either return auto-complete options, or pass them
* to the optional 'done' parameter.
* If the function signature includes 'done', it must be used
*
* The auto-complete options should be an array of objects in the form:
* {
* value: String : the value to insert if selected
* label: String|DOM Element : the label to display in the dropdown.
* }
*
*/
$.widget( "nodered.autoComplete", {
_create: function() {
var that = this;
this.completionMenuShown = false;
this.options.search = this.options.search || function() { return [] }
this.element.addClass("red-ui-autoComplete")
this.element.on("keydown.red-ui-autoComplete", function(evt) {
if ((evt.keyCode === 13 || evt.keyCode === 9) && that.completionMenuShown) {
var opts = that.menu.options();
that.element.val(opts[0].value);
that.menu.hide();
evt.preventDefault();
}
})
this.element.on("keyup.red-ui-autoComplete", function(evt) {
if (evt.keyCode === 13 || evt.keyCode === 9 || evt.keyCode === 27) {
// ENTER / TAB / ESCAPE
return
}
if (evt.keyCode === 8 || evt.keyCode === 46) {
// Delete/Backspace
if (!that.completionMenuShown) {
return;
}
}
that._updateCompletions(this.value);
});
},
_showCompletionMenu: function(completions) {
if (this.completionMenuShown) {
return;
}
this.menu = RED.popover.menu({
tabSelect: true,
width: 300,
maxHeight: 200,
class: "red-ui-autoComplete-container",
options: completions,
onselect: (opt) => { this.element.val(opt.value); this.element.focus() },
onclose: () => { this.completionMenuShown = false; delete this.menu; this.element.focus()}
});
this.menu.show({
target: this.element
})
this.completionMenuShown = true;
},
_updateCompletions: function(val) {
var that = this;
if (val.trim() === "") {
if (this.completionMenuShown) {
this.menu.hide();
}
return;
}
function displayResults(completions,requestId) {
if (requestId && requestId !== that.pendingRequest) {
// This request has been superseded
return
}
if (!completions || completions.length === 0) {
if (that.completionMenuShown) {
that.menu.hide();
}
return
}
if (that.completionMenuShown) {
that.menu.options(completions);
} else {
that._showCompletionMenu(completions);
}
}
if (this.options.search.length === 2) {
var requestId = 1+Math.floor(Math.random()*10000);
this.pendingRequest = requestId;
this.options.search(val,function(completions) { displayResults(completions,requestId);})
} else {
displayResults(this.options.search(val))
}
},
_destroy: function() {
this.element.removeClass("red-ui-autoComplete")
this.element.off("keydown.red-ui-autoComplete")
this.element.off("keyup.red-ui-autoComplete")
if (this.completionMenuShown) {
this.menu.hide();
}
}
});
})(jQuery);

View File

@ -82,12 +82,19 @@ RED.menu = (function() {
linkContent += '<span class="red-ui-menu-label-container"><span class="red-ui-menu-label">'+opt.label+'</span>'+ linkContent += '<span class="red-ui-menu-label-container"><span class="red-ui-menu-label">'+opt.label+'</span>'+
'<span class="red-ui-menu-sublabel">'+opt.sublabel+'</span></span>' '<span class="red-ui-menu-sublabel">'+opt.sublabel+'</span></span>'
} else { } else {
linkContent += '<span class="red-ui-menu-label">'+opt.label+'</span>' linkContent += '<span class="red-ui-menu-label"><span>'+opt.label+'</span></span>'
} }
linkContent += '</a>'; linkContent += '</a>';
var link = $(linkContent).appendTo(item); var link = $(linkContent).appendTo(item);
opt.link = link;
if (typeof opt.onselect === 'string') {
var shortcut = RED.keyboard.getShortcut(opt.onselect);
if (shortcut && shortcut.key) {
opt.shortcutSpan = $('<span class="red-ui-popover-key">'+RED.keyboard.formatKey(shortcut.key, true)+'</span>').appendTo(link.find(".red-ui-menu-label"));
}
}
menuItems[opt.id] = opt; menuItems[opt.id] = opt;
@ -276,6 +283,22 @@ RED.menu = (function() {
} }
} }
function refreshShortcuts() {
for (var id in menuItems) {
if (menuItems.hasOwnProperty(id)) {
var opt = menuItems[id];
if (typeof opt.onselect === "string" && opt.shortcutSpan) {
opt.shortcutSpan.remove();
delete opt.shortcutSpan;
var shortcut = RED.keyboard.getShortcut(opt.onselect);
if (shortcut && shortcut.key) {
opt.shortcutSpan = $('<span class="red-ui-popover-key">'+RED.keyboard.formatKey(shortcut.key, true)+'</span>').appendTo(opt.link.find(".red-ui-menu-label"));
}
}
}
}
}
return { return {
init: createMenu, init: createMenu,
setSelected: setSelected, setSelected: setSelected,
@ -284,6 +307,7 @@ RED.menu = (function() {
setDisabled: setDisabled, setDisabled: setDisabled,
addItem: addItem, addItem: addItem,
removeItem: removeItem, removeItem: removeItem,
setAction: setAction setAction: setAction,
refreshShortcuts: refreshShortcuts
} }
})(); })();

View File

@ -13,24 +13,138 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
**/ **/
/*
* RED.popover.create(options) - create a popover callout box
* RED.popover.tooltip(target,content, action) - add a tooltip to an element
* RED.popover.menu(options) - create a dropdown menu
* RED.popover.panel(content) - create a dropdown container element
*/
/*
* RED.popover.create(options)
*
* options
* - target : DOM element - the element to target with the popover
* - direction : string - position of the popover relative to target
* 'top', 'right'(default), 'bottom', 'left', 'inset-[top,right,bottom,left]'
* - trigger : string - what triggers the popover to be displayed
* 'hover' - display when hovering the target
* 'click' - display when target is clicked
* 'modal' - hmm not sure, need to find where we use that mode
* - content : string|function - contents of the popover. If a string, handled
* as raw HTML, so take care.
* If a function, can return a String to be added
* as text (not HTML), or a DOM element to append
* - delay : object - sets show/hide delays after mouseover/out events
* { show: 750, hide: 50 }
* - autoClose : number - delay before closing the popover in some cases
* if trigger is click - delay after mouseout
* else if trigger not hover/modal - delay after showing
* - width : number - width of popover, default 'auto'
* - maxWidth : number - max width of popover, default 'auto'
* - size : string - scale of popover. 'default', 'small'
* - offset : number - px offset from target
* - tooltip : boolean - if true, clicking on popover closes it
* - class : string - optional css class to apply to popover
* - interactive : if trigger is 'hover' and this is set to true, allow the mouse
* to move over the popover without hiding it.
*
* Returns the popover object with the following properties/functions:
* properties:
* - element : DOM element - the popover dom element
* functions:
* - setContent(content) - change the popover content. This only works if the
* popover is not currently displayed. It does not
* change the content of a visible popover.
* - open(instant) - show the popover. If 'instant' is true, don't fade in
* - close(instant) - hide the popover. If 'instant' is true, don't fade out
* - move(options) - move the popover. The options parameter can take many
* of the options detailed above including:
* target,direction,content,width,offset
* Other settings probably won't work because we haven't needed to change them
*/
/*
* RED.popover.tooltip(target,content, action)
*
* - target : DOM element - the element to apply the tooltip to
* - content : string - the text of the tooltip
* - action : string - *optional* the name of an Action this tooltip is tied to
* For example, it 'target' is a button that triggers a particular action.
* The tooltip will include the keyboard shortcut for the action
* if one is defined
*
*/
/*
* RED.popover.menu(options)
*
* options
* - options : array - list of menu options - see below for format
* - width : number - width of the menu. Default: 'auto'
* - class : string - class to apply to the menu container
* - maxHeight : number - maximum height of menu before scrolling items. Default: none
* - onselect : function(item) - called when a menu item is selected, if that item doesn't
* have its own onselect function
* - onclose : function(cancelled) - called when the menu is closed
* - disposeOnClose : boolean - by default, the menu is discarded when it closes
* and mustbe rebuilt to redisplay. Setting this to 'false'
* keeps the menu on the DOM so it can be shown again.
*
* Menu Options array:
* [
* label : string|DOM element - the label of the item. Can be custom DOM element
* onselect : function - called when the item is selected
* ]
*
* Returns the menu object with the following functions:
*
* - options([menuItems]) - if menuItems is undefined, returns the current items.
* otherwise, sets the current menu items
* - show(opts) - shows the menu. `opts` is an object of options. See RED.popover.panel.show(opts)
* for the full list of options. In most scenarios, this just needs:
* - target : DOM element - the element to display the menu below
* - hide(cancelled) - hide the menu
*/
/*
* RED.popover.panel(content)
* Create a UI panel that can be displayed relative to any target element.
* Handles auto-closing when mouse clicks outside the panel
*
* - 'content' - DOM element to display in the panel
*
* Returns the panel object with the following functions:
*
* properties:
* - container : DOM element - the panel element
*
* functions:
* - show(opts) - show the panel.
* opts:
* - onclose : function - called when the panel closes
* - closeButton : DOM element - if the panel is closeable by a click of a button,
* by providing a reference to it here, we can
* handle the events properly to hide the panel
* - target : DOM element - the element to display the panel relative to
* - align : string - should the panel align to the left or right edge of target
* default: 'right'
* - offset : Array - px offset to apply from the target. [width, height]
* - dispose : boolean - whether the panel should be removed from DOM when hidden
* default: true
* - hide(dispose) - hide the panel.
*/
RED.popover = (function() { RED.popover = (function() {
var deltaSizes = { var deltaSizes = {
"default": { "default": {
top: 10, x: 12,
topTop: 30, y: 12
leftRight: 17,
leftLeft: 25,
leftBottom: 8,
leftTop: 11
}, },
"small": { "small": {
top: 6, x:8,
topTop: 20, y:8
leftRight: 8,
leftLeft: 26,
leftBottom: 8,
leftTop: 9
} }
} }
function createPopover(options) { function createPopover(options) {
@ -41,7 +155,9 @@ RED.popover = (function() {
var delay = options.delay || { show: 750, hide: 50 }; var delay = options.delay || { show: 750, hide: 50 };
var autoClose = options.autoClose; var autoClose = options.autoClose;
var width = options.width||"auto"; var width = options.width||"auto";
var maxWidth = options.maxWidth;
var size = options.size||"default"; var size = options.size||"default";
var popupOffset = options.offset || 0;
if (!deltaSizes[size]) { if (!deltaSizes[size]) {
throw new Error("Invalid RED.popover size value:",size); throw new Error("Invalid RED.popover size value:",size);
} }
@ -49,6 +165,8 @@ RED.popover = (function() {
var timer = null; var timer = null;
var active; var active;
var div; var div;
var contentDiv;
var currentStyle;
var openPopup = function(instant) { var openPopup = function(instant) {
if (active) { if (active) {
@ -58,6 +176,10 @@ RED.popover = (function() {
return; return;
} }
div = $('<div class="red-ui-popover"></div>'); div = $('<div class="red-ui-popover"></div>');
if (options.class) {
div.addClass(options.class);
}
contentDiv = $('<div class="red-ui-popover-content">').appendTo(div);
if (size !== "default") { if (size !== "default") {
div.addClass("red-ui-popover-size-"+size); div.addClass("red-ui-popover-size-"+size);
} }
@ -67,71 +189,23 @@ RED.popover = (function() {
return; return;
} }
if (typeof result === 'string') { if (typeof result === 'string') {
div.text(result); contentDiv.text(result);
} else { } else {
div.append(result); contentDiv.append(result);
} }
} else { } else {
div.html(content); contentDiv.html(content);
}
if (width !== "auto") {
div.width(width);
} }
div.appendTo("body"); div.appendTo("body");
var targetPos = target.offset(); movePopup({target,direction,width,maxWidth});
var targetWidth = target.outerWidth();
var targetHeight = target.outerHeight();
var divHeight = div.height();
var divWidth = div.width();
var paddingRight = 10;
var viewportTop = $(window).scrollTop();
var viewportLeft = $(window).scrollLeft();
var viewportBottom = viewportTop + $(window).height();
var viewportRight = viewportLeft + $(window).width();
var top = 0;
var left = 0;
var d = direction;
if (d === 'right') {
top = targetPos.top+targetHeight/2-divHeight/2-deltaSizes[size].top;
left = targetPos.left+targetWidth+deltaSizes[size].leftRight;
} else if (d === 'left') {
top = targetPos.top+targetHeight/2-divHeight/2-deltaSizes[size].top;
left = targetPos.left-deltaSizes[size].leftLeft-divWidth;
} else if (d === 'bottom') {
top = targetPos.top+targetHeight+deltaSizes[size].top;
left = targetPos.left+targetWidth/2-divWidth/2 - deltaSizes[size].leftBottom;
if (left < 0) {
d = "right";
top = targetPos.top+targetHeight/2-divHeight/2-deltaSizes[size].top;
left = targetPos.left+targetWidth+deltaSizes[size].leftRight;
} else if (left+divWidth+paddingRight > viewportRight) {
d = "left";
top = targetPos.top+targetHeight/2-divHeight/2-deltaSizes[size].top;
left = targetPos.left-deltaSizes[size].leftLeft-divWidth;
if (top+divHeight+targetHeight/2 + 5 > viewportBottom) {
top -= (top+divHeight+targetHeight/2 - viewportBottom + 5)
}
} else if (top+divHeight > viewportBottom) {
d = 'top';
top = targetPos.top-deltaSizes[size].topTop-divHeight;
left = targetPos.left+targetWidth/2-divWidth/2 - deltaSizes[size].leftTop;
}
} else if (d === 'top') {
top = targetPos.top-deltaSizes[size].topTop-divHeight;
left = targetPos.left+targetWidth/2-divWidth/2 - deltaSizes[size].leftTop;
if (top < 0) {
d = 'bottom';
top = targetPos.top+targetHeight+deltaSizes[size].top;
left = targetPos.left+targetWidth/2-divWidth/2 - deltaSizes[size].leftBottom;
}
}
div.addClass('red-ui-popover-'+d).css({top: top, left: left});
if (existingPopover) { if (existingPopover) {
existingPopover.close(true); existingPopover.close(true);
} }
if (options.trigger !== 'manual') {
target.data("red-ui-popover",res) target.data("red-ui-popover",res)
}
if (options.tooltip) { if (options.tooltip) {
div.on("mousedown", function(evt) { div.on("mousedown", function(evt) {
closePopup(true); closePopup(true);
@ -161,6 +235,104 @@ RED.popover = (function() {
} }
} }
} }
var movePopup = function(options) {
target = options.target || target;
direction = options.direction || direction || "right";
popupOffset = options.offset || popupOffset;
var transition = options.transition;
var width = options.width||"auto";
div.width(width);
if (options.maxWidth) {
div.css("max-width",options.maxWidth)
} else {
div.css("max-width", 'auto');
}
var targetPos = target[0].getBoundingClientRect();
var targetHeight = targetPos.height;
var targetWidth = targetPos.width;
var divHeight = div.outerHeight();
var divWidth = div.outerWidth();
var paddingRight = 10;
var viewportTop = $(window).scrollTop();
var viewportLeft = $(window).scrollLeft();
var viewportBottom = viewportTop + $(window).height();
var viewportRight = viewportLeft + $(window).width();
var top = 0;
var left = 0;
if (direction === 'right') {
top = targetPos.top+targetHeight/2-divHeight/2;
left = targetPos.left+targetWidth+deltaSizes[size].x+popupOffset;
} else if (direction === 'left') {
top = targetPos.top+targetHeight/2-divHeight/2;
left = targetPos.left-deltaSizes[size].x-divWidth-popupOffset;
} else if (direction === 'bottom') {
top = targetPos.top+targetHeight+deltaSizes[size].y+popupOffset;
left = targetPos.left+targetWidth/2-divWidth/2;
if (left < 0) {
direction = "right";
top = targetPos.top+targetHeight/2-divHeight/2;
left = targetPos.left+targetWidth+deltaSizes[size].x+popupOffset;
} else if (left+divWidth+paddingRight > viewportRight) {
direction = "left";
top = targetPos.top+targetHeight/2-divHeight/2;
left = targetPos.left-deltaSizes[size].x-divWidth-popupOffset;
if (top+divHeight+targetHeight/2 + 5 > viewportBottom) {
top -= (top+divHeight+targetHeight/2 - viewportBottom + 5)
}
} else if (top+divHeight > viewportBottom) {
direction = 'top';
top = targetPos.top-deltaSizes[size].y-divHeight-popupOffset;
left = targetPos.left+targetWidth/2-divWidth/2;
}
} else if (direction === 'top') {
top = targetPos.top-deltaSizes[size].y-divHeight-popupOffset;
left = targetPos.left+targetWidth/2-divWidth/2;
if (top < 0) {
direction = 'bottom';
top = targetPos.top+targetHeight+deltaSizes[size].y+popupOffset;
left = targetPos.left+targetWidth/2-divWidth/2;
}
} else if (/inset/.test(direction)) {
top = targetPos.top + targetHeight/2 - divHeight/2;
left = targetPos.left + targetWidth/2 - divWidth/2;
if (/bottom/.test(direction)) {
top = targetPos.top + targetHeight - divHeight-popupOffset;
}
if (/top/.test(direction)) {
top = targetPos.top+popupOffset;
}
if (/left/.test(direction)) {
left = targetPos.left+popupOffset;
}
if (/right/.test(direction)) {
left = targetPos.left + targetWidth - divWidth-popupOffset;
}
}
if (currentStyle) {
div.removeClass(currentStyle);
}
if (transition) {
div.css({
"transition": "0.6s ease",
"transition-property": "top,left,right,bottom"
})
}
currentStyle = 'red-ui-popover-'+direction;
div.addClass(currentStyle).css({top: top, left: left});
if (transition) {
setTimeout(function() {
div.css({
"transition": "none"
});
},600);
}
}
var closePopup = function(instant) { var closePopup = function(instant) {
$(document).off('mousedown.red-ui-popover'); $(document).off('mousedown.red-ui-popover');
if (!active) { if (!active) {
@ -236,8 +408,10 @@ RED.popover = (function() {
},autoClose); },autoClose);
} }
var res = { var res = {
get element() { return div },
setContent: function(_content) { setContent: function(_content) {
content = _content; content = _content;
return res; return res;
}, },
open: function (instant) { open: function (instant) {
@ -249,6 +423,10 @@ RED.popover = (function() {
active = false; active = false;
closePopup(instant); closePopup(instant);
return res; return res;
},
move: function(options) {
movePopup(options);
return
} }
} }
return res; return res;
@ -258,18 +436,17 @@ RED.popover = (function() {
return { return {
create: createPopover, create: createPopover,
tooltip: function(target,content, action) { tooltip: function(target,content, action) {
var label = function() {
var label = content; var label = content;
if (action) { if (action) {
label = function() {
var label = content;
var shortcut = RED.keyboard.getShortcut(action); var shortcut = RED.keyboard.getShortcut(action);
if (shortcut && shortcut.key) { if (shortcut && shortcut.key) {
label = $('<span>'+content+' <span class="red-ui-popover-key">'+RED.keyboard.formatKey(shortcut.key, true)+'</span></span>'); label = $('<span>'+content+' <span class="red-ui-popover-key">'+RED.keyboard.formatKey(shortcut.key, true)+'</span></span>');
} }
}
return label; return label;
} }
} var popover = RED.popover.create({
return RED.popover.create({
tooltip: true, tooltip: true,
target:target, target:target,
trigger: "hover", trigger: "hover",
@ -278,6 +455,14 @@ RED.popover = (function() {
content: label, content: label,
delay: { show: 750, hide: 50 } delay: { show: 750, hide: 50 }
}); });
popover.setContent = function(newContent) {
content = newContent;
}
popover.setAction = function(newAction) {
action = newAction;
}
return popover;
}, },
menu: function(options) { menu: function(options) {
var list = $('<ul class="red-ui-menu"></ul>'); var list = $('<ul class="red-ui-menu"></ul>');
@ -286,20 +471,47 @@ RED.popover = (function() {
} }
var menuOptions = options.options || []; var menuOptions = options.options || [];
var first; var first;
var container = RED.popover.panel(list);
if (options.width) {
container.container.width(options.width);
}
if (options.class) {
container.container.addClass(options.class);
}
if (options.maxHeight) {
container.container.css({
"max-height": options.maxHeight,
"overflow-y": 'auto'
})
}
var menu = {
options: function(opts) {
if (opts === undefined) {
return menuOptions
}
menuOptions = opts || [];
list.empty();
menuOptions.forEach(function(opt) { menuOptions.forEach(function(opt) {
var item = $('<li>').appendTo(list); var item = $('<li>').appendTo(list);
var link = $('<a href="#"></a>').text(opt.label).appendTo(item); var link = $('<a href="#"></a>').appendTo(item);
if (typeof opt.label == "string") {
link.text(opt.label)
} else if (opt.label){
opt.label.appendTo(link);
}
link.on("click", function(evt) { link.on("click", function(evt) {
evt.preventDefault(); evt.preventDefault();
if (opt.onselect) { if (opt.onselect) {
opt.onselect(); opt.onselect();
} else if (options.onselect) {
options.onselect(opt);
} }
menu.hide(); menu.hide();
}) })
if (!first) { first = link} if (!first) { first = link}
}) })
var container = RED.popover.panel(list); },
var menu = {
show: function(opts) { show: function(opts) {
$(document).on("keydown.red-ui-menu", function(evt) { $(document).on("keydown.red-ui-menu", function(evt) {
var currentItem = list.find(":focus").parent(); var currentItem = list.find(":focus").parent();
@ -333,6 +545,11 @@ RED.popover = (function() {
// ESCAPE // ESCAPE
evt.preventDefault(); evt.preventDefault();
menu.hide(true); menu.hide(true);
} else if (evt.keyCode === 9 && options.tabSelect) {
// TAB - with tabSelect enabled
evt.preventDefault();
currentItem.find("a").trigger("click");
} }
evt.stopPropagation(); evt.stopPropagation();
}) })
@ -352,6 +569,7 @@ RED.popover = (function() {
} }
} }
} }
menu.options(menuOptions);
return menu; return menu;
}, },
panel: function(content) { panel: function(content) {
@ -380,12 +598,12 @@ RED.popover = (function() {
var pos = target.offset(); var pos = target.offset();
var targetWidth = target.width(); var targetWidth = target.width();
var targetHeight = target.height(); var targetHeight = target.outerHeight();
var panelHeight = panel.height(); var panelHeight = panel.height();
var panelWidth = panel.width(); var panelWidth = panel.width();
var top = (targetHeight+pos.top) + offset[1]; var top = (targetHeight+pos.top) + offset[1];
if (top+panelHeight > $(window).height()) { if (top+panelHeight-$(document).scrollTop() > $(window).height()) {
top -= (top+panelHeight)-$(window).height() + 5; top -= (top+panelHeight)-$(window).height() + 5;
} }
if (top < 0) { if (top < 0) {

View File

@ -38,6 +38,7 @@ RED.tabs = (function() {
if (options.vertical) { if (options.vertical) {
wrapper.addClass("red-ui-tabs-vertical"); wrapper.addClass("red-ui-tabs-vertical");
} }
if (options.addButton) { if (options.addButton) {
wrapper.addClass("red-ui-tabs-add"); wrapper.addClass("red-ui-tabs-add");
var addButton = $('<div class="red-ui-tab-button red-ui-tabs-add"><a href="#"><i class="fa fa-plus"></i></a></div>').appendTo(wrapper); var addButton = $('<div class="red-ui-tab-button red-ui-tabs-add"><a href="#"><i class="fa fa-plus"></i></a></div>').appendTo(wrapper);
@ -75,6 +76,8 @@ RED.tabs = (function() {
}); });
} }
if (options.searchButton) { if (options.searchButton) {
// This is soft-deprecated as we don't use this in the core anymore
// We no use the `menu` option to provide a drop-down list of actions
wrapper.addClass("red-ui-tabs-search"); wrapper.addClass("red-ui-tabs-search");
var searchButton = $('<div class="red-ui-tab-button red-ui-tabs-search"><a href="#"><i class="fa fa-list-ul"></i></a></div>').appendTo(wrapper); var searchButton = $('<div class="red-ui-tab-button red-ui-tabs-search"><a href="#"><i class="fa fa-list-ul"></i></a></div>').appendTo(wrapper);
searchButton.find('a').on("click", function(evt) { searchButton.find('a').on("click", function(evt) {
@ -94,6 +97,50 @@ RED.tabs = (function() {
} }
} }
if (options.menu) {
wrapper.addClass("red-ui-tabs-menu");
var menuButton = $('<div class="red-ui-tab-button red-ui-tabs-menu"><a href="#"><i class="fa fa-caret-down"></i></a></div>').appendTo(wrapper);
var menuButtonLink = menuButton.find('a')
var menuOpen = false;
var menu;
menuButtonLink.on("click", function(evt) {
evt.stopPropagation();
evt.preventDefault();
if (menuOpen) {
menu.remove();
menuOpen = false;
return;
}
menuOpen = true;
var menuOptions = [];
if (typeof options.searchButton === 'function') {
menuOptions = options.menu()
} else if (Array.isArray(options.menu)) {
menuOptions = options.menu;
}
menu = RED.menu.init({options: menuOptions});
menu.attr("id",options.id+"-menu");
menu.css({
position: "absolute"
})
menu.appendTo("body");
var elementPos = menuButton.offset();
menu.css({
top: (elementPos.top+menuButton.height()-2)+"px",
left: (elementPos.left - menu.width() + menuButton.width())+"px"
})
$(".red-ui-menu.red-ui-menu-dropdown").hide();
$(document).on("click.red-ui-tabmenu", function(evt) {
$(document).off("click.red-ui-tabmenu");
menuOpen = false;
menu.remove();
});
menu.show();
})
}
var scrollLeft; var scrollLeft;
var scrollRight; var scrollRight;
@ -117,9 +164,9 @@ RED.tabs = (function() {
} }
}) })
scrollLeft = $('<div class="red-ui-tab-button red-ui-tab-scroll red-ui-tab-scroll-left"><a href="#" style="display:none;"><i class="fa fa-caret-left"></i></a></div>').appendTo(wrapper).find("a"); scrollLeft = $('<div class="red-ui-tab-button red-ui-tab-scroll red-ui-tab-scroll-left"><a href="#" style="display:none;"><i class="fa fa-caret-left"></i></a></div>').appendTo(wrapper).find("a");
scrollLeft.on('mousedown',function(evt) { scrollEventHandler(evt,'-=150') }).on('click',function(evt){ evt.preventDefault();}); scrollLeft.on('mousedown',function(evt) {scrollEventHandler(evt, evt.shiftKey?('-='+scrollContainer.scrollLeft()):'-=150') }).on('click',function(evt){ evt.preventDefault();});
scrollRight = $('<div class="red-ui-tab-button red-ui-tab-scroll red-ui-tab-scroll-right"><a href="#" style="display:none;"><i class="fa fa-caret-right"></i></a></div>').appendTo(wrapper).find("a"); scrollRight = $('<div class="red-ui-tab-button red-ui-tab-scroll red-ui-tab-scroll-right"><a href="#" style="display:none;"><i class="fa fa-caret-right"></i></a></div>').appendTo(wrapper).find("a");
scrollRight.on('mousedown',function(evt) { scrollEventHandler(evt,'+=150') }).on('click',function(evt){ evt.preventDefault();}); scrollRight.on('mousedown',function(evt) { scrollEventHandler(evt,evt.shiftKey?('+='+(scrollContainer[0].scrollWidth - scrollContainer.width()-scrollContainer.scrollLeft())):'+=150') }).on('click',function(evt){ evt.preventDefault();});
} }
if (options.collapsible) { if (options.collapsible) {
@ -337,6 +384,12 @@ RED.tabs = (function() {
if (link.length === 0) { if (link.length === 0) {
return; return;
} }
if (link.parent().hasClass("hide-tab")) {
link.parent().removeClass("hide-tab").removeClass("hide");
if (options.onshow) {
options.onshow(tabs[link.attr('href').slice(1)])
}
}
if (!link.parent().hasClass("active")) { if (!link.parent().hasClass("active")) {
ul.children().removeClass("active"); ul.children().removeClass("active");
ul.children().css({"transition": "width 100ms"}); ul.children().css({"transition": "width 100ms"});
@ -362,13 +415,13 @@ RED.tabs = (function() {
} }
} }
function activatePreviousTab() { function activatePreviousTab() {
var previous = ul.find("li.active").prev(); var previous = findPreviousVisibleTab();
if (previous.length > 0) { if (previous.length > 0) {
activateTab(previous.find("a")); activateTab(previous.find("a"));
} }
} }
function activateNextTab() { function activateNextTab() {
var next = ul.find("li.active").next(); var next = findNextVisibleTab();
if (next.length > 0) { if (next.length > 0) {
activateTab(next.find("a")); activateTab(next.find("a"));
} }
@ -378,7 +431,9 @@ RED.tabs = (function() {
if (options.vertical) { if (options.vertical) {
return; return;
} }
var tabs = ul.find("li.red-ui-tab"); var allTabs = ul.find("li.red-ui-tab");
var tabs = allTabs.filter(":not(.hide-tab)");
var hiddenTabs = allTabs.filter(".hide-tab");
var width = wrapper.width(); var width = wrapper.width();
var tabCount = tabs.length; var tabCount = tabs.length;
var tabWidth; var tabWidth;
@ -446,6 +501,7 @@ RED.tabs = (function() {
// } // }
tabs.css({width:currentTabWidth}); tabs.css({width:currentTabWidth});
hiddenTabs.css({width:"0px"});
if (tabWidth < 50) { if (tabWidth < 50) {
// ul.find(".red-ui-tab-close").hide(); // ul.find(".red-ui-tab-close").hide();
ul.find(".red-ui-tab-icon").hide(); ul.find(".red-ui-tab-icon").hide();
@ -486,12 +542,20 @@ RED.tabs = (function() {
} }
var li = ul.find("a[href='#"+id+"']").parent(); var li = ul.find("a[href='#"+id+"']").parent();
if (li.hasClass("active")) { if (li.hasClass("active")) {
var tab = li.prev(); var tab = findPreviousVisibleTab(li);
if (tab.length === 0) { if (tab.length === 0) {
tab = li.next(); tab = findNextVisibleTab(li);
} }
if (tab.length > 0) {
activateTab(tab.find("a")); activateTab(tab.find("a"));
} else {
if (options.onchange) {
options.onchange(null);
} }
}
}
li.one("transitionend", function(evt) {
li.remove(); li.remove();
if (tabs[id].pinned) { if (tabs[id].pinned) {
pinnedTabsCount--; pinnedTabsCount--;
@ -505,6 +569,78 @@ RED.tabs = (function() {
collapsibleMenu.remove(); collapsibleMenu.remove();
collapsibleMenu = null; collapsibleMenu = null;
} }
})
li.addClass("hide-tab");
li.width(0);
}
function findPreviousVisibleTab(li) {
if (!li) {
li = ul.find("li.active").parent();
}
var previous = li.prev();
while(previous.length > 0 && previous.hasClass("hide-tab")) {
previous = previous.prev();
}
return previous;
}
function findNextVisibleTab(li) {
if (!li) {
li = ul.find("li.active").parent();
}
var next = ul.find("li.active").next();
while(next.length > 0 && next.hasClass("hide-tab")) {
next = next.next();
}
return next;
}
function showTab(id) {
if (tabs[id]) {
var li = ul.find("a[href='#"+id+"']").parent();
if (li.hasClass("hide-tab")) {
li.removeClass("hide-tab").removeClass("hide");
if (ul.find("li.red-ui-tab:not(.hide-tab)").length === 1) {
activateTab(li.find("a"))
}
updateTabWidths();
if (options.onshow) {
options.onshow(tabs[id])
}
}
}
}
function hideTab(id) {
if (tabs[id]) {
var li = ul.find("a[href='#"+id+"']").parent();
if (!li.hasClass("hide-tab")) {
if (li.hasClass("active")) {
var tab = findPreviousVisibleTab(li);
if (tab.length === 0) {
tab = findNextVisibleTab(li);
}
if (tab.length > 0) {
activateTab(tab.find("a"));
} else {
if (options.onchange) {
options.onchange(null);
}
}
}
li.removeClass("active");
li.one("transitionend", function(evt) {
li.addClass("hide");
updateTabWidths();
if (options.onhide) {
options.onhide(tabs[id])
}
setTimeout(function() {
updateScroll()
},200)
})
li.addClass("hide-tab");
li.css({width:0})
}
}
} }
var tabAPI = { var tabAPI = {
@ -663,7 +799,6 @@ RED.tabs = (function() {
link.on("click", function(evt) { evt.preventDefault(); }) link.on("click", function(evt) { evt.preventDefault(); })
link.on("dblclick", function(evt) { evt.stopPropagation(); evt.preventDefault(); }) link.on("dblclick", function(evt) { evt.stopPropagation(); evt.preventDefault(); })
$('<span class="red-ui-tabs-fade"></span>').appendTo(li); $('<span class="red-ui-tabs-fade"></span>').appendTo(li);
if (tab.closeable) { if (tab.closeable) {
@ -675,6 +810,15 @@ RED.tabs = (function() {
removeTab(tab.id); removeTab(tab.id);
}); });
} }
if (tab.hideable) {
li.addClass("red-ui-tabs-closeable")
var closeLink = $("<a/>",{href:"#",class:"red-ui-tab-close"}).appendTo(li);
closeLink.append('<i class="fa fa-times" />');
closeLink.on("click",function(event) {
event.preventDefault();
hideTab(tab.id);
});
}
var badges = $('<span class="red-ui-tabs-badges"></span>').appendTo(li); var badges = $('<span class="red-ui-tabs-badges"></span>').appendTo(li);
if (options.onselect) { if (options.onselect) {
@ -682,11 +826,11 @@ RED.tabs = (function() {
$('<i class="red-ui-tabs-badge-selected fa fa-check-circle"></i>').appendTo(badges); $('<i class="red-ui-tabs-badge-selected fa fa-check-circle"></i>').appendTo(badges);
} }
link.attr("title",tab.label);
if (options.onadd) { if (options.onadd) {
options.onadd(tab); options.onadd(tab);
} }
link.attr("title",tab.label);
if (ul.find("li.red-ui-tab").length == 1) { if (ul.find("li.red-ui-tab").length == 1) {
activateTab(link); activateTab(link);
} }
@ -787,7 +931,7 @@ RED.tabs = (function() {
previousTab: activatePreviousTab, previousTab: activatePreviousTab,
resize: updateTabWidths, resize: updateTabWidths,
count: function() { count: function() {
return ul.find("li.red-ui-tab").length; return ul.find("li.red-ui-tab:not(.hide)").length;
}, },
activeIndex: function() { activeIndex: function() {
return ul.find("li.active").index() return ul.find("li.active").index()
@ -795,6 +939,9 @@ RED.tabs = (function() {
contains: function(id) { contains: function(id) {
return ul.find("a[href='#"+id+"']").length > 0; return ul.find("a[href='#"+id+"']").length > 0;
}, },
showTab: showTab,
hideTab: hideTab,
renameTab: function(id,label) { renameTab: function(id,label) {
tabs[id].label = label; tabs[id].label = label;
var tab = ul.find("a[href='#"+id+"']"); var tab = ul.find("a[href='#"+id+"']");
@ -802,7 +949,20 @@ RED.tabs = (function() {
tab.find("span.red-ui-text-bidi-aware").text(label).attr('dir', RED.text.bidi.resolveBaseTextDir(label)); tab.find("span.red-ui-text-bidi-aware").text(label).attr('dir', RED.text.bidi.resolveBaseTextDir(label));
updateTabWidths(); updateTabWidths();
}, },
listTabs: function() {
return $.makeArray(ul.children().map(function() { return $(this).data('tabId');}));
},
selection: getSelection, selection: getSelection,
clearSelection: function() {
if (options.onselect) {
var selection = ul.find("li.red-ui-tab.selected");
if (selection.length > 0) {
selection.removeClass("selected");
selectionChanged();
}
}
},
order: function(order) { order: function(order) {
preferredOrder = order; preferredOrder = order;
var existingTabOrder = $.makeArray(ul.children().map(function() { return $(this).data('tabId');})); var existingTabOrder = $.makeArray(ul.children().map(function() { return $(this).data('tabId');}));

View File

@ -24,6 +24,9 @@
* - rootSortable: boolean - if 'sortable' is set, then setting this to * - rootSortable: boolean - if 'sortable' is set, then setting this to
* false, prevents items being sorted to the * false, prevents items being sorted to the
* top level of the tree * top level of the tree
* - autoSelect: boolean - default true - triggers item selection when navigating
* list by keyboard. If the list has checkboxed items
* you probably want to set this to false
* *
* methods: * methods:
* - data(items) - clears existing items and replaces with new data * - data(items) - clears existing items and replaces with new data
@ -41,6 +44,7 @@
* sublabel: 'Local', // a sub-label for the item * sublabel: 'Local', // a sub-label for the item
* icon: 'fa fa-rocket', // (optional) icon for the item * icon: 'fa fa-rocket', // (optional) icon for the item
* checkbox: true/false, // (optional) if present, display checkbox accordingly * checkbox: true/false, // (optional) if present, display checkbox accordingly
* radio: 'group-name', // (optional) if present, display radio box - using group-name to set radio group
* selected: true/false, // (optional) whether the item is selected or not * selected: true/false, // (optional) whether the item is selected or not
* children: [] | function(done,item) // (optional) an array of child items, or a function * children: [] | function(done,item) // (optional) an array of child items, or a function
* // that will call the `done` callback with an array * // that will call the `done` callback with an array
@ -49,6 +53,7 @@
* deferBuild: true/false, // don't build any ui elements for the item's children * deferBuild: true/false, // don't build any ui elements for the item's children
* until it is expanded by the user. * until it is expanded by the user.
* element: // custom dom element to use for the item - ignored if `label` is set * element: // custom dom element to use for the item - ignored if `label` is set
* collapsible: true/false, // prevent a parent item from being collapsed. default true.
* } * }
* ] * ]
* *
@ -89,77 +94,99 @@
$.widget( "nodered.treeList", { $.widget( "nodered.treeList", {
_create: function() { _create: function() {
var that = this; var that = this;
var autoSelect = true;
if (that.options.autoSelect === false) {
autoSelect = false;
}
this.element.addClass('red-ui-treeList'); this.element.addClass('red-ui-treeList');
this.element.attr("tabIndex",0); this.element.attr("tabIndex",0);
var wrapper = $('<div>',{class:'red-ui-treeList-container'}).appendTo(this.element); var wrapper = $('<div>',{class:'red-ui-treeList-container'}).appendTo(this.element);
this.element.on('keydown', function(evt) { this.element.on('keydown', function(evt) {
var selected = that._topList.find(".selected").parent().data('data'); var focussed = that._topList.find(".focus").parent().data('data');
if (!selected && (evt.keyCode === 40 || evt.keyCode === 38)) { if (!focussed && (evt.keyCode === 40 || evt.keyCode === 38)) {
if (that._data[0]) {
if (autoSelect) {
that.select(that._data[0]); that.select(that._data[0]);
} else {
that._topList.find(".focus").removeClass("focus")
}
that._data[0].treeList.label.addClass('focus')
}
return; return;
} }
var target; var target;
switch(evt.keyCode) { switch(evt.keyCode) {
case 32: // SPACE
case 13: // ENTER case 13: // ENTER
if (evt.altKey || evt.ctrlKey || evt.metaKey || evt.shiftKey) {
return
}
evt.preventDefault(); evt.preventDefault();
evt.stopPropagation(); evt.stopPropagation();
if (selected.children) { if (focussed.checkbox) {
if (selected.treeList.container.hasClass("expanded")) { focussed.treeList.checkbox.trigger("click");
selected.treeList.collapse() } else if (focussed.radio) {
focussed.treeList.radio.trigger("click");
} else if (focussed.children) {
if (focussed.treeList.container.hasClass("expanded")) {
focussed.treeList.collapse()
} else { } else {
selected.treeList.expand() focussed.treeList.expand()
} }
} else { } else {
that._trigger("confirm",null,selected) that._trigger("confirm",null,focussed)
} }
break; break;
case 37: // LEFT case 37: // LEFT
evt.preventDefault(); evt.preventDefault();
evt.stopPropagation(); evt.stopPropagation();
if (selected.children&& selected.treeList.container.hasClass("expanded")) { if (focussed.children&& focussed.treeList.container.hasClass("expanded")) {
selected.treeList.collapse() focussed.treeList.collapse()
} else if (selected.parent) { } else if (focussed.parent) {
target = selected.parent; target = focussed.parent;
} }
break; break;
case 38: // UP case 38: // UP
evt.preventDefault(); evt.preventDefault();
evt.stopPropagation(); evt.stopPropagation();
target = that._getPreviousSibling(selected); target = that._getPreviousSibling(focussed);
if (target) { if (target) {
target = that._getLastDescendant(target); target = that._getLastDescendant(target);
} }
if (!target && selected.parent) { if (!target && focussed.parent) {
target = selected.parent; target = focussed.parent;
} }
break; break;
case 39: // RIGHT case 39: // RIGHT
evt.preventDefault(); evt.preventDefault();
evt.stopPropagation(); evt.stopPropagation();
if (selected.children) { if (focussed.children) {
if (!selected.treeList.container.hasClass("expanded")) { if (!focussed.treeList.container.hasClass("expanded")) {
selected.treeList.expand() focussed.treeList.expand()
} }
} }
break break
case 40: //DOWN case 40: //DOWN
evt.preventDefault(); evt.preventDefault();
evt.stopPropagation(); evt.stopPropagation();
if (selected.children && Array.isArray(selected.children) && selected.children.length > 0 && selected.treeList.container.hasClass("expanded")) { if (focussed.children && Array.isArray(focussed.children) && focussed.children.length > 0 && focussed.treeList.container.hasClass("expanded")) {
target = selected.children[0]; target = focussed.children[0];
} else { } else {
target = that._getNextSibling(selected); target = that._getNextSibling(focussed);
while (!target && selected.parent) { while (!target && focussed.parent) {
selected = selected.parent; focussed = focussed.parent;
target = that._getNextSibling(selected); target = that._getNextSibling(focussed);
} }
} }
break break
} }
if (target) { if (target) {
if (autoSelect) {
that.select(target); that.select(target);
} else {
that._topList.find(".focus").removeClass("focus")
}
target.treeList.label.addClass('focus')
} }
}); });
this._data = []; this._data = [];
@ -462,6 +489,9 @@
container.addClass("expanded"); container.addClass("expanded");
} }
item.treeList.collapse = function() { item.treeList.collapse = function() {
if (item.collapsible === false) {
return
}
if (!item.children) { if (!item.children) {
return; return;
} }
@ -532,10 +562,11 @@
}).appendTo(label) }).appendTo(label)
} }
var labelPaddingWidth = (item.gutter?item.gutter.width()+2:0)+(depth*20); // var labelPaddingWidth = (item.gutter?item.gutter.width()+2:0)+(depth*20);
// var labelPaddingWidth = (item.gutter ? item.gutter[0].offsetWidth + 2 : 0) + (depth * 20) var labelPaddingWidth = (item.gutter ? item.gutter[0].offsetWidth + 2 : 0) + (depth * 20)
item.treeList.labelPadding = $('<span>').css({ item.treeList.labelPadding = $('<span>').css({
display: "inline-block", display: "inline-block",
"flex-shrink": 0,
width: labelPaddingWidth+'px' width: labelPaddingWidth+'px'
}).appendTo(label); }).appendTo(label);
@ -581,7 +612,7 @@
// Already a parent because we've got the angle-right icon // Already a parent because we've got the angle-right icon
return; return;
} }
$('<i class="fa fa-angle-right" />').appendTo(treeListIcon); $('<i class="fa fa-angle-right" />').toggleClass("hide",item.collapsible === false).appendTo(treeListIcon);
treeListIcon.on("click.red-ui-treeList-expand", function(e) { treeListIcon.on("click.red-ui-treeList-expand", function(e) {
e.stopPropagation(); e.stopPropagation();
e.preventDefault(); e.preventDefault();
@ -632,6 +663,46 @@
label.on("click", function(e) { label.on("click", function(e) {
e.stopPropagation(); e.stopPropagation();
cb.trigger("click"); cb.trigger("click");
that._topList.find(".focus").removeClass("focus")
label.addClass('focus')
})
}
item.treeList.select = function(v) {
if (v !== item.selected) {
cb.trigger("click");
}
}
item.treeList.checkbox = cb;
selectWrapper.appendTo(label)
} else if (item.radio) {
var selectWrapper = $('<span class="red-ui-treeList-icon"></span>');
var cb = $('<input class="red-ui-treeList-radio" type="radio">').prop('name', item.radio).prop('checked',item.selected).appendTo(selectWrapper);
cb.on('click', function(e) {
e.stopPropagation();
});
cb.on('change', function(e) {
item.selected = this.checked;
that._selected.forEach(function(selectedItem) {
if (selectedItem.radio === item.radio) {
selectedItem.treeList.label.removeClass("selected");
selectedItem.selected = false;
that._selected.delete(selectedItem);
}
})
if (item.selected) {
that._selected.add(item);
} else {
that._selected.delete(item);
}
label.toggleClass("selected",this.checked);
that._trigger("select",e,item);
})
if (!item.children) {
label.on("click", function(e) {
e.stopPropagation();
cb.trigger("click");
that._topList.find(".focus").removeClass("focus")
label.addClass('focus')
}) })
} }
item.treeList.select = function(v) { item.treeList.select = function(v) {
@ -640,6 +711,7 @@
} }
} }
selectWrapper.appendTo(label) selectWrapper.appendTo(label)
item.treeList.radio = cb;
} else { } else {
label.on("click", function(e) { label.on("click", function(e) {
if (!that.options.multi) { if (!that.options.multi) {
@ -647,10 +719,14 @@
} }
label.addClass("selected"); label.addClass("selected");
that._selected.add(item); that._selected.add(item);
that._topList.find(".focus").removeClass("focus")
label.addClass('focus')
that._trigger("select",e,item) that._trigger("select",e,item)
}) })
label.on("dblclick", function(e) { label.on("dblclick", function(e) {
that._topList.find(".focus").removeClass("focus")
label.addClass('focus')
if (!item.children) { if (!item.children) {
that._trigger("confirm",e,item); that._trigger("confirm",e,item);
} }
@ -798,6 +874,9 @@
if (item.treeList.label) { if (item.treeList.label) {
item.treeList.label.addClass("selected"); item.treeList.label.addClass("selected");
} }
that._topList.find(".focus").removeClass("focus");
if (triggerEvent !== false) { if (triggerEvent !== false) {
this._trigger("select",null,item) this._trigger("select",null,item)
} }
@ -805,6 +884,9 @@
clearSelection: function() { clearSelection: function() {
this._selected.forEach(function(item) { this._selected.forEach(function(item) {
item.selected = false; item.selected = false;
if (item.treeList.checkbox) {
item.treeList.checkbox.prop('checked',false)
}
if (item.treeList.label) { if (item.treeList.label) {
item.treeList.label.removeClass("selected") item.treeList.label.removeClass("selected")
} }

View File

@ -53,8 +53,88 @@
} }
return icon; return icon;
} }
var autoComplete = function(options) {
return function(val) {
var matches = [];
options.forEach(opt => {
let v = opt.value;
var i = v.toLowerCase().indexOf(val.toLowerCase());
if (i > -1) {
var pre = v.substring(0,i);
var matchedVal = v.substring(i,i+val.length);
var post = v.substring(i+val.length)
var el = $('<div/>',{style:"white-space:nowrap; overflow: hidden; flex-grow:1"});
$('<span/>').text(pre).appendTo(el);
$('<span/>',{style:"font-weight: bold"}).text(matchedVal).appendTo(el);
$('<span/>').text(post).appendTo(el);
var element = $('<div>',{style: "display: flex"});
el.appendTo(element);
if (opt.source) {
$('<div>').css({
"font-size": "0.8em"
}).text(opt.source.join(",")).appendTo(element);
}
matches.push({
value: v,
label: element,
i:i
})
}
})
matches.sort(function(A,B){return A.i-B.i})
return matches;
}
}
// This is a hand-generated list of completions for the core nodes (based on the node help html).
var msgCompletions = [
{ value: "payload" },
{ value: "req", source: ["http in"]},
{ value: "req.body", source: ["http in"]},
{ value: "req.headers", source: ["http in"]},
{ value: "req.query", source: ["http in"]},
{ value: "req.params", source: ["http in"]},
{ value: "req.cookies", source: ["http in"]},
{ value: "req.files", source: ["http in"]},
{ value: "complete", source: ["join"] },
{ value: "contentType", source: ["mqtt"] },
{ value: "cookies", source: ["http in","http request"] },
{ value: "correlationData", source: ["mqtt"] },
{ value: "delay", source: ["delay","trigger"] },
{ value: "encoding", source: ["file"] },
{ value: "error", source: ["catch"] },
{ value: "filename", source: ["file","file in"] },
{ value: "flush", source: ["delay"] },
{ value: "followRedirects", source: ["http request"] },
{ value: "headers", source: ["http in"," http request"] },
{ value: "kill", source: ["exec"] },
{ value: "messageExpiryInterval", source: ["mqtt"] },
{ value: "method", source: ["http-request"] },
{ value: "options", source: ["xml"] },
{ value: "parts", source: ["split","join"] },
{ value: "pid", source: ["exec"] },
{ value: "qos", source: ["mqtt"] },
{ value: "rate", source: ["delay"] },
{ value: "rejectUnauthorized", source: ["http request"] },
{ value: "requestTimeout", source: ["http request"] },
{ value: "reset", source: ["delay","trigger","join","rbe"] },
{ value: "responseTopic", source: ["mqtt"] },
{ value: "restartTimeout", source: ["join"] },
{ value: "retain", source: ["mqtt"] },
{ value: "select", source: ["html"] },
{ value: "statusCode", source: ["http in"] },
{ value: "template", source: ["template"] },
{ value: "toFront", source: ["delay"] },
{ value: "topic", source: ["inject","mqtt","rbe"] },
{ value: "url", source: ["http request"] },
{ value: "userProperties", source: ["mqtt"] }
]
var allOptions = { var allOptions = {
msg: {value:"msg",label:"msg.",validate:RED.utils.validatePropertyExpression}, msg: {value:"msg",label:"msg.",validate:RED.utils.validatePropertyExpression, autoComplete: autoComplete(msgCompletions)},
flow: {value:"flow",label:"flow.",hasValue:true, flow: {value:"flow",label:"flow.",hasValue:true,
options:[], options:[],
validate:RED.utils.validatePropertyExpression, validate:RED.utils.validatePropertyExpression,
@ -265,6 +345,47 @@
} }
} }
}; };
// For a type with options, check value is a valid selection
// If !opt.multiple, returns the valid option object
// if opt.multiple, returns an array of valid option objects
// If not valid, returns null;
function isOptionValueValid(opt, currentVal) {
if (!opt.multiple) {
for (var i=0;i<opt.options.length;i++) {
op = opt.options[i];
if (typeof op === "string" && op === currentVal) {
return {value:currentVal}
} else if (op.value === currentVal) {
return op;
}
}
} else {
// Check to see if value is a valid csv of
// options.
var currentValues = {};
var selected = [];
currentVal.split(",").forEach(function(v) {
if (v) {
currentValues[v] = true;
}
});
for (var i=0;i<opt.options.length;i++) {
op = opt.options[i];
var val = typeof op === "string" ? op : op.value;
if (currentValues.hasOwnProperty(val)) {
delete currentValues[val];
selected.push(typeof op === "string" ? {value:op} : op.value)
}
}
if (!$.isEmptyObject(currentValues)) {
return null;
}
return selected
}
}
var nlsd = false; var nlsd = false;
$.widget( "nodered.typedInput", { $.widget( "nodered.typedInput", {
@ -328,6 +449,8 @@
}); });
this.defaultInputType = this.input.attr('type'); this.defaultInputType = this.input.attr('type');
// Used to remember selections per-type to restore them when switching between types
this.oldValues = {};
this.uiSelect.addClass("red-ui-typedInput-container"); this.uiSelect.addClass("red-ui-typedInput-container");
@ -380,6 +503,9 @@
that.element.trigger('paste',evt); that.element.trigger('paste',evt);
}); });
this.input.on('keydown', function(evt) { this.input.on('keydown', function(evt) {
if (that.typeMap[that.propertyType].autoComplete) {
return
}
if (evt.keyCode >= 37 && evt.keyCode <= 40) { if (evt.keyCode >= 37 && evt.keyCode <= 40) {
evt.stopPropagation(); evt.stopPropagation();
} }
@ -428,6 +554,7 @@
this.optionExpandButton = $('<button tabindex="0" class="red-ui-typedInput-option-expand" style="display:inline-block"></button>').appendTo(this.uiSelect); this.optionExpandButton = $('<button tabindex="0" class="red-ui-typedInput-option-expand" style="display:inline-block"></button>').appendTo(this.uiSelect);
this.optionExpandButtonIcon = $('<i class="red-ui-typedInput-icon fa fa-ellipsis-h"></i>').appendTo(this.optionExpandButton); this.optionExpandButtonIcon = $('<i class="red-ui-typedInput-icon fa fa-ellipsis-h"></i>').appendTo(this.optionExpandButton);
this.type(this.options.default||this.typeList[0].value); this.type(this.options.default||this.typeList[0].value);
}catch(err) { }catch(err) {
console.log(err.stack); console.log(err.stack);
@ -579,7 +706,7 @@
var height = relativeTo.height(); var height = relativeTo.height();
var menuHeight = menu.height(); var menuHeight = menu.height();
var top = (height+pos.top); var top = (height+pos.top);
if (top+menuHeight > $(window).height()) { if (top+menuHeight-$(document).scrollTop() > $(window).height()) {
top -= (top+menuHeight)-$(window).height()+5; top -= (top+menuHeight)-$(window).height()+5;
} }
if (top < 0) { if (top < 0) {
@ -688,8 +815,10 @@
}); });
if (this.typeList.length < 2) { if (this.typeList.length < 2) {
this.selectTrigger.attr("tabindex", -1) this.selectTrigger.attr("tabindex", -1)
this.selectTrigger.on("mousedown.red-ui-typedInput-focus-block", function(evt) { evt.preventDefault(); })
} else { } else {
this.selectTrigger.attr("tabindex", 0) this.selectTrigger.attr("tabindex", 0)
this.selectTrigger.off("mousedown.red-ui-typedInput-focus-block")
} }
this.selectTrigger.toggleClass("disabled", this.typeList.length === 1); this.selectTrigger.toggleClass("disabled", this.typeList.length === 1);
this.selectTrigger.find(".fa-caret-down").toggle(this.typeList.length > 1) this.selectTrigger.find(".fa-caret-down").toggle(this.typeList.length > 1)
@ -703,6 +832,11 @@
this.propertyType = null; this.propertyType = null;
this.type(currentType); this.type(currentType);
} }
if (this.typeList.length === 1 && !this.typeList[0].icon && (!this.typeList[0].label || this.typeList[0].showLabel === false)) {
this.selectTrigger.hide()
} else {
this.selectTrigger.show()
}
}, },
width: function(desiredWidth) { width: function(desiredWidth) {
this.uiWidth = desiredWidth; this.uiWidth = desiredWidth;
@ -765,8 +899,51 @@
return this.propertyType; return this.propertyType;
} else { } else {
var that = this; var that = this;
var previousValue = null;
var opt = this.typeMap[type]; var opt = this.typeMap[type];
if (opt && this.propertyType !== type) { if (opt && this.propertyType !== type) {
// If previousType is !null, then this is a change of the type, rather than the initialisation
var previousType = this.typeMap[this.propertyType];
var typeChanged = !!previousType;
previousValue = this.input.val();
if (typeChanged) {
if (previousType.options && opt.hasValue !== true) {
this.oldValues[previousType.value] = previousValue;
} else if (previousType.hasValue === false) {
this.oldValues[previousType.value] = previousValue;
} else {
this.oldValues["_"] = previousValue;
}
if ((opt.options && opt.hasValue !== true) || opt.hasValue === false) {
if (this.oldValues.hasOwnProperty(opt.value)) {
this.input.val(this.oldValues[opt.value]);
} else {
// No old value for the option type.
// It is possible code has called 'value' then 'type'
// to set the selected option. This is what the Inject/Switch/Change
// nodes did before 2.1.
// So we need to be careful to not reset the value if it is a valid option.
var validOptions = isOptionValueValid(opt,previousValue);
if (previousValue && validOptions) {
this.input.val(previousValue);
} else {
if (typeof opt.default === "string") {
this.input.val(opt.default);
} else if (Array.isArray(opt.default)) {
this.input.val(opt.default.join(","))
} else {
this.input.val("");
}
}
}
} else {
this.input.val(this.oldValues.hasOwnProperty("_")?this.oldValues["_"]:(opt.default||""))
}
if (previousType.autoComplete) {
this.input.autoComplete("destroy");
}
}
this.propertyType = type; this.propertyType = type;
if (this.typeField) { if (this.typeField) {
this.typeField.val(type); this.typeField.val(type);
@ -836,22 +1013,12 @@
var op; var op;
if (!opt.hasValue) { if (!opt.hasValue) {
var validValue = false; // Check the value is valid for the available options
var currentVal = this.input.val(); var validValues = isOptionValueValid(opt,this.input.val());
if (!opt.multiple) { if (!opt.multiple) {
for (var i=0;i<opt.options.length;i++) { if (validValues) {
op = opt.options[i]; that._updateOptionSelectLabel(validValues)
if (typeof op === "string" && op === currentVal) { } else {
that._updateOptionSelectLabel({value:currentVal});
validValue = true;
break;
} else if (op.value === currentVal) {
that._updateOptionSelectLabel(op);
validValue = true;
break;
}
}
if (!validValue) {
op = opt.options[0]; op = opt.options[0];
if (typeof op === "string") { if (typeof op === "string") {
this.value(op); this.value(op);
@ -862,22 +1029,13 @@
} }
} }
} else { } else {
// Check to see if value is a valid csv of if (!validValues) {
// options. validValues = (opt.default || []).map(function(v) {
var currentValues = {}; return typeof v === "string"?v:v.value
currentVal.split(",").forEach(function(v) {
if (v) {
currentValues[v] = true;
}
}); });
for (var i=0;i<opt.options.length;i++) { this.value(validValues.join(","));
op = opt.options[i];
delete currentValues[op.value||op];
}
if (!$.isEmptyObject(currentValues)) {
// Invalid, set to default/empty
this.value((opt.default||[]).join(","));
} }
that._updateOptionSelectLabel(validValues);
} }
} else { } else {
var selectedOption = this.optionValue||opt.options[0]; var selectedOption = this.optionValue||opt.options[0];
@ -938,8 +1096,6 @@
this.input.attr('type',this.defaultInputType) this.input.attr('type',this.defaultInputType)
} }
if (opt.hasValue === false) { if (opt.hasValue === false) {
this.oldValue = this.input.val();
this.input.val("");
this.elementDiv.hide(); this.elementDiv.hide();
this.valueLabelContainer.hide(); this.valueLabelContainer.hide();
} else if (opt.valueLabel) { } else if (opt.valueLabel) {
@ -952,12 +1108,13 @@
this.elementDiv.hide(); this.elementDiv.hide();
opt.valueLabel.call(this,this.valueLabelContainer,this.input.val()); opt.valueLabel.call(this,this.valueLabelContainer,this.input.val());
} else { } else {
if (this.oldValue !== undefined) {
this.input.val(this.oldValue);
delete this.oldValue;
}
this.valueLabelContainer.hide(); this.valueLabelContainer.hide();
this.elementDiv.show(); this.elementDiv.show();
if (opt.autoComplete) {
this.input.autoComplete({
search: opt.autoComplete
})
}
} }
if (this.optionExpandButton) { if (this.optionExpandButton) {
if (opt.expand) { if (opt.expand) {
@ -1042,6 +1199,9 @@
}, },
disabled: function() { disabled: function() {
return this.uiSelect.attr("disabled") === "disabled"; return this.uiSelect.attr("disabled") === "disabled";
},
focus: function() {
this.input.focus();
} }
}); });
})(jQuery); })(jQuery);

View File

@ -1376,6 +1376,7 @@ RED.diff = (function() {
function mergeDiff(diff) { function mergeDiff(diff) {
//console.log(diff); //console.log(diff);
var selectedTab = RED.workspaces.active();
var appliedDiff = applyDiff(diff); var appliedDiff = applyDiff(diff);
var newConfig = appliedDiff.config; var newConfig = appliedDiff.config;
@ -1426,6 +1427,7 @@ RED.diff = (function() {
RED.view.redraw(true); RED.view.redraw(true);
RED.palette.refresh(); RED.palette.refresh();
RED.workspaces.refresh(); RED.workspaces.refresh();
RED.workspaces.show(selectedTab, true);
RED.sidebar.config.refresh(); RED.sidebar.config.refresh();
} }

File diff suppressed because it is too large Load Diff

View File

@ -54,6 +54,7 @@ RED.editor.codeEditor.monaco = (function() {
var initialised = false; var initialised = false;
const type = "monaco"; const type = "monaco";
const monacoThemes = ["vs","vs-dark","hc-black"]; //TODO: consider setting hc-black autmatically based on acessability? const monacoThemes = ["vs","vs-dark","hc-black"]; //TODO: consider setting hc-black autmatically based on acessability?
let userSelectedTheme;
//TODO: get from externalModules.js For now this is enough for feature parity with ACE (and then some). //TODO: get from externalModules.js For now this is enough for feature parity with ACE (and then some).
const knownModules = { const knownModules = {
@ -181,18 +182,34 @@ RED.editor.codeEditor.monaco = (function() {
var editorSettings = RED.editor.codeEditor.settings || {}; var editorSettings = RED.editor.codeEditor.settings || {};
var editorOptions = editorSettings.options || {}; var editorOptions = editorSettings.options || {};
if (editorOptions.theme) { //if editorOptions.theme is an object (set in theme.js context()), use the plugin theme name as the monaco theme name
if (!monacoThemes.includes(editorOptions.theme)) { //if editorOptions.theme is a string, it should be the name of a pre-set theme, load that
var customTheme = 'vendor/monaco/dist/theme/' + editorOptions.theme + '.json'; try {
$.get(customTheme, function (theme) { const addTheme = function (themeThemeName, theme) {
monacoThemes.push(editorOptions.theme);//add to list of loaded themes
if ((theme.rules && Array.isArray(theme.rules)) || theme.colors) { if ((theme.rules && Array.isArray(theme.rules)) || theme.colors) {
monaco.editor.defineTheme(editorOptions.theme, theme); monacoThemes.push(themeThemeName); //add to list of loaded themes
monaco.editor.setTheme(editorOptions.theme); monaco.editor.defineTheme(themeThemeName, theme);
monaco.editor.setTheme(themeThemeName);
userSelectedTheme = themeThemeName;
} }
};
if (editorOptions.theme) {
if (typeof editorOptions.theme == "object" && RED.settings.editorTheme.theme) {
let themeThemeName = editorOptions.theme.name || RED.settings.editorTheme.theme;
addTheme(themeThemeName, editorOptions.theme);
} else if (typeof editorOptions.theme == "string") {
let themeThemeName = editorOptions.theme;
if (!monacoThemes.includes(themeThemeName)) {
$.get('vendor/monaco/dist/theme/' + themeThemeName + '.json', function (theme) {
addTheme(themeThemeName, theme);
}); });
} }
} }
}
} catch (error) {
console.warn(error);
}
//Helper function to simplify snippet setup //Helper function to simplify snippet setup
function createMonacoCompletionItem(label, insertText, documentation, range, kind) { function createMonacoCompletionItem(label, insertText, documentation, range, kind) {
@ -653,6 +670,8 @@ RED.editor.codeEditor.monaco = (function() {
noSyntaxValidation: false, noSyntaxValidation: false,
diagnosticCodesToIgnore: [ diagnosticCodesToIgnore: [
1108, //return not inside function 1108, //return not inside function
1375, //'await' expressions are only allowed at the top level of a file when that file is a module
1378, //Top-level 'await' expressions are only allowed when the 'module' option is set to 'esnext' or 'system', and the 'target' option is set to 'es2017' or higher
//2304, //Cannot find name - this one is heavy handed and prevents user seeing stupid errors. Would provide better ACE feature parity (i.e. no need for declaration of vars) but misses lots of errors. Lets be bold & leave it out! //2304, //Cannot find name - this one is heavy handed and prevents user seeing stupid errors. Would provide better ACE feature parity (i.e. no need for declaration of vars) but misses lots of errors. Lets be bold & leave it out!
2307, //Cannot find module 'xxx' or its corresponding type declarations 2307, //Cannot find module 'xxx' or its corresponding type declarations
2322, //Type 'unknown' is not assignable to type 'string' 2322, //Type 'unknown' is not assignable to type 'string'
@ -742,6 +761,10 @@ RED.editor.codeEditor.monaco = (function() {
var editorOptions = $.extend({}, editorSettings.options, options); var editorOptions = $.extend({}, editorSettings.options, options);
editorOptions.language = convertAceModeToMonacoLang(options.mode); editorOptions.language = convertAceModeToMonacoLang(options.mode);
if(userSelectedTheme) {
editorOptions.theme = userSelectedTheme;//use user selected theme for this session
}
//by default, set javascript editors to text mode. //by default, set javascript editors to text mode.
//when element becomes visible, it will be (re) set to javascript mode //when element becomes visible, it will be (re) set to javascript mode
//this is to ensure multiple editors sharing the model dont present its //this is to ensure multiple editors sharing the model dont present its
@ -1167,7 +1190,10 @@ RED.editor.codeEditor.monaco = (function() {
return { row: p.lineNumber-1, column: p.column-1 }; return { row: p.lineNumber-1, column: p.column-1 };
} }
ed.setTheme = monaco.editor.setTheme; ed.setTheme = function(theme) {
monaco.editor.setTheme(theme);
userSelectedTheme = theme;//remember users choice for this session
}
ed.on = function (name, cb) { ed.on = function (name, cb) {
switch (name) { switch (name) {

View File

@ -1,4 +1,4 @@
RED.colorPicker = (function() { RED.editor.colorPicker = RED.colorPicker = (function() {
function create(options) { function create(options) {
var color = options.value; var color = options.value;

View File

@ -0,0 +1,616 @@
RED.editor.envVarList = (function() {
var currentLocale = 'en-US';
var DEFAULT_ENV_TYPE_LIST = ['str','num','bool','json','bin','env'];
var DEFAULT_ENV_TYPE_LIST_INC_CRED = ['str','num','bool','json','bin','env','cred'];
/**
* Create env var edit interface
* @param container - container
* @param node - subflow node
*/
function buildPropertiesList(envContainer, node) {
var isTemplateNode = (node.type === "subflow");
envContainer
.css({
'min-height':'150px',
'min-width':'450px'
})
.editableList({
header: isTemplateNode?$('<div><div><div></div><div data-i18n="common.label.name"></div><div data-i18n="editor-tab.defaultValue"></div><div></div></div></div>'):undefined,
addItem: function(container, i, opt) {
// If this is an instance node, these are properties unique to
// this instance - ie opt.parent will not be defined.
if (isTemplateNode) {
container.addClass("red-ui-editor-subflow-env-editable")
}
var envRow = $('<div/>').appendTo(container);
var nameField = null;
var valueField = null;
nameField = $('<input/>', {
class: "node-input-env-name",
type: "text",
placeholder: RED._("common.label.name")
}).attr("autocomplete","disable").appendTo(envRow).val(opt.name);
valueField = $('<input/>',{
style: "width:100%",
class: "node-input-env-value",
type: "text",
}).attr("autocomplete","disable").appendTo(envRow)
valueField.typedInput({default:'str',types:isTemplateNode?DEFAULT_ENV_TYPE_LIST:DEFAULT_ENV_TYPE_LIST_INC_CRED});
valueField.typedInput('type', opt.type);
if (opt.type === "cred") {
if (opt.value) {
valueField.typedInput('value', opt.value);
} else if (node.credentials && node.credentials[opt.name]) {
valueField.typedInput('value', node.credentials[opt.name]);
} else if (node.credentials && node.credentials['has_'+opt.name]) {
valueField.typedInput('value', "__PWRD__");
} else {
valueField.typedInput('value', "");
}
} else {
valueField.typedInput('value', opt.value);
}
opt.nameField = nameField;
opt.valueField = valueField;
var actionButton = $('<a/>',{href:"#",class:"red-ui-editableList-item-remove red-ui-button red-ui-button-small"}).appendTo(envRow);
$('<i/>',{class:"fa "+(opt.parent?"fa-reply":"fa-remove")}).appendTo(actionButton);
var removeTip = RED.popover.tooltip(actionButton,RED._("subflow.env.remove"));
actionButton.on("click", function(evt) {
evt.preventDefault();
removeTip.close();
container.parent().addClass("red-ui-editableList-item-deleting")
container.fadeOut(300, function() {
envContainer.editableList('removeItem',opt);
});
});
if (isTemplateNode) {
// Add the UI customisation row
// if `opt.ui` does not exist, then apply defaults. If these
// defaults do not change then they will get stripped off
// before saving.
if (opt.type === 'cred') {
opt.ui = opt.ui || {
icon: "",
type: "cred"
}
opt.ui.type = "cred";
} else {
opt.ui = opt.ui || {
icon: "",
type: "input",
opts: {types:DEFAULT_ENV_TYPE_LIST}
}
}
opt.ui.label = opt.ui.label || {};
opt.ui.type = opt.ui.type || "input";
var uiRow = $('<div/>').appendTo(container).hide();
// save current info for reverting on cancel
// var copy = $.extend(true, {}, ui);
$('<a href="#"><i class="fa fa-angle-right"></a>').prependTo(envRow).on("click", function (evt) {
evt.preventDefault();
if ($(this).hasClass('expanded')) {
uiRow.slideUp();
$(this).removeClass('expanded');
} else {
uiRow.slideDown();
$(this).addClass('expanded');
}
});
buildEnvEditRow(uiRow, opt.ui, nameField, valueField);
nameField.trigger('change');
}
},
sortable: ".red-ui-editableList-item-handle",
removable: false
});
var parentEnv = {};
var envList = [];
if (/^subflow:/.test(node.type)) {
var subflowDef = RED.nodes.subflow(node.type.substring(8));
if (subflowDef.env) {
subflowDef.env.forEach(function(env) {
var item = {
name:env.name,
parent: {
type: env.type,
value: env.value,
ui: env.ui
}
}
envList.push(item);
parentEnv[env.name] = item;
})
}
}
if (node.env) {
for (var i = 0; i < node.env.length; i++) {
var env = node.env[i];
if (parentEnv.hasOwnProperty(env.name)) {
parentEnv[env.name].type = env.type;
parentEnv[env.name].value = env.value;
} else {
envList.push({
name: env.name,
type: env.type,
value: env.value,
ui: env.ui
});
}
}
}
envList.forEach(function(env) {
if (env.parent && env.parent.ui && env.parent.ui.type === 'hide') {
return;
}
if (!isTemplateNode && env.parent) {
return;
}
envContainer.editableList('addItem', JSON.parse(JSON.stringify(env)));
});
}
/**
* Create UI edit interface for environment variable
* @param container - container
* @param env - env var definition
* @param nameField - name field of env var
* @param valueField - value field of env var
*/
function buildEnvEditRow(container, ui, nameField, valueField) {
container.addClass("red-ui-editor-subflow-env-ui-row")
var topRow = $('<div></div>').appendTo(container);
$('<div></div>').appendTo(topRow);
$('<div>').text(RED._("editor.icon")).appendTo(topRow);
$('<div>').text(RED._("editor.label")).appendTo(topRow);
$('<div>').text(RED._("editor.inputType")).appendTo(topRow);
var row = $('<div></div>').appendTo(container);
$('<div><i class="red-ui-editableList-item-handle fa fa-bars"></i></div>').appendTo(row);
var typeOptions = {
'input': {types:DEFAULT_ENV_TYPE_LIST},
'select': {opts:[]},
'spinner': {},
'cred': {}
};
if (ui.opts) {
typeOptions[ui.type] = ui.opts;
} else {
// Pick up the default values if not otherwise provided
ui.opts = typeOptions[ui.type];
}
var iconCell = $('<div></div>').appendTo(row);
var iconButton = $('<a href="#"></a>').appendTo(iconCell);
iconButton.on("click", function(evt) {
evt.preventDefault();
var icon = ui.icon || "";
var iconPath = (icon ? RED.utils.separateIconPath(icon) : {});
RED.editor.iconPicker.show(iconButton, null, iconPath, true, function (newIcon) {
iconButton.empty();
var path = newIcon || "";
var newPath = RED.utils.separateIconPath(path);
if (newPath) {
$('<i class="fa"></i>').addClass(newPath.file).appendTo(iconButton);
}
ui.icon = path;
});
})
if (ui.icon) {
var newPath = RED.utils.separateIconPath(ui.icon);
$('<i class="fa '+newPath.file+'"></i>').appendTo(iconButton);
}
var labelCell = $('<div></div>').appendTo(row);
var label = ui.label && ui.label[currentLocale] || "";
var labelInput = $('<input type="text">').val(label).appendTo(labelCell);
ui.labelField = labelInput;
labelInput.on('change', function(evt) {
ui.label = ui.label || {};
var val = $(this).val().trim();
if (val === "") {
delete ui.label[currentLocale];
} else {
ui.label[currentLocale] = val;
}
})
var labelIcon = $('<span class="red-ui-editor-subflow-env-lang-icon"><i class="fa fa-language"></i></span>').appendTo(labelCell);
RED.popover.tooltip(labelIcon,function() {
var langs = Object.keys(ui.label);
var content = $("<div>");
if (langs.indexOf(currentLocale) === -1) {
langs.push(currentLocale);
langs.sort();
}
langs.forEach(function(l) {
var row = $('<div>').appendTo(content);
$('<span>').css({display:"inline-block",width:"120px"}).text(RED._("languages."+l)+(l===currentLocale?"*":"")).appendTo(row);
$('<span>').text(ui.label[l]||"").appendTo(row);
});
return content;
})
nameField.on('change',function(evt) {
labelInput.attr("placeholder",$(this).val())
});
var inputCell = $('<div></div>').appendTo(row);
var inputCellInput = $('<input type="text">').css("width","100%").appendTo(inputCell);
if (ui.type === "input") {
inputCellInput.val(ui.opts.types.join(","));
}
var checkbox;
var selectBox;
inputCellInput.typedInput({
types: [
{
value:"input",
label:RED._("editor.inputs.input"), icon:"fa fa-i-cursor",showLabel:false,multiple:true,options:[
{value:"str",label:RED._("editor.types.str"),icon:"red/images/typedInput/az.svg"},
{value:"num",label:RED._("editor.types.num"),icon:"red/images/typedInput/09.svg"},
{value:"bool",label:RED._("editor.types.bool"),icon:"red/images/typedInput/bool.svg"},
{value:"json",label:RED._("editor.types.json"),icon:"red/images/typedInput/json.svg"},
{value: "bin",label: RED._("editor.types.bin"),icon: "red/images/typedInput/bin.svg"},
{value: "env",label: RED._("editor.types.env"),icon: "red/images/typedInput/env.svg"},
{value: "cred",label: RED._("editor.types.cred"),icon: "fa fa-lock"}
],
default: DEFAULT_ENV_TYPE_LIST,
valueLabel: function(container,value) {
container.css("padding",0);
var innerContainer = $('<div class="red-ui-editor-subflow-env-input-type"></div>').appendTo(container);
var input = $('<div class="placeholder-input">').appendTo(innerContainer);
$('<span><i class="fa fa-i-cursor"></i></span>').appendTo(input);
if (value.length) {
value.forEach(function(v) {
if (!/^fa /.test(v.icon)) {
$('<img>',{src:v.icon,style:"max-width:14px; padding: 0 3px; margin-top:-4px; margin-left: 1px"}).appendTo(input);
} else {
var s = $('<span>',{style:"max-width:14px; padding: 0 3px; margin-top:-4px; margin-left: 1px"}).appendTo(input);
$("<i>",{class: v.icon}).appendTo(s);
}
})
} else {
$('<span class="red-ui-editor-subflow-env-input-type-placeholder"></span>').text(RED._("editor.selectType")).appendTo(input);
}
}
},
{
value: "cred",
label: RED._("typedInput.type.cred"), icon:"fa fa-lock", showLabel: false,
valueLabel: function(container,value) {
container.css("padding",0);
var innerContainer = $('<div class="red-ui-editor-subflow-env-input-type">').css({
"border-top-right-radius": "4px",
"border-bottom-right-radius": "4px"
}).appendTo(container);
$('<div class="placeholder-input">').html("&bull;&bull;&bull;&bull;&bull;&bull;&bull;&bull;").appendTo(innerContainer);
}
},
{
value:"select",
label:RED._("editor.inputs.select"), icon:"fa fa-tasks",showLabel:false,
valueLabel: function(container,value) {
container.css("padding","0");
selectBox = $('<select></select>').appendTo(container);
if (ui.opts && Array.isArray(ui.opts.opts)) {
ui.opts.opts.forEach(function(o) {
var label = lookupLabel(o.l, o.l["en-US"]||o.v, currentLocale);
// $('<option>').val((o.t||'str')+":"+o.v).text(label).appendTo(selectBox);
$('<option>').val(o.v).text(label).appendTo(selectBox);
})
}
selectBox.on('change', function(evt) {
var v = selectBox.val();
// var parts = v.split(":");
// var t = parts.shift();
// v = parts.join(":");
//
// valueField.typedInput("type",'str')
valueField.typedInput("value",v)
});
selectBox.val(valueField.typedInput("value"));
// selectBox.val(valueField.typedInput('type')+":"+valueField.typedInput("value"));
},
expand: {
icon: "fa-caret-down",
minWidth: 400,
content: function(container) {
var content = $('<div class="red-ui-editor-subflow-ui-edit-panel">').appendTo(container);
var optList = $('<ol>').appendTo(content).editableList({
header:$("<div><div>"+RED._("editor.select.label")+"</div><div>"+RED._("editor.select.value")+"</div></div>"),
addItem: function(row,index,itemData) {
var labelDiv = $('<div>').appendTo(row);
var label = lookupLabel(itemData.l, "", currentLocale);
itemData.label = $('<input type="text">').val(label).appendTo(labelDiv);
itemData.label.on('keydown', function(evt) {
if (evt.keyCode === 13) {
itemData.input.focus();
evt.preventDefault();
}
});
var labelIcon = $('<span class="red-ui-editor-subflow-env-lang-icon"><i class="fa fa-language"></i></span>').appendTo(labelDiv);
RED.popover.tooltip(labelIcon,function() {
return currentLocale;
})
itemData.input = $('<input type="text">').val(itemData.v).appendTo(row);
// Problem using a TI here:
// - this is in a popout panel
// - clicking the expand button in the TI will close the parent edit tray
// and open the type editor.
// - but it leaves the popout panel over the top.
// - there is no way to get back to the popout panel after closing the type editor
//.typedInput({default:itemData.t||'str', types:DEFAULT_ENV_TYPE_LIST});
itemData.input.on('keydown', function(evt) {
if (evt.keyCode === 13) {
// Enter or Tab
var index = optList.editableList('indexOf',itemData);
var length = optList.editableList('length');
if (index + 1 === length) {
var newItem = {};
optList.editableList('addItem',newItem);
setTimeout(function() {
if (newItem.label) {
newItem.label.focus();
}
},100)
} else {
var nextItem = optList.editableList('getItemAt',index+1);
if (nextItem.label) {
nextItem.label.focus()
}
}
evt.preventDefault();
}
});
},
sortable: true,
removable: true,
height: 160
})
if (ui.opts.opts.length > 0) {
ui.opts.opts.forEach(function(o) {
optList.editableList('addItem',$.extend(true,{},o))
})
} else {
optList.editableList('addItem',{})
}
return {
onclose: function() {
var items = optList.editableList('items');
var vals = [];
items.each(function (i,el) {
var data = el.data('data');
var l = data.label.val().trim();
var v = data.input.val();
// var t = data.input.typedInput('type');
// var v = data.input.typedInput('value');
if (l.length > 0) {
data.l = data.l || {};
data.l[currentLocale] = l;
}
data.v = v;
if (l.length > 0 || v.length > 0) {
var val = {l:data.l,v:data.v};
// if (t !== 'str') {
// val.t = t;
// }
vals.push(val);
}
});
ui.opts.opts = vals;
inputCellInput.typedInput('value',Date.now())
}
}
}
}
},
{
value:"checkbox",
label:RED._("editor.inputs.checkbox"), icon:"fa fa-check-square-o",showLabel:false,
valueLabel: function(container,value) {
container.css("padding",0);
checkbox = $('<input type="checkbox">').appendTo(container);
checkbox.on('change', function(evt) {
valueField.typedInput('value',$(this).prop('checked')?"true":"false");
})
checkbox.prop('checked',valueField.typedInput('value')==="true");
}
},
{
value:"spinner",
label:RED._("editor.inputs.spinner"), icon:"fa fa-sort-numeric-asc", showLabel:false,
valueLabel: function(container,value) {
container.css("padding",0);
var innerContainer = $('<div class="red-ui-editor-subflow-env-input-type"></div>').appendTo(container);
var input = $('<div class="placeholder-input">').appendTo(innerContainer);
$('<span><i class="fa fa-sort-numeric-asc"></i></span>').appendTo(input);
var min = ui.opts && ui.opts.min;
var max = ui.opts && ui.opts.max;
var label = "";
if (min !== undefined && max !== undefined) {
label = Math.min(min,max)+" - "+Math.max(min,max);
} else if (min !== undefined) {
label = "> "+min;
} else if (max !== undefined) {
label = "< "+max;
}
$('<span>').css("margin-left","15px").text(label).appendTo(input);
},
expand: {
icon: "fa-caret-down",
content: function(container) {
var content = $('<div class="red-ui-editor-subflow-ui-edit-panel">').appendTo(container);
content.css("padding","8px 5px")
var min = ui.opts.min;
var max = ui.opts.max;
var minInput = $('<input type="number" style="margin-bottom:0; width:60px">');
minInput.val(min);
var maxInput = $('<input type="number" style="margin-bottom:0; width:60px">');
maxInput.val(max);
$('<div class="form-row" style="margin-bottom:3px"><label>'+RED._("editor.spinner.min")+'</label></div>').append(minInput).appendTo(content);
$('<div class="form-row" style="margin-bottom:0"><label>'+RED._("editor.spinner.max")+'</label></div>').append(maxInput).appendTo(content);
return {
onclose: function() {
var min = minInput.val().trim();
var max = maxInput.val().trim();
if (min !== "") {
ui.opts.min = parseInt(min);
} else {
delete ui.opts.min;
}
if (max !== "") {
ui.opts.max = parseInt(max);
} else {
delete ui.opts.max;
}
inputCellInput.typedInput('value',Date.now())
}
}
}
}
},
{
value:"none",
label:RED._("editor.inputs.none"), icon:"fa fa-times",hasValue:false
},
{
value:"hide",
label:RED._("editor.inputs.hidden"), icon:"fa fa-ban",hasValue:false
}
],
default: 'none'
}).on("typedinputtypechange", function(evt,type) {
ui.type = $(this).typedInput("type");
ui.opts = typeOptions[ui.type];
if (ui.type === 'input') {
// In the case of 'input' type, the typedInput uses the multiple-option
// mode. Its value needs to be set to a comma-separately list of the
// selected options.
inputCellInput.typedInput('value',ui.opts.types.join(","))
} else {
// No other type cares about `value`, but doing this will
// force a refresh of the label now that `ui.opts` has
// been updated.
inputCellInput.typedInput('value',Date.now())
}
switch (ui.type) {
case 'input':
valueField.typedInput('types',ui.opts.types);
break;
case 'select':
valueField.typedInput('types',['str']);
break;
case 'checkbox':
valueField.typedInput('types',['bool']);
break;
case 'spinner':
valueField.typedInput('types',['num']);
break;
case 'cred':
valueField.typedInput('types',['cred']);
break;
default:
valueField.typedInput('types',DEFAULT_ENV_TYPE_LIST)
}
if (ui.type === 'checkbox') {
valueField.typedInput('type','bool');
} else if (ui.type === 'spinner') {
valueField.typedInput('type','num');
}
if (ui.type !== 'checkbox') {
checkbox = null;
}
}).on("change", function(evt,type) {
if (ui.type === 'input') {
var types = inputCellInput.typedInput('value');
ui.opts.types = (types === "") ? ["str"] : types.split(",");
valueField.typedInput('types',ui.opts.types);
}
});
valueField.on("change", function(evt) {
if (checkbox) {
checkbox.prop('checked',$(this).typedInput('value')==="true")
}
})
// Set the input to the right type. This will trigger the 'typedinputtypechange'
// event handler (just above ^^) to update the value if needed
inputCellInput.typedInput('type',ui.type)
}
function setLocale(l, list) {
currentLocale = l;
if (list) {
var items = list.editableList("items");
items.each(function (i, item) {
var entry = $(this).data('data');
var labelField = entry.ui.labelField;
labelField.val(lookupLabel(entry.ui.label, "", currentLocale));
if (labelField.timeout) {
clearTimeout(labelField.timeout);
delete labelField.timeout;
}
labelField.addClass("input-updated");
labelField.timeout = setTimeout(function() {
delete labelField.timeout
labelField.removeClass("input-updated");
},3000);
});
}
}
/**
* Lookup text for specific locale
* @param labels - dict of labels
* @param defaultLabel - fallback label if not found
* @param locale - target locale
* @returns {string} text for specified locale
*/
function lookupLabel(labels, defaultLabel, locale) {
if (labels) {
if (labels[locale]) {
return labels[locale];
}
if (locale) {
var lang = locale.substring(0, 2);
if (labels[lang]) {
return labels[lang];
}
}
}
return defaultLabel;
}
return {
create: buildPropertiesList,
setLocale: setLocale,
lookupLabel: lookupLabel,
DEFAULT_ENV_TYPE_LIST: DEFAULT_ENV_TYPE_LIST,
DEFAULT_ENV_TYPE_LIST_INC_CRED: DEFAULT_ENV_TYPE_LIST_INC_CRED
}
})();

View File

@ -0,0 +1,99 @@
RED.editor.iconPicker = (function() {
function showIconPicker(container, backgroundColor, iconPath, faOnly, done) {
var picker = $('<div class="red-ui-icon-picker">');
var searchDiv = $("<div>",{class:"red-ui-search-container"}).appendTo(picker);
searchInput = $('<input type="text">').attr("placeholder",RED._("editor.searchIcons")).appendTo(searchDiv).searchBox({
delay: 50,
change: function() {
var searchTerm = $(this).val().trim();
if (searchTerm === "") {
iconList.find(".red-ui-icon-list-module").show();
iconList.find(".red-ui-icon-list-icon").show();
} else {
iconList.find(".red-ui-icon-list-module").hide();
iconList.find(".red-ui-icon-list-icon").each(function(i,n) {
if ($(n).data('icon').indexOf(searchTerm) === -1) {
$(n).hide();
} else {
$(n).show();
}
});
}
}
});
var row = $('<div>').appendTo(picker);
var iconList = $('<div class="red-ui-icon-list">').appendTo(picker);
var metaRow = $('<div class="red-ui-icon-meta"></div>').appendTo(picker);
var summary = $('<span>').appendTo(metaRow);
var resetButton = $('<button type="button" class="red-ui-button red-ui-button-small">'+RED._("editor.useDefault")+'</button>').appendTo(metaRow).on("click", function(e) {
e.preventDefault();
iconPanel.hide();
done(null);
});
if (!backgroundColor && faOnly) {
iconList.addClass("red-ui-icon-list-dark");
}
setTimeout(function() {
var iconSets = RED.nodes.getIconSets();
Object.keys(iconSets).forEach(function(moduleName) {
if (faOnly && (moduleName !== "font-awesome")) {
return;
}
var icons = iconSets[moduleName];
if (icons.length > 0) {
// selectIconModule.append($("<option></option>").val(moduleName).text(moduleName));
var header = $('<div class="red-ui-icon-list-module"></div>').text(moduleName).appendTo(iconList);
$('<i class="fa fa-cube"></i>').prependTo(header);
icons.forEach(function(icon) {
var iconDiv = $('<div>',{class:"red-ui-icon-list-icon"}).appendTo(iconList);
var nodeDiv = $('<div>',{class:"red-ui-search-result-node"}).appendTo(iconDiv);
var icon_url = RED.settings.apiRootUrl+"icons/"+moduleName+"/"+icon;
iconDiv.data('icon',icon_url);
if (backgroundColor) {
nodeDiv.css({
'backgroundColor': backgroundColor
});
var borderColor = RED.utils.getDarkerColor(backgroundColor);
if (borderColor !== backgroundColor) {
nodeDiv.css('border-color',borderColor)
}
}
var iconContainer = $('<div/>',{class:"red-ui-palette-icon-container"}).appendTo(nodeDiv);
RED.utils.createIconElement(icon_url, iconContainer, true);
if (iconPath.module === moduleName && iconPath.file === icon) {
iconDiv.addClass("selected");
}
iconDiv.on("mouseover", function() {
summary.text(icon);
})
iconDiv.on("mouseout", function() {
summary.html("&nbsp;");
})
iconDiv.on("click", function() {
iconPanel.hide();
done(moduleName+"/"+icon);
})
})
}
});
setTimeout(function() {
spinner.remove();
},50);
},300);
var spinner = RED.utils.addSpinnerOverlay(iconList,true);
var iconPanel = RED.popover.panel(picker);
iconPanel.show({
target: container
})
picker.slideDown(100);
searchInput.trigger("focus");
}
return {
show: showIconPicker
}
})();

View File

@ -0,0 +1,517 @@
;(function() {
RED.editor.registerEditPane("editor-tab-appearance", function(node) {
return {
label: RED._("editor-tab.appearance"),
name: RED._("editor-tab.appearance"),
iconClass: "fa fa-object-group",
create: function(container) {
this.content = container;
buildAppearanceForm(this.content,node);
if (node.type === 'subflow') {
this.defaultIcon = "node-red/subflow.svg";
} else {
var iconPath = RED.utils.getDefaultNodeIcon(node._def,node);
this.defaultIcon = iconPath.module+"/"+iconPath.file;
if (node.icon && node.icon !== this.defaultIcon) {
this.isDefaultIcon = false;
} else {
this.isDefaultIcon = true;
}
}
},
resize: function(size) {
},
close: function() {
},
show: function() {
refreshLabelForm(this.content, node);
},
apply: function(editState) {
if (updateLabels(node, editState.changes, editState.outputMap)) {
editState.changed = true;
}
if (!node._def.defaults || !node._def.defaults.hasOwnProperty("icon")) {
var icon = $("#red-ui-editor-node-icon").val()||""
if (!this.isDefaultIcon) {
if (icon !== node.icon) {
editState.changes.icon = node.icon;
node.icon = icon;
editState.changed = true;
}
} else {
if (icon !== "" && icon !== this.defaultIcon) {
editState.changes.icon = node.icon;
node.icon = icon;
editState.changed = true;
} else {
var iconPath = RED.utils.getDefaultNodeIcon(node._def, node);
var currentDefaultIcon = iconPath.module+"/"+iconPath.file;
if (this.defaultIcon !== currentDefaultIcon) {
editState.changes.icon = node.icon;
node.icon = currentDefaultIcon;
editState.changed = true;
}
}
}
}
if (node.type === "subflow") {
var newCategory = $("#subflow-appearance-input-category").val().trim();
if (newCategory === "_custom_") {
newCategory = $("#subflow-appearance-input-custom-category").val().trim();
if (newCategory === "") {
newCategory = node.category;
}
}
if (newCategory === 'subflows') {
newCategory = '';
}
if (newCategory != node.category) {
editState.changes['category'] = node.category;
node.category = newCategory;
editState.changed = true;
}
var oldColor = node.color;
var newColor = $("#red-ui-editor-node-color").val();
if (oldColor !== newColor) {
editState.changes.color = node.color;
node.color = newColor;
editState.changed = true;
RED.utils.clearNodeColorCache();
if (node.type === "subflow") {
var nodeDefinition = RED.nodes.getType(
"subflow:" + node.id
);
nodeDefinition["color"] = newColor;
}
}
}
var showLabel = node._def.hasOwnProperty("showLabel")?node._def.showLabel:true;
if (!$("#node-input-show-label").prop('checked')) {
// Not checked - hide label
if (showLabel) {
// Default to show label
if (node.l !== false) {
editState.changes.l = node.l
editState.changed = true;
}
node.l = false;
} else {
// Node has showLabel:false (eg link nodes)
if (node.hasOwnProperty('l') && node.l) {
editState.changes.l = node.l
editState.changed = true;
}
delete node.l;
}
} else {
// Checked - show label
if (showLabel) {
// Default to show label
if (node.hasOwnProperty('l') && !node.l) {
editState.changes.l = node.l
editState.changed = true;
}
delete node.l;
} else {
if (!node.l) {
editState.changes.l = node.l
editState.changed = true;
}
node.l = true;
}
}
}
}
});
function buildAppearanceForm(container,node) {
var dialogForm = $('<form class="dialog-form form-horizontal" autocomplete="off"></form>').appendTo(container);
var i,row;
if (node.type === "subflow") {
var categoryRow = $("<div/>", {
class: "form-row"
}).appendTo(dialogForm);
$("<label/>", {
for: "subflow-appearance-input-category",
"data-i18n": "editor:subflow.category"
}).appendTo(categoryRow);
var categorySelector = $("<select/>", {
id: "subflow-appearance-input-category"
}).css({
width: "250px"
}).appendTo(categoryRow);
$("<input/>", {
type: "text",
id: "subflow-appearance-input-custom-category"
}).css({
display: "none",
"margin-left": "10px",
width: "calc(100% - 250px)"
}).appendTo(categoryRow);
var categories = RED.palette.getCategories();
categories.sort(function(A,B) {
return A.label.localeCompare(B.label);
})
categories.forEach(function(cat) {
categorySelector.append($("<option/>").val(cat.id).text(cat.label));
})
categorySelector.append($("<option/>").attr('disabled',true).text("---"));
categorySelector.append($("<option/>").val("_custom_").text(RED._("palette.addCategory")));
$("#subflow-appearance-input-category").on("change", function() {
var val = $(this).val();
if (val === "_custom_") {
$("#subflow-appearance-input-category").width(120);
$("#subflow-appearance-input-custom-category").show();
} else {
$("#subflow-appearance-input-category").width(250);
$("#subflow-appearance-input-custom-category").hide();
}
})
$("#subflow-appearance-input-category").val(node.category||"subflows");
var userCount = 0;
var subflowType = "subflow:"+node.id;
// RED.nodes.eachNode(function(n) {
// if (n.type === subflowType) {
// userCount++;
// }
// });
$("#red-ui-editor-subflow-user-count")
.text(RED._("subflow.subflowInstances", {count:node.instances.length})).show();
}
$('<div class="form-row">'+
'<label for="node-input-show-label-btn" data-i18n="editor.label"></label>'+
'<span style="margin-right: 2px;"/>'+
'<input type="checkbox" id="node-input-show-label"/>'+
'</div>').appendTo(dialogForm);
$("#node-input-show-label").toggleButton({
enabledLabel: RED._("editor.show"),
disabledLabel: RED._("editor.hide")
})
if (!node.hasOwnProperty("l")) {
// Show label unless def.showLabel set to false
node.l = node._def.hasOwnProperty("showLabel")?node._def.showLabel:true;
}
$("#node-input-show-label").prop("checked",node.l).trigger("change");
if (node.type === "subflow") {
// subflow template can select its color
var color = node.color ? node.color : "#DDAA99";
var colorRow = $("<div/>", {
class: "form-row"
}).appendTo(dialogForm);
$("<label/>").text(RED._("editor.color")).appendTo(colorRow);
var recommendedColors = [
"#DDAA99",
"#3FADB5", "#87A980", "#A6BBCF",
"#AAAA66", "#C0C0C0", "#C0DEED",
"#C7E9C0", "#D7D7A0", "#D8BFD8",
"#DAC4B4", "#DEB887", "#DEBD5C",
"#E2D96E", "#E6E0F8", "#E7E7AE",
"#E9967A", "#F3B567", "#FDD0A2",
"#FDF0C2", "#FFAAAA", "#FFCC66",
"#FFF0F0", "#FFFFFF"
]
RED.editor.colorPicker.create({
id: "red-ui-editor-node-color",
value: color,
palette: recommendedColors,
sortPalette: function (a, b) {return a.l - b.l;}
}).appendTo(colorRow);
$("#red-ui-editor-node-color").on('change', function(ev) {
// Horribly out of scope...
var colour = $(this).val();
nodeDiv.css('backgroundColor',colour);
var borderColor = RED.utils.getDarkerColor(colour);
if (borderColor !== colour) {
nodeDiv.css('border-color',borderColor)
}
})
}
// If a node has icon property in defaults, the icon of the node cannot be modified. (e.g, ui_button node in dashboard)
if ((!node._def.defaults || !node._def.defaults.hasOwnProperty("icon"))) {
var iconRow = $('<div class="form-row"></div>').appendTo(dialogForm);
$('<label data-i18n="editor.settingIcon">').appendTo(iconRow);
var iconButton = $('<button type="button" class="red-ui-button red-ui-editor-node-appearance-button">').appendTo(iconRow);
$('<i class="fa fa-caret-down"></i>').appendTo(iconButton);
var nodeDiv = $('<div>',{class:"red-ui-search-result-node"}).appendTo(iconButton);
var colour = RED.utils.getNodeColor(node.type, node._def);
var icon_url = RED.utils.getNodeIcon(node._def,node);
nodeDiv.css('backgroundColor',colour);
var borderColor = RED.utils.getDarkerColor(colour);
if (borderColor !== colour) {
nodeDiv.css('border-color',borderColor)
}
var iconContainer = $('<div/>',{class:"red-ui-palette-icon-container"}).appendTo(nodeDiv);
RED.utils.createIconElement(icon_url, iconContainer, true);
iconButton.on("click", function(e) {
e.preventDefault();
var iconPath;
var icon = $("#red-ui-editor-node-icon").val()||"";
if (icon) {
iconPath = RED.utils.separateIconPath(icon);
} else {
iconPath = RED.utils.getDefaultNodeIcon(node._def, node);
}
var backgroundColor = RED.utils.getNodeColor(node.type, node._def);
if (node.type === "subflow") {
backgroundColor = $("#red-ui-editor-node-color").val();
}
RED.editor.iconPicker.show(iconButton,backgroundColor,iconPath,false,function(newIcon) {
$("#red-ui-editor-node-icon").val(newIcon||"");
var icon_url = RED.utils.getNodeIcon(node._def,{type:node.type,icon:newIcon});
RED.utils.createIconElement(icon_url, iconContainer, true);
});
});
RED.popover.tooltip(iconButton, function() {
return $("#red-ui-editor-node-icon").val() || RED._("editor.default");
})
$('<input type="hidden" id="red-ui-editor-node-icon">').val(node.icon).appendTo(iconRow);
}
$('<div class="form-row"><span data-i18n="editor.portLabels"></span></div>').appendTo(dialogForm);
var inputCount = node.inputs || node._def.inputs || 0;
var outputCount = node.outputs || node._def.outputs || 0;
if (node.type === 'subflow') {
inputCount = node.in.length;
outputCount = node.out.length;
}
var inputLabels = node.inputLabels || [];
var outputLabels = node.outputLabels || [];
var inputPlaceholder = node._def.inputLabels?RED._("editor.defaultLabel"):RED._("editor.noDefaultLabel");
var outputPlaceholder = node._def.outputLabels?RED._("editor.defaultLabel"):RED._("editor.noDefaultLabel");
$('<div class="form-row"><span style="margin-left: 50px;" data-i18n="editor.labelInputs"></span><div id="red-ui-editor-node-label-form-inputs"></div></div>').appendTo(dialogForm);
var inputsDiv = $("#red-ui-editor-node-label-form-inputs");
if (inputCount > 0) {
for (i=0;i<inputCount;i++) {
buildLabelRow("input",i,inputLabels[i],inputPlaceholder).appendTo(inputsDiv);
}
} else {
buildLabelRow().appendTo(inputsDiv);
}
$('<div class="form-row"><span style="margin-left: 50px;" data-i18n="editor.labelOutputs"></span><div id="red-ui-editor-node-label-form-outputs"></div></div>').appendTo(dialogForm);
var outputsDiv = $("#red-ui-editor-node-label-form-outputs");
if (outputCount > 0) {
for (i=0;i<outputCount;i++) {
buildLabelRow("output",i,outputLabels[i],outputPlaceholder).appendTo(outputsDiv);
}
} else {
buildLabelRow().appendTo(outputsDiv);
}
}
function refreshLabelForm(container,node) {
var inputPlaceholder = node._def.inputLabels?RED._("editor.defaultLabel"):RED._("editor.noDefaultLabel");
var outputPlaceholder = node._def.outputLabels?RED._("editor.defaultLabel"):RED._("editor.noDefaultLabel");
var inputsDiv = $("#red-ui-editor-node-label-form-inputs");
var outputsDiv = $("#red-ui-editor-node-label-form-outputs");
var inputCount;
var formInputs = $("#node-input-inputs").val();
if (formInputs === undefined) {
if (node.type === 'subflow') {
inputCount = node.in.length;
} else {
inputCount = node.inputs || node._def.inputs || 0;
}
} else {
inputCount = Math.min(1,Math.max(0,parseInt(formInputs)));
if (isNaN(inputCount)) {
inputCount = 0;
}
}
var children = inputsDiv.children();
var childCount = children.length;
if (childCount === 1 && $(children[0]).hasClass('red-ui-editor-node-label-form-none')) {
childCount--;
}
if (childCount < inputCount) {
if (childCount === 0) {
// remove the 'none' placeholder
$(children[0]).remove();
}
for (i = childCount;i<inputCount;i++) {
buildLabelRow("input",i,"",inputPlaceholder).appendTo(inputsDiv);
}
} else if (childCount > inputCount) {
for (i=inputCount;i<childCount;i++) {
$(children[i]).remove();
}
if (inputCount === 0) {
buildLabelRow().appendTo(inputsDiv);
}
}
var outputCount;
var i;
var formOutputs = $("#node-input-outputs").val();
if (formOutputs === undefined) {
if (node.type === 'subflow') {
outputCount = node.out.length;
} else {
inputCount = node.outputs || node._def.outputs || 0;
}
} else if (isNaN(formOutputs)) {
var outputMap = JSON.parse(formOutputs);
var keys = Object.keys(outputMap);
children = outputsDiv.children();
childCount = children.length;
if (childCount === 1 && $(children[0]).hasClass('red-ui-editor-node-label-form-none')) {
childCount--;
}
outputCount = 0;
var rows = [];
keys.forEach(function(p) {
var row = $("#red-ui-editor-node-label-form-output-"+p).parent();
if (row.length === 0 && outputMap[p] !== -1) {
if (childCount === 0) {
$(children[0]).remove();
childCount = -1;
}
row = buildLabelRow("output",p,"",outputPlaceholder);
} else {
row.detach();
}
if (outputMap[p] !== -1) {
outputCount++;
rows.push({i:parseInt(outputMap[p]),r:row});
}
});
rows.sort(function(A,B) {
return A.i-B.i;
})
rows.forEach(function(r,i) {
r.r.find("label").text((i+1)+".");
r.r.appendTo(outputsDiv);
})
if (rows.length === 0) {
buildLabelRow("output",i,"").appendTo(outputsDiv);
} else {
}
} else {
outputCount = Math.max(0,parseInt(formOutputs));
}
children = outputsDiv.children();
childCount = children.length;
if (childCount === 1 && $(children[0]).hasClass('red-ui-editor-node-label-form-none')) {
childCount--;
}
if (childCount < outputCount) {
if (childCount === 0) {
// remove the 'none' placeholder
$(children[0]).remove();
}
for (i = childCount;i<outputCount;i++) {
buildLabelRow("output",i,"").appendTo(outputsDiv);
}
} else if (childCount > outputCount) {
for (i=outputCount;i<childCount;i++) {
$(children[i]).remove();
}
if (outputCount === 0) {
buildLabelRow().appendTo(outputsDiv);
}
}
}
function buildLabelRow(type, index, value, placeHolder) {
var result = $('<div>',{class:"red-ui-editor-node-label-form-row"});
if (type === undefined) {
$('<span>').text(RED._("editor.noDefaultLabel")).appendTo(result);
result.addClass("red-ui-editor-node-label-form-none");
} else {
result.addClass("");
var id = "red-ui-editor-node-label-form-"+type+"-"+index;
$('<label>',{for:id}).text((index+1)+".").appendTo(result);
var input = $('<input>',{type:"text",id:id, placeholder: placeHolder}).val(value).appendTo(result);
var clear = $('<button type="button" class="red-ui-button red-ui-button-small"><i class="fa fa-times"></i></button>').appendTo(result);
clear.on("click", function(evt) {
evt.preventDefault();
input.val("");
})
}
return result;
}
function updateLabels(node, changes, outputMap) {
var inputLabels = $("#red-ui-editor-node-label-form-inputs").children().find("input");
var outputLabels = $("#red-ui-editor-node-label-form-outputs").children().find("input");
var hasNonBlankLabel = false;
var changed = false;
var newValue = inputLabels.map(function() {
var v = $(this).val();
hasNonBlankLabel = hasNonBlankLabel || v!== "";
return v;
}).toArray().slice(0,node.inputs);
if ((node.inputLabels === undefined && hasNonBlankLabel) ||
(node.inputLabels !== undefined && JSON.stringify(newValue) !== JSON.stringify(node.inputLabels))) {
changes.inputLabels = node.inputLabels;
node.inputLabels = newValue;
changed = true;
}
hasNonBlankLabel = false;
newValue = new Array(node.outputs);
outputLabels.each(function() {
var index = $(this).attr('id').substring("red-ui-editor-node-label-form-output-".length);
if (outputMap && outputMap.hasOwnProperty(index)) {
index = parseInt(outputMap[index]);
if (index === -1) {
return;
}
}
var v = $(this).val();
hasNonBlankLabel = hasNonBlankLabel || v!== "";
newValue[index] = v;
});
if ((node.outputLabels === undefined && hasNonBlankLabel) ||
(node.outputLabels !== undefined && JSON.stringify(newValue) !== JSON.stringify(node.outputLabels))) {
changes.outputLabels = node.outputLabels;
node.outputLabels = newValue;
changed = true;
}
return changed;
}
})();

View File

@ -0,0 +1,70 @@
;(function() {
RED.editor.registerEditPane("editor-tab-description", function(node) {
return {
label: RED._("editor-tab.description"),
name: RED._("editor-tab.description"),
iconClass: "fa fa-file-text-o",
create: function(container) {
this.editor = buildDescriptionForm(container,node);
RED.e = this.editor;
},
resize: function(size) {
this.editor.resize();
},
close: function() {
this.editor.destroy();
this.editor = null;
},
show: function() {
this.editor.focus();
},
apply: function(editState) {
var oldInfo = node.info;
var newInfo = this.editor.getValue();
if (!!oldInfo) {
// Has existing info property
if (newInfo.trim() === "") {
// New value is blank - remove the property
editState.changed = true;
editState.changes.info = oldInfo;
delete node.info;
} else if (newInfo !== oldInfo) {
// New value is different
editState.changed = true;
editState.changes.info = oldInfo;
node.info = newInfo;
}
} else {
// No existing info
if (newInfo.trim() !== "") {
// New value is not blank
editState.changed = true;
editState.changes.info = undefined;
node.info = newInfo;
}
}
}
}
});
function buildDescriptionForm(container,node) {
var dialogForm = $('<form class="dialog-form form-horizontal" autocomplete="off"></form>').appendTo(container);
var toolbarRow = $('<div></div>').appendTo(dialogForm);
var row = $('<div class="form-row node-text-editor-row" style="position:relative; padding-top: 4px; height: 100%"></div>').appendTo(dialogForm);
var editorId = "node-info-input-info-editor-"+Math.floor(1000*Math.random());
$('<div style="height: 100%" class="node-text-editor" id="'+editorId+'" ></div>').appendTo(row);
var nodeInfoEditor = RED.editor.createEditor({
id: editorId,
mode: 'ace/mode/markdown',
value: ""
});
if (node.info) {
nodeInfoEditor.getSession().setValue(node.info, -1);
}
node.infoEditor = nodeInfoEditor;
return nodeInfoEditor;
}
})();

View File

@ -0,0 +1,69 @@
;(function() {
RED.editor.registerEditPane("editor-tab-envProperties", function(node) {
return {
label: RED._("editor-tab.envProperties"),
name: RED._("editor-tab.envProperties"),
iconClass: "fa fa-list",
create: function(container) {
var form = $('<form class="dialog-form form-horizontal"></form>').appendTo(container);
var listContainer = $('<div class="form-row node-input-env-container-row"></div>').appendTo(form);
this.list = $('<ol></ol>').appendTo(listContainer);
RED.editor.envVarList.create(this.list, node);
},
resize: function(size) {
this.list.editableList('height',size.height);
},
close: function() {
},
apply: function(editState) {
var old_env = node.env;
var new_env = [];
if (/^subflow:/.test(node.type)) {
new_env = RED.subflow.exportSubflowInstanceEnv(node);
}
// Get the values from the Properties table tab
var items = this.list.editableList('items');
items.each(function (i,el) {
var data = el.data('data');
var item;
if (data.nameField && data.valueField) {
item = {
name: data.nameField.val(),
value: data.valueField.typedInput("value"),
type: data.valueField.typedInput("type")
}
if (item.name.trim() !== "") {
new_env.push(item);
}
}
});
if (new_env && new_env.length > 0) {
new_env.forEach(function(prop) {
if (prop.type === "cred") {
node.credentials = node.credentials || {_:{}};
node.credentials[prop.name] = prop.value;
node.credentials['has_'+prop.name] = (prop.value !== "");
if (prop.value !== '__PWRD__') {
editState.changed = true;
}
delete prop.value;
}
});
}
if (!isSameObj(old_env, new_env)) {
node.env = new_env;
editState.changes.env = node.env;
editState.changed = true;
}
}
}
});
function isSameObj(env0, env1) {
return (JSON.stringify(env0) === JSON.stringify(env1));
}
})();

View File

@ -0,0 +1,60 @@
;(function() {
RED.editor.registerEditPane("editor-tab-flow-properties", function(node) {
return {
label: RED._("editor-tab.properties"),
name: RED._("editor-tab.properties"),
iconClass: "fa fa-cog",
create: function(container) {
var dialogForm = $('<form id="dialog-form" class="form-horizontal"></form>').appendTo(container);
$('<div class="form-row">'+
'<label for="node-input-name" data-i18n="[append]editor:common.label.name"><i class="fa fa-tag"></i> </label>'+
'<input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">'+
'</div>').appendTo(dialogForm);
var row = $('<div class="form-row node-text-editor-row">'+
'<label for="node-input-info" data-i18n="editor:workspace.info" style="width:300px;"></label>'+
'<div style="min-height:150px;" class="node-text-editor" id="node-input-info"></div>'+
'</div>').appendTo(dialogForm);
this.tabflowEditor = RED.editor.createEditor({
id: 'node-input-info',
mode: 'ace/mode/markdown',
value: ""
});
$('<input type="text" style="display: none;" />').prependTo(dialogForm);
dialogForm.on("submit", function(e) { e.preventDefault();});
$("#node-input-name").val(node.label);
RED.text.bidi.prepareInput($("#node-input-name"));
this.tabflowEditor.getSession().setValue(node.info || "", -1);
},
resize: function(size) {
$("#node-input-info").css("height", (size.height-70)+"px");
this.tabflowEditor.resize();
},
close: function() {
this.tabflowEditor.destroy();
},
apply: function(editState) {
var label = $( "#node-input-name" ).val();
if (node.label != label) {
editState.changes.label = node.label;
editState.changed = true;
node.label = label;
}
var info = this.tabflowEditor.getValue();
if (node.info !== info) {
editState.changes.info = node.info;
editState.changed = true;
node.info = info;
}
$("#red-ui-tab-"+(node.id.replace(".","-"))).toggleClass('red-ui-workspace-disabled',!!node.disabled);
$("#red-ui-workspace").toggleClass("red-ui-workspace-disabled",!!node.disabled);
}
}
});
})();

View File

@ -0,0 +1,181 @@
;(function() {
RED.editor.registerEditPane("editor-tab-properties", function(node) {
return {
label: RED._("editor-tab.properties"),
name: RED._("editor-tab.properties"),
iconClass: "fa fa-cog",
create: function(container) {
var nodeType = node.type;
if (node.type === "subflow") {
nodeType = "subflow-template";
} else if (node.type.substring(0,8) == "subflow:") {
nodeType = "subflow";
}
var i18nNamespace;
if (node._def.set.module === "node-red") {
i18nNamespace = "node-red";
} else {
i18nNamespace = node._def.set.id;
}
var formStyle = "dialog-form";
this.inputClass = "node-input";
if (node._def.category === "config" && nodeType !== "group") {
this.inputClass = "node-config-input";
formStyle = "node-config-dialog-edit-form";
}
RED.editor.buildEditForm(container,formStyle,nodeType,i18nNamespace,node);
},
resize: function(size) {
if (node && node._def.oneditresize) {
try {
node._def.oneditresize.call(node,size);
} catch(err) {
console.log("oneditresize",node.id,node.type,err.toString());
}
}
},
close: function() {
},
apply: function(editState) {
var newValue;
var d;
if (node._def.defaults) {
for (d in node._def.defaults) {
if (node._def.defaults.hasOwnProperty(d)) {
var input = $("#"+this.inputClass+"-"+d);
if (input.attr('type') === "checkbox") {
newValue = input.prop('checked');
} else if (input.prop("nodeName") === "select" && input.attr("multiple") === "multiple") {
// An empty select-multiple box returns null.
// Need to treat that as an empty array.
newValue = input.val();
if (newValue == null) {
newValue = [];
}
} else if ("format" in node._def.defaults[d] && node._def.defaults[d].format !== "" && input[0].nodeName === "DIV") {
newValue = input.text();
} else {
newValue = input.val();
}
if (newValue != null) {
if (d === "outputs") {
if (newValue.trim() === "") {
continue;
}
if (isNaN(newValue)) {
editState.outputMap = JSON.parse(newValue);
var outputCount = 0;
var outputsChanged = false;
var keys = Object.keys(editState.outputMap);
keys.forEach(function(p) {
if (isNaN(p)) {
// New output;
outputCount ++;
delete editState.outputMap[p];
} else {
editState.outputMap[p] = editState.outputMap[p]+"";
if (editState.outputMap[p] !== "-1") {
outputCount++;
if (editState.outputMap[p] !== p) {
// Output moved
outputsChanged = true;
} else {
delete editState.outputMap[p];
}
} else {
// Output removed
outputsChanged = true;
}
}
});
newValue = outputCount;
if (outputsChanged) {
editState.changed = true;
}
} else {
newValue = parseInt(newValue);
}
}
if (node._def.defaults[d].type) {
if (newValue == "_ADD_") {
newValue = "";
}
}
if (node[d] != newValue) {
if (node._def.defaults[d].type) {
// Change to a related config node
var configNode = RED.nodes.node(node[d]);
if (configNode) {
var users = configNode.users;
users.splice(users.indexOf(node),1);
RED.events.emit("nodes:change",configNode);
}
configNode = RED.nodes.node(newValue);
if (configNode) {
configNode.users.push(node);
RED.events.emit("nodes:change",configNode);
}
}
editState.changes[d] = node[d];
node[d] = newValue;
editState.changed = true;
}
}
}
}
}
if (node._def.credentials) {
var credDefinition = node._def.credentials;
var credsChanged = updateNodeCredentials(node,credDefinition,this.inputClass);
editState.changed = editState.changed || credsChanged;
}
}
}
});
/**
* Update the node credentials from the edit form
* @param node - the node containing the credentials
* @param credDefinition - definition of the credentials
* @param prefix - prefix of the input fields
* @return {boolean} whether anything has changed
*/
function updateNodeCredentials(node, credDefinition, prefix) {
var changed = false;
if (!node.credentials) {
node.credentials = {_:{}};
} else if (!node.credentials._) {
node.credentials._ = {};
}
for (var cred in credDefinition) {
if (credDefinition.hasOwnProperty(cred)) {
var input = $("#" + prefix + '-' + cred);
if (input.length > 0) {
var value = input.val();
if (credDefinition[cred].type == 'password') {
node.credentials['has_' + cred] = (value !== "");
if (value == '__PWRD__') {
continue;
}
changed = true;
}
node.credentials[cred] = value;
if (value != node.credentials._[cred]) {
changed = true;
}
}
}
}
return changed;
}
})();

View File

@ -0,0 +1,179 @@
(function() {
var _subflowModulePaneTemplate = '<form class="dialog-form form-horizontal" autocomplete="off">'+
'<div class="form-row">'+
'<label for="subflow-input-module-module" data-i18n="[append]editor:subflow.module"><i class="fa fa-cube"></i> </label>'+
'<input style="width: calc(100% - 110px)" type="text" id="subflow-input-module-module" data-i18n="[placeholder]common.label.name">'+
'</div>'+
'<div class="form-row">'+
'<label for="subflow-input-module-type" data-i18n="[append]editor:subflow.type"> </label>'+
'<input style="width: calc(100% - 110px)" type="text" id="subflow-input-module-type">'+
'</div>'+
'<div class="form-row">'+
'<label for="subflow-input-module-version" data-i18n="[append]editor:subflow.version"></label>'+
'<input style="width: calc(100% - 110px)" type="text" id="subflow-input-module-version" data-i18n="[placeholder]editor:subflow.versionPlaceholder">'+
'</div>'+
'<div class="form-row">'+
'<label for="subflow-input-module-desc" data-i18n="[append]editor:subflow.desc"></label>'+
'<input style="width: calc(100% - 110px)" type="text" id="subflow-input-module-desc">'+
'</div>'+
'<div class="form-row">'+
'<label for="subflow-input-module-license" data-i18n="[append]editor:subflow.license"></label>'+
'<input style="width: calc(100% - 110px)" type="text" id="subflow-input-module-license">'+
'</div>'+
'<div class="form-row">'+
'<label for="subflow-input-module-author" data-i18n="[append]editor:subflow.author"></label>'+
'<input style="width: calc(100% - 110px)" type="text" id="subflow-input-module-author" data-i18n="[placeholder]editor:subflow.authorPlaceholder">'+
'</div>'+
'<div class="form-row">'+
'<label for="subflow-input-module-keywords" data-i18n="[append]editor:subflow.keys"></label>'+
'<input style="width: calc(100% - 110px)" type="text" id="subflow-input-module-keywords" data-i18n="[placeholder]editor:subflow.keysPlaceholder">'+
'</div>'+
'</form>';
RED.editor.registerEditPane("editor-tab-subflow-module", function(node) {
return {
label: RED._("editor-tab.module"),
name: RED._("editor-tab.module"),
iconClass: "fa fa-cube",
create: function(container) {
buildModuleForm(container, node);
},
resize: function(size) {
},
close: function() {
},
apply: function(editState) {
var newMeta = exportSubflowModuleProperties(node);
if (!isSameObj(node.meta,newMeta)) {
editState.changes.meta = node.meta;
node.meta = newMeta;
editState.changed = true;
}
}
}
});
function isSameObj(env0, env1) {
return (JSON.stringify(env0) === JSON.stringify(env1));
}
function setupInputValidation(input,validator) {
var errorTip;
var validateTimeout;
var validateFunction = function() {
if (validateTimeout) {
return;
}
validateTimeout = setTimeout(function() {
var error = validator(input.val());
// if (!error && errorTip) {
// errorTip.close();
// errorTip = null;
// } else if (error && !errorTip) {
// errorTip = RED.popover.create({
// tooltip: true,
// target:input,
// size: "small",
// direction: "bottom",
// content: error,
// }).open();
// }
input.toggleClass("input-error",!!error);
validateTimeout = null;
})
}
input.on("change keyup paste", validateFunction);
}
function buildModuleForm(container, node) {
$(_subflowModulePaneTemplate).appendTo(container);
var moduleProps = node.meta || {};
[
'module',
'type',
'version',
'author',
'desc',
'keywords',
'license'
].forEach(function(property) {
$("#subflow-input-module-"+property).val(moduleProps[property]||"")
})
$("#subflow-input-module-type").attr("placeholder",node.id);
setupInputValidation($("#subflow-input-module-module"), function(newValue) {
newValue = newValue.trim();
var isValid = newValue.length < 215;
isValid = isValid && !/^[._]/.test(newValue);
isValid = isValid && !/[A-Z]/.test(newValue);
if (newValue !== encodeURIComponent(newValue)) {
var m = /^@([^\/]+)\/([^\/]+)$/.exec(newValue);
if (m) {
isValid = isValid && (m[1] === encodeURIComponent(m[1]) && m[2] === encodeURIComponent(m[2]))
} else {
isValid = false;
}
}
return isValid?"":"Invalid module name"
})
setupInputValidation($("#subflow-input-module-version"), function(newValue) {
newValue = newValue.trim();
var isValid = newValue === "" ||
/^(\d|[1-9]\d*)\.(\d|[1-9]\d*)\.(\d|[1-9]\d*)(-(0|[1-9A-Za-z-][0-9A-Za-z-]*|[0-9]*[A-Za-z-][0-9A-Za-z-]*)(\.(0|[1-9A-Za-z-][0-9A-Za-z-]*|[0-9]*[A-Za-z-][0-9A-Za-z-]*))*)?(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$/.test(newValue);
return isValid?"":"Invalid version number"
})
var licenses = ["none", "Apache-2.0", "BSD-3-Clause", "BSD-2-Clause", "GPL-2.0", "GPL-3.0", "MIT", "MPL-2.0", "CDDL-1.0", "EPL-2.0"];
var typedLicenses = {
types: licenses.map(function(l) {
return {
value: l,
label: l === "none" ? RED._("editor:subflow.licenseNone") : l,
hasValue: false
};
})
}
typedLicenses.types.push({
value:"_custom_", label:RED._("editor:subflow.licenseOther"), icon:"red/images/typedInput/az.svg"
})
if (!moduleProps.license) {
typedLicenses.default = "none";
} else if (licenses.indexOf(moduleProps.license) > -1) {
typedLicenses.default = moduleProps.license;
} else {
typedLicenses.default = "_custom_";
}
$("#subflow-input-module-license").typedInput(typedLicenses)
}
function exportSubflowModuleProperties(node) {
var value;
var moduleProps = {};
[
'module',
'type',
'version',
'author',
'desc',
'keywords'
].forEach(function(property) {
value = $("#subflow-input-module-"+property).val().trim();
if (value) {
moduleProps[property] = value;
}
})
var selectedLicenseType = $("#subflow-input-module-license").typedInput("type");
if (selectedLicenseType === '_custom_') {
value = $("#subflow-input-module-license").val();
if (value) {
moduleProps.license = value;
}
} else if (selectedLicenseType !== "none") {
moduleProps.license = selectedLicenseType;
}
return moduleProps;
}
})();

View File

@ -87,16 +87,18 @@ RED.group = (function() {
"label-position": "nw" "label-position": "nw"
}; };
var groupDef = { var groupDef = {
defaults:{ defaults:{
name:{value:""}, name:{value:""},
style:{value:{label:true}}, style:{value:{label:true}},
nodes:{value:[]} nodes:{value:[]},
env: {value:[]},
}, },
category: "config", category: "config",
oneditprepare: function() { oneditprepare: function() {
var style = this.style || {}; var style = this.style || {};
RED.colorPicker.create({ RED.editor.colorPicker.create({
id:"node-input-style-stroke", id:"node-input-style-stroke",
value: style.stroke || defaultGroupStyle.stroke || "#a4a4a4", value: style.stroke || defaultGroupStyle.stroke || "#a4a4a4",
palette: colorPalette, palette: colorPalette,
@ -107,7 +109,7 @@ RED.group = (function() {
none: true, none: true,
opacity: style.hasOwnProperty('stroke-opacity')?style['stroke-opacity']:(defaultGroupStyle.hasOwnProperty('stroke-opacity')?defaultGroupStyle['stroke-opacity']:1.0) opacity: style.hasOwnProperty('stroke-opacity')?style['stroke-opacity']:(defaultGroupStyle.hasOwnProperty('stroke-opacity')?defaultGroupStyle['stroke-opacity']:1.0)
}).appendTo("#node-input-row-style-stroke"); }).appendTo("#node-input-row-style-stroke");
RED.colorPicker.create({ RED.editor.colorPicker.create({
id:"node-input-style-fill", id:"node-input-style-fill",
value: style.fill || defaultGroupStyle.fill ||"none", value: style.fill || defaultGroupStyle.fill ||"none",
palette: colorPalette, palette: colorPalette,
@ -124,7 +126,7 @@ RED.group = (function() {
value:style["label-position"] || "nw" value:style["label-position"] || "nw"
}).appendTo("#node-input-row-style-label-position"); }).appendTo("#node-input-row-style-label-position");
RED.colorPicker.create({ RED.editor.colorPicker.create({
id:"node-input-style-color", id:"node-input-style-color",
value: style.color || defaultGroupStyle.color ||"#a4a4a4", value: style.color || defaultGroupStyle.color ||"#a4a4a4",
palette: colorPalette, palette: colorPalette,
@ -144,7 +146,6 @@ RED.group = (function() {
}) })
$("#node-input-style-label").prop("checked", this.style.label) $("#node-input-style-label").prop("checked", this.style.label)
$("#node-input-style-label").trigger("change"); $("#node-input-style-label").trigger("change");
}, },
oneditresize: function(size) { oneditresize: function(size) {
}, },
@ -183,7 +184,9 @@ RED.group = (function() {
var activateUngroup = false; var activateUngroup = false;
var activateMerge = false; var activateMerge = false;
var activateRemove = false; var activateRemove = false;
var singleGroupSelected = false;
if (activateGroup) { if (activateGroup) {
singleGroupSelected = selection.nodes.length === 1 && selection.nodes[0].type === 'group';
selection.nodes.forEach(function (n) { selection.nodes.forEach(function (n) {
if (n.type === "group") { if (n.type === "group") {
activateUngroup = true; activateUngroup = true;
@ -200,6 +203,8 @@ RED.group = (function() {
RED.menu.setDisabled("menu-item-group-ungroup", !activateUngroup); RED.menu.setDisabled("menu-item-group-ungroup", !activateUngroup);
RED.menu.setDisabled("menu-item-group-merge", !activateMerge); RED.menu.setDisabled("menu-item-group-merge", !activateMerge);
RED.menu.setDisabled("menu-item-group-remove", !activateRemove); RED.menu.setDisabled("menu-item-group-remove", !activateRemove);
RED.menu.setDisabled("menu-item-edit-copy-group-style", !singleGroupSelected);
RED.menu.setDisabled("menu-item-edit-paste-group-style", !activateUngroup);
}); });
RED.actions.add("core:group-selection", function() { groupSelection() }) RED.actions.add("core:group-selection", function() { groupSelection() })
@ -252,6 +257,7 @@ RED.group = (function() {
if (selection.nodes && selection.nodes.length === 1 && selection.nodes[0].type === 'group') { if (selection.nodes && selection.nodes.length === 1 && selection.nodes[0].type === 'group') {
groupStyleClipboard = JSON.parse(JSON.stringify(selection.nodes[0].style)); groupStyleClipboard = JSON.parse(JSON.stringify(selection.nodes[0].style));
RED.notify(RED._("clipboard.groupStyleCopied"),{id:"clipboard"}) RED.notify(RED._("clipboard.groupStyleCopied"),{id:"clipboard"})
RED.menu.setDisabled("menu-item-edit-paste-group-style", false)
} }
} }
function pasteGroupStyle() { function pasteGroupStyle() {

View File

@ -131,7 +131,7 @@ RED.keyboard = (function() {
return mergedKeymap; return mergedKeymap;
} }
function init() { function init(done) {
// Migrate from pre-0.18 // Migrate from pre-0.18
migrateOldKeymap(); migrateOldKeymap();
@ -164,6 +164,7 @@ RED.keyboard = (function() {
} }
} }
} }
done();
}); });
RED.userSettings.add({ RED.userSettings.add({
@ -174,6 +175,9 @@ RED.keyboard = (function() {
setTimeout(function() { setTimeout(function() {
$("#red-ui-settings-tab-keyboard-filter").trigger("focus"); $("#red-ui-settings-tab-keyboard-filter").trigger("focus");
},200); },200);
},
close: function() {
RED.menu.refreshShortcuts();
} }
}) })
} }
@ -239,7 +243,13 @@ RED.keyboard = (function() {
function resolveKeyEvent(evt) { function resolveKeyEvent(evt) {
var slot = partialState||handlers; var slot = partialState||handlers;
if (evt.ctrlKey || evt.metaKey) { // We cheat with MacOS CMD key and consider it the same as Ctrl.
// That means we don't have to have separate keymaps for different OS.
// It mostly works.
// One exception is shortcuts that include both Cmd and Ctrl. We don't
// support them - but we need to make sure we don't block browser-specific
// shortcuts (such as Cmd-Ctrl-F for fullscreen).
if ((evt.ctrlKey || evt.metaKey) && (evt.ctrlKey !== evt.metaKey)) {
slot = slot.ctrl; slot = slot.ctrl;
} }
if (slot && evt.shiftKey) { if (slot && evt.shiftKey) {

View File

@ -536,7 +536,7 @@ RED.library = (function() {
// evt.preventDefault(); // evt.preventDefault();
// var icon = libraryFields['icon'].input.val() || ""; // var icon = libraryFields['icon'].input.val() || "";
// var iconPath = (icon ? RED.utils.separateIconPath(icon) : {}); // var iconPath = (icon ? RED.utils.separateIconPath(icon) : {});
// RED.editor.showIconPicker(iconButton, null, iconPath, true, function (newIcon) { // RED.editor.iconPicker.show(iconButton, null, iconPath, true, function (newIcon) {
// iconButton.empty(); // iconButton.empty();
// var path = newIcon || ""; // var path = newIcon || "";
// var newPath = RED.utils.separateIconPath(path); // var newPath = RED.utils.separateIconPath(path);

View File

@ -45,6 +45,22 @@ RED.notifications = (function() {
var persistentNotifications = {}; var persistentNotifications = {};
var shade = (function() {
var shadeUsers = 0;
return {
show: function() {
shadeUsers++;
$("#red-ui-full-shade").show();
},
hide: function() {
shadeUsers--;
if (shadeUsers === 0) {
$("#red-ui-full-shade").hide();
}
}
}
})();
var currentNotifications = []; var currentNotifications = [];
var c = 0; var c = 0;
function notify(msg,type,fixed,timeout) { function notify(msg,type,fixed,timeout) {
@ -54,6 +70,10 @@ RED.notifications = (function() {
fixed = options.fixed; fixed = options.fixed;
timeout = options.timeout; timeout = options.timeout;
type = options.type; type = options.type;
} else {
options.type = type;
options.fixed = fixed;
options.timeout = options.timeout;
} }
if (options.id && persistentNotifications.hasOwnProperty(options.id)) { if (options.id && persistentNotifications.hasOwnProperty(options.id)) {
@ -62,7 +82,7 @@ RED.notifications = (function() {
} }
if (options.modal) { if (options.modal) {
$("#red-ui-full-shade").show(); shade.show();
} }
if (currentNotifications.length > 4) { if (currentNotifications.length > 4) {
@ -79,6 +99,8 @@ RED.notifications = (function() {
var n = document.createElement("div"); var n = document.createElement("div");
n.id="red-ui-notification-"+c; n.id="red-ui-notification-"+c;
n.className = "red-ui-notification"; n.className = "red-ui-notification";
n.options = options;
n.fixed = fixed; n.fixed = fixed;
if (type) { if (type) {
n.className = "red-ui-notification red-ui-notification-"+type; n.className = "red-ui-notification red-ui-notification-"+type;
@ -115,7 +137,6 @@ RED.notifications = (function() {
}) })
} }
$("#red-ui-notifications").append(n); $("#red-ui-notifications").append(n);
if (!RED.notifications.hide) { if (!RED.notifications.hide) {
$(n).slideDown(300); $(n).slideDown(300);
@ -141,8 +162,8 @@ RED.notifications = (function() {
} else { } else {
nn.parentNode.removeChild(nn); nn.parentNode.removeChild(nn);
} }
if (options.modal) { if (nn.options.modal) {
$("#red-ui-full-shade").hide(); shade.hide();
} }
}; };
})(); })();
@ -173,7 +194,7 @@ RED.notifications = (function() {
n.update = (function() { n.update = (function() {
var nn = n; var nn = n;
return function(msg,options) { return function(msg,newOptions) {
if (typeof msg === "string") { if (typeof msg === "string") {
if (!/<p>/i.test(msg)) { if (!/<p>/i.test(msg)) {
msg = "<p>"+msg+"</p>"; msg = "<p>"+msg+"</p>";
@ -182,16 +203,31 @@ RED.notifications = (function() {
} else { } else {
$(nn).empty().append(msg); $(nn).empty().append(msg);
} }
var timeout; var newTimeout;
if (typeof options === 'number') { if (typeof newOptions === 'number') {
timeout = options; newTimeout = newOptions;
} else if (options !== undefined) { nn.options.timeout = newTimeout;
if (!options.fixed) { } else if (newOptions !== undefined) {
timeout = options.timeout || 5000;
if (!options.modal && newOptions.modal) {
nn.options.modal = true;
shade.show();
} else if (options.modal && newOptions.modal === false) {
nn.options.modal = false;
shade.hide();
} }
if (options.buttons) {
var newType = newOptions.hasOwnProperty('type')?newOptions.type:type;
if (newType) {
n.className = "red-ui-notification red-ui-notification-"+newType;
}
if (!fixed || newOptions.fixed === false) {
newTimeout = (newOptions.hasOwnProperty('timeout')?newOptions.timeout:timeout)||5000;
}
if (newOptions.buttons) {
var buttonSet = $('<div style="margin-top: 20px;" class="ui-dialog-buttonset"></div>').appendTo(nn) var buttonSet = $('<div style="margin-top: 20px;" class="ui-dialog-buttonset"></div>').appendTo(nn)
options.buttons.forEach(function(buttonDef) { newOptions.buttons.forEach(function(buttonDef) {
var b = $('<button>').text(buttonDef.text).on("click", buttonDef.click).appendTo(buttonSet); var b = $('<button>').text(buttonDef.text).on("click", buttonDef.click).appendTo(buttonSet);
if (buttonDef.id) { if (buttonDef.id) {
b.attr('id',buttonDef.id); b.attr('id',buttonDef.id);
@ -202,15 +238,22 @@ RED.notifications = (function() {
}) })
} }
} }
if (timeout !== undefined && timeout > 0) { $(nn).off("click.red-ui-notification-close");
if (newTimeout !== undefined && newTimeout > 0) {
window.clearTimeout(nn.timeoutid); window.clearTimeout(nn.timeoutid);
nn.timeoutid = window.setTimeout(nn.close,timeout); nn.timeoutid = window.setTimeout(nn.close,newTimeout);
setTimeout(function() {
$(nn).on("click.red-ui-notification-close", function() {
nn.close();
window.clearTimeout(nn.timeoutid);
});
},50);
} else { } else {
window.clearTimeout(nn.timeoutid); window.clearTimeout(nn.timeoutid);
} }
if (nn.hidden) { if (nn.hidden) {
nn.showNotification(); nn.showNotification();
} else if (!options || !options.silent){ } else if (!newOptions || !newOptions.silent){
$(nn).addClass("red-ui-notification-shake-horizontal"); $(nn).addClass("red-ui-notification-shake-horizontal");
setTimeout(function() { setTimeout(function() {
$(nn).removeClass("red-ui-notification-shake-horizontal"); $(nn).removeClass("red-ui-notification-shake-horizontal");
@ -221,7 +264,7 @@ RED.notifications = (function() {
})(); })();
if (!fixed) { if (!fixed) {
$(n).on("click", (function() { $(n).on("click.red-ui-notification-close", (function() {
var nn = n; var nn = n;
return function() { return function() {
nn.close(); nn.close();

View File

@ -333,7 +333,10 @@ RED.palette.editor = (function() {
nodeEntry.versionSpan.html(moduleInfo.version+' <i class="fa fa-long-arrow-right"></i> '+moduleInfo.pending_version).appendTo(nodeEntry.metaRow) nodeEntry.versionSpan.html(moduleInfo.version+' <i class="fa fa-long-arrow-right"></i> '+moduleInfo.pending_version).appendTo(nodeEntry.metaRow)
nodeEntry.updateButton.text(RED._('palette.editor.updated')).addClass('disabled').css('display', 'inline-block'); nodeEntry.updateButton.text(RED._('palette.editor.updated')).addClass('disabled').css('display', 'inline-block');
} else if (loadedIndex.hasOwnProperty(module)) { } else if (loadedIndex.hasOwnProperty(module)) {
if (semVerCompare(loadedIndex[module].version,moduleInfo.version) > 0) { if (updateAllowed &&
semVerCompare(loadedIndex[module].version,moduleInfo.version) > 0 &&
RED.utils.checkModuleAllowed(module,null,updateAllowList,updateDenyList)
) {
nodeEntry.updateButton.show(); nodeEntry.updateButton.show();
nodeEntry.updateButton.text(RED._('palette.editor.update',{version:loadedIndex[module].version})); nodeEntry.updateButton.text(RED._('palette.editor.update',{version:loadedIndex[module].version}));
} else { } else {
@ -484,6 +487,9 @@ RED.palette.editor = (function() {
var installAllowList = ['*']; var installAllowList = ['*'];
var installDenyList = []; var installDenyList = [];
var updateAllowed = true;
var updateAllowList = ['*'];
var updateDenyList = [];
function init() { function init() {
if (RED.settings.get('externalModules.palette.allowInstall', true) === false) { if (RED.settings.get('externalModules.palette.allowInstall', true) === false) {
@ -498,6 +504,17 @@ RED.palette.editor = (function() {
installAllowList = RED.utils.parseModuleList(installAllowList); installAllowList = RED.utils.parseModuleList(installAllowList);
installDenyList = RED.utils.parseModuleList(installDenyList); installDenyList = RED.utils.parseModuleList(installDenyList);
var settingsUpdateAllowList = RED.settings.get("externalModules.palette.allowUpdateList")
var settingsUpdateDenyList = RED.settings.get("externalModules.palette.denyUpdateList")
if (settingsUpdateAllowList || settingsUpdateDenyList) {
updateAllowList = settingsUpdateAllowList;
updateDenyList = settingsUpdateDenyList;
}
updateAllowList = RED.utils.parseModuleList(updateAllowList);
updateDenyList = RED.utils.parseModuleList(updateDenyList);
updateAllowed = RED.settings.get("externalModules.palette.allowUpdate",true);
createSettingsPane(); createSettingsPane();
RED.userSettings.add({ RED.userSettings.add({

View File

@ -2387,6 +2387,7 @@ RED.projects = (function() {
return { return {
init: init, init: init,
showStartup: function() { showStartup: function() {
console.warn("showStartup")
if (!RED.user.hasPermission("projects.write")) { if (!RED.user.hasPermission("projects.write")) {
RED.notify(RED._("user.errors.notAuthorized"),"error"); RED.notify(RED._("user.errors.notAuthorized"),"error");
return; return;

View File

@ -16,8 +16,6 @@
RED.subflow = (function() { RED.subflow = (function() {
var currentLocale = "en-US";
var _subflowEditTemplate = '<script type="text/x-red" data-template-name="subflow">'+ var _subflowEditTemplate = '<script type="text/x-red" data-template-name="subflow">'+
'<div class="form-row">'+ '<div class="form-row">'+
'<label for="node-input-name" data-i18n="[append]editor:common.label.name"><i class="fa fa-tag"></i> </label>'+ '<label for="node-input-name" data-i18n="[append]editor:common.label.name"><i class="fa fa-tag"></i> </label>'+
@ -37,7 +35,7 @@ RED.subflow = (function() {
'<div id="subflow-env-tabs-content">'+ '<div id="subflow-env-tabs-content">'+
'<div id="subflow-env-tab-edit">'+ '<div id="subflow-env-tab-edit">'+
'<div class="form-row node-input-env-container-row" id="subflow-input-edit-ui">'+ '<div class="form-row node-input-env-container-row" id="subflow-input-edit-ui">'+
'<ol class="red-ui-editor-subflow-env-list" id="node-input-env-container"></ol>'+ '<ol id="node-input-env-container"></ol>'+
'<div class="node-input-env-locales-row"><i class="fa fa-language"></i> <select id="subflow-input-env-locale"></select></div>'+ '<div class="node-input-env-locales-row"><i class="fa fa-language"></i> <select id="subflow-input-env-locale"></select></div>'+
'</div>'+ '</div>'+
'</div>'+ '</div>'+
@ -47,37 +45,6 @@ RED.subflow = (function() {
'</div>'+ '</div>'+
'</script>'; '</script>';
var _subflowModulePaneTemplate = '<form class="dialog-form form-horizontal" autocomplete="off">'+
'<div class="form-row">'+
'<label for="subflow-input-module-module" data-i18n="[append]editor:subflow.module"><i class="fa fa-cube"></i> </label>'+
'<input style="width: calc(100% - 110px)" type="text" id="subflow-input-module-module" data-i18n="[placeholder]common.label.name">'+
'</div>'+
'<div class="form-row">'+
'<label for="subflow-input-module-type" data-i18n="[append]editor:subflow.type"> </label>'+
'<input style="width: calc(100% - 110px)" type="text" id="subflow-input-module-type">'+
'</div>'+
'<div class="form-row">'+
'<label for="subflow-input-module-version" data-i18n="[append]editor:subflow.version"></label>'+
'<input style="width: calc(100% - 110px)" type="text" id="subflow-input-module-version" data-i18n="[placeholder]editor:subflow.versionPlaceholder">'+
'</div>'+
'<div class="form-row">'+
'<label for="subflow-input-module-desc" data-i18n="[append]editor:subflow.desc"></label>'+
'<input style="width: calc(100% - 110px)" type="text" id="subflow-input-module-desc">'+
'</div>'+
'<div class="form-row">'+
'<label for="subflow-input-module-license" data-i18n="[append]editor:subflow.license"></label>'+
'<input style="width: calc(100% - 110px)" type="text" id="subflow-input-module-license">'+
'</div>'+
'<div class="form-row">'+
'<label for="subflow-input-module-author" data-i18n="[append]editor:subflow.author"></label>'+
'<input style="width: calc(100% - 110px)" type="text" id="subflow-input-module-author" data-i18n="[placeholder]editor:subflow.authorPlaceholder">'+
'</div>'+
'<div class="form-row">'+
'<label for="subflow-input-module-keywords" data-i18n="[append]editor:subflow.keys"></label>'+
'<input style="width: calc(100% - 110px)" type="text" id="subflow-input-module-keywords" data-i18n="[placeholder]editor:subflow.keysPlaceholder">'+
'</div>'+
'</form>';
function findAvailableSubflowIOPosition(subflow,isInput) { function findAvailableSubflowIOPosition(subflow,isInput) {
var pos = {x:50,y:30}; var pos = {x:50,y:30};
if (!isInput) { if (!isInput) {
@ -909,7 +876,6 @@ RED.subflow = (function() {
* Create interface for controlling env var UI definition * Create interface for controlling env var UI definition
*/ */
function buildEnvControl(envList,node) { function buildEnvControl(envList,node) {
var tabs = RED.tabs.create({ var tabs = RED.tabs.create({
id: "subflow-env-tabs", id: "subflow-env-tabs",
onchange: function(tab) { onchange: function(tab) {
@ -950,588 +916,11 @@ RED.subflow = (function() {
locales.val(locale); locales.val(locale);
locales.on("change", function() { locales.on("change", function() {
currentLocale = $(this).val(); RED.editor.envVarList.setLocale($(this).val(), $("#node-input-env-container"));
var items = $("#node-input-env-container").editableList("items");
items.each(function (i, item) {
var entry = $(this).data('data');
var labelField = entry.ui.labelField;
labelField.val(lookupLabel(entry.ui.label, "", currentLocale));
if (labelField.timeout) {
clearTimeout(labelField.timeout);
delete labelField.timeout;
}
labelField.addClass("input-updated");
labelField.timeout = setTimeout(function() {
delete labelField.timeout
labelField.removeClass("input-updated");
},3000);
});
}); });
RED.editor.envVarList.setLocale(locale);
} }
var DEFAULT_ENV_TYPE_LIST = ['str','num','bool','json','bin','env'];
var DEFAULT_ENV_TYPE_LIST_INC_CRED = ['str','num','bool','json','bin','env','cred'];
/**
* Create env var edit interface
* @param container - container
* @param node - subflow node
*/
function buildPropertiesList(envContainer, node) {
var isTemplateNode = (node.type === "subflow");
if (isTemplateNode) {
buildEnvControl(envContainer, node);
}
envContainer
.css({
'min-height':'150px',
'min-width':'450px'
})
.editableList({
header: isTemplateNode?$('<div><div><div></div><div data-i18n="common.label.name"></div><div data-i18n="editor-tab.defaultValue"></div><div></div></div></div>'):undefined,
addItem: function(container, i, opt) {
// If this is an instance node, these are properties unique to
// this instance - ie opt.parent will not be defined.
if (isTemplateNode) {
container.addClass("red-ui-editor-subflow-env-editable")
}
var envRow = $('<div/>').appendTo(container);
var nameField = null;
var valueField = null;
nameField = $('<input/>', {
class: "node-input-env-name",
type: "text",
placeholder: RED._("common.label.name")
}).attr("autocomplete","disable").appendTo(envRow).val(opt.name);
valueField = $('<input/>',{
style: "width:100%",
class: "node-input-env-value",
type: "text",
}).attr("autocomplete","disable").appendTo(envRow)
valueField.typedInput({default:'str',types:isTemplateNode?DEFAULT_ENV_TYPE_LIST:DEFAULT_ENV_TYPE_LIST_INC_CRED});
valueField.typedInput('type', opt.type);
if (opt.type === "cred") {
if (opt.value) {
valueField.typedInput('value', opt.value);
} else if (node.credentials && node.credentials[opt.name]) {
valueField.typedInput('value', node.credentials[opt.name]);
} else if (node.credentials && node.credentials['has_'+opt.name]) {
valueField.typedInput('value', "__PWRD__");
} else {
valueField.typedInput('value', "");
}
} else {
valueField.typedInput('value', opt.value);
}
opt.nameField = nameField;
opt.valueField = valueField;
var actionButton = $('<a/>',{href:"#",class:"red-ui-editableList-item-remove red-ui-button red-ui-button-small"}).appendTo(envRow);
$('<i/>',{class:"fa "+(opt.parent?"fa-reply":"fa-remove")}).appendTo(actionButton);
var removeTip = RED.popover.tooltip(actionButton,RED._("subflow.env.remove"));
actionButton.on("click", function(evt) {
evt.preventDefault();
removeTip.close();
container.parent().addClass("red-ui-editableList-item-deleting")
container.fadeOut(300, function() {
envContainer.editableList('removeItem',opt);
});
});
if (isTemplateNode) {
// Add the UI customisation row
// if `opt.ui` does not exist, then apply defaults. If these
// defaults do not change then they will get stripped off
// before saving.
if (opt.type === 'cred') {
opt.ui = opt.ui || {
icon: "",
type: "cred"
}
opt.ui.type = "cred";
} else {
opt.ui = opt.ui || {
icon: "",
type: "input",
opts: {types:DEFAULT_ENV_TYPE_LIST}
}
}
opt.ui.label = opt.ui.label || {};
opt.ui.type = opt.ui.type || "input";
var uiRow = $('<div/>').appendTo(container).hide();
// save current info for reverting on cancel
// var copy = $.extend(true, {}, ui);
$('<a href="#"><i class="fa fa-angle-right"></a>').prependTo(envRow).on("click", function (evt) {
evt.preventDefault();
if ($(this).hasClass('expanded')) {
uiRow.slideUp();
$(this).removeClass('expanded');
} else {
uiRow.slideDown();
$(this).addClass('expanded');
}
});
buildEnvEditRow(uiRow, opt.ui, nameField, valueField);
nameField.trigger('change');
}
},
sortable: ".red-ui-editableList-item-handle",
removable: false
});
var parentEnv = {};
var envList = [];
if (/^subflow:/.test(node.type)) {
var subflowDef = RED.nodes.subflow(node.type.substring(8));
if (subflowDef.env) {
subflowDef.env.forEach(function(env) {
var item = {
name:env.name,
parent: {
type: env.type,
value: env.value,
ui: env.ui
}
}
envList.push(item);
parentEnv[env.name] = item;
})
}
}
if (node.env) {
for (var i = 0; i < node.env.length; i++) {
var env = node.env[i];
if (parentEnv.hasOwnProperty(env.name)) {
parentEnv[env.name].type = env.type;
parentEnv[env.name].value = env.value;
} else {
envList.push({
name: env.name,
type: env.type,
value: env.value,
ui: env.ui
});
}
}
}
envList.forEach(function(env) {
if (env.parent && env.parent.ui && env.parent.ui.type === 'hide') {
return;
}
if (!isTemplateNode && env.parent) {
return;
}
envContainer.editableList('addItem', JSON.parse(JSON.stringify(env)));
});
}
/**
* Create UI edit interface for environment variable
* @param container - container
* @param env - env var definition
* @param nameField - name field of env var
* @param valueField - value field of env var
*/
function buildEnvEditRow(container, ui, nameField, valueField) {
container.addClass("red-ui-editor-subflow-env-ui-row")
var topRow = $('<div></div>').appendTo(container);
$('<div></div>').appendTo(topRow);
$('<div>').text(RED._("editor.icon")).appendTo(topRow);
$('<div>').text(RED._("editor.label")).appendTo(topRow);
$('<div>').text(RED._("editor.inputType")).appendTo(topRow);
var row = $('<div></div>').appendTo(container);
$('<div><i class="red-ui-editableList-item-handle fa fa-bars"></i></div>').appendTo(row);
var typeOptions = {
'input': {types:DEFAULT_ENV_TYPE_LIST},
'select': {opts:[]},
'spinner': {},
'cred': {}
};
if (ui.opts) {
typeOptions[ui.type] = ui.opts;
} else {
// Pick up the default values if not otherwise provided
ui.opts = typeOptions[ui.type];
}
var iconCell = $('<div></div>').appendTo(row);
var iconButton = $('<a href="#"></a>').appendTo(iconCell);
iconButton.on("click", function(evt) {
evt.preventDefault();
var icon = ui.icon || "";
var iconPath = (icon ? RED.utils.separateIconPath(icon) : {});
RED.editor.showIconPicker(iconButton, null, iconPath, true, function (newIcon) {
iconButton.empty();
var path = newIcon || "";
var newPath = RED.utils.separateIconPath(path);
if (newPath) {
$('<i class="fa"></i>').addClass(newPath.file).appendTo(iconButton);
}
ui.icon = path;
});
})
if (ui.icon) {
var newPath = RED.utils.separateIconPath(ui.icon);
$('<i class="fa '+newPath.file+'"></i>').appendTo(iconButton);
}
var labelCell = $('<div></div>').appendTo(row);
var label = ui.label && ui.label[currentLocale] || "";
var labelInput = $('<input type="text">').val(label).appendTo(labelCell);
ui.labelField = labelInput;
labelInput.on('change', function(evt) {
ui.label = ui.label || {};
var val = $(this).val().trim();
if (val === "") {
delete ui.label[currentLocale];
} else {
ui.label[currentLocale] = val;
}
})
var labelIcon = $('<span class="red-ui-editor-subflow-env-lang-icon"><i class="fa fa-language"></i></span>').appendTo(labelCell);
RED.popover.tooltip(labelIcon,function() {
var langs = Object.keys(ui.label);
var content = $("<div>");
if (langs.indexOf(currentLocale) === -1) {
langs.push(currentLocale);
langs.sort();
}
langs.forEach(function(l) {
var row = $('<div>').appendTo(content);
$('<span>').css({display:"inline-block",width:"120px"}).text(RED._("languages."+l)+(l===currentLocale?"*":"")).appendTo(row);
$('<span>').text(ui.label[l]||"").appendTo(row);
});
return content;
})
nameField.on('change',function(evt) {
labelInput.attr("placeholder",$(this).val())
});
var inputCell = $('<div></div>').appendTo(row);
var inputCellInput = $('<input type="text">').css("width","100%").appendTo(inputCell);
if (ui.type === "input") {
inputCellInput.val(ui.opts.types.join(","));
}
var checkbox;
var selectBox;
inputCellInput.typedInput({
types: [
{
value:"input",
label:RED._("editor.inputs.input"), icon:"fa fa-i-cursor",showLabel:false,multiple:true,options:[
{value:"str",label:RED._("editor.types.str"),icon:"red/images/typedInput/az.svg"},
{value:"num",label:RED._("editor.types.num"),icon:"red/images/typedInput/09.svg"},
{value:"bool",label:RED._("editor.types.bool"),icon:"red/images/typedInput/bool.svg"},
{value:"json",label:RED._("editor.types.json"),icon:"red/images/typedInput/json.svg"},
{value: "bin",label: RED._("editor.types.bin"),icon: "red/images/typedInput/bin.svg"},
{value: "env",label: RED._("editor.types.env"),icon: "red/images/typedInput/env.svg"},
{value: "cred",label: RED._("editor.types.cred"),icon: "fa fa-lock"}
],
default: DEFAULT_ENV_TYPE_LIST,
valueLabel: function(container,value) {
container.css("padding",0);
var innerContainer = $('<div class="red-ui-editor-subflow-env-input-type"></div>').appendTo(container);
var input = $('<div class="placeholder-input">').appendTo(innerContainer);
$('<span><i class="fa fa-i-cursor"></i></span>').appendTo(input);
if (value.length) {
value.forEach(function(v) {
if (!/^fa /.test(v.icon)) {
$('<img>',{src:v.icon,style:"max-width:14px; padding: 0 3px; margin-top:-4px; margin-left: 1px"}).appendTo(input);
} else {
var s = $('<span>',{style:"max-width:14px; padding: 0 3px; margin-top:-4px; margin-left: 1px"}).appendTo(input);
$("<i>",{class: v.icon}).appendTo(s);
}
})
} else {
$('<span class="red-ui-editor-subflow-env-input-type-placeholder"></span>').text(RED._("editor.selectType")).appendTo(input);
}
}
},
{
value: "cred",
label: RED._("typedInput.type.cred"), icon:"fa fa-lock", showLabel: false,
valueLabel: function(container,value) {
container.css("padding",0);
var innerContainer = $('<div class="red-ui-editor-subflow-env-input-type">').css({
"border-top-right-radius": "4px",
"border-bottom-right-radius": "4px"
}).appendTo(container);
$('<div class="placeholder-input">').html("&bull;&bull;&bull;&bull;&bull;&bull;&bull;&bull;").appendTo(innerContainer);
}
},
{
value:"select",
label:RED._("editor.inputs.select"), icon:"fa fa-tasks",showLabel:false,
valueLabel: function(container,value) {
container.css("padding","0");
selectBox = $('<select></select>').appendTo(container);
if (ui.opts && Array.isArray(ui.opts.opts)) {
ui.opts.opts.forEach(function(o) {
var label = lookupLabel(o.l, o.l["en-US"]||o.v, currentLocale);
// $('<option>').val((o.t||'str')+":"+o.v).text(label).appendTo(selectBox);
$('<option>').val(o.v).text(label).appendTo(selectBox);
})
}
selectBox.on('change', function(evt) {
var v = selectBox.val();
// var parts = v.split(":");
// var t = parts.shift();
// v = parts.join(":");
//
// valueField.typedInput("type",'str')
valueField.typedInput("value",v)
});
selectBox.val(valueField.typedInput("value"));
// selectBox.val(valueField.typedInput('type')+":"+valueField.typedInput("value"));
},
expand: {
icon: "fa-caret-down",
minWidth: 400,
content: function(container) {
var content = $('<div class="red-ui-editor-subflow-ui-edit-panel">').appendTo(container);
var optList = $('<ol>').appendTo(content).editableList({
header:$("<div><div>"+RED._("editor.select.label")+"</div><div>"+RED._("editor.select.value")+"</div></div>"),
addItem: function(row,index,itemData) {
var labelDiv = $('<div>').appendTo(row);
var label = lookupLabel(itemData.l, "", currentLocale);
itemData.label = $('<input type="text">').val(label).appendTo(labelDiv);
itemData.label.on('keydown', function(evt) {
if (evt.keyCode === 13) {
itemData.input.focus();
evt.preventDefault();
}
});
var labelIcon = $('<span class="red-ui-editor-subflow-env-lang-icon"><i class="fa fa-language"></i></span>').appendTo(labelDiv);
RED.popover.tooltip(labelIcon,function() {
return currentLocale;
})
itemData.input = $('<input type="text">').val(itemData.v).appendTo(row);
// Problem using a TI here:
// - this is in a popout panel
// - clicking the expand button in the TI will close the parent edit tray
// and open the type editor.
// - but it leaves the popout panel over the top.
// - there is no way to get back to the popout panel after closing the type editor
//.typedInput({default:itemData.t||'str', types:DEFAULT_ENV_TYPE_LIST});
itemData.input.on('keydown', function(evt) {
if (evt.keyCode === 13) {
// Enter or Tab
var index = optList.editableList('indexOf',itemData);
var length = optList.editableList('length');
if (index + 1 === length) {
var newItem = {};
optList.editableList('addItem',newItem);
setTimeout(function() {
if (newItem.label) {
newItem.label.focus();
}
},100)
} else {
var nextItem = optList.editableList('getItemAt',index+1);
if (nextItem.label) {
nextItem.label.focus()
}
}
evt.preventDefault();
}
});
},
sortable: true,
removable: true,
height: 160
})
if (ui.opts.opts.length > 0) {
ui.opts.opts.forEach(function(o) {
optList.editableList('addItem',$.extend(true,{},o))
})
} else {
optList.editableList('addItem',{})
}
return {
onclose: function() {
var items = optList.editableList('items');
var vals = [];
items.each(function (i,el) {
var data = el.data('data');
var l = data.label.val().trim();
var v = data.input.val();
// var t = data.input.typedInput('type');
// var v = data.input.typedInput('value');
if (l.length > 0) {
data.l = data.l || {};
data.l[currentLocale] = l;
}
data.v = v;
if (l.length > 0 || v.length > 0) {
var val = {l:data.l,v:data.v};
// if (t !== 'str') {
// val.t = t;
// }
vals.push(val);
}
});
ui.opts.opts = vals;
inputCellInput.typedInput('value',Date.now())
}
}
}
}
},
{
value:"checkbox",
label:RED._("editor.inputs.checkbox"), icon:"fa fa-check-square-o",showLabel:false,
valueLabel: function(container,value) {
container.css("padding",0);
checkbox = $('<input type="checkbox">').appendTo(container);
checkbox.on('change', function(evt) {
valueField.typedInput('value',$(this).prop('checked')?"true":"false");
})
checkbox.prop('checked',valueField.typedInput('value')==="true");
}
},
{
value:"spinner",
label:RED._("editor.inputs.spinner"), icon:"fa fa-sort-numeric-asc", showLabel:false,
valueLabel: function(container,value) {
container.css("padding",0);
var innerContainer = $('<div class="red-ui-editor-subflow-env-input-type"></div>').appendTo(container);
var input = $('<div class="placeholder-input">').appendTo(innerContainer);
$('<span><i class="fa fa-sort-numeric-asc"></i></span>').appendTo(input);
var min = ui.opts && ui.opts.min;
var max = ui.opts && ui.opts.max;
var label = "";
if (min !== undefined && max !== undefined) {
label = Math.min(min,max)+" - "+Math.max(min,max);
} else if (min !== undefined) {
label = "> "+min;
} else if (max !== undefined) {
label = "< "+max;
}
$('<span>').css("margin-left","15px").text(label).appendTo(input);
},
expand: {
icon: "fa-caret-down",
content: function(container) {
var content = $('<div class="red-ui-editor-subflow-ui-edit-panel">').appendTo(container);
content.css("padding","8px 5px")
var min = ui.opts.min;
var max = ui.opts.max;
var minInput = $('<input type="number" style="margin-bottom:0; width:60px">');
minInput.val(min);
var maxInput = $('<input type="number" style="margin-bottom:0; width:60px">');
maxInput.val(max);
$('<div class="form-row" style="margin-bottom:3px"><label>'+RED._("editor.spinner.min")+'</label></div>').append(minInput).appendTo(content);
$('<div class="form-row" style="margin-bottom:0"><label>'+RED._("editor.spinner.max")+'</label></div>').append(maxInput).appendTo(content);
return {
onclose: function() {
var min = minInput.val().trim();
var max = maxInput.val().trim();
if (min !== "") {
ui.opts.min = parseInt(min);
} else {
delete ui.opts.min;
}
if (max !== "") {
ui.opts.max = parseInt(max);
} else {
delete ui.opts.max;
}
inputCellInput.typedInput('value',Date.now())
}
}
}
}
},
{
value:"none",
label:RED._("editor.inputs.none"), icon:"fa fa-times",hasValue:false
},
{
value:"hide",
label:RED._("editor.inputs.hidden"), icon:"fa fa-ban",hasValue:false
}
],
default: 'none'
}).on("typedinputtypechange", function(evt,type) {
ui.type = $(this).typedInput("type");
ui.opts = typeOptions[ui.type];
if (ui.type === 'input') {
// In the case of 'input' type, the typedInput uses the multiple-option
// mode. Its value needs to be set to a comma-separately list of the
// selected options.
inputCellInput.typedInput('value',ui.opts.types.join(","))
} else {
// No other type cares about `value`, but doing this will
// force a refresh of the label now that `ui.opts` has
// been updated.
inputCellInput.typedInput('value',Date.now())
}
switch (ui.type) {
case 'input':
valueField.typedInput('types',ui.opts.types);
break;
case 'select':
valueField.typedInput('types',['str']);
break;
case 'checkbox':
valueField.typedInput('types',['bool']);
break;
case 'spinner':
valueField.typedInput('types',['num']);
break;
case 'cred':
valueField.typedInput('types',['cred']);
break;
default:
valueField.typedInput('types',DEFAULT_ENV_TYPE_LIST)
}
if (ui.type === 'checkbox') {
valueField.typedInput('type','bool');
} else if (ui.type === 'spinner') {
valueField.typedInput('type','num');
}
if (ui.type !== 'checkbox') {
checkbox = null;
}
}).on("change", function(evt,type) {
if (ui.type === 'input') {
var types = inputCellInput.typedInput('value');
ui.opts.types = (types === "") ? ["str"] : types.split(",");
valueField.typedInput('types',ui.opts.types);
}
});
valueField.on("change", function(evt) {
if (checkbox) {
checkbox.prop('checked',$(this).typedInput('value')==="true")
}
})
// Set the input to the right type. This will trigger the 'typedinputtypechange'
// event handler (just above ^^) to update the value if needed
inputCellInput.typedInput('type',ui.type)
}
function buildEnvUIRow(row, tenv, ui, node) { function buildEnvUIRow(row, tenv, ui, node) {
ui.label = ui.label||{}; ui.label = ui.label||{};
@ -1540,7 +929,7 @@ RED.subflow = (function() {
ui.opts = {}; ui.opts = {};
} else if (!ui.type) { } else if (!ui.type) {
ui.type = "input"; ui.type = "input";
ui.opts = {types:DEFAULT_ENV_TYPE_LIST} ui.opts = { types: RED.editor.envVarList.DEFAULT_ENV_TYPE_LIST }
} else { } else {
if (!ui.opts) { if (!ui.opts) {
ui.opts = (ui.type === "select") ? {opts:[]} : {}; ui.opts = (ui.type === "select") ? {opts:[]} : {};
@ -1549,7 +938,7 @@ RED.subflow = (function() {
var labels = ui.label || {}; var labels = ui.label || {};
var locale = RED.i18n.lang(); var locale = RED.i18n.lang();
var labelText = lookupLabel(labels, labels["en-US"]||tenv.name, locale); var labelText = RED.editor.envVarList.lookupLabel(labels, labels["en-US"]||tenv.name, locale);
var label = $('<label>').appendTo(row); var label = $('<label>').appendTo(row);
$('<span>&nbsp;</span>').appendTo(row); $('<span>&nbsp;</span>').appendTo(row);
var labelContainer = $('<span></span>').appendTo(label); var labelContainer = $('<span></span>').appendTo(label);
@ -1602,7 +991,7 @@ RED.subflow = (function() {
input = $('<select>').css('width','70%').appendTo(row); input = $('<select>').css('width','70%').appendTo(row);
if (ui.opts.opts) { if (ui.opts.opts) {
ui.opts.opts.forEach(function(o) { ui.opts.opts.forEach(function(o) {
$('<option>').val(o.v).text(lookupLabel(o.l, o.l['en-US']||o.v, locale)).appendTo(input); $('<option>').val(o.v).text(RED.editor.envVarList.lookupLabel(o.l, o.l['en-US']||o.v, locale)).appendTo(input);
}) })
} }
input.val(val.value); input.val(val.value);
@ -1670,7 +1059,6 @@ RED.subflow = (function() {
*/ */
function buildEnvUI(uiContainer, envList, node) { function buildEnvUI(uiContainer, envList, node) {
uiContainer.empty(); uiContainer.empty();
var elementID = 0;
for (var i = 0; i < envList.length; i++) { for (var i = 0; i < envList.length; i++) {
var tenv = envList[i]; var tenv = envList[i];
if (tenv.ui && tenv.ui.type === 'hide') { if (tenv.ui && tenv.ui.type === 'hide') {
@ -1678,8 +1066,6 @@ RED.subflow = (function() {
} }
var row = $("<div/>", { class: "form-row" }).appendTo(uiContainer); var row = $("<div/>", { class: "form-row" }).appendTo(uiContainer);
buildEnvUIRow(row,tenv, tenv.ui || {}, node); buildEnvUIRow(row,tenv, tenv.ui || {}, node);
// console.log(ui);
} }
} }
// buildEnvUI // buildEnvUI
@ -1715,7 +1101,7 @@ RED.subflow = (function() {
// icon: "", // icon: "",
// label: {}, // label: {},
// type: "input", // type: "input",
// opts: {types:DEFAULT_ENV_TYPE_LIST} // opts: {types:RED.editor.envVarList.DEFAULT_ENV_TYPE_LIST}
// } // }
if (!ui.icon) { if (!ui.icon) {
delete ui.icon; delete ui.icon;
@ -1725,7 +1111,7 @@ RED.subflow = (function() {
} }
switch (ui.type) { switch (ui.type) {
case "input": case "input":
if (JSON.stringify(ui.opts) === JSON.stringify({types:DEFAULT_ENV_TYPE_LIST})) { if (JSON.stringify(ui.opts) === JSON.stringify({types:RED.editor.envVarList.DEFAULT_ENV_TYPE_LIST})) {
// This is the default input config. Delete it as it will // This is the default input config. Delete it as it will
// be applied automatically // be applied automatically
delete ui.type; delete ui.type;
@ -1841,7 +1227,6 @@ RED.subflow = (function() {
function exportSubflowInstanceEnv(node) { function exportSubflowInstanceEnv(node) {
var env = []; var env = [];
// First, get the values for the SubflowTemplate defined properties // First, get the values for the SubflowTemplate defined properties
// - these are the ones with custom UI elements // - these are the ones with custom UI elements
var parentEnv = getSubflowInstanceParentEnv(node); var parentEnv = getSubflowInstanceParentEnv(node);
@ -1853,7 +1238,7 @@ RED.subflow = (function() {
ui.type = "cred"; ui.type = "cred";
} else { } else {
ui.type = "input"; ui.type = "input";
ui.opts = {types:DEFAULT_ENV_TYPE_LIST} ui.opts = {types:RED.editor.envVarList.DEFAULT_ENV_TYPE_LIST}
} }
} else { } else {
ui.opts = ui.opts || {}; ui.opts = ui.opts || {};
@ -1893,22 +1278,6 @@ RED.subflow = (function() {
} }
} }
}) })
// Second, get the values from the Properties table tab
var items = $('#red-ui-editor-subflow-env-list').editableList('items');
items.each(function (i,el) {
var data = el.data('data');
var item;
if (data.nameField && data.valueField) {
item = {
name: data.nameField.val(),
value: data.valueField.typedInput("value"),
type: data.valueField.typedInput("type")
}
if (item.name.trim() !== "") {
env.push(item);
}
}
});
return env; return env;
} }
@ -1916,164 +1285,18 @@ RED.subflow = (function() {
return 'node-input-subflow-env-'+name.replace(/[^a-z0-9-_]/ig,"_"); return 'node-input-subflow-env-'+name.replace(/[^a-z0-9-_]/ig,"_");
} }
/** // Called by subflow.oneditprepare for both instances and templates
* Lookup text for specific locale
* @param labels - dict of labels
* @param defaultLabel - fallback label if not found
* @param locale - target locale
* @returns {string} text for specified locale
*/
function lookupLabel(labels, defaultLabel, locale) {
if (labels) {
if (labels[locale]) {
return labels[locale];
}
if (locale) {
var lang = locale.substring(0, 2);
if (labels[lang]) {
return labels[lang];
}
}
}
return defaultLabel;
}
function buildEditForm(type,node) { function buildEditForm(type,node) {
if (type === "subflow-template") { if (type === "subflow-template") {
buildPropertiesList($('#node-input-env-container'), node); // This is the tabbed UI that offers the env list - with UI options
// plus the preview tab
buildEnvControl($('#node-input-env-container'), node);
RED.editor.envVarList.create($('#node-input-env-container'), node);
} else if (type === "subflow") { } else if (type === "subflow") {
// This gets called by the subflow type `oneditprepare` function // This is the rendered version of the subflow env var list
// registered in nodes.js#addSubflow()
buildEnvUI($("#subflow-input-ui"), getSubflowInstanceParentEnv(node), node); buildEnvUI($("#subflow-input-ui"), getSubflowInstanceParentEnv(node), node);
} }
} }
function buildPropertiesForm(node) {
var container = $('#editor-subflow-envProperties-content');
var form = $('<form class="dialog-form form-horizontal"></form>').appendTo(container);
var listContainer = $('<div class="form-row node-input-env-container-row"></div>').appendTo(form);
var list = $('<ol id="red-ui-editor-subflow-env-list" class="red-ui-editor-subflow-env-list"></ol>').appendTo(listContainer);
buildPropertiesList(list, node);
}
function setupInputValidation(input,validator) {
var errorTip;
var validateTimeout;
var validateFunction = function() {
if (validateTimeout) {
return;
}
validateTimeout = setTimeout(function() {
var error = validator(input.val());
// if (!error && errorTip) {
// errorTip.close();
// errorTip = null;
// } else if (error && !errorTip) {
// errorTip = RED.popover.create({
// tooltip: true,
// target:input,
// size: "small",
// direction: "bottom",
// content: error,
// }).open();
// }
input.toggleClass("input-error",!!error);
validateTimeout = null;
})
}
input.on("change keyup paste", validateFunction);
}
function buildModuleForm(container, node) {
$(_subflowModulePaneTemplate).appendTo(container);
var moduleProps = node.meta || {};
[
'module',
'type',
'version',
'author',
'desc',
'keywords',
'license'
].forEach(function(property) {
$("#subflow-input-module-"+property).val(moduleProps[property]||"")
})
$("#subflow-input-module-type").attr("placeholder",node.id);
setupInputValidation($("#subflow-input-module-module"), function(newValue) {
newValue = newValue.trim();
var isValid = newValue.length < 215;
isValid = isValid && !/^[._]/.test(newValue);
isValid = isValid && !/[A-Z]/.test(newValue);
if (newValue !== encodeURIComponent(newValue)) {
var m = /^@([^\/]+)\/([^\/]+)$/.exec(newValue);
if (m) {
isValid = isValid && (m[1] === encodeURIComponent(m[1]) && m[2] === encodeURIComponent(m[2]))
} else {
isValid = false;
}
}
return isValid?"":"Invalid module name"
})
setupInputValidation($("#subflow-input-module-version"), function(newValue) {
newValue = newValue.trim();
var isValid = newValue === "" ||
/^(\d|[1-9]\d*)\.(\d|[1-9]\d*)\.(\d|[1-9]\d*)(-(0|[1-9A-Za-z-][0-9A-Za-z-]*|[0-9]*[A-Za-z-][0-9A-Za-z-]*)(\.(0|[1-9A-Za-z-][0-9A-Za-z-]*|[0-9]*[A-Za-z-][0-9A-Za-z-]*))*)?(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$/.test(newValue);
return isValid?"":"Invalid version number"
})
var licenses = ["none", "Apache-2.0", "BSD-3-Clause", "BSD-2-Clause", "GPL-2.0", "GPL-3.0", "MIT", "MPL-2.0", "CDDL-1.0", "EPL-2.0"];
var typedLicenses = {
types: licenses.map(function(l) {
return {
value: l,
label: l === "none" ? RED._("editor:subflow.licenseNone") : l,
hasValue: false
};
})
}
typedLicenses.types.push({
value:"_custom_", label:RED._("editor:subflow.licenseOther"), icon:"red/images/typedInput/az.svg"
})
if (!moduleProps.license) {
typedLicenses.default = "none";
} else if (licenses.indexOf(moduleProps.license) > -1) {
typedLicenses.default = moduleProps.license;
} else {
typedLicenses.default = "_custom_";
}
$("#subflow-input-module-license").typedInput(typedLicenses)
}
function exportSubflowModuleProperties(node) {
var value;
var moduleProps = {};
[
'module',
'type',
'version',
'author',
'desc',
'keywords'
].forEach(function(property) {
value = $("#subflow-input-module-"+property).val().trim();
if (value) {
moduleProps[property] = value;
}
})
var selectedLicenseType = $("#subflow-input-module-license").typedInput("type");
if (selectedLicenseType === '_custom_') {
value = $("#subflow-input-module-license").val();
if (value) {
moduleProps.license = value;
}
} else if (selectedLicenseType !== "none") {
moduleProps.license = selectedLicenseType;
}
return moduleProps;
}
return { return {
init: init, init: init,
@ -2085,14 +1308,9 @@ RED.subflow = (function() {
removeOutput: removeSubflowOutput, removeOutput: removeSubflowOutput,
removeStatus: removeSubflowStatus, removeStatus: removeSubflowStatus,
buildEditForm: buildEditForm, buildEditForm: buildEditForm,
buildPropertiesForm: buildPropertiesForm,
buildModuleForm: buildModuleForm,
exportSubflowTemplateEnv: exportEnvList, exportSubflowTemplateEnv: exportEnvList,
exportSubflowInstanceEnv: exportSubflowInstanceEnv, exportSubflowInstanceEnv: exportSubflowInstanceEnv
exportSubflowModuleProperties: exportSubflowModuleProperties
} }
})(); })();

View File

@ -229,7 +229,7 @@ RED.sidebar.config = (function() {
var globalConfigNodes = []; var globalConfigNodes = [];
var configList = {}; var configList = {};
RED.nodes.eachConfig(function(cn) { RED.nodes.eachConfig(function(cn) {
if (cn.z) {//} == RED.workspaces.active()) { if (cn.z) {
configList[cn.z.replace(/\./g,"-")] = configList[cn.z.replace(/\./g,"-")]||[]; configList[cn.z.replace(/\./g,"-")] = configList[cn.z.replace(/\./g,"-")]||[];
configList[cn.z.replace(/\./g,"-")].push(cn); configList[cn.z.replace(/\./g,"-")].push(cn);
} else if (!cn.z) { } else if (!cn.z) {

View File

@ -25,7 +25,6 @@ RED.sidebar.help = (function() {
var tocPanel; var tocPanel;
var helpIndex = {}; var helpIndex = {};
function resizeStack() { function resizeStack() {
var h = $(content).parent().height() - toolbar.outerHeight(); var h = $(content).parent().height() - toolbar.outerHeight();
panels.resize(h) panels.resize(h)
@ -93,9 +92,28 @@ RED.sidebar.help = (function() {
$('<span class="red-ui-help-info-none">'+RED._("sidebar.help.noHelp")+'</span>').appendTo(helpSection); $('<span class="red-ui-help-info-none">'+RED._("sidebar.help.noHelp")+'</span>').appendTo(helpSection);
treeList = $("<div>").css({width: "100%"}).appendTo(tocPanel).treeList({data: []}) treeList = $("<div>").css({width: "100%"}).appendTo(tocPanel).treeList({data: []})
var pendingContentLoad;
treeList.on('treelistselect', function(e,item) { treeList.on('treelistselect', function(e,item) {
pendingContentLoad = item;
if (item.nodeType) { if (item.nodeType) {
showHelp(item.nodeType); showNodeTypeHelp(item.nodeType);
} else if (item.content) {
helpSection.empty();
if (typeof item.content === "string") {
setInfoText(item.label, item.content);
} else if (typeof item.content === "function") {
if (item.content.length === 0) {
setInfoText(item.label, item.content());
} else {
setInfoText(item.label, '<div class="red-ui-component-spinner red-ui-component-spinner-contain"><img src="red/images/spin.svg" /></div>',helpSection)
item.content(function(content) {
if (pendingContentLoad === item) {
helpSection.empty();
setInfoText(item.label, content);
}
})
}
}
} }
}) })
@ -174,21 +192,28 @@ RED.sidebar.help = (function() {
var moduleNames = Object.keys(modules); var moduleNames = Object.keys(modules);
moduleNames.sort(); moduleNames.sort();
var helpData = [{ var nodeHelp = {
label: RED._("sidebar.help.nodeHelp"), label: RED._("sidebar.help.nodeHelp"),
children: [], children: [],
expanded: true expanded: true
}] }
var helpData = [
{
id: 'changelog',
label: "Node-RED v"+RED.settings.version,
content: getChangelog
},
nodeHelp
]
var subflows = RED.nodes.registry.getNodeTypes().filter(function(t) {return /subflow/.test(t)}); var subflows = RED.nodes.registry.getNodeTypes().filter(function(t) {return /subflow/.test(t)});
if (subflows.length > 0) { if (subflows.length > 0) {
helpData[0].children.push({ nodeHelp.children.push({
label: RED._("menu.label.subflows"), label: RED._("menu.label.subflows"),
children: [] children: []
}) })
subflows.forEach(function(nodeType) { subflows.forEach(function(nodeType) {
var sf = RED.nodes.getType(nodeType); var sf = RED.nodes.getType(nodeType);
helpData[0].children[0].children.push({ nodeHelp.children[0].children.push({
id:"node-type:"+nodeType, id:"node-type:"+nodeType,
nodeType: nodeType, nodeType: nodeType,
subflowLabel: sf.label().toLowerCase(), subflowLabel: sf.label().toLowerCase(),
@ -218,7 +243,7 @@ RED.sidebar.help = (function() {
nodeTypes.sort(function(A,B) { nodeTypes.sort(function(A,B) {
return A.nodeType.localeCompare(B.nodeType) return A.nodeType.localeCompare(B.nodeType)
}) })
helpData[0].children.push({ nodeHelp.children.push({
id: moduleName, id: moduleName,
icon: "fa fa-cube", icon: "fa fa-cube",
label: moduleName, label: moduleName,
@ -244,7 +269,7 @@ RED.sidebar.help = (function() {
return div; return div;
} }
function showHelp(nodeType) { function showNodeTypeHelp(nodeType) {
helpSection.empty(); helpSection.empty();
var helpText; var helpText;
var title; var title;
@ -265,7 +290,7 @@ RED.sidebar.help = (function() {
} }
} }
} }
setInfoText(title, helpText, helpSection); setInfoText(title, helpText);
var ratio = panels.ratio(); var ratio = panels.ratio();
if (ratio > 0.7) { if (ratio > 0.7) {
@ -282,7 +307,7 @@ RED.sidebar.help = (function() {
} }
if (type) { if (type) {
// hideTOC(); // hideTOC();
showHelp(type); showNodeTypeHelp(type);
} }
resizeStack(); resizeStack();
} }
@ -298,11 +323,12 @@ RED.sidebar.help = (function() {
return el; return el;
} }
function setInfoText(title, infoText,target) { function setInfoText(title, infoText) {
helpSection.empty();
if (title) { if (title) {
$("<h1>",{class:"red-ui-help-title"}).text(title).appendTo(target); $("<h1>",{class:"red-ui-help-title"}).text(title).appendTo(helpSection);
} }
var info = addTargetToExternalLinks($('<div class="red-ui-help"><span class="red-ui-text-bidi-aware" dir=\"'+RED.text.bidi.resolveBaseTextDir(infoText)+'">'+infoText+'</span></div>')).appendTo(target); var info = addTargetToExternalLinks($('<div class="red-ui-help"><span class="red-ui-text-bidi-aware" dir=\"'+RED.text.bidi.resolveBaseTextDir(infoText)+'">'+infoText+'</span></div>')).appendTo(helpSection);
info.find(".red-ui-text-bidi-aware").contents().filter(function() { return this.nodeType === 3 && this.textContent.trim() !== "" }).wrap( "<span></span>" ); info.find(".red-ui-text-bidi-aware").contents().filter(function() { return this.nodeType === 3 && this.textContent.trim() !== "" }).wrap( "<span></span>" );
var foldingHeader = "H3"; var foldingHeader = "H3";
info.find(foldingHeader).wrapInner('<a class="red-ui-help-info-header expanded" href="#"></a>') info.find(foldingHeader).wrapInner('<a class="red-ui-help-info-header expanded" href="#"></a>')
@ -316,12 +342,12 @@ RED.sidebar.help = (function() {
} }
$(this).toggleClass('expanded',!isExpanded); $(this).toggleClass('expanded',!isExpanded);
}) })
target.parent().scrollTop(0); helpSection.parent().scrollTop(0);
} }
function set(html,title) { function set(html,title) {
$(helpSection).empty(); $(helpSection).empty();
setInfoText(title,html,helpSection); setInfoText(title,html);
hideTOC(); hideTOC();
show(); show();
} }
@ -336,13 +362,91 @@ RED.sidebar.help = (function() {
if (node.type === "subflow" && node.direction) { if (node.type === "subflow" && node.direction) {
// ignore subflow virtual ports // ignore subflow virtual ports
} else if (node.type !== 'group'){ } else if (node.type !== 'group'){
showHelp(node.type); showNodeTypeHelp(node.type);
} }
} }
} }
} }
RED.events.on("view:selection-changed",refreshSelection); RED.events.on("view:selection-changed",refreshSelection);
function getChangelog(done) {
$.get('red/about', function(data) {
// data will be strictly markdown. Any HTML should be escaped.
data = RED.utils.sanitize(data);
RED.tourGuide.load("./tours/welcome.js", function(err, tour) {
var tourHeader = '<div><img width="50px" src="red/images/node-red-icon.svg" /></div>';
if (tour) {
var currentVersionParts = RED.settings.version.split(".");
var tourVersionParts = tour.version.split(".");
if (tourVersionParts[0] === currentVersionParts[0] && tourVersionParts[1] === currentVersionParts[1]) {
tourHeader = '<div><button type="button" onclick="RED.actions.invoke(\'core:show-welcome-tour\')" class="red-ui-button">Take a tour</button></div>'
}
}
var aboutHeader = '<div style="text-align:center;">'+tourHeader+'</div>'
done(aboutHeader+RED.utils.renderMarkdown(data))
});
});
}
function showAbout() {
treeList.treeList("show","changelog")
treeList.treeList("select","changelog");
show();
}
function showWelcomeTour(lastSeenVersion, done) {
done = done || function() {};
RED.tourGuide.load("./tours/welcome.js", function(err, tour) {
if (err) {
console.warn("Failed to load welcome tour",err);
done()
return;
}
var currentVersionParts = RED.settings.version.split(".");
var tourVersionParts = tour.version.split(".");
// Only display the tour if its MAJ.MIN versions the current version
// This means if we update MAJ/MIN without updating the tour, the old tour won't get shown
if (tourVersionParts[0] !== currentVersionParts[0] || tourVersionParts[1] !== currentVersionParts[1]) {
done()
return;
}
if (lastSeenVersion) {
// Previously displayed a welcome tour.
if (lastSeenVersion === RED.settings.version) {
// Exact match - don't show the tour
done()
return;
}
var lastSeenParts = lastSeenVersion.split(".");
if (currentVersionParts[0] < lastSeenParts[0] || (currentVersionParts[0] === lastSeenParts[0] && currentVersionParts[1] < lastSeenParts[1])) {
// Running an *older* version than last displayed tour.
done()
return;
}
if (currentVersionParts[0] === lastSeenParts[0] && currentVersionParts[1] === lastSeenParts[1]) {
if (lastSeenParts.length === 3 && currentVersionParts.length === 3) {
// Matching non-beta MAJ.MIN - don't repeat tour
done()
return;
}
if (currentVersionParts.length === 4 && (lastSeenParts.length === 3 || currentVersionParts[3] < lastSeenParts[3])) {
// Running an *older* beta than last displayed tour.
done()
return
}
}
}
RED.tourGuide.run("./tours/welcome.js", function(err) {
RED.settings.set("editor.tours.welcome", RED.settings.version)
done()
})
})
}
RED.actions.add("core:show-about", showAbout);
RED.actions.add("core:show-welcome-tour", showWelcomeTour);
return { return {
init: init, init: init,
show: show, show: show,

View File

@ -122,11 +122,20 @@ RED.sidebar.info.outliner = (function() {
}) })
RED.popover.tooltip(triggerButton,RED._("sidebar.info.triggerAction")); RED.popover.tooltip(triggerButton,RED._("sidebar.info.triggerAction"));
} }
// $('<button type="button" class="red-ui-info-outline-item-control-reveal red-ui-button red-ui-button-small"><i class="fa fa-eye"></i></button>').appendTo(controls).on("click",function(evt) {
// evt.preventDefault(); if (n.type === "tab") {
// evt.stopPropagation(); var toggleVisibleButton = $('<button type="button" class="red-ui-info-outline-item-control-hide red-ui-button red-ui-button-small"><i class="fa fa-eye"></i><i class="fa fa-eye-slash"></i></button>').appendTo(controls).on("click",function(evt) {
// RED.view.reveal(n.id); evt.preventDefault();
// }) evt.stopPropagation();
var isHidden = !div.hasClass("red-ui-info-outline-item-hidden");
div.toggleClass("red-ui-info-outline-item-hidden",isHidden);
if (isHidden) {
RED.workspaces.hide(n.id);
} else {
RED.workspaces.show(n.id, null, true);
}
});
}
if (n.type !== 'subflow') { if (n.type !== 'subflow') {
var toggleButton = $('<button type="button" class="red-ui-info-outline-item-control-disable red-ui-button red-ui-button-small"><i class="fa fa-circle-thin"></i><i class="fa fa-ban"></i></button>').appendTo(controls).on("click",function(evt) { var toggleButton = $('<button type="button" class="red-ui-info-outline-item-control-disable red-ui-button red-ui-button-small"><i class="fa fa-circle-thin"></i><i class="fa fa-ban"></i></button>').appendTo(controls).on("click",function(evt) {
evt.preventDefault(); evt.preventDefault();
@ -278,11 +287,11 @@ RED.sidebar.info.outliner = (function() {
var node = RED.nodes.node(item.id) || RED.nodes.group(item.id); var node = RED.nodes.node(item.id) || RED.nodes.group(item.id);
if (node) { if (node) {
if (node.type === 'group' || node._def.category !== "config") { if (node.type === 'group' || node._def.category !== "config") {
RED.view.select({nodes:[node]}) // RED.view.select({nodes:[node]})
} else if (node._def.category === "config") { } else if (node._def.category === "config") {
RED.sidebar.info.refresh(node); RED.sidebar.info.refresh(node);
} else { } else {
RED.view.select({nodes:[]}) // RED.view.select({nodes:[]})
} }
} }
}) })
@ -311,18 +320,33 @@ RED.sidebar.info.outliner = (function() {
RED.events.on("nodes:add",onNodeAdd); RED.events.on("nodes:add",onNodeAdd);
RED.events.on("nodes:remove",onObjectRemove); RED.events.on("nodes:remove",onObjectRemove);
RED.events.on("nodes:change",onNodeChange); RED.events.on("nodes:change",onNodeChange);
// RED.events.on("nodes:reorder",onNodesReorder);
RED.events.on("groups:add",onNodeAdd); RED.events.on("groups:add",onNodeAdd);
RED.events.on("groups:remove",onObjectRemove); RED.events.on("groups:remove",onObjectRemove);
RED.events.on("groups:change",onNodeChange); RED.events.on("groups:change",onNodeChange);
RED.events.on("workspace:clear", onWorkspaceClear) RED.events.on("workspace:show", onWorkspaceShow);
RED.events.on("workspace:hide", onWorkspaceHide);
RED.events.on("workspace:clear", onWorkspaceClear);
return container; return container;
} }
function onWorkspaceClear() { function onWorkspaceClear() {
treeList.treeList('data',getFlowData()); treeList.treeList('data',getFlowData());
} }
function onWorkspaceShow(event) {
var existingObject = objects[event.workspace];
if (existingObject) {
existingObject.element.removeClass("red-ui-info-outline-item-hidden")
}
}
function onWorkspaceHide(event) {
var existingObject = objects[event.workspace];
if (existingObject) {
existingObject.element.addClass("red-ui-info-outline-item-hidden")
}
}
function onFlowAdd(ws) { function onFlowAdd(ws) {
objects[ws.id] = { objects[ws.id] = {
id: ws.id, id: ws.id,
@ -369,6 +393,21 @@ RED.sidebar.info.outliner = (function() {
return indexMap[A.id] - indexMap[B.id] return indexMap[A.id] - indexMap[B.id]
}) })
} }
// function onNodesReorder(event) {
// //
// var nodes = RED.nodes.getNodeOrder(event.z);
// var indexMap = {};
// nodes.forEach(function(id,index) {
// indexMap[id] = index;
// })
// var existingObject = objects[event.z];
// existingObject.treeList.sortChildren(function(A,B) {
// if (A.children && !B.children) { return -1 }
// if (!A.children && B.children) { return 1 }
// if (A.children && B.children) { return -1 }
// return indexMap[A.id] - indexMap[B.id]
// })
// }
function onSubflowAdd(sf) { function onSubflowAdd(sf) {
objects[sf.id] = { objects[sf.id] = {
id: sf.id, id: sf.id,

View File

@ -180,6 +180,10 @@ RED.sidebar.info = (function() {
if (node === null) { if (node === null) {
RED.sidebar.info.outliner.select(null); RED.sidebar.info.outliner.select(null);
propertiesPanelHeaderIcon.empty();
propertiesPanelHeaderLabel.text("");
propertiesPanelHeaderReveal.hide();
propertiesPanelHeaderHelp.hide();
return; return;
} else if (Array.isArray(node)) { } else if (Array.isArray(node)) {
// Multiple things selected // Multiple things selected

View File

@ -0,0 +1,434 @@
RED.tourGuide = (function() {
var activeListeners = [];
var shade;
var focus;
var popover;
var stepContent;
var targetElement;
var fullscreen;
var tourCache = {};
function run(tourPath, done) {
done = done || function(err) {
if (err) {
console.error(err);
}
};
loadTour(tourPath, function(err, tour) {
if (err) {
console.warn("Error loading tour:",err);
return;
}
runTour(tour, done);
})
}
function loadTour(tourPath, done) {
if (tourCache[tourPath]) {
done(null, tourCache[tourPath]);
} else {
/* jshint ignore:start */
// jshint<2.13 doesn't support dynamic imports. Once grunt-contrib-jshint
// has been updated with the new jshint, we can stop ignoring this block
import(tourPath).then(function(module) {
tourCache[tourPath] = module.default;
done(null, tourCache[tourPath]);
}).catch(function(err) {
done(err);
})
/* jshint ignore:end */
}
}
function repositionFocus() {
if (targetElement) {
if (!fullscreen) {
var pos = targetElement[0].getBoundingClientRect();
var dimension = Math.max(50, Math.max(pos.width,pos.height)*1.5);
focus.css({
left: (pos.left+pos.width/2)+"px",
top: (pos.top+pos.height/2)+"px",
width: (2*dimension)+"px",
height: (2*dimension)+"px"
})
var flush = focus[0].offsetHeight; // Flush CSS changes
focus.addClass("transition");
focus.css({
width: dimension+"px",
height: dimension+"px"
})
} else {
focus.css({
left: ($(window).width()/2)+"px",
top: ($(window).height()/2)+"px",
width: "0px",
height: "0px"
})
}
if (popover) {
popover.move({
target: targetElement,
})
}
}
}
function runTour(tour, done) {
shade = $('<div class="red-ui-tourGuide-shade"></div>').appendTo(document.body);
focus = $('<div class="red-ui-tourGuide-shade-focus"></div>').appendTo(shade);
// var resizeTimer;
//
$(window).on("resize.red-ui-tourGuide", function() {
repositionFocus();
})
var i = 0;
var state = {
index: 0,
count: tour.steps.length
};
function endTour(err) {
$(window).off("resize.red-ui-tourGuide");
$(document).off('keydown.red-ui-tourGuide');
if (popover) {
popover.close();
}
stepContent = null;
popover = null;
shade.remove();
shade = null;
done(err);
}
function runStep(carryOn) {
if (carryOn === false) {
endTour(false);
return;
}
if (i === tour.steps.length) {
endTour();
return
}
state.index = i;
// console.log("TOUR STEP",i+1,"OF",tour.steps.length)
try {
runTourStep(tour.steps[i++], state, runStep)
} catch(err) {
endTour(err);
return;
}
}
runStep();
}
function clearListeners() {
activeListeners.forEach(function(listener) {
if (listener.type === "dom-event") {
listener.target[0].removeEventListener(listener.event,listener.listener,listener.opts);
} else if (listener.type === "nr-event") {
RED.events.off(listener.event, listener.listener)
}
})
activeListeners = [];
}
function prepareStep(step, state, done) {
if (step.prepare) {
if (step.prepare.length === 0) {
step.prepare.call(state);
} else {
if (popover) {
popover.element.hide();
if (!fullscreen) {
fullscreen = true;
repositionFocus()
}
}
step.prepare.call(state, function() {
if (popover) {
popover.element.show();
}
done();
})
return;
}
}
done();
}
function completeStep(step, state, done) {
function finish() {
clearListeners();
setTimeout(function() {
done();
},0)
}
if (step.complete) {
if (step.complete.length === 0) {
step.complete.call(state);
} else {
if (popover) {
popover.element.hide();
if (!fullscreen) {
fullscreen = true;
repositionFocus()
}
}
step.complete.call(state, function() {
if (popover) {
popover.element.show();
}
finish();
})
return;
}
}
finish();
}
function getLocaleText(property) {
if (typeof property === 'string') {
return property;
}
var currentLang = RED.i18n.lang() || 'en-US';
var availableLangs = Object.keys(property);
return property[currentLang]||property['en-US']||property[availableLangs[0]]
}
function runTourStep(step, state, done) {
shade.fadeIn();
prepareStep(step, state, function() {
var zIndex;
var direction = step.direction || "bottom";
fullscreen = false;
if (typeof step.element === "string") {
targetElement = $(step.element)
} else if (typeof step.element === "function") {
targetElement = step.element.call(state);
} else if (!step.element) {
targetElement = $(".red-ui-editor")
fullscreen = true;
direction = "inset";
} else {
targetElement = step.element;
}
if (targetElement.length === 0) {
targetElement = null;
shade.hide();
throw new Error("Element not found")
}
if ($(window).width() < 400) {
targetElement = $(".red-ui-editor");
fullscreen = true;
direction = "inset";
}
zIndex = targetElement.css("z-index");
if (!fullscreen && (step.interactive || step.wait)) {
targetElement.css("z-index",2002);
}
repositionFocus();
if (!stepContent) {
stepContent = $('<div style="position:relative"></div>');
} else {
stepContent.empty();
}
$('<button type="button" class="red-ui-button red-ui-button-small" style="float: right; margin-top: -4px; margin-right: -4px;"><i class="fa fa-times"></i></button>').appendTo(stepContent).click(function(evt) {
evt.preventDefault();
completeStep(step, state, function() {
done(false);
});
})
var stepDescription = $('<div class="red-ui-tourGuide-popover-description"></div>').appendTo(stepContent);
if (step.titleIcon) {
$('<h2><i class="'+step.titleIcon+'"></i></h2>').appendTo(stepDescription);
}
if (step.title) {
$('<h2>').text(getLocaleText(step.title)).appendTo(stepDescription);
}
$('<div>').css("text-align","left").html(getLocaleText(step.description)).appendTo(stepDescription);
var stepToolbar = $('<div>',{class:"red-ui-tourGuide-toolbar"}).appendTo(stepContent);
// var breadcrumbs = $('<div>',{class:"red-ui-tourGuide-breadcrumbs"}).appendTo(stepToolbar);
// var bcStart = Math.max(0,state.index - 3);
// var bcEnd = Math.min(state.count, bcStart + 7);
// if (bcEnd === state.count) {
// bcStart = Math.max(0,bcEnd - 7);
// }
// for (var i = bcStart; i < bcEnd; i++) {
// var bullet = $('<i class="fa"></i>').addClass(i===state.index ? "fa-circle":"fa-circle-o").appendTo(breadcrumbs);
// if (i === bcStart) {
// if (i > 1) {
// bullet.css("font-size", "3px");
// } else if (i === 1) {
// bullet.css("font-size", "4px");
// }
// } else if (i === bcStart + 1) {
// if (i > 2) {
// bullet.css("font-size", "4px");
// }
// }
// if (i === bcEnd - 1) {
// if (i < state.count - 2) {
// bullet.css("font-size", "3px");
// } else if (i === state.count - 2) {
// bullet.css("font-size", "4px");
// }
// } else if (i === bcEnd - 2) {
// if (i < state.count - 3) {
// bullet.css("font-size", "4px");
// }
// }
// // if (i === bcEnd - 1) {
// // if (i < state.count - 2) {
// // bullet.css("font-size", "3px");
// // } else if (i === state.count - 2) {
// // bullet.css("font-size", "4px");
// // }
// // }
// }
$('<small>').text((state.index+1)+"/"+state.count).appendTo(stepToolbar)
var nextButton;
if (fullscreen || !step.wait) {
nextButton = $('<button type="button" class="red-ui-button" style="position: absolute; right:0;bottom:0;"></button>').appendTo(stepToolbar).one('click',function(evt) {
evt.preventDefault();
stepEventListener();
});
if (state.index === state.count - 1) {
$('<span></span>').text(RED._("common.label.close")).appendTo(nextButton);
} else if (state.index === 0) {
$('<span>start</span>').text(RED._("tourGuide.start")).appendTo(nextButton);
$('<span style="margin-left: 6px"><i class="fa fa-chevron-right"></i></span>').appendTo(nextButton);
} else if (state.index < state.count-1) {
$('<span></span>').text(RED._("tourGuide.next")).appendTo(nextButton);
$('<span style="margin-left: 6px"><i class="fa fa-chevron-right"></i></span>').appendTo(nextButton);
}
}
var width = step.width;
if (fullscreen) {
width = 500;
}
var maxWidth = Math.min($(window).width()-10,Math.max(width || 0, 300));
if (!popover) {
popover = RED.popover.create({
target: targetElement,
width: width || "auto",
maxWidth: maxWidth+"px",
direction: direction,
class: "red-ui-tourGuide-popover"+(fullscreen?" ":""),
trigger: "manual",
content: stepContent
}).open();
}
$(document).off('keydown.red-ui-tourGuide');
$(document).on('keydown.red-ui-tourGuide', function(evt) {
if (evt.key === "Escape" || evt.key === "Esc") {
evt.preventDefault();
evt.stopPropagation();
completeStep(step, state, function() {
done(false);
});
}
})
popover.element.toggleClass("red-ui-tourGuide-popover-full",!!fullscreen);
popover.move({
target: targetElement,
width: width || "auto",
maxWidth: maxWidth+"px",
direction: direction,
})
if (nextButton) {
setTimeout(function() {
nextButton.focus();
},100);
}
var isSVG = targetElement[0] instanceof SVGElement;
if (step.fallback) {
focus.one("mouseenter", function(evt) {
setTimeout(function() {
focus.css({
width: (4*dimension)+"px",
height: (4*dimension)+"px"
})
shade.fadeOut();
popover.move({
target: $(".red-ui-editor"),
direction: step.fallback,
offset: 10,
transition: true
})
// popover.element.addClass('red-ui-tourGuide-popover-bounce');
},isSVG?0:500);
})
}
var stepEventListener = function() {
focus.removeClass("transition");
targetElement.css("z-index",zIndex);
completeStep(step, state, done);
}
if (step.wait) {
if (step.wait.type === "dom-event") {
var eventTarget = targetElement;
if (step.wait.element) {
if (typeof step.wait.element === "string") {
eventTarget = $(step.wait.element);
} else if (typeof step.wait.element === "function") {
eventTarget = step.wait.element.call(state);
}
}
var listener = {
type: step.wait.type,
target: eventTarget,
event: step.wait.event,
listener: function() {
stepEventListener();
},
opts: { once: true }
}
activeListeners.push(listener)
eventTarget[0].addEventListener(listener.event,listener.listener,listener.opts)
} else if (step.wait.type === "nr-event") {
var listener = {
type: step.wait.type,
event: step.wait.event,
listener: function() {
if (step.wait.filter) {
if (!step.wait.filter.apply(state,arguments)) {
return;
}
}
stepEventListener();
}
}
activeListeners.push(listener);
RED.events.on(listener.event,listener.listener);
}
}
})
}
return {
load: loadTour,
run: run,
reset: function() {
RED.settings.set("editor.tours.welcome",'');
}
}
})();

View File

@ -139,7 +139,8 @@ RED.userSettings = (function() {
{ {
title: "menu.label.other", title: "menu.label.other",
options: [ options: [
{setting:"view-show-tips",oldSettings:"menu-menu-item-show-tips",label:"menu.label.showTips",toggle:true,default:true,onchange:"core:toggle-show-tips"} {setting:"view-show-tips",oldSettings:"menu-menu-item-show-tips",label:"menu.label.showTips",toggle:true,default:true,onchange:"core:toggle-show-tips"},
{setting:"view-show-welcome-tours",label:"menu.label.showWelcomeTours",toggle:true,default:true}
] ]
} }
]; ];

View File

@ -22,8 +22,82 @@ RED.utils = (function() {
return renderMarkdown(txt); return renderMarkdown(txt);
} }
_marked.setOptions({ const descriptionList = {
renderer: new _marked.Renderer(), name: 'descriptionList',
level: 'block', // Is this a block-level or inline-level tokenizer?
start(src) {
if (!src) { return null; }
let m = src.match(/:[^:\n]/);
return m && m.index; // Hint to Marked.js to stop and check for a match
},
tokenizer(src, tokens) {
if (!src) { return null; }
const rule = /^(?::[^:\n]+:[^:\n]*(?:\n|$))+/; // Regex for the complete token
const match = rule.exec(src);
if (match) {
return { // Token to generate
type: 'descriptionList', // Should match "name" above
raw: match[0], // Text to consume from the source
text: match[0].trim(), // Additional custom properties
tokens: this.lexer.inlineTokens(match[0].trim()) // inlineTokens to process **bold**, *italics*, etc.
};
}
},
renderer(token) {
return `<dl class="message-properties">${this.parser.parseInline(token.tokens)}\n</dl>`; // parseInline to turn child tokens into HTML
}
};
const description = {
name: 'description',
level: 'inline', // Is this a block-level or inline-level tokenizer?
start(src) {
if (!src) { return null; }
let m = src.match(/:/);
return m && m.index; // Hint to Marked.js to stop and check for a match
},
tokenizer(src, tokens) {
if (!src) { return null; }
const rule = /^:([^:\n]+)\(([^:\n]+)\).*?:([^:\n]*)(?:\n|$)/; // Regex for the complete token
const match = rule.exec(src);
if (match) {
return { // Token to generate
type: 'description', // Should match "name" above
raw: match[0], // Text to consume from the source
dt: this.lexer.inlineTokens(match[1].trim()), // Additional custom properties
types: this.lexer.inlineTokens(match[2].trim()),
dd: this.lexer.inlineTokens(match[3].trim()),
};
}
},
renderer(token) {
return `\n<dt>${this.parser.parseInline(token.dt)}<span class="property-type">${this.parser.parseInline(token.types)}</span></dt><dd>${this.parser.parseInline(token.dd)}</dd>`;
},
childTokens: ['dt', 'dd'], // Any child tokens to be visited by walkTokens
walkTokens(token) { // Post-processing on the completed token tree
if (token.type === 'strong') {
token.text += ' walked';
}
}
};
const renderer = new window._marked.Renderer();
//override list creation - add node-ports to order lists
renderer.list = function (body, ordered, start) {
let addClass = /dl.*?class.*?message-properties.*/.test(body);
if (addClass && ordered) {
return '<ol class="node-ports">' + body + '</ol>';
} else if (ordered) {
return '<ol>' + body + '</ol>';
} else {
return '<ul>' + body + '</ul>'
}
}
window._marked.setOptions({
renderer: renderer,
gfm: true, gfm: true,
tables: true, tables: true,
breaks: false, breaks: false,
@ -32,6 +106,8 @@ RED.utils = (function() {
smartypants: false smartypants: false
}); });
window._marked.use({extensions: [descriptionList, description] } );
function renderMarkdown(txt) { function renderMarkdown(txt) {
var rendered = _marked(txt); var rendered = _marked(txt);
var cleaned = DOMPurify.sanitize(rendered, {SAFE_FOR_JQUERY: true}) var cleaned = DOMPurify.sanitize(rendered, {SAFE_FOR_JQUERY: true})
@ -487,7 +563,8 @@ RED.utils = (function() {
expandPaths: expandPaths, expandPaths: expandPaths,
ontoggle: ontoggle, ontoggle: ontoggle,
exposeApi: exposeApi, exposeApi: exposeApi,
tools: tools // tools: tools // Do not pass tools down as we
// keep them attached to the top-level header
} }
).appendTo(row); ).appendTo(row);
} }
@ -516,7 +593,8 @@ RED.utils = (function() {
expandPaths: expandPaths, expandPaths: expandPaths,
ontoggle: ontoggle, ontoggle: ontoggle,
exposeApi: exposeApi, exposeApi: exposeApi,
tools: tools // tools: tools // Do not pass tools down as we
// keep them attached to the top-level header
} }
).appendTo(row); ).appendTo(row);
} }
@ -571,7 +649,8 @@ RED.utils = (function() {
expandPaths: expandPaths, expandPaths: expandPaths,
ontoggle: ontoggle, ontoggle: ontoggle,
exposeApi: exposeApi, exposeApi: exposeApi,
tools: tools // tools: tools // Do not pass tools down as we
// keep them attached to the top-level header
} }
).appendTo(row); ).appendTo(row);
} }

View File

@ -159,15 +159,15 @@ RED.view.tools = (function() {
nodes.forEach(function(n) { nodes.forEach(function(n) {
var modified = false; var modified = false;
var oldValue = n.l === undefined?true:n.l; var oldValue = n.l === undefined?true:n.l;
var isLink = /^link (in|out)$/.test(n._def.type); var showLabel = n._def.hasOwnProperty("showLabel")?n._def.showLabel:true;
if (labelShown) { if (labelShown) {
if (n.l === false || (isLink && !n.hasOwnProperty('l'))) { if (n.l === false || (!showLabel && !n.hasOwnProperty('l'))) {
n.l = true; n.l = true;
modified = true; modified = true;
} }
} else { } else {
if ((!isLink && (!n.hasOwnProperty('l') || n.l === true)) || (isLink && n.l === true) ) { if ((showLabel && (!n.hasOwnProperty('l') || n.l === true)) || (!showLabel && n.l === true) ) {
n.l = false; n.l = false;
modified = true; modified = true;
} }
@ -427,18 +427,309 @@ RED.view.tools = (function() {
} }
} }
} }
} }
function alignSelectionToEdge(direction) {
var selection = RED.view.selection();
if (selection.nodes && selection.nodes.length > 1) {
var changedNodes = [];
var bounds = {
minX: Number.MAX_SAFE_INTEGER,
minY: Number.MAX_SAFE_INTEGER,
maxX: Number.MIN_SAFE_INTEGER,
maxY: Number.MIN_SAFE_INTEGER
}
selection.nodes.forEach(function(n) {
if (n.type === "group") {
bounds.minX = Math.min(bounds.minX, n.x);
bounds.minY = Math.min(bounds.minY, n.y);
bounds.maxX = Math.max(bounds.maxX, n.x + n.w);
bounds.maxY = Math.max(bounds.maxY, n.y + n.h);
} else {
bounds.minX = Math.min(bounds.minX, n.x - n.w/2);
bounds.minY = Math.min(bounds.minY, n.y - n.h/2);
bounds.maxX = Math.max(bounds.maxX, n.x + n.w/2);
bounds.maxY = Math.max(bounds.maxY, n.y + n.h/2);
}
});
bounds.midX = bounds.minX + (bounds.maxX - bounds.minX)/2;
bounds.midY = bounds.minY + (bounds.maxY - bounds.minY)/2;
selection.nodes.forEach(function(n) {
var targetX;
var targetY;
var isGroup = n.type==="group";
switch(direction) {
case 'top':
targetX = n.x;
targetY = bounds.minY + (isGroup?0:(n.h/2));
break;
case 'bottom':
targetX = n.x;
targetY = bounds.maxY - (isGroup?n.h:(n.h/2));
break;
case 'left':
targetX = bounds.minX + (isGroup?0:(n.w/2));
targetY = n.y;
break;
case 'right':
targetX = bounds.maxX - (isGroup?n.w:(n.w/2));
targetY = n.y;
break;
case 'middle':
targetX = n.x;
targetY = bounds.midY - (isGroup?n.h/2:0)
break;
case 'center':
targetX = bounds.midX - (isGroup?n.w/2:0)
targetY = n.y;
break;
}
if (n.x !== targetX || n.y !== targetY) {
if (!isGroup) {
changedNodes.push({
n:n,
ox: n.x,
oy: n.y,
moved: n.moved
});
n.x = targetX;
n.y = targetY;
n.dirty = true;
n.moved = true;
} else {
var groupNodes = RED.group.getNodes(n, true);
var deltaX = n.x - targetX;
var deltaY = n.y - targetY;
groupNodes.forEach(function(gn) {
if (gn.type !== "group" ) {
changedNodes.push({
n:gn,
ox: gn.x,
oy: gn.y,
moved: gn.moved
});
gn.x = gn.x - deltaX;
gn.y = gn.y - deltaY;
gn.dirty = true;
gn.moved = true;
}
})
}
}
});
if (changedNodes.length > 0) {
RED.history.push({t:"move",nodes:changedNodes,dirty:RED.nodes.dirty()});
RED.nodes.dirty(true);
RED.view.redraw(true);
}
}
}
function distributeSelection(direction) {
var selection = RED.view.selection();
if (selection.nodes && selection.nodes.length > 2) {
var changedNodes = [];
var bounds = {
minX: Number.MAX_SAFE_INTEGER,
minY: Number.MAX_SAFE_INTEGER,
maxX: Number.MIN_SAFE_INTEGER,
maxY: Number.MIN_SAFE_INTEGER
}
var startAnchors = [];
var endAnchors = [];
selection.nodes.forEach(function(n) {
var nx,ny;
if (n.type === "group") {
nx = n.x + n.w/2;
ny = n.y + n.h/2;
} else {
nx = n.x;
ny = n.y;
}
if (direction === "h") {
if (nx < bounds.minX) {
startAnchors = [];
bounds.minX = nx;
}
if (nx === bounds.minX) {
startAnchors.push(n);
}
if (nx > bounds.maxX) {
endAnchors = [];
bounds.maxX = nx;
}
if (nx === bounds.maxX) {
endAnchors.push(n);
}
} else {
if (ny < bounds.minY) {
startAnchors = [];
bounds.minY = ny;
}
if (ny === bounds.minY) {
startAnchors.push(n);
}
if (ny > bounds.maxY) {
endAnchors = [];
bounds.maxY = ny;
}
if (ny === bounds.maxY) {
endAnchors.push(n);
}
}
});
var startAnchor = startAnchors[0];
var endAnchor = endAnchors[0];
var nodeSpace = 0;
var nodesToMove = selection.nodes.filter(function(n) {
if (n.id !== startAnchor.id && n.id !== endAnchor.id) {
nodeSpace += direction === 'h'?n.w:n.h;
return true;
}
return false;
}).sort(function(A,B) {
if (direction === 'h') {
return A.x - B.x
} else {
return A.y - B.y
}
})
var saX = startAnchor.x + startAnchor.w/2;
var saY = startAnchor.y + startAnchor.h/2;
if (startAnchor.type === "group") {
saX = startAnchor.x + startAnchor.w;
saY = startAnchor.y + startAnchor.h;
}
var eaX = endAnchor.x;
var eaY = endAnchor.y;
if (endAnchor.type !== "group") {
eaX -= endAnchor.w/2;
eaY -= endAnchor.h/2;
}
var spaceToFill = direction === 'h'?(eaX - saX - nodeSpace): (eaY - saY - nodeSpace);
var spaceBetweenNodes = spaceToFill / (nodesToMove.length + 1);
var tx = saX;
var ty = saY;
while(nodesToMove.length > 0) {
if (direction === 'h') {
tx += spaceBetweenNodes;
} else {
ty += spaceBetweenNodes;
}
var nextNode = nodesToMove.shift();
var isGroup = nextNode.type==="group";
var nx = nextNode.x;
var ny = nextNode.y;
if (!isGroup) {
tx += nextNode.w/2;
ty += nextNode.h/2;
}
if ((direction === 'h' && nx !== tx) || (direction === 'v' && ny !== ty)) {
if (!isGroup) {
changedNodes.push({
n:nextNode,
ox: nextNode.x,
oy: nextNode.y,
moved: nextNode.moved
});
if (direction === 'h') {
nextNode.x = tx;
} else {
nextNode.y = ty;
}
nextNode.dirty = true;
nextNode.moved = true;
} else {
var groupNodes = RED.group.getNodes(nextNode, true);
var deltaX = direction === 'h'? nx - tx : 0;
var deltaY = direction === 'v'? ny - ty : 0;
groupNodes.forEach(function(gn) {
if (gn.type !== "group" ) {
changedNodes.push({
n:gn,
ox: gn.x,
oy: gn.y,
moved: gn.moved
});
gn.x = gn.x - deltaX;
gn.y = gn.y - deltaY;
gn.dirty = true;
gn.moved = true;
}
})
}
}
if (isGroup) {
tx += nextNode.w;
ty += nextNode.h;
} else {
tx += nextNode.w/2;
ty += nextNode.h/2;
}
}
if (changedNodes.length > 0) {
RED.history.push({t:"move",nodes:changedNodes,dirty:RED.nodes.dirty()});
RED.nodes.dirty(true);
RED.view.redraw(true);
}
}
}
function reorderSelection(dir) {
var selection = RED.view.selection();
if (selection.nodes) {
var nodesToMove = [];
selection.nodes.forEach(function(n) {
if (n.type === "group") {
nodesToMove = nodesToMove.concat(RED.group.getNodes(n, true).filter(function(n) {
return n.type !== "group";
}))
} else if (n.type !== "subflow"){
nodesToMove.push(n);
}
})
if (nodesToMove.length > 0) {
var z = nodesToMove[0].z;
var existingOrder = RED.nodes.getNodeOrder(z);
var movedNodes;
if (dir === "forwards") {
movedNodes = RED.nodes.moveNodesForwards(nodesToMove);
} else if (dir === "backwards") {
movedNodes = RED.nodes.moveNodesBackwards(nodesToMove);
} else if (dir === "front") {
movedNodes = RED.nodes.moveNodesToFront(nodesToMove);
} else if (dir === "back") {
movedNodes = RED.nodes.moveNodesToBack(nodesToMove);
}
if (movedNodes.length > 0) {
var newOrder = RED.nodes.getNodeOrder(z);
RED.history.push({t:"reorder",nodes:{z:z,from:existingOrder,to:newOrder},dirty:RED.nodes.dirty()});
RED.nodes.dirty(true);
RED.view.redraw(true);
}
}
}
}
return { return {
init: function() { init: function() {
RED.actions.add("core:show-selected-node-labels", function() { setSelectedNodeLabelState(true); }) RED.actions.add("core:show-selected-node-labels", function() { setSelectedNodeLabelState(true); })
RED.actions.add("core:hide-selected-node-labels", function() { setSelectedNodeLabelState(false); }) RED.actions.add("core:hide-selected-node-labels", function() { setSelectedNodeLabelState(false); })
RED.actions.add("core:align-selection-to-grid", alignToGrid);
RED.actions.add("core:scroll-view-up", function() { RED.view.scroll(0,-RED.view.gridSize());}); RED.actions.add("core:scroll-view-up", function() { RED.view.scroll(0,-RED.view.gridSize());});
RED.actions.add("core:scroll-view-right", function() { RED.view.scroll(RED.view.gridSize(),0);}); RED.actions.add("core:scroll-view-right", function() { RED.view.scroll(RED.view.gridSize(),0);});
RED.actions.add("core:scroll-view-down", function() { RED.view.scroll(0,RED.view.gridSize());}); RED.actions.add("core:scroll-view-down", function() { RED.view.scroll(0,RED.view.gridSize());});
@ -454,6 +745,12 @@ RED.view.tools = (function() {
RED.actions.add("core:move-selection-down", function() { moveSelection(0,1);}); RED.actions.add("core:move-selection-down", function() { moveSelection(0,1);});
RED.actions.add("core:move-selection-left", function() { moveSelection(-1,0);}); RED.actions.add("core:move-selection-left", function() { moveSelection(-1,0);});
RED.actions.add("core:move-selection-forwards", function() { reorderSelection('forwards') })
RED.actions.add("core:move-selection-backwards", function() { reorderSelection('backwards') })
RED.actions.add("core:move-selection-to-front", function() { reorderSelection('front') })
RED.actions.add("core:move-selection-to-back", function() { reorderSelection('back') })
RED.actions.add("core:step-selection-up", function() { moveSelection(0,-RED.view.gridSize());}); RED.actions.add("core:step-selection-up", function() { moveSelection(0,-RED.view.gridSize());});
RED.actions.add("core:step-selection-right", function() { moveSelection(RED.view.gridSize(),0);}); RED.actions.add("core:step-selection-right", function() { moveSelection(RED.view.gridSize(),0);});
RED.actions.add("core:step-selection-down", function() { moveSelection(0,RED.view.gridSize());}); RED.actions.add("core:step-selection-down", function() { moveSelection(0,RED.view.gridSize());});
@ -474,6 +771,20 @@ RED.view.tools = (function() {
RED.actions.add("core:go-to-nearest-node-on-right", function() { gotoNearestNode('right')}) RED.actions.add("core:go-to-nearest-node-on-right", function() { gotoNearestNode('right')})
RED.actions.add("core:go-to-nearest-node-above", function() { gotoNearestNode('up') }) RED.actions.add("core:go-to-nearest-node-above", function() { gotoNearestNode('up') })
RED.actions.add("core:go-to-nearest-node-below", function() { gotoNearestNode('down') }) RED.actions.add("core:go-to-nearest-node-below", function() { gotoNearestNode('down') })
RED.actions.add("core:align-selection-to-grid", alignToGrid);
RED.actions.add("core:align-selection-to-left", function() { alignSelectionToEdge('left') })
RED.actions.add("core:align-selection-to-right", function() { alignSelectionToEdge('right') })
RED.actions.add("core:align-selection-to-top", function() { alignSelectionToEdge('top') })
RED.actions.add("core:align-selection-to-bottom", function() { alignSelectionToEdge('bottom') })
RED.actions.add("core:align-selection-to-middle", function() { alignSelectionToEdge('middle') })
RED.actions.add("core:align-selection-to-center", function() { alignSelectionToEdge('center') })
RED.actions.add("core:distribute-selection-horizontally", function() { distributeSelection('h') })
RED.actions.add("core:distribute-selection-vertically", function() { distributeSelection('v') })
// RED.actions.add("core:add-node", function() { addNode() }) // RED.actions.add("core:add-node", function() { addNode() })
}, },
/** /**

View File

@ -345,8 +345,8 @@ RED.view = (function() {
activeSubflow = RED.nodes.subflow(event.workspace); activeSubflow = RED.nodes.subflow(event.workspace);
RED.menu.setDisabled("menu-item-workspace-edit", activeSubflow); RED.menu.setDisabled("menu-item-workspace-edit", activeSubflow || event.workspace === 0);
RED.menu.setDisabled("menu-item-workspace-delete",RED.workspaces.count() == 1 || activeSubflow); RED.menu.setDisabled("menu-item-workspace-delete",event.workspace === 0 || RED.workspaces.count() == 1 || activeSubflow);
if (workspaceScrollPositions[event.workspace]) { if (workspaceScrollPositions[event.workspace]) {
chart.scrollLeft(workspaceScrollPositions[event.workspace].left); chart.scrollLeft(workspaceScrollPositions[event.workspace].left);
@ -413,7 +413,7 @@ RED.view = (function() {
var nn = result.node; var nn = result.node;
var showLabel = RED.utils.getMessageProperty(RED.settings.get('editor'),"view.view-node-show-label"); var showLabel = RED.utils.getMessageProperty(RED.settings.get('editor'),"view.view-node-show-label");
if (showLabel !== undefined && !/^link (in|out)$/.test(nn._def.type) && !nn._def.defaults.hasOwnProperty("l")) { if (showLabel !== undefined && (nn._def.hasOwnProperty("showLabel")?nn._def.showLabel:true) && !nn._def.defaults.hasOwnProperty("l")) {
nn.l = showLabel; nn.l = showLabel;
} }
@ -501,6 +501,28 @@ RED.view = (function() {
RED.actions.add("core:copy-selection-to-internal-clipboard",copySelection); RED.actions.add("core:copy-selection-to-internal-clipboard",copySelection);
RED.actions.add("core:cut-selection-to-internal-clipboard",function(){copySelection();deleteSelection();}); RED.actions.add("core:cut-selection-to-internal-clipboard",function(){copySelection();deleteSelection();});
RED.actions.add("core:paste-from-internal-clipboard",function(){importNodes(clipboard,{generateIds: true});}); RED.actions.add("core:paste-from-internal-clipboard",function(){importNodes(clipboard,{generateIds: true});});
RED.events.on("view:selection-changed", function(selection) {
var hasSelection = (selection.nodes && selection.nodes.length > 0);
var hasMultipleSelection = hasSelection && selection.nodes.length > 1;
RED.menu.setDisabled("menu-item-edit-cut",!hasSelection);
RED.menu.setDisabled("menu-item-edit-copy",!hasSelection);
RED.menu.setDisabled("menu-item-edit-select-connected",!hasSelection);
RED.menu.setDisabled("menu-item-view-tools-move-to-back",!hasSelection);
RED.menu.setDisabled("menu-item-view-tools-move-to-front",!hasSelection);
RED.menu.setDisabled("menu-item-view-tools-move-backwards",!hasSelection);
RED.menu.setDisabled("menu-item-view-tools-move-forwards",!hasSelection);
RED.menu.setDisabled("menu-item-view-tools-align-left",!hasMultipleSelection);
RED.menu.setDisabled("menu-item-view-tools-align-center",!hasMultipleSelection);
RED.menu.setDisabled("menu-item-view-tools-align-right",!hasMultipleSelection);
RED.menu.setDisabled("menu-item-view-tools-align-top",!hasMultipleSelection);
RED.menu.setDisabled("menu-item-view-tools-align-middle",!hasMultipleSelection);
RED.menu.setDisabled("menu-item-view-tools-align-bottom",!hasMultipleSelection);
RED.menu.setDisabled("menu-item-view-tools-distribute-horizontally",!hasMultipleSelection);
RED.menu.setDisabled("menu-item-view-tools-distribute-veritcally",!hasMultipleSelection);
})
RED.actions.add("core:delete-selection",deleteSelection); RED.actions.add("core:delete-selection",deleteSelection);
RED.actions.add("core:edit-selected-node",editSelection); RED.actions.add("core:edit-selected-node",editSelection);
RED.actions.add("core:go-to-selection",function() { RED.actions.add("core:go-to-selection",function() {
@ -653,16 +675,19 @@ RED.view = (function() {
function updateActiveNodes() { function updateActiveNodes() {
var activeWorkspace = RED.workspaces.active(); var activeWorkspace = RED.workspaces.active();
if (activeWorkspace !== 0) {
activeNodes = RED.nodes.filterNodes({z:activeWorkspace}); activeNodes = RED.nodes.filterNodes({z:activeWorkspace});
activeNodes.forEach(function(n,i) {
n._index = i;
})
activeLinks = RED.nodes.filterLinks({ activeLinks = RED.nodes.filterLinks({
source:{z:activeWorkspace}, source:{z:activeWorkspace},
target:{z:activeWorkspace} target:{z:activeWorkspace}
}); });
activeGroups = RED.nodes.groups(activeWorkspace)||[]; activeGroups = RED.nodes.groups(activeWorkspace)||[];
activeGroups.forEach(function(g) { activeGroups.forEach(function(g, i) {
g._index = i;
if (g.g) { if (g.g) {
g._root = g.g; g._root = g.g;
g._depth = 1; g._depth = 1;
@ -671,6 +696,12 @@ RED.view = (function() {
g._depth = 0; g._depth = 0;
} }
}); });
} else {
activeNodes = [];
activeLinks = [];
activeGroups = [];
}
var changed = false; var changed = false;
do { do {
changed = false; changed = false;
@ -695,7 +726,8 @@ RED.view = (function() {
if (a._root === b._root) { if (a._root === b._root) {
return a._depth - b._depth; return a._depth - b._depth;
} else { } else {
return a._root.localeCompare(b._root); // return a._root.localeCompare(b._root);
return a._index - b._index;
} }
}); });
@ -704,7 +736,8 @@ RED.view = (function() {
if (a._root === b._root) { if (a._root === b._root) {
return a._depth - b._depth; return a._depth - b._depth;
} else { } else {
return a._root.localeCompare(b._root); return a._index - b._index;
// return a._root.localeCompare(b._root);
} }
}) })
} }
@ -1055,7 +1088,7 @@ RED.view = (function() {
nn.x = point[0]; nn.x = point[0];
nn.y = point[1]; nn.y = point[1];
var showLabel = RED.utils.getMessageProperty(RED.settings.get('editor'),"view.view-node-show-label"); var showLabel = RED.utils.getMessageProperty(RED.settings.get('editor'),"view.view-node-show-label");
if (showLabel !== undefined && !/^link (in|out)$/.test(nn._def.type) && !nn._def.defaults.hasOwnProperty("l")) { if (showLabel !== undefined && (nn._def.hasOwnProperty("showLabel")?nn._def.showLabel:true) && !nn._def.defaults.hasOwnProperty("l")) {
nn.l = showLabel; nn.l = showLabel;
} }
if (quickAddLink) { if (quickAddLink) {
@ -1939,8 +1972,8 @@ RED.view = (function() {
function updateSelection() { function updateSelection() {
var selection = {}; var selection = {};
var activeWorkspace = RED.workspaces.active(); var activeWorkspace = RED.workspaces.active();
var workspaceSelection = RED.workspaces.selection(); var workspaceSelection = RED.workspaces.selection();
if (activeWorkspace !== 0) {
if (workspaceSelection.length === 0) { if (workspaceSelection.length === 0) {
selection = getSelection(); selection = getSelection();
activeLinks = RED.nodes.filterLinks({ activeLinks = RED.nodes.filterLinks({
@ -1958,7 +1991,7 @@ RED.view = (function() {
activeLinkNodes = {}; activeLinkNodes = {};
for (var i=0;i<movingSet.length();i++) { for (var i=0;i<movingSet.length();i++) {
var msn = movingSet.get(i); var msn = movingSet.get(i);
if ((msn.n.type === "link out" || msn.n.type === "link in") && if (((msn.n.type === "link out" && msn.n.mode !== 'return') || msn.n.type === "link in") &&
(msn.n.z === activeWorkspace)) { (msn.n.z === activeWorkspace)) {
var linkNode = msn.n; var linkNode = msn.n;
activeLinkNodes[linkNode.id] = linkNode; activeLinkNodes[linkNode.id] = linkNode;
@ -2027,6 +2060,7 @@ RED.view = (function() {
} else { } else {
selection.flows = workspaceSelection; selection.flows = workspaceSelection;
} }
}
var selectionJSON = activeWorkspace+":"+JSON.stringify(selection,function(key,value) { var selectionJSON = activeWorkspace+":"+JSON.stringify(selection,function(key,value) {
if (key === 'nodes' || key === 'flows') { if (key === 'nodes' || key === 'flows') {
return value.map(function(n) { return n.id }) return value.map(function(n) { return n.id })
@ -2332,6 +2366,7 @@ RED.view = (function() {
} }
} }
clipboard = JSON.stringify(nns); clipboard = JSON.stringify(nns);
RED.menu.setDisabled("menu-item-edit-paste", false);
if (nodeCount > 0) { if (nodeCount > 0) {
RED.notify(RED._("clipboard.nodeCopied",{count:nodeCount}),{id:"clipboard"}); RED.notify(RED._("clipboard.nodeCopied",{count:nodeCount}),{id:"clipboard"});
} else if (groupCount > 0) { } else if (groupCount > 0) {
@ -3807,7 +3842,6 @@ RED.view = (function() {
.attr("class", "red-ui-flow-node red-ui-flow-node-group") .attr("class", "red-ui-flow-node red-ui-flow-node-group")
.classed("red-ui-flow-subflow", activeSubflow != null); .classed("red-ui-flow-subflow", activeSubflow != null);
nodeEnter.each(function(d,i) { nodeEnter.each(function(d,i) {
this.__outputs__ = []; this.__outputs__ = [];
this.__inputs__ = []; this.__inputs__ = [];
@ -3953,7 +3987,12 @@ RED.view = (function() {
RED.hooks.trigger("viewAddNode",{node:d,el:this}) RED.hooks.trigger("viewAddNode",{node:d,el:this})
}); });
var nodesReordered = false;
node.each(function(d,i) { node.each(function(d,i) {
if (d._reordered) {
nodesReordered = true;
delete d._reordered;
}
if (d.dirty) { if (d.dirty) {
var self = this; var self = this;
var thisNode = d3.select(this); var thisNode = d3.select(this);
@ -3967,10 +4006,10 @@ RED.view = (function() {
var labelParts; var labelParts;
if (d.resize || this.__hideLabel__ !== hideLabel || this.__label__ !== label || this.__outputs__.length !== d.outputs) { if (d.resize || this.__hideLabel__ !== hideLabel || this.__label__ !== label || this.__outputs__.length !== d.outputs) {
labelParts = getLabelParts(label, "red-ui-flow-node-label"); labelParts = getLabelParts(label, "red-ui-flow-node-label");
this.__label__ = label; if (labelParts.lines.length !== this.__labelLineCount__ || this.__label__ !== label) {
if (labelParts.lines.length !== this.__labelLineCount__) {
d.resize = true; d.resize = true;
} }
this.__label__ = label;
this.__labelLineCount__ = labelParts.lines.length; this.__labelLineCount__ = labelParts.lines.length;
if (hideLabel) { if (hideLabel) {
@ -4101,7 +4140,7 @@ RED.view = (function() {
} }
var numOutputs = d.outputs; var numOutputs = d.outputs;
if (isLink && d.type === "link out") { if (isLink && d.type === "link out") {
if (showAllLinkPorts===PORT_TYPE_OUTPUT || activeLinkNodes[d.id]) { if (d.mode !== "return" && (showAllLinkPorts===PORT_TYPE_OUTPUT || activeLinkNodes[d.id])) {
numOutputs = 1; numOutputs = 1;
} else { } else {
numOutputs = 0; numOutputs = 0;
@ -4261,6 +4300,13 @@ RED.view = (function() {
RED.hooks.trigger("viewRedrawNode",{node:d,el:this}) RED.hooks.trigger("viewRedrawNode",{node:d,el:this})
}); });
if (nodesReordered) {
node.sort(function(a,b) {
return a._index - b._index;
})
}
var link = linkLayer.selectAll(".red-ui-flow-link").data( var link = linkLayer.selectAll(".red-ui-flow-link").data(
activeLinks, activeLinks,
function(d) { function(d) {
@ -4499,7 +4545,7 @@ RED.view = (function() {
if (a._root === b._root) { if (a._root === b._root) {
return a._depth - b._depth; return a._depth - b._depth;
} else { } else {
return a._root.localeCompare(b._root); return a._index - b._index;
} }
}) })
} }

View File

@ -21,21 +21,46 @@ RED.workspaces = (function() {
var workspaceIndex = 0; var workspaceIndex = 0;
var viewStack = []; var viewStack = [];
var hideStack = [];
var viewStackPos = 0; var viewStackPos = 0;
function addToViewStack(id) { function addToViewStack(id) {
if (viewStackPos !== viewStack.length) { if (viewStackPos !== viewStack.length) {
viewStack.splice(viewStackPos); viewStack.splice(viewStackPos);
} }
viewStack.push(id); viewStack.push(id);
viewStackPos = viewStack.length; viewStackPos = viewStack.length;
// console.warn("addToViewStack",id,viewStack); }
function removeFromHideStack(id) {
hideStack = hideStack.filter(function(v) {
if (v === id) {
return false;
} else if (Array.isArray(v)) {
var i = v.indexOf(id);
if (i > -1) {
v.splice(i,1);
}
if (v.length === 0) {
return false;
}
return true
}
return true;
})
} }
function addWorkspace(ws,skipHistoryEntry,targetIndex) { function addWorkspace(ws,skipHistoryEntry,targetIndex) {
if (ws) { if (ws) {
if (!ws.closeable) {
ws.hideable = true;
}
workspace_tabs.addTab(ws,targetIndex); workspace_tabs.addTab(ws,targetIndex);
var hiddenTabs = JSON.parse(RED.settings.getLocal("hiddenTabs")||"{}");
if (hiddenTabs[ws.id]) {
workspace_tabs.hideTab(ws.id);
}
workspace_tabs.resize(); workspace_tabs.resize();
} else { } else {
var tabId = RED.nodes.id(); var tabId = RED.nodes.id();
@ -43,7 +68,15 @@ RED.workspaces = (function() {
workspaceIndex += 1; workspaceIndex += 1;
} while ($("#red-ui-workspace-tabs a[title='"+RED._('workspace.defaultName',{number:workspaceIndex})+"']").size() !== 0); } while ($("#red-ui-workspace-tabs a[title='"+RED._('workspace.defaultName',{number:workspaceIndex})+"']").size() !== 0);
ws = {type:"tab",id:tabId,disabled: false,info:"",label:RED._('workspace.defaultName',{number:workspaceIndex})}; ws = {
type: "tab",
id: tabId,
disabled: false,
info: "",
label: RED._('workspace.defaultName',{number:workspaceIndex}),
env: [],
hideable: true
};
RED.nodes.addWorkspace(ws,targetIndex); RED.nodes.addWorkspace(ws,targetIndex);
workspace_tabs.addTab(ws,targetIndex); workspace_tabs.addTab(ws,targetIndex);
workspace_tabs.activateTab(tabId); workspace_tabs.activateTab(tabId);
@ -55,6 +88,7 @@ RED.workspaces = (function() {
RED.view.focus(); RED.view.focus();
return ws; return ws;
} }
function deleteWorkspace(ws) { function deleteWorkspace(ws) {
if (workspaceTabCount === 1) { if (workspaceTabCount === 1) {
return; return;
@ -78,165 +112,9 @@ RED.workspaces = (function() {
if (subflow) { if (subflow) {
RED.editor.editSubflow(subflow); RED.editor.editSubflow(subflow);
} }
return; } else {
RED.editor.editFlow(workspace);
} }
RED.view.state(RED.state.EDITING);
var tabflowEditor;
var trayOptions = {
title: RED._("workspace.editFlow",{name:RED.utils.sanitize(workspace.label)}),
buttons: [
{
id: "node-dialog-delete",
class: 'leftButton'+((workspaceTabCount === 1)?" disabled":""),
text: RED._("common.label.delete"), //'<i class="fa fa-trash"></i>',
click: function() {
deleteWorkspace(workspace);
RED.tray.close();
}
},
{
id: "node-dialog-cancel",
text: RED._("common.label.cancel"),
click: function() {
RED.tray.close();
}
},
{
id: "node-dialog-ok",
class: "primary",
text: RED._("common.label.done"),
click: function() {
var label = $( "#node-input-name" ).val();
var changed = false;
var changes = {};
if (workspace.label != label) {
changes.label = workspace.label;
changed = true;
workspace.label = label;
workspace_tabs.renameTab(workspace.id,label);
}
var disabled = $("#node-input-disabled").prop("checked");
if (workspace.disabled !== disabled) {
changes.disabled = workspace.disabled;
changed = true;
workspace.disabled = disabled;
}
var info = tabflowEditor.getValue();
if (workspace.info !== info) {
changes.info = workspace.info;
changed = true;
workspace.info = info;
}
$("#red-ui-tab-"+(workspace.id.replace(".","-"))).toggleClass('red-ui-workspace-disabled',!!workspace.disabled);
$("#red-ui-workspace").toggleClass("red-ui-workspace-disabled",!!workspace.disabled);
if (changed) {
var historyEvent = {
t: "edit",
changes:changes,
node: workspace,
dirty: RED.nodes.dirty()
}
workspace.changed = true;
RED.history.push(historyEvent);
RED.nodes.dirty(true);
RED.sidebar.config.refresh();
if (changes.hasOwnProperty('disabled')) {
RED.nodes.eachNode(function(n) {
if (n.z === workspace.id) {
n.dirty = true;
}
});
RED.view.redraw();
}
RED.events.emit("flows:change",workspace);
}
RED.tray.close();
}
}
],
resize: function(dimensions) {
var rows = $("#dialog-form>div:not(.node-text-editor-row)");
var editorRow = $("#dialog-form>div.node-text-editor-row");
var height = $("#dialog-form").height();
for (var i=0; i<rows.size(); i++) {
height -= $(rows[i]).outerHeight(true);
}
height -= (parseInt($("#dialog-form").css("marginTop"))+parseInt($("#dialog-form").css("marginBottom")));
$(".node-text-editor").css("height",height+"px");
tabflowEditor.resize();
},
open: function(tray) {
var trayFooter = tray.find(".red-ui-tray-footer");
var trayBody = tray.find('.red-ui-tray-body');
var trayFooterLeft = $('<div class="red-ui-tray-footer-left"></div>').appendTo(trayFooter)
var dialogForm = $('<form id="dialog-form" class="form-horizontal"></form>').appendTo(trayBody);
$('<div class="form-row">'+
'<label for="node-input-name" data-i18n="[append]editor:common.label.name"><i class="fa fa-tag"></i> </label>'+
'<input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">'+
'</div>').appendTo(dialogForm);
if (!workspace.hasOwnProperty("disabled")) {
workspace.disabled = false;
}
$('<input id="node-input-disabled" type="checkbox">').prop("checked",workspace.disabled).appendTo(trayFooterLeft).toggleButton({
enabledIcon: "fa-circle-thin",
disabledIcon: "fa-ban",
invertState: true
})
var row = $('<div class="form-row node-text-editor-row">'+
'<label for="node-input-info" data-i18n="editor:workspace.info" style="width:300px;"></label>'+
'<div style="min-height:250px;" class="node-text-editor" id="node-input-info"></div>'+
'</div>').appendTo(dialogForm);
tabflowEditor = RED.editor.createEditor({
id: 'node-input-info',
mode: 'ace/mode/markdown',
value: ""
});
$('#node-info-input-info-expand').on("click", function(e) {
e.preventDefault();
var value = tabflowEditor.getValue();
RED.editor.editMarkdown({
value: value,
width: "Infinity",
cursor: tabflowEditor.getCursorPosition(),
complete: function(v,cursor) {
tabflowEditor.setValue(v, -1);
tabflowEditor.gotoLine(cursor.row+1,cursor.column,false);
setTimeout(function() {
tabflowEditor.focus();
},300);
}
})
});
$('<input type="text" style="display: none;" />').prependTo(dialogForm);
dialogForm.on("submit", function(e) { e.preventDefault();});
$("#node-input-name").val(workspace.label);
RED.text.bidi.prepareInput($("#node-input-name"));
tabflowEditor.getSession().setValue(workspace.info || "", -1);
dialogForm.i18n();
},
close: function() {
if (RED.view.state() != RED.state.IMPORT_DRAGGING) {
RED.view.state(RED.state.DEFAULT);
}
var selection = RED.view.selection();
if (!selection.nodes && !selection.links && workspace.id === activeWorkspace) {
RED.sidebar.info.refresh(workspace);
}
tabflowEditor.destroy();
}
}
RED.tray.show(trayOptions);
} }
@ -249,11 +127,18 @@ RED.workspaces = (function() {
var event = { var event = {
old: activeWorkspace old: activeWorkspace
} }
if (tab) {
$("#red-ui-workspace-chart").show();
activeWorkspace = tab.id; activeWorkspace = tab.id;
event.workspace = activeWorkspace;
RED.events.emit("workspace:change",event);
window.location.hash = 'flow/'+tab.id; window.location.hash = 'flow/'+tab.id;
$("#red-ui-workspace").toggleClass("red-ui-workspace-disabled",!!tab.disabled); $("#red-ui-workspace").toggleClass("red-ui-workspace-disabled",!!tab.disabled);
} else {
$("#red-ui-workspace-chart").hide();
activeWorkspace = 0;
window.location.hash = '';
}
event.workspace = activeWorkspace;
RED.events.emit("workspace:change",event);
RED.sidebar.config.refresh(); RED.sidebar.config.refresh();
RED.view.focus(); RED.view.focus();
}, },
@ -278,7 +163,7 @@ RED.workspaces = (function() {
if (tab.disabled) { if (tab.disabled) {
$("#red-ui-tab-"+(tab.id.replace(".","-"))).addClass('red-ui-workspace-disabled'); $("#red-ui-tab-"+(tab.id.replace(".","-"))).addClass('red-ui-workspace-disabled');
} }
RED.menu.setDisabled("menu-item-workspace-delete",workspaceTabCount <= 1); RED.menu.setDisabled("menu-item-workspace-delete",activeWorkspace === 0 || workspaceTabCount <= 1);
if (workspaceTabCount === 1) { if (workspaceTabCount === 1) {
showWorkspace(); showWorkspace();
} }
@ -286,14 +171,23 @@ RED.workspaces = (function() {
onremove: function(tab) { onremove: function(tab) {
if (tab.type === "tab") { if (tab.type === "tab") {
workspaceTabCount--; workspaceTabCount--;
} else {
hideStack.push(tab.id);
} }
RED.menu.setDisabled("menu-item-workspace-delete",workspaceTabCount <= 1); RED.menu.setDisabled("menu-item-workspace-delete",activeWorkspace === 0 || workspaceTabCount <= 1);
if (workspaceTabCount === 0) { if (workspaceTabCount === 0) {
hideWorkspace(); hideWorkspace();
} }
}, },
onreorder: function(oldOrder, newOrder) { onreorder: function(oldOrder, newOrder) {
RED.history.push({t:'reorder',order:oldOrder,dirty:RED.nodes.dirty()}); RED.history.push({
t:'reorder',
workspaces: {
from:oldOrder,
to:newOrder
},
dirty:RED.nodes.dirty()
});
RED.nodes.dirty(true); RED.nodes.dirty(true);
setWorkspaceOrder(newOrder); setWorkspaceOrder(newOrder);
}, },
@ -312,12 +206,67 @@ RED.workspaces = (function() {
$(".red-ui-sidebar-shade").show(); $(".red-ui-sidebar-shade").show();
} }
}, },
onhide: function(tab) {
hideStack.push(tab.id);
RED.events.emit("workspace:hide",{workspace: tab.id})
},
onshow: function(tab) {
removeFromHideStack(tab.id);
RED.events.emit("workspace:show",{workspace: tab.id})
},
minimumActiveTabWidth: 150, minimumActiveTabWidth: 150,
scrollable: true, scrollable: true,
addButton: "core:add-flow", addButton: "core:add-flow",
addButtonCaption: RED._("workspace.addFlow"), addButtonCaption: RED._("workspace.addFlow"),
searchButton: "core:list-flows", menu: [
searchButtonCaption: RED._("workspace.listFlows") {
id:"red-ui-tabs-menu-option-search-flows",
label: RED._("workspace.listFlows"),
onselect: "core:list-flows"
},
{
id:"red-ui-tabs-menu-option-search-subflows",
label: RED._("workspace.listSubflows"),
onselect: "core:list-subflows"
},
null,
{
id:"red-ui-tabs-menu-option-add-flow",
label: RED._("workspace.addFlow"),
onselect: "core:add-flow"
},
{
id:"red-ui-tabs-menu-option-add-flow-right",
label: RED._("workspace.addFlowToRight"),
onselect: "core:add-flow-to-right"
},
null,
{
id:"red-ui-tabs-menu-option-add-hide-flows",
label: RED._("workspace.hideFlow"),
onselect: "core:hide-flow"
},
{
id:"red-ui-tabs-menu-option-add-hide-other-flows",
label: RED._("workspace.hideOtherFlows"),
onselect: "core:hide-other-flows"
},
{
id:"red-ui-tabs-menu-option-add-show-all-flows",
label: RED._("workspace.showAllFlows"),
onselect: "core:show-all-flows"
},
{
id:"red-ui-tabs-menu-option-add-hide-all-flows",
label: RED._("workspace.hideAllFlows"),
onselect: "core:hide-all-flows"
},
{
id:"red-ui-tabs-menu-option-add-show-last-flow",
label: RED._("workspace.showLastHiddenFlow"),
onselect: "core:show-last-hidden-flow"
}
]
}); });
workspaceTabCount = 0; workspaceTabCount = 0;
} }
@ -368,15 +317,102 @@ RED.workspaces = (function() {
}); });
RED.actions.add("core:add-flow",function(opts) { addWorkspace(undefined,undefined,opts?opts.index:undefined)}); RED.actions.add("core:add-flow",function(opts) { addWorkspace(undefined,undefined,opts?opts.index:undefined)});
RED.actions.add("core:add-flow-to-right",function(opts) { addWorkspace(undefined,undefined,workspace_tabs.activeIndex()+1)});
RED.actions.add("core:edit-flow",editWorkspace); RED.actions.add("core:edit-flow",editWorkspace);
RED.actions.add("core:remove-flow",removeWorkspace); RED.actions.add("core:remove-flow",removeWorkspace);
RED.actions.add("core:enable-flow",enableWorkspace); RED.actions.add("core:enable-flow",enableWorkspace);
RED.actions.add("core:disable-flow",disableWorkspace); RED.actions.add("core:disable-flow",disableWorkspace);
RED.actions.add("core:hide-flow", function() {
var selection = workspace_tabs.selection();
if (selection.length === 0) {
selection = [{id:activeWorkspace}]
}
var hiddenTabs = [];
selection.forEach(function(ws) {
RED.workspaces.hide(ws.id);
hideStack.pop();
hiddenTabs.push(ws.id);
})
if (hiddenTabs.length > 0) {
hideStack.push(hiddenTabs);
}
workspace_tabs.clearSelection();
})
RED.actions.add("core:hide-other-flows", function() {
var selection = workspace_tabs.selection();
if (selection.length === 0) {
selection = [{id:activeWorkspace}]
}
var selected = new Set(selection.map(function(ws) { return ws.id }))
var currentTabs = workspace_tabs.listTabs();
var hiddenTabs = [];
currentTabs.forEach(function(id) {
if (!selected.has(id)) {
RED.workspaces.hide(id);
hideStack.pop();
hiddenTabs.push(id);
}
})
if (hiddenTabs.length > 0) {
hideStack.push(hiddenTabs);
}
})
RED.actions.add("core:hide-all-flows", function() {
var currentTabs = workspace_tabs.listTabs();
currentTabs.forEach(function(id) {
RED.workspaces.hide(id);
hideStack.pop();
})
if (currentTabs.length > 0) {
hideStack.push(currentTabs);
}
workspace_tabs.clearSelection();
})
RED.actions.add("core:show-all-flows", function() {
var currentTabs = workspace_tabs.listTabs();
currentTabs.forEach(function(id) {
RED.workspaces.show(id, null, true)
})
})
// RED.actions.add("core:toggle-flows", function() {
// var currentTabs = workspace_tabs.listTabs();
// var visibleCount = workspace_tabs.count();
// currentTabs.forEach(function(id) {
// if (visibleCount === 0) {
// RED.workspaces.show(id)
// } else {
// RED.workspaces.hide(id)
// }
// })
// })
RED.actions.add("core:show-last-hidden-flow", function() {
var id = hideStack.pop();
if (id) {
if (typeof id === 'string') {
RED.workspaces.show(id);
} else {
var last = id.pop();
id.forEach(function(i) {
RED.workspaces.show(i, null, true);
})
setTimeout(function() {
RED.workspaces.show(last);
},150)
}
}
})
RED.actions.add("core:list-flows",function() { RED.actions.add("core:list-flows",function() {
RED.actions.invoke("core:search","type:tab "); RED.actions.invoke("core:search","type:tab ");
}) })
RED.actions.add("core:list-subflows",function() {
RED.actions.invoke("core:search","type:subflow ");
})
RED.actions.add("core:go-to-previous-location", function() { RED.actions.add("core:go-to-previous-location", function() {
if (viewStackPos > 0) { if (viewStackPos > 0) {
if (viewStackPos === viewStack.length) { if (viewStackPos === viewStack.length) {
@ -392,8 +428,6 @@ RED.workspaces = (function() {
RED.workspaces.show(viewStack[++viewStackPos],true); RED.workspaces.show(viewStack[++viewStackPos],true);
} }
}) })
hideWorkspace(); hideWorkspace();
} }
@ -416,7 +450,7 @@ RED.workspaces = (function() {
var changes = { disabled: workspace.disabled }; var changes = { disabled: workspace.disabled };
workspace.disabled = disabled; workspace.disabled = disabled;
$("#red-ui-tab-"+(workspace.id.replace(".","-"))).toggleClass('red-ui-workspace-disabled',!!workspace.disabled); $("#red-ui-tab-"+(workspace.id.replace(".","-"))).toggleClass('red-ui-workspace-disabled',!!workspace.disabled);
if (id === activeWorkspace) { if (id || activeWorkspace) {
$("#red-ui-workspace").toggleClass("red-ui-workspace-disabled",!!workspace.disabled); $("#red-ui-workspace").toggleClass("red-ui-workspace-disabled",!!workspace.disabled);
} }
var historyEvent = { var historyEvent = {
@ -445,7 +479,6 @@ RED.workspaces = (function() {
} }
} }
function removeWorkspace(ws) { function removeWorkspace(ws) {
if (!ws) { if (!ws) {
deleteWorkspace(RED.nodes.workspace(activeWorkspace)); deleteWorkspace(RED.nodes.workspace(activeWorkspace));
@ -474,7 +507,10 @@ RED.workspaces = (function() {
return { return {
init: init, init: init,
add: addWorkspace, add: addWorkspace,
// remove: remove workspace without editor history etc
remove: removeWorkspace, remove: removeWorkspace,
// delete: remove workspace and update editor history
delete: deleteWorkspace,
order: setWorkspaceOrder, order: setWorkspaceOrder,
edit: editWorkspace, edit: editWorkspace,
contains: function(id) { contains: function(id) {
@ -489,7 +525,18 @@ RED.workspaces = (function() {
selection: function() { selection: function() {
return workspace_tabs.selection(); return workspace_tabs.selection();
}, },
show: function(id,skipStack) { hide: function(id) {
if (!id) {
id = activeWorkspace;
}
if (workspace_tabs.contains(id)) {
workspace_tabs.hideTab(id);
var hiddenTabs = JSON.parse(RED.settings.getLocal("hiddenTabs")||"{}");
hiddenTabs[id] = true;
RED.settings.setLocal("hiddenTabs",JSON.stringify(hiddenTabs));
}
},
show: function(id,skipStack,unhideOnly) {
if (!workspace_tabs.contains(id)) { if (!workspace_tabs.contains(id)) {
var sf = RED.nodes.subflow(id); var sf = RED.nodes.subflow(id);
if (sf) { if (sf) {
@ -498,14 +545,22 @@ RED.workspaces = (function() {
null, null,
workspace_tabs.activeIndex()+1 workspace_tabs.activeIndex()+1
); );
removeFromHideStack(id);
} else { } else {
return; return;
} }
} }
if (unhideOnly) {
workspace_tabs.showTab(id);
} else {
if (!skipStack && activeWorkspace !== id) { if (!skipStack && activeWorkspace !== id) {
addToViewStack(activeWorkspace) addToViewStack(activeWorkspace)
} }
workspace_tabs.activateTab(id); workspace_tabs.activateTab(id);
}
var hiddenTabs = JSON.parse(RED.settings.getLocal("hiddenTabs")||"{}");
delete hiddenTabs[id];
RED.settings.setLocal("hiddenTabs",JSON.stringify(hiddenTabs));
}, },
refresh: function() { refresh: function() {
RED.nodes.eachWorkspace(function(ws) { RED.nodes.eachWorkspace(function(ws) {

View File

@ -21,10 +21,10 @@ RED.user = (function() {
opts = {}; opts = {};
} }
var dialog = $('<div id="node-dialog-login" class="hide">'+ var dialog = $('<div id="node-dialog-login" class="hide" style="display: flex; align-items: flex-end;">'+
'<div style="display: inline-block;width: 250px; vertical-align: top; margin-right: 10px; margin-bottom: 20px;"><img id="node-dialog-login-image" src=""/></div>'+ '<div style="width: 250px; flex-grow: 0;"><img id="node-dialog-login-image" src=""/></div>'+
'<div style="display: inline-block; width: 250px; vertical-align: bottom; margin-left: 10px; margin-bottom: 20px;">'+ '<div style="flex-grow: 1;">'+
'<form id="node-dialog-login-fields" class="form-horizontal" style="margin-bottom: 0px;"></form>'+ '<form id="node-dialog-login-fields" class="form-horizontal" style="margin-bottom: 0px; margin-left:20px;"></form>'+
'</div>'+ '</div>'+
'</div>'); '</div>');
@ -76,7 +76,7 @@ RED.user = (function() {
} }
row.appendTo("#node-dialog-login-fields"); row.appendTo("#node-dialog-login-fields");
} }
$('<div class="form-row" style="text-align: right; margin-top: 10px;"><span id="node-dialog-login-failed" style="line-height: 2em;float:left;" class="hide">'+RED._("user.loginFailed")+'</span><img src="red/images/spin.svg" style="height: 30px; margin-right: 10px; " class="login-spinner hide"/>'+ $('<div class="form-row" style="text-align: right; margin-top: 10px;"><span id="node-dialog-login-failed" style="line-height: 2em;float:left;color:var(--red-ui-text-color-error);" class="hide">'+RED._("user.loginFailed")+'</span><img src="red/images/spin.svg" style="height: 30px; margin-right: 10px; " class="login-spinner hide"/>'+
(opts.cancelable?'<a href="#" id="node-dialog-login-cancel" class="red-ui-button" style="margin-right: 20px;" tabIndex="'+(i+1)+'">'+RED._("common.label.cancel")+'</a>':'')+ (opts.cancelable?'<a href="#" id="node-dialog-login-cancel" class="red-ui-button" style="margin-right: 20px;" tabIndex="'+(i+1)+'">'+RED._("common.label.cancel")+'</a>':'')+
'<input type="submit" id="node-dialog-login-submit" class="red-ui-button" style="width: auto;" tabIndex="'+(i+2)+'" value="'+RED._("user.login")+'"></div>').appendTo("#node-dialog-login-fields"); '<input type="submit" id="node-dialog-login-submit" class="red-ui-button" style="width: auto;" tabIndex="'+(i+2)+'" value="'+RED._("user.login")+'"></div>').appendTo("#node-dialog-login-fields");
@ -121,6 +121,24 @@ RED.user = (function() {
i = 0; i = 0;
for (;i<data.prompts.length;i++) { for (;i<data.prompts.length;i++) {
var field = data.prompts[i]; var field = data.prompts[i];
var sessionMessage = /[?&]session_message=(.*?)(?:$|&)/.exec(window.location.search);
if (sessionMessage) {
RED.sessionMessages = RED.sessionMessages || [];
RED.sessionMessages.push(sessionMessage[1]);
if (history.pushState) {
var newurl = window.location.protocol+"//"+window.location.host+window.location.pathname
window.history.replaceState({ path: newurl }, "", newurl);
} else {
window.location.search = "";
}
}
if (RED.sessionMessages) {
var sessionMessages = $("<div/>",{class:"form-row",style:"text-align: center"}).appendTo("#node-dialog-login-fields");
RED.sessionMessages.forEach(function (msg) {
$('<div>').css("color","var(--red-ui-text-color-error)").text(msg).appendTo(sessionMessages);
});
delete RED.sessionMessages;
}
var row = $("<div/>",{class:"form-row",style:"text-align: center"}).appendTo("#node-dialog-login-fields"); var row = $("<div/>",{class:"form-row",style:"text-align: center"}).appendTo("#node-dialog-login-fields");
var loginButton = $('<a href="#" class="red-ui-button"></a>',{style: "padding: 10px"}).appendTo(row).on("click", function() { var loginButton = $('<a href="#" class="red-ui-button"></a>',{style: "padding: 10px"}).appendTo(row).on("click", function() {
@ -152,7 +170,7 @@ RED.user = (function() {
}); });
} }
var loginImageSrc = data.image || "red/images/node-red-256.png"; var loginImageSrc = data.image || "red/images/node-red-256.svg";
$("#node-dialog-login-image").load(function() { $("#node-dialog-login-image").load(function() {
dialog.dialog("open"); dialog.dialog("open");

View File

@ -140,8 +140,8 @@ $workspace-button-color-focus-outline: $form-input-focus-color;
$shade-color: rgba(160,160,160,0.5); $shade-color: rgba(160,160,160,0.5);
$popover-background: #333; $popover-background: #333;
$popover-border: $popover-background;
$popover-color: #eee; $popover-color: #eee;
$popover-button-border-color: #bbb; $popover-button-border-color: #bbb;
$popover-button-border-color-hover: #666; $popover-button-border-color-hover: #666;
@ -295,6 +295,9 @@ $group-default-stroke: #999;
$group-default-stroke-opacity: 1; $group-default-stroke-opacity: 1;
$group-default-label-color: #a4a4a4; $group-default-label-color: #a4a4a4;
$tourGuide-border: #c56c6c;
$tourGuide-heading-color: #c56c6c;
// Deprecated // Deprecated
$text-color-green: $text-color-success; $text-color-green: $text-color-success;
$info-text-code-color: $text-color-code; $info-text-code-color: $text-color-code;

View File

@ -43,12 +43,24 @@
border-bottom: 1px solid $secondary-border-color; border-bottom: 1px solid $secondary-border-color;
box-shadow: 0 2px 6px $shadow; box-shadow: 0 2px 6px $shadow;
} }
.red-ui-debug-filter-row { #red-ui-sidebar-debug-filter-node-list-row {
.red-ui-nodeList { .red-ui-treeList-label.disabled {
margin: 10px 0; font-style: italic;
} color: $secondary-text-color-disabled;
} }
.red-ui-treeList-label {
&.selected, &.selected .red-ui-treeList-sublabel-text {
background: inherit;
}
&.selected, &.selected .red-ui-treeList-sublabel-text {
background: inherit;
}
&.focus, &.focus .red-ui-treeList-sublabel-text {
background: $list-item-background-hover !important;
}
}
}
.red-ui-debug-msg { .red-ui-debug-msg {
position: relative; position: relative;
border-bottom: 1px solid $debug-message-border; border-bottom: 1px solid $debug-message-border;

View File

@ -19,7 +19,7 @@
font-size: $primary-font-size; font-size: $primary-font-size;
position: absolute; position: absolute;
top: 100%; top: 100%;
width: 200px; width: 230px;
left: 0; left: 0;
z-index: 1000; z-index: 1000;
display: none; display: none;
@ -46,7 +46,7 @@
& > li > a, & > li > a,
& > li > a:focus { & > li > a:focus {
display: block; display: block;
padding: 4px 0 4px 32px; padding: 4px 12px 4px 32px;
clear: both; clear: both;
font-weight: normal; font-weight: normal;
line-height: 20px; line-height: 20px;
@ -68,6 +68,10 @@
& > .disabled > a:hover, & > .disabled > a:hover,
& > .disabled > a:focus { & > .disabled > a:focus {
color: $menuDisabledColor; color: $menuDisabledColor;
.red-ui-popover-key {
color: $menuDisabledColor;
border-color: $menuDisabledColor;
}
} }
& > .disabled > a:hover, & > .disabled > a:hover,
@ -83,6 +87,7 @@
max-width: 14px; max-width: 14px;
} }
.fa { .fa {
float: left;
width: 20px; width: 20px;
margin-left: -25px; margin-left: -25px;
margin-top: 3px; margin-top: 3px;
@ -102,6 +107,20 @@
display: none; display: none;
} }
} }
.red-ui-menu-label {
display: flex;
& > :first-child {
flex-grow: 1
}
}
.red-ui-popover-key {
border: none;
padding: 0;
font-size: 13px;
// float: right;
color: $menuColor;
border-color: $menuColor;
}
} }
} }
@ -113,6 +132,7 @@
.red-ui-menu-dropdown > li > a:hover, .red-ui-menu-dropdown > li > a:hover,
.red-ui-menu-dropdown > li.open > a,
.red-ui-menu-dropdown > li > a:focus, .red-ui-menu-dropdown > li > a:focus,
.red-ui-menu-dropdown-submenu:hover > a, .red-ui-menu-dropdown-submenu:hover > a,
.red-ui-menu-dropdown-submenu:focus > a { .red-ui-menu-dropdown-submenu:focus > a {
@ -129,6 +149,7 @@
margin-top: -6px; margin-top: -6px;
margin-left: -1px; margin-left: -1px;
} }
&.open > .red-ui-menu-dropdown,
&:hover > .red-ui-menu-dropdown { &:hover > .red-ui-menu-dropdown {
display: block; display: block;
} }

View File

@ -191,14 +191,17 @@
margin-top: 0; margin-top: 0;
li a { li a {
color: $header-menu-color; color: $header-menu-color;
padding: 3px 40px; padding: 3px 10px 3px 40px;
img { img {
max-width: 100%; max-width: 100%;
margin-right: 10px; margin-right: 10px;
padding: 4px; padding: 4px;
border: 3px solid transparent; border: 3px solid transparent;
} }
.red-ui-popover-key {
color: $header-menu-color-disabled !important;
border-color: $header-menu-color-disabled !important;
}
&.active img { &.active img {
border: 3px solid $header-menu-item-border-active; border: 3px solid $header-menu-item-border-active;
} }
@ -211,7 +214,6 @@
} }
span.red-ui-menu-label { span.red-ui-menu-label {
font-size: 14px; font-size: 14px;
display: inline-block;
text-indent: 0px; text-indent: 0px;
} }
span.red-ui-menu-sublabel { span.red-ui-menu-sublabel {
@ -222,6 +224,7 @@
} }
} }
> li > a:hover, > li > a:hover,
> li.open > a,
> li > a:focus, > li > a:focus,
> li:hover > a, > li:hover > a,
> li:focus > a { > li:focus > a {

View File

@ -137,10 +137,10 @@
padding: 0; padding: 0;
border: 1px solid $form-input-border-color; border: 1px solid $form-input-border-color;
} }
.ui-spinner input { .ui-spinner input[type=text] {
background: $form-input-background; background: $form-input-background;
margin: 0 17px 0 0; margin: 0 17px 0 0;
padding: 6px; padding: 8px;
border: none; border: none;
border-top-right-radius: 0px; border-top-right-radius: 0px;
border-bottom-right-radius: 0px; border-bottom-right-radius: 0px;

View File

@ -19,19 +19,23 @@
display: none; display: none;
position: absolute; position: absolute;
width: auto; width: auto;
padding: 10px; padding: 2px;
height: auto; height: auto;
background: $popover-background; background: var(--red-ui-popover-border);
color: $popover-color; color: var(--red-ui-popover-color);
border-radius: 4px; border-radius: 4px;
z-index: 1000; z-index: 1000;
font-family: $primary-font; font-family: $primary-font;
font-size: 14px; font-size: 14px;
line-height: 1.4em; line-height: 1.4em;
@include component-shadow; @include component-shadow;
border-color: $popover-background; border-color: var(--red-ui-popover-border);
}
.red-ui-popover-content {
padding: 8px;
border-radius: 2px;
background: var(--red-ui-popover-background);
} }
.red-ui-popover:after, .red-ui-popover:before { .red-ui-popover:after, .red-ui-popover:before {
border: solid transparent; border: solid transparent;
content: " "; content: " ";
@ -61,26 +65,26 @@
.red-ui-popover.red-ui-popover-right:after { .red-ui-popover.red-ui-popover-right:after {
border-color: transparent; border-color: transparent;
border-right-color: $popover-background; border-right-color: var(--red-ui-popover-border);
border-width: 10px; border-width: 10px;
margin-top: -10px; margin-top: -10px;
} }
.red-ui-popover.red-ui-popover-right:before { .red-ui-popover.red-ui-popover-right:before {
border-color: transparent; border-color: transparent;
border-right-color: $popover-background; border-right-color: var(--red-ui-popover-border);
border-width: 11px; border-width: 11px;
margin-top: -11px; margin-top: -11px;
} }
.red-ui-popover.red-ui-popover-left:after { .red-ui-popover.red-ui-popover-left:after {
border-color: transparent; border-color: transparent;
border-left-color: $popover-background; border-left-color: var(--red-ui-popover-border);
border-width: 10px; border-width: 10px;
margin-top: -10px; margin-top: -10px;
} }
.red-ui-popover.red-ui-popover-left:before { .red-ui-popover.red-ui-popover-left:before {
border-color: transparent; border-color: transparent;
border-left-color: $popover-background; border-left-color: var(--red-ui-popover-border);
border-width: 11px; border-width: 11px;
margin-top: -11px; margin-top: -11px;
} }
@ -88,26 +92,26 @@
.red-ui-popover.red-ui-popover-bottom:after { .red-ui-popover.red-ui-popover-bottom:after {
border-color: transparent; border-color: transparent;
border-bottom-color: $popover-background; border-bottom-color: var(--red-ui-popover-border);
border-width: 10px; border-width: 10px;
margin-left: -10px; margin-left: -10px;
} }
.red-ui-popover.red-ui-popover-bottom:before { .red-ui-popover.red-ui-popover-bottom:before {
border-color: transparent; border-color: transparent;
border-bottom-color: $popover-background; border-bottom-color: var(--red-ui-popover-border);
border-width: 11px; border-width: 11px;
margin-left: -11px; margin-left: -11px;
} }
.red-ui-popover.red-ui-popover-top:after { .red-ui-popover.red-ui-popover-top:after {
border-color: transparent; border-color: transparent;
border-top-color: $popover-background; border-top-color: var(--red-ui-popover-border);
border-width: 10px; border-width: 10px;
margin-left: -10px; margin-left: -10px;
} }
.red-ui-popover.red-ui-popover-top:before { .red-ui-popover.red-ui-popover-top:before {
border-color: transparent; border-color: transparent;
border-top-color: $popover-background; border-top-color: var(--red-ui-popover-border);
border-width: 11px; border-width: 11px;
margin-left: -11px; margin-left: -11px;
} }
@ -116,9 +120,10 @@
.red-ui-popover-size-small { .red-ui-popover-size-small {
font-size: 12px; font-size: 12px;
padding: 5px 7px;
line-height: 1.8em; line-height: 1.8em;
.red-ui-popover-content {
padding: 1px 4px;
}
&.red-ui-popover-right:after, &.red-ui-popover-left:after { &.red-ui-popover-right:after, &.red-ui-popover-left:after {
border-width: 7px; border-width: 7px;
margin-top: -7px; margin-top: -7px;
@ -143,7 +148,7 @@
font-size: 11px; font-size: 11px;
font-family: $monospace-font; font-family: $monospace-font;
margin-left: 3px; margin-left: 3px;
border: 1px solid $popover-color; border: 1px solid var(--red-ui-popover-color);
border-radius:3px; border-radius:3px;
padding: 1px 2px; padding: 1px 2px;
} }
@ -152,8 +157,8 @@
.red-ui-popover button.red-ui-button { .red-ui-popover button.red-ui-button {
&:not(.primary) { &:not(.primary) {
border-color: $popover-button-border-color; border-color: $popover-button-border-color;
background: $popover-background; background: var(--red-ui-popover-background);
color: $popover-color !important; color: var(--red-ui-popover-color) !important;
} }
&:not(.primary):not(.disabled):not(.ui-button-disabled):hover { &:not(.primary):not(.disabled):not(.ui-button-disabled):hover {
border-color: $popover-button-border-color-hover; border-color: $popover-button-border-color-hover;

View File

@ -73,13 +73,13 @@
.red-ui-projects-dialog-screen-start { .red-ui-projects-dialog-screen-start {
.red-ui-projects-dialog-screen-start-hero { .red-ui-projects-dialog-screen-start-hero {
text-align: center; text-align: center;
font-size: 2em; font-size: 1.4em;
padding: 10px; padding: 10px;
min-height: 60px; min-height: 40px;
color: $primary-text-color; color: $primary-text-color;
} }
.red-ui-projects-dialog-screen-start-body { .red-ui-projects-dialog-screen-start-body {
min-height: 400px; min-height: 300px;
line-height: 1.6em; line-height: 1.6em;
p { p {
font-size: 1.1em; font-size: 1.1em;
@ -92,7 +92,7 @@
} }
button.red-ui-button.red-ui-projects-dialog-button { button.red-ui-button.red-ui-projects-dialog-button {
width: calc(50% - 80px); width: calc(50% - 80px);
margin: 20px; margin: 10px 20px;
height: auto; height: auto;
line-height: 2em; line-height: 2em;
padding: 10px; padding: 10px;

View File

@ -61,6 +61,7 @@
@import "ui/common/checkboxSet"; @import "ui/common/checkboxSet";
@import "ui/common/stack"; @import "ui/common/stack";
@import "ui/common/treeList"; @import "ui/common/treeList";
@import "ui/common/autoComplete";
@import "dragdrop"; @import "dragdrop";
@ -69,3 +70,5 @@
@import "debug"; @import "debug";
@import "radialMenu"; @import "radialMenu";
@import "tourGuide";

View File

@ -16,6 +16,7 @@
.red-ui-sidebar-info { .red-ui-sidebar-info {
height: 100%; height: 100%;
overflow: hidden;
} }
.red-ui-sidebar-info hr { .red-ui-sidebar-info hr {
margin: 10px 0; margin: 10px 0;
@ -212,6 +213,9 @@ div.red-ui-info-table {
border: none; border: none;
} }
} }
p {
display: inline;
}
} }
.red-ui-help-info-header { .red-ui-help-info-header {
i { i {
@ -230,7 +234,26 @@ div.red-ui-info-table {
} }
} }
} }
table {
border-collapse: collapse;
border: 1px solid var(--red-ui-secondary-border-color);
margin : 8px 0 8px 0;
min-width : 300px;
overflow : hidden;
}
table thead tr {
background-color: var(--red-ui-primary-background); //$primary-text-color;
border-bottom: 1px solid var(--red-ui-secondary-border-color);
color: var(--red-ui-header-text-color);
text-align: left;
}
table th,
table td {
padding: 6px 8px;
}
table tbody tr:nth-of-type(even) {
background-color: var(--red-ui-tertiary-background); //$primary-background;
}
} }
.red-ui-sidebar-info-stack { .red-ui-sidebar-info-stack {
height: 100%; height: 100%;
@ -411,16 +434,19 @@ div.red-ui-info-table {
} }
.red-ui-info-outline-item-controls { .red-ui-info-outline-item-controls {
position: absolute; position: absolute;
top:0; top:1px;
bottom: 0; bottom: 1px;
right: 0px; right: 1px;
padding: 2px 3px 0 1px; padding: 1px 2px 0 1px;
text-align: right; text-align: right;
background: $list-item-background; background: $list-item-background;
.red-ui-treeList-label:hover & { .red-ui-treeList-label:hover & {
background: $list-item-background-hover; background: $list-item-background-hover;
} }
.red-ui-treeList-label.focus & {
background: $list-item-background-hover;
}
.red-ui-treeList-label.selected & { .red-ui-treeList-label.selected & {
background: $list-item-background-selected; background: $list-item-background-selected;
} }
@ -435,6 +461,12 @@ div.red-ui-info-table {
border: none; border: none;
background: none; background: none;
} }
.fa-circle-thin {
display: none;
}
.fa-eye {
display: none;
}
} }
.red-ui-info-outline-item-control-reveal, .red-ui-info-outline-item-control-reveal,
.red-ui-info-outline-item-control-action { .red-ui-info-outline-item-control-action {
@ -446,7 +478,17 @@ div.red-ui-info-table {
display: inline-block; display: inline-block;
} }
} }
.fa-eye-slash {
display: none;
}
.red-ui-info-outline-item.red-ui-info-outline-item-hidden & {
.fa-eye-slash {
display: inline-block;
}
.fa-eye {
display: none;
}
}
.fa-ban { .fa-ban {
display: none; display: none;
} }

View File

@ -21,6 +21,9 @@
height: 35px; height: 35px;
box-sizing: border-box; box-sizing: border-box;
.hide-tab {
transition: width 0.1s ease-in;
}
.red-ui-tabs-scroll-container { .red-ui-tabs-scroll-container {
height: 60px; height: 60px;
overflow-x: scroll; overflow-x: scroll;
@ -142,13 +145,18 @@
padding-right: 21px; padding-right: 21px;
} }
&.red-ui-tabs-add { &.red-ui-tabs-add {
padding-right: 35px; padding-right: 29px;
} }
&.red-ui-tabs-add.red-ui-tabs-scrollable { &.red-ui-tabs-add.red-ui-tabs-scrollable {
padding-right: 59px; padding-right: 53px;
} }
&.red-ui-tabs-add.red-ui-tabs-menu.red-ui-tabs-scrollable,
&.red-ui-tabs-add.red-ui-tabs-search.red-ui-tabs-scrollable { &.red-ui-tabs-add.red-ui-tabs-search.red-ui-tabs-scrollable {
padding-right: 95px; padding-right: 83px;
}
&.red-ui-tabs-add.red-ui-tabs-search.red-ui-tabs-menu.red-ui-tabs-scrollable {
padding-right: 113px;
} }
&.red-ui-tabs-collapsible { &.red-ui-tabs-collapsible {
@ -232,13 +240,14 @@
a { a {
@include workspace-button; @include workspace-button;
line-height: 32px; line-height: 30px;
height: 32px; height: 28px;
width: 32px; width: 28px;
margin-left: 2px;
margin-right: 2px;
margin-top: 3px; margin-top: 3px;
margin-right:3px; margin-bottom: 3px;
margin-left:3px; border: none;
border: 1px solid $primary-border-color;
z-index: 2; z-index: 2;
} }
} }
@ -280,6 +289,8 @@
border-left: none; border-left: none;
border-right: none; border-right: none;
border-top: none; border-top: none;
border-bottom: 1px solid $primary-border-color;
line-height: 34px;
} }
} }
.red-ui-tab-scroll-left { .red-ui-tab-scroll-left {
@ -296,15 +307,30 @@
} }
.red-ui-tabs.red-ui-tabs-add .red-ui-tab-scroll-right { .red-ui-tabs.red-ui-tabs-add .red-ui-tab-scroll-right {
right: 38px; right: 32px;
} }
.red-ui-tabs.red-ui-tabs-add.red-ui-tabs-menu .red-ui-tab-scroll-right,
.red-ui-tabs.red-ui-tabs-add.red-ui-tabs-search .red-ui-tab-scroll-right { .red-ui-tabs.red-ui-tabs-add.red-ui-tabs-search .red-ui-tab-scroll-right {
right: 76px; right: 64px;
} }
.red-ui-tabs.red-ui-tabs-add.red-ui-tabs-menu .red-ui-tabs-add,
.red-ui-tabs.red-ui-tabs-add.red-ui-tabs-search .red-ui-tabs-add { .red-ui-tabs.red-ui-tabs-add.red-ui-tabs-search .red-ui-tabs-add {
right: 38px; right: 32px;
} }
.red-ui-tabs.red-ui-tabs-add.red-ui-tabs-search.red-ui-tabs-menu {
.red-ui-tab-scroll-right {
right: 96px;
}
.red-ui-tabs-add {
right: 64px;
}
.red-ui-tabs-search {
right: 32px;
}
}
.red-ui-tabs-fade { .red-ui-tabs-fade {
position: absolute; position: absolute;
bottom: 0; bottom: 0;

View File

@ -0,0 +1,118 @@
.red-ui-tourGuide-shade {
position: absolute;
top:0;
left:0;
bottom:0;
right:0;
z-index: 2000;
overflow: hidden;
}
.red-ui-tourGuide-shade-focus {
display: block;
width: 100px;
height: 100px;
position: absolute;
z-index: 2001;
transform: translate(-50%, -50%);
border-radius: 50%;
border: 2px solid var(--red-ui-tourGuide-border);
&.transition {
transition: 0.4s ease;
transition-property: width,height;
}
&::before {
content: '';
position: absolute;
width: 100%;
height: 100%;
border-radius: 50%;
border: solid 6000px var(--red-ui-shade-color);
margin-left: -6000px;
margin-top: -6000px;
pointer-events: none;
}
}
.red-ui-popover.red-ui-tourGuide-popover {
z-index: 2003;
--red-ui-popover-background: var(--red-ui-secondary-background);
--red-ui-popover-border: var(--red-ui-tourGuide-border);
--red-ui-popover-color: var(--red-ui-primary-text-color);
.red-ui-popover-content {
h2 {
text-align: center;
margin-top: 0px;
line-height: 1.2em;
color: var(--red-ui-tourGuide-heading-color);
i.fa {
font-size: 1.5em
}
}
}
}
.red-ui-tourGuide-toolbar {
min-height: 36px;
position: relative;
display: flex;
align-items: flex-end;
}
.red-ui-tourGuide-breadcrumbs {
flex-grow: 1;
display: flex;
align-items: center;
justify-content: center;
font-size: 6px;
& > div {
display: inline-block;
}
i {
line-height: 16px;
margin: 0 3px;
}
}
.red-ui-tourGuide-popover-description {
padding: 10px 20px 5px;
}
.red-ui-tourGuide-popover-full {
.red-ui-tourGuide-popover-description {
padding: 20px 40px 10px;
text-align: center;
}
}
.red-ui-popover.red-ui-tourGuide-popover button.red-ui-button {
&:not(.primary) {
background: var(--red-ui-secondary-background);
color: var(--red-ui-primary-text-color) !important;
}
&:not(.primary):not(.disabled):not(.ui-button-disabled):hover {
border-color: $popover-button-border-color-hover;
}
}
// .red-ui-tourGuide-popover-bounce {
// animation: 10s ease-in 5s infinite both red-ui-tourGuide-popover-bounce;
// }
// // @keyframes *must* be on multiple lines so build-custom-theme can filter them out
// @keyframes red-ui-tourGuide-popover-bounce {
// 0%,
// 10%,
// 100% {
// -webkit-transform: translateY(0);
// transform: translateY(0);
// }
// 2%,8% {
// -webkit-transform: translateY(-5px);
// transform: translateY(-5px);
// }
// 5% {
// -webkit-transform: translateY(5px);
// transform: translateY(5px);
// }
// }

View File

@ -0,0 +1,5 @@
.red-ui-autoComplete-container {
&.red-ui-popover-panel {
border-top: none;
}
}

View File

@ -89,18 +89,27 @@
color: $list-item-color; color: $list-item-color;
text-decoration: none; text-decoration: none;
} }
&.focus, &.focus .red-ui-treeList-sublabel-text {
background: $list-item-background-hover;
outline: 1px solid $form-input-focus-color !important;
outline-offset: -1px;
color: $list-item-color;
}
&.selected, &.selected .red-ui-treeList-sublabel-text { &.selected, &.selected .red-ui-treeList-sublabel-text {
background: $list-item-background-selected; background: $list-item-background-selected;
outline: none; outline: none;
color: $list-item-color; color: $list-item-color;
} }
input.red-ui-treeList-checkbox { input.red-ui-treeList-checkbox,
input.red-ui-treeList-radio {
margin: 0; margin: 0;
} }
} }
.red-ui-treeList-label-text { .red-ui-treeList-label-text {
margin-left: 4px; margin-left: 4px;
overflow: hidden;
text-overflow: ellipsis;
&:empty { &:empty {
min-height: 20px; min-height: 20px;
} }
@ -120,6 +129,7 @@
.red-ui-treeList-icon { .red-ui-treeList-icon {
display: inline-block; display: inline-block;
flex-shrink: 0;
width: 20px; width: 20px;
text-align: center; text-align: center;
} }

View File

@ -81,7 +81,8 @@
z-index: 2000; z-index: 2000;
a { a {
padding: 6px 18px 6px 6px; padding: 6px 18px 6px 6px;
display: block; display: flex;
align-items: center;
border-bottom: 1px solid $secondary-border-color; border-bottom: 1px solid $secondary-border-color;
color: $form-text-color; color: $form-text-color;
&:hover { &:hover {
@ -98,7 +99,7 @@
background: $workspace-button-background-active; background: $workspace-button-background-active;
} }
input[type="checkbox"] { input[type="checkbox"] {
margin-right: 6px; margin: 0 6px 0 0;
} }
} }
.red-ui-typedInput-icon { .red-ui-typedInput-icon {

View File

@ -81,12 +81,18 @@
--red-ui-node-status-changed-border: #{$node-status-changed-border}; --red-ui-node-status-changed-border: #{$node-status-changed-border};
--red-ui-node-status-changed-background: #{$node-status-changed-background}; --red-ui-node-status-changed-background: #{$node-status-changed-background};
--red-ui-node-border: #{$node-border}; --red-ui-node-border: #{$node-border};
--red-ui-node-port-background:#{$node-port-background}; --red-ui-node-port-background:#{$node-port-background};
--red-ui-node-label-color: #{$node-label-color}; --red-ui-node-label-color: #{$node-label-color};
--red-ui-node-selected-color: #{$node-selected-color}; --red-ui-node-selected-color: #{$node-selected-color};
--red-ui-port-selected-color: #{$port-selected-color}; --red-ui-port-selected-color: #{$port-selected-color};
--red-ui-popover-background: #{$popover-background};
--red-ui-popover-border: #{$popover-border};
--red-ui-popover-color: #{$popover-color};
--red-ui-tourGuide-border: #{$tourGuide-border};
--red-ui-tourGuide-heading-color: #{$tourGuide-heading-color};
} }

View File

@ -0,0 +1,80 @@
export default {
steps: [
{
title: "Create your first flow",
width: 400,
description: 'This tutorial will guide you through creating your first flow',
nextButton: 'start'
},
{
element: "#red-ui-workspace .red-ui-tab-button.red-ui-tabs-add",
description: 'To add a new tab, click the <i class="fa fa-plus"></i> button',
wait: {
type: "dom-event",
event: "click",
element: "#red-ui-workspace .red-ui-tab-button.red-ui-tabs-add a"
},
},
{
element: '.red-ui-palette-node[data-palette-type="inject"]',
direction: 'right',
description: 'The palette lists all of the nodes available to use. Drag a new Inject node into the workspace.',
fallback: 'inset-bottom-right',
wait: {
type: "nr-event",
event: "nodes:add",
filter: function(event) {
if (event.type === "inject") {
this.injectNode = event;
return true;
}
return false
}
},
complete: function() {
$('.red-ui-palette-node[data-palette-type="inject"]').css("z-index","auto");
}
},
{
element: '.red-ui-palette-node[data-palette-type="debug"]',
direction: 'right',
description: 'Next, drag a new Debug node into the workspace.',
fallback: 'inset-bottom-right',
wait: {
type: "nr-event",
event: "nodes:add",
filter: function(event) {
if (event.type === "debug") {
this.debugNode = event;
return true;
}
return false
}
},
complete: function() {
$('.red-ui-palette-node[data-palette-type="debug"]').css("z-index","auto");
},
},
{
element: function() { return $("#"+this.injectNode.id+" .red-ui-flow-port") },
description: 'Add a wire from the output of the Inject node to the input of the Debug node',
fallback: 'inset-bottom-right',
wait: {
type: "nr-event",
event: "links:add",
filter: function(event) {
return event.source.id === this.injectNode.id && event.target.id === this.debugNode.id;
}
},
},
{
element: "#red-ui-header-button-deploy",
description: 'Deploy your changes so the flow is active in the runtime',
width: 200,
wait: {
type: "dom-event",
event: "click"
},
}
]
}

View File

@ -0,0 +1,151 @@
export default {
version: "2.1.0",
steps: [
{
titleIcon: "fa fa-map-o",
title: { "en-US": "Welcome to Node-RED 2.1!" },
description: { "en-US": "Let's take a moment to discover the new features in this release." }
},
{
title: { "en-US": "A new Tour Guide" },
description: { "en-US": "<p>First, as you've already found, we now have this tour of new features. We'll only show the tour the first time you open the editor for each new version of Node-RED.</p>"+
"<p>You can choose not to see this tour in the future by disabling it under the View tab of User Settings.</p>" }
},
{
title: { "en-US": "New Edit menu" },
prepare() {
$("#red-ui-header-button-sidemenu").trigger("click");
$("#menu-item-edit-menu").parent().addClass("open")
},
complete() {
$("#menu-item-edit-menu").parent().removeClass("open")
},
element: "#menu-item-edit-menu-submenu",
interactive: false,
direction: "left",
description: { "en-US": "<p>The main menu has been updated with a new 'Edit' section. This includes all of the familar options, like cut/paste and undo/redo.</p>"+
"<p>The menu now displays keyboard shortcuts for the options.</p>" }
},
{
title: { "en-US": "Arranging nodes" },
prepare() {
$("#red-ui-header-button-sidemenu").trigger("click");
$("#menu-item-arrange-menu").parent().addClass("open")
},
complete() {
$("#menu-item-arrange-menu").parent().removeClass("open")
},
element: "#menu-item-arrange-menu-submenu",
interactive: false,
direction: "left",
description: { "en-US": "<p>The new 'Arrange' section of the menu provides new options to help arrange your nodes. You can align them to a common edge, spread them out evenly or change their order.</p>" },
},
{
title: { "en-US": "Hiding tabs" },
element: "#red-ui-workspace-tabs > li.active",
description: { "en-US": '<p>Tabs can now be hidden by clicking their <i class="fa fa-times"></i> icon.</p><p>The Info Sidebar will still list all of your tabs, and tell you which ones are currently hidden.' },
interactive: false,
prepare() {
$("#red-ui-workspace-tabs > li.active .red-ui-tab-close").css("display","block");
},
complete() {
$("#red-ui-workspace-tabs > li.active .red-ui-tab-close").css("display","");
}
},
{
title: { "en-US": "Tab menu" },
element: "#red-ui-workspace-tabs-menu",
description: { "en-US": '<p>The new tab menu also provides lots of new options for your tabs.</p>' },
interactive: false,
direction: "left",
prepare() {
$("#red-ui-workspace > .red-ui-tabs > .red-ui-tabs-menu a").trigger("click");
},
complete() {
$(document).trigger("click");
}
},
{
title: { "en-US": "Flow and Group level environment variables" },
element: "#red-ui-workspace-tabs > li.active",
interactive: false,
description: { "en-US": "<p>Flows and Groups can now have their own environment variables that can be referenced by nodes inside them.</p>" },
},
{
prepare(done) {
RED.editor.editFlow(RED.nodes.workspace(RED.workspaces.active()),"editor-tab-envProperties");
setTimeout(done,700);
},
element: "#red-ui-tab-editor-tab-envProperties-link-button",
description: { "en-US": "<p>Their edit dialogs have a new Environment Variables section.</p>" },
},
{
element: ".node-input-env-container-row",
direction: "left",
description: { "en-US": '<p>The environment variables are listed in this table and new ones can be added by clicking the <i class="fa fa-plus"></i> button.</p>' },
complete(done) {
$("#node-dialog-cancel").trigger("click");
setTimeout(done,500);
}
},
{
title: {"en-US":"Link Call node added"},
prepare(done) {
this.paletteWasClosed = $("#red-ui-main-container").hasClass("red-ui-palette-closed");
RED.actions.invoke("core:toggle-palette",true)
$('[data-palette-type="link call"]')[0].scrollIntoView({block:"center"})
setTimeout(done,100);
},
element: '[data-palette-type="link call"]',
direction: "right",
description: { "en-US": '<p>The <code>Link Call</code> node lets you call another flow that begins with a <code>Link In</code> node and get the result back when the message reaches a <code>Link Out</code> node.</p>' },
},
{
title: {"en-US":"MQTT nodes support dynamic connections"},
prepare(done) {
$('[data-palette-type="mqtt out"]')[0].scrollIntoView({block:"center"})
setTimeout(done,100);
},
element: '[data-palette-type="mqtt out"]',
direction: "right",
description: { "en-US": '<p>The <code>MQTT</code> nodes now support creating their connections and subscriptions dynamically.</p>' },
},
{
title: {"en-US":"File nodes renamed"},
prepare(done) {
$('[data-palette-type="file"]')[0].scrollIntoView({block:"center"})
setTimeout(done,100);
},
complete() {
if (this.paletteWasClosed) {
RED.actions.invoke("core:toggle-palette",false)
}
},
element: '[data-palette-type="file"]',
direction: "right",
description: { "en-US": '<p>The file nodes have been renamed to make it clearer which node does what.</p>' },
},
{
title: {"en-US":"Deep copy option on Change node"},
prepare(done) {
var def = RED.nodes.getType('change')
RED.editor.edit({id:"test",type:"change",rules:[{t:'set',p:'payload',pt:'msg', tot:'msg',to:"anotherProperty"}],_def:def, _:def._})
setTimeout(done,700);
},
complete(done) {
$("#node-dialog-cancel").trigger("click");
setTimeout(done,500);
},
element: function() {
return $(".node-input-rule-property-deepCopy").next()
},
description: { "en-US": '<p>The Set rule has a new option to create a deep copy of the value. This ensures a complete copy is made, rather than using a reference.</p>' },
},
{
title: { "en-US": "And that's not all..." },
description: { "en-US": "<p>There are many more smaller changes, including:</p><ul><li>Auto-complete suggestions in the <code>msg</code> TypedInput.</li><li>Support for <code>msg.resetTimeout</code> in the <code>Join</code> node.</li><li>Pushing messages to the front of the queue in the <code>Delay</code> node's rate limiting mode.</li><li>An optional second output on the <code>Delay</code> node for rate limited messages.</li></ul>" }
}
]
}

View File

@ -1,5 +1,5 @@
/* NOTE: Do not edit directly! This file is generated using \`npm run update-types\` in https://github.com/Steve-Mcl/monaco-editor-esm-i18n */ /* NOTE: Do not edit directly! This file is generated using `npm run update-types` in https://github.com/node-red/nr-monaco-build */
interface NodeMessage { interface NodeMessage {

View File

@ -1,5 +1,5 @@
/* NOTE: Do not edit directly! This file is generated using \`npm run update-types\` in https://github.com/Steve-Mcl/monaco-editor-esm-i18n */ /* NOTE: Do not edit directly! This file is generated using `npm run update-types` in https://github.com/node-red/nr-monaco-build */
/* /*

View File

@ -0,0 +1,127 @@
/* NOTE: Do not edit directly! This file is generated using `npm run update-types` in https://github.com/node-red/nr-monaco-build */
declare module 'assert' {
/** An alias of `assert.ok()`. */
function assert(value: any, message?: string | Error): asserts value;
namespace assert {
class AssertionError extends Error {
actual: any;
expected: any;
operator: string;
generatedMessage: boolean;
code: 'ERR_ASSERTION';
constructor(options?: {
/** If provided, the error message is set to this value. */
message?: string | undefined;
/** The `actual` property on the error instance. */
actual?: any;
/** The `expected` property on the error instance. */
expected?: any;
/** The `operator` property on the error instance. */
operator?: string | undefined;
/** If provided, the generated stack trace omits frames before this function. */
// tslint:disable-next-line:ban-types
stackStartFn?: Function | undefined;
});
}
class CallTracker {
calls(exact?: number): () => void;
calls<Func extends (...args: any[]) => any>(fn?: Func, exact?: number): Func;
report(): CallTrackerReportInformation[];
verify(): void;
}
interface CallTrackerReportInformation {
message: string;
/** The actual number of times the function was called. */
actual: number;
/** The number of times the function was expected to be called. */
expected: number;
/** The name of the function that is wrapped. */
operator: string;
/** A stack trace of the function. */
stack: object;
}
type AssertPredicate = RegExp | (new () => object) | ((thrown: any) => boolean) | object | Error;
function fail(message?: string | Error): never;
/** @deprecated since v10.0.0 - use fail([message]) or other assert functions instead. */
function fail(
actual: any,
expected: any,
message?: string | Error,
operator?: string,
// tslint:disable-next-line:ban-types
stackStartFn?: Function,
): never;
function ok(value: any, message?: string | Error): asserts value;
/** @deprecated since v9.9.0 - use strictEqual() instead. */
function equal(actual: any, expected: any, message?: string | Error): void;
/** @deprecated since v9.9.0 - use notStrictEqual() instead. */
function notEqual(actual: any, expected: any, message?: string | Error): void;
/** @deprecated since v9.9.0 - use deepStrictEqual() instead. */
function deepEqual(actual: any, expected: any, message?: string | Error): void;
/** @deprecated since v9.9.0 - use notDeepStrictEqual() instead. */
function notDeepEqual(actual: any, expected: any, message?: string | Error): void;
function strictEqual<T>(actual: any, expected: T, message?: string | Error): asserts actual is T;
function notStrictEqual(actual: any, expected: any, message?: string | Error): void;
function deepStrictEqual<T>(actual: any, expected: T, message?: string | Error): asserts actual is T;
function notDeepStrictEqual(actual: any, expected: any, message?: string | Error): void;
function throws(block: () => any, message?: string | Error): void;
function throws(block: () => any, error: AssertPredicate, message?: string | Error): void;
function doesNotThrow(block: () => any, message?: string | Error): void;
function doesNotThrow(block: () => any, error: AssertPredicate, message?: string | Error): void;
function ifError(value: any): asserts value is null | undefined;
function rejects(block: (() => Promise<any>) | Promise<any>, message?: string | Error): Promise<void>;
function rejects(
block: (() => Promise<any>) | Promise<any>,
error: AssertPredicate,
message?: string | Error,
): Promise<void>;
function doesNotReject(block: (() => Promise<any>) | Promise<any>, message?: string | Error): Promise<void>;
function doesNotReject(
block: (() => Promise<any>) | Promise<any>,
error: AssertPredicate,
message?: string | Error,
): Promise<void>;
function match(value: string, regExp: RegExp, message?: string | Error): void;
function doesNotMatch(value: string, regExp: RegExp, message?: string | Error): void;
const strict: Omit<
typeof assert,
| 'equal'
| 'notEqual'
| 'deepEqual'
| 'notDeepEqual'
| 'ok'
| 'strictEqual'
| 'deepStrictEqual'
| 'ifError'
| 'strict'
> & {
(value: any, message?: string | Error): asserts value;
equal: typeof strictEqual;
notEqual: typeof notStrictEqual;
deepEqual: typeof deepStrictEqual;
notDeepEqual: typeof notDeepStrictEqual;
// Mapped types and assertion functions are incompatible?
// TS2775: Assertions require every name in the call target
// to be declared with an explicit type annotation.
ok: typeof ok;
strictEqual: typeof strictEqual;
deepStrictEqual: typeof deepStrictEqual;
ifError: typeof ifError;
strict: typeof strict;
};
}
export = assert;
}

View File

@ -0,0 +1,229 @@
/* NOTE: Do not edit directly! This file is generated using `npm run update-types` in https://github.com/node-red/nr-monaco-build */
/**
* Async Hooks module: https://nodejs.org/api/async_hooks.html
*/
declare module 'async_hooks' {
/**
* Returns the asyncId of the current execution context.
*/
function executionAsyncId(): number;
/**
* The resource representing the current execution.
* Useful to store data within the resource.
*
* Resource objects returned by `executionAsyncResource()` are most often internal
* Node.js handle objects with undocumented APIs. Using any functions or properties
* on the object is likely to crash your application and should be avoided.
*
* Using `executionAsyncResource()` in the top-level execution context will
* return an empty object as there is no handle or request object to use,
* but having an object representing the top-level can be helpful.
*/
function executionAsyncResource(): object;
/**
* Returns the ID of the resource responsible for calling the callback that is currently being executed.
*/
function triggerAsyncId(): number;
interface HookCallbacks {
/**
* Called when a class is constructed that has the possibility to emit an asynchronous event.
* @param asyncId a unique ID for the async resource
* @param type the type of the async resource
* @param triggerAsyncId the unique ID of the async resource in whose execution context this async resource was created
* @param resource reference to the resource representing the async operation, needs to be released during destroy
*/
init?(asyncId: number, type: string, triggerAsyncId: number, resource: object): void;
/**
* When an asynchronous operation is initiated or completes a callback is called to notify the user.
* The before callback is called just before said callback is executed.
* @param asyncId the unique identifier assigned to the resource about to execute the callback.
*/
before?(asyncId: number): void;
/**
* Called immediately after the callback specified in before is completed.
* @param asyncId the unique identifier assigned to the resource which has executed the callback.
*/
after?(asyncId: number): void;
/**
* Called when a promise has resolve() called. This may not be in the same execution id
* as the promise itself.
* @param asyncId the unique id for the promise that was resolve()d.
*/
promiseResolve?(asyncId: number): void;
/**
* Called after the resource corresponding to asyncId is destroyed
* @param asyncId a unique ID for the async resource
*/
destroy?(asyncId: number): void;
}
interface AsyncHook {
/**
* Enable the callbacks for a given AsyncHook instance. If no callbacks are provided enabling is a noop.
*/
enable(): this;
/**
* Disable the callbacks for a given AsyncHook instance from the global pool of AsyncHook callbacks to be executed. Once a hook has been disabled it will not be called again until enabled.
*/
disable(): this;
}
/**
* Registers functions to be called for different lifetime events of each async operation.
* @param options the callbacks to register
* @return an AsyncHooks instance used for disabling and enabling hooks
*/
function createHook(options: HookCallbacks): AsyncHook;
interface AsyncResourceOptions {
/**
* The ID of the execution context that created this async event.
* @default executionAsyncId()
*/
triggerAsyncId?: number | undefined;
/**
* Disables automatic `emitDestroy` when the object is garbage collected.
* This usually does not need to be set (even if `emitDestroy` is called
* manually), unless the resource's `asyncId` is retrieved and the
* sensitive API's `emitDestroy` is called with it.
* @default false
*/
requireManualDestroy?: boolean | undefined;
}
/**
* The class AsyncResource was designed to be extended by the embedder's async resources.
* Using this users can easily trigger the lifetime events of their own resources.
*/
class AsyncResource {
/**
* AsyncResource() is meant to be extended. Instantiating a
* new AsyncResource() also triggers init. If triggerAsyncId is omitted then
* async_hook.executionAsyncId() is used.
* @param type The type of async event.
* @param triggerAsyncId The ID of the execution context that created
* this async event (default: `executionAsyncId()`), or an
* AsyncResourceOptions object (since 9.3)
*/
constructor(type: string, triggerAsyncId?: number|AsyncResourceOptions);
/**
* Binds the given function to the current execution context.
* @param fn The function to bind to the current execution context.
* @param type An optional name to associate with the underlying `AsyncResource`.
*/
static bind<Func extends (...args: any[]) => any>(fn: Func, type?: string): Func & { asyncResource: AsyncResource };
/**
* Binds the given function to execute to this `AsyncResource`'s scope.
* @param fn The function to bind to the current `AsyncResource`.
*/
bind<Func extends (...args: any[]) => any>(fn: Func): Func & { asyncResource: AsyncResource };
/**
* Call the provided function with the provided arguments in the
* execution context of the async resource. This will establish the
* context, trigger the AsyncHooks before callbacks, call the function,
* trigger the AsyncHooks after callbacks, and then restore the original
* execution context.
* @param fn The function to call in the execution context of this
* async resource.
* @param thisArg The receiver to be used for the function call.
* @param args Optional arguments to pass to the function.
*/
runInAsyncScope<This, Result>(fn: (this: This, ...args: any[]) => Result, thisArg?: This, ...args: any[]): Result;
/**
* Call AsyncHooks destroy callbacks.
*/
emitDestroy(): this;
/**
* @return the unique ID assigned to this AsyncResource instance.
*/
asyncId(): number;
/**
* @return the trigger ID for this AsyncResource instance.
*/
triggerAsyncId(): number;
}
/**
* When having multiple instances of `AsyncLocalStorage`, they are independent
* from each other. It is safe to instantiate this class multiple times.
*/
class AsyncLocalStorage<T> {
/**
* This method disables the instance of `AsyncLocalStorage`. All subsequent calls
* to `asyncLocalStorage.getStore()` will return `undefined` until
* `asyncLocalStorage.run()` is called again.
*
* When calling `asyncLocalStorage.disable()`, all current contexts linked to the
* instance will be exited.
*
* Calling `asyncLocalStorage.disable()` is required before the
* `asyncLocalStorage` can be garbage collected. This does not apply to stores
* provided by the `asyncLocalStorage`, as those objects are garbage collected
* along with the corresponding async resources.
*
* This method is to be used when the `asyncLocalStorage` is not in use anymore
* in the current process.
*/
disable(): void;
/**
* This method returns the current store. If this method is called outside of an
* asynchronous context initialized by calling `asyncLocalStorage.run`, it will
* return `undefined`.
*/
getStore(): T | undefined;
/**
* This methods runs a function synchronously within a context and return its
* return value. The store is not accessible outside of the callback function or
* the asynchronous operations created within the callback.
*
* Optionally, arguments can be passed to the function. They will be passed to the
* callback function.
*
* I the callback function throws an error, it will be thrown by `run` too. The
* stacktrace will not be impacted by this call and the context will be exited.
*/
// TODO: Apply generic vararg once available
run<R>(store: T, callback: (...args: any[]) => R, ...args: any[]): R;
/**
* This methods runs a function synchronously outside of a context and return its
* return value. The store is not accessible within the callback function or the
* asynchronous operations created within the callback.
*
* Optionally, arguments can be passed to the function. They will be passed to the
* callback function.
*
* If the callback function throws an error, it will be thrown by `exit` too. The
* stacktrace will not be impacted by this call and the context will be
* re-entered.
*/
// TODO: Apply generic vararg once available
exit<R>(callback: (...args: any[]) => R, ...args: any[]): R;
/**
* Calling `asyncLocalStorage.enterWith(store)` will transition into the context
* for the remainder of the current synchronous execution and will persist
* through any following asynchronous calls.
*/
enterWith(store: T): void;
}
}

View File

@ -1 +1,25 @@
declare module'node:buffer'{export*from'buffer';}declare module'buffer'{export const INSPECT_MAX_BYTES:number;export const kMaxLength:number;export const kStringMaxLength:number;export const constants:{MAX_LENGTH:number;MAX_STRING_LENGTH:number;};const BuffType:typeof Buffer;export type TranscodeEncoding="ascii"|"utf8"|"utf16le"|"ucs2"|"latin1"|"binary";export function transcode(source:Uint8Array,fromEnc:TranscodeEncoding,toEnc:TranscodeEncoding):Buffer;export const SlowBuffer:{new(size:number):Buffer;prototype:Buffer;};export{BuffType as Buffer};}
/* NOTE: Do not edit directly! This file is generated using `npm run update-types` in https://github.com/node-red/nr-monaco-build */
declare module 'buffer' {
export const INSPECT_MAX_BYTES: number;
export const kMaxLength: number;
export const kStringMaxLength: number;
export const constants: {
MAX_LENGTH: number;
MAX_STRING_LENGTH: number;
};
const BuffType: typeof Buffer;
export type TranscodeEncoding = "ascii" | "utf8" | "utf16le" | "ucs2" | "latin1" | "binary";
export function transcode(source: Uint8Array, fromEnc: TranscodeEncoding, toEnc: TranscodeEncoding): Buffer;
export const SlowBuffer: {
/** @deprecated since v6.0.0, use `Buffer.allocUnsafeSlow()` */
new(size: number): Buffer;
prototype: Buffer;
};
export { BuffType as Buffer };
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,265 @@
/* NOTE: Do not edit directly! This file is generated using `npm run update-types` in https://github.com/node-red/nr-monaco-build */
declare module 'cluster' {
import * as child from 'child_process';
import EventEmitter = require('events');
import * as net from 'net';
// interfaces
interface ClusterSettings {
execArgv?: string[] | undefined; // default: process.execArgv
exec?: string | undefined;
args?: string[] | undefined;
silent?: boolean | undefined;
stdio?: any[] | undefined;
uid?: number | undefined;
gid?: number | undefined;
inspectPort?: number | (() => number) | undefined;
}
interface Address {
address: string;
port: number;
addressType: number | "udp4" | "udp6"; // 4, 6, -1, "udp4", "udp6"
}
class Worker extends EventEmitter {
id: number;
process: child.ChildProcess;
send(message: child.Serializable, sendHandle?: child.SendHandle, callback?: (error: Error | null) => void): boolean;
kill(signal?: string): void;
destroy(signal?: string): void;
disconnect(): void;
isConnected(): boolean;
isDead(): boolean;
exitedAfterDisconnect: boolean;
/**
* events.EventEmitter
* 1. disconnect
* 2. error
* 3. exit
* 4. listening
* 5. message
* 6. online
*/
addListener(event: string, listener: (...args: any[]) => void): this;
addListener(event: "disconnect", listener: () => void): this;
addListener(event: "error", listener: (error: Error) => void): this;
addListener(event: "exit", listener: (code: number, signal: string) => void): this;
addListener(event: "listening", listener: (address: Address) => void): this;
addListener(event: "message", listener: (message: any, handle: net.Socket | net.Server) => void): this; // the handle is a net.Socket or net.Server object, or undefined.
addListener(event: "online", listener: () => void): this;
emit(event: string | symbol, ...args: any[]): boolean;
emit(event: "disconnect"): boolean;
emit(event: "error", error: Error): boolean;
emit(event: "exit", code: number, signal: string): boolean;
emit(event: "listening", address: Address): boolean;
emit(event: "message", message: any, handle: net.Socket | net.Server): boolean;
emit(event: "online"): boolean;
on(event: string, listener: (...args: any[]) => void): this;
on(event: "disconnect", listener: () => void): this;
on(event: "error", listener: (error: Error) => void): this;
on(event: "exit", listener: (code: number, signal: string) => void): this;
on(event: "listening", listener: (address: Address) => void): this;
on(event: "message", listener: (message: any, handle: net.Socket | net.Server) => void): this; // the handle is a net.Socket or net.Server object, or undefined.
on(event: "online", listener: () => void): this;
once(event: string, listener: (...args: any[]) => void): this;
once(event: "disconnect", listener: () => void): this;
once(event: "error", listener: (error: Error) => void): this;
once(event: "exit", listener: (code: number, signal: string) => void): this;
once(event: "listening", listener: (address: Address) => void): this;
once(event: "message", listener: (message: any, handle: net.Socket | net.Server) => void): this; // the handle is a net.Socket or net.Server object, or undefined.
once(event: "online", listener: () => void): this;
prependListener(event: string, listener: (...args: any[]) => void): this;
prependListener(event: "disconnect", listener: () => void): this;
prependListener(event: "error", listener: (error: Error) => void): this;
prependListener(event: "exit", listener: (code: number, signal: string) => void): this;
prependListener(event: "listening", listener: (address: Address) => void): this;
prependListener(event: "message", listener: (message: any, handle: net.Socket | net.Server) => void): this; // the handle is a net.Socket or net.Server object, or undefined.
prependListener(event: "online", listener: () => void): this;
prependOnceListener(event: string, listener: (...args: any[]) => void): this;
prependOnceListener(event: "disconnect", listener: () => void): this;
prependOnceListener(event: "error", listener: (error: Error) => void): this;
prependOnceListener(event: "exit", listener: (code: number, signal: string) => void): this;
prependOnceListener(event: "listening", listener: (address: Address) => void): this;
prependOnceListener(event: "message", listener: (message: any, handle: net.Socket | net.Server) => void): this; // the handle is a net.Socket or net.Server object, or undefined.
prependOnceListener(event: "online", listener: () => void): this;
}
interface Cluster extends EventEmitter {
Worker: Worker;
disconnect(callback?: () => void): void;
fork(env?: any): Worker;
isMaster: boolean;
isWorker: boolean;
schedulingPolicy: number;
settings: ClusterSettings;
setupMaster(settings?: ClusterSettings): void;
worker?: Worker | undefined;
workers?: NodeJS.Dict<Worker> | undefined;
readonly SCHED_NONE: number;
readonly SCHED_RR: number;
/**
* events.EventEmitter
* 1. disconnect
* 2. exit
* 3. fork
* 4. listening
* 5. message
* 6. online
* 7. setup
*/
addListener(event: string, listener: (...args: any[]) => void): this;
addListener(event: "disconnect", listener: (worker: Worker) => void): this;
addListener(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): this;
addListener(event: "fork", listener: (worker: Worker) => void): this;
addListener(event: "listening", listener: (worker: Worker, address: Address) => void): this;
addListener(event: "message", listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void): this; // the handle is a net.Socket or net.Server object, or undefined.
addListener(event: "online", listener: (worker: Worker) => void): this;
addListener(event: "setup", listener: (settings: ClusterSettings) => void): this;
emit(event: string | symbol, ...args: any[]): boolean;
emit(event: "disconnect", worker: Worker): boolean;
emit(event: "exit", worker: Worker, code: number, signal: string): boolean;
emit(event: "fork", worker: Worker): boolean;
emit(event: "listening", worker: Worker, address: Address): boolean;
emit(event: "message", worker: Worker, message: any, handle: net.Socket | net.Server): boolean;
emit(event: "online", worker: Worker): boolean;
emit(event: "setup", settings: ClusterSettings): boolean;
on(event: string, listener: (...args: any[]) => void): this;
on(event: "disconnect", listener: (worker: Worker) => void): this;
on(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): this;
on(event: "fork", listener: (worker: Worker) => void): this;
on(event: "listening", listener: (worker: Worker, address: Address) => void): this;
on(event: "message", listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void): this; // the handle is a net.Socket or net.Server object, or undefined.
on(event: "online", listener: (worker: Worker) => void): this;
on(event: "setup", listener: (settings: ClusterSettings) => void): this;
once(event: string, listener: (...args: any[]) => void): this;
once(event: "disconnect", listener: (worker: Worker) => void): this;
once(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): this;
once(event: "fork", listener: (worker: Worker) => void): this;
once(event: "listening", listener: (worker: Worker, address: Address) => void): this;
once(event: "message", listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void): this; // the handle is a net.Socket or net.Server object, or undefined.
once(event: "online", listener: (worker: Worker) => void): this;
once(event: "setup", listener: (settings: ClusterSettings) => void): this;
prependListener(event: string, listener: (...args: any[]) => void): this;
prependListener(event: "disconnect", listener: (worker: Worker) => void): this;
prependListener(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): this;
prependListener(event: "fork", listener: (worker: Worker) => void): this;
prependListener(event: "listening", listener: (worker: Worker, address: Address) => void): this;
prependListener(event: "message", listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void): this; // the handle is a net.Socket or net.Server object, or undefined.
prependListener(event: "online", listener: (worker: Worker) => void): this;
prependListener(event: "setup", listener: (settings: ClusterSettings) => void): this;
prependOnceListener(event: string, listener: (...args: any[]) => void): this;
prependOnceListener(event: "disconnect", listener: (worker: Worker) => void): this;
prependOnceListener(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): this;
prependOnceListener(event: "fork", listener: (worker: Worker) => void): this;
prependOnceListener(event: "listening", listener: (worker: Worker, address: Address) => void): this;
// the handle is a net.Socket or net.Server object, or undefined.
prependOnceListener(event: "message", listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void): this;
prependOnceListener(event: "online", listener: (worker: Worker) => void): this;
prependOnceListener(event: "setup", listener: (settings: ClusterSettings) => void): this;
}
const SCHED_NONE: number;
const SCHED_RR: number;
function disconnect(callback?: () => void): void;
function fork(env?: any): Worker;
const isMaster: boolean;
const isWorker: boolean;
let schedulingPolicy: number;
const settings: ClusterSettings;
function setupMaster(settings?: ClusterSettings): void;
const worker: Worker;
const workers: NodeJS.Dict<Worker>;
/**
* events.EventEmitter
* 1. disconnect
* 2. exit
* 3. fork
* 4. listening
* 5. message
* 6. online
* 7. setup
*/
function addListener(event: string, listener: (...args: any[]) => void): Cluster;
function addListener(event: "disconnect", listener: (worker: Worker) => void): Cluster;
function addListener(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): Cluster;
function addListener(event: "fork", listener: (worker: Worker) => void): Cluster;
function addListener(event: "listening", listener: (worker: Worker, address: Address) => void): Cluster;
// the handle is a net.Socket or net.Server object, or undefined.
function addListener(event: "message", listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void): Cluster;
function addListener(event: "online", listener: (worker: Worker) => void): Cluster;
function addListener(event: "setup", listener: (settings: ClusterSettings) => void): Cluster;
function emit(event: string | symbol, ...args: any[]): boolean;
function emit(event: "disconnect", worker: Worker): boolean;
function emit(event: "exit", worker: Worker, code: number, signal: string): boolean;
function emit(event: "fork", worker: Worker): boolean;
function emit(event: "listening", worker: Worker, address: Address): boolean;
function emit(event: "message", worker: Worker, message: any, handle: net.Socket | net.Server): boolean;
function emit(event: "online", worker: Worker): boolean;
function emit(event: "setup", settings: ClusterSettings): boolean;
function on(event: string, listener: (...args: any[]) => void): Cluster;
function on(event: "disconnect", listener: (worker: Worker) => void): Cluster;
function on(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): Cluster;
function on(event: "fork", listener: (worker: Worker) => void): Cluster;
function on(event: "listening", listener: (worker: Worker, address: Address) => void): Cluster;
function on(event: "message", listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void): Cluster; // the handle is a net.Socket or net.Server object, or undefined.
function on(event: "online", listener: (worker: Worker) => void): Cluster;
function on(event: "setup", listener: (settings: ClusterSettings) => void): Cluster;
function once(event: string, listener: (...args: any[]) => void): Cluster;
function once(event: "disconnect", listener: (worker: Worker) => void): Cluster;
function once(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): Cluster;
function once(event: "fork", listener: (worker: Worker) => void): Cluster;
function once(event: "listening", listener: (worker: Worker, address: Address) => void): Cluster;
function once(event: "message", listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void): Cluster; // the handle is a net.Socket or net.Server object, or undefined.
function once(event: "online", listener: (worker: Worker) => void): Cluster;
function once(event: "setup", listener: (settings: ClusterSettings) => void): Cluster;
function removeListener(event: string, listener: (...args: any[]) => void): Cluster;
function removeAllListeners(event?: string): Cluster;
function setMaxListeners(n: number): Cluster;
function getMaxListeners(): number;
function listeners(event: string): Function[];
function listenerCount(type: string): number;
function prependListener(event: string, listener: (...args: any[]) => void): Cluster;
function prependListener(event: "disconnect", listener: (worker: Worker) => void): Cluster;
function prependListener(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): Cluster;
function prependListener(event: "fork", listener: (worker: Worker) => void): Cluster;
function prependListener(event: "listening", listener: (worker: Worker, address: Address) => void): Cluster;
// the handle is a net.Socket or net.Server object, or undefined.
function prependListener(event: "message", listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void): Cluster;
function prependListener(event: "online", listener: (worker: Worker) => void): Cluster;
function prependListener(event: "setup", listener: (settings: ClusterSettings) => void): Cluster;
function prependOnceListener(event: string, listener: (...args: any[]) => void): Cluster;
function prependOnceListener(event: "disconnect", listener: (worker: Worker) => void): Cluster;
function prependOnceListener(event: "exit", listener: (worker: Worker, code: number, signal: string) => void): Cluster;
function prependOnceListener(event: "fork", listener: (worker: Worker) => void): Cluster;
function prependOnceListener(event: "listening", listener: (worker: Worker, address: Address) => void): Cluster;
// the handle is a net.Socket or net.Server object, or undefined.
function prependOnceListener(event: "message", listener: (worker: Worker, message: any, handle: net.Socket | net.Server) => void): Cluster;
function prependOnceListener(event: "online", listener: (worker: Worker) => void): Cluster;
function prependOnceListener(event: "setup", listener: (settings: ClusterSettings) => void): Cluster;
function eventNames(): string[];
}

View File

@ -1 +1,136 @@
declare module'node:console'{export=console;}declare module'console'{import{InspectOptions}from'node:util';global{interface Console{Console:NodeJS.ConsoleConstructor;assert(value:any,message?:string,...optionalParams:any[]):void;clear():void;count(label?:string):void;countReset(label?:string):void;debug(message?:any,...optionalParams:any[]):void;dir(obj:any,options?:InspectOptions):void;dirxml(...data:any[]):void;error(message?:any,...optionalParams:any[]):void;group(...label:any[]):void;groupCollapsed(...label:any[]):void;groupEnd():void;info(message?:any,...optionalParams:any[]):void;log(message?:any,...optionalParams:any[]):void;table(tabularData:any,properties?:ReadonlyArray<string>):void;time(label?:string):void;timeEnd(label?:string):void;timeLog(label?:string,...data:any[]):void;trace(message?:any,...optionalParams:any[]):void;warn(message?:any,...optionalParams:any[]):void;profile(label?:string):void;profileEnd(label?:string):void;timeStamp(label?:string):void;}var console:Console;namespace NodeJS{interface ConsoleConstructorOptions{stdout:WritableStream;stderr?:WritableStream;ignoreErrors?:boolean;colorMode?:boolean|'auto';inspectOptions?:InspectOptions;}interface ConsoleConstructor{prototype:Console;new(stdout:WritableStream,stderr?:WritableStream,ignoreErrors?:boolean):Console;new(options:ConsoleConstructorOptions):Console;}interface Global{console:typeof console;}}}export=console;}
/* NOTE: Do not edit directly! This file is generated using `npm run update-types` in https://github.com/node-red/nr-monaco-build */
declare module 'console' {
import { InspectOptions } from 'util';
global {
// This needs to be global to avoid TS2403 in case lib.dom.d.ts is present in the same build
interface Console {
Console: NodeJS.ConsoleConstructor;
/**
* A simple assertion test that verifies whether `value` is truthy.
* If it is not, an `AssertionError` is thrown.
* If provided, the error `message` is formatted using `util.format()` and used as the error message.
*/
assert(value: any, message?: string, ...optionalParams: any[]): void;
/**
* When `stdout` is a TTY, calling `console.clear()` will attempt to clear the TTY.
* When `stdout` is not a TTY, this method does nothing.
*/
clear(): void;
/**
* Maintains an internal counter specific to `label` and outputs to `stdout` the number of times `console.count()` has been called with the given `label`.
*/
count(label?: string): void;
/**
* Resets the internal counter specific to `label`.
*/
countReset(label?: string): void;
/**
* The `console.debug()` function is an alias for {@link console.log}.
*/
debug(message?: any, ...optionalParams: any[]): void;
/**
* Uses {@link util.inspect} on `obj` and prints the resulting string to `stdout`.
* This function bypasses any custom `inspect()` function defined on `obj`.
*/
dir(obj: any, options?: InspectOptions): void;
/**
* This method calls {@link console.log} passing it the arguments received. Please note that this method does not produce any XML formatting
*/
dirxml(...data: any[]): void;
/**
* Prints to `stderr` with newline.
*/
error(message?: any, ...optionalParams: any[]): void;
/**
* Increases indentation of subsequent lines by two spaces.
* If one or more `label`s are provided, those are printed first without the additional indentation.
*/
group(...label: any[]): void;
/**
* The `console.groupCollapsed()` function is an alias for {@link console.group}.
*/
groupCollapsed(...label: any[]): void;
/**
* Decreases indentation of subsequent lines by two spaces.
*/
groupEnd(): void;
/**
* The {@link console.info} function is an alias for {@link console.log}.
*/
info(message?: any, ...optionalParams: any[]): void;
/**
* Prints to `stdout` with newline.
*/
log(message?: any, ...optionalParams: any[]): void;
/**
* This method does not display anything unless used in the inspector.
* Prints to `stdout` the array `array` formatted as a table.
*/
table(tabularData: any, properties?: ReadonlyArray<string>): void;
/**
* Starts a timer that can be used to compute the duration of an operation. Timers are identified by a unique `label`.
*/
time(label?: string): void;
/**
* Stops a timer that was previously started by calling {@link console.time} and prints the result to `stdout`.
*/
timeEnd(label?: string): void;
/**
* For a timer that was previously started by calling {@link console.time}, prints the elapsed time and other `data` arguments to `stdout`.
*/
timeLog(label?: string, ...data: any[]): void;
/**
* Prints to `stderr` the string 'Trace :', followed by the {@link util.format} formatted message and stack trace to the current position in the code.
*/
trace(message?: any, ...optionalParams: any[]): void;
/**
* The {@link console.warn} function is an alias for {@link console.error}.
*/
warn(message?: any, ...optionalParams: any[]): void;
// --- Inspector mode only ---
/**
* This method does not display anything unless used in the inspector.
* Starts a JavaScript CPU profile with an optional label.
*/
profile(label?: string): void;
/**
* This method does not display anything unless used in the inspector.
* Stops the current JavaScript CPU profiling session if one has been started and prints the report to the Profiles panel of the inspector.
*/
profileEnd(label?: string): void;
/**
* This method does not display anything unless used in the inspector.
* Adds an event with the label `label` to the Timeline panel of the inspector.
*/
timeStamp(label?: string): void;
}
var console: Console;
namespace NodeJS {
interface ConsoleConstructorOptions {
stdout: WritableStream;
stderr?: WritableStream | undefined;
ignoreErrors?: boolean | undefined;
colorMode?: boolean | 'auto' | undefined;
inspectOptions?: InspectOptions | undefined;
}
interface ConsoleConstructor {
prototype: Console;
new(stdout: WritableStream, stderr?: WritableStream, ignoreErrors?: boolean): Console;
new(options: ConsoleConstructorOptions): Console;
}
interface Global {
console: typeof console;
}
}
}
export = console;
}

File diff suppressed because one or more lines are too long

View File

@ -1 +1,144 @@
declare module'node:dgram'{export*from'dgram';}declare module'dgram'{import{AddressInfo}from'node:net';import*as dns from'node:dns';import EventEmitter=require('node:events');interface RemoteInfo{address:string;family:'IPv4'|'IPv6';port:number;size:number;}interface BindOptions{port?:number;address?:string;exclusive?:boolean;fd?:number;}type SocketType="udp4"|"udp6";interface SocketOptions{type:SocketType;reuseAddr?:boolean;ipv6Only?:boolean;recvBufferSize?:number;sendBufferSize?:number;lookup?:(hostname:string,options:dns.LookupOneOptions,callback:(err:NodeJS.ErrnoException|null,address:string,family:number)=>void)=>void;}function createSocket(type:SocketType,callback?:(msg:Buffer,rinfo:RemoteInfo)=>void):Socket;function createSocket(options:SocketOptions,callback?:(msg:Buffer,rinfo:RemoteInfo)=>void):Socket;class Socket extends EventEmitter{addMembership(multicastAddress:string,multicastInterface?:string):void;address():AddressInfo;bind(port?:number,address?:string,callback?:()=>void):void;bind(port?:number,callback?:()=>void):void;bind(callback?:()=>void):void;bind(options:BindOptions,callback?:()=>void):void;close(callback?:()=>void):void;connect(port:number,address?:string,callback?:()=>void):void;connect(port:number,callback:()=>void):void;disconnect():void;dropMembership(multicastAddress:string,multicastInterface?:string):void;getRecvBufferSize():number;getSendBufferSize():number;ref():this;remoteAddress():AddressInfo;send(msg:string|Uint8Array|ReadonlyArray<any>,port?:number,address?:string,callback?:(error:Error|null,bytes:number)=>void):void;send(msg:string|Uint8Array|ReadonlyArray<any>,port?:number,callback?:(error:Error|null,bytes:number)=>void):void;send(msg:string|Uint8Array|ReadonlyArray<any>,callback?:(error:Error|null,bytes:number)=>void):void;send(msg:string|Uint8Array,offset:number,length:number,port?:number,address?:string,callback?:(error:Error|null,bytes:number)=>void):void;send(msg:string|Uint8Array,offset:number,length:number,port?:number,callback?:(error:Error|null,bytes:number)=>void):void;send(msg:string|Uint8Array,offset:number,length:number,callback?:(error:Error|null,bytes:number)=>void):void;setBroadcast(flag:boolean):void;setMulticastInterface(multicastInterface:string):void;setMulticastLoopback(flag:boolean):void;setMulticastTTL(ttl:number):void;setRecvBufferSize(size:number):void;setSendBufferSize(size:number):void;setTTL(ttl:number):void;unref():this;addSourceSpecificMembership(sourceAddress:string,groupAddress:string,multicastInterface?:string):void;dropSourceSpecificMembership(sourceAddress:string,groupAddress:string,multicastInterface?:string):void;addListener(event:string,listener:(...args:any[])=>void):this;addListener(event:"close",listener:()=>void):this;addListener(event:"connect",listener:()=>void):this;addListener(event:"error",listener:(err:Error)=>void):this;addListener(event:"listening",listener:()=>void):this;addListener(event:"message",listener:(msg:Buffer,rinfo:RemoteInfo)=>void):this;emit(event:string|symbol,...args:any[]):boolean;emit(event:"close"):boolean;emit(event:"connect"):boolean;emit(event:"error",err:Error):boolean;emit(event:"listening"):boolean;emit(event:"message",msg:Buffer,rinfo:RemoteInfo):boolean;on(event:string,listener:(...args:any[])=>void):this;on(event:"close",listener:()=>void):this;on(event:"connect",listener:()=>void):this;on(event:"error",listener:(err:Error)=>void):this;on(event:"listening",listener:()=>void):this;on(event:"message",listener:(msg:Buffer,rinfo:RemoteInfo)=>void):this;once(event:string,listener:(...args:any[])=>void):this;once(event:"close",listener:()=>void):this;once(event:"connect",listener:()=>void):this;once(event:"error",listener:(err:Error)=>void):this;once(event:"listening",listener:()=>void):this;once(event:"message",listener:(msg:Buffer,rinfo:RemoteInfo)=>void):this;prependListener(event:string,listener:(...args:any[])=>void):this;prependListener(event:"close",listener:()=>void):this;prependListener(event:"connect",listener:()=>void):this;prependListener(event:"error",listener:(err:Error)=>void):this;prependListener(event:"listening",listener:()=>void):this;prependListener(event:"message",listener:(msg:Buffer,rinfo:RemoteInfo)=>void):this;prependOnceListener(event:string,listener:(...args:any[])=>void):this;prependOnceListener(event:"close",listener:()=>void):this;prependOnceListener(event:"connect",listener:()=>void):this;prependOnceListener(event:"error",listener:(err:Error)=>void):this;prependOnceListener(event:"listening",listener:()=>void):this;prependOnceListener(event:"message",listener:(msg:Buffer,rinfo:RemoteInfo)=>void):this;}}
/* NOTE: Do not edit directly! This file is generated using `npm run update-types` in https://github.com/node-red/nr-monaco-build */
declare module 'dgram' {
import { AddressInfo } from 'net';
import * as dns from 'dns';
import EventEmitter = require('events');
interface RemoteInfo {
address: string;
family: 'IPv4' | 'IPv6';
port: number;
size: number;
}
interface BindOptions {
port?: number | undefined;
address?: string | undefined;
exclusive?: boolean | undefined;
fd?: number | undefined;
}
type SocketType = "udp4" | "udp6";
interface SocketOptions {
type: SocketType;
reuseAddr?: boolean | undefined;
/**
* @default false
*/
ipv6Only?: boolean | undefined;
recvBufferSize?: number | undefined;
sendBufferSize?: number | undefined;
lookup?: ((hostname: string, options: dns.LookupOneOptions, callback: (err: NodeJS.ErrnoException | null, address: string, family: number) => void) => void) | undefined;
}
function createSocket(type: SocketType, callback?: (msg: Buffer, rinfo: RemoteInfo) => void): Socket;
function createSocket(options: SocketOptions, callback?: (msg: Buffer, rinfo: RemoteInfo) => void): Socket;
class Socket extends EventEmitter {
addMembership(multicastAddress: string, multicastInterface?: string): void;
address(): AddressInfo;
bind(port?: number, address?: string, callback?: () => void): void;
bind(port?: number, callback?: () => void): void;
bind(callback?: () => void): void;
bind(options: BindOptions, callback?: () => void): void;
close(callback?: () => void): void;
connect(port: number, address?: string, callback?: () => void): void;
connect(port: number, callback: () => void): void;
disconnect(): void;
dropMembership(multicastAddress: string, multicastInterface?: string): void;
getRecvBufferSize(): number;
getSendBufferSize(): number;
ref(): this;
remoteAddress(): AddressInfo;
send(msg: string | Uint8Array | ReadonlyArray<any>, port?: number, address?: string, callback?: (error: Error | null, bytes: number) => void): void;
send(msg: string | Uint8Array | ReadonlyArray<any>, port?: number, callback?: (error: Error | null, bytes: number) => void): void;
send(msg: string | Uint8Array | ReadonlyArray<any>, callback?: (error: Error | null, bytes: number) => void): void;
send(msg: string | Uint8Array, offset: number, length: number, port?: number, address?: string, callback?: (error: Error | null, bytes: number) => void): void;
send(msg: string | Uint8Array, offset: number, length: number, port?: number, callback?: (error: Error | null, bytes: number) => void): void;
send(msg: string | Uint8Array, offset: number, length: number, callback?: (error: Error | null, bytes: number) => void): void;
setBroadcast(flag: boolean): void;
setMulticastInterface(multicastInterface: string): void;
setMulticastLoopback(flag: boolean): void;
setMulticastTTL(ttl: number): void;
setRecvBufferSize(size: number): void;
setSendBufferSize(size: number): void;
setTTL(ttl: number): void;
unref(): this;
/**
* Tells the kernel to join a source-specific multicast channel at the given
* `sourceAddress` and `groupAddress`, using the `multicastInterface` with the
* `IP_ADD_SOURCE_MEMBERSHIP` socket option.
* If the `multicastInterface` argument
* is not specified, the operating system will choose one interface and will add
* membership to it.
* To add membership to every available interface, call
* `socket.addSourceSpecificMembership()` multiple times, once per interface.
*/
addSourceSpecificMembership(sourceAddress: string, groupAddress: string, multicastInterface?: string): void;
/**
* Instructs the kernel to leave a source-specific multicast channel at the given
* `sourceAddress` and `groupAddress` using the `IP_DROP_SOURCE_MEMBERSHIP`
* socket option. This method is automatically called by the kernel when the
* socket is closed or the process terminates, so most apps will never have
* reason to call this.
*
* If `multicastInterface` is not specified, the operating system will attempt to
* drop membership on all valid interfaces.
*/
dropSourceSpecificMembership(sourceAddress: string, groupAddress: string, multicastInterface?: string): void;
/**
* events.EventEmitter
* 1. close
* 2. connect
* 3. error
* 4. listening
* 5. message
*/
addListener(event: string, listener: (...args: any[]) => void): this;
addListener(event: "close", listener: () => void): this;
addListener(event: "connect", listener: () => void): this;
addListener(event: "error", listener: (err: Error) => void): this;
addListener(event: "listening", listener: () => void): this;
addListener(event: "message", listener: (msg: Buffer, rinfo: RemoteInfo) => void): this;
emit(event: string | symbol, ...args: any[]): boolean;
emit(event: "close"): boolean;
emit(event: "connect"): boolean;
emit(event: "error", err: Error): boolean;
emit(event: "listening"): boolean;
emit(event: "message", msg: Buffer, rinfo: RemoteInfo): boolean;
on(event: string, listener: (...args: any[]) => void): this;
on(event: "close", listener: () => void): this;
on(event: "connect", listener: () => void): this;
on(event: "error", listener: (err: Error) => void): this;
on(event: "listening", listener: () => void): this;
on(event: "message", listener: (msg: Buffer, rinfo: RemoteInfo) => void): this;
once(event: string, listener: (...args: any[]) => void): this;
once(event: "close", listener: () => void): this;
once(event: "connect", listener: () => void): this;
once(event: "error", listener: (err: Error) => void): this;
once(event: "listening", listener: () => void): this;
once(event: "message", listener: (msg: Buffer, rinfo: RemoteInfo) => void): this;
prependListener(event: string, listener: (...args: any[]) => void): this;
prependListener(event: "close", listener: () => void): this;
prependListener(event: "connect", listener: () => void): this;
prependListener(event: "error", listener: (err: Error) => void): this;
prependListener(event: "listening", listener: () => void): this;
prependListener(event: "message", listener: (msg: Buffer, rinfo: RemoteInfo) => void): this;
prependOnceListener(event: string, listener: (...args: any[]) => void): this;
prependOnceListener(event: "close", listener: () => void): this;
prependOnceListener(event: "connect", listener: () => void): this;
prependOnceListener(event: "error", listener: (err: Error) => void): this;
prependOnceListener(event: "listening", listener: () => void): this;
prependOnceListener(event: "message", listener: (msg: Buffer, rinfo: RemoteInfo) => void): this;
}
}

File diff suppressed because one or more lines are too long

View File

@ -1 +1,27 @@
declare module'node:domain'{export*from'domain';}declare module'domain'{import EventEmitter=require('node:events');global{namespace NodeJS{interface Domain extends EventEmitter{run<T>(fn:(...args:any[])=>T,...args:any[]):T;add(emitter:EventEmitter|Timer):void;remove(emitter:EventEmitter|Timer):void;bind<T extends Function>(cb:T):T;intercept<T extends Function>(cb:T):T;}}}interface Domain extends NodeJS.Domain{}class Domain extends EventEmitter{members:Array<EventEmitter|NodeJS.Timer>;enter():void;exit():void;}function create():Domain;}
/* NOTE: Do not edit directly! This file is generated using `npm run update-types` in https://github.com/node-red/nr-monaco-build */
declare module 'domain' {
import EventEmitter = require('events');
global {
namespace NodeJS {
interface Domain extends EventEmitter {
run<T>(fn: (...args: any[]) => T, ...args: any[]): T;
add(emitter: EventEmitter | Timer): void;
remove(emitter: EventEmitter | Timer): void;
bind<T extends Function>(cb: T): T;
intercept<T extends Function>(cb: T): T;
}
}
}
interface Domain extends NodeJS.Domain {}
class Domain extends EventEmitter {
members: Array<EventEmitter | NodeJS.Timer>;
enter(): void;
exit(): void;
}
function create(): Domain;
}

View File

@ -1 +1,81 @@
declare module'node:events'{import EventEmitter=require('events');export=EventEmitter;}declare module'events'{interface EventEmitterOptions{captureRejections?:boolean;}interface NodeEventTarget{once(event:string|symbol,listener:(...args:any[])=>void):this;}interface DOMEventTarget{addEventListener(event:string,listener:(...args:any[])=>void,opts?:{once:boolean}):any;}interface EventEmitter extends NodeJS.EventEmitter{}class EventEmitter{constructor(options?:EventEmitterOptions);static once(emitter:NodeEventTarget,event:string|symbol):Promise<any[]>;static once(emitter:DOMEventTarget,event:string):Promise<any[]>;static on(emitter:NodeJS.EventEmitter,event:string):AsyncIterableIterator<any>;static listenerCount(emitter:NodeJS.EventEmitter,event:string|symbol):number;static readonly errorMonitor:unique symbol;static readonly captureRejectionSymbol:unique symbol;static captureRejections:boolean;static defaultMaxListeners:number;}import internal=require('events');namespace EventEmitter{export{internal as EventEmitter};}global{namespace NodeJS{interface EventEmitter{addListener(event:string|symbol,listener:(...args:any[])=>void):this;on(event:string|symbol,listener:(...args:any[])=>void):this;once(event:string|symbol,listener:(...args:any[])=>void):this;removeListener(event:string|symbol,listener:(...args:any[])=>void):this;off(event:string|symbol,listener:(...args:any[])=>void):this;removeAllListeners(event?:string|symbol):this;setMaxListeners(n:number):this;getMaxListeners():number;listeners(event:string|symbol):Function[];rawListeners(event:string|symbol):Function[];emit(event:string|symbol,...args:any[]):boolean;listenerCount(event:string|symbol):number;prependListener(event:string|symbol,listener:(...args:any[])=>void):this;prependOnceListener(event:string|symbol,listener:(...args:any[])=>void):this;eventNames():Array<string|symbol>;}}}export=EventEmitter;}
/* NOTE: Do not edit directly! This file is generated using `npm run update-types` in https://github.com/node-red/nr-monaco-build */
declare module 'events' {
interface EventEmitterOptions {
/**
* Enables automatic capturing of promise rejection.
*/
captureRejections?: boolean | undefined;
}
interface NodeEventTarget {
once(event: string | symbol, listener: (...args: any[]) => void): this;
}
interface DOMEventTarget {
addEventListener(event: string, listener: (...args: any[]) => void, opts?: { once: boolean }): any;
}
interface EventEmitter extends NodeJS.EventEmitter {}
class EventEmitter {
constructor(options?: EventEmitterOptions);
static once(emitter: NodeEventTarget, event: string | symbol): Promise<any[]>;
static once(emitter: DOMEventTarget, event: string): Promise<any[]>;
static on(emitter: NodeJS.EventEmitter, event: string): AsyncIterableIterator<any>;
/** @deprecated since v4.0.0 */
static listenerCount(emitter: NodeJS.EventEmitter, event: string | symbol): number;
/**
* This symbol shall be used to install a listener for only monitoring `'error'`
* events. Listeners installed using this symbol are called before the regular
* `'error'` listeners are called.
*
* Installing a listener using this symbol does not change the behavior once an
* `'error'` event is emitted, therefore the process will still crash if no
* regular `'error'` listener is installed.
*/
static readonly errorMonitor: unique symbol;
static readonly captureRejectionSymbol: unique symbol;
/**
* Sets or gets the default captureRejection value for all emitters.
*/
// TODO: These should be described using static getter/setter pairs:
static captureRejections: boolean;
static defaultMaxListeners: number;
}
import internal = require('events');
namespace EventEmitter {
// Should just be `export { EventEmitter }`, but that doesn't work in TypeScript 3.4
export { internal as EventEmitter };
}
global {
namespace NodeJS {
interface EventEmitter {
addListener(event: string | symbol, listener: (...args: any[]) => void): this;
on(event: string | symbol, listener: (...args: any[]) => void): this;
once(event: string | symbol, listener: (...args: any[]) => void): this;
removeListener(event: string | symbol, listener: (...args: any[]) => void): this;
off(event: string | symbol, listener: (...args: any[]) => void): this;
removeAllListeners(event?: string | symbol): this;
setMaxListeners(n: number): this;
getMaxListeners(): number;
listeners(event: string | symbol): Function[];
rawListeners(event: string | symbol): Function[];
emit(event: string | symbol, ...args: any[]): boolean;
listenerCount(event: string | symbol): number;
// Added in Node 6...
prependListener(event: string | symbol, listener: (...args: any[]) => void): this;
prependOnceListener(event: string | symbol, listener: (...args: any[]) => void): this;
eventNames(): Array<string | symbol>;
}
}
}
export = EventEmitter;
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,568 @@
/* NOTE: Do not edit directly! This file is generated using `npm run update-types` in https://github.com/node-red/nr-monaco-build */
declare module 'fs/promises' {
import {
Stats,
BigIntStats,
StatOptions,
WriteVResult,
ReadVResult,
PathLike,
RmDirOptions,
RmOptions,
MakeDirectoryOptions,
Dirent,
OpenDirOptions,
Dir,
BaseEncodingOptions,
BufferEncodingOption,
OpenMode,
Mode,
} from 'fs';
interface FileHandle {
/**
* Gets the file descriptor for this file handle.
*/
readonly fd: number;
/**
* Asynchronously append data to a file, creating the file if it does not exist. The underlying file will _not_ be closed automatically.
* The `FileHandle` must have been opened for appending.
* @param data The data to write. If something other than a `Buffer` or `Uint8Array` is provided, the value is coerced to a string.
* @param options Either the encoding for the file, or an object optionally specifying the encoding, file mode, and flag.
* If `encoding` is not supplied, the default of `'utf8'` is used.
* If `mode` is not supplied, the default of `0o666` is used.
* If `mode` is a string, it is parsed as an octal integer.
* If `flag` is not supplied, the default of `'a'` is used.
*/
appendFile(data: string | Uint8Array, options?: BaseEncodingOptions & { mode?: Mode | undefined, flag?: OpenMode | undefined } | BufferEncoding | null): Promise<void>;
/**
* Asynchronous fchown(2) - Change ownership of a file.
*/
chown(uid: number, gid: number): Promise<void>;
/**
* Asynchronous fchmod(2) - Change permissions of a file.
* @param mode A file mode. If a string is passed, it is parsed as an octal integer.
*/
chmod(mode: Mode): Promise<void>;
/**
* Asynchronous fdatasync(2) - synchronize a file's in-core state with storage device.
*/
datasync(): Promise<void>;
/**
* Asynchronous fsync(2) - synchronize a file's in-core state with the underlying storage device.
*/
sync(): Promise<void>;
/**
* Asynchronously reads data from the file.
* The `FileHandle` must have been opened for reading.
* @param buffer The buffer that the data will be written to.
* @param offset The offset in the buffer at which to start writing.
* @param length The number of bytes to read.
* @param position The offset from the beginning of the file from which data should be read. If `null`, data will be read from the current position.
*/
read<TBuffer extends Uint8Array>(buffer: TBuffer, offset?: number | null, length?: number | null, position?: number | null): Promise<{ bytesRead: number, buffer: TBuffer }>;
/**
* Asynchronously reads the entire contents of a file. The underlying file will _not_ be closed automatically.
* The `FileHandle` must have been opened for reading.
* @param options An object that may contain an optional flag.
* If a flag is not provided, it defaults to `'r'`.
*/
readFile(options?: { encoding?: null | undefined, flag?: OpenMode | undefined } | null): Promise<Buffer>;
/**
* Asynchronously reads the entire contents of a file. The underlying file will _not_ be closed automatically.
* The `FileHandle` must have been opened for reading.
* @param options An object that may contain an optional flag.
* If a flag is not provided, it defaults to `'r'`.
*/
readFile(options: { encoding: BufferEncoding, flag?: OpenMode | undefined } | BufferEncoding): Promise<string>;
/**
* Asynchronously reads the entire contents of a file. The underlying file will _not_ be closed automatically.
* The `FileHandle` must have been opened for reading.
* @param options An object that may contain an optional flag.
* If a flag is not provided, it defaults to `'r'`.
*/
readFile(options?: BaseEncodingOptions & { flag?: OpenMode | undefined } | BufferEncoding | null): Promise<string | Buffer>;
/**
* Asynchronous fstat(2) - Get file status.
*/
stat(opts?: StatOptions & { bigint?: false | undefined }): Promise<Stats>;
stat(opts: StatOptions & { bigint: true }): Promise<BigIntStats>;
stat(opts?: StatOptions): Promise<Stats | BigIntStats>;
/**
* Asynchronous ftruncate(2) - Truncate a file to a specified length.
* @param len If not specified, defaults to `0`.
*/
truncate(len?: number): Promise<void>;
/**
* Asynchronously change file timestamps of the file.
* @param atime The last access time. If a string is provided, it will be coerced to number.
* @param mtime The last modified time. If a string is provided, it will be coerced to number.
*/
utimes(atime: string | number | Date, mtime: string | number | Date): Promise<void>;
/**
* Asynchronously writes `buffer` to the file.
* The `FileHandle` must have been opened for writing.
* @param buffer The buffer that the data will be written to.
* @param offset The part of the buffer to be written. If not supplied, defaults to `0`.
* @param length The number of bytes to write. If not supplied, defaults to `buffer.length - offset`.
* @param position The offset from the beginning of the file where this data should be written. If not supplied, defaults to the current position.
*/
write<TBuffer extends Uint8Array>(buffer: TBuffer, offset?: number | null, length?: number | null, position?: number | null): Promise<{ bytesWritten: number, buffer: TBuffer }>;
/**
* Asynchronously writes `string` to the file.
* The `FileHandle` must have been opened for writing.
* It is unsafe to call `write()` multiple times on the same file without waiting for the `Promise`
* to be resolved (or rejected). For this scenario, `fs.createWriteStream` is strongly recommended.
* @param string A string to write.
* @param position The offset from the beginning of the file where this data should be written. If not supplied, defaults to the current position.
* @param encoding The expected string encoding.
*/
write(data: string | Uint8Array, position?: number | null, encoding?: BufferEncoding | null): Promise<{ bytesWritten: number, buffer: string }>;
/**
* Asynchronously writes data to a file, replacing the file if it already exists. The underlying file will _not_ be closed automatically.
* The `FileHandle` must have been opened for writing.
* It is unsafe to call `writeFile()` multiple times on the same file without waiting for the `Promise` to be resolved (or rejected).
* @param data The data to write. If something other than a `Buffer` or `Uint8Array` is provided, the value is coerced to a string.
* @param options Either the encoding for the file, or an object optionally specifying the encoding, file mode, and flag.
* If `encoding` is not supplied, the default of `'utf8'` is used.
* If `mode` is not supplied, the default of `0o666` is used.
* If `mode` is a string, it is parsed as an octal integer.
* If `flag` is not supplied, the default of `'w'` is used.
*/
writeFile(data: string | Uint8Array, options?: BaseEncodingOptions & { mode?: Mode | undefined, flag?: OpenMode | undefined } | BufferEncoding | null): Promise<void>;
/**
* See `fs.writev` promisified version.
*/
writev(buffers: ReadonlyArray<NodeJS.ArrayBufferView>, position?: number): Promise<WriteVResult>;
/**
* See `fs.readv` promisified version.
*/
readv(buffers: ReadonlyArray<NodeJS.ArrayBufferView>, position?: number): Promise<ReadVResult>;
/**
* Asynchronous close(2) - close a `FileHandle`.
*/
close(): Promise<void>;
}
/**
* Asynchronously tests a user's permissions for the file specified by path.
* @param path A path to a file or directory. If a URL is provided, it must use the `file:` protocol.
* URL support is _experimental_.
*/
function access(path: PathLike, mode?: number): Promise<void>;
/**
* Asynchronously copies `src` to `dest`. By default, `dest` is overwritten if it already exists.
* Node.js makes no guarantees about the atomicity of the copy operation.
* If an error occurs after the destination file has been opened for writing, Node.js will attempt
* to remove the destination.
* @param src A path to the source file.
* @param dest A path to the destination file.
* @param flags An optional integer that specifies the behavior of the copy operation. The only
* supported flag is `fs.constants.COPYFILE_EXCL`, which causes the copy operation to fail if
* `dest` already exists.
*/
function copyFile(src: PathLike, dest: PathLike, flags?: number): Promise<void>;
/**
* Asynchronous open(2) - open and possibly create a file.
* @param path A path to a file. If a URL is provided, it must use the `file:` protocol.
* @param mode A file mode. If a string is passed, it is parsed as an octal integer. If not
* supplied, defaults to `0o666`.
*/
function open(path: PathLike, flags: string | number, mode?: Mode): Promise<FileHandle>;
/**
* Asynchronously reads data from the file referenced by the supplied `FileHandle`.
* @param handle A `FileHandle`.
* @param buffer The buffer that the data will be written to.
* @param offset The offset in the buffer at which to start writing.
* @param length The number of bytes to read.
* @param position The offset from the beginning of the file from which data should be read. If
* `null`, data will be read from the current position.
*/
function read<TBuffer extends Uint8Array>(
handle: FileHandle,
buffer: TBuffer,
offset?: number | null,
length?: number | null,
position?: number | null,
): Promise<{ bytesRead: number, buffer: TBuffer }>;
/**
* Asynchronously writes `buffer` to the file referenced by the supplied `FileHandle`.
* It is unsafe to call `fsPromises.write()` multiple times on the same file without waiting for the `Promise`
* to be resolved (or rejected). For this scenario, `fs.createWriteStream` is strongly recommended.
* @param handle A `FileHandle`.
* @param buffer The buffer that the data will be written to.
* @param offset The part of the buffer to be written. If not supplied, defaults to `0`.
* @param length The number of bytes to write. If not supplied, defaults to `buffer.length - offset`.
* @param position The offset from the beginning of the file where this data should be written. If not supplied, defaults to the current position.
*/
function write<TBuffer extends Uint8Array>(
handle: FileHandle,
buffer: TBuffer,
offset?: number | null,
length?: number | null, position?: number | null): Promise<{ bytesWritten: number, buffer: TBuffer }>;
/**
* Asynchronously writes `string` to the file referenced by the supplied `FileHandle`.
* It is unsafe to call `fsPromises.write()` multiple times on the same file without waiting for the `Promise`
* to be resolved (or rejected). For this scenario, `fs.createWriteStream` is strongly recommended.
* @param handle A `FileHandle`.
* @param string A string to write.
* @param position The offset from the beginning of the file where this data should be written. If not supplied, defaults to the current position.
* @param encoding The expected string encoding.
*/
function write(handle: FileHandle, string: string, position?: number | null, encoding?: BufferEncoding | null): Promise<{ bytesWritten: number, buffer: string }>;
/**
* Asynchronous rename(2) - Change the name or location of a file or directory.
* @param oldPath A path to a file. If a URL is provided, it must use the `file:` protocol.
* URL support is _experimental_.
* @param newPath A path to a file. If a URL is provided, it must use the `file:` protocol.
* URL support is _experimental_.
*/
function rename(oldPath: PathLike, newPath: PathLike): Promise<void>;
/**
* Asynchronous truncate(2) - Truncate a file to a specified length.
* @param path A path to a file. If a URL is provided, it must use the `file:` protocol.
* @param len If not specified, defaults to `0`.
*/
function truncate(path: PathLike, len?: number): Promise<void>;
/**
* Asynchronous ftruncate(2) - Truncate a file to a specified length.
* @param handle A `FileHandle`.
* @param len If not specified, defaults to `0`.
*/
function ftruncate(handle: FileHandle, len?: number): Promise<void>;
/**
* Asynchronous rmdir(2) - delete a directory.
* @param path A path to a file. If a URL is provided, it must use the `file:` protocol.
*/
function rmdir(path: PathLike, options?: RmDirOptions): Promise<void>;
/**
* Asynchronously removes files and directories (modeled on the standard POSIX `rm` utility).
*/
function rm(path: PathLike, options?: RmOptions): Promise<void>;
/**
* Asynchronous fdatasync(2) - synchronize a file's in-core state with storage device.
* @param handle A `FileHandle`.
*/
function fdatasync(handle: FileHandle): Promise<void>;
/**
* Asynchronous fsync(2) - synchronize a file's in-core state with the underlying storage device.
* @param handle A `FileHandle`.
*/
function fsync(handle: FileHandle): Promise<void>;
/**
* Asynchronous mkdir(2) - create a directory.
* @param path A path to a file. If a URL is provided, it must use the `file:` protocol.
* @param options Either the file mode, or an object optionally specifying the file mode and whether parent folders
* should be created. If a string is passed, it is parsed as an octal integer. If not specified, defaults to `0o777`.
*/
function mkdir(path: PathLike, options: MakeDirectoryOptions & { recursive: true; }): Promise<string | undefined>;
/**
* Asynchronous mkdir(2) - create a directory.
* @param path A path to a file. If a URL is provided, it must use the `file:` protocol.
* @param options Either the file mode, or an object optionally specifying the file mode and whether parent folders
* should be created. If a string is passed, it is parsed as an octal integer. If not specified, defaults to `0o777`.
*/
function mkdir(path: PathLike, options?: Mode | (MakeDirectoryOptions & { recursive?: false | undefined; }) | null): Promise<void>;
/**
* Asynchronous mkdir(2) - create a directory.
* @param path A path to a file. If a URL is provided, it must use the `file:` protocol.
* @param options Either the file mode, or an object optionally specifying the file mode and whether parent folders
* should be created. If a string is passed, it is parsed as an octal integer. If not specified, defaults to `0o777`.
*/
function mkdir(path: PathLike, options?: Mode | MakeDirectoryOptions | null): Promise<string | undefined>;
/**
* Asynchronous readdir(3) - read a directory.
* @param path A path to a file. If a URL is provided, it must use the `file:` protocol.
* @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used.
*/
function readdir(path: PathLike, options?: BaseEncodingOptions & { withFileTypes?: false | undefined } | BufferEncoding | null): Promise<string[]>;
/**
* Asynchronous readdir(3) - read a directory.
* @param path A path to a file. If a URL is provided, it must use the `file:` protocol.
* @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used.
*/
function readdir(path: PathLike, options: { encoding: "buffer"; withFileTypes?: false | undefined } | "buffer"): Promise<Buffer[]>;
/**
* Asynchronous readdir(3) - read a directory.
* @param path A path to a file. If a URL is provided, it must use the `file:` protocol.
* @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used.
*/
function readdir(path: PathLike, options?: BaseEncodingOptions & { withFileTypes?: false | undefined } | BufferEncoding | null): Promise<string[] | Buffer[]>;
/**
* Asynchronous readdir(3) - read a directory.
* @param path A path to a file. If a URL is provided, it must use the `file:` protocol.
* @param options If called with `withFileTypes: true` the result data will be an array of Dirent.
*/
function readdir(path: PathLike, options: BaseEncodingOptions & { withFileTypes: true }): Promise<Dirent[]>;
/**
* Asynchronous readlink(2) - read value of a symbolic link.
* @param path A path to a file. If a URL is provided, it must use the `file:` protocol.
* @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used.
*/
function readlink(path: PathLike, options?: BaseEncodingOptions | BufferEncoding | null): Promise<string>;
/**
* Asynchronous readlink(2) - read value of a symbolic link.
* @param path A path to a file. If a URL is provided, it must use the `file:` protocol.
* @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used.
*/
function readlink(path: PathLike, options: BufferEncodingOption): Promise<Buffer>;
/**
* Asynchronous readlink(2) - read value of a symbolic link.
* @param path A path to a file. If a URL is provided, it must use the `file:` protocol.
* @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used.
*/
function readlink(path: PathLike, options?: BaseEncodingOptions | string | null): Promise<string | Buffer>;
/**
* Asynchronous symlink(2) - Create a new symbolic link to an existing file.
* @param target A path to an existing file. If a URL is provided, it must use the `file:` protocol.
* @param path A path to the new symlink. If a URL is provided, it must use the `file:` protocol.
* @param type May be set to `'dir'`, `'file'`, or `'junction'` (default is `'file'`) and is only available on Windows (ignored on other platforms).
* When using `'junction'`, the `target` argument will automatically be normalized to an absolute path.
*/
function symlink(target: PathLike, path: PathLike, type?: string | null): Promise<void>;
/**
* Asynchronous lstat(2) - Get file status. Does not dereference symbolic links.
* @param path A path to a file. If a URL is provided, it must use the `file:` protocol.
*/
function lstat(path: PathLike, opts?: StatOptions & { bigint?: false | undefined }): Promise<Stats>;
function lstat(path: PathLike, opts: StatOptions & { bigint: true }): Promise<BigIntStats>;
function lstat(path: PathLike, opts?: StatOptions): Promise<Stats | BigIntStats>;
/**
* Asynchronous stat(2) - Get file status.
* @param path A path to a file. If a URL is provided, it must use the `file:` protocol.
*/
function stat(path: PathLike, opts?: StatOptions & { bigint?: false | undefined }): Promise<Stats>;
function stat(path: PathLike, opts: StatOptions & { bigint: true }): Promise<BigIntStats>;
function stat(path: PathLike, opts?: StatOptions): Promise<Stats | BigIntStats>;
/**
* Asynchronous link(2) - Create a new link (also known as a hard link) to an existing file.
* @param existingPath A path to a file. If a URL is provided, it must use the `file:` protocol.
* @param newPath A path to a file. If a URL is provided, it must use the `file:` protocol.
*/
function link(existingPath: PathLike, newPath: PathLike): Promise<void>;
/**
* Asynchronous unlink(2) - delete a name and possibly the file it refers to.
* @param path A path to a file. If a URL is provided, it must use the `file:` protocol.
*/
function unlink(path: PathLike): Promise<void>;
/**
* Asynchronous fchmod(2) - Change permissions of a file.
* @param handle A `FileHandle`.
* @param mode A file mode. If a string is passed, it is parsed as an octal integer.
*/
function fchmod(handle: FileHandle, mode: Mode): Promise<void>;
/**
* Asynchronous chmod(2) - Change permissions of a file.
* @param path A path to a file. If a URL is provided, it must use the `file:` protocol.
* @param mode A file mode. If a string is passed, it is parsed as an octal integer.
*/
function chmod(path: PathLike, mode: Mode): Promise<void>;
/**
* Asynchronous lchmod(2) - Change permissions of a file. Does not dereference symbolic links.
* @param path A path to a file. If a URL is provided, it must use the `file:` protocol.
* @param mode A file mode. If a string is passed, it is parsed as an octal integer.
*/
function lchmod(path: PathLike, mode: Mode): Promise<void>;
/**
* Asynchronous lchown(2) - Change ownership of a file. Does not dereference symbolic links.
* @param path A path to a file. If a URL is provided, it must use the `file:` protocol.
*/
function lchown(path: PathLike, uid: number, gid: number): Promise<void>;
/**
* Changes the access and modification times of a file in the same way as `fsPromises.utimes()`,
* with the difference that if the path refers to a symbolic link, then the link is not
* dereferenced: instead, the timestamps of the symbolic link itself are changed.
* @param path A path to a file. If a URL is provided, it must use the `file:` protocol.
* @param atime The last access time. If a string is provided, it will be coerced to number.
* @param mtime The last modified time. If a string is provided, it will be coerced to number.
*/
function lutimes(path: PathLike, atime: string | number | Date, mtime: string | number | Date): Promise<void>;
/**
* Asynchronous fchown(2) - Change ownership of a file.
* @param handle A `FileHandle`.
*/
function fchown(handle: FileHandle, uid: number, gid: number): Promise<void>;
/**
* Asynchronous chown(2) - Change ownership of a file.
* @param path A path to a file. If a URL is provided, it must use the `file:` protocol.
*/
function chown(path: PathLike, uid: number, gid: number): Promise<void>;
/**
* Asynchronously change file timestamps of the file referenced by the supplied path.
* @param path A path to a file. If a URL is provided, it must use the `file:` protocol.
* @param atime The last access time. If a string is provided, it will be coerced to number.
* @param mtime The last modified time. If a string is provided, it will be coerced to number.
*/
function utimes(path: PathLike, atime: string | number | Date, mtime: string | number | Date): Promise<void>;
/**
* Asynchronously change file timestamps of the file referenced by the supplied `FileHandle`.
* @param handle A `FileHandle`.
* @param atime The last access time. If a string is provided, it will be coerced to number.
* @param mtime The last modified time. If a string is provided, it will be coerced to number.
*/
function futimes(handle: FileHandle, atime: string | number | Date, mtime: string | number | Date): Promise<void>;
/**
* Asynchronous realpath(3) - return the canonicalized absolute pathname.
* @param path A path to a file. If a URL is provided, it must use the `file:` protocol.
* @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used.
*/
function realpath(path: PathLike, options?: BaseEncodingOptions | BufferEncoding | null): Promise<string>;
/**
* Asynchronous realpath(3) - return the canonicalized absolute pathname.
* @param path A path to a file. If a URL is provided, it must use the `file:` protocol.
* @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used.
*/
function realpath(path: PathLike, options: BufferEncodingOption): Promise<Buffer>;
/**
* Asynchronous realpath(3) - return the canonicalized absolute pathname.
* @param path A path to a file. If a URL is provided, it must use the `file:` protocol.
* @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used.
*/
function realpath(path: PathLike, options?: BaseEncodingOptions | BufferEncoding | null): Promise<string | Buffer>;
/**
* Asynchronously creates a unique temporary directory.
* Generates six random characters to be appended behind a required `prefix` to create a unique temporary directory.
* @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used.
*/
function mkdtemp(prefix: string, options?: BaseEncodingOptions | BufferEncoding | null): Promise<string>;
/**
* Asynchronously creates a unique temporary directory.
* Generates six random characters to be appended behind a required `prefix` to create a unique temporary directory.
* @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used.
*/
function mkdtemp(prefix: string, options: BufferEncodingOption): Promise<Buffer>;
/**
* Asynchronously creates a unique temporary directory.
* Generates six random characters to be appended behind a required `prefix` to create a unique temporary directory.
* @param options The encoding (or an object specifying the encoding), used as the encoding of the result. If not provided, `'utf8'` is used.
*/
function mkdtemp(prefix: string, options?: BaseEncodingOptions | BufferEncoding | null): Promise<string | Buffer>;
/**
* Asynchronously writes data to a file, replacing the file if it already exists.
* It is unsafe to call `fsPromises.writeFile()` multiple times on the same file without waiting for the `Promise` to be resolved (or rejected).
* @param path A path to a file. If a URL is provided, it must use the `file:` protocol.
* URL support is _experimental_.
* If a `FileHandle` is provided, the underlying file will _not_ be closed automatically.
* @param data The data to write. If something other than a `Buffer` or `Uint8Array` is provided, the value is coerced to a string.
* @param options Either the encoding for the file, or an object optionally specifying the encoding, file mode, and flag.
* If `encoding` is not supplied, the default of `'utf8'` is used.
* If `mode` is not supplied, the default of `0o666` is used.
* If `mode` is a string, it is parsed as an octal integer.
* If `flag` is not supplied, the default of `'w'` is used.
*/
function writeFile(
path: PathLike | FileHandle,
data: string | Uint8Array,
options?: BaseEncodingOptions & { mode?: Mode | undefined, flag?: OpenMode | undefined } | BufferEncoding | null
): Promise<void>;
/**
* Asynchronously append data to a file, creating the file if it does not exist.
* @param file A path to a file. If a URL is provided, it must use the `file:` protocol.
* URL support is _experimental_.
* If a `FileHandle` is provided, the underlying file will _not_ be closed automatically.
* @param data The data to write. If something other than a `Buffer` or `Uint8Array` is provided, the value is coerced to a string.
* @param options Either the encoding for the file, or an object optionally specifying the encoding, file mode, and flag.
* If `encoding` is not supplied, the default of `'utf8'` is used.
* If `mode` is not supplied, the default of `0o666` is used.
* If `mode` is a string, it is parsed as an octal integer.
* If `flag` is not supplied, the default of `'a'` is used.
*/
function appendFile(
path: PathLike | FileHandle,
data: string | Uint8Array,
options?: BaseEncodingOptions & { mode?: Mode | undefined, flag?: OpenMode | undefined } | BufferEncoding | null
): Promise<void>;
/**
* Asynchronously reads the entire contents of a file.
* @param path A path to a file. If a URL is provided, it must use the `file:` protocol.
* If a `FileHandle` is provided, the underlying file will _not_ be closed automatically.
* @param options An object that may contain an optional flag.
* If a flag is not provided, it defaults to `'r'`.
*/
function readFile(path: PathLike | FileHandle, options?: { encoding?: null | undefined, flag?: OpenMode | undefined } | null): Promise<Buffer>;
/**
* Asynchronously reads the entire contents of a file.
* @param path A path to a file. If a URL is provided, it must use the `file:` protocol.
* If a `FileHandle` is provided, the underlying file will _not_ be closed automatically.
* @param options An object that may contain an optional flag.
* If a flag is not provided, it defaults to `'r'`.
*/
function readFile(path: PathLike | FileHandle, options: { encoding: BufferEncoding, flag?: OpenMode | undefined } | BufferEncoding): Promise<string>;
/**
* Asynchronously reads the entire contents of a file.
* @param path A path to a file. If a URL is provided, it must use the `file:` protocol.
* If a `FileHandle` is provided, the underlying file will _not_ be closed automatically.
* @param options An object that may contain an optional flag.
* If a flag is not provided, it defaults to `'r'`.
*/
function readFile(path: PathLike | FileHandle, options?: BaseEncodingOptions & { flag?: OpenMode | undefined } | BufferEncoding | null): Promise<string | Buffer>;
function opendir(path: string, options?: OpenDirOptions): Promise<Dir>;
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,961 @@
/* NOTE: Do not edit directly! This file is generated using `npm run update-types` in https://github.com/node-red/nr-monaco-build */
declare module 'http2' {
import EventEmitter = require('events');
import * as fs from 'fs';
import * as net from 'net';
import * as stream from 'stream';
import * as tls from 'tls';
import * as url from 'url';
import {
IncomingHttpHeaders as Http1IncomingHttpHeaders,
OutgoingHttpHeaders,
IncomingMessage,
ServerResponse,
} from 'http';
export { OutgoingHttpHeaders } from 'http';
export interface IncomingHttpStatusHeader {
":status"?: number | undefined;
}
export interface IncomingHttpHeaders extends Http1IncomingHttpHeaders {
":path"?: string | undefined;
":method"?: string | undefined;
":authority"?: string | undefined;
":scheme"?: string | undefined;
}
// Http2Stream
export interface StreamPriorityOptions {
exclusive?: boolean | undefined;
parent?: number | undefined;
weight?: number | undefined;
silent?: boolean | undefined;
}
export interface StreamState {
localWindowSize?: number | undefined;
state?: number | undefined;
localClose?: number | undefined;
remoteClose?: number | undefined;
sumDependencyWeight?: number | undefined;
weight?: number | undefined;
}
export interface ServerStreamResponseOptions {
endStream?: boolean | undefined;
waitForTrailers?: boolean | undefined;
}
export interface StatOptions {
offset: number;
length: number;
}
export interface ServerStreamFileResponseOptions {
statCheck?(stats: fs.Stats, headers: OutgoingHttpHeaders, statOptions: StatOptions): void | boolean;
waitForTrailers?: boolean | undefined;
offset?: number | undefined;
length?: number | undefined;
}
export interface ServerStreamFileResponseOptionsWithError extends ServerStreamFileResponseOptions {
onError?(err: NodeJS.ErrnoException): void;
}
export interface Http2Stream extends stream.Duplex {
readonly aborted: boolean;
readonly bufferSize: number;
readonly closed: boolean;
readonly destroyed: boolean;
/**
* Set the true if the END_STREAM flag was set in the request or response HEADERS frame received,
* indicating that no additional data should be received and the readable side of the Http2Stream will be closed.
*/
readonly endAfterHeaders: boolean;
readonly id?: number | undefined;
readonly pending: boolean;
readonly rstCode: number;
readonly sentHeaders: OutgoingHttpHeaders;
readonly sentInfoHeaders?: OutgoingHttpHeaders[] | undefined;
readonly sentTrailers?: OutgoingHttpHeaders | undefined;
readonly session: Http2Session;
readonly state: StreamState;
close(code?: number, callback?: () => void): void;
priority(options: StreamPriorityOptions): void;
setTimeout(msecs: number, callback?: () => void): void;
sendTrailers(headers: OutgoingHttpHeaders): void;
addListener(event: "aborted", listener: () => void): this;
addListener(event: "close", listener: () => void): this;
addListener(event: "data", listener: (chunk: Buffer | string) => void): this;
addListener(event: "drain", listener: () => void): this;
addListener(event: "end", listener: () => void): this;
addListener(event: "error", listener: (err: Error) => void): this;
addListener(event: "finish", listener: () => void): this;
addListener(event: "frameError", listener: (frameType: number, errorCode: number) => void): this;
addListener(event: "pipe", listener: (src: stream.Readable) => void): this;
addListener(event: "unpipe", listener: (src: stream.Readable) => void): this;
addListener(event: "streamClosed", listener: (code: number) => void): this;
addListener(event: "timeout", listener: () => void): this;
addListener(event: "trailers", listener: (trailers: IncomingHttpHeaders, flags: number) => void): this;
addListener(event: "wantTrailers", listener: () => void): this;
addListener(event: string | symbol, listener: (...args: any[]) => void): this;
emit(event: "aborted"): boolean;
emit(event: "close"): boolean;
emit(event: "data", chunk: Buffer | string): boolean;
emit(event: "drain"): boolean;
emit(event: "end"): boolean;
emit(event: "error", err: Error): boolean;
emit(event: "finish"): boolean;
emit(event: "frameError", frameType: number, errorCode: number): boolean;
emit(event: "pipe", src: stream.Readable): boolean;
emit(event: "unpipe", src: stream.Readable): boolean;
emit(event: "streamClosed", code: number): boolean;
emit(event: "timeout"): boolean;
emit(event: "trailers", trailers: IncomingHttpHeaders, flags: number): boolean;
emit(event: "wantTrailers"): boolean;
emit(event: string | symbol, ...args: any[]): boolean;
on(event: "aborted", listener: () => void): this;
on(event: "close", listener: () => void): this;
on(event: "data", listener: (chunk: Buffer | string) => void): this;
on(event: "drain", listener: () => void): this;
on(event: "end", listener: () => void): this;
on(event: "error", listener: (err: Error) => void): this;
on(event: "finish", listener: () => void): this;
on(event: "frameError", listener: (frameType: number, errorCode: number) => void): this;
on(event: "pipe", listener: (src: stream.Readable) => void): this;
on(event: "unpipe", listener: (src: stream.Readable) => void): this;
on(event: "streamClosed", listener: (code: number) => void): this;
on(event: "timeout", listener: () => void): this;
on(event: "trailers", listener: (trailers: IncomingHttpHeaders, flags: number) => void): this;
on(event: "wantTrailers", listener: () => void): this;
on(event: string | symbol, listener: (...args: any[]) => void): this;
once(event: "aborted", listener: () => void): this;
once(event: "close", listener: () => void): this;
once(event: "data", listener: (chunk: Buffer | string) => void): this;
once(event: "drain", listener: () => void): this;
once(event: "end", listener: () => void): this;
once(event: "error", listener: (err: Error) => void): this;
once(event: "finish", listener: () => void): this;
once(event: "frameError", listener: (frameType: number, errorCode: number) => void): this;
once(event: "pipe", listener: (src: stream.Readable) => void): this;
once(event: "unpipe", listener: (src: stream.Readable) => void): this;
once(event: "streamClosed", listener: (code: number) => void): this;
once(event: "timeout", listener: () => void): this;
once(event: "trailers", listener: (trailers: IncomingHttpHeaders, flags: number) => void): this;
once(event: "wantTrailers", listener: () => void): this;
once(event: string | symbol, listener: (...args: any[]) => void): this;
prependListener(event: "aborted", listener: () => void): this;
prependListener(event: "close", listener: () => void): this;
prependListener(event: "data", listener: (chunk: Buffer | string) => void): this;
prependListener(event: "drain", listener: () => void): this;
prependListener(event: "end", listener: () => void): this;
prependListener(event: "error", listener: (err: Error) => void): this;
prependListener(event: "finish", listener: () => void): this;
prependListener(event: "frameError", listener: (frameType: number, errorCode: number) => void): this;
prependListener(event: "pipe", listener: (src: stream.Readable) => void): this;
prependListener(event: "unpipe", listener: (src: stream.Readable) => void): this;
prependListener(event: "streamClosed", listener: (code: number) => void): this;
prependListener(event: "timeout", listener: () => void): this;
prependListener(event: "trailers", listener: (trailers: IncomingHttpHeaders, flags: number) => void): this;
prependListener(event: "wantTrailers", listener: () => void): this;
prependListener(event: string | symbol, listener: (...args: any[]) => void): this;
prependOnceListener(event: "aborted", listener: () => void): this;
prependOnceListener(event: "close", listener: () => void): this;
prependOnceListener(event: "data", listener: (chunk: Buffer | string) => void): this;
prependOnceListener(event: "drain", listener: () => void): this;
prependOnceListener(event: "end", listener: () => void): this;
prependOnceListener(event: "error", listener: (err: Error) => void): this;
prependOnceListener(event: "finish", listener: () => void): this;
prependOnceListener(event: "frameError", listener: (frameType: number, errorCode: number) => void): this;
prependOnceListener(event: "pipe", listener: (src: stream.Readable) => void): this;
prependOnceListener(event: "unpipe", listener: (src: stream.Readable) => void): this;
prependOnceListener(event: "streamClosed", listener: (code: number) => void): this;
prependOnceListener(event: "timeout", listener: () => void): this;
prependOnceListener(event: "trailers", listener: (trailers: IncomingHttpHeaders, flags: number) => void): this;
prependOnceListener(event: "wantTrailers", listener: () => void): this;
prependOnceListener(event: string | symbol, listener: (...args: any[]) => void): this;
}
export interface ClientHttp2Stream extends Http2Stream {
addListener(event: "continue", listener: () => {}): this;
addListener(event: "headers", listener: (headers: IncomingHttpHeaders & IncomingHttpStatusHeader, flags: number) => void): this;
addListener(event: "push", listener: (headers: IncomingHttpHeaders, flags: number) => void): this;
addListener(event: "response", listener: (headers: IncomingHttpHeaders & IncomingHttpStatusHeader, flags: number) => void): this;
addListener(event: string | symbol, listener: (...args: any[]) => void): this;
emit(event: "continue"): boolean;
emit(event: "headers", headers: IncomingHttpHeaders & IncomingHttpStatusHeader, flags: number): boolean;
emit(event: "push", headers: IncomingHttpHeaders, flags: number): boolean;
emit(event: "response", headers: IncomingHttpHeaders & IncomingHttpStatusHeader, flags: number): boolean;
emit(event: string | symbol, ...args: any[]): boolean;
on(event: "continue", listener: () => {}): this;
on(event: "headers", listener: (headers: IncomingHttpHeaders & IncomingHttpStatusHeader, flags: number) => void): this;
on(event: "push", listener: (headers: IncomingHttpHeaders, flags: number) => void): this;
on(event: "response", listener: (headers: IncomingHttpHeaders & IncomingHttpStatusHeader, flags: number) => void): this;
on(event: string | symbol, listener: (...args: any[]) => void): this;
once(event: "continue", listener: () => {}): this;
once(event: "headers", listener: (headers: IncomingHttpHeaders & IncomingHttpStatusHeader, flags: number) => void): this;
once(event: "push", listener: (headers: IncomingHttpHeaders, flags: number) => void): this;
once(event: "response", listener: (headers: IncomingHttpHeaders & IncomingHttpStatusHeader, flags: number) => void): this;
once(event: string | symbol, listener: (...args: any[]) => void): this;
prependListener(event: "continue", listener: () => {}): this;
prependListener(event: "headers", listener: (headers: IncomingHttpHeaders & IncomingHttpStatusHeader, flags: number) => void): this;
prependListener(event: "push", listener: (headers: IncomingHttpHeaders, flags: number) => void): this;
prependListener(event: "response", listener: (headers: IncomingHttpHeaders & IncomingHttpStatusHeader, flags: number) => void): this;
prependListener(event: string | symbol, listener: (...args: any[]) => void): this;
prependOnceListener(event: "continue", listener: () => {}): this;
prependOnceListener(event: "headers", listener: (headers: IncomingHttpHeaders & IncomingHttpStatusHeader, flags: number) => void): this;
prependOnceListener(event: "push", listener: (headers: IncomingHttpHeaders, flags: number) => void): this;
prependOnceListener(event: "response", listener: (headers: IncomingHttpHeaders & IncomingHttpStatusHeader, flags: number) => void): this;
prependOnceListener(event: string | symbol, listener: (...args: any[]) => void): this;
}
export interface ServerHttp2Stream extends Http2Stream {
readonly headersSent: boolean;
readonly pushAllowed: boolean;
additionalHeaders(headers: OutgoingHttpHeaders): void;
pushStream(headers: OutgoingHttpHeaders, callback?: (err: Error | null, pushStream: ServerHttp2Stream, headers: OutgoingHttpHeaders) => void): void;
pushStream(headers: OutgoingHttpHeaders, options?: StreamPriorityOptions, callback?: (err: Error | null, pushStream: ServerHttp2Stream, headers: OutgoingHttpHeaders) => void): void;
respond(headers?: OutgoingHttpHeaders, options?: ServerStreamResponseOptions): void;
respondWithFD(fd: number | fs.promises.FileHandle, headers?: OutgoingHttpHeaders, options?: ServerStreamFileResponseOptions): void;
respondWithFile(path: string, headers?: OutgoingHttpHeaders, options?: ServerStreamFileResponseOptionsWithError): void;
}
// Http2Session
export interface Settings {
headerTableSize?: number | undefined;
enablePush?: boolean | undefined;
initialWindowSize?: number | undefined;
maxFrameSize?: number | undefined;
maxConcurrentStreams?: number | undefined;
maxHeaderListSize?: number | undefined;
enableConnectProtocol?: boolean | undefined;
}
export interface ClientSessionRequestOptions {
endStream?: boolean | undefined;
exclusive?: boolean | undefined;
parent?: number | undefined;
weight?: number | undefined;
waitForTrailers?: boolean | undefined;
}
export interface SessionState {
effectiveLocalWindowSize?: number | undefined;
effectiveRecvDataLength?: number | undefined;
nextStreamID?: number | undefined;
localWindowSize?: number | undefined;
lastProcStreamID?: number | undefined;
remoteWindowSize?: number | undefined;
outboundQueueSize?: number | undefined;
deflateDynamicTableSize?: number | undefined;
inflateDynamicTableSize?: number | undefined;
}
export interface Http2Session extends EventEmitter {
readonly alpnProtocol?: string | undefined;
readonly closed: boolean;
readonly connecting: boolean;
readonly destroyed: boolean;
readonly encrypted?: boolean | undefined;
readonly localSettings: Settings;
readonly originSet?: string[] | undefined;
readonly pendingSettingsAck: boolean;
readonly remoteSettings: Settings;
readonly socket: net.Socket | tls.TLSSocket;
readonly state: SessionState;
readonly type: number;
close(callback?: () => void): void;
destroy(error?: Error, code?: number): void;
goaway(code?: number, lastStreamID?: number, opaqueData?: NodeJS.ArrayBufferView): void;
ping(callback: (err: Error | null, duration: number, payload: Buffer) => void): boolean;
ping(payload: NodeJS.ArrayBufferView, callback: (err: Error | null, duration: number, payload: Buffer) => void): boolean;
ref(): void;
setLocalWindowSize(windowSize: number): void;
setTimeout(msecs: number, callback?: () => void): void;
settings(settings: Settings): void;
unref(): void;
addListener(event: "close", listener: () => void): this;
addListener(event: "error", listener: (err: Error) => void): this;
addListener(event: "frameError", listener: (frameType: number, errorCode: number, streamID: number) => void): this;
addListener(event: "goaway", listener: (errorCode: number, lastStreamID: number, opaqueData: Buffer) => void): this;
addListener(event: "localSettings", listener: (settings: Settings) => void): this;
addListener(event: "ping", listener: () => void): this;
addListener(event: "remoteSettings", listener: (settings: Settings) => void): this;
addListener(event: "timeout", listener: () => void): this;
addListener(event: string | symbol, listener: (...args: any[]) => void): this;
emit(event: "close"): boolean;
emit(event: "error", err: Error): boolean;
emit(event: "frameError", frameType: number, errorCode: number, streamID: number): boolean;
emit(event: "goaway", errorCode: number, lastStreamID: number, opaqueData: Buffer): boolean;
emit(event: "localSettings", settings: Settings): boolean;
emit(event: "ping"): boolean;
emit(event: "remoteSettings", settings: Settings): boolean;
emit(event: "timeout"): boolean;
emit(event: string | symbol, ...args: any[]): boolean;
on(event: "close", listener: () => void): this;
on(event: "error", listener: (err: Error) => void): this;
on(event: "frameError", listener: (frameType: number, errorCode: number, streamID: number) => void): this;
on(event: "goaway", listener: (errorCode: number, lastStreamID: number, opaqueData: Buffer) => void): this;
on(event: "localSettings", listener: (settings: Settings) => void): this;
on(event: "ping", listener: () => void): this;
on(event: "remoteSettings", listener: (settings: Settings) => void): this;
on(event: "timeout", listener: () => void): this;
on(event: string | symbol, listener: (...args: any[]) => void): this;
once(event: "close", listener: () => void): this;
once(event: "error", listener: (err: Error) => void): this;
once(event: "frameError", listener: (frameType: number, errorCode: number, streamID: number) => void): this;
once(event: "goaway", listener: (errorCode: number, lastStreamID: number, opaqueData: Buffer) => void): this;
once(event: "localSettings", listener: (settings: Settings) => void): this;
once(event: "ping", listener: () => void): this;
once(event: "remoteSettings", listener: (settings: Settings) => void): this;
once(event: "timeout", listener: () => void): this;
once(event: string | symbol, listener: (...args: any[]) => void): this;
prependListener(event: "close", listener: () => void): this;
prependListener(event: "error", listener: (err: Error) => void): this;
prependListener(event: "frameError", listener: (frameType: number, errorCode: number, streamID: number) => void): this;
prependListener(event: "goaway", listener: (errorCode: number, lastStreamID: number, opaqueData: Buffer) => void): this;
prependListener(event: "localSettings", listener: (settings: Settings) => void): this;
prependListener(event: "ping", listener: () => void): this;
prependListener(event: "remoteSettings", listener: (settings: Settings) => void): this;
prependListener(event: "timeout", listener: () => void): this;
prependListener(event: string | symbol, listener: (...args: any[]) => void): this;
prependOnceListener(event: "close", listener: () => void): this;
prependOnceListener(event: "error", listener: (err: Error) => void): this;
prependOnceListener(event: "frameError", listener: (frameType: number, errorCode: number, streamID: number) => void): this;
prependOnceListener(event: "goaway", listener: (errorCode: number, lastStreamID: number, opaqueData: Buffer) => void): this;
prependOnceListener(event: "localSettings", listener: (settings: Settings) => void): this;
prependOnceListener(event: "ping", listener: () => void): this;
prependOnceListener(event: "remoteSettings", listener: (settings: Settings) => void): this;
prependOnceListener(event: "timeout", listener: () => void): this;
prependOnceListener(event: string | symbol, listener: (...args: any[]) => void): this;
}
export interface ClientHttp2Session extends Http2Session {
request(headers?: OutgoingHttpHeaders, options?: ClientSessionRequestOptions): ClientHttp2Stream;
addListener(event: "altsvc", listener: (alt: string, origin: string, stream: number) => void): this;
addListener(event: "origin", listener: (origins: string[]) => void): this;
addListener(event: "connect", listener: (session: ClientHttp2Session, socket: net.Socket | tls.TLSSocket) => void): this;
addListener(event: "stream", listener: (stream: ClientHttp2Stream, headers: IncomingHttpHeaders & IncomingHttpStatusHeader, flags: number) => void): this;
addListener(event: string | symbol, listener: (...args: any[]) => void): this;
emit(event: "altsvc", alt: string, origin: string, stream: number): boolean;
emit(event: "origin", origins: ReadonlyArray<string>): boolean;
emit(event: "connect", session: ClientHttp2Session, socket: net.Socket | tls.TLSSocket): boolean;
emit(event: "stream", stream: ClientHttp2Stream, headers: IncomingHttpHeaders & IncomingHttpStatusHeader, flags: number): boolean;
emit(event: string | symbol, ...args: any[]): boolean;
on(event: "altsvc", listener: (alt: string, origin: string, stream: number) => void): this;
on(event: "origin", listener: (origins: string[]) => void): this;
on(event: "connect", listener: (session: ClientHttp2Session, socket: net.Socket | tls.TLSSocket) => void): this;
on(event: "stream", listener: (stream: ClientHttp2Stream, headers: IncomingHttpHeaders & IncomingHttpStatusHeader, flags: number) => void): this;
on(event: string | symbol, listener: (...args: any[]) => void): this;
once(event: "altsvc", listener: (alt: string, origin: string, stream: number) => void): this;
once(event: "origin", listener: (origins: string[]) => void): this;
once(event: "connect", listener: (session: ClientHttp2Session, socket: net.Socket | tls.TLSSocket) => void): this;
once(event: "stream", listener: (stream: ClientHttp2Stream, headers: IncomingHttpHeaders & IncomingHttpStatusHeader, flags: number) => void): this;
once(event: string | symbol, listener: (...args: any[]) => void): this;
prependListener(event: "altsvc", listener: (alt: string, origin: string, stream: number) => void): this;
prependListener(event: "origin", listener: (origins: string[]) => void): this;
prependListener(event: "connect", listener: (session: ClientHttp2Session, socket: net.Socket | tls.TLSSocket) => void): this;
prependListener(event: "stream", listener: (stream: ClientHttp2Stream, headers: IncomingHttpHeaders & IncomingHttpStatusHeader, flags: number) => void): this;
prependListener(event: string | symbol, listener: (...args: any[]) => void): this;
prependOnceListener(event: "altsvc", listener: (alt: string, origin: string, stream: number) => void): this;
prependOnceListener(event: "origin", listener: (origins: string[]) => void): this;
prependOnceListener(event: "connect", listener: (session: ClientHttp2Session, socket: net.Socket | tls.TLSSocket) => void): this;
prependOnceListener(event: "stream", listener: (stream: ClientHttp2Stream, headers: IncomingHttpHeaders & IncomingHttpStatusHeader, flags: number) => void): this;
prependOnceListener(event: string | symbol, listener: (...args: any[]) => void): this;
}
export interface AlternativeServiceOptions {
origin: number | string | url.URL;
}
export interface ServerHttp2Session extends Http2Session {
readonly server: Http2Server | Http2SecureServer;
altsvc(alt: string, originOrStream: number | string | url.URL | AlternativeServiceOptions): void;
origin(...args: Array<string | url.URL | { origin: string }>): void;
addListener(event: "connect", listener: (session: ServerHttp2Session, socket: net.Socket | tls.TLSSocket) => void): this;
addListener(event: "stream", listener: (stream: ServerHttp2Stream, headers: IncomingHttpHeaders, flags: number) => void): this;
addListener(event: string | symbol, listener: (...args: any[]) => void): this;
emit(event: "connect", session: ServerHttp2Session, socket: net.Socket | tls.TLSSocket): boolean;
emit(event: "stream", stream: ServerHttp2Stream, headers: IncomingHttpHeaders, flags: number): boolean;
emit(event: string | symbol, ...args: any[]): boolean;
on(event: "connect", listener: (session: ServerHttp2Session, socket: net.Socket | tls.TLSSocket) => void): this;
on(event: "stream", listener: (stream: ServerHttp2Stream, headers: IncomingHttpHeaders, flags: number) => void): this;
on(event: string | symbol, listener: (...args: any[]) => void): this;
once(event: "connect", listener: (session: ServerHttp2Session, socket: net.Socket | tls.TLSSocket) => void): this;
once(event: "stream", listener: (stream: ServerHttp2Stream, headers: IncomingHttpHeaders, flags: number) => void): this;
once(event: string | symbol, listener: (...args: any[]) => void): this;
prependListener(event: "connect", listener: (session: ServerHttp2Session, socket: net.Socket | tls.TLSSocket) => void): this;
prependListener(event: "stream", listener: (stream: ServerHttp2Stream, headers: IncomingHttpHeaders, flags: number) => void): this;
prependListener(event: string | symbol, listener: (...args: any[]) => void): this;
prependOnceListener(event: "connect", listener: (session: ServerHttp2Session, socket: net.Socket | tls.TLSSocket) => void): this;
prependOnceListener(event: "stream", listener: (stream: ServerHttp2Stream, headers: IncomingHttpHeaders, flags: number) => void): this;
prependOnceListener(event: string | symbol, listener: (...args: any[]) => void): this;
}
// Http2Server
export interface SessionOptions {
maxDeflateDynamicTableSize?: number | undefined;
maxSessionMemory?: number | undefined;
maxHeaderListPairs?: number | undefined;
maxOutstandingPings?: number | undefined;
maxSendHeaderBlockLength?: number | undefined;
paddingStrategy?: number | undefined;
peerMaxConcurrentStreams?: number | undefined;
settings?: Settings | undefined;
selectPadding?(frameLen: number, maxFrameLen: number): number;
createConnection?(authority: url.URL, option: SessionOptions): stream.Duplex;
}
export interface ClientSessionOptions extends SessionOptions {
maxReservedRemoteStreams?: number | undefined;
createConnection?: ((authority: url.URL, option: SessionOptions) => stream.Duplex) | undefined;
protocol?: 'http:' | 'https:' | undefined;
}
export interface ServerSessionOptions extends SessionOptions {
Http1IncomingMessage?: typeof IncomingMessage | undefined;
Http1ServerResponse?: typeof ServerResponse | undefined;
Http2ServerRequest?: typeof Http2ServerRequest | undefined;
Http2ServerResponse?: typeof Http2ServerResponse | undefined;
}
export interface SecureClientSessionOptions extends ClientSessionOptions, tls.ConnectionOptions { }
export interface SecureServerSessionOptions extends ServerSessionOptions, tls.TlsOptions { }
export interface ServerOptions extends ServerSessionOptions { }
export interface SecureServerOptions extends SecureServerSessionOptions {
allowHTTP1?: boolean | undefined;
origins?: string[] | undefined;
}
export interface Http2Server extends net.Server {
addListener(event: "checkContinue", listener: (request: Http2ServerRequest, response: Http2ServerResponse) => void): this;
addListener(event: "request", listener: (request: Http2ServerRequest, response: Http2ServerResponse) => void): this;
addListener(event: "session", listener: (session: ServerHttp2Session) => void): this;
addListener(event: "sessionError", listener: (err: Error) => void): this;
addListener(event: "stream", listener: (stream: ServerHttp2Stream, headers: IncomingHttpHeaders, flags: number) => void): this;
addListener(event: "timeout", listener: () => void): this;
addListener(event: string | symbol, listener: (...args: any[]) => void): this;
emit(event: "checkContinue", request: Http2ServerRequest, response: Http2ServerResponse): boolean;
emit(event: "request", request: Http2ServerRequest, response: Http2ServerResponse): boolean;
emit(event: "session", session: ServerHttp2Session): boolean;
emit(event: "sessionError", err: Error): boolean;
emit(event: "stream", stream: ServerHttp2Stream, headers: IncomingHttpHeaders, flags: number): boolean;
emit(event: "timeout"): boolean;
emit(event: string | symbol, ...args: any[]): boolean;
on(event: "checkContinue", listener: (request: Http2ServerRequest, response: Http2ServerResponse) => void): this;
on(event: "request", listener: (request: Http2ServerRequest, response: Http2ServerResponse) => void): this;
on(event: "session", listener: (session: ServerHttp2Session) => void): this;
on(event: "sessionError", listener: (err: Error) => void): this;
on(event: "stream", listener: (stream: ServerHttp2Stream, headers: IncomingHttpHeaders, flags: number) => void): this;
on(event: "timeout", listener: () => void): this;
on(event: string | symbol, listener: (...args: any[]) => void): this;
once(event: "checkContinue", listener: (request: Http2ServerRequest, response: Http2ServerResponse) => void): this;
once(event: "request", listener: (request: Http2ServerRequest, response: Http2ServerResponse) => void): this;
once(event: "session", listener: (session: ServerHttp2Session) => void): this;
once(event: "sessionError", listener: (err: Error) => void): this;
once(event: "stream", listener: (stream: ServerHttp2Stream, headers: IncomingHttpHeaders, flags: number) => void): this;
once(event: "timeout", listener: () => void): this;
once(event: string | symbol, listener: (...args: any[]) => void): this;
prependListener(event: "checkContinue", listener: (request: Http2ServerRequest, response: Http2ServerResponse) => void): this;
prependListener(event: "request", listener: (request: Http2ServerRequest, response: Http2ServerResponse) => void): this;
prependListener(event: "session", listener: (session: ServerHttp2Session) => void): this;
prependListener(event: "sessionError", listener: (err: Error) => void): this;
prependListener(event: "stream", listener: (stream: ServerHttp2Stream, headers: IncomingHttpHeaders, flags: number) => void): this;
prependListener(event: "timeout", listener: () => void): this;
prependListener(event: string | symbol, listener: (...args: any[]) => void): this;
prependOnceListener(event: "checkContinue", listener: (request: Http2ServerRequest, response: Http2ServerResponse) => void): this;
prependOnceListener(event: "request", listener: (request: Http2ServerRequest, response: Http2ServerResponse) => void): this;
prependOnceListener(event: "session", listener: (session: ServerHttp2Session) => void): this;
prependOnceListener(event: "sessionError", listener: (err: Error) => void): this;
prependOnceListener(event: "stream", listener: (stream: ServerHttp2Stream, headers: IncomingHttpHeaders, flags: number) => void): this;
prependOnceListener(event: "timeout", listener: () => void): this;
prependOnceListener(event: string | symbol, listener: (...args: any[]) => void): this;
setTimeout(msec?: number, callback?: () => void): this;
}
export interface Http2SecureServer extends tls.Server {
addListener(event: "checkContinue", listener: (request: Http2ServerRequest, response: Http2ServerResponse) => void): this;
addListener(event: "request", listener: (request: Http2ServerRequest, response: Http2ServerResponse) => void): this;
addListener(event: "session", listener: (session: ServerHttp2Session) => void): this;
addListener(event: "sessionError", listener: (err: Error) => void): this;
addListener(event: "stream", listener: (stream: ServerHttp2Stream, headers: IncomingHttpHeaders, flags: number) => void): this;
addListener(event: "timeout", listener: () => void): this;
addListener(event: "unknownProtocol", listener: (socket: tls.TLSSocket) => void): this;
addListener(event: string | symbol, listener: (...args: any[]) => void): this;
emit(event: "checkContinue", request: Http2ServerRequest, response: Http2ServerResponse): boolean;
emit(event: "request", request: Http2ServerRequest, response: Http2ServerResponse): boolean;
emit(event: "session", session: ServerHttp2Session): boolean;
emit(event: "sessionError", err: Error): boolean;
emit(event: "stream", stream: ServerHttp2Stream, headers: IncomingHttpHeaders, flags: number): boolean;
emit(event: "timeout"): boolean;
emit(event: "unknownProtocol", socket: tls.TLSSocket): boolean;
emit(event: string | symbol, ...args: any[]): boolean;
on(event: "checkContinue", listener: (request: Http2ServerRequest, response: Http2ServerResponse) => void): this;
on(event: "request", listener: (request: Http2ServerRequest, response: Http2ServerResponse) => void): this;
on(event: "session", listener: (session: ServerHttp2Session) => void): this;
on(event: "sessionError", listener: (err: Error) => void): this;
on(event: "stream", listener: (stream: ServerHttp2Stream, headers: IncomingHttpHeaders, flags: number) => void): this;
on(event: "timeout", listener: () => void): this;
on(event: "unknownProtocol", listener: (socket: tls.TLSSocket) => void): this;
on(event: string | symbol, listener: (...args: any[]) => void): this;
once(event: "checkContinue", listener: (request: Http2ServerRequest, response: Http2ServerResponse) => void): this;
once(event: "request", listener: (request: Http2ServerRequest, response: Http2ServerResponse) => void): this;
once(event: "session", listener: (session: ServerHttp2Session) => void): this;
once(event: "sessionError", listener: (err: Error) => void): this;
once(event: "stream", listener: (stream: ServerHttp2Stream, headers: IncomingHttpHeaders, flags: number) => void): this;
once(event: "timeout", listener: () => void): this;
once(event: "unknownProtocol", listener: (socket: tls.TLSSocket) => void): this;
once(event: string | symbol, listener: (...args: any[]) => void): this;
prependListener(event: "checkContinue", listener: (request: Http2ServerRequest, response: Http2ServerResponse) => void): this;
prependListener(event: "request", listener: (request: Http2ServerRequest, response: Http2ServerResponse) => void): this;
prependListener(event: "session", listener: (session: ServerHttp2Session) => void): this;
prependListener(event: "sessionError", listener: (err: Error) => void): this;
prependListener(event: "stream", listener: (stream: ServerHttp2Stream, headers: IncomingHttpHeaders, flags: number) => void): this;
prependListener(event: "timeout", listener: () => void): this;
prependListener(event: "unknownProtocol", listener: (socket: tls.TLSSocket) => void): this;
prependListener(event: string | symbol, listener: (...args: any[]) => void): this;
prependOnceListener(event: "checkContinue", listener: (request: Http2ServerRequest, response: Http2ServerResponse) => void): this;
prependOnceListener(event: "request", listener: (request: Http2ServerRequest, response: Http2ServerResponse) => void): this;
prependOnceListener(event: "session", listener: (session: ServerHttp2Session) => void): this;
prependOnceListener(event: "sessionError", listener: (err: Error) => void): this;
prependOnceListener(event: "stream", listener: (stream: ServerHttp2Stream, headers: IncomingHttpHeaders, flags: number) => void): this;
prependOnceListener(event: "timeout", listener: () => void): this;
prependOnceListener(event: "unknownProtocol", listener: (socket: tls.TLSSocket) => void): this;
prependOnceListener(event: string | symbol, listener: (...args: any[]) => void): this;
setTimeout(msec?: number, callback?: () => void): this;
}
export class Http2ServerRequest extends stream.Readable {
constructor(stream: ServerHttp2Stream, headers: IncomingHttpHeaders, options: stream.ReadableOptions, rawHeaders: ReadonlyArray<string>);
readonly aborted: boolean;
readonly authority: string;
readonly connection: net.Socket | tls.TLSSocket;
readonly complete: boolean;
readonly headers: IncomingHttpHeaders;
readonly httpVersion: string;
readonly httpVersionMinor: number;
readonly httpVersionMajor: number;
readonly method: string;
readonly rawHeaders: string[];
readonly rawTrailers: string[];
readonly scheme: string;
readonly socket: net.Socket | tls.TLSSocket;
readonly stream: ServerHttp2Stream;
readonly trailers: IncomingHttpHeaders;
readonly url: string;
setTimeout(msecs: number, callback?: () => void): void;
read(size?: number): Buffer | string | null;
addListener(event: "aborted", listener: (hadError: boolean, code: number) => void): this;
addListener(event: "close", listener: () => void): this;
addListener(event: "data", listener: (chunk: Buffer | string) => void): this;
addListener(event: "end", listener: () => void): this;
addListener(event: "readable", listener: () => void): this;
addListener(event: "error", listener: (err: Error) => void): this;
addListener(event: string | symbol, listener: (...args: any[]) => void): this;
emit(event: "aborted", hadError: boolean, code: number): boolean;
emit(event: "close"): boolean;
emit(event: "data", chunk: Buffer | string): boolean;
emit(event: "end"): boolean;
emit(event: "readable"): boolean;
emit(event: "error", err: Error): boolean;
emit(event: string | symbol, ...args: any[]): boolean;
on(event: "aborted", listener: (hadError: boolean, code: number) => void): this;
on(event: "close", listener: () => void): this;
on(event: "data", listener: (chunk: Buffer | string) => void): this;
on(event: "end", listener: () => void): this;
on(event: "readable", listener: () => void): this;
on(event: "error", listener: (err: Error) => void): this;
on(event: string | symbol, listener: (...args: any[]) => void): this;
once(event: "aborted", listener: (hadError: boolean, code: number) => void): this;
once(event: "close", listener: () => void): this;
once(event: "data", listener: (chunk: Buffer | string) => void): this;
once(event: "end", listener: () => void): this;
once(event: "readable", listener: () => void): this;
once(event: "error", listener: (err: Error) => void): this;
once(event: string | symbol, listener: (...args: any[]) => void): this;
prependListener(event: "aborted", listener: (hadError: boolean, code: number) => void): this;
prependListener(event: "close", listener: () => void): this;
prependListener(event: "data", listener: (chunk: Buffer | string) => void): this;
prependListener(event: "end", listener: () => void): this;
prependListener(event: "readable", listener: () => void): this;
prependListener(event: "error", listener: (err: Error) => void): this;
prependListener(event: string | symbol, listener: (...args: any[]) => void): this;
prependOnceListener(event: "aborted", listener: (hadError: boolean, code: number) => void): this;
prependOnceListener(event: "close", listener: () => void): this;
prependOnceListener(event: "data", listener: (chunk: Buffer | string) => void): this;
prependOnceListener(event: "end", listener: () => void): this;
prependOnceListener(event: "readable", listener: () => void): this;
prependOnceListener(event: "error", listener: (err: Error) => void): this;
prependOnceListener(event: string | symbol, listener: (...args: any[]) => void): this;
}
export class Http2ServerResponse extends stream.Writable {
constructor(stream: ServerHttp2Stream);
readonly connection: net.Socket | tls.TLSSocket;
readonly finished: boolean;
readonly headersSent: boolean;
readonly socket: net.Socket | tls.TLSSocket;
readonly stream: ServerHttp2Stream;
sendDate: boolean;
statusCode: number;
statusMessage: '';
addTrailers(trailers: OutgoingHttpHeaders): void;
end(callback?: () => void): void;
end(data: string | Uint8Array, callback?: () => void): void;
end(data: string | Uint8Array, encoding: BufferEncoding, callback?: () => void): void;
getHeader(name: string): string;
getHeaderNames(): string[];
getHeaders(): OutgoingHttpHeaders;
hasHeader(name: string): boolean;
removeHeader(name: string): void;
setHeader(name: string, value: number | string | ReadonlyArray<string>): void;
setTimeout(msecs: number, callback?: () => void): void;
write(chunk: string | Uint8Array, callback?: (err: Error) => void): boolean;
write(chunk: string | Uint8Array, encoding: BufferEncoding, callback?: (err: Error) => void): boolean;
writeContinue(): void;
writeHead(statusCode: number, headers?: OutgoingHttpHeaders): this;
writeHead(statusCode: number, statusMessage: string, headers?: OutgoingHttpHeaders): this;
createPushResponse(headers: OutgoingHttpHeaders, callback: (err: Error | null, res: Http2ServerResponse) => void): void;
addListener(event: "close", listener: () => void): this;
addListener(event: "drain", listener: () => void): this;
addListener(event: "error", listener: (error: Error) => void): this;
addListener(event: "finish", listener: () => void): this;
addListener(event: "pipe", listener: (src: stream.Readable) => void): this;
addListener(event: "unpipe", listener: (src: stream.Readable) => void): this;
addListener(event: string | symbol, listener: (...args: any[]) => void): this;
emit(event: "close"): boolean;
emit(event: "drain"): boolean;
emit(event: "error", error: Error): boolean;
emit(event: "finish"): boolean;
emit(event: "pipe", src: stream.Readable): boolean;
emit(event: "unpipe", src: stream.Readable): boolean;
emit(event: string | symbol, ...args: any[]): boolean;
on(event: "close", listener: () => void): this;
on(event: "drain", listener: () => void): this;
on(event: "error", listener: (error: Error) => void): this;
on(event: "finish", listener: () => void): this;
on(event: "pipe", listener: (src: stream.Readable) => void): this;
on(event: "unpipe", listener: (src: stream.Readable) => void): this;
on(event: string | symbol, listener: (...args: any[]) => void): this;
once(event: "close", listener: () => void): this;
once(event: "drain", listener: () => void): this;
once(event: "error", listener: (error: Error) => void): this;
once(event: "finish", listener: () => void): this;
once(event: "pipe", listener: (src: stream.Readable) => void): this;
once(event: "unpipe", listener: (src: stream.Readable) => void): this;
once(event: string | symbol, listener: (...args: any[]) => void): this;
prependListener(event: "close", listener: () => void): this;
prependListener(event: "drain", listener: () => void): this;
prependListener(event: "error", listener: (error: Error) => void): this;
prependListener(event: "finish", listener: () => void): this;
prependListener(event: "pipe", listener: (src: stream.Readable) => void): this;
prependListener(event: "unpipe", listener: (src: stream.Readable) => void): this;
prependListener(event: string | symbol, listener: (...args: any[]) => void): this;
prependOnceListener(event: "close", listener: () => void): this;
prependOnceListener(event: "drain", listener: () => void): this;
prependOnceListener(event: "error", listener: (error: Error) => void): this;
prependOnceListener(event: "finish", listener: () => void): this;
prependOnceListener(event: "pipe", listener: (src: stream.Readable) => void): this;
prependOnceListener(event: "unpipe", listener: (src: stream.Readable) => void): this;
prependOnceListener(event: string | symbol, listener: (...args: any[]) => void): this;
}
// Public API
export namespace constants {
const NGHTTP2_SESSION_SERVER: number;
const NGHTTP2_SESSION_CLIENT: number;
const NGHTTP2_STREAM_STATE_IDLE: number;
const NGHTTP2_STREAM_STATE_OPEN: number;
const NGHTTP2_STREAM_STATE_RESERVED_LOCAL: number;
const NGHTTP2_STREAM_STATE_RESERVED_REMOTE: number;
const NGHTTP2_STREAM_STATE_HALF_CLOSED_LOCAL: number;
const NGHTTP2_STREAM_STATE_HALF_CLOSED_REMOTE: number;
const NGHTTP2_STREAM_STATE_CLOSED: number;
const NGHTTP2_NO_ERROR: number;
const NGHTTP2_PROTOCOL_ERROR: number;
const NGHTTP2_INTERNAL_ERROR: number;
const NGHTTP2_FLOW_CONTROL_ERROR: number;
const NGHTTP2_SETTINGS_TIMEOUT: number;
const NGHTTP2_STREAM_CLOSED: number;
const NGHTTP2_FRAME_SIZE_ERROR: number;
const NGHTTP2_REFUSED_STREAM: number;
const NGHTTP2_CANCEL: number;
const NGHTTP2_COMPRESSION_ERROR: number;
const NGHTTP2_CONNECT_ERROR: number;
const NGHTTP2_ENHANCE_YOUR_CALM: number;
const NGHTTP2_INADEQUATE_SECURITY: number;
const NGHTTP2_HTTP_1_1_REQUIRED: number;
const NGHTTP2_ERR_FRAME_SIZE_ERROR: number;
const NGHTTP2_FLAG_NONE: number;
const NGHTTP2_FLAG_END_STREAM: number;
const NGHTTP2_FLAG_END_HEADERS: number;
const NGHTTP2_FLAG_ACK: number;
const NGHTTP2_FLAG_PADDED: number;
const NGHTTP2_FLAG_PRIORITY: number;
const DEFAULT_SETTINGS_HEADER_TABLE_SIZE: number;
const DEFAULT_SETTINGS_ENABLE_PUSH: number;
const DEFAULT_SETTINGS_INITIAL_WINDOW_SIZE: number;
const DEFAULT_SETTINGS_MAX_FRAME_SIZE: number;
const MAX_MAX_FRAME_SIZE: number;
const MIN_MAX_FRAME_SIZE: number;
const MAX_INITIAL_WINDOW_SIZE: number;
const NGHTTP2_DEFAULT_WEIGHT: number;
const NGHTTP2_SETTINGS_HEADER_TABLE_SIZE: number;
const NGHTTP2_SETTINGS_ENABLE_PUSH: number;
const NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS: number;
const NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE: number;
const NGHTTP2_SETTINGS_MAX_FRAME_SIZE: number;
const NGHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE: number;
const PADDING_STRATEGY_NONE: number;
const PADDING_STRATEGY_MAX: number;
const PADDING_STRATEGY_CALLBACK: number;
const HTTP2_HEADER_STATUS: string;
const HTTP2_HEADER_METHOD: string;
const HTTP2_HEADER_AUTHORITY: string;
const HTTP2_HEADER_SCHEME: string;
const HTTP2_HEADER_PATH: string;
const HTTP2_HEADER_ACCEPT_CHARSET: string;
const HTTP2_HEADER_ACCEPT_ENCODING: string;
const HTTP2_HEADER_ACCEPT_LANGUAGE: string;
const HTTP2_HEADER_ACCEPT_RANGES: string;
const HTTP2_HEADER_ACCEPT: string;
const HTTP2_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN: string;
const HTTP2_HEADER_AGE: string;
const HTTP2_HEADER_ALLOW: string;
const HTTP2_HEADER_AUTHORIZATION: string;
const HTTP2_HEADER_CACHE_CONTROL: string;
const HTTP2_HEADER_CONNECTION: string;
const HTTP2_HEADER_CONTENT_DISPOSITION: string;
const HTTP2_HEADER_CONTENT_ENCODING: string;
const HTTP2_HEADER_CONTENT_LANGUAGE: string;
const HTTP2_HEADER_CONTENT_LENGTH: string;
const HTTP2_HEADER_CONTENT_LOCATION: string;
const HTTP2_HEADER_CONTENT_MD5: string;
const HTTP2_HEADER_CONTENT_RANGE: string;
const HTTP2_HEADER_CONTENT_TYPE: string;
const HTTP2_HEADER_COOKIE: string;
const HTTP2_HEADER_DATE: string;
const HTTP2_HEADER_ETAG: string;
const HTTP2_HEADER_EXPECT: string;
const HTTP2_HEADER_EXPIRES: string;
const HTTP2_HEADER_FROM: string;
const HTTP2_HEADER_HOST: string;
const HTTP2_HEADER_IF_MATCH: string;
const HTTP2_HEADER_IF_MODIFIED_SINCE: string;
const HTTP2_HEADER_IF_NONE_MATCH: string;
const HTTP2_HEADER_IF_RANGE: string;
const HTTP2_HEADER_IF_UNMODIFIED_SINCE: string;
const HTTP2_HEADER_LAST_MODIFIED: string;
const HTTP2_HEADER_LINK: string;
const HTTP2_HEADER_LOCATION: string;
const HTTP2_HEADER_MAX_FORWARDS: string;
const HTTP2_HEADER_PREFER: string;
const HTTP2_HEADER_PROXY_AUTHENTICATE: string;
const HTTP2_HEADER_PROXY_AUTHORIZATION: string;
const HTTP2_HEADER_RANGE: string;
const HTTP2_HEADER_REFERER: string;
const HTTP2_HEADER_REFRESH: string;
const HTTP2_HEADER_RETRY_AFTER: string;
const HTTP2_HEADER_SERVER: string;
const HTTP2_HEADER_SET_COOKIE: string;
const HTTP2_HEADER_STRICT_TRANSPORT_SECURITY: string;
const HTTP2_HEADER_TRANSFER_ENCODING: string;
const HTTP2_HEADER_TE: string;
const HTTP2_HEADER_UPGRADE: string;
const HTTP2_HEADER_USER_AGENT: string;
const HTTP2_HEADER_VARY: string;
const HTTP2_HEADER_VIA: string;
const HTTP2_HEADER_WWW_AUTHENTICATE: string;
const HTTP2_HEADER_HTTP2_SETTINGS: string;
const HTTP2_HEADER_KEEP_ALIVE: string;
const HTTP2_HEADER_PROXY_CONNECTION: string;
const HTTP2_METHOD_ACL: string;
const HTTP2_METHOD_BASELINE_CONTROL: string;
const HTTP2_METHOD_BIND: string;
const HTTP2_METHOD_CHECKIN: string;
const HTTP2_METHOD_CHECKOUT: string;
const HTTP2_METHOD_CONNECT: string;
const HTTP2_METHOD_COPY: string;
const HTTP2_METHOD_DELETE: string;
const HTTP2_METHOD_GET: string;
const HTTP2_METHOD_HEAD: string;
const HTTP2_METHOD_LABEL: string;
const HTTP2_METHOD_LINK: string;
const HTTP2_METHOD_LOCK: string;
const HTTP2_METHOD_MERGE: string;
const HTTP2_METHOD_MKACTIVITY: string;
const HTTP2_METHOD_MKCALENDAR: string;
const HTTP2_METHOD_MKCOL: string;
const HTTP2_METHOD_MKREDIRECTREF: string;
const HTTP2_METHOD_MKWORKSPACE: string;
const HTTP2_METHOD_MOVE: string;
const HTTP2_METHOD_OPTIONS: string;
const HTTP2_METHOD_ORDERPATCH: string;
const HTTP2_METHOD_PATCH: string;
const HTTP2_METHOD_POST: string;
const HTTP2_METHOD_PRI: string;
const HTTP2_METHOD_PROPFIND: string;
const HTTP2_METHOD_PROPPATCH: string;
const HTTP2_METHOD_PUT: string;
const HTTP2_METHOD_REBIND: string;
const HTTP2_METHOD_REPORT: string;
const HTTP2_METHOD_SEARCH: string;
const HTTP2_METHOD_TRACE: string;
const HTTP2_METHOD_UNBIND: string;
const HTTP2_METHOD_UNCHECKOUT: string;
const HTTP2_METHOD_UNLINK: string;
const HTTP2_METHOD_UNLOCK: string;
const HTTP2_METHOD_UPDATE: string;
const HTTP2_METHOD_UPDATEREDIRECTREF: string;
const HTTP2_METHOD_VERSION_CONTROL: string;
const HTTP_STATUS_CONTINUE: number;
const HTTP_STATUS_SWITCHING_PROTOCOLS: number;
const HTTP_STATUS_PROCESSING: number;
const HTTP_STATUS_OK: number;
const HTTP_STATUS_CREATED: number;
const HTTP_STATUS_ACCEPTED: number;
const HTTP_STATUS_NON_AUTHORITATIVE_INFORMATION: number;
const HTTP_STATUS_NO_CONTENT: number;
const HTTP_STATUS_RESET_CONTENT: number;
const HTTP_STATUS_PARTIAL_CONTENT: number;
const HTTP_STATUS_MULTI_STATUS: number;
const HTTP_STATUS_ALREADY_REPORTED: number;
const HTTP_STATUS_IM_USED: number;
const HTTP_STATUS_MULTIPLE_CHOICES: number;
const HTTP_STATUS_MOVED_PERMANENTLY: number;
const HTTP_STATUS_FOUND: number;
const HTTP_STATUS_SEE_OTHER: number;
const HTTP_STATUS_NOT_MODIFIED: number;
const HTTP_STATUS_USE_PROXY: number;
const HTTP_STATUS_TEMPORARY_REDIRECT: number;
const HTTP_STATUS_PERMANENT_REDIRECT: number;
const HTTP_STATUS_BAD_REQUEST: number;
const HTTP_STATUS_UNAUTHORIZED: number;
const HTTP_STATUS_PAYMENT_REQUIRED: number;
const HTTP_STATUS_FORBIDDEN: number;
const HTTP_STATUS_NOT_FOUND: number;
const HTTP_STATUS_METHOD_NOT_ALLOWED: number;
const HTTP_STATUS_NOT_ACCEPTABLE: number;
const HTTP_STATUS_PROXY_AUTHENTICATION_REQUIRED: number;
const HTTP_STATUS_REQUEST_TIMEOUT: number;
const HTTP_STATUS_CONFLICT: number;
const HTTP_STATUS_GONE: number;
const HTTP_STATUS_LENGTH_REQUIRED: number;
const HTTP_STATUS_PRECONDITION_FAILED: number;
const HTTP_STATUS_PAYLOAD_TOO_LARGE: number;
const HTTP_STATUS_URI_TOO_LONG: number;
const HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE: number;
const HTTP_STATUS_RANGE_NOT_SATISFIABLE: number;
const HTTP_STATUS_EXPECTATION_FAILED: number;
const HTTP_STATUS_TEAPOT: number;
const HTTP_STATUS_MISDIRECTED_REQUEST: number;
const HTTP_STATUS_UNPROCESSABLE_ENTITY: number;
const HTTP_STATUS_LOCKED: number;
const HTTP_STATUS_FAILED_DEPENDENCY: number;
const HTTP_STATUS_UNORDERED_COLLECTION: number;
const HTTP_STATUS_UPGRADE_REQUIRED: number;
const HTTP_STATUS_PRECONDITION_REQUIRED: number;
const HTTP_STATUS_TOO_MANY_REQUESTS: number;
const HTTP_STATUS_REQUEST_HEADER_FIELDS_TOO_LARGE: number;
const HTTP_STATUS_UNAVAILABLE_FOR_LEGAL_REASONS: number;
const HTTP_STATUS_INTERNAL_SERVER_ERROR: number;
const HTTP_STATUS_NOT_IMPLEMENTED: number;
const HTTP_STATUS_BAD_GATEWAY: number;
const HTTP_STATUS_SERVICE_UNAVAILABLE: number;
const HTTP_STATUS_GATEWAY_TIMEOUT: number;
const HTTP_STATUS_HTTP_VERSION_NOT_SUPPORTED: number;
const HTTP_STATUS_VARIANT_ALSO_NEGOTIATES: number;
const HTTP_STATUS_INSUFFICIENT_STORAGE: number;
const HTTP_STATUS_LOOP_DETECTED: number;
const HTTP_STATUS_BANDWIDTH_LIMIT_EXCEEDED: number;
const HTTP_STATUS_NOT_EXTENDED: number;
const HTTP_STATUS_NETWORK_AUTHENTICATION_REQUIRED: number;
}
export function getDefaultSettings(): Settings;
export function getPackedSettings(settings: Settings): Buffer;
export function getUnpackedSettings(buf: Uint8Array): Settings;
export function createServer(onRequestHandler?: (request: Http2ServerRequest, response: Http2ServerResponse) => void): Http2Server;
export function createServer(options: ServerOptions, onRequestHandler?: (request: Http2ServerRequest, response: Http2ServerResponse) => void): Http2Server;
export function createSecureServer(onRequestHandler?: (request: Http2ServerRequest, response: Http2ServerResponse) => void): Http2SecureServer;
export function createSecureServer(options: SecureServerOptions, onRequestHandler?: (request: Http2ServerRequest, response: Http2ServerResponse) => void): Http2SecureServer;
export function connect(authority: string | url.URL, listener: (session: ClientHttp2Session, socket: net.Socket | tls.TLSSocket) => void): ClientHttp2Session;
export function connect(
authority: string | url.URL,
options?: ClientSessionOptions | SecureClientSessionOptions,
listener?: (session: ClientHttp2Session, socket: net.Socket | tls.TLSSocket) => void
): ClientHttp2Session;
}

View File

@ -0,0 +1,142 @@
/* NOTE: Do not edit directly! This file is generated using `npm run update-types` in https://github.com/node-red/nr-monaco-build */
declare module 'https' {
import { Duplex } from 'stream';
import * as tls from 'tls';
import * as http from 'http';
import { URL } from 'url';
type ServerOptions = tls.SecureContextOptions & tls.TlsOptions & http.ServerOptions;
type RequestOptions = http.RequestOptions & tls.SecureContextOptions & {
rejectUnauthorized?: boolean | undefined; // Defaults to true
servername?: string | undefined; // SNI TLS Extension
};
interface AgentOptions extends http.AgentOptions, tls.ConnectionOptions {
rejectUnauthorized?: boolean | undefined;
maxCachedSessions?: number | undefined;
}
class Agent extends http.Agent {
constructor(options?: AgentOptions);
options: AgentOptions;
}
interface Server extends http.Server {}
class Server extends tls.Server {
constructor(requestListener?: http.RequestListener);
constructor(options: ServerOptions, requestListener?: http.RequestListener);
addListener(event: string, listener: (...args: any[]) => void): this;
addListener(event: 'keylog', listener: (line: Buffer, tlsSocket: tls.TLSSocket) => void): this;
addListener(event: 'newSession', listener: (sessionId: Buffer, sessionData: Buffer, callback: (err: Error, resp: Buffer) => void) => void): this;
addListener(event: 'OCSPRequest', listener: (certificate: Buffer, issuer: Buffer, callback: (err: Error | null, resp: Buffer) => void) => void): this;
addListener(event: 'resumeSession', listener: (sessionId: Buffer, callback: (err: Error, sessionData: Buffer) => void) => void): this;
addListener(event: 'secureConnection', listener: (tlsSocket: tls.TLSSocket) => void): this;
addListener(event: 'tlsClientError', listener: (err: Error, tlsSocket: tls.TLSSocket) => void): this;
addListener(event: 'close', listener: () => void): this;
addListener(event: 'connection', listener: (socket: Duplex) => void): this;
addListener(event: 'error', listener: (err: Error) => void): this;
addListener(event: 'listening', listener: () => void): this;
addListener(event: 'checkContinue', listener: http.RequestListener): this;
addListener(event: 'checkExpectation', listener: http.RequestListener): this;
addListener(event: 'clientError', listener: (err: Error, socket: Duplex) => void): this;
addListener(event: 'connect', listener: (req: http.IncomingMessage, socket: Duplex, head: Buffer) => void): this;
addListener(event: 'request', listener: http.RequestListener): this;
addListener(event: 'upgrade', listener: (req: http.IncomingMessage, socket: Duplex, head: Buffer) => void): this;
emit(event: string, ...args: any[]): boolean;
emit(event: 'keylog', line: Buffer, tlsSocket: tls.TLSSocket): boolean;
emit(event: 'newSession', sessionId: Buffer, sessionData: Buffer, callback: (err: Error, resp: Buffer) => void): boolean;
emit(event: 'OCSPRequest', certificate: Buffer, issuer: Buffer, callback: (err: Error | null, resp: Buffer) => void): boolean;
emit(event: 'resumeSession', sessionId: Buffer, callback: (err: Error, sessionData: Buffer) => void): boolean;
emit(event: 'secureConnection', tlsSocket: tls.TLSSocket): boolean;
emit(event: 'tlsClientError', err: Error, tlsSocket: tls.TLSSocket): boolean;
emit(event: 'close'): boolean;
emit(event: 'connection', socket: Duplex): boolean;
emit(event: 'error', err: Error): boolean;
emit(event: 'listening'): boolean;
emit(event: 'checkContinue', req: http.IncomingMessage, res: http.ServerResponse): boolean;
emit(event: 'checkExpectation', req: http.IncomingMessage, res: http.ServerResponse): boolean;
emit(event: 'clientError', err: Error, socket: Duplex): boolean;
emit(event: 'connect', req: http.IncomingMessage, socket: Duplex, head: Buffer): boolean;
emit(event: 'request', req: http.IncomingMessage, res: http.ServerResponse): boolean;
emit(event: 'upgrade', req: http.IncomingMessage, socket: Duplex, head: Buffer): boolean;
on(event: string, listener: (...args: any[]) => void): this;
on(event: 'keylog', listener: (line: Buffer, tlsSocket: tls.TLSSocket) => void): this;
on(event: 'newSession', listener: (sessionId: Buffer, sessionData: Buffer, callback: (err: Error, resp: Buffer) => void) => void): this;
on(event: 'OCSPRequest', listener: (certificate: Buffer, issuer: Buffer, callback: (err: Error | null, resp: Buffer) => void) => void): this;
on(event: 'resumeSession', listener: (sessionId: Buffer, callback: (err: Error, sessionData: Buffer) => void) => void): this;
on(event: 'secureConnection', listener: (tlsSocket: tls.TLSSocket) => void): this;
on(event: 'tlsClientError', listener: (err: Error, tlsSocket: tls.TLSSocket) => void): this;
on(event: 'close', listener: () => void): this;
on(event: 'connection', listener: (socket: Duplex) => void): this;
on(event: 'error', listener: (err: Error) => void): this;
on(event: 'listening', listener: () => void): this;
on(event: 'checkContinue', listener: http.RequestListener): this;
on(event: 'checkExpectation', listener: http.RequestListener): this;
on(event: 'clientError', listener: (err: Error, socket: Duplex) => void): this;
on(event: 'connect', listener: (req: http.IncomingMessage, socket: Duplex, head: Buffer) => void): this;
on(event: 'request', listener: http.RequestListener): this;
on(event: 'upgrade', listener: (req: http.IncomingMessage, socket: Duplex, head: Buffer) => void): this;
once(event: string, listener: (...args: any[]) => void): this;
once(event: 'keylog', listener: (line: Buffer, tlsSocket: tls.TLSSocket) => void): this;
once(event: 'newSession', listener: (sessionId: Buffer, sessionData: Buffer, callback: (err: Error, resp: Buffer) => void) => void): this;
once(event: 'OCSPRequest', listener: (certificate: Buffer, issuer: Buffer, callback: (err: Error | null, resp: Buffer) => void) => void): this;
once(event: 'resumeSession', listener: (sessionId: Buffer, callback: (err: Error, sessionData: Buffer) => void) => void): this;
once(event: 'secureConnection', listener: (tlsSocket: tls.TLSSocket) => void): this;
once(event: 'tlsClientError', listener: (err: Error, tlsSocket: tls.TLSSocket) => void): this;
once(event: 'close', listener: () => void): this;
once(event: 'connection', listener: (socket: Duplex) => void): this;
once(event: 'error', listener: (err: Error) => void): this;
once(event: 'listening', listener: () => void): this;
once(event: 'checkContinue', listener: http.RequestListener): this;
once(event: 'checkExpectation', listener: http.RequestListener): this;
once(event: 'clientError', listener: (err: Error, socket: Duplex) => void): this;
once(event: 'connect', listener: (req: http.IncomingMessage, socket: Duplex, head: Buffer) => void): this;
once(event: 'request', listener: http.RequestListener): this;
once(event: 'upgrade', listener: (req: http.IncomingMessage, socket: Duplex, head: Buffer) => void): this;
prependListener(event: string, listener: (...args: any[]) => void): this;
prependListener(event: 'keylog', listener: (line: Buffer, tlsSocket: tls.TLSSocket) => void): this;
prependListener(event: 'newSession', listener: (sessionId: Buffer, sessionData: Buffer, callback: (err: Error, resp: Buffer) => void) => void): this;
prependListener(event: 'OCSPRequest', listener: (certificate: Buffer, issuer: Buffer, callback: (err: Error | null, resp: Buffer) => void) => void): this;
prependListener(event: 'resumeSession', listener: (sessionId: Buffer, callback: (err: Error, sessionData: Buffer) => void) => void): this;
prependListener(event: 'secureConnection', listener: (tlsSocket: tls.TLSSocket) => void): this;
prependListener(event: 'tlsClientError', listener: (err: Error, tlsSocket: tls.TLSSocket) => void): this;
prependListener(event: 'close', listener: () => void): this;
prependListener(event: 'connection', listener: (socket: Duplex) => void): this;
prependListener(event: 'error', listener: (err: Error) => void): this;
prependListener(event: 'listening', listener: () => void): this;
prependListener(event: 'checkContinue', listener: http.RequestListener): this;
prependListener(event: 'checkExpectation', listener: http.RequestListener): this;
prependListener(event: 'clientError', listener: (err: Error, socket: Duplex) => void): this;
prependListener(event: 'connect', listener: (req: http.IncomingMessage, socket: Duplex, head: Buffer) => void): this;
prependListener(event: 'request', listener: http.RequestListener): this;
prependListener(event: 'upgrade', listener: (req: http.IncomingMessage, socket: Duplex, head: Buffer) => void): this;
prependOnceListener(event: string, listener: (...args: any[]) => void): this;
prependOnceListener(event: 'keylog', listener: (line: Buffer, tlsSocket: tls.TLSSocket) => void): this;
prependOnceListener(event: 'newSession', listener: (sessionId: Buffer, sessionData: Buffer, callback: (err: Error, resp: Buffer) => void) => void): this;
prependOnceListener(event: 'OCSPRequest', listener: (certificate: Buffer, issuer: Buffer, callback: (err: Error | null, resp: Buffer) => void) => void): this;
prependOnceListener(event: 'resumeSession', listener: (sessionId: Buffer, callback: (err: Error, sessionData: Buffer) => void) => void): this;
prependOnceListener(event: 'secureConnection', listener: (tlsSocket: tls.TLSSocket) => void): this;
prependOnceListener(event: 'tlsClientError', listener: (err: Error, tlsSocket: tls.TLSSocket) => void): this;
prependOnceListener(event: 'close', listener: () => void): this;
prependOnceListener(event: 'connection', listener: (socket: Duplex) => void): this;
prependOnceListener(event: 'error', listener: (err: Error) => void): this;
prependOnceListener(event: 'listening', listener: () => void): this;
prependOnceListener(event: 'checkContinue', listener: http.RequestListener): this;
prependOnceListener(event: 'checkExpectation', listener: http.RequestListener): this;
prependOnceListener(event: 'clientError', listener: (err: Error, socket: Duplex) => void): this;
prependOnceListener(event: 'connect', listener: (req: http.IncomingMessage, socket: Duplex, head: Buffer) => void): this;
prependOnceListener(event: 'request', listener: http.RequestListener): this;
prependOnceListener(event: 'upgrade', listener: (req: http.IncomingMessage, socket: Duplex, head: Buffer) => void): this;
}
function createServer(requestListener?: http.RequestListener): Server;
function createServer(options: ServerOptions, requestListener?: http.RequestListener): Server;
function request(options: RequestOptions | string | URL, callback?: (res: http.IncomingMessage) => void): http.ClientRequest;
function request(url: string | URL, options: RequestOptions, callback?: (res: http.IncomingMessage) => void): http.ClientRequest;
function get(options: RequestOptions | string | URL, callback?: (res: http.IncomingMessage) => void): http.ClientRequest;
function get(url: string | URL, options: RequestOptions, callback?: (res: http.IncomingMessage) => void): http.ClientRequest;
let globalAgent: Agent;
}

View File

@ -0,0 +1,55 @@
/* NOTE: Do not edit directly! This file is generated using `npm run update-types` in https://github.com/node-red/nr-monaco-build */
declare module 'module' {
import { URL } from 'url';
namespace Module {
/**
* Updates all the live bindings for builtin ES Modules to match the properties of the CommonJS exports.
* It does not add or remove exported names from the ES Modules.
*/
function syncBuiltinESMExports(): void;
function findSourceMap(path: string, error?: Error): SourceMap;
interface SourceMapPayload {
file: string;
version: number;
sources: string[];
sourcesContent: string[];
names: string[];
mappings: string;
sourceRoot: string;
}
interface SourceMapping {
generatedLine: number;
generatedColumn: number;
originalSource: string;
originalLine: number;
originalColumn: number;
}
class SourceMap {
readonly payload: SourceMapPayload;
constructor(payload: SourceMapPayload);
findEntry(line: number, column: number): SourceMapping;
}
}
interface Module extends NodeModule {}
class Module {
static runMain(): void;
static wrap(code: string): string;
/**
* @deprecated Deprecated since: v12.2.0. Please use createRequire() instead.
*/
static createRequireFromPath(path: string): NodeRequire;
static createRequire(path: string | URL): NodeRequire;
static builtinModules: string[];
static Module: typeof Module;
constructor(id: string, parent?: Module);
}
export = Module;
}

File diff suppressed because one or more lines are too long

View File

@ -1 +1,242 @@
declare module'node:os'{export*from'os';}declare module'os'{interface CpuInfo{model:string;speed:number;times:{user:number;nice:number;sys:number;idle:number;irq:number;};}interface NetworkInterfaceBase{address:string;netmask:string;mac:string;internal:boolean;cidr:string|null;}interface NetworkInterfaceInfoIPv4 extends NetworkInterfaceBase{family:"IPv4";}interface NetworkInterfaceInfoIPv6 extends NetworkInterfaceBase{family:"IPv6";scopeid:number;}interface UserInfo<T>{username:T;uid:number;gid:number;shell:T;homedir:T;}type NetworkInterfaceInfo=NetworkInterfaceInfoIPv4|NetworkInterfaceInfoIPv6;function hostname():string;function loadavg():number[];function uptime():number;function freemem():number;function totalmem():number;function cpus():CpuInfo[];function type():string;function release():string;function networkInterfaces():NodeJS.Dict<NetworkInterfaceInfo[]>;function homedir():string;function userInfo(options:{encoding:'buffer'}):UserInfo<Buffer>;function userInfo(options?:{encoding:BufferEncoding}):UserInfo<string>;type SignalConstants={[key in NodeJS.Signals]:number;};namespace constants{const UV_UDP_REUSEADDR:number;namespace signals{}const signals:SignalConstants;namespace errno{const E2BIG:number;const EACCES:number;const EADDRINUSE:number;const EADDRNOTAVAIL:number;const EAFNOSUPPORT:number;const EAGAIN:number;const EALREADY:number;const EBADF:number;const EBADMSG:number;const EBUSY:number;const ECANCELED:number;const ECHILD:number;const ECONNABORTED:number;const ECONNREFUSED:number;const ECONNRESET:number;const EDEADLK:number;const EDESTADDRREQ:number;const EDOM:number;const EDQUOT:number;const EEXIST:number;const EFAULT:number;const EFBIG:number;const EHOSTUNREACH:number;const EIDRM:number;const EILSEQ:number;const EINPROGRESS:number;const EINTR:number;const EINVAL:number;const EIO:number;const EISCONN:number;const EISDIR:number;const ELOOP:number;const EMFILE:number;const EMLINK:number;const EMSGSIZE:number;const EMULTIHOP:number;const ENAMETOOLONG:number;const ENETDOWN:number;const ENETRESET:number;const ENETUNREACH:number;const ENFILE:number;const ENOBUFS:number;const ENODATA:number;const ENODEV:number;const ENOENT:number;const ENOEXEC:number;const ENOLCK:number;const ENOLINK:number;const ENOMEM:number;const ENOMSG:number;const ENOPROTOOPT:number;const ENOSPC:number;const ENOSR:number;const ENOSTR:number;const ENOSYS:number;const ENOTCONN:number;const ENOTDIR:number;const ENOTEMPTY:number;const ENOTSOCK:number;const ENOTSUP:number;const ENOTTY:number;const ENXIO:number;const EOPNOTSUPP:number;const EOVERFLOW:number;const EPERM:number;const EPIPE:number;const EPROTO:number;const EPROTONOSUPPORT:number;const EPROTOTYPE:number;const ERANGE:number;const EROFS:number;const ESPIPE:number;const ESRCH:number;const ESTALE:number;const ETIME:number;const ETIMEDOUT:number;const ETXTBSY:number;const EWOULDBLOCK:number;const EXDEV:number;const WSAEINTR:number;const WSAEBADF:number;const WSAEACCES:number;const WSAEFAULT:number;const WSAEINVAL:number;const WSAEMFILE:number;const WSAEWOULDBLOCK:number;const WSAEINPROGRESS:number;const WSAEALREADY:number;const WSAENOTSOCK:number;const WSAEDESTADDRREQ:number;const WSAEMSGSIZE:number;const WSAEPROTOTYPE:number;const WSAENOPROTOOPT:number;const WSAEPROTONOSUPPORT:number;const WSAESOCKTNOSUPPORT:number;const WSAEOPNOTSUPP:number;const WSAEPFNOSUPPORT:number;const WSAEAFNOSUPPORT:number;const WSAEADDRINUSE:number;const WSAEADDRNOTAVAIL:number;const WSAENETDOWN:number;const WSAENETUNREACH:number;const WSAENETRESET:number;const WSAECONNABORTED:number;const WSAECONNRESET:number;const WSAENOBUFS:number;const WSAEISCONN:number;const WSAENOTCONN:number;const WSAESHUTDOWN:number;const WSAETOOMANYREFS:number;const WSAETIMEDOUT:number;const WSAECONNREFUSED:number;const WSAELOOP:number;const WSAENAMETOOLONG:number;const WSAEHOSTDOWN:number;const WSAEHOSTUNREACH:number;const WSAENOTEMPTY:number;const WSAEPROCLIM:number;const WSAEUSERS:number;const WSAEDQUOT:number;const WSAESTALE:number;const WSAEREMOTE:number;const WSASYSNOTREADY:number;const WSAVERNOTSUPPORTED:number;const WSANOTINITIALISED:number;const WSAEDISCON:number;const WSAENOMORE:number;const WSAECANCELLED:number;const WSAEINVALIDPROCTABLE:number;const WSAEINVALIDPROVIDER:number;const WSAEPROVIDERFAILEDINIT:number;const WSASYSCALLFAILURE:number;const WSASERVICE_NOT_FOUND:number;const WSATYPE_NOT_FOUND:number;const WSA_E_NO_MORE:number;const WSA_E_CANCELLED:number;const WSAEREFUSED:number;}namespace priority{const PRIORITY_LOW:number;const PRIORITY_BELOW_NORMAL:number;const PRIORITY_NORMAL:number;const PRIORITY_ABOVE_NORMAL:number;const PRIORITY_HIGH:number;const PRIORITY_HIGHEST:number;}}function arch():string;function version():string;function platform():NodeJS.Platform;function tmpdir():string;const EOL:string;function endianness():"BE"|"LE";function getPriority(pid?:number):number;function setPriority(priority:number):void;function setPriority(pid:number,priority:number):void;}
/* NOTE: Do not edit directly! This file is generated using `npm run update-types` in https://github.com/node-red/nr-monaco-build */
declare module 'os' {
interface CpuInfo {
model: string;
speed: number;
times: {
user: number;
nice: number;
sys: number;
idle: number;
irq: number;
};
}
interface NetworkInterfaceBase {
address: string;
netmask: string;
mac: string;
internal: boolean;
cidr: string | null;
}
interface NetworkInterfaceInfoIPv4 extends NetworkInterfaceBase {
family: "IPv4";
}
interface NetworkInterfaceInfoIPv6 extends NetworkInterfaceBase {
family: "IPv6";
scopeid: number;
}
interface UserInfo<T> {
username: T;
uid: number;
gid: number;
shell: T;
homedir: T;
}
type NetworkInterfaceInfo = NetworkInterfaceInfoIPv4 | NetworkInterfaceInfoIPv6;
function hostname(): string;
function loadavg(): number[];
function uptime(): number;
function freemem(): number;
function totalmem(): number;
function cpus(): CpuInfo[];
function type(): string;
function release(): string;
function networkInterfaces(): NodeJS.Dict<NetworkInterfaceInfo[]>;
function homedir(): string;
function userInfo(options: { encoding: 'buffer' }): UserInfo<Buffer>;
function userInfo(options?: { encoding: BufferEncoding }): UserInfo<string>;
type SignalConstants = {
[key in NodeJS.Signals]: number;
};
namespace constants {
const UV_UDP_REUSEADDR: number;
namespace signals {}
const signals: SignalConstants;
namespace errno {
const E2BIG: number;
const EACCES: number;
const EADDRINUSE: number;
const EADDRNOTAVAIL: number;
const EAFNOSUPPORT: number;
const EAGAIN: number;
const EALREADY: number;
const EBADF: number;
const EBADMSG: number;
const EBUSY: number;
const ECANCELED: number;
const ECHILD: number;
const ECONNABORTED: number;
const ECONNREFUSED: number;
const ECONNRESET: number;
const EDEADLK: number;
const EDESTADDRREQ: number;
const EDOM: number;
const EDQUOT: number;
const EEXIST: number;
const EFAULT: number;
const EFBIG: number;
const EHOSTUNREACH: number;
const EIDRM: number;
const EILSEQ: number;
const EINPROGRESS: number;
const EINTR: number;
const EINVAL: number;
const EIO: number;
const EISCONN: number;
const EISDIR: number;
const ELOOP: number;
const EMFILE: number;
const EMLINK: number;
const EMSGSIZE: number;
const EMULTIHOP: number;
const ENAMETOOLONG: number;
const ENETDOWN: number;
const ENETRESET: number;
const ENETUNREACH: number;
const ENFILE: number;
const ENOBUFS: number;
const ENODATA: number;
const ENODEV: number;
const ENOENT: number;
const ENOEXEC: number;
const ENOLCK: number;
const ENOLINK: number;
const ENOMEM: number;
const ENOMSG: number;
const ENOPROTOOPT: number;
const ENOSPC: number;
const ENOSR: number;
const ENOSTR: number;
const ENOSYS: number;
const ENOTCONN: number;
const ENOTDIR: number;
const ENOTEMPTY: number;
const ENOTSOCK: number;
const ENOTSUP: number;
const ENOTTY: number;
const ENXIO: number;
const EOPNOTSUPP: number;
const EOVERFLOW: number;
const EPERM: number;
const EPIPE: number;
const EPROTO: number;
const EPROTONOSUPPORT: number;
const EPROTOTYPE: number;
const ERANGE: number;
const EROFS: number;
const ESPIPE: number;
const ESRCH: number;
const ESTALE: number;
const ETIME: number;
const ETIMEDOUT: number;
const ETXTBSY: number;
const EWOULDBLOCK: number;
const EXDEV: number;
const WSAEINTR: number;
const WSAEBADF: number;
const WSAEACCES: number;
const WSAEFAULT: number;
const WSAEINVAL: number;
const WSAEMFILE: number;
const WSAEWOULDBLOCK: number;
const WSAEINPROGRESS: number;
const WSAEALREADY: number;
const WSAENOTSOCK: number;
const WSAEDESTADDRREQ: number;
const WSAEMSGSIZE: number;
const WSAEPROTOTYPE: number;
const WSAENOPROTOOPT: number;
const WSAEPROTONOSUPPORT: number;
const WSAESOCKTNOSUPPORT: number;
const WSAEOPNOTSUPP: number;
const WSAEPFNOSUPPORT: number;
const WSAEAFNOSUPPORT: number;
const WSAEADDRINUSE: number;
const WSAEADDRNOTAVAIL: number;
const WSAENETDOWN: number;
const WSAENETUNREACH: number;
const WSAENETRESET: number;
const WSAECONNABORTED: number;
const WSAECONNRESET: number;
const WSAENOBUFS: number;
const WSAEISCONN: number;
const WSAENOTCONN: number;
const WSAESHUTDOWN: number;
const WSAETOOMANYREFS: number;
const WSAETIMEDOUT: number;
const WSAECONNREFUSED: number;
const WSAELOOP: number;
const WSAENAMETOOLONG: number;
const WSAEHOSTDOWN: number;
const WSAEHOSTUNREACH: number;
const WSAENOTEMPTY: number;
const WSAEPROCLIM: number;
const WSAEUSERS: number;
const WSAEDQUOT: number;
const WSAESTALE: number;
const WSAEREMOTE: number;
const WSASYSNOTREADY: number;
const WSAVERNOTSUPPORTED: number;
const WSANOTINITIALISED: number;
const WSAEDISCON: number;
const WSAENOMORE: number;
const WSAECANCELLED: number;
const WSAEINVALIDPROCTABLE: number;
const WSAEINVALIDPROVIDER: number;
const WSAEPROVIDERFAILEDINIT: number;
const WSASYSCALLFAILURE: number;
const WSASERVICE_NOT_FOUND: number;
const WSATYPE_NOT_FOUND: number;
const WSA_E_NO_MORE: number;
const WSA_E_CANCELLED: number;
const WSAEREFUSED: number;
}
namespace priority {
const PRIORITY_LOW: number;
const PRIORITY_BELOW_NORMAL: number;
const PRIORITY_NORMAL: number;
const PRIORITY_ABOVE_NORMAL: number;
const PRIORITY_HIGH: number;
const PRIORITY_HIGHEST: number;
}
}
function arch(): string;
/**
* Returns a string identifying the kernel version.
* On POSIX systems, the operating system release is determined by calling
* [uname(3)][]. On Windows, `pRtlGetVersion` is used, and if it is not available,
* `GetVersionExW()` will be used. See
* https://en.wikipedia.org/wiki/Uname#Examples for more information.
*/
function version(): string;
function platform(): NodeJS.Platform;
function tmpdir(): string;
const EOL: string;
function endianness(): "BE" | "LE";
/**
* Gets the priority of a process.
* Defaults to current process.
*/
function getPriority(pid?: number): number;
/**
* Sets the priority of the current process.
* @param priority Must be in range of -20 to 19
*/
function setPriority(priority: number): void;
/**
* Sets the priority of the process specified process.
* @param priority Must be in range of -20 to 19
*/
function setPriority(pid: number, priority: number): void;
}

View File

@ -1 +1,156 @@
declare module'node:path'{import path=require('path');export=path;}declare module'path'{namespace path{interface ParsedPath{root:string;dir:string;base:string;ext:string;name:string;}interface FormatInputPathObject{root?:string;dir?:string;base?:string;ext?:string;name?:string;}interface PlatformPath{normalize(p:string):string;join(...paths:string[]):string;resolve(...pathSegments:string[]):string;isAbsolute(p:string):boolean;relative(from:string,to:string):string;dirname(p:string):string;basename(p:string,ext?:string):string;extname(p:string):string;readonly sep:string;readonly delimiter:string;parse(p:string):ParsedPath;format(pP:FormatInputPathObject):string;toNamespacedPath(path:string):string;readonly posix:PlatformPath;readonly win32:PlatformPath;}}const path:path.PlatformPath;export=path;}
/* NOTE: Do not edit directly! This file is generated using `npm run update-types` in https://github.com/node-red/nr-monaco-build */
declare module 'path' {
namespace path {
/**
* A parsed path object generated by path.parse() or consumed by path.format().
*/
interface ParsedPath {
/**
* The root of the path such as '/' or 'c:\'
*/
root: string;
/**
* The full directory path such as '/home/user/dir' or 'c:\path\dir'
*/
dir: string;
/**
* The file name including extension (if any) such as 'index.html'
*/
base: string;
/**
* The file extension (if any) such as '.html'
*/
ext: string;
/**
* The file name without extension (if any) such as 'index'
*/
name: string;
}
interface FormatInputPathObject {
/**
* The root of the path such as '/' or 'c:\'
*/
root?: string | undefined;
/**
* The full directory path such as '/home/user/dir' or 'c:\path\dir'
*/
dir?: string | undefined;
/**
* The file name including extension (if any) such as 'index.html'
*/
base?: string | undefined;
/**
* The file extension (if any) such as '.html'
*/
ext?: string | undefined;
/**
* The file name without extension (if any) such as 'index'
*/
name?: string | undefined;
}
interface PlatformPath {
/**
* Normalize a string path, reducing '..' and '.' parts.
* When multiple slashes are found, they're replaced by a single one; when the path contains a trailing slash, it is preserved. On Windows backslashes are used.
*
* @param p string path to normalize.
*/
normalize(p: string): string;
/**
* Join all arguments together and normalize the resulting path.
* Arguments must be strings. In v0.8, non-string arguments were silently ignored. In v0.10 and up, an exception is thrown.
*
* @param paths paths to join.
*/
join(...paths: string[]): string;
/**
* The right-most parameter is considered {to}. Other parameters are considered an array of {from}.
*
* Starting from leftmost {from} parameter, resolves {to} to an absolute path.
*
* If {to} isn't already absolute, {from} arguments are prepended in right to left order,
* until an absolute path is found. If after using all {from} paths still no absolute path is found,
* the current working directory is used as well. The resulting path is normalized,
* and trailing slashes are removed unless the path gets resolved to the root directory.
*
* @param pathSegments string paths to join. Non-string arguments are ignored.
*/
resolve(...pathSegments: string[]): string;
/**
* Determines whether {path} is an absolute path. An absolute path will always resolve to the same location, regardless of the working directory.
*
* @param path path to test.
*/
isAbsolute(p: string): boolean;
/**
* Solve the relative path from {from} to {to}.
* At times we have two absolute paths, and we need to derive the relative path from one to the other. This is actually the reverse transform of path.resolve.
*/
relative(from: string, to: string): string;
/**
* Return the directory name of a path. Similar to the Unix dirname command.
*
* @param p the path to evaluate.
*/
dirname(p: string): string;
/**
* Return the last portion of a path. Similar to the Unix basename command.
* Often used to extract the file name from a fully qualified path.
*
* @param p the path to evaluate.
* @param ext optionally, an extension to remove from the result.
*/
basename(p: string, ext?: string): string;
/**
* Return the extension of the path, from the last '.' to end of string in the last portion of the path.
* If there is no '.' in the last portion of the path or the first character of it is '.', then it returns an empty string
*
* @param p the path to evaluate.
*/
extname(p: string): string;
/**
* The platform-specific file separator. '\\' or '/'.
*/
readonly sep: string;
/**
* The platform-specific file delimiter. ';' or ':'.
*/
readonly delimiter: string;
/**
* Returns an object from a path string - the opposite of format().
*
* @param pathString path to evaluate.
*/
parse(p: string): ParsedPath;
/**
* Returns a path string from an object - the opposite of parse().
*
* @param pathString path to evaluate.
*/
format(pP: FormatInputPathObject): string;
/**
* On Windows systems only, returns an equivalent namespace-prefixed path for the given path.
* If path is not a string, path will be returned without modifications.
* This method is meaningful only on Windows system.
* On POSIX systems, the method is non-operational and always returns path without modifications.
*/
toNamespacedPath(path: string): string;
/**
* Posix specific pathing.
* Same as parent object on posix.
*/
readonly posix: PlatformPath;
/**
* Windows specific pathing.
* Same as parent object on windows
*/
readonly win32: PlatformPath;
}
}
const path: path.PlatformPath;
export = path;
}

View File

@ -0,0 +1,274 @@
/* NOTE: Do not edit directly! This file is generated using `npm run update-types` in https://github.com/node-red/nr-monaco-build */
declare module 'perf_hooks' {
import { AsyncResource } from 'async_hooks';
type EntryType = 'node' | 'mark' | 'measure' | 'gc' | 'function' | 'http2' | 'http';
interface PerformanceEntry {
/**
* The total number of milliseconds elapsed for this entry.
* This value will not be meaningful for all Performance Entry types.
*/
readonly duration: number;
/**
* The name of the performance entry.
*/
readonly name: string;
/**
* The high resolution millisecond timestamp marking the starting time of the Performance Entry.
*/
readonly startTime: number;
/**
* The type of the performance entry.
* Currently it may be one of: 'node', 'mark', 'measure', 'gc', or 'function'.
*/
readonly entryType: EntryType;
/**
* When `performanceEntry.entryType` is equal to 'gc', `the performance.kind` property identifies
* the type of garbage collection operation that occurred.
* See perf_hooks.constants for valid values.
*/
readonly kind?: number | undefined;
/**
* When `performanceEntry.entryType` is equal to 'gc', the `performance.flags`
* property contains additional information about garbage collection operation.
* See perf_hooks.constants for valid values.
*/
readonly flags?: number | undefined;
}
interface PerformanceNodeTiming extends PerformanceEntry {
/**
* The high resolution millisecond timestamp at which the Node.js process completed bootstrap.
*/
readonly bootstrapComplete: number;
/**
* The high resolution millisecond timestamp at which the Node.js process completed bootstrapping.
* If bootstrapping has not yet finished, the property has the value of -1.
*/
readonly environment: number;
/**
* The high resolution millisecond timestamp at which the Node.js environment was initialized.
*/
readonly idleTime: number;
/**
* The high resolution millisecond timestamp of the amount of time the event loop has been idle
* within the event loop's event provider (e.g. `epoll_wait`). This does not take CPU usage
* into consideration. If the event loop has not yet started (e.g., in the first tick of the main script),
* the property has the value of 0.
*/
readonly loopExit: number;
/**
* The high resolution millisecond timestamp at which the Node.js event loop started.
* If the event loop has not yet started (e.g., in the first tick of the main script), the property has the value of -1.
*/
readonly loopStart: number;
/**
* The high resolution millisecond timestamp at which the V8 platform was initialized.
*/
readonly v8Start: number;
}
interface EventLoopUtilization {
idle: number;
active: number;
utilization: number;
}
interface Performance {
/**
* If name is not provided, removes all PerformanceMark objects from the Performance Timeline.
* If name is provided, removes only the named mark.
* @param name
*/
clearMarks(name?: string): void;
/**
* Creates a new PerformanceMark entry in the Performance Timeline.
* A PerformanceMark is a subclass of PerformanceEntry whose performanceEntry.entryType is always 'mark',
* and whose performanceEntry.duration is always 0.
* Performance marks are used to mark specific significant moments in the Performance Timeline.
* @param name
*/
mark(name?: string): void;
/**
* Creates a new PerformanceMeasure entry in the Performance Timeline.
* A PerformanceMeasure is a subclass of PerformanceEntry whose performanceEntry.entryType is always 'measure',
* and whose performanceEntry.duration measures the number of milliseconds elapsed since startMark and endMark.
*
* The startMark argument may identify any existing PerformanceMark in the the Performance Timeline, or may identify
* any of the timestamp properties provided by the PerformanceNodeTiming class. If the named startMark does not exist,
* then startMark is set to timeOrigin by default.
*
* The endMark argument must identify any existing PerformanceMark in the the Performance Timeline or any of the timestamp
* properties provided by the PerformanceNodeTiming class. If the named endMark does not exist, an error will be thrown.
* @param name
* @param startMark
* @param endMark
*/
measure(name: string, startMark?: string, endMark?: string): void;
/**
* An instance of the PerformanceNodeTiming class that provides performance metrics for specific Node.js operational milestones.
*/
readonly nodeTiming: PerformanceNodeTiming;
/**
* @return the current high resolution millisecond timestamp
*/
now(): number;
/**
* The timeOrigin specifies the high resolution millisecond timestamp from which all performance metric durations are measured.
*/
readonly timeOrigin: number;
/**
* Wraps a function within a new function that measures the running time of the wrapped function.
* A PerformanceObserver must be subscribed to the 'function' event type in order for the timing details to be accessed.
* @param fn
*/
timerify<T extends (...optionalParams: any[]) => any>(fn: T): T;
/**
* eventLoopUtilization is similar to CPU utilization except that it is calculated using high precision wall-clock time.
* It represents the percentage of time the event loop has spent outside the event loop's event provider (e.g. epoll_wait).
* No other CPU idle time is taken into consideration.
*
* @param util1 The result of a previous call to eventLoopUtilization()
* @param util2 The result of a previous call to eventLoopUtilization() prior to util1
*/
eventLoopUtilization(util1?: EventLoopUtilization, util2?: EventLoopUtilization): EventLoopUtilization;
}
interface PerformanceObserverEntryList {
/**
* @return a list of PerformanceEntry objects in chronological order with respect to performanceEntry.startTime.
*/
getEntries(): PerformanceEntry[];
/**
* @return a list of PerformanceEntry objects in chronological order with respect to performanceEntry.startTime
* whose performanceEntry.name is equal to name, and optionally, whose performanceEntry.entryType is equal to type.
*/
getEntriesByName(name: string, type?: EntryType): PerformanceEntry[];
/**
* @return Returns a list of PerformanceEntry objects in chronological order with respect to performanceEntry.startTime
* whose performanceEntry.entryType is equal to type.
*/
getEntriesByType(type: EntryType): PerformanceEntry[];
}
type PerformanceObserverCallback = (list: PerformanceObserverEntryList, observer: PerformanceObserver) => void;
class PerformanceObserver extends AsyncResource {
constructor(callback: PerformanceObserverCallback);
/**
* Disconnects the PerformanceObserver instance from all notifications.
*/
disconnect(): void;
/**
* Subscribes the PerformanceObserver instance to notifications of new PerformanceEntry instances identified by options.entryTypes.
* When options.buffered is false, the callback will be invoked once for every PerformanceEntry instance.
* Property buffered defaults to false.
* @param options
*/
observe(options: { entryTypes: ReadonlyArray<EntryType>; buffered?: boolean | undefined }): void;
}
namespace constants {
const NODE_PERFORMANCE_GC_MAJOR: number;
const NODE_PERFORMANCE_GC_MINOR: number;
const NODE_PERFORMANCE_GC_INCREMENTAL: number;
const NODE_PERFORMANCE_GC_WEAKCB: number;
const NODE_PERFORMANCE_GC_FLAGS_NO: number;
const NODE_PERFORMANCE_GC_FLAGS_CONSTRUCT_RETAINED: number;
const NODE_PERFORMANCE_GC_FLAGS_FORCED: number;
const NODE_PERFORMANCE_GC_FLAGS_SYNCHRONOUS_PHANTOM_PROCESSING: number;
const NODE_PERFORMANCE_GC_FLAGS_ALL_AVAILABLE_GARBAGE: number;
const NODE_PERFORMANCE_GC_FLAGS_ALL_EXTERNAL_MEMORY: number;
const NODE_PERFORMANCE_GC_FLAGS_SCHEDULE_IDLE: number;
}
const performance: Performance;
interface EventLoopMonitorOptions {
/**
* The sampling rate in milliseconds.
* Must be greater than zero.
* @default 10
*/
resolution?: number | undefined;
}
interface EventLoopDelayMonitor {
/**
* Enables the event loop delay sample timer. Returns `true` if the timer was started, `false` if it was already started.
*/
enable(): boolean;
/**
* Disables the event loop delay sample timer. Returns `true` if the timer was stopped, `false` if it was already stopped.
*/
disable(): boolean;
/**
* Resets the collected histogram data.
*/
reset(): void;
/**
* Returns the value at the given percentile.
* @param percentile A percentile value between 1 and 100.
*/
percentile(percentile: number): number;
/**
* A `Map` object detailing the accumulated percentile distribution.
*/
readonly percentiles: Map<number, number>;
/**
* The number of times the event loop delay exceeded the maximum 1 hour eventloop delay threshold.
*/
readonly exceeds: number;
/**
* The minimum recorded event loop delay.
*/
readonly min: number;
/**
* The maximum recorded event loop delay.
*/
readonly max: number;
/**
* The mean of the recorded event loop delays.
*/
readonly mean: number;
/**
* The standard deviation of the recorded event loop delays.
*/
readonly stddev: number;
}
function monitorEventLoopDelay(options?: EventLoopMonitorOptions): EventLoopDelayMonitor;
}

File diff suppressed because one or more lines are too long

View File

@ -1 +1,31 @@
declare module'node:querystring'{export*from'querystring';}declare module'querystring'{interface StringifyOptions{encodeURIComponent?:(str:string)=>string;}interface ParseOptions{maxKeys?:number;decodeURIComponent?:(str:string)=>string;}interface ParsedUrlQuery extends NodeJS.Dict<string|string[]>{}interface ParsedUrlQueryInput extends NodeJS.Dict<string|number|boolean|ReadonlyArray<string>|ReadonlyArray<number>|ReadonlyArray<boolean>|null>{}function stringify(obj?:ParsedUrlQueryInput,sep?:string,eq?:string,options?:StringifyOptions):string;function parse(str:string,sep?:string,eq?:string,options?:ParseOptions):ParsedUrlQuery;const encode:typeof stringify;const decode:typeof parse;function escape(str:string):string;function unescape(str:string):string;}
/* NOTE: Do not edit directly! This file is generated using `npm run update-types` in https://github.com/node-red/nr-monaco-build */
declare module 'querystring' {
interface StringifyOptions {
encodeURIComponent?: ((str: string) => string) | undefined;
}
interface ParseOptions {
maxKeys?: number | undefined;
decodeURIComponent?: ((str: string) => string) | undefined;
}
interface ParsedUrlQuery extends NodeJS.Dict<string | string[]> { }
interface ParsedUrlQueryInput extends NodeJS.Dict<string | number | boolean | ReadonlyArray<string> | ReadonlyArray<number> | ReadonlyArray<boolean> | null> {
}
function stringify(obj?: ParsedUrlQueryInput, sep?: string, eq?: string, options?: StringifyOptions): string;
function parse(str: string, sep?: string, eq?: string, options?: ParseOptions): ParsedUrlQuery;
/**
* The querystring.encode() function is an alias for querystring.stringify().
*/
const encode: typeof stringify;
/**
* The querystring.decode() function is an alias for querystring.parse().
*/
const decode: typeof parse;
function escape(str: string): string;
function unescape(str: string): string;
}

View File

@ -0,0 +1,173 @@
/* NOTE: Do not edit directly! This file is generated using `npm run update-types` in https://github.com/node-red/nr-monaco-build */
declare module 'readline' {
import EventEmitter = require('events');
interface Key {
sequence?: string | undefined;
name?: string | undefined;
ctrl?: boolean | undefined;
meta?: boolean | undefined;
shift?: boolean | undefined;
}
class Interface extends EventEmitter {
readonly terminal: boolean;
// Need direct access to line/cursor data, for use in external processes
// see: https://github.com/nodejs/node/issues/30347
/** The current input data */
readonly line: string;
/** The current cursor position in the input line */
readonly cursor: number;
/**
* NOTE: According to the documentation:
*
* > Instances of the `readline.Interface` class are constructed using the
* > `readline.createInterface()` method.
*
* @see https://nodejs.org/dist/latest-v10.x/docs/api/readline.html#readline_class_interface
*/
protected constructor(input: NodeJS.ReadableStream, output?: NodeJS.WritableStream, completer?: Completer | AsyncCompleter, terminal?: boolean);
/**
* NOTE: According to the documentation:
*
* > Instances of the `readline.Interface` class are constructed using the
* > `readline.createInterface()` method.
*
* @see https://nodejs.org/dist/latest-v10.x/docs/api/readline.html#readline_class_interface
*/
protected constructor(options: ReadLineOptions);
setPrompt(prompt: string): void;
prompt(preserveCursor?: boolean): void;
question(query: string, callback: (answer: string) => void): void;
pause(): this;
resume(): this;
close(): void;
write(data: string | Buffer, key?: Key): void;
/**
* Returns the real position of the cursor in relation to the input
* prompt + string. Long input (wrapping) strings, as well as multiple
* line prompts are included in the calculations.
*/
getCursorPos(): CursorPos;
/**
* events.EventEmitter
* 1. close
* 2. line
* 3. pause
* 4. resume
* 5. SIGCONT
* 6. SIGINT
* 7. SIGTSTP
*/
addListener(event: string, listener: (...args: any[]) => void): this;
addListener(event: "close", listener: () => void): this;
addListener(event: "line", listener: (input: string) => void): this;
addListener(event: "pause", listener: () => void): this;
addListener(event: "resume", listener: () => void): this;
addListener(event: "SIGCONT", listener: () => void): this;
addListener(event: "SIGINT", listener: () => void): this;
addListener(event: "SIGTSTP", listener: () => void): this;
emit(event: string | symbol, ...args: any[]): boolean;
emit(event: "close"): boolean;
emit(event: "line", input: string): boolean;
emit(event: "pause"): boolean;
emit(event: "resume"): boolean;
emit(event: "SIGCONT"): boolean;
emit(event: "SIGINT"): boolean;
emit(event: "SIGTSTP"): boolean;
on(event: string, listener: (...args: any[]) => void): this;
on(event: "close", listener: () => void): this;
on(event: "line", listener: (input: string) => void): this;
on(event: "pause", listener: () => void): this;
on(event: "resume", listener: () => void): this;
on(event: "SIGCONT", listener: () => void): this;
on(event: "SIGINT", listener: () => void): this;
on(event: "SIGTSTP", listener: () => void): this;
once(event: string, listener: (...args: any[]) => void): this;
once(event: "close", listener: () => void): this;
once(event: "line", listener: (input: string) => void): this;
once(event: "pause", listener: () => void): this;
once(event: "resume", listener: () => void): this;
once(event: "SIGCONT", listener: () => void): this;
once(event: "SIGINT", listener: () => void): this;
once(event: "SIGTSTP", listener: () => void): this;
prependListener(event: string, listener: (...args: any[]) => void): this;
prependListener(event: "close", listener: () => void): this;
prependListener(event: "line", listener: (input: string) => void): this;
prependListener(event: "pause", listener: () => void): this;
prependListener(event: "resume", listener: () => void): this;
prependListener(event: "SIGCONT", listener: () => void): this;
prependListener(event: "SIGINT", listener: () => void): this;
prependListener(event: "SIGTSTP", listener: () => void): this;
prependOnceListener(event: string, listener: (...args: any[]) => void): this;
prependOnceListener(event: "close", listener: () => void): this;
prependOnceListener(event: "line", listener: (input: string) => void): this;
prependOnceListener(event: "pause", listener: () => void): this;
prependOnceListener(event: "resume", listener: () => void): this;
prependOnceListener(event: "SIGCONT", listener: () => void): this;
prependOnceListener(event: "SIGINT", listener: () => void): this;
prependOnceListener(event: "SIGTSTP", listener: () => void): this;
[Symbol.asyncIterator](): AsyncIterableIterator<string>;
}
type ReadLine = Interface; // type forwarded for backwards compatibility
type Completer = (line: string) => CompleterResult;
type AsyncCompleter = (line: string, callback: (err?: null | Error, result?: CompleterResult) => void) => any;
type CompleterResult = [string[], string];
interface ReadLineOptions {
input: NodeJS.ReadableStream;
output?: NodeJS.WritableStream | undefined;
completer?: Completer | AsyncCompleter | undefined;
terminal?: boolean | undefined;
historySize?: number | undefined;
prompt?: string | undefined;
crlfDelay?: number | undefined;
removeHistoryDuplicates?: boolean | undefined;
escapeCodeTimeout?: number | undefined;
tabSize?: number | undefined;
}
function createInterface(input: NodeJS.ReadableStream, output?: NodeJS.WritableStream, completer?: Completer | AsyncCompleter, terminal?: boolean): Interface;
function createInterface(options: ReadLineOptions): Interface;
function emitKeypressEvents(stream: NodeJS.ReadableStream, readlineInterface?: Interface): void;
type Direction = -1 | 0 | 1;
interface CursorPos {
rows: number;
cols: number;
}
/**
* Clears the current line of this WriteStream in a direction identified by `dir`.
*/
function clearLine(stream: NodeJS.WritableStream, dir: Direction, callback?: () => void): boolean;
/**
* Clears this `WriteStream` from the current cursor down.
*/
function clearScreenDown(stream: NodeJS.WritableStream, callback?: () => void): boolean;
/**
* Moves this WriteStream's cursor to the specified position.
*/
function cursorTo(stream: NodeJS.WritableStream, x: number, y?: number, callback?: () => void): boolean;
/**
* Moves this WriteStream's cursor relative to its current position.
*/
function moveCursor(stream: NodeJS.WritableStream, dx: number, dy: number, callback?: () => void): boolean;
}

View File

@ -0,0 +1,358 @@
/* NOTE: Do not edit directly! This file is generated using `npm run update-types` in https://github.com/node-red/nr-monaco-build */
declare module 'stream' {
import EventEmitter = require('events');
class internal extends EventEmitter {
pipe<T extends NodeJS.WritableStream>(destination: T, options?: { end?: boolean | undefined; }): T;
}
namespace internal {
class Stream extends internal {
constructor(opts?: ReadableOptions);
}
interface ReadableOptions {
highWaterMark?: number | undefined;
encoding?: BufferEncoding | undefined;
objectMode?: boolean | undefined;
read?(this: Readable, size: number): void;
destroy?(this: Readable, error: Error | null, callback: (error: Error | null) => void): void;
autoDestroy?: boolean | undefined;
}
class Readable extends Stream implements NodeJS.ReadableStream {
/**
* A utility method for creating Readable Streams out of iterators.
*/
static from(iterable: Iterable<any> | AsyncIterable<any>, options?: ReadableOptions): Readable;
readable: boolean;
readonly readableEncoding: BufferEncoding | null;
readonly readableEnded: boolean;
readonly readableFlowing: boolean | null;
readonly readableHighWaterMark: number;
readonly readableLength: number;
readonly readableObjectMode: boolean;
destroyed: boolean;
constructor(opts?: ReadableOptions);
_read(size: number): void;
read(size?: number): any;
setEncoding(encoding: BufferEncoding): this;
pause(): this;
resume(): this;
isPaused(): boolean;
unpipe(destination?: NodeJS.WritableStream): this;
unshift(chunk: any, encoding?: BufferEncoding): void;
wrap(oldStream: NodeJS.ReadableStream): this;
push(chunk: any, encoding?: BufferEncoding): boolean;
_destroy(error: Error | null, callback: (error?: Error | null) => void): void;
destroy(error?: Error): void;
/**
* Event emitter
* The defined events on documents including:
* 1. close
* 2. data
* 3. end
* 4. error
* 5. pause
* 6. readable
* 7. resume
*/
addListener(event: "close", listener: () => void): this;
addListener(event: "data", listener: (chunk: any) => void): this;
addListener(event: "end", listener: () => void): this;
addListener(event: "error", listener: (err: Error) => void): this;
addListener(event: "pause", listener: () => void): this;
addListener(event: "readable", listener: () => void): this;
addListener(event: "resume", listener: () => void): this;
addListener(event: string | symbol, listener: (...args: any[]) => void): this;
emit(event: "close"): boolean;
emit(event: "data", chunk: any): boolean;
emit(event: "end"): boolean;
emit(event: "error", err: Error): boolean;
emit(event: "pause"): boolean;
emit(event: "readable"): boolean;
emit(event: "resume"): boolean;
emit(event: string | symbol, ...args: any[]): boolean;
on(event: "close", listener: () => void): this;
on(event: "data", listener: (chunk: any) => void): this;
on(event: "end", listener: () => void): this;
on(event: "error", listener: (err: Error) => void): this;
on(event: "pause", listener: () => void): this;
on(event: "readable", listener: () => void): this;
on(event: "resume", listener: () => void): this;
on(event: string | symbol, listener: (...args: any[]) => void): this;
once(event: "close", listener: () => void): this;
once(event: "data", listener: (chunk: any) => void): this;
once(event: "end", listener: () => void): this;
once(event: "error", listener: (err: Error) => void): this;
once(event: "pause", listener: () => void): this;
once(event: "readable", listener: () => void): this;
once(event: "resume", listener: () => void): this;
once(event: string | symbol, listener: (...args: any[]) => void): this;
prependListener(event: "close", listener: () => void): this;
prependListener(event: "data", listener: (chunk: any) => void): this;
prependListener(event: "end", listener: () => void): this;
prependListener(event: "error", listener: (err: Error) => void): this;
prependListener(event: "pause", listener: () => void): this;
prependListener(event: "readable", listener: () => void): this;
prependListener(event: "resume", listener: () => void): this;
prependListener(event: string | symbol, listener: (...args: any[]) => void): this;
prependOnceListener(event: "close", listener: () => void): this;
prependOnceListener(event: "data", listener: (chunk: any) => void): this;
prependOnceListener(event: "end", listener: () => void): this;
prependOnceListener(event: "error", listener: (err: Error) => void): this;
prependOnceListener(event: "pause", listener: () => void): this;
prependOnceListener(event: "readable", listener: () => void): this;
prependOnceListener(event: "resume", listener: () => void): this;
prependOnceListener(event: string | symbol, listener: (...args: any[]) => void): this;
removeListener(event: "close", listener: () => void): this;
removeListener(event: "data", listener: (chunk: any) => void): this;
removeListener(event: "end", listener: () => void): this;
removeListener(event: "error", listener: (err: Error) => void): this;
removeListener(event: "pause", listener: () => void): this;
removeListener(event: "readable", listener: () => void): this;
removeListener(event: "resume", listener: () => void): this;
removeListener(event: string | symbol, listener: (...args: any[]) => void): this;
[Symbol.asyncIterator](): AsyncIterableIterator<any>;
}
interface WritableOptions {
highWaterMark?: number | undefined;
decodeStrings?: boolean | undefined;
defaultEncoding?: BufferEncoding | undefined;
objectMode?: boolean | undefined;
emitClose?: boolean | undefined;
write?(this: Writable, chunk: any, encoding: BufferEncoding, callback: (error?: Error | null) => void): void;
writev?(this: Writable, chunks: Array<{ chunk: any, encoding: BufferEncoding }>, callback: (error?: Error | null) => void): void;
destroy?(this: Writable, error: Error | null, callback: (error: Error | null) => void): void;
final?(this: Writable, callback: (error?: Error | null) => void): void;
autoDestroy?: boolean | undefined;
}
class Writable extends Stream implements NodeJS.WritableStream {
readonly writable: boolean;
readonly writableEnded: boolean;
readonly writableFinished: boolean;
readonly writableHighWaterMark: number;
readonly writableLength: number;
readonly writableObjectMode: boolean;
readonly writableCorked: number;
destroyed: boolean;
constructor(opts?: WritableOptions);
_write(chunk: any, encoding: BufferEncoding, callback: (error?: Error | null) => void): void;
_writev?(chunks: Array<{ chunk: any, encoding: BufferEncoding }>, callback: (error?: Error | null) => void): void;
_destroy(error: Error | null, callback: (error?: Error | null) => void): void;
_final(callback: (error?: Error | null) => void): void;
write(chunk: any, cb?: (error: Error | null | undefined) => void): boolean;
write(chunk: any, encoding: BufferEncoding, cb?: (error: Error | null | undefined) => void): boolean;
setDefaultEncoding(encoding: BufferEncoding): this;
end(cb?: () => void): void;
end(chunk: any, cb?: () => void): void;
end(chunk: any, encoding: BufferEncoding, cb?: () => void): void;
cork(): void;
uncork(): void;
destroy(error?: Error): void;
/**
* Event emitter
* The defined events on documents including:
* 1. close
* 2. drain
* 3. error
* 4. finish
* 5. pipe
* 6. unpipe
*/
addListener(event: "close", listener: () => void): this;
addListener(event: "drain", listener: () => void): this;
addListener(event: "error", listener: (err: Error) => void): this;
addListener(event: "finish", listener: () => void): this;
addListener(event: "pipe", listener: (src: Readable) => void): this;
addListener(event: "unpipe", listener: (src: Readable) => void): this;
addListener(event: string | symbol, listener: (...args: any[]) => void): this;
emit(event: "close"): boolean;
emit(event: "drain"): boolean;
emit(event: "error", err: Error): boolean;
emit(event: "finish"): boolean;
emit(event: "pipe", src: Readable): boolean;
emit(event: "unpipe", src: Readable): boolean;
emit(event: string | symbol, ...args: any[]): boolean;
on(event: "close", listener: () => void): this;
on(event: "drain", listener: () => void): this;
on(event: "error", listener: (err: Error) => void): this;
on(event: "finish", listener: () => void): this;
on(event: "pipe", listener: (src: Readable) => void): this;
on(event: "unpipe", listener: (src: Readable) => void): this;
on(event: string | symbol, listener: (...args: any[]) => void): this;
once(event: "close", listener: () => void): this;
once(event: "drain", listener: () => void): this;
once(event: "error", listener: (err: Error) => void): this;
once(event: "finish", listener: () => void): this;
once(event: "pipe", listener: (src: Readable) => void): this;
once(event: "unpipe", listener: (src: Readable) => void): this;
once(event: string | symbol, listener: (...args: any[]) => void): this;
prependListener(event: "close", listener: () => void): this;
prependListener(event: "drain", listener: () => void): this;
prependListener(event: "error", listener: (err: Error) => void): this;
prependListener(event: "finish", listener: () => void): this;
prependListener(event: "pipe", listener: (src: Readable) => void): this;
prependListener(event: "unpipe", listener: (src: Readable) => void): this;
prependListener(event: string | symbol, listener: (...args: any[]) => void): this;
prependOnceListener(event: "close", listener: () => void): this;
prependOnceListener(event: "drain", listener: () => void): this;
prependOnceListener(event: "error", listener: (err: Error) => void): this;
prependOnceListener(event: "finish", listener: () => void): this;
prependOnceListener(event: "pipe", listener: (src: Readable) => void): this;
prependOnceListener(event: "unpipe", listener: (src: Readable) => void): this;
prependOnceListener(event: string | symbol, listener: (...args: any[]) => void): this;
removeListener(event: "close", listener: () => void): this;
removeListener(event: "drain", listener: () => void): this;
removeListener(event: "error", listener: (err: Error) => void): this;
removeListener(event: "finish", listener: () => void): this;
removeListener(event: "pipe", listener: (src: Readable) => void): this;
removeListener(event: "unpipe", listener: (src: Readable) => void): this;
removeListener(event: string | symbol, listener: (...args: any[]) => void): this;
}
interface DuplexOptions extends ReadableOptions, WritableOptions {
allowHalfOpen?: boolean | undefined;
readableObjectMode?: boolean | undefined;
writableObjectMode?: boolean | undefined;
readableHighWaterMark?: number | undefined;
writableHighWaterMark?: number | undefined;
writableCorked?: number | undefined;
read?(this: Duplex, size: number): void;
write?(this: Duplex, chunk: any, encoding: BufferEncoding, callback: (error?: Error | null) => void): void;
writev?(this: Duplex, chunks: Array<{ chunk: any, encoding: BufferEncoding }>, callback: (error?: Error | null) => void): void;
final?(this: Duplex, callback: (error?: Error | null) => void): void;
destroy?(this: Duplex, error: Error | null, callback: (error: Error | null) => void): void;
}
// Note: Duplex extends both Readable and Writable.
class Duplex extends Readable implements Writable {
readonly writable: boolean;
readonly writableEnded: boolean;
readonly writableFinished: boolean;
readonly writableHighWaterMark: number;
readonly writableLength: number;
readonly writableObjectMode: boolean;
readonly writableCorked: number;
allowHalfOpen: boolean;
constructor(opts?: DuplexOptions);
_write(chunk: any, encoding: BufferEncoding, callback: (error?: Error | null) => void): void;
_writev?(chunks: Array<{ chunk: any, encoding: BufferEncoding }>, callback: (error?: Error | null) => void): void;
_destroy(error: Error | null, callback: (error: Error | null) => void): void;
_final(callback: (error?: Error | null) => void): void;
write(chunk: any, encoding?: BufferEncoding, cb?: (error: Error | null | undefined) => void): boolean;
write(chunk: any, cb?: (error: Error | null | undefined) => void): boolean;
setDefaultEncoding(encoding: BufferEncoding): this;
end(cb?: () => void): void;
end(chunk: any, cb?: () => void): void;
end(chunk: any, encoding?: BufferEncoding, cb?: () => void): void;
cork(): void;
uncork(): void;
}
type TransformCallback = (error?: Error | null, data?: any) => void;
interface TransformOptions extends DuplexOptions {
read?(this: Transform, size: number): void;
write?(this: Transform, chunk: any, encoding: BufferEncoding, callback: (error?: Error | null) => void): void;
writev?(this: Transform, chunks: Array<{ chunk: any, encoding: BufferEncoding }>, callback: (error?: Error | null) => void): void;
final?(this: Transform, callback: (error?: Error | null) => void): void;
destroy?(this: Transform, error: Error | null, callback: (error: Error | null) => void): void;
transform?(this: Transform, chunk: any, encoding: BufferEncoding, callback: TransformCallback): void;
flush?(this: Transform, callback: TransformCallback): void;
}
class Transform extends Duplex {
constructor(opts?: TransformOptions);
_transform(chunk: any, encoding: BufferEncoding, callback: TransformCallback): void;
_flush(callback: TransformCallback): void;
}
class PassThrough extends Transform { }
interface FinishedOptions {
error?: boolean | undefined;
readable?: boolean | undefined;
writable?: boolean | undefined;
}
function finished(stream: NodeJS.ReadableStream | NodeJS.WritableStream | NodeJS.ReadWriteStream, options: FinishedOptions, callback: (err?: NodeJS.ErrnoException | null) => void): () => void;
function finished(stream: NodeJS.ReadableStream | NodeJS.WritableStream | NodeJS.ReadWriteStream, callback: (err?: NodeJS.ErrnoException | null) => void): () => void;
namespace finished {
function __promisify__(stream: NodeJS.ReadableStream | NodeJS.WritableStream | NodeJS.ReadWriteStream, options?: FinishedOptions): Promise<void>;
}
function pipeline<T extends NodeJS.WritableStream>(stream1: NodeJS.ReadableStream, stream2: T, callback?: (err: NodeJS.ErrnoException | null) => void): T;
function pipeline<T extends NodeJS.WritableStream>(stream1: NodeJS.ReadableStream, stream2: NodeJS.ReadWriteStream, stream3: T, callback?: (err: NodeJS.ErrnoException | null) => void): T;
function pipeline<T extends NodeJS.WritableStream>(
stream1: NodeJS.ReadableStream,
stream2: NodeJS.ReadWriteStream,
stream3: NodeJS.ReadWriteStream,
stream4: T,
callback?: (err: NodeJS.ErrnoException | null) => void,
): T;
function pipeline<T extends NodeJS.WritableStream>(
stream1: NodeJS.ReadableStream,
stream2: NodeJS.ReadWriteStream,
stream3: NodeJS.ReadWriteStream,
stream4: NodeJS.ReadWriteStream,
stream5: T,
callback?: (err: NodeJS.ErrnoException | null) => void,
): T;
function pipeline(
streams: ReadonlyArray<NodeJS.ReadableStream | NodeJS.WritableStream | NodeJS.ReadWriteStream>,
callback?: (err: NodeJS.ErrnoException | null) => void,
): NodeJS.WritableStream;
function pipeline(
stream1: NodeJS.ReadableStream,
stream2: NodeJS.ReadWriteStream | NodeJS.WritableStream,
...streams: Array<NodeJS.ReadWriteStream | NodeJS.WritableStream | ((err: NodeJS.ErrnoException | null) => void)>,
): NodeJS.WritableStream;
namespace pipeline {
function __promisify__(stream1: NodeJS.ReadableStream, stream2: NodeJS.WritableStream): Promise<void>;
function __promisify__(stream1: NodeJS.ReadableStream, stream2: NodeJS.ReadWriteStream, stream3: NodeJS.WritableStream): Promise<void>;
function __promisify__(stream1: NodeJS.ReadableStream, stream2: NodeJS.ReadWriteStream, stream3: NodeJS.ReadWriteStream, stream4: NodeJS.WritableStream): Promise<void>;
function __promisify__(
stream1: NodeJS.ReadableStream,
stream2: NodeJS.ReadWriteStream,
stream3: NodeJS.ReadWriteStream,
stream4: NodeJS.ReadWriteStream,
stream5: NodeJS.WritableStream,
): Promise<void>;
function __promisify__(streams: ReadonlyArray<NodeJS.ReadableStream | NodeJS.WritableStream | NodeJS.ReadWriteStream>): Promise<void>;
function __promisify__(
stream1: NodeJS.ReadableStream,
stream2: NodeJS.ReadWriteStream | NodeJS.WritableStream,
...streams: Array<NodeJS.ReadWriteStream | NodeJS.WritableStream>,
): Promise<void>;
}
interface Pipe {
close(): void;
hasRef(): boolean;
ref(): void;
unref(): void;
}
}
export = internal;
}

Some files were not shown because too many files have changed in this diff Show More