Compare commits

..

260 Commits

Author SHA1 Message Date
Nick O'Leary
269cf02c0b Merge pull request #4586 from node-red/rel316
Bump for 3.1.6 release
2024-03-01 11:47:57 +00:00
Nick O'Leary
fb50e2772a Bump for 3.1.6 release 2024-03-01 10:50:06 +00:00
Nick O'Leary
058c97138a Merge pull request #4582 from node-red/3795-allow-env-var-in-num-field-validation
Do not flag env var in num typedInput as error
2024-02-26 17:01:45 +00:00
Nick O'Leary
828ae29aed Merge pull request #4581 from node-red/4579-fix-undef-env-vars
Handle undefined env vars
2024-02-26 17:01:27 +00:00
Nick O'Leary
6a0f45140c Merge pull request #4568 from JaysonHurst/fips
fix: Removed offending MD5 crypto hash and replaced with SHA1 and SHA256 …
2024-02-26 17:00:26 +00:00
Nick O'Leary
50a267528d Merge pull request #4580 from giscafer/remove-never-use-code
chore: remove never use import code
2024-02-26 16:58:20 +00:00
Nick O'Leary
220786be60 Do not flag env var in num typedInput as error 2024-02-26 16:55:01 +00:00
Nick O'Leary
fa78bb3d78 Handle undefined env vars
Fixes #4579
2024-02-26 16:17:09 +00:00
Nick O'Leary
9a32ebd0c0 Merge pull request #4578 from kazuhitoyokoi/master-fiximportdialog
Fix example flow name in import dialog
2024-02-26 16:09:10 +00:00
giscafer
4643f5e8cc chore: remove never use import code 2024-02-25 22:44:01 +08:00
Kazuhito Yokoi
7de0984d6d Update test case for example flow name 2024-02-25 17:38:46 +09:00
Kazuhito Yokoi
635334f096 Fix example flow name in import dialog 2024-02-25 17:04:42 +09:00
Nick O'Leary
f0d0990b5a Merge pull request #4575 from giscafer/master
fix: template node zh-CN translation
2024-02-22 13:03:24 +00:00
giscafer
43b3589451 fix: template node zh-CN translation 2024-02-22 13:02:06 +08:00
Nick O'Leary
016a19ba7c Merge pull request #4570 from node-red/fix-icon-scaling
Fix missing node icons in workspace
2024-02-20 10:37:33 +00:00
Nick O'Leary
aeb79bce2a Fix missing node icons in workspace 2024-02-19 16:07:22 +00:00
Jayson Hurst
0ab9b9a5fd Merge branch 'master' into fips 2024-02-16 17:53:30 -07:00
Jayson Hurst
56e58521bd Removed offending MD5 crypto hash and replaced with SHA1 and SHA256 crypto hashes to work with the FIPS crypto policy. 2024-02-17 00:35:03 +00:00
Nick O'Leary
b10ef4c98c Merge pull request #4564 from node-red/rel315
Bump for 3.1.5 release
2024-02-08 15:37:48 +00:00
Nick O'Leary
3ff038fb98 Bump for 3.1.5 release 2024-02-08 15:32:53 +00:00
Nick O'Leary
adb498af24 Merge pull request #4562 from node-red/fix-require
Fix require of dns module
2024-02-07 15:24:10 +00:00
Nick O'Leary
fc67a2efc2 Merge pull request #4561 from node-red/4560-fix-global-env-cred
Ensure global creds object is initialised when adding first cred
2024-02-07 14:52:17 +00:00
Nick O'Leary
55771c7241 Fix require of dns module 2024-02-07 14:50:46 +00:00
Nick O'Leary
109fa5f04e Ensure global creds object is initialised when adding first cred 2024-02-07 10:02:22 +00:00
Nick O'Leary
1f412f3d78 Merge pull request #4558 from node-red/rel314
Updates for 3.1.4 release
2024-02-06 16:58:29 +00:00
Nick O'Leary
2b69f52c92 Bump dependencies in packages 2024-02-06 16:54:05 +00:00
Nick O'Leary
6e90798f16 Updates for 3.1.4 release 2024-02-06 16:51:59 +00:00
Nick O'Leary
3994b404a1 Merge pull request #4477 from GogoVega/french-translation-v3.1.3-changes
Add French translation of v3.1.3 changes
2024-02-06 16:37:20 +00:00
Nick O'Leary
0b7e8ec323 Merge pull request #4495 from joebordes/joebordes/i18n_001
i18n(es-ES) Spanish Spain translation
2024-02-06 16:36:45 +00:00
Nick O'Leary
bb0b547d5a Merge pull request #4550 from node-red/4549-improve-import-confict-dialog
Improve feedback in import dialog to show conflicted nodes
2024-02-06 16:36:15 +00:00
Nick O'Leary
1e1acc7ad7 Merge pull request #4556 from node-red/4548-handle-replacement-config-unknown
Handle modified-nodes deploy after replacing unknown config node
2024-02-06 16:36:02 +00:00
Nick O'Leary
1419432b04 Merge branch 'master' into joebordes/i18n_001 2024-02-05 16:47:55 +00:00
Nick O'Leary
1a521d7e09 Merge branch 'master' into 4548-handle-replacement-config-unknown 2024-02-05 16:46:04 +00:00
Nick O'Leary
5858d2789a Add FR translation 2024-02-05 16:44:55 +00:00
Nick O'Leary
6a1e4fac5a Merge pull request #4552 from guidoffm/patch-1
Update editor.json fix typo in German translation
2024-02-05 16:42:24 +00:00
Nick O'Leary
bab6e57a59 Merge pull request #4539 from node-red/4536-handle-undefined-default-export
Handle undefined default export when importing module
2024-02-05 16:36:06 +00:00
Nick O'Leary
4ed53fb622 Merge pull request #4531 from GogoVega/i18n-languages-list
Do not translate the list of available languages
2024-02-05 16:35:45 +00:00
Nick O'Leary
e17775c435 Merge pull request #4554 from node-red/dependabot/github_actions/github-actions-894fc5cb1d
Bump the github-actions group with 1 update
2024-02-05 16:32:44 +00:00
Nick O'Leary
565c212779 Handle modified-nodes deploy after replacing unknown config node
Fixes #4548
2024-02-05 16:22:58 +00:00
dependabot[bot]
b54e9d8d55 Bump the github-actions group with 1 update
Bumps the github-actions group with 1 update: [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request).


Updates `peter-evans/create-pull-request` from 5 to 6
- [Release notes](https://github.com/peter-evans/create-pull-request/releases)
- [Commits](https://github.com/peter-evans/create-pull-request/compare/v5...v6)

---
updated-dependencies:
- dependency-name: peter-evans/create-pull-request
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-01 07:29:17 +00:00
Guido Mülller (Guido Mueller)
861c89a0cc Update editor.json fix typo in German translation 2024-01-30 10:35:54 +01:00
Nick O'Leary
4268a04a04 Improve feedback in import dialog to show conflicted nodes
Fixes #4549
2024-01-29 17:48:01 +00:00
Nick O'Leary
9bd7131914 Merge pull request #4544 from GogoVega/fix-creds-convert-node
(convertNode) Do not create the credentials object if there is nothing to export
2024-01-26 13:49:56 +00:00
Nick O'Leary
8485ca254f Merge pull request #4538 from node-red/4533-fix-subflow-instance-g-property-mapping
Ensure subflow instance node has g property set
2024-01-26 13:48:07 +00:00
Nick O'Leary
507f9b68eb Merge pull request #4546 from node-red/4545-importing-duplicate-subflow
Handle importing flow with existing subflow and instance node
2024-01-26 13:47:20 +00:00
Nick O'Leary
f7b726372f Handle importing flow with existing subflow and instance node
Fixes #4545
2024-01-25 17:26:52 +00:00
GogoVega
14811b5aec Do not create the credentials object if not exported 2024-01-25 15:35:40 +01:00
Nick O'Leary
c24f05c2cd Handle undefined default export when importing module
Fixes #4536
2024-01-22 16:54:51 +00:00
Nick O'Leary
d2dc1fcc80 Ensure subflow instance node has g property set 2024-01-22 16:28:22 +00:00
Joe Bordes
97e05c8784 i18n(Editor) sync ES with #4531 to centralize list of languages 2024-01-20 20:36:47 +01:00
Joe Bordes
26cb03da42 i18n(Editor) sync ES with lastest changes 2024-01-20 20:36:01 +01:00
Joe Bordes
d5a8b1592c Merge branch 'master' into joebordes/i18n_001 2024-01-20 20:26:05 +01:00
Nick O'Leary
5b096bfd5e Merge pull request #4483 from gorenje/patch-1
Update index.mst
2024-01-19 17:13:09 +00:00
Nick O'Leary
a1e242ec1e Merge branch 'master' into patch-1 2024-01-19 16:14:20 +00:00
Nick O'Leary
5b9d002f56 Merge pull request #4529 from node-red/4397-hightlight-config-node-errors
Highlight errors in config node sidebar
2024-01-19 16:08:17 +00:00
GogoVega
dd57323889 Do not translate the list of available languages 2024-01-19 10:00:32 +01:00
Nick O'Leary
6620679008 Show standard validation triangle on config nodes 2024-01-16 17:35:50 +00:00
Nick O'Leary
f93654f680 Merge pull request #4527 from node-red/4485-copy-context-path
Include top level property name when copying path from context
2024-01-16 11:59:50 +00:00
Nick O'Leary
1bef0c32a2 Merge pull request #4519 from node-red/4479-ensure-env-not-modified
Clone objects types when getting env values
2024-01-16 11:59:37 +00:00
Nick O'Leary
a5725c59fd Merge pull request #4526 from node-red/4508
Ensure global-config credential env vars are merged on deploy
2024-01-16 11:58:20 +00:00
Nick O'Leary
4168bbb751 Merge pull request #4528 from node-red/4497-fix-config-footer-css
Modify node users info in config editor footer
2024-01-16 11:58:07 +00:00
Nick O'Leary
b0086edcf9 Update packages/node_modules/@node-red/editor-client/src/sass/tab-config.scss
Co-authored-by: Mauricio Bonani <bonanitech@gmail.com>
2024-01-15 20:16:18 +00:00
Nick O'Leary
89c2efe17d Highlight errors in config node sidebar
Fixes #4397
2024-01-15 17:49:17 +00:00
Nick O'Leary
9030b7d27c Merge pull request #4491 from ralphwetzel/master_fix_icon_resize
Fix icon scaling for non .svg icons
2024-01-15 17:20:14 +00:00
Nick O'Leary
de5111b13f Merge pull request #4522 from gorenje/remove_unused_code
21-httprequest.js remove unused code, because of broken use of toLowercase
2024-01-15 17:17:43 +00:00
Nick O'Leary
8600f4131e Modify node users info in config editor footer
Fixes #4497
2024-01-15 17:11:54 +00:00
Nick O'Leary
8a8245b560 Include top level property name when copying path from context
Fixes #4485
2024-01-15 16:54:16 +00:00
Nick O'Leary
58e2fcbeee Ensure global-config credential env vars are merged on deploy
Fixes #4508
2024-01-15 16:44:43 +00:00
Nick O'Leary
282bb6c414 Merge pull request #4512 from node-red/4503-fix-cache-busting
Restore caching busting functionality without using explict version number
2024-01-15 15:54:40 +00:00
Gerrit Riessen
962fc5990e Merge remote-tracking branch 'nodered/master' into remove_unused_code 2024-01-11 12:04:02 +01:00
Gerrit Riessen
eb2f57fc0d removed unused code 2024-01-11 12:03:28 +01:00
Nick O'Leary
ce5b6a8024 Merge pull request #4487 from GogoVega/fix-validation-nls
Add missing validation messages
2024-01-08 23:42:58 +00:00
Nick O'Leary
0773edcaff Merge pull request #4498 from kazuhitoyokoi/master-jpn3.1.3
Add Japanese translations for v3.1.3
2024-01-08 23:42:35 +00:00
Nick O'Leary
68dcf7bceb Merge pull request #4500 from kazuhitoyokoi/master-disablemenuitems
Add handling to disable items on context menu
2024-01-08 23:42:19 +00:00
Nick O'Leary
d876146ea5 Guard settings access 2024-01-08 23:37:44 +00:00
Nick O'Leary
50627cd697 Generate instanceId and include in hash for cache busting 2024-01-08 23:27:14 +00:00
Nick O'Leary
3a6b1e86dc Clone objects types when getting env values
Fixes #4479
2024-01-08 20:56:17 +00:00
Nick O'Leary
6a4d293352 Merge pull request #4516 from kazuhitoyokoi/master-fixfocus4contextmenu
Focus Quick Add dialog from context menu
2024-01-08 17:04:00 +00:00
Nick O'Leary
1ad4fe44e2 Merge pull request #4518 from kazuhitoyokoi/master-fixquickadddialog4sf
Fix subflow ports in Quick Add dialog
2024-01-08 17:03:13 +00:00
Kazuhito Yokoi
59ea7a4f70 Fix subflow ports in Quick Add dialog 2024-01-08 03:12:36 +09:00
Kazuhito Yokoi
6c64ba45c2 Focus Quick Add dialog from context menu 2024-01-07 20:46:50 +09:00
Kazuhito Yokoi
c68cc4ac19 Merge branch 'master' into master-disablemenuitems 2024-01-07 18:47:12 +09:00
Kazuhito Yokoi
84ed88c8dd Use single forEach instead of multiple filter 2024-01-07 18:41:08 +09:00
Nick O'Leary
d7345d5bc6 Restore caching busting functionality without using explict version number
Fixes #4503
2024-01-05 23:14:00 +00:00
Nick O'Leary
f0a9b0cf69 Merge pull request #4506 from GogoVega/fix-4505-menu-flow-edit-label
Replace `rename` by `edit` for the menu flow label
2024-01-05 21:00:29 +00:00
Nick O'Leary
26ddb5c1b7 Merge pull request #4502 from kazuhitoyokoi/master-fixsubflowports
Fix location of subflow ports in palette
2024-01-05 20:59:45 +00:00
Nick O'Leary
82f8b64599 Merge pull request #4484 from gorenje/patch-2
Client/Editor Events: fix off-in-on pattern emulating once
2024-01-05 20:56:43 +00:00
GogoVega
7f24de442f Replace 'rename' with 'edit' for the flow label 2024-01-01 15:33:39 +01:00
GogoVega
c3536fd7c7 Removes translation of interpolation keys 2024-01-01 15:02:48 +01:00
Kazuhito Yokoi
8365310ca7 Put the changed code on one line to avoid jshint error 2023-12-29 20:32:14 +09:00
Kazuhito Yokoi
aaed9882b8 Add handling to disable items on context menu for node labels 2023-12-29 17:51:03 +09:00
Kazuhito Yokoi
8f5ebfcede Update Japanese translation for v3.1.3 2023-12-29 15:41:40 +09:00
Joe Bordes
83279df0fa i18n(es-ES) node help screens 2023-12-27 18:28:54 +01:00
Joe Bordes
2550da9c6e i18n(es-ES) node help screens 2023-12-27 16:06:41 +01:00
Joe Bordes
041f00b811 i18n(es-ES) node help screens 2023-12-27 11:57:02 +01:00
Joe Bordes
21cd4aaeb6 i18n(es-ES) node help screens 2023-12-26 13:16:02 +01:00
Joe Bordes
70ce1e648d i18n(es-ES) messages and runtime. start working on node help screens 2023-12-26 11:42:23 +01:00
Joe Bordes
eab5a9772b i18n(es-ES) Spanish Spain translation 2023-12-24 20:50:40 +01:00
Kazuhito Yokoi
74ff0599d1 Fix location of subflow ports in palette 2023-12-23 19:51:57 +09:00
Ralph Wetzel
c31e622160 Fix icon scaling for non .svg icons 2023-12-20 17:14:12 +01:00
GogoVega
1828d8a279 Add missing validation messages 2023-12-17 19:59:16 +01:00
Kazuhito Yokoi
70ea5c839a Add handling to disable items on context menu 2023-12-16 17:02:18 +09:00
Gerrit Riessen
0b0f1f8701 Update index.mst
Update two additional path specifications
2023-12-15 11:32:26 +01:00
Gerrit Riessen
e1f2e0656b Client Events: fix off-in-on pattern emulating once
This fixes an issue when RED.events.off(..) is called in a RED.events.on(..) callback:

```
let cb = () => {
  RED.events.off("event-name", cb)
  ....
}
RED.events.on("event-name", cb)
```

This pattern emulates a once(..), i.e., execute a callback once-only for an event.

Discussed in [Forum](https://discourse.nodered.org/t/event-offing-an-on-event-to-perform-only-once/83726)
2023-12-15 10:54:11 +01:00
Gerrit Riessen
b5e955bd5e Update index.mst
Avoid escaping slashes (`/`) in asset paths. 

Content is currently generated as:

```
<title>Node-RED</title>
<link rel="icon" type="image/png" href="favicon.ico">
<link rel="mask-icon" href="red&#x2F;images&#x2F;node-red-icon-black.svg" color="#8f0000">
<link rel="stylesheet" href="vendor/jquery/css/base/jquery-ui.min.css?v=">
<link rel="stylesheet" href="vendor/font-awesome/css/font-awesome.min.css?v=">
<link rel="stylesheet" href="red/style.min.css?v=">
<link rel="stylesheet" href="vendor/monaco/style.css?v=">
</head>
<body spellcheck="false">
<div id="red-ui-editor"></div>
<script src="vendor/vendor.js?v="></script>
<script src="vendor&#x2F;monaco&#x2F;monaco-bootstrap.js?v="></script>
<script src="red&#x2F;red.min.js?v="></script>
<script src="red&#x2F;main.min.js?v="></script>
```

It still works of course, so feel free to ignore this change.
2023-12-13 17:29:39 +01:00
GogoVega
b4b5d296d9 French translation of v3.1.3 changes 2023-12-08 09:47:00 +01:00
Kazuhito Yokoi
d287b8867b Add Japanese translations for v3.1.3 2023-12-08 15:28:49 +09:00
Nick O'Leary
0e8d312794 Merge pull request #4476 from node-red/rel313
Bump for 3.1.3 release
2023-12-07 20:30:08 +00:00
Nick O'Leary
c584d51432 Bump for 3.1.3 release 2023-12-07 18:27:33 +00:00
Nick O'Leary
2366b4508f Merge pull request #4475 from node-red/fix-nls
Add missing en-us messages
2023-12-07 18:25:37 +00:00
Nick O'Leary
2f1565fbc9 Add missing en-us messages 2023-12-07 18:19:37 +00:00
Nick O'Leary
7fd0ecf721 Merge pull request #4474 from node-red/rel312
Bump for 3.1.2 release
2023-12-07 14:23:56 +00:00
Nick O'Leary
37d1539fda Bump for 3.1.2 release 2023-12-07 14:12:53 +00:00
Nick O'Leary
1e518396d6 Merge pull request #4470 from wangyiyi2056/Add-action-list-Chinese-translation
Added action list Chinese (Simplified and Traditional) translation + v3.1.1 changes
2023-12-07 13:59:54 +00:00
Nick O'Leary
617b98ed49 Merge pull request #4466 from GogoVega/add-action-list-translation
Add French translation of `action-list` + v3.1.1 changes
2023-12-07 13:56:25 +00:00
Nick O'Leary
6d2a870812 Merge pull request #4472 from node-red/fix-nested-groups-in-subflow
Ensure nested groups inside subflows have their g props remapped
2023-12-07 13:42:14 +00:00
Nick O'Leary
2963f3f1b8 Ensure nested groups inside subflows have their g props remapped 2023-12-07 11:47:02 +00:00
wangyiyi2056
17e4bdbff1 Merge branch 'master' into Add-action-list-Chinese-translation 2023-12-07 09:19:46 +08:00
Nick O'Leary
f3dd5770d9 Merge pull request #4471 from node-red/relax-validation
Relax some node validators to allow undefined value
2023-12-06 12:11:30 +00:00
Nick O'Leary
eebab4a921 Relax some node validators to allow undefined value 2023-12-06 10:30:49 +00:00
Nick O'Leary
b06494c5be Merge pull request #4465 from node-red/4464-fix-switch-typeof-validation
Fix switch validation of typeof field
2023-12-06 10:09:39 +00:00
wangyiyi2056
a0562bef81 Added action list Chinese translation + v3.1.1 2023-12-05 22:50:03 +08:00
Nick O'Leary
eff063a748 Merge pull request #4467 from node-red/fix-group-mouse-pointer
Use move cursor when hovering on group border
2023-12-04 15:55:15 +00:00
Nick O'Leary
94abaaff1e Use move cursor when hovering on group border 2023-12-04 11:49:29 +00:00
GogoVega
03732869e4 Fix that little guy hiding 2023-12-02 18:53:06 +01:00
GogoVega
41868e2652 Apply v3.1.1 changes 2023-12-02 16:16:03 +01:00
GogoVega
81bfba3cea Add actions list translation 2023-12-02 16:10:52 +01:00
Nick O'Leary
8a04eb2e29 Update packages/node_modules/@node-red/nodes/core/function/10-switch.html 2023-12-01 19:40:49 +00:00
Nick O'Leary
1777fc749d Fix switch validation of typeof field
Fixes #4464
2023-12-01 13:11:07 +00:00
Nick O'Leary
fd32ee09ff Merge pull request #4462 from node-red/rel311
Bump for 3.1.1 release
2023-11-30 16:14:40 +00:00
Nick O'Leary
4bb2157cab Bump for 3.1.1 release 2023-11-30 15:49:57 +00:00
Nick O'Leary
47f20cc86a Merge pull request #4404 from node-red/dependabot/github_actions/github-actions-62712cefbd
Bump the github-actions group with 2 updates
2023-11-30 15:15:42 +00:00
Nick O'Leary
5fc4526c70 Merge pull request #4461 from node-red/fix-debug-filter
Fix debug filter
2023-11-30 15:15:04 +00:00
Nick O'Leary
9fe653f821 Merge branch 'master' into fix-debug-filter 2023-11-30 15:08:14 +00:00
Nick O'Leary
55da21ed15 Merge pull request #4460 from node-red/4369-improve-error-handling-in-subflowmodule-parsing
Handle unknown node reference inside subflow module
2023-11-30 15:07:58 +00:00
Nick O'Leary
7ebf84f38c Fix debug filter 2023-11-30 14:50:28 +00:00
Nick O'Leary
d42e75ebd0 Handle unknown node reference inside subflow module 2023-11-30 14:46:43 +00:00
Nick O'Leary
28825049fe Merge pull request #4459 from node-red/4401-fix-debug-window
Fix various issues with debug pop-out window
2023-11-30 11:36:16 +00:00
Nick O'Leary
1c3644e338 Fix various issues with debug pop-out window 2023-11-30 11:23:35 +00:00
Nick O'Leary
2dfabb523b Merge pull request #4457 from node-red/4456-fix-group-in-subflow-lookup
Ensure subflow instances keep track of their groups
2023-11-29 16:41:52 +00:00
Nick O'Leary
3e2d20e536 Merge pull request #4455 from GogoVega/4429-fix-validateNodeProperty
Fix `validateNodeProperty` without validator provided
2023-11-29 16:19:41 +00:00
Nick O'Leary
ee7ee083b0 Merge pull request #4440 from node-red/4429-add-typed-validators
Add validators to any fields using msg-typed Input
2023-11-29 16:18:53 +00:00
Nick O'Leary
fb54c05d9f Ensure subflow instances keep track of their groups 2023-11-29 16:12:12 +00:00
Nick O'Leary
21f807aa66 Merge pull request #4453 from node-red/4413-debounce-uninstall-notifications
Debounce node-removed notifications
2023-11-29 16:11:18 +00:00
Nick O'Leary
6b088bda12 Merge pull request #4452 from node-red/4443-add-modules-install-audit-event
Add modules.install audit event when external module installed
2023-11-29 16:11:04 +00:00
Nick O'Leary
a32ee869ae Merge pull request #4448 from bonanitech/first-commit-has-no-parents
Don't try to load the parents of the first commit
2023-11-29 16:10:42 +00:00
GogoVega
a2d7772958 Fix validateNodeProperty if no validator provided 2023-11-28 20:13:25 +01:00
Stephen McLaughlin
6ec052be18 Merge pull request #4454 from node-red/4380-mqtt-undefined-value
Guard against node.broker being undefined
2023-11-27 17:48:02 +00:00
Nick O'Leary
9c71d52d69 Check node.broker is a string before trying to use it
Fixes #4380
2023-11-27 17:27:32 +00:00
Nick O'Leary
171c146ec5 Debounce node-removed notifications
Fixes #4413
2023-11-27 17:14:15 +00:00
Nick O'Leary
bc6afa2164 Add modules.install audit event when external module installed 2023-11-27 16:58:14 +00:00
Stephen McLaughlin
3c036257ef Merge pull request #4451 from node-red/4446-allow-import-of-subpath-modules
Allow import of modules with subpath in specifier
2023-11-27 16:57:32 +00:00
Nick O'Leary
6633730bf1 Allow import of modules with subpath in specifier
Fixes #4446
2023-11-27 16:44:56 +00:00
Mauricio Bonani
2964a4da5e Don't try to load the parents of the first commit 2023-11-24 16:22:29 -05:00
Stephen McLaughlin
a55554193b Merge pull request #4441 from node-red/4274-allow-theme-to-set-mermaid-theme
Allow a theme to specifiy which theme mermaid should use
2023-11-20 21:43:03 +00:00
Nick O'Leary
d2a8338d4a Rename mermaidOptions to mermaid for contrib themes 2023-11-20 17:50:59 +00:00
Nick O'Leary
e945deeab6 Allow mermaid theme to be set via editorTheme and custom themes
Fixes #4274
2023-11-20 17:47:39 +00:00
Nick O'Leary
722fe02933 Add validators to any fields using msg-typed Input
Fixes #4429
2023-11-20 17:17:52 +00:00
Nick O'Leary
3dec609459 Merge pull request #4438 from node-red/update-deps-2
Update node-red-admin version
2023-11-20 10:00:44 +01:00
Nick O'Leary
e73b9f646d Update nr package to match 2023-11-17 10:44:34 +00:00
Nick O'Leary
3cea6400d1 Update node-red-admin version 2023-11-17 10:42:06 +00:00
Nick O'Leary
c6a8eee73d Merge pull request #4416 from node-red/mqtt-check-topic-length
check topic length > 0 before publish
2023-11-07 17:46:33 +00:00
Nick O'Leary
74d431ea36 Merge pull request #4427 from node-red/4394-update-page-title-on-flow-nav
Update browser title with flow name if set
2023-11-07 17:40:36 +00:00
Nick O'Leary
409a559a13 Merge pull request #4411 from node-red/4376-handle-falsy-env-vars
Handle false-like env vars properly
2023-11-07 17:40:18 +00:00
Nick O'Leary
6829535350 Merge pull request #4409 from node-red/4381-avoid-multiple-settings-saves
Only save settings once during node load process
2023-11-07 17:40:03 +00:00
Nick O'Leary
6488111f79 Merge pull request #4423 from node-red/4415-handle-excluded-core-nodes
Ensure typeSearch handles undefined node definitions
2023-11-07 17:39:46 +00:00
Nick O'Leary
923339c1d8 Merge pull request #4426 from node-red/4044-group-bb-import
Ensure group w/h are imported if present
2023-11-07 17:39:30 +00:00
Nick O'Leary
3f4d96f4cd Merge pull request #4425 from node-red/4418-fix-empty-status-background
Hide node status background when there is no status to show
2023-11-07 17:26:00 +00:00
Nick O'Leary
c52985d245 Update browser title with flow name if set
Fixes #4394
2023-11-07 17:24:04 +00:00
Nick O'Leary
88e6c71aa0 Ensure group w/h are imported if present
Fixes #4044
2023-11-07 17:09:22 +00:00
Nick O'Leary
4d08e297c4 Hide node status background when there is no status to show
Fixes #4418
2023-11-07 16:34:36 +00:00
Nick O'Leary
ad2b30691f Ensure typeSearch handles undefined node definitions
Fixes #4415
2023-11-03 11:28:04 +01:00
Dave Conway-Jones
369bad01b8 check topic length > 0 before publish
to close #4414
2023-11-03 08:55:38 +00:00
Nick O'Leary
b6ecc6d9ea Handle false-like env vars properly 2023-11-02 00:40:55 +01:00
Nick O'Leary
0117df0960 Only save settings once during node load process 2023-11-01 16:18:03 +01:00
Nick O'Leary
6ac905f264 Merge pull request #4407 from node-red/4392-add-close-button-to-restart-notification
Add a close button to the restart-required notification
2023-11-01 15:20:48 +01:00
Nick O'Leary
e5307f6604 Add a close button to the restart-required notification
Fixes #4392
2023-11-01 14:39:51 +01:00
Nick O'Leary
8d9b6dd859 Merge pull request #4405 from node-red/4396-fix-global-config-cred-lookup
Ensure global-config nodes lookup cred values properly
2023-11-01 14:20:56 +01:00
Nick O'Leary
01821ead0f Merge pull request #4371 from ralphwetzel/master
Extend typedInput "num" type validity check to NaN, binary, octal & hex
2023-11-01 14:20:31 +01:00
Nick O'Leary
1451fb9e2f Merge pull request #4399 from kazuhitoyokoi/master-fixrepeat4inject
Fix unintended new line in node name
2023-11-01 14:17:21 +01:00
Nick O'Leary
245751bb23 Merge pull request #4382 from hazymat/master
Ctrl-Enter does not close tray (Monaco) #4377
2023-11-01 14:15:08 +01:00
Nick O'Leary
f07519c705 Merge pull request #4393 from node-red/Fix-buffer-viewer-to-handle-0b-style-
fix buffer viewer to handle 0b style binary
2023-11-01 14:14:20 +01:00
Nick O'Leary
33a978a246 Ensure credentials.get stub is restored after tests 2023-11-01 14:12:20 +01:00
Nick O'Leary
861dc0c383 Ensure global-config nodes lookup cred values properly
Fixes #4396
2023-11-01 11:07:48 +01:00
dependabot[bot]
60593fed4a Bump the github-actions group with 2 updates
Bumps the github-actions group with 2 updates: [actions/setup-node](https://github.com/actions/setup-node) and [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request).


Updates `actions/setup-node` from 3 to 4
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/v3...v4)

Updates `peter-evans/create-pull-request` from 2 to 5
- [Release notes](https://github.com/peter-evans/create-pull-request/releases)
- [Commits](https://github.com/peter-evans/create-pull-request/compare/v2...v5)

---
updated-dependencies:
- dependency-name: actions/setup-node
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
- dependency-name: peter-evans/create-pull-request
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-01 07:42:43 +00:00
Kazuhito Yokoi
fae3a5c26a Fix unintended new line in node name 2023-10-29 14:58:03 +09:00
Dave Conway-Jones
1a52c0adfc fix buffer viewer to handle 0b style binary 2023-10-24 23:15:34 +01:00
Mat Smith
44c0bbc61e Ctrl-Enter does not close tray (Monaco) #4377 2023-10-12 18:53:34 +01:00
ralphwetzel
5ac50fae3a Extend typedInput "num" type validity check to NaN, binary, octal & hex 2023-09-26 20:00:48 +02:00
Nick O'Leary
ee48a2f2bf Merge pull request #4362 from node-red/4342-subflow-err
Handle credential env var evaluation when no value set
2023-09-25 18:20:28 +01:00
Nick O'Leary
680d5b8216 Merge pull request #4364 from node-red/4323-redo-mermaid-integration
Rework mermaid integration to support off-DOM rendering
2023-09-25 18:08:48 +01:00
Nick O'Leary
c9320c190d Ensure creds object is not undefined when evaling env vars 2023-09-25 18:08:02 +01:00
Nick O'Leary
566c667c5d Merge pull request #4354 from bonanitech/ignore-package-lock
Don't commit package-lock.json
2023-09-25 18:05:46 +01:00
Nick O'Leary
ec6e42e655 Merge pull request #4361 from node-red/4342-fix-subflow-env-self-reference
Fix env evaluation when one env references another in the same object
2023-09-25 18:04:58 +01:00
Nick O'Leary
bba6b6f71d Merge pull request #4365 from node-red/4334-context-labels
Add missing nls labels to context menu
2023-09-25 18:04:35 +01:00
Nick O'Leary
c261f6625a Merge pull request #4368 from node-red/4340-switch-validation
Improve validation of switch/change node rules
2023-09-25 18:04:19 +01:00
Nick O'Leary
a489b270d1 Remove extra debug 2023-09-25 17:38:16 +01:00
Nick O'Leary
51cb61940d Improve validation of switch/change node rules
Fixes #4340
2023-09-25 17:33:59 +01:00
Nick O'Leary
ce2f896b45 Add missing nls labels to context menu
Fixes #4334
2023-09-22 16:29:33 +01:00
Nick O'Leary
6635ff9a69 Rework mermaid integration to support off-DOM rendering 2023-09-22 15:23:01 +01:00
Nick O'Leary
41797f8cef Handle credential env var evaluation when no value set 2023-09-22 13:56:54 +01:00
Nick O'Leary
797cea5394 Fix env evaluation when one env references another in the same object
Fixes #4342
2023-09-22 13:49:54 +01:00
Mauricio Bonani
2880d4120e Don't commit package-lock.json 2023-09-19 14:58:44 -04:00
Nick O'Leary
58dec7b9b0 Merge pull request #4312 from Rotzbua/add_dependabot
Add dependabot for Github Actions
2023-09-19 09:28:50 +01:00
Nick O'Leary
b0f900e25d Merge pull request #4311 from Rotzbua/update_gh_actions
Update outdated Github Actions
2023-09-19 09:28:19 +01:00
Nick O'Leary
fc54848318 Merge pull request #4349 from braincube-io/feat/fmo/makeCsvExportFast
Performance : make CSV export way faster by not re-allocating and handling huge string
2023-09-19 09:22:54 +01:00
Nick O'Leary
2f9f8cda81 Merge pull request #4350 from node-red/Fix-delay-node-passing-on-reset-regression
Fix regression in delay node to not pass on msg.reset
2023-09-19 09:21:33 +01:00
Nick O'Leary
667e7ab8dc Merge pull request #4348 from ZJvandeWeg/patch-2
github: Request `npm run test` in PR template
2023-09-19 09:21:06 +01:00
Nick O'Leary
4e55408fed Merge pull request #4346 from kazuhitoyokoi/master-fixheight4templete
Fix height of description editor in template node
2023-09-19 09:20:09 +01:00
Nick O'Leary
88aa61ea77 Merge pull request #4329 from GogoVega/french-translation-v3.1-beta.4-changes
Add French translation of v3.1.0-beta.4 changes + slight improvements
2023-09-19 09:19:49 +01:00
Nick O'Leary
2ccdeb968c Merge pull request #4332 from node-red/4330-fix-multiple-input-handlers
Handle nodes with multiple input handlers properly
2023-09-19 09:19:22 +01:00
Nick O'Leary
90045683c9 Merge pull request #4331 from node-red/fix-unexpected-link-validation-err
Handle undefined linkType value for existing link-call nodes
2023-09-19 09:18:50 +01:00
Nick O'Leary
eb49b01cbc Merge pull request #4351 from node-red/knolleary-patch-1
Soften the language around unrequited PRs
2023-09-19 09:18:26 +01:00
Nick O'Leary
3a6062775e Update CONTRIBUTING.md
Soften the language around unrequited PRs
2023-09-18 21:03:46 +01:00
Dave Conway-Jones
718a7bfc26 Update 89-delay.js 2023-09-18 19:32:01 +01:00
Franck
27ca30aa82 PERF : make csv way faster by not allocating and handling huge string 2023-09-18 15:16:15 +02:00
Zeger-Jan van de Weg
01b0bf1a36 github: Request npm run test in PR template
Due to the way grunt is installed, `grunt` might not work for the user locally.
However, `npm run test` will succeed for them, as NPM knows where `grunt` is located to execute.
2023-09-17 08:38:10 +02:00
Kazuhito Yokoi
e1cecc9601 Fix height of description editor in template node 2023-09-16 15:46:07 +09:00
GogoVega
4c13f5a0af Adapting the translation depending on the context 2023-09-09 14:34:33 +02:00
GogoVega
f5a9942d5e Fix translation mistakenly erased 2023-09-09 10:59:59 +02:00
Nick O'Leary
ee2d91fb4a Handle nodes with multiple input handlers properly
Fixes #4330
2023-09-08 16:26:10 +01:00
Nick O'Leary
6ca41ba69d Handle undefined linkType value for existing link-call nodes 2023-09-08 16:03:08 +01:00
GogoVega
7f9d142038 Add translation of v3.1-beta.4 changes 2023-09-08 15:45:00 +02:00
GogoVega
44a1f83b26 Add some capital letters 2023-09-08 15:39:46 +02:00
Nick O'Leary
d9bbac20f3 Merge pull request #4320 from node-red/dev
Sync `dev` to `master` for 3.1.0 release
2023-09-06 14:04:36 +01:00
Nick O'Leary
a48c57dd17 Merge pull request #4321 from node-red/rel-310
Bump version and changelog for 3.1.0 release
2023-09-06 13:57:44 +01:00
Nick O'Leary
77b235655c Bump version and changelog 2023-09-05 21:29:20 +01:00
Nick O'Leary
8dc0261993 Merge pull request #4319 from Rotzbua/fix_duplicate
Fix duplicate declaration
2023-09-05 20:41:38 +01:00
Rotzbua
65d2ad68d3 Fix duplicate declaration 2023-09-05 19:02:39 +02:00
Nick O'Leary
52fde088e9 Merge pull request #4318 from node-red/4315-small-catalogs-fix
Default filter to All Catalogues and show nodes for small lists
2023-09-05 17:59:57 +01:00
Nick O'Leary
ab6d537c3e Default filter to All Catalogues and show nodes for small lists 2023-09-05 17:49:50 +01:00
Nick O'Leary
3a6078a56a Merge pull request #4317 from node-red/update-deps-31
Dependency updates
2023-09-05 17:21:06 +01:00
Nick O'Leary
b0c3fefcab Dependency updates 2023-09-05 17:16:05 +01:00
Nick O'Leary
2bc739194e Merge pull request #4316 from node-red/4221-handle-concurrent-write-file
Ensure storage/util.writeFile handles concurrent write attempts
2023-09-05 15:57:27 +01:00
Nick O'Leary
e18721a03e Merge pull request #4313 from Rotzbua/fix_https
Migrate http -> https for nodered.org
2023-09-05 14:20:32 +01:00
Rotzbua
25120e44ce Update outdated GH Actions 2023-09-05 14:56:14 +02:00
Rotzbua
aea32cc279 Migrate http -> https for nodered.org 2023-09-05 14:55:56 +02:00
Nick O'Leary
ce0feb2f42 Merge pull request #4310 from node-red/4206-ctrl-click-behaviour
Better distinguish between ctrl and meta keys on mac
2023-09-05 13:48:17 +01:00
Rotzbua
12a1c5c2f4 Add dependabot for GH Action workflows 2023-09-05 14:11:08 +02:00
Nick O'Leary
d307968880 Better distinguish between ctrl and meta keys on mac
Fixes #4206, #4205
2023-09-05 12:36:44 +01:00
Nick O'Leary
1f98d19f77 Merge pull request #4309 from node-red/pr_4265
Adding function timeout to settings file (#4265)
2023-09-05 11:44:41 +01:00
Nick O'Leary
9a934c941f Tidy up functionTimeout setting 2023-09-05 10:34:18 +01:00
Nick O'Leary
dbc7284b97 Merge pull request #4308 from node-red/revert-3991-http-request-form-array
Revert "Support form-data arrays"
2023-09-05 10:03:13 +01:00
Nick O'Leary
46b15a51d4 Revert "Support form-data arrays" 2023-09-05 09:41:48 +01:00
Nick O'Leary
cc5533c183 Merge pull request #4281 from kazuhitoyokoi/master-roundedcorners
Fix not rounded corners in project settings UI
2023-08-16 15:53:07 +01:00
Nick O'Leary
19787e5d28 Merge pull request #4280 from kazuhitoyokoi/master-svgicon2
Add svg icons for nodes
2023-08-16 15:52:47 +01:00
Kazuhito Yokoi
6e46666895 Fix not rounded corners in project settings UI 2023-08-16 20:14:22 +09:00
Kazuhito Yokoi
a87d7276c5 Add svg icons for nodes 2023-08-16 19:21:31 +09:00
Nick O'Leary
c630b4f770 Merge pull request #4276 from kazuhitoyokoi/master-svgicon
Add svg icons for nodes
2023-08-16 10:23:35 +01:00
Kazuhito Yokoi
66144c1eb5 Add svg icons for nodes 2023-08-15 16:16:04 +09:00
Nick O'Leary
9542c22191 Merge pull request #4259 from kazuhitoyokoi/master-fixtooltip4textdiff
Add tooltip to text diff button
2023-08-14 11:11:32 +01:00
Nick O'Leary
15b8d79489 Merge pull request #4261 from DarshanDixit05/fix-Invalid-label
fix : Invalid label for attribute on the tray
2023-08-14 11:11:10 +01:00
Nick O'Leary
37a518b655 Merge pull request #4273 from kazuhitoyokoi/master-fixswitchnode
Fix broken text input in the switch node (again)
2023-08-14 11:09:05 +01:00
Nick O'Leary
312b2f8ddb Merge pull request #4270 from AuspeXeu/master
fix: undefined node and wrong method name
2023-08-14 11:08:04 +01:00
Kazuhito Yokoi
9caa6a3553 Fix broken text input in the switch node (again) 2023-08-13 15:33:37 +09:00
Christian Vaas
6c597bba5b fix: undefined node and wrong method name 2023-08-08 19:21:31 +02:00
Kilian Hertel
f7b64b101e adding function timeout to settings file
adding function timeout to settings file
2023-08-04 14:20:49 +02:00
DarshanDixit05
9540502d06 removed package lock 2023-07-31 20:22:46 +05:30
DarshanDixit05
792dedb1f1 fix : Invalid label for attribute on the tray 2023-07-31 19:34:12 +05:30
Kazuhito Yokoi
0bf1343442 Add tooltip to text diff button 2023-07-29 16:36:55 +09:00
188 changed files with 6306 additions and 1003 deletions

View File

@@ -30,5 +30,5 @@ the [forum](https://discourse.nodered.org) or
- [ ] I have read the [contribution guidelines](https://github.com/node-red/node-red/blob/master/CONTRIBUTING.md)
- [ ] For non-bugfix PRs, I have discussed this change on the forum/slack team.
- [ ] I have run `grunt` to verify the unit tests pass
- [ ] I have run `npm run test` to verify the unit tests pass
- [ ] I have added suitable unit tests to cover the new/changed functionality

15
.github/dependabot.yml vendored Normal file
View File

@@ -0,0 +1,15 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2
updates:
- package-ecosystem: "github-actions" # See documentation for possible values
directory: "/" # Location of package manifests
schedule:
interval: "monthly"
groups:
github-actions:
patterns:
- "*"

View File

@@ -14,25 +14,25 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out node-red repository
uses: actions/checkout@v2
uses: actions/checkout@v4
with:
path: 'node-red'
- name: Check out node-red-docker repository
uses: actions/checkout@v2
uses: actions/checkout@v4
with:
repository: 'node-red/node-red-docker'
path: 'node-red-docker'
- name: Check out node-red.github.io repository
uses: actions/checkout@v2
uses: actions/checkout@v4
with:
repository: 'node-red/node-red.github.io'
path: 'node-red.github.io'
- uses: actions/setup-node@v1
- uses: actions/setup-node@v4
with:
node-version: '16'
- run: node ./node-red/.github/scripts/update-node-red-docker.js
- name: Create Docker Pull Request
uses: peter-evans/create-pull-request@v2
uses: peter-evans/create-pull-request@v6
with:
token: ${{ secrets.NR_REPO_TOKEN }}
committer: GitHub <noreply@github.com>
@@ -48,7 +48,7 @@ jobs:
This PR was auto-generated by a GitHub Action. Any questions, speak to @knolleary
- run: node ./node-red/.github/scripts/update-node-red-website.js
- name: Create Website Pull Request
uses: peter-evans/create-pull-request@v2
uses: peter-evans/create-pull-request@v6
with:
token: ${{ secrets.NR_REPO_TOKEN }}
committer: GitHub <noreply@github.com>

View File

@@ -19,9 +19,9 @@ jobs:
matrix:
node-version: [16, 18, 20]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
- name: Install Dependencies

1
.gitignore vendored
View File

@@ -27,3 +27,4 @@ docs
.vscode
.nyc_output
sync.ffs_db
package-lock.json

View File

@@ -1,4 +1,176 @@
#### 3.1.0-beta.4: Beta Release
#### 3.1.6: Maintenance Release
Editor
- Do not flag env var in num typedInput as error (#4582) @knolleary
- Fix example flow name in import dialog (#4578) @kazuhitoyokoi
- Fix missing node icons in workspace (#4570) @knolleary
Runtime
- Handle undefined env vars (#4581) @knolleary
- fix: Removed offending MD5 crypto hash and replaced with SHA1 and SHA256 … (#4568) @JaysonHurst
- chore: remove never use import code (#4580) @giscafer
Nodes
- fix: template node zh-CN translation (#4575) @giscafer
#### 3.1.5: Maintenance Release
Runtime
- Fix require of dns module (#4562) @knolleary
- Ensure global creds object is initialised when adding first cred (#4561) @knolleary
#### 3.1.4: Maintenance Release
Editor
- Highlight errors in config node sidebar (#4529) @knolleary
- Improve feedback in import dialog to show conflicted nodes (#4550) @knolleary
- Modify node users info in config editor footer (#4528) @knolleary
- Handle modified-nodes deploy after replacing unknown config node (#4556) @knolleary
- Handle undefined default export when importing module (#4539) @knolleary
- Fix icon scaling for non .svg icons (#4491) @ralphwetzel
- (convertNode) Do not create the credentials object if there is nothing to export (#4544) @GogoVega
- Ensure subflow instance node has g property set (#4538) @knolleary
- Handle importing flow with existing subflow and instance node (#4546) @knolleary
- Update index.mst (#4483) @gorenje
- Include top level property name when copying path from context (#4527) @knolleary
- Add handling to disable items on context menu (#4500) @kazuhitoyokoi
- Focus Quick Add dialog from context menu (#4516) @kazuhitoyokoi
- Fix subflow ports in Quick Add dialog (#4518) @kazuhitoyokoi
- Fix location of subflow ports in palette (#4502) @kazuhitoyokoi
- Client/Editor Events: fix off-in-on pattern emulating once (#4484) @gorenje
- Restore caching busting functionality without using explict version number (#4512) @knolleary
- Do not translate the list of available languages (#4531) @GogoVega
- Add French translation of v3.1.3 changes (#4477) @GogoVega
- i18n(es-ES) Spanish Spain translation (#4495) @joebordes
- Add missing validation messages (#4487) @GogoVega
- Add Japanese translations for v3.1.3 (#4498) @kazuhitoyokoi
- Replace `rename` by `edit` for the menu flow label (#4506) @GogoVega
- Update editor.json fix typo in German translation (#4552) @guidoffm
Runtime
- Bump the github-actions group with 1 update (#4554) @app/dependabot
- Clone objects types when getting env values (#4519) @knolleary
- Ensure global-config credential env vars are merged on deploy (#4526) @knolleary
Nodes
- 21-httprequest.js remove unused code, because of broken use of toLowercase (#4522) @gorenje
#### 3.1.3: Maintenance Release
Editor
- Add missing en-us messages (#4475) @knolleary
#### 3.1.2: Maintenance Release
Editor
- Relax some node validators to allow undefined value (#4471) @knolleary
- Fix switch validation of typeof field (#4465) @knolleary
- Use move cursor when hovering on group border (#4467) @knolleary
- Added action list Chinese (Simplified and Traditional) translation + v3.1.1 changes (#4470) @wangyiyi2056
- Add French translation of `action-list` + v3.1.1 changes (#4466) @GogoVega
Runtime
- Ensure nested groups inside subflows have their g props remapped (#4472) @knolleary
#### 3.1.1: Maintenance Release
Editor
- Fix debug filter (#4461) @knolleary
- Fix various issues with debug pop-out window (#4459) @knolleary
- Ensure subflow instances keep track of their groups (#4457) @knolleary
- Fix `validateNodeProperty` without validator provided (#4455) @GogoVega
- Debounce node-removed notifications (#4453) @knolleary
- Don't try to load the parents of the first commit (#4448) @bonanitech
- Allow a theme to specifiy which theme mermaid should use (#4441) @knolleary
- Update browser title with flow name if set (#4427) @knolleary
- Ensure typeSearch handles undefined node definitions (#4423) @knolleary
- Ensure group w/h are imported if present (#4426) @knolleary
- Hide node status background when there is no status to show (#4425) @knolleary
- Add a close button to the restart-required notification (#4407) @knolleary
- Extend typedInput "num" type validity check to NaN, binary, octal & hex (#4371) @ralphwetzel
- Fix unintended new line in node name (#4399) @kazuhitoyokoi
- Ctrl-Enter does not close tray (Monaco) #4377 (#4382) @hazymat
- fix buffer viewer to handle 0b style binary (#4393) @dceejay
- Rework mermaid integration to support off-DOM rendering (#4364) @knolleary
- Add missing nls labels to context menu (#4365) @knolleary
Runtime
- Bump the github-actions group with 2 updates (#4404) @app/dependabot
- Handle unknown node reference inside subflow module (#4460) @knolleary
- Add modules.install audit event when external module installed (#4452) @knolleary
- Allow import of modules with subpath in specifier (#4451) @knolleary
- Update node-red-admin version (#4438) @knolleary
- Handle false-like env vars properly (#4411) @knolleary
- Only save settings once during node load process (#4409) @knolleary
- Ensure global-config nodes lookup cred values properly (#4405) @knolleary
- Handle credential env var evaluation when no value set (#4362) @knolleary
- Don't commit package-lock.json (#4354) @bonanitech
- Fix env evaluation when one env references another in the same object (#4361) @knolleary
- Add dependabot for Github Actions (#4312) @Rotzbua
- Update outdated Github Actions (#4311) @Rotzbua
- github: Request `npm run test` in PR template (#4348) @ZJvandeWeg
- Add French translation of v3.1.0-beta.4 changes + slight improvements (#4329) @GogoVega
- Handle nodes with multiple input handlers properly (#4332) @knolleary
- Soften the language around unrequited PRs (#4351) @knolleary
Nodes
- CSV: make CSV export way faster by not re-allocating and handling huge string (#4349) @Fadoli
- Delay: Fix regression in delay node to not pass on msg.reset (#4350) @dceejay
- Link Call: Handle undefined linkType value for existing link-call nodes (#4331) @knolleary
- MQTT: Guard against node.broker being undefined (#4454) @knolleary
- MQTT: check topic length > 0 before publish (#4416) @dceejay
- Switch/Change: Improve validation of switch/change node rules (#4368) @knolleary
- Template: Fix height of description editor in template node (#4346) @kazuhitoyokoi
- Various: Add validators to any fields using msg-typed Input (#4440) @knolleary
#### 3.1.0: Milestone Release
Editor
- Default filter to All Catalogues and show nodes for small lists (#4318) @knolleary
- Better distinguish between ctrl and meta keys on mac (#4310) @knolleary
- Ensure junction appears when filtering quick-add list (#4297) @knolleary
- Update message catalogs for JSONata Expression editor (#4287) @kazuhitoyokoi
- Add tooltip to relevance sort button in user settings UI (#4288) @kazuhitoyokoi
- Capture workspace dirty state when quick-adding junction (#4283) @knolleary
- Add docs for $clone function (#4284) @knolleary
Runtime
- Dependency updates (#4317) @knolleary
- Ensure storage/util.writeFile handles concurrent write attempts (#4316) @knolleary
- Migrate http -> https for nodered.org (#4313) @Rotzbua
- Add Node 20 to GH Action test matrix (#4305) @Rotzbua
- Handle group-scoped nodes inside subflow (#4301) @knolleary
- Handle non-url-safe chars in context api (#4298) @knolleary
- Fix git pull operation in project feature (#4290) @kazuhitoyokoi
- Change linefeed codes in Korean message catalogs (#4286) @kazuhitoyokoi
- Fix file permissions of message catalogs (#4285) @kazuhitoyokoi
- Update tour (#4278) @knolleary
Nodes
- File: Fix handling in file nodes when number is specified as file name (#4267) @kazuhitoyokoi
- Function: Adding function timeout to settings file (#4265) (#4309) @knolleary
- Function: Fix function setup tab layout (#4299) @knolleary
- HTTP Request: Handle 204 in httprequest JSON (#4262) @sammachin
- JSON: Fix test cases of JSON node (#4275) @kazuhitoyokoi
- MQTT: Remove unnecessary check for clientid if autoUnsub set (#4302) @knolleary
##### 3.1.0-beta.4: Beta Release
Editor
@@ -28,7 +200,7 @@
- Fix delay node flush issue (#4203) @dceejay
- Update status and catch node labels in group mode (#4207) @Steve-Mcl
#### 3.1.0-beta.3: Beta Release
##### 3.1.0-beta.3: Beta Release
Editor
@@ -63,7 +235,7 @@ Nodes
- MQTT: Option to disable MQTT topic unsubscribe on disconnect (#4078) @flying7eleven
#### 3.1.0-beta.2: Beta Release
##### 3.1.0-beta.2: Beta Release
Editor
@@ -113,7 +285,7 @@ Nodes
- File Out: Fix extra newline append for multipart file write (#3915) @dceejay
- Add validators for complete and link call nodes (#4056) @kazuhitoyokoi
#### 3.1.0-beta.1: Beta Release
##### 3.1.0-beta.1: Beta Release
Editor

View File

@@ -16,6 +16,9 @@ behavior to the project's core team at team@nodered.org.
Please raise any bug reports on the relevant project's issue tracker. Be sure to
search the list to see if your issue has already been raised.
If your issue is more of a question on how to do something with Node-RED, please
consider using the [community forum](https://discourse.nodered.org/).
A good bug report is one that make it easy for us to understand what you were
trying to do and what went wrong.
@@ -35,14 +38,18 @@ For feature requests, please raise them on the [forum](https://discourse.nodered
## Pull-Requests
If you want to raise a pull-request with a new feature, or a refactoring
of existing code, it may well get rejected if you haven't discussed it on
the [forum](https://discourse.nodered.org) first.
of existing code, please come and discuss it with us first. We prefer to
do it that way to make sure your time and effort is well spent on something
that fits with our goals.
If you've got a bug-fix or similar for us, then you are most welcome to
get it raised - just make sure you link back to the issue it's fixing and
try to include some tests!
All contributors need to sign the OpenJS Foundation's Contributor License Agreement.
It is an online process and quick to do. If you raise a pull-request without
having signed the CLA, you will be prompted to do so automatically.
### Code Branches
When raising a PR for a fix or a new feature, it is important to target the right branch.

View File

@@ -151,7 +151,6 @@ module.exports = function(grunt) {
"packages/node_modules/@node-red/editor-client/src/js/font-awesome.js",
"packages/node_modules/@node-red/editor-client/src/js/history.js",
"packages/node_modules/@node-red/editor-client/src/js/validators.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/mermaid.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/utils.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/common/editableList.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/common/treeList.js",

View File

@@ -1,16 +1,16 @@
# Node-RED
http://nodered.org
https://nodered.org
[![Build Status](https://github.com/node-red/node-red/actions/workflows/tests.yml/badge.svg?branch=master)](https://github.com/node-red/node-red/actions?query=branch%3Amaster)
Low-code programming for event-driven applications.
![Node-RED: Low-code programming for event-driven applications](http://nodered.org/images/node-red-screenshot.png)
![Node-RED: Low-code programming for event-driven applications](https://nodered.org/images/node-red-screenshot.png)
## Quick Start
Check out http://nodered.org/docs/getting-started/ for full instructions on getting
Check out https://nodered.org/docs/getting-started/ for full instructions on getting
started.
1. `sudo npm install -g --unsafe-perm node-red`
@@ -19,7 +19,7 @@ started.
## Getting Help
More documentation can be found [here](http://nodered.org/docs).
More documentation can be found [here](https://nodered.org/docs).
For further help, or general discussion, please use the [Node-RED Forum](https://discourse.nodered.org) or [slack team](https://nodered.org/slack).

View File

@@ -1,8 +1,8 @@
{
"name": "node-red",
"version": "3.1.0-beta.4",
"version": "3.1.6",
"description": "Low-code programming for event-driven applications",
"homepage": "http://nodered.org",
"homepage": "https://nodered.org",
"license": "Apache-2.0",
"repository": {
"type": "git",
@@ -64,8 +64,8 @@
"mqtt": "4.3.7",
"multer": "1.4.5-lts.1",
"mustache": "4.2.0",
"node-red-admin": "^3.0.0",
"node-watch": "0.7.3",
"node-red-admin": "^3.1.2",
"node-watch": "0.7.4",
"nopt": "5.0.0",
"oauth2orize": "1.11.1",
"on-headers": "1.0.2",
@@ -73,16 +73,16 @@
"passport-http-bearer": "1.0.1",
"passport-oauth2-client-password": "0.1.2",
"raw-body": "2.5.2",
"semver": "7.5.0",
"semver": "7.5.4",
"tar": "6.1.13",
"tough-cookie": "4.1.2",
"tough-cookie": "4.1.3",
"uglify-js": "3.17.4",
"uuid": "9.0.0",
"ws": "7.5.6",
"xml2js": "0.6.0"
"xml2js": "0.6.2"
},
"optionalDependencies": {
"bcrypt": "5.1.0"
"bcrypt": "5.1.1"
},
"devDependencies": {
"dompurify": "2.4.1",
@@ -109,7 +109,7 @@
"jquery-i18next": "1.2.1",
"jsdoc-nr-template": "github:node-red/jsdoc-nr-template",
"marked": "4.3.0",
"mermaid": "^9.4.3",
"mermaid": "^10.4.0",
"minami": "1.2.3",
"mocha": "9.2.2",
"node-red-node-test-helper": "^0.3.2",

View File

@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
**/
var apiUtils = require("../util");
var runtimeAPI;
var settings;
var theme = require("../editor/theme");

View File

@@ -18,7 +18,6 @@ var BearerStrategy = require('passport-http-bearer').Strategy;
var ClientPasswordStrategy = require('passport-oauth2-client-password').Strategy;
var passport = require("passport");
var crypto = require("crypto");
var util = require("util");
var Tokens = require("./tokens");

View File

@@ -14,11 +14,9 @@
* limitations under the License.
**/
var express = require("express");
var path = require('path');
var comms = require("./comms");
var library = require("./library");
var info = require("./settings");
var auth = require("../auth");
@@ -51,7 +49,7 @@ module.exports = {
var ui = require("./ui");
ui.init(runtimeAPI);
ui.init(settings, runtimeAPI);
const editorApp = apiUtil.createExpressApp(settings)

View File

@@ -15,8 +15,6 @@
**/
var apiUtils = require("../util");
var fs = require('fs');
var fspath = require('path');
var runtimeAPI;

View File

@@ -13,9 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
**/
var fs = require('fs');
var path = require('path');
// var apiUtil = require('../util');
var i18n = require("@node-red/util").i18n; // TODO: separate module

View File

@@ -15,7 +15,6 @@
**/
var apiUtils = require("../util");
var express = require("express");
var runtimeAPI;
var settings;

View File

@@ -14,7 +14,6 @@
* limitations under the License.
**/
var express = require("express");
var util = require("util");
var path = require("path");
var fs = require("fs");
@@ -339,6 +338,8 @@ module.exports = {
}
theme.codeEditor = theme.codeEditor || {}
theme.codeEditor.options = Object.assign({}, themePlugin.monacoOptions, theme.codeEditor.options);
theme.mermaid = Object.assign({}, themePlugin.mermaid, theme.mermaid)
}
activeThemeInitialised = true;
}

View File

@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
**/
const crypto = require('crypto')
var express = require('express');
var fs = require("fs");
var path = require("path");
@@ -24,13 +25,16 @@ var apiUtils = require("../util");
var theme = require("./theme");
var runtimeAPI;
let settings;
var editorClientDir = path.dirname(require.resolve("@node-red/editor-client"));
var defaultNodeIcon = path.join(editorClientDir,"public","red","images","icons","arrow-in.svg");
var editorTemplatePath = path.join(editorClientDir,"templates","index.mst");
var editorTemplate;
let cacheBuster
module.exports = {
init: function(_runtimeAPI) {
init: function(_settings, _runtimeAPI) {
settings = _settings;
runtimeAPI = _runtimeAPI;
editorTemplate = fs.readFileSync(editorTemplatePath,"utf8");
Mustache.parse(editorTemplate);
@@ -91,6 +95,12 @@ module.exports = {
},
editor: async function(req,res) {
if (!cacheBuster) {
// settings.instanceId is set asynchronously to the editor-api
// being initiaised. So we defer calculating the cacheBuster hash
// until the first load of the editor
cacheBuster = crypto.createHash('sha1').update(`${settings.version || 'version'}-${settings.instanceId || 'instanceId'}`).digest("hex").substring(0,12)
}
let sessionMessages;
if (req.session && req.session.messages) {
@@ -99,6 +109,7 @@ module.exports = {
}
res.send(Mustache.render(editorTemplate,{
sessionMessages,
cacheBuster,
...await theme.context()
}));
},

View File

@@ -24,11 +24,8 @@
* @namespace @node-red/editor-api
*/
var express = require("express");
var bodyParser = require("body-parser");
var util = require('util');
var passport = require('passport');
var cors = require('cors');
var auth = require("./auth");
var apiUtil = require("./util");

View File

@@ -1,6 +1,6 @@
{
"name": "@node-red/editor-api",
"version": "3.1.0-beta.4",
"version": "3.1.6",
"license": "Apache-2.0",
"main": "./lib/index.js",
"repository": {
@@ -16,8 +16,8 @@
}
],
"dependencies": {
"@node-red/util": "3.1.0-beta.4",
"@node-red/editor-client": "3.1.0-beta.4",
"@node-red/util": "3.1.6",
"@node-red/editor-client": "3.1.6",
"bcryptjs": "2.4.3",
"body-parser": "1.20.2",
"clone": "2.1.2",

View File

@@ -109,7 +109,6 @@
"selectionToSubflow": "Auswahl in Subflow umwandeln",
"flows": "Flow",
"add": "Hinzufügen",
"rename": "Umbenennen",
"delete": "Löschen",
"keyboardShortcuts": "Tastenkürzel",
"login": "Anmelden",
@@ -1076,7 +1075,7 @@
"git-auth-error": "Git-Authentifizierungsfehler"
},
"create-success": {
"success": "Sie haben Ihr erstes Projekt erfolgreich erstduellt!",
"success": "Sie haben Ihr erstes Projekt erfolgreich erstellt!",
"desc0": "Sie können jetzt Node-RED wie bisher verwenden.",
"desc1": "Im Tab 'Info' in der Seitenleiste wird angezeigt, welches das aktuelle Projekt ist. Über die Schaltfläche rechts neben dem Projektnamen gelangt man zu 'Projekteinstellungen'.",
"desc2": "Im Tab 'Commit-Historie' in der Seitenleiste werden alle Dateien angezeigt, die sich in Ihrem Projekt geändert haben, und um sie ins lokale Repository zu übertragen (commit). Es zeigt Ihnen eine vollständige Historie Ihrer Commits an und ermöglicht es Ihnen, Ihre Commits in ein (remote) Server-Repository zu schieben (push)."
@@ -1172,17 +1171,6 @@
"diagnostics": {
"title": "System-Informationen"
},
"languages": {
"de": "Deutsch",
"en-US": "Englisch",
"fr": "Französisch",
"ja": "Japanisch",
"ko": "Koreanisch",
"pt-BR":"Portugiesisch",
"ru": "Russisch",
"zh-CN": "Chinesisch (Vereinfacht)",
"zh-TW": "Chinesisch (Traditionell)"
},
"validator": {
"errors": {
"invalid-json": "Ungültige JSON-Daten: __error__",

View File

@@ -113,7 +113,7 @@
"displayStatus": "Show node status",
"displayConfig": "Configuration nodes",
"import": "Import",
"importExample": "Import Example Flow",
"importExample": "Import example flow",
"export": "Export",
"search": "Search flows",
"searchInput": "search your flows",
@@ -122,7 +122,6 @@
"selectionToSubflow": "Selection to Subflow",
"flows": "Flows",
"add": "Add",
"rename": "Rename",
"delete": "Delete",
"keyboardShortcuts": "Keyboard shortcuts",
"login": "Login",
@@ -130,6 +129,11 @@
"editPalette": "Manage palette",
"other": "Other",
"showTips": "Show tips",
"showNodeHelp": "Show node help",
"enableSelectedNodes": "Enable selected nodes",
"disableSelectedNodes": "Disable selected nodes",
"showSelectedNodeLabels": "Show selected node labels",
"hideSelectedNodeLabels": "Hide selected node labels",
"showWelcomeTours": "Show guided tours for new versions",
"help": "Node-RED website",
"projects": "Projects",
@@ -299,7 +303,8 @@
"missingType": "Input not a valid flow - item __index__ missing 'type' property"
},
"conflictNotification1": "Some of the nodes you are importing already exist in your workspace.",
"conflictNotification2": "Select which nodes to import and whether to replace the existing nodes, or to import a copy of them."
"conflictNotification2": "Select which nodes to import and whether to replace the existing nodes, or to import a copy of them.",
"alreadyExists": "This node already exists"
},
"copyMessagePath": "Path copied",
"copyMessageValue": "Value copied",
@@ -511,8 +516,8 @@
"selectAllConnected": "Select connected",
"addRemoveNode": "Add/remove node from selection",
"editSelected": "Edit selected node",
"deleteSelected": "Delete selected nodes or link",
"deleteReconnect": "Delete and Reconnect",
"deleteSelected": "Delete selection",
"deleteReconnect": "Delete and reconnect",
"importNode": "Import nodes",
"exportNode": "Export nodes",
"nudgeNode": "Move selected nodes (1px)",
@@ -703,7 +708,7 @@
"triggerAction": "Trigger action",
"find": "Find in workspace",
"copyItemUrl": "Copy item url",
"copyURL2Clipboard": "Copied url to clipboard",
"copyURL2Clipboard": "Copied url to clipboard",
"showFlow": "Show",
"hideFlow": "Hide"
},
@@ -1202,22 +1207,22 @@
"title": "System Info"
},
"languages": {
"de": "German",
"de": "Deutsch",
"en-US": "English",
"fr": "French",
"ja": "Japanese",
"es-ES": "Español (España)",
"fr": "Français",
"ja": "日本語",
"ko": "Korean",
"pt-BR":"Portuguese",
"ru": "Russian",
"zh-CN": "Chinese(Simplified)",
"zh-TW": "Chinese(Traditional)"
"pt-BR": "Português (Brasil)",
"ru": "Русский",
"zh-CN": "简体中文",
"zh-TW": "繁體中文"
},
"validator": {
"errors": {
"invalid-json": "Invalid JSON data: __error__",
"invalid-json-prop": "__prop__: invalid JSON data: __error__",
"invalid-expr": "Invalid JSONata expression: __error__",
"invalid-prop": "Invalid property expression",
"invalid-prop-prop": "__prop__: invalid property expression",
"invalid-num": "Invalid number",
"invalid-num-prop": "__prop__: invalid number",
"invalid-regexp": "Invalid input pattern",
@@ -1229,6 +1234,7 @@
}
},
"contextMenu": {
"showActionList": "Show action list",
"insert": "Insert",
"node": "Node",
"junction": "Junction",

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,26 @@
{
"info": {
"tip0": "Puedes eliminar los nodos o enlaces seleccionados con {{core:delete-selection}}",
"tip1": "Busca nodos con {{core:search}}",
"tip2": "{{core:toggle-sidebar}} alternará la vista de esta barra lateral",
"tip3": "Puedes gestionar tu paleta de nodos con {{core:manage-palette}}",
"tip4": "Tus nodos de configuración de flujo aparecen en el panel de la barra lateral. Se puede acceder desde el menú o con {{core:show-config-tab}}",
"tip5": "Activa o desactiva estos consejos desde la opción en la configuración",
"tip6": "Mueve los nodos seleccionados usando las teclas [izquierda] [arriba] [abajo] y [derecha]. Mantén pulsada [Mayús] para desplazarlos más",
"tip7": "Arrastrar un nodo a un cable lo insertará en el enlace",
"tip8": "Exporta los nodos seleccionados, o la pestaña actual con {{core:show-export-dialog}}",
"tip9": "Importa un flujo arrastrando su JSON al editor, o con {{core:show-import-dialog}}",
"tip10": "[shift][clic] y arrastrar en un puerto de nodo para mover todos los cables conectados o sólo el seleccionado",
"tip11": "Mostrar la pestaña Información con {{core:show-info-tab}} o la pestaña Depuración con {{core:show-debug-tab}}",
"tip12": "[ctrl] [clic] en el área de trabajo para abrir el diálogo de adición rápida",
"tip13": "Mantén pulsada [ctrl] cuando [haces clic] en un puerto de nodo para habilitar el enlazado rápido",
"tip14": "Mantén pulsada [shift] cuando [haces clic] en un nodo para seleccionar también todos sus nodos conectados",
"tip15": "Mantén pulsada [ctrl] cuando [haces clic] en un nodo para añadirlo o eliminarlo de la selección actual",
"tip16": "Cambia de pestaña de flujo con {{core:show-previous-tab}} y {{core:show-next-tab}}",
"tip17": "Puedes confirmar tus cambios en la bandeja de edición de nodos con {{core:confirm-edit-tray}} o cancelarlos con {{core:cancel-edit-tray}}",
"tip18": "Al pulsar {{core:edit-selected-node}} se editará el primer nodo de la selección actual"
}
}

View File

@@ -0,0 +1,278 @@
{
"$string": {
"args": "arg[, prettify]",
"desc": "Convierte el parámetro `arg` a una cadena usando las siguientes reglas de conversión:\n\n - Las cadenas no cambian\n - Las funciones se convierten en una cadena vacía\n - El infinito numérico y NaN arrojan un error porque no se pueden representar como un número JSON\n: todos los demás valores se convierten a una cadena JSON usando la función `JSON.stringify`. Si `prettify` es verdadero, entonces se produce JSON \"prettified\". es decir, una línea por campo y las líneas se indentarán según la profundidad del campo."
},
"$length": {
"args": "str",
"desc": "Devuelve el número de caracteres de la cadena `str`. Se genera un error si `str` no es una cadena."
},
"$substring": {
"args": "str, start[, length]",
"desc": "Devuelve una cadena que contiene los caracteres del primer parámetro `str` comenzando en la posición `start` (desplazamiento cero). Si se especifica 'longitud', la subcadena contendrá el máximo de caracteres de 'longitud'. Si 'inicio' es negativo, indica el número de caracteres desde el final de 'cadena'."
},
"$substringBefore": {
"args": "str, chars",
"desc": "Devuelve la subcadena antes de la primera aparición de la secuencia de caracteres `chars` en `str`. Si `str` no contiene `caracteres`, entonces devuelve `str`."
},
"$substringAfter": {
"args": "str, chars",
"desc": "Devuelve la subcadena después de la primera aparición de la secuencia de caracteres `chars` en `str`. Si `str` no contiene `caracteres`, entonces devuelve `str`."
},
"$uppercase": {
"args": "str",
"desc": "Devuelve una cadena con todos los caracteres de `str` convertidos a mayúsculas."
},
"$lowercase": {
"args": "str",
"desc": "Devuelve una cadena con todos los caracteres de `str` convertidos a minúsculas."
},
"$trim": {
"args": "str",
"desc": "Normaliza y recorta todos los caracteres de espacio en blanco en `str` aplicando los siguientes pasos:\n\n - Todas las tabulaciones, retornos de carro y avances de línea se reemplazan con espacios.\n- Las secuencias contiguas de espacios se reducen a un solo espacio.\n- Se eliminan los espacios iniciales y finales.\n\n Si no se especifica `str` (es decir, esta función se invoca sin argumentos), entonces el valor de contexto se utiliza como el valor de `str`. Se genera un error si `str` no es una cadena."
},
"$contains": {
"args": "str, pattern",
"desc": "Devuelve 'verdadero' si 'cadena' coincide con 'patrón', de lo contrario, devuelve 'falso'. Si no se especifica `str` (es decir, esta función se invoca con un argumento), entonces el valor del contexto se utiliza como valor de `str`. El parámetro `patrón` puede ser una cadena o una expresión regular."
},
"$split": {
"args": "str[, separator][, limit]",
"desc": "Divide el parámetro `str` en una matriz de subcadenas. Es un error si `str` no es una cadena. El parámetro opcional `separador` especifica los caracteres dentro de la `cadena` sobre los cuales se debe dividir como una cadena o una expresión regular. Si no se especifica 'separador', se supone que la cadena está vacía y 'cadena' se dividirá en una matriz de caracteres individuales. Es un error si el 'separador' no es una cadena. El parámetro opcional 'límite' es un número que especifica el número máximo de subcadenas que se incluirán en la matriz resultante. Cualquier subcadena adicional se descarta. Si no se especifica `límite`, entonces `str` se divide completamente sin límite para el tamaño de la matriz resultante. Es un error si 'límite' no es un número positivo."
},
"$join": {
"args": "array[, separator]",
"desc": "Une una matriz de cadenas de componentes en una única cadena concatenada con cada cadena de componentes separada por el parámetro 'separador' opcional. Es un error si la 'matriz' de entrada contiene un elemento que no es una cadena. Si no se especifica 'separador', se supone que es una cadena vacía, es decir, que no hay 'separador' entre las cadenas componentes. Es un error si el 'separador' no es una cadena."
},
"$match": {
"args": "str, pattern [, limit]",
"desc": "Aplica la cadena `str` a la expresión regular `pattern` y devuelve una matriz de objetos, cada objeto contiene información sobre cada aparición de una coincidencia dentro de `str`."
},
"$replace": {
"args": "str, pattern, replacement [, limit]",
"desc": "Encuentra apariciones de `patrón` dentro de `str` y las reemplaza con `reemplazo`.\n\nEl parámetro opcional `límite` es el número máximo de reemplazos."
},
"$now": {
"args": "$[picture [, timezone]]",
"desc": "Genera una marca de tiempo en formato compatible con ISO 8601 y la devuelve como una cadena. Si se proporcionan los parámetros opcionales `picture` y `zona horaria`, entonces la marca de tiempo actual se formatea como se describe en la función `$fromMillis()`"
},
"$base64encode": {
"args": "string",
"desc": "Convierte una cadena ASCII a una representación base 64. Cada carácter de la cadena se trata como un byte de datos binarios. Esto requiere que todos los caracteres de la cadena estén en el rango de 0x00 a 0xFF, que incluye todos los caracteres de las cadenas codificadas con URI. No se admiten caracteres Unicode fuera de ese rango."
},
"$base64decode": {
"args": "string",
"desc": "Convierte bytes codificados en base 64 en una cadena, utilizando una página de códigos Unicode UTF-8."
},
"$number": {
"args": "arg",
"desc": "Convierte el parámetro `arg` a un número usando las siguientes reglas de conversión:\n\n - Los números no cambian\n - Las cadenas que contienen una secuencia de caracteres que representan un número JSON legal se convierten a ese número\n - Todos los demás valores provocar que se arroje un error."
},
"$abs": {
"args": "number",
"desc": "Devuelve el valor absoluto del parámetro 'número'."
},
"$floor": {
"args": "number",
"desc": "Devuelve el valor de 'número' redondeado hacia abajo al entero más cercano que sea menor o igual a 'número'."
},
"$ceil": {
"args": "number",
"desc": "Devuelve el valor de 'número' redondeado al número entero más cercano que sea mayor o igual a 'número'."
},
"$round": {
"args": "number [, precision]",
"desc": "Devuelve el valor del parámetro 'número' redondeado al número de decimales especificado por el parámetro opcional 'precisión'."
},
"$power": {
"args": "base, exponent",
"desc": "Devuelve el valor de 'base' elevado a la potencia de 'exponente'."
},
"$sqrt": {
"args": "number",
"desc": "Devuelve la raíz cuadrada del valor del parámetro 'número'."
},
"$random": {
"args": "",
"desc": "Devuelve un número pseudoaleatorio mayor o igual a cero y menor que uno."
},
"$millis": {
"args": "",
"desc": "Devuelve el número de milisegundos desde la época Unix (1 de enero de 1970 UTC) como un número. Todas las invocaciones de `$millis()` dentro de una evaluación de una expresión devolverán el mismo valor."
},
"$sum": {
"args": "array",
"desc": "Devuelve la suma aritmética de una 'matriz' de números. Es un error si la 'matriz' de entrada contiene un elemento que no es un número."
},
"$max": {
"args": "array",
"desc": "Devuelve el número máximo en una 'matriz' de números. Es un error si la 'matriz' de entrada contiene un elemento que no es un número."
},
"$min": {
"args": "array",
"desc": "Devuelve el número mínimo en una 'matriz' de números. Es un error si la 'matriz' de entrada contiene un elemento que no es un número."
},
"$average": {
"args": "array",
"desc": "Devuelve el valor medio de una 'matriz' de números. Es un error si la 'matriz' de entrada contiene un elemento que no es un número."
},
"$boolean": {
"args": "arg",
"desc": "Convierte el argumento a un booleano usando las siguientes reglas:\n\n - `Booleano`: sin cambios\n - `cadena`: vacía: `falso`\n - `cadena`: no vacía: `verdadero`\n - `número`: `0`: `falso`\n - `número`: distinto de cero: `verdadero`\n - `nulo`: `falso`\n - `matriz`: vacía: `falso`\n - `array`: contiene un miembro que se convierte en `true`: `true`\n - `array`: todos los miembros se convierten en `false`: `false`\n - `object`: vacío: `false`\n - `objeto`: no vacío: `verdadero`\n - `función`: `falso`"
},
"$not": {
"args": "arg",
"desc": "Devuelve booleano NEGADO del argumento. `arg` se convierte antes en un booleano"
},
"$exists": {
"args": "arg",
"desc": "Devuelve booleano 'verdadero' si la expresión 'arg' se evalúa como un valor, o 'falso' si la expresión no coincide con nada (por ejemplo, una ruta a una referencia de campo inexistente)."
},
"$count": {
"args": "array",
"desc": "Devuelve el número de elementos de la matriz."
},
"$append": {
"args": "array, array",
"desc": "Agrega dos matrices"
},
"$sort": {
"args": "array [, function]",
"desc": "Devuelve una matriz que contiene todos los valores en el parámetro `array`, pero ordenados.\n\nSi se proporciona una `función` de comparador, entonces debe ser una función que toma dos parámetros:\n\n`function(left , derecha)`\n\nEsta función es invocada por el algoritmo de clasificación para comparar dos valores `izquierda` y `derecha`. Si el valor de `izquierda` debe colocarse después del valor de `derecha` en el orden de clasificación deseado, entonces la función debe devolver un valor booleano 'verdadero' para indicar un intercambio. De lo contrario debe devolver 'falso'."
},
"$reverse": {
"args": "array",
"desc": "Devuelve una matriz que contiene todos los valores del parámetro `matriz`, pero en orden inverso."
},
"$shuffle": {
"args": "array",
"desc": "Devuelve una matriz que contiene todos los valores del parámetro `array`, pero mezclados en orden aleatorio."
},
"$zip": {
"args": "array, ...",
"desc": "Devuelve una matriz convolucionada (comprimida) que contiene matrices agrupadas de valores de los argumentos `matriz1`... `matrizN` del índice 0, 1, 2...."
},
"$keys": {
"args": "object",
"desc": "Devuelve una matriz que contiene las claves del objeto. Si el argumento es una matriz de objetos, entonces la matriz devuelta contiene una lista deduplicada de todas las claves de todos los objetos."
},
"$lookup": {
"args": "object, key",
"desc": "Devuelve el valor asociado con la clave en el objeto. Si el primer argumento es una matriz de objetos, entonces se buscan todos los objetos de la matriz y se devuelven los valores asociados con todas las apariciones de la clave."
},
"$spread": {
"args": "object",
"desc": "Divide un objeto que contiene pares clave/valor en una matriz de objetos, cada uno de los cuales tiene un único par clave/valor del objeto de entrada. Si el parámetro es una matriz de objetos, entonces la matriz resultante contiene un objeto para cada par clave/valor en cada objeto de la matriz proporcionada."
},
"$merge": {
"args": "array&lt;object&gt;",
"desc": "Fusiona una matriz de objetos en un único objeto que contiene todos los pares clave/valor de cada uno de los objetos en la matriz de entrada. Si alguno de los objetos de entrada contiene la misma clave, entonces el objeto devuelto contendrá el valor del último en la matriz. Es un error si la matriz de entrada contiene un elemento que no es un objeto."
},
"$sift": {
"args": "object, function",
"desc": "Devuelve un objeto que contiene solo los pares clave/valor del parámetro `objeto` que satisfacen el predicado `función` pasado como segundo parámetro.\n\nLa `función` que se proporciona como segundo parámetro debe tener la siguiente firma:\n\n`función(valor [, clave [, objeto]])`"
},
"$each": {
"args": "object, function",
"desc": "Devuelve una matriz que contiene los valores devueltos por la función cuando se aplica a cada par clave/valor en el objeto."
},
"$map": {
"args": "array, function",
"desc": "Devuelve una matriz que contiene los resultados de aplicar el parámetro `función` a cada valor en el parámetro `matriz`.\n\nLa `función` que se proporciona como segundo parámetro debe tener la siguiente firma:\n\n`función( valor [, índice [, matriz]])`"
},
"$filter": {
"args": "array, function",
"desc": "Devuelve una matriz que contiene solo los valores en el parámetro `matriz` que satisfacen el predicado `función`.\n\nLa `función` que se proporciona como segundo parámetro debe tener la siguiente firma:\n\n`función(valor [ , índice [, matriz]])`"
},
"$reduce": {
"args": "array, function [, init]",
"desc": "Devuelve un valor agregado derivado de aplicar el parámetro `función` sucesivamente a cada valor en `matriz` en combinación con el resultado de la aplicación anterior de la función.\n\nLa función debe aceptar dos argumentos y se comporta como un operador infijo entre cada valor dentro de la matriz. La firma de la `función` debe tener la forma: `myfunc($accumulator, $value[, $index[, $array]])`\n\nEl parámetro opcional `init` se utiliza como valor inicial en la agregación."
},
"$flowContext": {
"args": "string[, string]",
"desc": "Recupera una propiedad de contexto de flujo.\n\nEsta es una función definida por Node-RED."
},
"$globalContext": {
"args": "string[, string]",
"desc": "Recupera una propiedad de contexto global.\n\nEsta es una función definida por Node-RED."
},
"$pad": {
"args": "string, width [, char]",
"desc": "Devuelve una copia de la `cadena` con relleno adicional, si es necesario, de modo que su número total de caracteres sea al menos el valor absoluto del parámetro `ancho`.\n\nSi `ancho` es un número positivo, entonces la cadena está acolchado hacia la derecha; si es negativo, se rellena hacia la izquierda.\n\nEl argumento opcional `char` especifica los caracteres de relleno que se utilizarán. Si no se especifica, el valor predeterminado es el carácter de espacio."
},
"$fromMillis": {
"args": "number, [, picture [, timezone]]",
"desc": "Convierte el `número` que representa milisegundos desde la época Unix (1 de enero de 1970 UTC) en una representación de cadena formateada según la plantilla en picture.\n\nSi se omite el parámetro opcional `picture`, entonces la marca de tiempo es formateado en el formato ISO 8601.\n\nSi se proporciona la cadena opcional `picture`, entonces la marca de tiempo se formatea de acuerdo con la representación especificada en esa cadena. El comportamiento de esta función es consistente con la versión de dos argumentos de la función XPath/XQuery `format-dateTime` tal como se define en la especificación XPath F&O 3.1. El parámetro de plantilla define cómo se formatea la marca de tiempo y tiene la misma sintaxis que `format-dateTime`.\n\nSi se proporciona la cadena opcional `timezone`, entonces la marca de tiempo formateada estará en esa zona horaria. La cadena `timezone` debe tener el formato '±HHMM', donde ± es el signo más o menos y HHMM es el desplazamiento en horas y minutos desde UTC. Desplazamiento positivo para zonas horarias al este de UTC, desplazamiento negativo para zonas horarias al oeste de UTC."
},
"$formatNumber": {
"args": "number, picture [, options]",
"desc": "Convierte el `número` en una cadena y lo formatea en una representación decimal según lo especificado en la cadena `picture`.\n\n El comportamiento de esta función es coherente con la función XPath/XQuery `fn:format-number` tal como se define en la especificación XPath F&O 3.1. El parámetro de cadena `picture` define cómo se formatea el número y tiene la misma sintaxis que `fn:formato-número`.\n\nEl tercer argumento opcional `opciones` se utiliza para anular los caracteres de formato específicos de la configuración regional predeterminada, como el decimal. separador. Si se proporciona, este argumento debe ser un objeto que contenga pares de nombre/valor especificados en la sección de formato decimal de la especificación XPath F&O 3.1."
},
"$formatBase": {
"args": "number [, radix]",
"desc": "Convierte el número en una cadena y lo formatea como un número entero representado en la base numérica especificada por el argumento `radix`. Si no se especifica `radix`, el valor predeterminado es la base 10. `radix` puede estar entre 2 y 36; de lo contrario, se genera un error."
},
"$toMillis": {
"args": "timestamp",
"desc": "Convierte una cadena de `marca de tiempo` en el formato ISO 8601 al número de milisegundos desde la época Unix (1 de enero de 1970 UTC) como un número. Se genera un error si la cadena no tiene el formato correcto."
},
"$env": {
"args": "arg",
"desc": "Devuelve el valor de una variable de entorno.\n\nEsta es una función definida por Node-RED."
},
"$eval": {
"args": "expr [, context]",
"desc": "Analiza y evalúa la cadena `expr` que contiene JSON literal o una expresión JSONata utilizando el contexto actual como contexto para la evaluación."
},
"$formatInteger": {
"args": "number, picture",
"desc": "Convierte el número en una cadena y lo formatea en una representación entera como lo especifica la cadena `picture`. El parámetro de define cómo se formatea el número y tiene la misma sintaxis que `fn:format-integer` de la especificación XPath F&O 3.1."
},
"$parseInteger": {
"args": "string, picture",
"desc": "Analiza el contenido del parámetro cadena en un número entero (como un número JSON) utilizando el formato especificado por la cadena `picture`. El parámetro tiene el mismo formato que `$formatInteger`."
},
"$error": {
"args": "[str]",
"desc": "Lanza un error con un mensaje. El parámetro `str` opcional reemplazará el mensaje predeterminado de `$error() función evaluada`"
},
"$assert": {
"args": "arg, str",
"desc": "Si `arg` es `verdadero`, la función devuelve indefinido. Si `arg` es `falso`, se lanza una excepción con `str` como mensaje de excepción."
},
"$single": {
"args": "array, function",
"desc": "Devuelve el único valor en el parámetro `array` que satisface el predicado de `función` (es decir, la `función` devuelve booleano `verdadero` cuando se pasa el valor). Lanza una excepción si el número de valores coincidentes no es exactamente uno.\n\nLa función debe proporcionarse con la siguiente firma: `función(valor [, índice [, matriz]])` donde el valor es cada entrada de la matriz. El índice es la posición de ese valor y toda la matriz se pasa como tercer argumento."
},
"$encodeUrlComponent": {
"args": "str",
"desc": "Codifica un componente de URL reemplazando cada instancia de ciertos caracteres por una, dos, tres o cuatro secuencias de escape que representan la codificación UTF-8 del carácter.\n\nEjemplo: `$encodeUrlComponent(\"?x=prueba\")` => `\"%3Fx%3Dprueba\"`"
},
"$encodeUrl": {
"args": "str",
"desc": "Codifica una URL reemplazando cada instancia de ciertos caracteres por una, dos, tres o cuatro secuencias de escape que representan la codificación UTF-8 del carácter.\n\nEjemplo: `$encodeUrl(\"https://mozilla.org/?x=шеллы\")` => `\"https://mozilla.org/?x=%D1%88%D0%B5%D0%BB%D0%BB%D1%8B\"`"
},
"$decodeUrlComponent": {
"args": "str",
"desc": "Decodifica un componente de URL creado previamente por encodeUrlComponent.\n\nEjemplo: `$decodeUrlComponent(\"%3Fx%3Dtest\")` => `\"?x=test\"`"
},
"$decodeUrl": {
"args": "str",
"desc": "Decodifica una URL creado previamente por encodeUrl.\n\nEjemplo: `$decodeUrl(\"https://mozilla.org/?x=%D1%88%D0%B5%D0%BB%D0%BB%D1%8B\")` => `\"https://mozilla.org/?x=шеллы\"`"
},
"$distinct": {
"args": "array",
"desc": "Devuelve una matriz con valores duplicados eliminados de `matriz`"
},
"$type": {
"args": "value",
"desc": "Devuelve el tipo de `valor` como una cadena. Si `valor` no está definido, esto devolverá indefinido."
},
"$moment": {
"args": "[str]",
"desc": "Obtiene un objeto de fecha usando la biblioteca Moment."
},
"$clone": {
"args": "value",
"desc": "Clona un objeto de forma segura."
}
}

View File

@@ -119,10 +119,9 @@
"searchInput": "Rechercher vos flux",
"subflows": "Sous-flux",
"createSubflow": "Créer un sous-flux",
"selectionToSubflow": "Selection d'un sous-flux",
"selectionToSubflow": "Convertir en sous-flux",
"flows": "Flux",
"add": "Ajouter",
"rename": "Renommer",
"delete": "Supprimer",
"keyboardShortcuts": "Raccourcis clavier",
"login": "Se connecter",
@@ -130,6 +129,11 @@
"editPalette": "Gérer la palette",
"other": "Autre",
"showTips": "Afficher les astuces",
"showNodeHelp": "Afficher l'aide du noeud",
"enableSelectedNodes": "Activer les noeuds sélectionnés",
"disableSelectedNodes": "Désactiver les noeuds sélectionnés",
"showSelectedNodeLabels": "Afficher les étiquettes des noeuds sélectionnés",
"hideSelectedNodeLabels": "Masquer les étiquettes des noeuds sélectionnés",
"showWelcomeTours": "Afficher les visites guidées pour les nouvelles versions",
"help": "Site web de Node-RED",
"projects": "Projets",
@@ -274,23 +278,23 @@
"recoveredNodesInfo": "Les noeuds importés sur ce flux contiennent un mauvais identifiant de flux. Ces noeuds ont été ajoutés à ce flux afin que vous puissiez les restaurer ou les supprimer.",
"recoveredNodesNotification": "<p>Noeuds importés sans identifiant de flux valide</p><p>Ils ont été ajoutés à un nouveau flux appelé '__flowName__'.</p>",
"export": {
"selected": "noeuds sélectionnés",
"current": "flux actuel",
"selected": "les noeuds sélectionnés",
"current": "le flux actuel",
"all": "tous les flux",
"compact": "condensé",
"formatted": "formaté",
"compact": "Condensé",
"formatted": "Formaté",
"copy": "Copier dans le presse-papier",
"export": "Exporter vers la bibliothèque",
"exportAs": "Exporter en tant que",
"exportAs": "Exporter comme",
"overwrite": "Remplacer",
"exists": "<p><b>\"__file__\"</b> existe déjà.</p><p>Voulez-vous le remplacer ?</p>"
},
"import": {
"import": "Importer vers",
"importSelected": "Importation sélectionnée",
"importSelected": "Importer la sélection",
"importCopy": "Importer une copie",
"viewNodes": "Afficher les noeuds...",
"newFlow": "Nouveau flux",
"viewNodes": "Vérifier ces noeuds",
"newFlow": "un nouveau flux",
"replace": "Remplacer",
"errors": {
"notArray": "L'entrée n'est pas un tableau JSON",
@@ -299,7 +303,8 @@
"missingType": "L'entrée n'est pas un flux valide - l'élément '__index__' n'a pas de propriété 'type'"
},
"conflictNotification1": "Certains des noeuds que vous avez importés existent déjà dans votre espace de travail.",
"conflictNotification2": "Sélectionner les noeuds à importer et choisir s'il faut remplacer les noeuds existants ou en importer une copie."
"conflictNotification2": "Sélectionnez les noeuds à importer et choisissez s'il faut remplacer les noeuds existants ou en importer une copie.",
"alreadyExists": "Ce noeud existe déjà"
},
"copyMessagePath": "Chemin copié",
"copyMessageValue": "Valeur copiée",
@@ -391,10 +396,10 @@
"subflowInstances": "Il existe __count__ instance de ce modèle de sous-flux",
"subflowInstances_plural": "Il existe __count__ instances de ce modèle de sous-flux",
"editSubflowProperties": "modifier les propriétés",
"input": "entrées:",
"output": "sorties:",
"status": "statut du noeud",
"deleteSubflow": "supprimer le sous-flux",
"input": "Entrées:",
"output": "Sorties:",
"status": "Statut du noeud",
"deleteSubflow": "Supprimer le sous-flux",
"confirmDelete": "Voulez-vous vraiment supprimer ce sous-flux ?",
"info": "Description",
"category": "Catégorie",
@@ -416,6 +421,7 @@
},
"errors": {
"noNodesSelected": "<strong>Impossible de créer un sous-flux</strong> : aucun noeud sélectionné",
"acrossMultipleGroups": "Impossible de créer un sous-flux sur plusieurs groupes",
"multipleInputsToSelection": "<strong>Impossible de créer un sous-flux</strong> : plusieurs entrées pour la sélection"
}
},
@@ -447,8 +453,8 @@
"default": "Par défaut",
"noDefaultLabel": "Aucune",
"defaultLabel": "Utiliser l'étiquette par défaut",
"searchIcons": "Icônes de recherche",
"useDefault": "Utilisation par défaut",
"searchIcons": "Rechercher une icône",
"useDefault": "Icône par défaut",
"description": "Description",
"show": "Afficher",
"hide": "Masquer",
@@ -498,19 +504,19 @@
"keyboard": {
"title": "Raccourcis clavier",
"keyboard": "Clavier",
"filterActions": "Actions de filtrage",
"shortcut": "raccourci",
"scope": "portée",
"filterActions": "Rechercher l'action",
"shortcut": "Raccourci",
"scope": "Portée",
"unassigned": "Non attribué",
"global": "global",
"workspace": "espace de travail",
"editor": "boîte de dialogue d'édition",
"global": "Global",
"workspace": "Espace de travail",
"editor": "Boîte de dialogue d'édition",
"selectAll": "Tout sélectionner",
"selectNone": "Ne rien sélectionner",
"selectAllConnected": "Sélectionner tous les éléments connectés",
"addRemoveNode": "Ajouter/supprimer un noeud de la sélection",
"editSelected": "Modifier le noeud sélectionné",
"deleteSelected": "Supprimer les noeuds ou le lien sélectionné(s)",
"deleteSelected": "Supprimer la sélection",
"deleteReconnect": "Supprimer et reconnecter",
"importNode": "Importer les noeuds",
"exportNode": "Exporter les noeuds",
@@ -550,22 +556,22 @@
},
"palette": {
"noInfo": "Pas d'information disponible",
"filter": "Filtrer les noeuds",
"filter": "Rechercher le noeud",
"search": "Rechercher les modules",
"addCategory": "Ajouter un nouveau...",
"label": {
"subflows": "sous-flux",
"network": "réseau",
"common": "commun",
"input": "entrée",
"output": "sortie",
"function": "fonction",
"sequence": "séquence",
"parser": "analyseur",
"social": "social",
"storage": "stockage",
"analysis": "analyse",
"advanced": "avancé"
"subflows": "Sous-flux",
"network": "Réseau",
"common": "Commun",
"input": "Entrée",
"output": "Sortie",
"function": "Fonction",
"sequence": "Séquence",
"parser": "Analyseur",
"social": "Social",
"storage": "Stockage",
"analysis": "Analyse",
"advanced": "Avancé"
},
"actions": {
"collapse-all": "Réduire toutes les catégories",
@@ -586,6 +592,7 @@
"editor": {
"title": "Gérer la palette",
"palette": "Palette",
"allCatalogs": "Tous les catalogues",
"times": {
"seconds": "il y a quelques secondes",
"minutes": "il y a quelques minutes",
@@ -609,24 +616,25 @@
"nodeCount_plural": "__label__ noeuds",
"moduleCount": "__count__ module disponible",
"moduleCount_plural": "__count__ modules disponibles",
"inuse": "en cours d'utilisation",
"enableall": "activer tout",
"disableall": "désactiver tout",
"enable": "activer",
"disable": "désactiver",
"remove": "supprimer",
"update": "mettre à jour vers __version__",
"updated": "mis à jour",
"install": "installer",
"installed": "installé",
"conflict": "conflit",
"inuse": "En cours d'utilisation",
"enableall": "Activer tout",
"disableall": "Désactiver tout",
"enable": "Activer",
"disable": "Désactiver",
"remove": "Supprimer",
"update": "Mettre à jour vers __version__",
"updated": "Mis à jour",
"install": "Installer",
"installed": "Installé",
"conflict": "Conflit",
"conflictTip": "<p>Ce module ne peut pas être installé car il inclut un<br/>type de noeud qui a déjà été installé</p><p>Conflits avec <code>__module__</code></p>",
"loading": "Chargement des catalogues...",
"tab-nodes": "Noeuds",
"tab-install": "Installer",
"sort": "trier:",
"sortAZ": "a-z",
"sortRecent": "récent",
"sort": "Trier:",
"sortRelevance": "Pertinence",
"sortAZ": "A-Z",
"sortRecent": "Récent",
"more": "+ __count__ en plus",
"upload": "Charger le fichier tgz du module",
"refresh": "Actualiser la liste des modules",
@@ -667,7 +675,7 @@
"info": {
"name": "Information",
"tabName": "Nom",
"label": "info",
"label": "Info",
"node": "Noeud",
"type": "Type",
"group": "Groupe",
@@ -681,10 +689,10 @@
"properties": "Propriétés",
"info": "Information",
"desc": "Description",
"blank": "vide",
"null": "nul",
"showMore": "afficher en plus",
"showLess": "afficher en moins",
"blank": "Vide",
"null": "Nul",
"showMore": "Afficher en plus",
"showLess": "Afficher en moins",
"flow": "Flux",
"selection": "Sélection",
"nodes": "__count__ noeuds",
@@ -695,7 +703,7 @@
"arrayItems": "__count__ éléments",
"showTips": "Vous pouvez ouvrir les astuces à partir du panneau des paramètres",
"outline": "Plan",
"empty": "vide",
"empty": "Vide",
"globalConfig": "Noeuds de configuration globale",
"triggerAction": "Déclencher une action",
"find": "Rechercher dans l'espace de travail",
@@ -706,7 +714,7 @@
},
"help": {
"name": "Aide",
"label": "aide",
"label": "Aide",
"search": "Aide à la recherche",
"nodeHelp": "Aide sur les noeuds",
"showHelp": "Afficher l'aide",
@@ -717,23 +725,23 @@
},
"config": {
"name": "Noeuds de configuration",
"label": "configuration",
"label": "Configuration",
"global": "Tous les flux",
"none": "aucun",
"subflows": "sous-flux",
"flows": "flux",
"filterAll": "tout",
"none": "Aucun",
"subflows": "Sous-flux",
"flows": "Flux",
"filterAll": "Tout",
"showAllConfigNodes": "Afficher tous les noeuds de configuration",
"filterUnused": "inutilisé",
"filterUnused": "Inutilisé",
"showAllUnusedConfigNodes": "Afficher tous les noeuds de configuration inutilisés",
"filtered": "__count__ caché(s)"
},
"context": {
"name": "Données contextuelles",
"label": "contexte",
"none": "aucune sélection",
"refresh": "actualiser pour charger",
"empty": "vide",
"label": "Contexte",
"none": "Aucune sélection",
"refresh": "Actualiser pour charger",
"empty": "Vide",
"node": "Noeud",
"flow": "Flux",
"global": "Global",
@@ -744,10 +752,10 @@
},
"palette": {
"name": "Gestion des palettes",
"label": "palette"
"label": "Palette"
},
"project": {
"label": "projet",
"label": "Projet",
"name": "Projet",
"description": "Description",
"dependencies": "Dépendances",
@@ -760,11 +768,11 @@
"showProjectSettings": "Afficher les paramètres du projet",
"projectSettings": {
"title": "Paramètres du projet",
"edit": "modifier",
"edit": "Modifier",
"none": "Vide",
"install": "installer",
"removeFromProject": "supprimer du projet",
"addToProject": "ajouter au projet",
"install": "Installer",
"removeFromProject": "Supprimer du projet",
"addToProject": "Ajouter au projet",
"files": "Fichiers",
"flow": "Flux",
"credentials": "Identifiants",
@@ -812,7 +820,7 @@
"workflowAutoTip": "Les modifications sont validées automatiquement à chaque déploiement",
"sshKeys": "Clés SSH",
"sshKeysTip": "Vous permet de créer des connexions sécurisées aux référentiels Git distants.",
"add": "ajouter une clé",
"add": "Ajouter une clé",
"addSshKey": "Ajouter une clé SSH",
"addSshKeyTip": "Générer une nouvelle paire de clés publique/privée",
"name": "Nom",
@@ -826,7 +834,7 @@
"copyPublicKey": "Copier la clé publique dans le presse-papiers",
"delete": "Supprimer une clé",
"gitConfig": "Configuration Git",
"deleteConfirm": "Êtes-vous sûr de vouloir supprimer la clé SSH __nom__ ? Ça ne peut pas être annulé."
"deleteConfirm": "Êtes-vous sûr de vouloir supprimer la clé SSH __name__ ? Ça ne peut pas être annulé."
},
"versionControl": {
"unstagedChanges": "Abandon des changements",
@@ -848,7 +856,7 @@
"none": "Vide",
"conflictResolve": "Tous les conflits ont été résolus. Valider les modifications pour terminer la fusion.",
"localFiles": "Fichiers locaux",
"all": "tout",
"all": "Tout",
"unmergedChanges": "Modifications non fusionnées",
"abortMerge": "Abandonner la fusion",
"commit": "Valider",
@@ -1097,9 +1105,9 @@
"desc8": "Le fichier contenant les identifiants ne sera pas crypté et son contenu sera facilement lisible",
"create-project-files": "Créer des fichiers de projet",
"create-project": "Créer un projet",
"already-exists": "existe déjà",
"already-exists": "Existe déjà",
"git-error": "Erreur Git",
"git-auth-error": "erreur d'authentification Git"
"git-auth-error": "Erreur d'authentification Git"
},
"create-success": {
"success": "Vous avez créé avec succès votre premier projet !",
@@ -1135,8 +1143,8 @@
"desc2": "Avant de pouvoir cloner un référentiel sur ssh, vous devez ajouter une clé SSH pour y accéder.",
"add-ssh-key": "Ajouter une clé ssh",
"credentials-encryption-key": "Clé de chiffrement des identifiants",
"already-exists-2": "existe déjà",
"git-error": "erreur git",
"already-exists-2": "Existe déjà",
"git-error": "Erreur git",
"con-failed": "La connexion a échoué",
"not-git": "Ce n'est pas un dépôt git",
"no-resource": "Référentiel introuvable",
@@ -1148,8 +1156,8 @@
"confirm": "Voulez-vous vraiment supprimer ce projet ?"
},
"create-project-list": {
"search": "rechercher vos projets",
"current": "actuel"
"search": "Rechercher vos projets",
"current": "Actuel"
},
"require-clean": {
"confirm": "<p>Vous avez des modifications non déployées qui seront perdues.</p><p>Voulez-vous continuer ?</p>"
@@ -1198,23 +1206,11 @@
"diagnostics": {
"title": "Information système"
},
"languages": {
"de": "Allemand",
"en-US": "Anglais",
"fr": "Français",
"ja": "Japonais",
"ko": "Coréen",
"pt-BR": "Portugais brésilien",
"ru": "Russe",
"zh-CN": "Chinois (Simplifié)",
"zh-TW": "Chinois (Traditionnel)"
},
"validator": {
"errors": {
"invalid-json": "Données JSON invalides : __error__",
"invalid-json-prop": "__prop__: données JSON invalides : __error__",
"invalid-prop": "Expression de propriété non valide",
"invalid-prop-prop": "__prop__: expression de propriété invalide",
"invalid-expr": "Expression JSONata invalide : __error__",
"invalid-prop": "Expression de propriété invalide",
"invalid-num": "Numéro invalide",
"invalid-num-prop": "__prop__: numéro invalide",
"invalid-regexp": "Modèle d'entrée non valide",
@@ -1226,6 +1222,7 @@
}
},
"contextMenu": {
"showActionList": "Afficher la liste des actions",
"insert": "Insérer",
"node": "Noeud",
"junction": "Jonction",
@@ -1235,5 +1232,159 @@
"environment": "Environment",
"header": "Variables d'environnement globales",
"revert": "Rétablir"
},
"action-list": {
"toggle-show-tips": "Basculer l'affichage des astuces",
"show-about": "Afficher la description de Node-RED",
"show-welcome-tour": "Afficher la visite de bienvenue",
"show-next-tab": "Afficher l'onglet suivant",
"show-previous-tab": "Afficher l'onglet précédent",
"add-flow": "Ajouter un flux",
"add-flow-to-right": "Ajouter un flux à droite",
"edit-flow": "Modifier le flux",
"remove-flow": "Supprimer le flux",
"enable-flow": "Activer le flux",
"disable-flow": "Désactiver le flux",
"hide-flow": "Masquer le flux",
"hide-other-flows": "Masquer les autres flux",
"hide-all-flows": "Masquer tous les flux",
"show-all-flows": "Afficher tous les flux",
"show-last-hidden-flow": "Afficher le dernier flux masqué",
"list-modified-nodes": "Afficher les flux modifiés",
"list-hidden-flows": "Afficher les flux cachés",
"list-flows": "Lister les flux",
"list-subflows": "Liste les sous-flux",
"go-to-previous-location": "Aller à l'emplacement précédent",
"go-to-next-location": "Aller à l'emplacement suivant",
"copy-selection-to-internal-clipboard": "Copier la sélection dans le presse-papiers",
"cut-selection-to-internal-clipboard": "Couper la sélection dans le presse-papiers",
"paste-from-internal-clipboard": "Coller depuis le presse-papiers",
"detach-selected-nodes": "Détacher les noeuds sélectionnés",
"delete-selection": "Supprimer la sélection",
"delete-selection-and-reconnect": "Supprimer la sélection et reconnecter",
"edit-selected-node": "Modifier le noeud sélectionné",
"go-to-selection": "Aller à la sélection",
"undo": "Annuler les modifications",
"redo": "Rétablir les modifications",
"select-all-nodes": "Sélectionner tous les noeuds",
"select-none": "Sélectionner un noeud",
"enable-selected-nodes": "Activer les noeuds sélectionnés",
"disable-selected-nodes": "Désactiver les noeuds sélectionnés",
"toggle-show-grid": "Basculer l'affichage de la grille",
"toggle-snap-grid": "Basculer l'aide au placement des noeuds",
"toggle-status": "Commuter l'état",
"show-selected-node-labels": "Afficher les étiquettes des noeuds sélectionnés",
"hide-selected-node-labels": "Masquer les étiquettes des noeuds sélectionnés",
"scroll-view-up": "Faire défiler vers le haut",
"scroll-view-right": "Faire défiler vers la droite",
"scroll-view-down": "Faire défiler vers le bas",
"scroll-view-left": "Faire défiler vers la gauche",
"step-view-up": "Faire défiler d'une unité vers le haut",
"step-view-right": "Faire défiler d'une unité vers la droite",
"step-view-down": "Faire défiler d'une unité vers le bas",
"step-view-left": "Faire défiler d'une unité vers la gauche",
"move-selection-up": "Déplacer la sélection vers le haut",
"move-selection-right": "Déplacer la sélection vers la droite",
"move-selection-down": "Déplacer la sélection vers le bas",
"move-selection-left": "Déplacer la sélection vers la gauche",
"move-selection-forwards": "Avancer la sélection",
"move-selection-backwards": "Reculer la sélection",
"move-selection-to-front": "Déplacer la sélection vers l'avant",
"move-selection-to-back": "Déplacer la sélection vers l'arrière",
"step-selection-up": "Déplacer la sélection d'une unité vers le haut",
"step-selection-right": "Déplacer la sélection d'une unité vers la droite",
"step-selection-down": "Déplacer la sélection d'une unité vers le bas",
"step-selection-left": "Déplacer la sélection d'une unité vers la gauche",
"select-connected-nodes": "Sélectionner les noeuds connectés",
"select-downstream-nodes": "Sélectionner les noeuds connectés en aval",
"select-upstream-nodes": "Sélectionner les noeuds connectés en amont",
"go-to-next-node": "Aller au noeud suivant",
"go-to-previous-node": "Aller au noeud précédent",
"go-to-next-sibling": "Aller au noeud frère suivant",
"go-to-previous-sibling": "Aller au noeud frère précédent",
"go-to-nearest-node-on-left": "Aller au noeud gauche le plus proche",
"go-to-nearest-node-on-right": "Aller au noeud droit le plus proche",
"go-to-nearest-node-above": "Aller au noeud supérieur le plus proche",
"go-to-nearest-node-below": "Aller au noeud le plus proche ci-dessous",
"align-selection-to-grid": "Aligner la sélection",
"align-selection-to-left": "Aligner la sélection à gauche",
"align-selection-to-right": "Aligner la sélection à droite",
"align-selection-to-top": "Aligner la sélection en haut",
"align-selection-to-bottom": "Aligner la sélection vers le bas",
"align-selection-to-middle": "Aligner la sélection au centre verticalement",
"align-selection-to-center": "Aligner la sélection au centre horizontalement",
"distribute-selection-horizontally": "Distribuer la sélection horizontalement",
"distribute-selection-vertical": "Distribuer la sélection verticalement",
"wire-series-of-nodes": "Connecter les noeuds en série",
"wire-node-to-multiple": "Connecter les noeuds à plusieurs",
"wire-multiple-to-node": "Connecter plusieurs au noeud",
"split-wire-with-link-nodes": "Diviser le fil avec des noeuds de liaison",
"generate-node-names": "Générer les noms de noeuds",
"show-user-settings": "Afficher les paramètres utilisateur",
"show-help": "Afficher l'aide",
"toggle-palette": "Basculer l'affichage de la palette",
"show-event-log": "Afficher le journal des événements",
"manage-palette": "Gérer la palette",
"toggle-sidebar": "Basculer l'affichage de la barre latérale",
"show-info-tab": "Afficher l'onglet d'informations sur le noeud",
"show-help-tab": "Afficher l'onglet d'aide du noeud",
"show-config-tab": "Afficher l'onglet du noeud de configuration",
"select-all-config-nodes": "Sélectionner tous les noeuds de configuration",
"delete-config-selection": "Supprimer le noeud de configuration sélectionné",
"show-context-tab": "Afficher l'onglet des données contextuelles",
"create-subflow": "Créer un sous-flux",
"convert-to-subflow": "Convertir la sélection en sous-flux",
"group-selection": "Grouper la sélection",
"ungroup-selection": "Dissocier la sélection",
"merge-selection-to-group": "Fusionner la sélection dans le groupe",
"remove-selection-from-group": "Supprimer la sélection du groupe",
"copy-group-style": "Copier le style du groupe",
"paste-group-style": "Coller le style du groupe",
"show-export-dialog": "Afficher la boîte de dialogue d'exportation",
"show-import-dialog": "Afficher la boîte de dialogue d'importation",
"show-library-export-dialog": "Afficher la boîte de dialogue d'exportation de la bibliothèque",
"show-library-import-dialog": "Afficher la boîte de dialogue d'importation de bibliothèque",
"show-examples-import-dialog": "Afficher la boîte de dialogue d'importation d'exemples",
"search": "Rechercher",
"search-previous": "Recherche précédente",
"search-next": "Recherche suivante",
"show-action-list": "Afficher la liste d'actions",
"confirm-edit-tray": "Confirmer la modification",
"cancel-edit-tray": "Annuler la modification",
"show-remote-diff": "Afficher les différences avec les modifications distantes",
"deploy-flows": "Déployer des flux",
"restart-flows": "Redémarrer les flux",
"set-deploy-type-to-full": "Définir le déploiement sur 'tout'",
"set-deploy-type-to-modified-flows": "Définir le déploiement sur 'flux modifiés'",
"set-deploy-type-to-modified-nodes": "Définir le déploiement sur 'noeuds modifiés'",
"show-debug-tab": "Afficher l'onglet de débogage",
"clear-debug-messages": "Supprimer les messages de débogage",
"clear-filtered-debug-messages": "Supprimer les messages de débogage filtrés",
"activate-selected-debug-nodes": "Activer les noeuds de débogage sélectionnés",
"activate-all-debug-nodes": "Activer tous les noeuds de débogage",
"activate-all-flow-debug-nodes": "Activer tous les noeuds de débogage dans un flux",
"deactivate-selected-debug-nodes": "Désactiver les noeuds de débogage sélectionnés",
"deactivate-all-debug-nodes": "Désactiver tous les noeuds de débogage",
"deactivate-all-flow-debug-nodes": "Désactiver tous les noeuds de débogage dans un flux",
"zoom-in": "Zoomer",
"zoom-out": "Dézoomer",
"zoom-reset": "Réinitialiser le zoom",
"toggle-navigator": "Basculer l'affichage du navigateur",
"show-system-info": "Afficher les informations système",
"split-wires-with-junctions": "Diviser les fils avec des jonctions",
"new-project": "Nouveau projet",
"open-project": "Ouvrir le projet",
"show-project-settings": "Afficher les paramètres du projet",
"show-version-control-tab": "Afficher l'onglet de contrôle de version",
"start-flows": "Démarrer les flux",
"stop-flows": "Arrêter les flux",
"copy-item-url": "Copier l'URL de l'élément",
"copy-item-edit-url": "Copier l'URL de modification de l'élément",
"move-flow-to-start": "Déplacer le flux jusqu'au début",
"move-flow-to-end": "Déplacer le flux jusqu'à la fin",
"show-global-env": "Afficher les variables d'environnement globales",
"lock-flow": "Verrouiller le flux",
"unlock-flow": "Déverrouiller le flux",
"show-node-help": "Afficher l'aide du noeud"
}
}

View File

@@ -270,5 +270,9 @@
"$moment": {
"args": "[str]",
"desc": "Obtient un objet de date à l'aide de la bibliothèque Moment."
},
"$clone": {
"args": "valeur",
"desc": "Cloner un objet en toute sécurité."
}
}

View File

@@ -122,7 +122,6 @@
"selectionToSubflow": "選択部分をサブフロー化",
"flows": "フロー",
"add": "フローを新規追加",
"rename": "フロー名を変更",
"delete": "フローを削除",
"keyboardShortcuts": "ショートカットキーの説明",
"login": "ログイン",
@@ -130,6 +129,11 @@
"editPalette": "パレットの管理",
"other": "その他",
"showTips": "ヒントを表示",
"showNodeHelp": "ノードのヘルプを表示",
"enableSelectedNodes": "選択したノードを有効化",
"disableSelectedNodes": "選択したノードを無効化",
"showSelectedNodeLabels": "選択したノードのラベル表示",
"hideSelectedNodeLabels": "選択したノードのラベル非表示",
"showWelcomeTours": "新バージョンのガイドツアーを表示",
"help": "Node-REDウェブサイト",
"projects": "プロジェクト",
@@ -511,7 +515,7 @@
"selectAllConnected": "接続されたノードを選択",
"addRemoveNode": "ノードの選択、選択解除",
"editSelected": "選択したノードを編集",
"deleteSelected": "選択したノードや接続を削除",
"deleteSelected": "選択部分を削除",
"deleteReconnect": "削除と再接続",
"importNode": "フローの読み込み",
"exportNode": "フローの書き出し",
@@ -1201,23 +1205,11 @@
"diagnostics": {
"title": "システム情報"
},
"languages": {
"de": "ドイツ語",
"en-US": "英語",
"fr": "フランス語",
"ja": "日本語",
"ko": "韓国語",
"pt-BR": "ポルトガル語",
"ru": "ロシア語",
"zh-CN": "中国語(簡体)",
"zh-TW": "中国語(繁体)"
},
"validator": {
"errors": {
"invalid-json": "JSONデータが不正: __error__",
"invalid-json-prop": "__prop__: JSONデータが不正: __error__",
"invalid-expr": "不正なJSONata式: __error__",
"invalid-prop": "プロパティ式が不正",
"invalid-prop-prop": "__prop__: プロパティ式が不正",
"invalid-num": "数値が不正",
"invalid-num-prop": "__prop__: 数値が不正",
"invalid-regexp": "入力パターンが不正",
@@ -1229,6 +1221,7 @@
}
},
"contextMenu": {
"showActionList": "動作一覧を表示",
"insert": "挿入",
"node": "ノード",
"junction": "分岐点",

View File

@@ -79,7 +79,6 @@
"selectionToSubflow": "서브 플로우 선택",
"flows": "플로우",
"add": "추가",
"rename": "이름변경",
"delete": "삭제",
"keyboardShortcuts": "단축키",
"login": "로그인",

View File

@@ -109,7 +109,6 @@
"selectionToSubflow": "Seleção para subfluxo",
"flows": "Fluxos",
"add": "Adicionar",
"rename": "Renomear",
"delete": "Apagar",
"keyboardShortcuts": "Atalhos do teclado",
"login": "Ingressar",
@@ -1173,22 +1172,10 @@
"diagnostics": {
"title": "informações do Sistema"
},
"languages": {
"de": "Alemão",
"en-US": "Inglês",
"ja": "Japonês",
"ko": "Coreano",
"pt-BR": "Português(Brasil)",
"ru": "Russo",
"zh-CN": "Chinês(Simplificado)",
"zh-TW": "Chinês(Tradicional)"
},
"validator": {
"errors": {
"invalid-json": "Dados JSON inválidos: __error__",
"invalid-json-prop": "__prop__: dados JSON inválidos: __error__",
"invalid-prop": "Expressão de propriedade inválida",
"invalid-prop-prop": "__prop__: expressão de propriedade inválida",
"invalid-num": "Número inválido",
"invalid-num-prop": "__prop__: número inválido",
"invalid-regexp": "Padrão de entrada inválido",

View File

@@ -95,7 +95,6 @@
"selectionToSubflow": "Выделение в подпоток",
"flows": "Потоки",
"add": "Добавить",
"rename": "Переименовать",
"delete": "Удалить",
"keyboardShortcuts": "Сочетания клавиш",
"login": "Войти",
@@ -1129,16 +1128,5 @@
"appearance": "Внешний вид",
"preview": "Предпросмотр редактора",
"defaultValue": "Значение по умолчанию"
},
"languages" : {
"de": "Немецкий",
"en-US": "Английский",
"fr": "Французский",
"ja": "Японский",
"ko": "Корейский",
"pt-BR":"португальский",
"ru": "Русский",
"zh-CN": "Китайский (упрощенный)",
"zh-TW": "Китайский (традиционный)"
}
}

View File

@@ -23,7 +23,11 @@
"position": "位置",
"enable": "启用",
"disable": "禁用",
"upload": "上传"
"upload": "上传",
"lock": "锁定",
"unlock": "解锁",
"locked": "锁定",
"unlocked": "解锁"
},
"type": {
"string": "字符串",
@@ -68,7 +72,13 @@
"enabled": "有效",
"disabled": "无效",
"info": "详细描述",
"selectNodes": "点击节点来选择"
"selectNodes": "点击节点来选择",
"enableFlow": "启用流程",
"disableFlow": "禁用流程",
"lockFlow": "锁定流程",
"unlockFlow": "解除锁定",
"moveToStart": "移动到起始",
"moveToEnd": "移动到末尾"
},
"menu": {
"label": {
@@ -101,6 +111,7 @@
"displayStatus": "显示节点状态",
"displayConfig": "修改节点配置",
"import": "导入",
"importExample": "导入示例流程",
"export": "导出",
"search": "查找流程",
"searchInput": "查找流程",
@@ -109,7 +120,6 @@
"selectionToSubflow": "将选择部分更改为子流程",
"flows": "流程",
"add": "增加",
"rename": "重命名",
"delete": "删除",
"keyboardShortcuts": "键盘快捷方式",
"login": "登录",
@@ -142,7 +152,12 @@
"moveToBack": "置于底层",
"moveToFront": "置于顶层",
"moveBackwards": "向后移动",
"moveForwards": "向前移动"
"moveForwards": "向前移动",
"showNodeHelp":"显示节点帮助",
"enableSelectedNodes":"启用当前选中节点",
"disableSelectedNodes":"禁用当前选中节点",
"showSelectedNodeLabels":"显示选中的节点标签",
"hideSelectedNodeLabels":"隐藏选中的节点标签"
}
},
"actions": {
@@ -403,6 +418,7 @@
},
"errors": {
"noNodesSelected": "<strong>无法创建子流程</strong>: 未选择节点",
"acrossMultipleGroups": "无法跨多个组创建子流",
"multipleInputsToSelection": "<strong>无法创建子流程</strong>: 多个输入到了选择"
}
},
@@ -491,12 +507,14 @@
"unassigned": "未分配",
"global": "全局",
"workspace": "工作区",
"editor": "编辑对话框",
"selectAll": "选择所有节点",
"selectNone": "取消所有选择",
"selectAllConnected": "选择所有连接的节点",
"addRemoveNode": "从选择中添加/删除节点",
"editSelected": "编辑选定节点",
"deleteSelected": "删除选定节点或链接",
"deleteReconnect": "删除并重新连接",
"importNode": "导入节点",
"exportNode": "导出节点",
"nudgeNode": "移动所选节点(1px)",
@@ -571,6 +589,7 @@
"editor": {
"title": "面板管理",
"palette": "控制板",
"allCatalogs": "所有目录",
"times": {
"seconds": "秒前",
"minutes": "分前",
@@ -610,6 +629,7 @@
"tab-nodes": "节点",
"tab-install": "安装",
"sort": "排序:",
"sortRelevance": "关联",
"sortAZ": "a-z顺序",
"sortRecent": "日期顺序",
"more": "增加 __count__ 个",
@@ -683,7 +703,11 @@
"empty": "空的",
"globalConfig": "全局配置节点",
"triggerAction": "触发动作",
"find": "在工作区中查找"
"find": "在工作区中查找",
"copyItemUrl": "复制地址",
"copyURL2Clipboard": "复制地址到剪贴板",
"showFlow": "显示流程",
"hideFlow": "隐藏流程"
},
"help": {
"name": "帮助",
@@ -984,7 +1008,10 @@
"quote": "引用",
"link": "链接",
"horizontal-rule": "水平线",
"toggle-preview": "切换预览"
"toggle-preview": "切换预览",
"mermaid": {
"summary": "美人鱼图"
}
},
"bufferEditor": {
"title": "Buffer 编辑器",
@@ -1147,17 +1174,6 @@
"create": "创建分支",
"current": "当前的"
},
"languages": {
"de": "德语",
"en-US": "英文",
"fr": "法语",
"ja": "日语",
"ko": "韩文",
"pt-BR":"葡萄牙语",
"ru":"俄語",
"zh-CN": "简体中文",
"zh-TW": "繁体中文"
},
"create-default-file-set": {
"no-active": "没有活动项目就无法创建默认文件集",
"no-empty": "无法在非空项目上创建默认文件集",
@@ -1187,21 +1203,11 @@
"diagnostics": {
"title": "系统信息"
},
"languages": {
"de": "德语-Deutsch",
"en-US": "英文-English",
"ja": "日语-日本",
"ko": "韩文-한국인",
"ru": "俄语-Русский",
"zh-CN": "简体中文",
"zh-TW": "繁體中文"
},
"validator": {
"errors": {
"invalid-json": "无效的 JSON 数据: __error__",
"invalid-json-prop": "__prop__: 无效的 JSON 数据: __error__",
"invalid-expr": "无效的 JSONata 表达式: __error__",
"invalid-prop": "无效的属性表达式",
"invalid-prop-prop": "__prop__: 无效的属性表达式",
"invalid-num": "无效的数字",
"invalid-num-prop": "__prop__: 无效的数字",
"invalid-regexp": "输入格式无效",
@@ -1213,9 +1219,15 @@
}
},
"contextMenu": {
"showActionList":"显示动作列表",
"insert": "插入",
"node": "节点",
"junction": "连接点",
"linkNodes": "链接节点"
},
"env-var": {
"environment": "环境配置",
"header": "全局环境变量",
"revert": "重置"
}
}

View File

@@ -270,5 +270,9 @@
"$moment": {
"args": "[str]",
"desc": "使用Moment库获取日期对象。"
},
"$clone": {
"args": "value",
"desc": "安全克隆对象."
}
}

View File

@@ -23,7 +23,11 @@
"position": "位置",
"enable": "啟用",
"disable": "禁用",
"upload": "上傳"
"upload": "上傳",
"lock": "鎖定",
"unlock": "解鎖",
"locked": "鎖定",
"unlocked": "解鎖"
},
"type": {
"string": "字符串",
@@ -38,11 +42,14 @@
}
},
"event": {
"loadPlugins": "加載插件",
"loadPalette": "加載控制板",
"loadNodeCatalogs": "加載節點目錄",
"loadNodes": "加載 __count__ 個節點",
"loadFlows": "加載流程",
"importFlows": "往工作區中加載流程"
"importFlows": "往工作區中加載流程",
"importError": "<p>加載流程錯誤</p><p>__message__</p>",
"loadingProject": "加載項目"
},
"workspace": {
"defaultName": "流程__number__",
@@ -51,18 +58,35 @@
"delete": "確定想要刪除 '__label__'?",
"dropFlowHere": "把流程放到這裡",
"addFlow": "新增流程",
"listFlows": "流程列表",
"addFlowToRight": "在右側新增流程",
"hideFlow": "隱藏流程",
"hideOtherFlows": "隱藏其它流程",
"showAllFlows": "顯示所有流程",
"hideAllFlows": "隱藏所有流程",
"hiddenFlows": "列出 __count__ 個隱藏流程",
"hiddenFlows_plural": "列出 __count__ 個隱藏流程",
"showLastHiddenFlow": "顯示最後一個隱藏流程",
" ": "流程列表",
"listSubflows": "列出子流程",
"status": "狀態",
"enabled": "有效",
"disabled": "無效",
"info": "詳細描述",
"selectNodes": "點擊節點用於選擇"
"selectNodes": "點擊節點用於選擇",
"enableFlow": "啟用流程",
"disableFlow": "禁用流程",
"lockFlow": "鎖定流程",
"unlockFlow": "解除鎖定",
"moveToStart": "移動到起始",
"moveToEnd": "移動到末尾"
},
"menu": {
"label": {
"view": {
"view": "顯示",
"grid": "格線",
"storeZoom": "加載時還原縮放尺寸",
"storePosition": "加載時還原滾動位置",
"showGrid": "顯示格線",
"snapGrid": "對齊格線",
"gridSize": "格線尺寸",
@@ -80,12 +104,14 @@
"palette": {
"show": "顯示控制板"
},
"edit": "編輯",
"settings": "設置",
"userSettings": "使用者設置",
"nodes": "節點",
"displayStatus": "顯示節點狀態",
"displayConfig": "修改節點配置",
"import": "匯入",
"importExample": "導入示例流程",
"export": "匯出",
"search": "搜尋流程",
"searchInput": "搜尋流程",
@@ -94,7 +120,6 @@
"selectionToSubflow": "將選擇部分更改為子流程",
"flows": "流程",
"add": "增加",
"rename": "重新命名",
"delete": "刪除",
"keyboardShortcuts": "鍵盤快速鍵",
"login": "登入",
@@ -102,24 +127,48 @@
"editPalette": "節點管理",
"other": "其他",
"showTips": "顯示小提示",
"help": "Node-RED website",
"showWelcomeTours": "顯示新版本向導",
"help": "Node-RED 文檔主頁",
"projects": "專案",
"projects-new": "新專案",
"projects-open": "開啟專案",
"projects-settings": "專案設定",
"showNodeLabelDefault": "顯示新添加節點的標籤",
"codeEditor": "代碼編輯器",
"groups": "組",
"groupSelection": "選擇組",
"ungroupSelection": "取消選擇組",
"groupMergeSelection": "合并選擇",
"groupRemoveSelection": "從組中移除"
"groupRemoveSelection": "從組中移除",
"arrange": "布局",
"alignLeft": "左對齊",
"alignCenter": "居中對齊",
"alignRight": "右對齊",
"alignTop": "頂部對齊",
"alignMiddle": "垂直居中對齊",
"alignBottom": "底部對齊",
"distributeHorizontally": "横向分布",
"distributeVertically": "垂直分布",
"moveToBack": "置於底層",
"moveToFront": "置於頂層",
"moveBackwards": "向後移動",
"moveForwards": "向前移動",
"showNodeHelp":"顯示節點幫助",
"enableSelectedNodes":"啟用當前選中節點",
"disableSelectedNodes":"禁用當前選中節點",
"showSelectedNodeLabels":"顯示選中的節點標簽",
"hideSelectedNodeLabels":"隱藏選中的節點標簽"
}
},
"actions": {
"toggle-navigator": "切換導航器",
"zoom-out": "縮小",
"zoom-reset": "重置縮放",
"zoom-in": "放大"
"zoom-in": "放大",
"search-flows": "搜索流程",
"search-prev": "上一個",
"search-next": "下一個",
"search-counter": "\"__term__\" __result__ of __count__"
},
"user": {
"loggedInAs": "作為 __name__ 登入",
@@ -135,12 +184,17 @@
}
},
"notification": {
"state": {
"flowsStopped": "流程已停止",
"flowsStarted": "流程已啟動"
},
"warning": "<strong>警告</strong>: __message__",
"warnings": {
"undeployedChanges": "節點中存在未部署的更改",
"nodeActionDisabled": "節點動作在子流程中被禁用",
"nodeActionDisabledSubflow": "子流程中禁用了節點操作",
"missing-types": "流程由於缺少節點類型而停止。請檢查日誌的詳細資訊",
"missing-modules": "<p>流程因缺少模塊而停止。</p>",
"safe-mode": "<p>流程在安全模式下停止。</p><p>您可以修改流程並部署更改以重新啟動。</p>",
"restartRequired": "Node-RED必須重新啟動以啟用升級的模組",
"credentials_load_failed": "<p>流程由於無法解密證書而停止。</p> <p>流程證書文件已加密,但是項目的加密密鑰丟失或無效。</p>",
@@ -151,7 +205,7 @@
"project_not_found": "<p>找不到項目的'__project__'</p>",
"git_merge_conflict": "<p>自動合併更改失敗。</p><p>修復未合併的衝突,然後提交結果。</p>"
},
"error": "<strong>Error</strong>: __message__",
"error": "<strong>錯誤</strong>: __message__",
"errors": {
"lostConnection": "丟失與伺服器的連接,重新連接...",
"lostConnectionReconnect": "丟失與伺服器的連接__time__ 秒後重新連接",
@@ -208,6 +262,8 @@
"download": "下載",
"importUnrecognised": "匯入了無法識別的類型:",
"importUnrecognised_plural": "匯入了無法識別的類型:",
"importDuplicate": "導入了重復節點:",
"importDuplicate_plural": "導入了重復節點:",
"nodesExported": "節點匯出到了剪貼簿",
"nodesImported": "已匯入:",
"nodeCopied": "已複製 __count__ 個節點",
@@ -259,6 +315,10 @@
"modifiedFlowsDesc": "只部署包含已更改節點的流程",
"modifiedNodes": "已更改的節點",
"modifiedNodesDesc": "只部署已經更改的節點",
"startFlows": "啟動",
"startFlowsDesc": "啟動流程",
"stopFlows": "停止",
"stopFlowsDesc": "停止流程",
"restartFlows": "重新啟動流程",
"restartFlowsDesc": "重新啟動當前部署的流程",
"successfulDeploy": "部署成功",
@@ -337,14 +397,28 @@
"output": "輸出:",
"status": "狀態節點",
"deleteSubflow": "刪除子流程",
"confirmDelete": "您確定要刪除此子流程?",
"info": "詳細描述",
"category": "類別",
"module": "模塊",
"license": "許可",
"licenseNone": "無",
"licenseOther": "其它",
"type": "節點類型",
"version": "版本",
"versionPlaceholder": "x.y.z",
"keys": "關鍵字",
"keysPlaceholder": "使用英文逗號分隔關鍵字",
"author": "作者",
"authorPlaceholder": "名字 <email@example.com>",
"desc": "描述",
"env": {
"restore": "恢復為默認子流程",
"remove": "類別刪除環境變量"
},
"errors": {
"noNodesSelected": "<strong>無法創建子流程</strong>: 未選擇節點",
"acrossMultipleGroups": "無法跨多個組創建子流",
"multipleInputsToSelection": "<strong>無法創建子流程</strong>: 多個輸入到了選擇"
}
},
@@ -367,12 +441,12 @@
"editConfig": "編輯 __type__ 配置",
"addNewType": "添加新的 __type__ 節點",
"nodeProperties": "節點屬性",
"label": "Label",
"label": "標簽",
"color": "顏色",
"portLabels": "埠標籤",
"labelInputs": "輸入",
"labelOutputs": "輸出",
"settingIcon": "Icon",
"settingIcon": "圖標",
"default": "默認",
"noDefaultLabel": "無",
"defaultLabel": "使用默認標籤",
@@ -385,6 +459,7 @@
"icon": "圖標",
"inputType": "輸入類型",
"selectType": "選擇類型...",
"loadCredentials": "加載節點憑證",
"inputs": {
"input": "輸入",
"select": "選擇",
@@ -419,7 +494,8 @@
},
"errors": {
"scopeChange": "更改範圍將使其他流程中的節點無法使用",
"invalidProperties": "無效的屬性:"
"invalidProperties": "無效的屬性:",
"credentialLoadFailed": "無法加載節點憑據"
}
},
"keyboard": {
@@ -431,11 +507,14 @@
"unassigned": "未分配",
"global": "全局",
"workspace": "工作區",
"editor": "編輯對話框",
"selectAll": "選擇所有節點",
"selectNone": "取消所有選擇",
"selectAllConnected": "選擇所有連接的節點",
"addRemoveNode": "從選擇中添加/刪除節點",
"editSelected": "編輯選定節點",
"deleteSelected": "刪除選定節點或連結",
"deleteReconnect": "刪除並重新連接",
"importNode": "匯入節點",
"exportNode": "匯出節點",
"nudgeNode": "移動所選節點(1px)",
@@ -445,10 +524,14 @@
"copyNode": "複製所選節點",
"cutNode": "剪切所選節點",
"pasteNode": "粘貼節點",
"copyGroupStyle": "復製組樣式",
"pasteGroupStyle": "粘貼組樣式",
"undoChange": "撤銷上次執行的更改",
"redoChange": "重做",
"searchBox": "打開搜尋框",
"managePalette": "管理面板",
"actionList": "動作列表"
"actionList": "動作列表",
"splitWireWithLinks": "使用Link節點拆分已選項"
},
"library": {
"library": "庫",
@@ -466,12 +549,11 @@
"types": {
"local": "本地",
"examples": "例子"
},
"exportToLibrary": "將節點匯出到庫"
}
},
"palette": {
"noInfo": "無可用資訊",
"filter": "過濾節點",
"filter": "過濾已安裝模組",
"search": "搜尋模組",
"addCategory": "添加新的...",
"label": {
@@ -501,11 +583,13 @@
"nodeEnabled_plural": "啟用多個節點:",
"nodeDisabled": "禁用節點:",
"nodeDisabled_plural": "禁用多個節點:",
"nodeUpgraded": "節點模組__module__升級到__version__版本"
"nodeUpgraded": "節點模組__module__升級到__version__版本",
"unknownNodeRegistered": "加載節點錯誤: <ul><li>__type__<br>__error__</li></ul>"
},
"editor": {
"title": "面板管理",
"palette": "Palette",
"palette": "控製板",
"allCatalogs": "所有目錄",
"times": {
"seconds": "秒前",
"minutes": "分前",
@@ -545,10 +629,12 @@
"tab-nodes": "節點",
"tab-install": "安裝",
"sort": "排序:",
"sortRelevance": "關聯",
"sortAZ": "a-z順序",
"sortRecent": "日期順序",
"more": "增加 __count__ 個",
"upload": "上傳模塊tgz文件",
"refresh": "更新模塊列表",
"errors": {
"catalogLoadFailed": "無法載入節點目錄。<br>查看瀏覽器控制臺瞭解更多資訊",
"installFailed": "無法安裝: __module__<br>__message__<br>查看日誌瞭解更多資訊",
@@ -617,7 +703,11 @@
"empty": "空的",
"globalConfig": "全局配置節點",
"triggerAction": "觸發動作",
"find": "在工作區中查找"
"find": "在工作區中查找",
"copyItemUrl": "復製地址",
"copyURL2Clipboard": "復製地址到剪貼板",
"showFlow": "顯示流程",
"hideFlow": "隱藏流程"
},
"help": {
"name": "幫助",
@@ -627,7 +717,8 @@
"showHelp": "顯示幫助",
"showInOutline": "在大綱中顯示",
"showTopics": "顯示主題",
"noHelp": "未選擇幫助主題"
"noHelp": "未選擇幫助主題",
"changeLog": "更新日誌"
},
"config": {
"name": "配置節點",
@@ -828,31 +919,37 @@
"json": "JSON",
"bin": "二進位流",
"date": "時間戳記",
"jsonata": "expression",
"env": "env variable",
"jsonata": "表達式",
"env": "環境變量",
"cred": "證書"
}
},
"editableList": {
"add": "添加"
"add": "添加",
"addTitle": "添加項"
},
"search": {
"empty": "找不到匹配",
"history": "搜索歷史",
"clear": "清除所有",
"empty": "找不到匹配項",
"addNode": "添加一個節點...",
"options": {
"configNodes": "配置節點",
"unusedConfigNodes": "未使用的配置節點",
"invalidNodes": "無效的節點",
"uknownNodes": "未知的節點",
"unusedSubflows": "未使用的子流程"
"unusedSubflows": "未使用的子流程",
"hiddenFlows": "隱藏的流程",
"modifiedNodes": "已修改的節點或流程",
"thisFlow": "當前流程"
}
},
"expressionEditor": {
"functions": "功能",
"functionReference": "Function reference",
"functionReference": "功能參考",
"insert": "插入",
"title": "JSONata運算式編輯器",
"test": "Test",
"test": "測試",
"data": "示例消息",
"result": "結果",
"format": "格式表達方法",
@@ -863,20 +960,28 @@
"invalid-expr": "無效的JSONata運算式:\n __message__",
"invalid-msg": "無效的示例JSON消息:\n __message__",
"context-unsupported": "無法測試上下文函數\n $flowContext 或 $globalContext",
"env-unsupported": "無法測試 $env 函數",
"moment-unsupported": "無法測試 $moment 函數",
"clone-unsupported": "無法測試 $clone 函數",
"eval": "評估運算式錯誤:\n __message__"
}
},
"monaco": {
"setTheme": "設置主題"
},
"jsEditor": {
"title": "JavaScript 編輯器"
},
"textEditor": {
"title": "Text 編輯器"
"title": "文本編輯器"
},
"jsonEditor": {
"title": "JSON編輯器",
"format": "格式化JSON",
"rawMode": "編輯 JSON",
"uiMode": "Visual編輯器",
"uiMode": "可視化編輯器",
"rawMode-readonly": "原始JSON",
"uiMode-readonly": "可視化",
"insertAbove": "在上方插入",
"insertBelow": "在下方插入",
"addItem": "添加項目",
@@ -892,9 +997,9 @@
"title": "Markdown 編輯器",
"expand": "展開",
"format": "F使用markdown格式化",
"heading1": "Heading 1",
"heading2": "Heading 2",
"heading3": "Heading 3",
"heading1": "標題 1",
"heading2": "標題 2",
"heading3": "標題 3",
"bold": "粗體",
"italic": "斜體",
"code": "程式碼",
@@ -903,7 +1008,10 @@
"quote": "引用",
"link": "連結",
"horizontal-rule": "分隔線",
"toggle-preview": "預覽"
"toggle-preview": "切換預覽",
"mermaid": {
"summary": "美人魚圖"
}
},
"bufferEditor": {
"title": "緩衝區編輯器",
@@ -1038,7 +1146,8 @@
"not-git": "不是git倉庫",
"no-resource": "找不到存儲庫",
"cant-get-ssh-key-path": "錯誤! 無法獲取所選的SSH密鑰路徑。",
"unexpected_error": "意外的錯誤"
"unexpected_error": "意外的錯誤",
"clearContext": "更改項目時清除上下文"
},
"delete": {
"confirm": "您確定要刪除此項目嗎?"
@@ -1068,7 +1177,7 @@
"create-default-file-set": {
"no-active": "沒有活動項目就無法創建默認文件集",
"no-empty": "無法在非空項目上創建默認文件集",
"git-error": "git error"
"git-error": "git錯誤"
},
"errors": {
"no-username-email": "您的Git客戶端未配置用戶名/電子郵件。",
@@ -1079,21 +1188,45 @@
"editor-tab": {
"properties": "屬性",
"envProperties": "環境變量",
"module": "模塊屬性",
"description": "描述",
"appearance": "外觀",
"preview": "UI預覽",
"defaultValue": "默認值",
"env": "環境變量"
"defaultValue": "默認值"
},
"languages": {
"de": "德語",
"en-US": "英語",
"fr": "法語",
"ja": "日語",
"ko": "韓語",
"pt-BR":"葡萄牙语",
"ru":"俄語",
"zh-CN": "簡體中文",
"zh-TW": "繁體中文"
"tourGuide": {
"takeATour": "查看更新內容",
"start": "開始",
"next": "下一個",
"welcomeTours": "歡迎使用 Node-RED"
},
"diagnostics": {
"title": "系统信息"
},
"validator": {
"errors": {
"invalid-json": "無效的 JSON 數據: __error__",
"invalid-expr": "無效的 JSONata 表達式: __error__",
"invalid-prop": "無效的屬性表達式",
"invalid-num": "無效的數字",
"invalid-regexp": "輸入格式無效",
"invalid-regex-prop": "__prop__: 輸入格式無效",
"missing-required-prop": "__prop__: 缺少屬性值",
"invalid-config": "__prop__: 無效的配置節點",
"missing-config": "__prop__: 缺少配置節點",
"validation-error": "__prop__: 驗證錯誤: __node__, __id__: __error__"
}
},
"contextMenu": {
"showActionList":"顯示動作列表",
"insert": "插入",
"node": "節點",
"junction": "連接點",
"linkNodes": "鏈接節點"
},
"env-var": {
"environment": "環境配置",
"header": "全局環境變量",
"revert": "重置"
}
}

View File

@@ -270,5 +270,9 @@
"$moment": {
"args": "[str]",
"desc": "使用Moment庫獲取日期對象。"
},
"$clone": {
"args": "value",
"desc": "安全克隆對象."
}
}

View File

@@ -1,6 +1,6 @@
{
"name": "@node-red/editor-client",
"version": "3.1.0-beta.4",
"version": "3.1.6",
"license": "Apache-2.0",
"repository": {
"type": "git",

View File

@@ -39,15 +39,16 @@
console.warn(evt,args);
}
if (handlers[evt]) {
for (var i=0;i<handlers[evt].length;i++) {
let cpyHandlers = [...handlers[evt]];
for (var i=0;i<cpyHandlers.length;i++) {
try {
handlers[evt][i].apply(null, args);
cpyHandlers[i].apply(null, args);
} catch(err) {
console.warn("RED.events.emit error: ["+evt+"] "+(err.toString()));
console.warn(err);
}
}
}
}
return {

View File

@@ -797,8 +797,8 @@ RED.nodes = (function() {
if (node && node._def.onremove) {
// Deprecated: never documented but used by some early nodes
console.log("Deprecated API warning: node type ",node.type," has an onremove function - should be oneditremove - please report");
node._def.onremove.call(n);
console.log("Deprecated API warning: node type ",node.type," has an onremove function - should be oneditdelete - please report");
node._def.onremove.call(node);
}
return {links:removedLinks,nodes:removedNodes};
}
@@ -1228,7 +1228,6 @@ RED.nodes = (function() {
}
}
} else if (n.credentials) {
node.credentials = {};
// All other nodes have a well-defined list of possible credentials
for (var cred in n._def.credentials) {
if (n._def.credentials.hasOwnProperty(cred)) {
@@ -2198,6 +2197,12 @@ RED.nodes = (function() {
}
node._config.x = node.x;
node._config.y = node.y;
if (n.hasOwnProperty('w')) {
node.w = n.w
}
if (n.hasOwnProperty('h')) {
node.h = n.h
}
} else if (n.type.substring(0,7) === "subflow") {
var parentId = n.type.split(":")[1];
var subflow = subflow_denylist[parentId]||subflow_map[parentId]||getSubflow(parentId);
@@ -2211,7 +2216,7 @@ RED.nodes = (function() {
set: registry.getNodeSet("node-red/unknown")
}
} else {
if (createNewIds || options.importMap[n.id] === "copy") {
if (subflow_denylist[parentId] || createNewIds || options.importMap[n.id] === "copy") {
parentId = subflow.id;
node.type = "subflow:"+parentId;
node._def = registry.getNodeType(node.type);

View File

@@ -498,6 +498,15 @@ var RED = (function() {
]
}
}
} else if (notificationId === 'restart-required') {
options.buttons = [
{
text: RED._("common.label.close"),
click: function() {
persistentNotifications[notificationId].hideNotification();
}
}
]
}
if (!persistentNotifications.hasOwnProperty(notificationId)) {
persistentNotifications[notificationId] = RED.notify(text,options);
@@ -525,6 +534,10 @@ var RED = (function() {
RED.view.redrawStatus(node);
}
});
let pendingNodeRemovedNotifications = []
let pendingNodeRemovedTimeout
RED.comms.subscribe("notification/node/#",function(topic,msg) {
var i,m;
var typeList;
@@ -562,8 +575,15 @@ var RED = (function() {
m = msg[i];
info = RED.nodes.removeNodeSet(m.id);
if (info.added) {
typeList = "<ul><li>"+m.types.map(RED.utils.sanitize).join("</li><li>")+"</li></ul>";
RED.notify(RED._("palette.event.nodeRemoved", {count:m.types.length})+typeList,"success");
pendingNodeRemovedNotifications = pendingNodeRemovedNotifications.concat(m.types.map(RED.utils.sanitize))
if (pendingNodeRemovedTimeout) {
clearTimeout(pendingNodeRemovedTimeout)
}
pendingNodeRemovedTimeout = setTimeout(function () {
typeList = "<ul><li>"+pendingNodeRemovedNotifications.join("</li><li>")+"</li></ul>";
RED.notify(RED._("palette.event.nodeRemoved", {count:pendingNodeRemovedNotifications.length})+typeList,"success");
pendingNodeRemovedNotifications = []
}, 200)
}
}
loadIconList();
@@ -702,7 +722,7 @@ var RED = (function() {
menuOptions.push({id:"menu-item-config-nodes",label:RED._("menu.label.displayConfig"),onselect:"core:show-config-tab"});
menuOptions.push({id:"menu-item-workspace",label:RED._("menu.label.flows"),options:[
{id:"menu-item-workspace-add",label:RED._("menu.label.add"),onselect:"core:add-flow"},
{id:"menu-item-workspace-edit",label:RED._("menu.label.rename"),onselect:"core:edit-flow"},
{id:"menu-item-workspace-edit",label:RED._("menu.label.edit"),onselect:"core:edit-flow"},
{id:"menu-item-workspace-delete",label:RED._("menu.label.delete"),onselect:"core:remove-flow"}
]});
menuOptions.push({id:"menu-item-subflow",label:RED._("menu.label.subflows"), options: [
@@ -731,7 +751,7 @@ var RED = (function() {
}
menuOptions.push({id:"menu-item-help",
label: RED.settings.theme("menu.menu-item-help.label",RED._("menu.label.help")),
href: RED.settings.theme("menu.menu-item-help.url","http://nodered.org/docs")
href: RED.settings.theme("menu.menu-item-help.url","https://nodered.org/docs")
});
menuOptions.push({id:"menu-item-node-red-version", label:"v"+RED.settings.version, onselect: "core:show-about" });

View File

@@ -819,7 +819,7 @@ RED.clipboard = (function() {
flow.forEach(function(node) {
if (node.type === "tab") {
flows[node.id] = {
element: getFlowLabel(node,false),
element: getFlowLabel(node),
deferBuild: type !== "flow",
expanded: type === "flow",
children: []
@@ -1000,7 +1000,6 @@ RED.clipboard = (function() {
try {
RED.view.importNodes(newNodes, importOptions);
} catch(error) {
console.log(error.importConfig)
// Thrown for import_conflict
confirmImport(error.importConfig, newNodes, importOptions);
}
@@ -1170,9 +1169,9 @@ RED.clipboard = (function() {
function getNodeElement(n, isConflicted, isSelected, parent) {
var element;
if (n.type === "tab") {
element = getFlowLabel(n, isSelected);
element = getFlowLabel(n, isConflicted);
} else {
element = getNodeLabel(n, isConflicted, isSelected);
element = getNodeLabel(n, isConflicted, isSelected, parent);
}
var controls = $('<div>',{class:"red-ui-clipboard-dialog-import-conflicts-controls"}).appendTo(element);
controls.on("click", function(evt) { evt.stopPropagation(); });
@@ -1222,14 +1221,14 @@ RED.clipboard = (function() {
}
}
function getFlowLabel(n) {
function getFlowLabel(n, isConflicted) {
n = JSON.parse(JSON.stringify(n));
n._def = RED.nodes.getType(n.type) || {};
if (n._def) {
n._ = n._def._;
}
var div = $('<div>',{class:"red-ui-info-outline-item red-ui-info-outline-item-flow"});
var div = $('<div>',{class:"red-ui-info-outline-item red-ui-info-outline-item-flow red-ui-node-list-item"});
var contentDiv = $('<div>',{class:"red-ui-search-result-description red-ui-info-outline-item-label"}).appendTo(div);
var label = (typeof n === "string")? n : n.label;
var newlineIndex = label.indexOf("\\n");
@@ -1237,11 +1236,17 @@ RED.clipboard = (function() {
label = label.substring(0,newlineIndex)+"...";
}
contentDiv.text(label);
if (!!isConflicted) {
const conflictIcon = $('<span style="padding: 0 10px;"><i class="fa fa-exclamation-circle"></span>').appendTo(div)
RED.popover.tooltip(conflictIcon, RED._('clipboard.import.alreadyExists'))
}
// A conflicted flow should not be imported by default.
return div;
}
function getNodeLabel(n, isConflicted) {
function getNodeLabel(n, isConflicted, isSelected, parent) {
n = JSON.parse(JSON.stringify(n));
n._def = RED.nodes.getType(n.type) || {};
if (n._def) {
@@ -1249,6 +1254,11 @@ RED.clipboard = (function() {
}
var div = $('<div>',{class:"red-ui-node-list-item"});
RED.utils.createNodeIcon(n,true).appendTo(div);
if (!parent && !!isConflicted) {
const conflictIcon = $('<span style="padding: 0 10px;"><i class="fa fa-exclamation-circle"></span>').appendTo(div)
RED.popover.tooltip(conflictIcon, RED._('clipboard.import.alreadyExists'))
}
return div;
}

View File

@@ -182,7 +182,9 @@
valueLabel: contextLabel
},
str: {value:"str",label:"string",icon:"red/images/typedInput/az.svg"},
num: {value:"num",label:"number",icon:"red/images/typedInput/09.svg",validate:/^[+-]?[0-9]*\.?[0-9]*([eE][-+]?[0-9]+)?$/},
num: {value:"num",label:"number",icon:"red/images/typedInput/09.svg",validate: function(v) {
return (true === RED.utils.validateTypedProperty(v, "num"));
} },
bool: {value:"bool",label:"boolean",icon:"red/images/typedInput/bool.svg",options:["true","false"]},
json: {
value:"json",

View File

@@ -30,8 +30,26 @@ RED.contextMenu = (function () {
const isGroup = hasSelection && selection.nodes.length === 1 && selection.nodes[0].type === 'group'
const canEdit = !RED.workspaces.isLocked()
const canRemoveFromGroup = hasSelection && !!selection.nodes[0].g
const isAllGroups = hasSelection && selection.nodes.filter(n => n.type !== 'group').length === 0
const hasGroup = hasSelection && selection.nodes.filter(n => n.type === 'group' ).length > 0
let hasGroup, isAllGroups = true, hasDisabledNode, hasEnabledNode, hasLabeledNode, hasUnlabeledNode;
if (hasSelection) {
selection.nodes.forEach(n => {
if (n.type === 'group') {
hasGroup = true;
} else {
isAllGroups = false;
}
if (n.d) {
hasDisabledNode = true;
} else {
hasEnabledNode = true;
}
if (n.l === undefined || n.l) {
hasLabeledNode = true;
} else {
hasUnlabeledNode = true;
}
});
}
const offset = $("#red-ui-workspace-chart").offset()
let addX = options.x - offset.left + $("#red-ui-workspace-chart").scrollLeft()
@@ -44,7 +62,7 @@ RED.contextMenu = (function () {
}
menuItems.push(
{ onselect: 'core:show-action-list', onpostselect: function () { } }
{ onselect: 'core:show-action-list', label: RED._("contextMenu.showActionList"), onpostselect: function () { } }
)
const insertOptions = []
@@ -55,7 +73,7 @@ RED.contextMenu = (function () {
onselect: function () {
RED.view.showQuickAddDialog({
position: [addX, addY],
touchTrigger: true,
touchTrigger: 'ontouchstart' in window,
splice: isSingleLink ? selection.links[0] : undefined,
// spliceMultiple: isMultipleLinks
})
@@ -108,16 +126,16 @@ RED.contextMenu = (function () {
const nodeOptions = []
if (!hasMultipleSelection && !isGroup) {
nodeOptions.push(
{ onselect: 'core:show-node-help' },
{ onselect: 'core:show-node-help', label: RED._('menu.label.showNodeHelp') },
null
)
}
nodeOptions.push(
{ onselect: 'core:enable-selected-nodes' },
{ onselect: 'core:disable-selected-nodes' },
{ onselect: 'core:enable-selected-nodes', label: RED._('menu.label.enableSelectedNodes'), disabled: !hasDisabledNode },
{ onselect: 'core:disable-selected-nodes', label: RED._('menu.label.disableSelectedNodes'), disabled: !hasEnabledNode },
null,
{ onselect: 'core:show-selected-node-labels' },
{ onselect: 'core:hide-selected-node-labels' }
{ onselect: 'core:show-selected-node-labels', label: RED._('menu.label.showSelectedNodeLabels'), disabled: !hasUnlabeledNode },
{ onselect: 'core:hide-selected-node-labels', label: RED._('menu.label.hideSelectedNodeLabels'), disabled: !hasLabeledNode }
)
menuItems.push({
label: RED._('sidebar.info.node'),
@@ -126,8 +144,8 @@ RED.contextMenu = (function () {
menuItems.push({
label: RED._('sidebar.info.group'),
options: [
{ onselect: 'core:group-selection' },
{ onselect: 'core:ungroup-selection', disabled: !hasGroup },
{ onselect: 'core:group-selection', label: RED._("menu.label.groupSelection") },
{ onselect: 'core:ungroup-selection', label: RED._("menu.label.ungroupSelection"), disabled: !hasGroup },
]
})
if (hasGroup) {
@@ -143,8 +161,8 @@ RED.contextMenu = (function () {
}
menuItems[menuItems.length - 1].options.push(
null,
{ onselect: 'core:copy-group-style', disabled: !hasGroup },
{ onselect: 'core:paste-group-style', disabled: !hasGroup}
{ onselect: 'core:copy-group-style', label: RED._("keyboard.copyGroupStyle"), disabled: !hasGroup },
{ onselect: 'core:paste-group-style', label: RED._("keyboard.pasteGroupStyle"), disabled: !hasGroup}
)
}
if (canEdit && hasMultipleSelection) {
@@ -168,16 +186,16 @@ RED.contextMenu = (function () {
menuItems.push(
null,
{ onselect: 'core:undo', disabled: RED.history.list().length === 0 },
{ onselect: 'core:redo', disabled: RED.history.listRedo().length === 0 },
{ onselect: 'core:undo', label: RED._("keyboard.undoChange"), disabled: RED.history.list().length === 0 },
{ onselect: 'core:redo', label: RED._("keyboard.redoChange"), disabled: RED.history.listRedo().length === 0 },
null,
{ onselect: 'core:cut-selection-to-internal-clipboard', label: RED._("keyboard.cutNode"), disabled: !canEdit || !hasSelection },
{ onselect: 'core:copy-selection-to-internal-clipboard', label: RED._("keyboard.copyNode"), disabled: !hasSelection },
{ onselect: 'core:paste-from-internal-clipboard', label: RED._("keyboard.pasteNode"), disabled: !canEdit || !RED.view.clipboard() },
{ onselect: 'core:delete-selection', disabled: !canEdit || !canDelete },
{ onselect: 'core:delete-selection', label: RED._('keyboard.deleteSelected'), disabled: !canEdit || !canDelete },
{ onselect: 'core:delete-selection-and-reconnect', label: RED._('keyboard.deleteReconnect'), disabled: !canEdit || !canDelete },
{ onselect: 'core:show-export-dialog', label: RED._("menu.label.export") },
{ onselect: 'core:select-all-nodes' },
{ onselect: 'core:select-all-nodes', label: RED._("keyboard.selectAll") },
)
}

View File

@@ -989,9 +989,10 @@ RED.diff = (function() {
}
if (localNode && remoteNode && typeof localNode[d] === "string") {
if (/\n/.test(localNode[d]) || /\n/.test(remoteNode[d])) {
$('<button class="red-ui-button red-ui-button-small red-ui-diff-text-diff-button"><i class="fa fa-file-o"> <i class="fa fa-caret-left"></i> <i class="fa fa-caret-right"></i> <i class="fa fa-file-o"></i></button>').on("click", function() {
var textDiff = $('<button class="red-ui-button red-ui-button-small red-ui-diff-text-diff-button"><i class="fa fa-file-o"> <i class="fa fa-caret-left"></i> <i class="fa fa-caret-right"></i> <i class="fa fa-file-o"></i></button>').on("click", function() {
showTextDiff(localNode[d],remoteNode[d]);
}).appendTo(propertyNameCell);
RED.popover.tooltip(textDiff, RED._("diff.compareChanges"));
}
}

View File

@@ -115,8 +115,9 @@ RED.editor = (function() {
var valid = validateNodeProperty(node, definition, prop, properties[prop]);
if ((typeof valid) === "string") {
result.push(valid);
}
else if(!valid) {
} else if (Array.isArray(valid)) {
result = result.concat(valid)
} else if(!valid) {
result.push(prop);
}
}
@@ -165,7 +166,7 @@ RED.editor = (function() {
// If the validator takes two arguments, it is a 3.x validator that
// can return a String to mean 'invalid' and provide a reason
if ((definition[property].validate.length === 2) &&
((typeof valid) === "string")) {
((typeof valid) === "string") || Array.isArray(valid)) {
return valid;
} else {
// Otherwise, a 2.x returns a truth-like/false-like value that
@@ -181,6 +182,17 @@ RED.editor = (function() {
error: err.message
});
}
} else if (valid) {
// If the validator is not provided in node property => Check if the input has a validator
if ("category" in node._def) {
const isConfig = node._def.category === "config";
const prefix = isConfig ? "node-config-input" : "node-input";
const input = $("#"+prefix+"-"+property);
const isTypedInput = input.length > 0 && input.next(".red-ui-typedInput-container").length > 0;
if (isTypedInput) {
valid = input.typedInput("validate");
}
}
}
if (valid && definition[property].type && RED.nodes.getType(definition[property].type) && !("validate" in definition[property])) {
if (!value || value == "_ADD_") {
@@ -1219,7 +1231,11 @@ RED.editor = (function() {
})
if (node_def.hasUsers !== false) {
$('<span><i class="fa fa-info-circle"></i> <span id="red-ui-editor-config-user-count"></span></span>').css("margin-left", "10px").appendTo(trayFooterLeft);
// $('<span><i class="fa fa-info-circle"></i> <span id="red-ui-editor-config-user-count"></span></span>').css("margin-left", "10px").appendTo(trayFooterLeft);
$('<button type="button" class="red-ui-button"><i class="fa fa-user"></i><span id="red-ui-editor-config-user-count"></span></button>').on('click', function() {
RED.sidebar.info.outliner.search('uses:'+editing_config_node.id)
RED.sidebar.info.show()
}).appendTo(trayFooterLeft);
}
trayFooter.append('<span class="red-ui-tray-footer-right"><span id="red-ui-editor-config-scope-warning" data-i18n="[title]editor.errors.scopeChange"><i class="fa fa-warning"></i></span><select id="red-ui-editor-config-scope"></select></span>');
@@ -1277,7 +1293,8 @@ RED.editor = (function() {
});
}
if (node_def.hasUsers !== false) {
$("#red-ui-editor-config-user-count").text(RED._("editor.nodesUse", {count:editing_config_node.users.length})).parent().show();
$("#red-ui-editor-config-user-count").text(editing_config_node.users.length).parent().show();
RED.popover.tooltip($("#red-ui-editor-config-user-count").parent(), function() { return RED._('editor.nodesUse',{count:editing_config_node.users.length})});
}
trayBody.i18n();
trayFooter.i18n();

View File

@@ -121,7 +121,7 @@
var i=0,l=bufferBinValue.length;
var c = 0;
for(i=0;i<l;i++) {
var d = parseInt(bufferBinValue[i]);
var d = parseInt(Number(bufferBinValue[i]));
if (!isString && (isNaN(d) || d < 0 || d > 255)) {
valid = false;
break;

View File

@@ -966,12 +966,10 @@ RED.editor.codeEditor.monaco = (function() {
//Unbind ctrl-Enter (default action is to insert a newline in editor) This permits the shortcut to close the tray.
try {
ed._standaloneKeybindingService.addDynamicKeybinding(
'-editor.action.insertLineAfter', // command ID prefixed by '-'
null, // keybinding
() => {} // need to pass an empty handler
);
} catch (error) { }
monaco.editor.addKeybindingRule({keybinding: 0, command: "-editor.action.insertLineAfter"});
} catch (error) {
console.warn(error)
}
ed.nodered = {
refreshModuleLibs: refreshModuleLibs //expose this for function node externalModules refresh

View File

@@ -169,7 +169,7 @@
var currentScrollTop = $(".red-ui-editor-type-markdown-panel-preview").scrollTop();
$(".red-ui-editor-type-markdown-panel-preview").html(RED.utils.renderMarkdown(expressionEditor.getValue()));
$(".red-ui-editor-type-markdown-panel-preview").scrollTop(currentScrollTop);
mermaid.init();
RED.editor.mermaid.render()
},200);
})
if (options.header) {
@@ -178,7 +178,7 @@
if (value) {
$(".red-ui-editor-type-markdown-panel-preview").html(RED.utils.renderMarkdown(expressionEditor.getValue()));
mermaid.init();
RED.editor.mermaid.render()
}
panels = RED.panels.create({
id:"red-ui-editor-type-markdown-panels",

View File

@@ -0,0 +1,54 @@
RED.editor.mermaid = (function () {
let initializing = false
let loaded = false
let pendingEvals = []
let diagramIds = 0
function render(selector = '.mermaid') {
// $(selector).hide()
if (!loaded) {
pendingEvals.push(selector)
if (!initializing) {
initializing = true
$.getScript(
'vendor/mermaid/mermaid.min.js',
function (data, stat, jqxhr) {
mermaid.initialize({
startOnLoad: false,
theme: RED.settings.get('mermaid', {}).theme
})
loaded = true
while(pendingEvals.length > 0) {
const pending = pendingEvals.shift()
render(pending)
}
}
)
}
} else {
const nodes = document.querySelectorAll(selector)
nodes.forEach(async node => {
if (!node.getAttribute('mermaid-processed')) {
const mermaidContent = node.innerText
node.setAttribute('mermaid-processed', true)
try {
const { svg } = await mermaid.render('mermaid-render-'+Date.now()+'-'+(diagramIds++), mermaidContent);
node.innerHTML = svg
} catch (err) {
$('<div>').css({
fontSize: '0.8em',
border: '1px solid var(--red-ui-border-color-error)',
padding: '5px',
marginBottom: '10px',
}).text(err.toString()).prependTo(node)
}
}
})
}
}
return {
render: render,
};
})();

View File

@@ -196,7 +196,7 @@
}
$('<div class="form-row">'+
'<label for="node-input-show-label-btn" data-i18n="editor.label"></label>'+
'<label for="node-input-show-label" data-i18n="editor.label"></label>'+
'<span style="margin-right: 2px;"/>'+
'<input type="checkbox" id="node-input-show-label"/>'+
'</div>').appendTo(dialogForm);

View File

@@ -71,7 +71,7 @@ RED.envVar = (function() {
};
if (item.name.trim() !== "") {
new_env.push(item);
if ((item.type === "cred") && (item.value !== "__PWRD__")) {
if (item.type === "cred") {
credentials.map[item.name] = item.value;
credentials.map["has_"+item.name] = (item.value !== "");
item.value = "__PWRD__";

View File

@@ -1,46 +0,0 @@
// Mermaid diagram stub library for on-demand dynamic loading
// Will be overwritten after script loading by $.getScript
var mermaid = (function () {
var enabled /* = undefined */;
var initializing = false;
var initCalled = false;
function initialize(opt) {
if (enabled === undefined) {
if (RED.settings.markdownEditor &&
RED.settings.markdownEditor.mermaid) {
enabled = RED.settings.markdownEditor.mermaid.enabled;
}
else {
enabled = true;
}
}
if (enabled) {
initializing = true;
$.getScript("vendor/mermaid/mermaid.min.js",
function (data, stat, jqxhr) {
$(".mermaid").show();
// invoke loaded mermaid API
initializing = false;
mermaid.initialize(opt);
if (initCalled) {
mermaid.init();
initCalled = false;
}
});
}
}
function init() {
if (initializing) {
$(".mermaid").hide();
initCalled = true;
}
}
return {
initialize: initialize,
init: init,
};
})();

View File

@@ -494,6 +494,7 @@ RED.palette.editor = (function() {
// if there is only 1 catalog, hide the select
if (catalogEntries.length > 1) {
catalogSelection.prepend(`<option value="all">${RED._('palette.editor.allCatalogs')}</option>`)
catalogSelection.val('all')
catalogSelection.removeAttr('disabled') // permit the user to select a catalog
}
// refresh the searchInput counter and trigger a change
@@ -523,7 +524,7 @@ RED.palette.editor = (function() {
function refreshFilteredItems() {
packageList.editableList('empty');
var currentFilter = searchInput.searchBox('value').trim();
if (currentFilter === ""){
if (currentFilter === "" && loadedList.length > 20){
packageList.editableList('addItem',{count:loadedList.length})
return;
}
@@ -893,7 +894,7 @@ RED.palette.editor = (function() {
delay: 300,
change: function() {
var searchTerm = $(this).val().trim().toLowerCase();
if (searchTerm.length > 0) {
if (searchTerm.length > 0 || loadedList.length < 20) {
filteredList = loadedList.filter(function(m) {
return (m.index.indexOf(searchTerm) > -1);
}).map(function(f) { return {info:f}});

View File

@@ -484,7 +484,7 @@ RED.palette = (function() {
var currentLabel = paletteNode.attr("data-palette-label");
var currentInfo = paletteNode.attr("data-palette-info");
if (currentLabel !== sf.name || currentInfo !== sf.info) {
if (currentLabel !== sf.name || currentInfo !== sf.info || sf.in.length > 0 || sf.out.length > 0) {
paletteNode.attr("data-palette-info",sf.info);
setLabel(sf.type+":"+sf.id,paletteNode,sf.name,RED.utils.renderMarkdown(sf.info||""));
}

View File

@@ -166,7 +166,7 @@ RED.projects.settings = (function() {
var description = addTargetToExternalLinks($('<span class="red-ui-text-bidi-aware" dir=\"'+RED.text.bidi.resolveBaseTextDir(desc)+'">'+desc+'</span>')).appendTo(container);
description.find(".red-ui-text-bidi-aware").contents().filter(function() { return this.nodeType === 3 && this.textContent.trim() !== "" }).wrap( "<span></span>" );
setTimeout(function () {
mermaid.init();
RED.editor.mermaid.render()
}, 200);
}

View File

@@ -647,9 +647,9 @@ RED.sidebar.versionControl = (function() {
$.getJSON("projects/"+activeProject.name+"/commits/"+entry.sha,function(result) {
result.project = activeProject;
result.parents = entry.parents;
result.oldRev = entry.sha+"~1";
result.oldRev = entry.parents[0].length !== 0 ? entry.sha+"~1" : entry.sha;
result.newRev = entry.sha;
result.oldRevTitle = RED._("sidebar.project.versionControl.commitCapital")+" "+entry.sha.substring(0,7)+"~1";
result.oldRevTitle = entry.parents[0].length !== 0 ? RED._("sidebar.project.versionControl.commitCapital")+" "+entry.sha.substring(0,7)+"~1" : " ";
result.newRevTitle = RED._("sidebar.project.versionControl.commitCapital")+" "+entry.sha.substring(0,7);
result.date = humanizeSinceDate(parseInt(entry.date));
RED.diff.showCommitDiff(result);

View File

@@ -158,6 +158,7 @@ RED.sidebar.config = (function() {
entry.data('node',node.id);
nodeDiv.data('node',node.id);
var label = $('<div class="red-ui-palette-label"></div>').text(labelText).appendTo(nodeDiv);
if (node.d) {
nodeDiv.addClass("red-ui-palette-node-config-disabled");
$('<i class="fa fa-ban"></i>').prependTo(label);
@@ -179,6 +180,20 @@ RED.sidebar.config = (function() {
nodeDiv.addClass("red-ui-palette-node-config-unused");
}
}
if (!node.valid) {
nodeDiv.addClass("red-ui-palette-node-config-invalid")
const nodeDivAnnotations = $('<svg class="red-ui-palette-node-annotations red-ui-flow-node-error" width="10" height="10"></svg>').appendTo(nodeDiv)
const errorBadge = document.createElementNS("http://www.w3.org/2000/svg","path");
errorBadge.setAttribute("d","M 0,9 l 10,0 -5,-8 z");
nodeDivAnnotations.append($(errorBadge))
RED.popover.tooltip(nodeDivAnnotations, function () {
if (node.validationErrors && node.validationErrors.length > 0) {
return RED._("editor.errors.invalidProperties")+"<br> - "+node.validationErrors.join("<br> - ")
}
})
}
nodeDiv.on('click',function(e) {
e.stopPropagation();
RED.view.select(false);

View File

@@ -232,7 +232,7 @@ RED.sidebar.context = (function() {
typeHint: data.format,
sourceId: id+"."+k,
tools: tools,
path: ""
path: k
}).appendTo(propRow.children()[1]);
}
})
@@ -278,7 +278,7 @@ RED.sidebar.context = (function() {
typeHint: data.format,
sourceId: id+"."+k,
tools: tools,
path: ""
path: k
}).appendTo(propRow.children()[1]);
}
});
@@ -299,7 +299,7 @@ RED.sidebar.context = (function() {
typeHint: v.format,
sourceId: id+"."+k,
tools: tools,
path: ""
path: k
}).appendTo(propRow.children()[1]);
if (contextStores.length > 1) {
$("<span>",{class:"red-ui-sidebar-context-property-storename"}).text(v.store).appendTo($(propRow.children()[0]))

View File

@@ -383,6 +383,7 @@ RED.sidebar.help = (function() {
$(this).toggleClass('expanded',!isExpanded);
})
helpSection.parent().scrollTop(0);
RED.editor.mermaid.render()
}
function set(html,title) {

View File

@@ -464,7 +464,7 @@ RED.sidebar.info = (function() {
}
$(this).toggleClass('expanded',!isExpanded);
});
mermaid.init();
RED.editor.mermaid.render()
}
var tips = (function() {

View File

@@ -186,8 +186,15 @@ RED.typeSearch = (function() {
var iconContainer = $('<div/>',{class:"red-ui-palette-icon-container"}).appendTo(nodeDiv);
RED.utils.createIconElement(icon_url, iconContainer, false);
if (!/^_action_:/.test(object.type) && object.type !== "junction") {
if (/^subflow:/.test(object.type)) {
var sf = RED.nodes.subflow(object.type.substring(8));
if (sf.in.length > 0) {
$('<div/>',{class:"red-ui-search-result-node-port"}).appendTo(nodeDiv);
}
if (sf.out.length > 0) {
$('<div/>',{class:"red-ui-search-result-node-port red-ui-search-result-node-output"}).appendTo(nodeDiv);
}
} else if (!/^_action_:/.test(object.type) && object.type !== "junction") {
if (def.inputs > 0) {
$('<div/>',{class:"red-ui-search-result-node-port"}).appendTo(nodeDiv);
}
@@ -323,7 +330,7 @@ RED.typeSearch = (function() {
}
}
function applyFilter(filter,type,def) {
return !filter ||
return !def || !filter ||
(
(!filter.spliceMultiple) &&
(!filter.type || type === filter.type) &&

View File

@@ -101,28 +101,8 @@ RED.utils = (function() {
renderer.code = function (code, lang) {
if(lang === "mermaid") {
// mermaid diagram rendering
if (mermaidIsEnabled === undefined) {
if (RED.settings.markdownEditor &&
RED.settings.markdownEditor.mermaid) {
mermaidIsEnabled = RED.settings.markdownEditor.mermaid.enabled;
}
else {
mermaidIsEnabled = true;
}
}
if (mermaidIsEnabled) {
if (!mermaidIsInitialized) {
mermaidIsInitialized = true;
mermaid.initialize({startOnLoad:false});
}
return `<pre class='mermaid'>${code}</pre>`;
}
else {
return `<details><summary>${RED._("markdownEditor.mermaid.summary")}</summary><pre><code>${code}</code></pre></details>`;
}
}
else {
return `<pre class='mermaid'>${code}</pre>`;
} else {
return "<pre><code>" +code +"</code></pre>";
}
};
@@ -917,6 +897,54 @@ RED.utils = (function() {
}
}
/**
* Checks a typed property is valid according to the type.
* Returns true if valid.
* Return String error message if invalid
* @param {*} propertyType
* @param {*} propertyValue
* @returns true if valid, String if invalid
*/
function validateTypedProperty(propertyValue, propertyType, opt) {
if (propertyValue && /^\${[^}]+}$/.test(propertyValue)) {
// Allow ${ENV_VAR} value
return true
}
let error
if (propertyType === 'json') {
try {
JSON.parse(propertyValue);
} catch(err) {
error = RED._("validator.errors.invalid-json", {
error: err.message
})
}
} else if (propertyType === 'msg' || propertyType === 'flow' || propertyType === 'global' ) {
if (!RED.utils.validatePropertyExpression(propertyValue)) {
error = RED._("validator.errors.invalid-prop")
}
} else if (propertyType === 'num') {
if (!/^NaN$|^[+-]?[0-9]*\.?[0-9]*([eE][-+]?[0-9]+)?$|^[+-]?(0b|0B)[01]+$|^[+-]?(0o|0O)[0-7]+$|^[+-]?(0x|0X)[0-9a-fA-F]+$/.test(propertyValue)) {
error = RED._("validator.errors.invalid-num")
}
} else if (propertyType === 'jsonata') {
try {
jsonata(propertyValue)
} catch(err) {
error = RED._("validator.errors.invalid-expr", {
error: err.message
})
}
}
if (error) {
if (opt && opt.label) {
return opt.label+': '+error
}
return error
}
return true
}
function getMessageProperty(msg,expr) {
var result = null;
var msgPropParts;
@@ -1451,6 +1479,7 @@ RED.utils = (function() {
getDarkerColor: getDarkerColor,
parseModuleList: parseModuleList,
checkModuleAllowed: checkModuleAllowed,
getBrowserInfo: getBrowserInfo
getBrowserInfo: getBrowserInfo,
validateTypedProperty: validateTypedProperty
}
})();

View File

@@ -302,11 +302,21 @@ RED.view = (function() {
return api
})()
const isMac = RED.utils.getBrowserInfo().os === 'mac'
// 'Control' is the main modifier key for mouse actions. On Windows,
// that is the standard Ctrl key. On Mac that is the Cmd key.
function isControlPressed (event) {
return (isMac && event.metaKey) || (!isMac && event.ctrlKey)
}
function init() {
chart = $("#red-ui-workspace-chart");
chart.on('contextmenu', function(evt) {
if (RED.view.DEBUG) {
console.warn("contextmenu", { mouse_mode, event: d3.event });
}
mouse_mode = RED.state.DEFAULT
evt.preventDefault()
evt.stopPropagation()
RED.contextMenu.show({
@@ -1190,7 +1200,7 @@ RED.view = (function() {
lasso = null;
}
if (d3.event.touches || d3.event.button === 0) {
if ((mouse_mode === 0 || mouse_mode === RED.state.QUICK_JOINING) && (d3.event.metaKey || d3.event.ctrlKey) && !(d3.event.altKey || d3.event.shiftKey)) {
if ((mouse_mode === 0 || mouse_mode === RED.state.QUICK_JOINING) && isControlPressed(d3.event) && !(d3.event.altKey || d3.event.shiftKey)) {
// Trigger quick add dialog
d3.event.stopPropagation();
clearSelection();
@@ -1200,7 +1210,7 @@ RED.view = (function() {
clickedGroup = clickedGroup || RED.nodes.group(drag_lines[0].node.g)
}
showQuickAddDialog({ position: point, group: clickedGroup });
} else if (mouse_mode === 0 && !(d3.event.metaKey || d3.event.ctrlKey)) {
} else if (mouse_mode === 0 && !isControlPressed(d3.event)) {
// CTRL not being held
if (!d3.event.altKey) {
// ALT not held (shift is allowed) Trigger lasso
@@ -3540,7 +3550,7 @@ RED.view = (function() {
d3.event.preventDefault()
document.getSelection().removeAllRanges()
if (d.type != "subflow") {
if (/^subflow:/.test(d.type) && (d3.event.ctrlKey || d3.event.metaKey)) {
if (/^subflow:/.test(d.type) && isControlPressed(d3.event)) {
RED.workspaces.show(d.type.substring(8));
} else {
RED.editor.edit(d);
@@ -3704,12 +3714,12 @@ RED.view = (function() {
d.type !== 'junction'
lastClickNode = mousedown_node;
if (d.selected && (d3.event.ctrlKey||d3.event.metaKey)) {
if (d.selected && isControlPressed(d3.event)) {
mousedown_node.selected = false;
movingSet.remove(mousedown_node);
} else {
if (d3.event.shiftKey) {
if (!(d3.event.ctrlKey||d3.event.metaKey)) {
if (!isControlPressed(d3.event)) {
clearSelection();
}
var clickPosition = (d3.event.offsetX/scaleFactor - mousedown_node.x)
@@ -3878,10 +3888,10 @@ RED.view = (function() {
}
mousedown_link = d;
if (!(d3.event.metaKey || d3.event.ctrlKey)) {
if (!isControlPressed(d3.event)) {
clearSelection();
}
if (d3.event.metaKey || d3.event.ctrlKey) {
if (isControlPressed(d3.event)) {
if (!selectedLinks.has(mousedown_link)) {
selectedLinks.add(mousedown_link);
} else {
@@ -3896,7 +3906,7 @@ RED.view = (function() {
redraw();
focusView();
d3.event.stopPropagation();
if (!mousedown_link.link && movingSet.length() === 0 && (d3.event.touches || d3.event.button === 0) && selectedLinks.length() === 1 && selectedLinks.has(mousedown_link) && (d3.event.metaKey || d3.event.ctrlKey)) {
if (!mousedown_link.link && movingSet.length() === 0 && (d3.event.touches || d3.event.button === 0) && selectedLinks.length() === 1 && selectedLinks.has(mousedown_link) && isControlPressed(d3.event)) {
d3.select(this).classed("red-ui-flow-link-splice",true);
var point = d3.mouse(this);
var clickedGroup = getGroupAt(point[0],point[1]);
@@ -3977,7 +3987,7 @@ RED.view = (function() {
);
lastClickNode = g;
if (g.selected && (d3.event.ctrlKey||d3.event.metaKey)) {
if (g.selected && isControlPressed(d3.event)) {
selectedGroups.remove(g);
d3.event.stopPropagation();
} else {
@@ -4145,10 +4155,15 @@ RED.view = (function() {
scaleFactor = 30/largestEdge;
}
var width = img.width * scaleFactor;
if (width > 20) {
scaleFactor *= 20/width;
width = 20;
}
var height = img.height * scaleFactor;
icon.attr("width",width);
icon.attr("height",height);
icon.attr("x",15-width/2);
icon.attr("y",(30-height)/2);
}
icon.attr("xlink:href",iconUrl);
icon.style("display",null);
@@ -4177,7 +4192,7 @@ RED.view = (function() {
nodeEl.__statusGroup__.style.display = "none";
} else {
nodeEl.__statusGroup__.style.display = "inline";
let backgroundWidth = 12
let backgroundWidth = 15
var fill = status_colours[d.status.fill]; // Only allow our colours for now
if (d.status.shape == null && fill == null) {
backgroundWidth = 0
@@ -4197,7 +4212,11 @@ RED.view = (function() {
nodeEl.__statusLabel__.textContent = "";
}
const textSize = nodeEl.__statusLabel__.getBBox()
nodeEl.__statusBackground__.setAttribute('width', backgroundWidth + textSize.width + 6)
backgroundWidth += textSize.width
if (backgroundWidth > 0 && textSize.width > 0) {
backgroundWidth += 6
}
nodeEl.__statusBackground__.setAttribute('width', backgroundWidth)
}
delete d.dirtyStatus;
}
@@ -4609,8 +4628,8 @@ RED.view = (function() {
statusBackground.setAttribute("y",-1);
statusBackground.setAttribute("width",200);
statusBackground.setAttribute("height",13);
statusBackground.setAttribute("rx",1);
statusBackground.setAttribute("ry",1);
statusBackground.setAttribute("rx",2);
statusBackground.setAttribute("ry",2);
statusEl.appendChild(statusBackground);
node[0][0].__statusBackground__ = statusBackground;

View File

@@ -17,6 +17,8 @@
RED.workspaces = (function() {
const documentTitle = document.title;
var activeWorkspace = 0;
var workspaceIndex = 0;
@@ -339,12 +341,18 @@ RED.workspaces = (function() {
$("#red-ui-workspace-chart").show();
activeWorkspace = tab.id;
window.location.hash = 'flow/'+tab.id;
if (tab.label) {
document.title = `${documentTitle} : ${tab.label}`
} else {
document.title = documentTitle
}
$("#red-ui-workspace").toggleClass("red-ui-workspace-disabled", !!tab.disabled);
$("#red-ui-workspace").toggleClass("red-ui-workspace-locked", !!tab.locked);
} else {
$("#red-ui-workspace-chart").hide();
activeWorkspace = 0;
window.location.hash = '';
document.title = documentTitle
}
event.workspace = activeWorkspace;
RED.events.emit("workspace:change",event);

View File

@@ -16,8 +16,20 @@
RED.validators = {
number: function(blankAllowed,mopt){
return function(v, opt) {
if ((blankAllowed&&(v===''||v===undefined)) || (v!=='' && !isNaN(v))) {
return true;
if (blankAllowed && (v === '' || v === undefined)) {
return true
}
if (v !== '') {
if (/^NaN$|^[+-]?[0-9]*\.?[0-9]*([eE][-+]?[0-9]+)?$|^[+-]?(0b|0B)[01]+$|^[+-]?(0o|0O)[0-7]+$|^[+-]?(0x|0X)[0-9a-fA-F]+$/.test(v)) {
return true
}
if (/^\${[^}]+}$/.test(v)) {
// Allow ${ENV_VAR} value
return true
}
}
if (!isNaN(v)) {
return true
}
if (opt && opt.label) {
return RED._("validator.errors.invalid-num-prop", {
@@ -40,46 +52,32 @@ RED.validators = {
return opt ? RED._("validator.errors.invalid-regexp") : false;
};
},
typedInput: function(ptypeName,isConfig,mopt) {
typedInput: function(ptypeName, isConfig, mopt) {
let options = ptypeName
if (typeof ptypeName === 'string' ) {
options = {}
options.typeField = ptypeName
options.isConfig = isConfig
options.allowBlank = false
}
return function(v, opt) {
var ptype = $("#node-"+(isConfig?"config-":"")+"input-"+ptypeName).val() || this[ptypeName];
if (ptype === 'json') {
try {
JSON.parse(v);
return true;
} catch(err) {
if (opt && opt.label) {
return RED._("validator.errors.invalid-json-prop", {
error: err.message,
prop: opt.label,
});
}
return opt ? RED._("validator.errors.invalid-json", {
error: err.message
}) : false;
}
} else if (ptype === 'msg' || ptype === 'flow' || ptype === 'global' ) {
if (RED.utils.validatePropertyExpression(v)) {
return true;
}
if (opt && opt.label) {
return RED._("validator.errors.invalid-prop-prop", {
prop: opt.label
});
}
return opt ? RED._("validator.errors.invalid-prop") : false;
} else if (ptype === 'num') {
if (/^[+-]?[0-9]*\.?[0-9]*([eE][-+]?[0-9]+)?$/.test(v)) {
return true;
}
if (opt && opt.label) {
return RED._("validator.errors.invalid-num-prop", {
prop: opt.label
});
}
return opt ? RED._("validator.errors.invalid-num") : false;
let ptype = options.type
if (!ptype && options.typeField) {
ptype = $("#node-"+(options.isConfig?"config-":"")+"input-"+options.typeField).val() || this[options.typeField];
}
return true;
};
if (options.allowBlank && v === '') {
return true
}
if (options.allowUndefined && v === undefined) {
return true
}
const result = RED.utils.validateTypedProperty(v, ptype, opt)
if (result === true || opt) {
// Valid, or opt provided - return result as-is
return result
}
// No opt - need to return false for backwards compatibilty
return false
}
}
};
};

View File

@@ -114,6 +114,7 @@
pointer-events: stroke;
}
.red-ui-flow-group-outline-select {
cursor: move;
fill: none;
stroke: var(--red-ui-node-selected-color);
pointer-events: none;

View File

@@ -194,10 +194,6 @@
}
}
.red-ui-clipboard-dialog-import-conflicts-controls {
position: absolute;
top:0;
bottom: 0;
right: 0px;
text-align: center;
color: var(--red-ui-form-text-color);
.form-row & label {
@@ -218,9 +214,21 @@
margin: 0;
}
}
#red-ui-clipboard-dialog-import-conflicts-list .disabled .red-ui-info-outline-item {
opacity: 0.4;
#red-ui-clipboard-dialog-import-conflicts-list .disabled {
.red-ui-info-outline-item,
.red-ui-node-list-item {
opacity: 0.4;
}
}
#red-ui-clipboard-dialog-import-conflicts-list .red-ui-node-list-item {
display: flex;
align-items: center;
& > :first-child {
flex-grow: 1
}
}
.form-row label.red-ui-clipboard-dialog-import-conflicts-gutter {
box-sizing: border-box;
width: 22px;

View File

@@ -825,6 +825,7 @@ div.red-ui-projects-dialog-ssh-public-key {
margin-top: 0 !important;
padding: 5px 10px;
margin-bottom: 10px;
border-radius: 3px 3px 0px 0px;
}
}

View File

@@ -36,7 +36,7 @@ ul.red-ui-sidebar-node-config-list {
text-align: center;
}
.red-ui-palette-node {
overflow: hidden;
// overflow: hidden;
cursor: default;
&.selected {
border-color: transparent;
@@ -113,6 +113,15 @@ ul.red-ui-sidebar-node-config-list li.red-ui-palette-node-config-type {
margin-right: 5px;
}
}
.red-ui-palette-node-config-invalid {
border-color: var(--red-ui-form-input-border-error-color)
}
.red-ui-palette-node-annotations {
position: absolute;
left: calc(100% - 15px);
top: -8px;
display: block;
}
.red-ui-sidebar-node-config-filter-info {
position: absolute;
top: 0;

View File

@@ -22,26 +22,26 @@
limitations under the License.
-->
<title>{{ page.title }}</title>
<link rel="icon" type="image/png" href="{{ page.favicon }}">
<link rel="mask-icon" href="{{ page.tabicon.icon }}" color="{{ page.tabicon.colour }}">
<link rel="stylesheet" href="vendor/jquery/css/base/jquery-ui.min.css?v={{ page.version }}">
<link rel="stylesheet" href="vendor/font-awesome/css/font-awesome.min.css?v={{ page.version }}">
<link rel="stylesheet" href="red/style.min.css?v={{ page.version }}">
<link rel="icon" type="image/png" href="{{{ page.favicon }}}">
<link rel="mask-icon" href="{{{ page.tabicon.icon }}}" color="{{ page.tabicon.colour }}">
<link rel="stylesheet" href="vendor/jquery/css/base/jquery-ui.min.css?v={{ cacheBuster }}">
<link rel="stylesheet" href="vendor/font-awesome/css/font-awesome.min.css?v={{ cacheBuster }}">
<link rel="stylesheet" href="red/style.min.css?v={{ cacheBuster }}">
{{#page.css}}
<link rel="stylesheet" href="{{.}}">
{{/page.css}}
{{#asset.vendorMonaco}}
<link rel="stylesheet" href="vendor/monaco/style.css?v={{ page.version }}">
<link rel="stylesheet" href="vendor/monaco/style.css?v={{ cacheBuster }}">
{{/asset.vendorMonaco}}
</head>
<body spellcheck="false">
<div id="red-ui-editor"></div>
<script src="vendor/vendor.js?v={{ page.version }}"></script>
<script src="vendor/vendor.js?v={{ cacheBuster }}"></script>
{{#asset.vendorMonaco}}
<script src="{{ asset.vendorMonaco }}?v={{ page.version }}"></script>
<script src="{{{ asset.vendorMonaco }}}?v={{ cacheBuster }}"></script>
{{/asset.vendorMonaco}}
<script src="{{ asset.red }}?v={{ page.version }}"></script>
<script src="{{ asset.main }}?v={{ page.version }}"></script>
<script src="{{{ asset.red }}}?v={{ cacheBuster }}"></script>
<script src="{{{ asset.main }}}?v={{ cacheBuster }}"></script>
{{# page.scripts }}
<script src="{{.}}"></script>
{{/ page.scripts }}

View File

@@ -227,34 +227,42 @@
name: {value:""},
props:{value:[{p:"payload"},{p:"topic",vt:"str"}], validate:function(v, opt) {
if (!v || v.length === 0) { return true }
const errors = []
for (var i=0;i<v.length;i++) {
if (/^\${[^}]+}$/.test(v[i].v)) {
// Allow ${ENV_VAR} value
continue
}
if (/msg|flow|global/.test(v[i].vt)) {
if (!RED.utils.validatePropertyExpression(v[i].v)) {
return RED._("node-red:inject.errors.invalid-prop", { prop: 'msg.'+v[i].p, error: v[i].v });
errors.push(RED._("node-red:inject.errors.invalid-prop", { prop: 'msg.'+v[i].p, error: v[i].v }))
}
} else if (v[i].vt === "jsonata") {
try{ jsonata(v[i].v); }
catch(e){
return RED._("node-red:inject.errors.invalid-jsonata", { prop: 'msg.'+v[i].p, error: e.message });
errors.push(RED._("node-red:inject.errors.invalid-jsonata", { prop: 'msg.'+v[i].p, error: e.message }))
}
} else if (v[i].vt === "json") {
try{ JSON.parse(v[i].v); }
catch(e){
return RED._("node-red:inject.errors.invalid-json", { prop: 'msg.'+v[i].p, error: e.message });
errors.push(RED._("node-red:inject.errors.invalid-json", { prop: 'msg.'+v[i].p, error: e.message }))
}
} else if (v[i].vt === "num"){
if (!/^[+-]?[0-9]*\.?[0-9]*([eE][-+]?[0-9]+)?$/.test(v[i].v)) {
return RED._("node-red:inject.errors.invalid-prop", { prop: 'msg.'+v[i].p, error: v[i].v });
errors.push(RED._("node-red:inject.errors.invalid-prop", { prop: 'msg.'+v[i].p, error: v[i].v }))
}
}
}
if (errors.length > 0) {
return errors
}
return true;
}
},
repeat: {
value:"", validate: function(v, opt) {
if ((v === "") ||
(RED.validators.number(v) &&
(RED.validators.number()(v) &&
(v >= 0) && (v <= 2147483))) {
return true;
}
@@ -263,7 +271,7 @@
},
crontab: {value:""},
once: {value:false},
onceDelay: {value:0.1},
onceDelay: {value:0.1, validate: RED.validators.number(true)},
topic: {value:""},
payload: {value:"", validate: RED.validators.typedInput("payloadType", false) },
payloadType: {value:"date"},
@@ -320,7 +328,7 @@
}
// but replace with repeat one if set to repeat
if ((this.repeat && this.repeat != 0) || this.crontab) {
suffix = " ↻";
suffix = "\t↻";
}
if (this.name) {
return this.name+suffix;

View File

@@ -109,9 +109,8 @@ module.exports = function(RED) {
}
const p = props.shift()
const property = p.p;
const value = p.v ? p.v : '';
const valueType = p.vt ? p.vt : 'str';
const value = p.v !== undefined ? p.v : '';
const valueType = p.vt !== undefined ? p.vt : 'str';
if (property) {
if (valueType === "jsonata") {
if (p.v) {

View File

@@ -86,7 +86,7 @@
},
label: function() {
var suffix = "";
if (this.console === true || this.console === "true") { suffix = " ⇲"; }
if (this.console === true || this.console === "true") { suffix = "\t⇲"; }
if (this.targetType === "jsonata") {
return (this.name || "JSONata") + suffix;
}
@@ -195,6 +195,119 @@
node.dirty = true;
});
RED.view.redraw();
},
requestDebugNodeList: function(filteredNodes) {
var workspaceOrder = RED.nodes.getWorkspaceOrder();
var workspaceOrderMap = {};
workspaceOrder.forEach(function(ws,i) {
workspaceOrderMap[ws] = i;
});
var candidateNodes = [];
var candidateSFs = [];
var subflows = {};
RED.nodes.eachNode(function (n) {
var nt = n.type;
if (nt === "debug") {
if (n.z in workspaceOrderMap) {
candidateNodes.push(n);
}
else {
var sf = RED.nodes.subflow(n.z);
if (sf) {
subflows[sf.id] = {
debug: true,
subflows: {}
};
}
}
}
else if(nt.substring(0, 8) === "subflow:") {
if (n.z in workspaceOrderMap) {
candidateSFs.push(n);
}
else {
var psf = RED.nodes.subflow(n.z);
if (psf) {
var sid = nt.substring(8);
var item = subflows[psf.id];
if (!item) {
item = {
debug: undefined,
subflows: {}
};
subflows[psf.id] = item;
}
item.subflows[sid] = true;
}
}
}
});
candidateSFs.forEach(function (sf) {
var sid = sf.type.substring(8);
if (containsDebug(sid, subflows)) {
candidateNodes.push(sf);
}
});
candidateNodes.sort(function(A,B) {
var wsA = workspaceOrderMap[A.z];
var wsB = workspaceOrderMap[B.z];
if (wsA !== wsB) {
return wsA-wsB;
}
var labelA = RED.utils.getNodeLabel(A,A.id);
var labelB = RED.utils.getNodeLabel(B,B.id);
return labelA.localeCompare(labelB);
});
var currentWs = null;
var data = [];
var currentFlow;
var currentSelectedCount = 0;
candidateNodes.forEach(function(node) {
if (currentWs !== node.z) {
if (currentFlow && currentFlow.checkbox) {
currentFlow.selected = currentSelectedCount === currentFlow.children.length
}
currentSelectedCount = 0;
currentWs = node.z;
var parent = RED.nodes.workspace(currentWs) || RED.nodes.subflow(currentWs);
currentFlow = {
label: RED.utils.getNodeLabel(parent, currentWs),
}
if (!parent.disabled) {
currentFlow.children = [];
currentFlow.checkbox = true;
} else {
currentFlow.class = "disabled"
}
data.push(currentFlow);
}
if (currentFlow.children) {
if (!filteredNodes[node.id]) {
currentSelectedCount++;
}
currentFlow.children.push({
label: RED.utils.getNodeLabel(node,node.id),
node: {
id: node.id
},
checkbox: true,
selected: !filteredNodes[node.id]
});
}
});
if (currentFlow && currentFlow.checkbox) {
currentFlow.selected = currentSelectedCount === currentFlow.children.length
}
if (subWindow) {
try {
subWindow.postMessage({event:"refreshDebugNodeList", nodes:data},"*");
} catch(err) {
console.log(err);
}
}
RED.debug.refreshDebugNodeList(data)
}
};
@@ -396,6 +509,26 @@
}
}
function containsDebug(sid, map) {
var item = map[sid];
if (item) {
if (item.debug === undefined) {
var sfs = Object.keys(item.subflows);
var contain = false;
for (var i = 0; i < sfs.length; i++) {
var sf = sfs[i];
if (containsDebug(sf, map)) {
contain = true;
break;
}
}
item.debug = contain;
}
return item.debug;
}
return false;
}
$("#red-ui-sidebar-debug-open").on("click", function(e) {
e.preventDefault();
subWindow = window.open(document.location.toString().replace(/[?#].*$/,"")+"debug/view/view.html"+document.location.search,"nodeREDDebugView","menubar=no,location=no,toolbar=no,chrome,height=500,width=600");
@@ -427,6 +560,8 @@
options.messageSourceClick(msg.id,msg._alias,msg.path);
} else if (msg.event === "clear") {
options.clear();
} else if (msg.event === "requestDebugNodeList") {
options.requestDebugNodeList(msg.filteredNodes)
}
};
window.addEventListener('message',this.handleWindowMessage);

View File

@@ -275,7 +275,7 @@
value: [],
type: "link in[]",
validate: function (v, opt) {
if ((this.linkType === "static" && v.length > 0)
if (((this.linkType || "static") === "static" && v.length > 0)
|| this.linkType === "dynamic") {
return true;
}

View File

@@ -167,19 +167,13 @@ RED.debug = (function() {
var menu = RED.popover.menu({
options: options,
onselect: function(item) {
if (item.value !== filterType) {
filterType = item.value;
$('#red-ui-sidebar-debug-filter span').text(RED._('node-red:debug.sidebar.'+filterType));
refreshMessageList();
RED.settings.set("debug.filter",filterType)
}
setFilterType(item.value)
if (filterType === 'filterSelected') {
refreshDebugNodeList();
config.requestDebugNodeList(filteredNodes);
filterDialog.slideDown(200);
filterDialogShown = true;
debugNodeTreeList.focus();
}
}
});
menu.show({
@@ -254,131 +248,7 @@ RED.debug = (function() {
}
function containsDebug(sid, map) {
var item = map[sid];
if (item) {
if (item.debug === undefined) {
var sfs = Object.keys(item.subflows);
var contain = false;
for (var i = 0; i < sfs.length; i++) {
var sf = sfs[i];
if (containsDebug(sf, map)) {
contain = true;
break;
}
}
item.debug = contain;
}
return item.debug;
}
return false;
}
function refreshDebugNodeList() {
var workspaceOrder = RED.nodes.getWorkspaceOrder();
var workspaceOrderMap = {};
workspaceOrder.forEach(function(ws,i) {
workspaceOrderMap[ws] = i;
});
var candidateNodes = [];
var candidateSFs = [];
var subflows = {};
RED.nodes.eachNode(function (n) {
var nt = n.type;
if (nt === "debug") {
if (n.z in workspaceOrderMap) {
candidateNodes.push(n);
}
else {
var sf = RED.nodes.subflow(n.z);
if (sf) {
subflows[sf.id] = {
debug: true,
subflows: {}
};
}
}
}
else if(nt.substring(0, 8) === "subflow:") {
if (n.z in workspaceOrderMap) {
candidateSFs.push(n);
}
else {
var psf = RED.nodes.subflow(n.z);
if (psf) {
var sid = nt.substring(8);
var item = subflows[psf.id];
if (!item) {
item = {
debug: undefined,
subflows: {}
};
subflows[psf.id] = item;
}
item.subflows[sid] = true;
}
}
}
});
candidateSFs.forEach(function (sf) {
var sid = sf.type.substring(8);
if (containsDebug(sid, subflows)) {
candidateNodes.push(sf);
}
});
candidateNodes.sort(function(A,B) {
var wsA = workspaceOrderMap[A.z];
var wsB = workspaceOrderMap[B.z];
if (wsA !== wsB) {
return wsA-wsB;
}
var labelA = RED.utils.getNodeLabel(A,A.id);
var labelB = RED.utils.getNodeLabel(B,B.id);
return labelA.localeCompare(labelB);
});
var currentWs = null;
var data = [];
var currentFlow;
var currentSelectedCount = 0;
candidateNodes.forEach(function(node) {
if (currentWs !== node.z) {
if (currentFlow && currentFlow.checkbox) {
currentFlow.selected = currentSelectedCount === currentFlow.children.length
}
currentSelectedCount = 0;
currentWs = node.z;
var parent = RED.nodes.workspace(currentWs) || RED.nodes.subflow(currentWs);
currentFlow = {
label: RED.utils.getNodeLabel(parent, currentWs),
}
if (!parent.disabled) {
currentFlow.children = [];
currentFlow.checkbox = true;
} else {
currentFlow.class = "disabled"
}
data.push(currentFlow);
}
if (currentFlow.children) {
if (!filteredNodes[node.id]) {
currentSelectedCount++;
}
currentFlow.children.push({
label: RED.utils.getNodeLabel(node,node.id),
node: node,
checkbox: true,
selected: !filteredNodes[node.id]
});
}
});
if (currentFlow && currentFlow.checkbox) {
currentFlow.selected = currentSelectedCount === currentFlow.children.length
}
function refreshDebugNodeList(data) {
debugNodeTreeList.treeList("data", data);
}
@@ -401,7 +271,7 @@ RED.debug = (function() {
},200);
}
function _refreshMessageList(_activeWorkspace) {
if (_activeWorkspace) {
if (typeof _activeWorkspace === 'string') {
activeWorkspace = _activeWorkspace.replace(/\./g,"_");
}
if (filterType === "filterAll") {
@@ -479,12 +349,12 @@ RED.debug = (function() {
filteredNodes[n.id] = true;
});
delete filteredNodes[sourceId];
$("#red-ui-sidebar-debug-filterSelected").trigger("click");
RED.settings.set('debug.filteredNodes',Object.keys(filteredNodes))
setFilterType('filterSelected')
refreshMessageList();
}},
{id:"red-ui-debug-msg-menu-item-clear-filter",label:RED._("node-red:debug.messageMenu.clearFilter"),onselect:function(){
$("#red-ui-sidebar-debug-filterAll").trigger("click");
clearFilterSettings()
refreshMessageList();
}}
);
@@ -713,9 +583,17 @@ RED.debug = (function() {
if (!!clearFilter) {
clearFilterSettings();
}
refreshDebugNodeList();
config.requestDebugNodeList(filteredNodes);
}
function setFilterType(type) {
if (type !== filterType) {
filterType = type;
$('#red-ui-sidebar-debug-filter span').text(RED._('node-red:debug.sidebar.'+filterType));
refreshMessageList();
RED.settings.set("debug.filter",filterType)
}
}
function clearFilterSettings() {
filteredNodes = {};
filterType = 'filterAll';
@@ -728,6 +606,7 @@ RED.debug = (function() {
init: init,
refreshMessageList:refreshMessageList,
handleDebugMessage: handleDebugMessage,
clearMessageList: clearMessageList
clearMessageList: clearMessageList,
refreshDebugNodeList: refreshDebugNodeList
}
})();

View File

@@ -12,6 +12,9 @@ $(function() {
},
clear: function() {
window.opener.postMessage({event:"clear"},'*');
},
requestDebugNodeList: function(filteredNodes) {
window.opener.postMessage({event: 'requestDebugNodeList', filteredNodes},'*')
}
}
@@ -26,6 +29,8 @@ $(function() {
RED.debug.refreshMessageList(evt.data.activeWorkspace);
} else if (evt.data.event === "projectChange") {
RED.debug.clearMessageList(true);
} else if (evt.data.event === "refreshDebugNodeList") {
RED.debug.refreshDebugNodeList(evt.data.nodes)
}
},false);
} catch(err) {

View File

@@ -366,7 +366,7 @@
name: {value:"_DEFAULT_"},
func: {value:"\nreturn msg;"},
outputs: {value:1},
timeout:{value:0},
timeout:{value:RED.settings.functionTimeout || 0},
noerr: {value:0,required:true,
validate: function(v, opt) {
if (!v) {

View File

@@ -315,7 +315,7 @@ module.exports = function(RED) {
var spec = module.module;
if (spec && (spec !== "")) {
moduleLoadPromises.push(RED.import(module.module).then(lib => {
sandbox[vname] = lib.default;
sandbox[vname] = lib.default || lib;
}).catch(err => {
node.error(RED._("function.error.moduleLoadError",{module:module.spec, error:err.toString()}))
throw err;
@@ -521,7 +521,8 @@ module.exports = function(RED) {
RED.nodes.registerType("function",FunctionNode, {
dynamicModuleList: "libs",
settings: {
functionExternalModules: { value: true, exportable: true }
functionExternalModules: { value: true, exportable: true },
functionTimeout: { value:0, exportable: true }
}
});
RED.library.register("functions");

View File

@@ -103,7 +103,6 @@
} else if (type === "istype") {
r.v = rule.find(".node-input-rule-type-value").typedInput('type');
r.vt = rule.find(".node-input-rule-type-value").typedInput('type');
r.vt = (r.vt === "number") ? "num" : "str";
} else if (type === "jsonata_exp") {
r.v = rule.find(".node-input-rule-exp-value").typedInput('value');
r.vt = rule.find(".node-input-rule-exp-value").typedInput('type');
@@ -168,7 +167,35 @@
label:RED._("node-red:common.label.payload"),
validate: RED.validators.typedInput("propertyType", false)},
propertyType: { value:"msg" },
rules: {value:[{t:"eq", v:"", vt:"str"}]},
rules: {
value:[{t:"eq", v:"", vt:"str"}],
validate: function (rules, opt) {
let msg;
const errors = []
if (!rules || rules.length === 0) { return true }
for (var i=0;i<rules.length;i++) {
const opt = { label: RED._('node-red:switch.label.rule')+' '+(i+1) }
const r = rules[i];
if (r.t !== 'istype') {
if (r.hasOwnProperty('v')) {
if ((msg = RED.utils.validateTypedProperty(r.v,r.vt,opt)) !== true) {
errors.push(msg)
}
}
if (r.hasOwnProperty('v2')) {
if ((msg = RED.utils.validateTypedProperty(r.v2,r.v2t,opt)) !== true) {
errors.push(msg)
}
}
}
}
if (errors.length) {
console.log(errors)
return errors
}
return true;
}
},
checkall: {value:"true", required:true},
repair: {value:false},
outputs: {value:1}
@@ -218,7 +245,11 @@
if (i > 0) {
var lastRule = $("#node-input-rule-container").editableList('getItemAt',i-1);
var exportedRule = exportRule(lastRule.element);
opt.r.vt = exportedRule.vt;
if (exportedRule.t === "istype") {
opt.r.vt = (exportedRule.vt === "number") ? "num" : "str";
} else {
opt.r.vt = exportedRule.vt;
}
opt.r.v = "";
// We could copy the value over as well and preselect it (see the 'activeElement' code below)
// But not sure that feels right. Is copying over the last value 'expected' behaviour?

View File

@@ -19,71 +19,42 @@
<script type="text/javascript">
(function() {
function isInvalidProperty(v,vt) {
if (/msg|flow|global/.test(vt)) {
if (!RED.utils.validatePropertyExpression(v)) {
return RED._("node-red:change.errors.invalid-prop", {
property: v
});
}
} else if (vt === "jsonata") {
try{ jsonata(v); } catch(e) {
return RED._("node-red:change.errors.invalid-expr", {
error: e.message
});
}
} else if (vt === "json") {
try{ JSON.parse(v); } catch(e) {
return RED._("node-red:change.errors.invalid-json-data", {
error: e.message
});
}
}
return false;
}
RED.nodes.registerType('change', {
color: "#E2D96E",
category: 'function',
defaults: {
name: {value:""},
rules:{value:[{t:"set",p:"payload",pt:"msg",to:"",tot:"str"}],validate: function(rules, opt) {
var msg;
if (!rules || rules.length === 0) { return true }
for (var i=0;i<rules.length;i++) {
var r = rules[i];
if (r.t === 'set') {
if (msg = isInvalidProperty(r.p,r.pt)) {
return msg;
rules:{
value:[{t:"set",p:"payload",pt:"msg",to:"",tot:"str"}],
validate: function(rules, opt) {
let msg;
const errors = []
if (!rules || rules.length === 0) { return true }
for (var i=0;i<rules.length;i++) {
const opt = { label: RED._('node-red:change.label.rule')+' '+(i+1) }
const r = rules[i];
if (r.t === 'set' || r.t === 'change' || r.t === 'delete' || r.t === 'move') {
if ((msg = RED.utils.validateTypedProperty(r.p,r.pt,opt)) !== true) {
errors.push(msg)
}
}
if (msg = isInvalidProperty(r.to,r.tot)) {
return msg;
if (r.t === 'set' || r.t === 'change' || r.t === 'move') {
if ((msg = RED.utils.validateTypedProperty(r.to,r.tot,opt)) !== true) {
errors.push(msg)
}
}
} else if (r.t === 'change') {
if (msg = isInvalidProperty(r.p,r.pt)) {
return msg;
}
if(msg = isInvalidProperty(r.from,r.fromt)) {
return msg;
}
if(msg = isInvalidProperty(r.to,r.tot)) {
return msg;
}
} else if (r.t === 'delete') {
if (msg = isInvalidProperty(r.p,r.pt)) {
return msg;
}
} else if (r.t === 'move') {
if (msg = isInvalidProperty(r.p,r.pt)) {
return msg;
}
if (msg = isInvalidProperty(r.to,r.tot)) {
return msg;
if (r.t === 'change') {
if ((msg = RED.utils.validateTypedProperty(r.from,r.fromt,opt)) !== true) {
errors.push(msg)
}
}
}
if (errors.length) {
return errors
}
return true;
}
return true;
}},
},
// legacy
action: {value:""},
property: {value:""},

View File

@@ -57,7 +57,9 @@
action: {value:"scale"},
round: {value:false},
property: {value:"payload",required:true,
label:RED._("node-red:common.label.property")},
label:RED._("node-red:common.label.property"),
validate: RED.validators.typedInput({ type: 'msg', allowBlank: true })
},
name: {value:""}
},
inputs: 1,

View File

@@ -153,7 +153,7 @@
}
var editorRow = $("#dialog-form>div.node-text-editor-row");
height -= (parseInt(editorRow.css("marginTop"))+parseInt(editorRow.css("marginBottom")));
$(".node-text-editor").css("height",height+"px");
$("#dialog-form .node-text-editor").css("height",height+"px");
this.editor.resize();
}
});

View File

@@ -284,7 +284,7 @@ module.exports = function(RED) {
done();
}
}
else {
else if (!msg.hasOwnProperty("reset")) {
if (maxKeptMsgsCount(node) > 0) {
if (node.intervalID === -1) {
node.send(msg);

View File

@@ -56,7 +56,7 @@
color:"darksalmon",
defaults: {
command: {value:""},
addpay: {value:""},
addpay: {value:"", validate: RED.validators.typedInput({ type: 'msg', allowBlank: true })},
append: {value:""},
useSpawn: {value:"false"},
timer: {value:""},

View File

@@ -56,9 +56,11 @@
inout: {value:"out"},
septopics: {value:true},
property: {value:"payload", required:true,
label:RED._("node-red:rbe.label.property")},
label:RED._("node-red:rbe.label.property"),
validate: RED.validators.typedInput({ type: 'msg', allowUndefined: true })},
topi: {value:"topic", required:true,
label:RED._("node-red:rbe.label.topic")}
label:RED._("node-red:rbe.label.topic"),
validate: RED.validators.typedInput({ type: 'msg', allowUndefined: true })}
},
inputs:1,
outputs:1,

View File

@@ -24,7 +24,6 @@ module.exports = function(RED) {
"text/css":"string",
"text/html":"string",
"text/plain":"string",
"text/html":"string",
"application/json":"json",
"application/octet-stream":"buffer",
"application/pdf":"buffer",
@@ -105,6 +104,7 @@ module.exports = function(RED) {
* @returns `true` if it is a valid topic
*/
function isValidPublishTopic(topic) {
if (topic.length === 0) return false;
return !/[\+#\b\f\n\r\t\v\0]/.test(topic);
}
@@ -220,8 +220,8 @@ module.exports = function(RED) {
*/
function subscriptionHandler(node, datatype ,topic, payload, packet) {
const msg = {topic:topic, payload:null, qos:packet.qos, retain:packet.retain};
const v5 = (node && node.brokerConn)
? node.brokerConn.v5()
const v5 = (node && node.brokerConn)
? node.brokerConn.v5()
: Object.prototype.hasOwnProperty.call(packet, "properties");
if(v5 && packet.properties) {
setStrProp(packet.properties, msg, "responseTopic");
@@ -452,7 +452,7 @@ module.exports = function(RED) {
/**
* Perform the disconnect action
* @param {MQTTInNode|MQTTOutNode} node
* @param {MQTTInNode|MQTTOutNode} node
* @param {Function} done
*/
function handleDisconnectAction(node, done) {
@@ -612,7 +612,7 @@ module.exports = function(RED) {
node.brokerurl = node.url;
} else {
// if the broker is ws:// or wss:// or tcp://
if (node.broker.indexOf("://") > -1) {
if ((typeof node.broker === 'string') && node.broker.indexOf("://") > -1) {
node.brokerurl = node.broker;
// Only for ws or wss, check if proxy env var for additional configuration
if (node.brokerurl.indexOf("wss://") > -1 || node.brokerurl.indexOf("ws://") > -1) {
@@ -866,7 +866,7 @@ module.exports = function(RED) {
* Call end and wait for the client to end (or timeout)
* @param {mqtt.MqttClient} client The broker client
* @param {number} ms The time to wait for the client to end
* @returns
* @returns
*/
let waitEnd = (client, ms) => {
return new Promise( (resolve, reject) => {
@@ -906,7 +906,7 @@ module.exports = function(RED) {
node.subid = 1;
//typedef for subscription object:
/**
/**
* @typedef {Object} Subscription
* @property {String} topic - topic to subscribe to
* @property {Object} [options] - options object
@@ -934,7 +934,7 @@ module.exports = function(RED) {
const ref = _ref || 0;
let options
let qos = 1 // default to QoS 1 (AWS and several other brokers don't support QoS 2)
// if options is an object, then clone it
if (typeof _options == "object") {
options = RED.util.cloneMessage(_options || {})
@@ -948,7 +948,7 @@ module.exports = function(RED) {
if (typeof qos === "number" && qos >= 0 && qos <= 2) {
options.qos = qos;
}
subscription.topic = _topic;
subscription.qos = qos;
subscription.options = RED.util.cloneMessage(options);
@@ -958,16 +958,16 @@ module.exports = function(RED) {
}
/**
* If topic is a subscription object, then use that, otherwise look up the topic in
* If topic is a subscription object, then use that, otherwise look up the topic in
* the subscriptions object. If the topic is not found, then create a new subscription
* object and add it to the subscriptions object.
* @param {Subscription|String} topic
* @param {*} options
* @param {*} callback
* @param {*} ref
* @param {Subscription|String} topic
* @param {*} options
* @param {*} callback
* @param {*} ref
*/
node.subscribe = function (topic, options, callback, ref) {
/** @type {Subscription} */
/** @type {Subscription} */
let subscription
let doCompare = false
let changesFound = false
@@ -1005,7 +1005,7 @@ module.exports = function(RED) {
_brokerConn.unsubscribe(sub.topic, sub.ref, true)
}
})
// if subscription is found (or sent in as a parameter), then check for changes.
// if there are any changes requested, tidy up the old subscription
if (subscription) {
@@ -1092,7 +1092,7 @@ module.exports = function(RED) {
delete sub[ref]
}
}
// if instructed to remove the actual MQTT client subscription
// if instructed to remove the actual MQTT client subscription
if (unsub) {
// if there are no more subscriptions for the topic, then remove the topic
if (Object.keys(sub).length === 0) {

View File

@@ -141,15 +141,7 @@ in your Node-RED user directory (${RED.settings.userDir}).
});
}
}
/**
* @param {Object} headersObject
* @param {string} name
* @return {any} value
*/
const getHeaderValue = (headersObject, name) => {
const asLowercase = name.toLowercase();
return headersObject[Object.keys(headersObject).find(k => k.toLowerCase() === asLowercase)];
}
this.on("input",function(msg,nodeSend,nodeDone) {
checkNodeAgentPatch();
//reset redirectList on each request
@@ -300,7 +292,7 @@ in your Node-RED user directory (${RED.settings.userDir}).
}
opts.headers = {};
//add msg.headers
//add msg.headers
//NOTE: ui headers will take precidence over msg.headers
if (msg.headers) {
if (msg.headers.hasOwnProperty('x-node-red-request-node')) {
@@ -452,10 +444,6 @@ in your Node-RED user directory (${RED.settings.userDir}).
formData.append(opt, val);
} else if (typeof val === 'object' && val.hasOwnProperty('value')) {
formData.append(opt,val.value,val.options || {});
} else if (Array.isArray(val)) {
for (var i=0; i<val.length; i++) {
formData.append(opt, val[i])
}
} else {
formData.append(opt,JSON.stringify(val));
}
@@ -637,7 +625,7 @@ in your Node-RED user directory (${RED.settings.userDir}).
msg.payload = msg.payload.toString('utf8'); // txt
if (node.ret === "obj") {
if (msg.statusCode == 204){msg.payload= "{}"};
if (msg.statusCode == 204){msg.payload= "{}"};
try { msg.payload = JSON.parse(msg.payload); } // obj
catch(e) { node.warn(RED._("httpin.errors.json-error")); }
}
@@ -744,7 +732,7 @@ in your Node-RED user directory (${RED.settings.userDir}).
*
* If the algorithm directive's value ends with "-sess", then HA1 is
* HA1=digestCompute(digestCompute(username:realm:password):nonce:cnonce)
*
*
* If the algorithm directive's value does not end with "-sess", then HA1 is
* HA1=digestCompute(username:realm:password)
*/

View File

@@ -63,7 +63,7 @@ module.exports = function(RED) {
if (!(notemplate && (msg.hasOwnProperty("parts") && msg.parts.hasOwnProperty("index") && msg.parts.index > 0))) {
template = clean(node.template);
}
var ou = "";
const ou = [];
if (!Array.isArray(msg.payload)) { msg.payload = [ msg.payload ]; }
if (node.hdrout !== "none" && node.hdrSent === false) {
if ((template.length === 1) && (template[0] === '')) {
@@ -74,7 +74,7 @@ module.exports = function(RED) {
template = Object.keys(msg.payload[0]);
}
}
ou += template.map(v => v.indexOf(node.sep)!==-1 ? '"'+v+'"' : v).join(node.sep) + node.ret;
ou.push(template.map(v => v.indexOf(node.sep)!==-1 ? '"'+v+'"' : v).join(node.sep));
if (node.hdrout === "once") { node.hdrSent = true; }
}
for (var s = 0; s < msg.payload.length; s++) {
@@ -93,7 +93,7 @@ module.exports = function(RED) {
msg.payload[s][t] = node.quo + msg.payload[s][t].toString() + node.quo;
}
}
ou += msg.payload[s].join(node.sep) + node.ret;
ou.push(msg.payload[s].join(node.sep));
}
else {
if ((template.length === 1) && (template[0] === '') && (msg.hasOwnProperty("columns"))) {
@@ -105,6 +105,7 @@ module.exports = function(RED) {
node.warn(RED._("csv.errors.obj_csv"));
tmpwarn = false;
}
const row = [];
for (var p in msg.payload[0]) {
/* istanbul ignore else */
if (msg.payload[s].hasOwnProperty(p)) {
@@ -118,21 +119,22 @@ module.exports = function(RED) {
}
if (q.indexOf(node.quo) !== -1) { // add double quotes if any quotes
q = q.replace(/"/g, '""');
ou += node.quo + q + node.quo + node.sep;
row.push(node.quo + q + node.quo);
}
else if (q.indexOf(node.sep) !== -1 || p.indexOf("\n") !== -1) { // add quotes if any "commas" or "\n"
ou += node.quo + q + node.quo + node.sep;
row.push(node.quo + q + node.quo);
}
else { ou += q + node.sep; } // otherwise just add
else { row.push(q); } // otherwise just add
}
}
}
ou = ou.slice(0,-1) + node.ret;
ou.push(row.join(node.sep)); // add separator
}
else {
const row = [];
for (var t=0; t < template.length; t++) {
if (template[t] === '') {
ou += node.sep;
row.push('');
}
else {
var tt = template[t];
@@ -146,19 +148,20 @@ module.exports = function(RED) {
p = RED.util.ensureString(p);
if (p.indexOf(node.quo) !== -1) { // add double quotes if any quotes
p = p.replace(/"/g, '""');
ou += node.quo + p + node.quo + node.sep;
row.push(node.quo + p + node.quo);
}
else if (p.indexOf(node.sep) !== -1 || p.indexOf("\n") !== -1) { // add quotes if any "commas" or "\n"
ou += node.quo + p + node.quo + node.sep;
row.push(node.quo + p + node.quo);
}
else { ou += p + node.sep; } // otherwise just add
else { row.push(p); } // otherwise just add
}
}
ou = ou.slice(0,-1) + node.ret; // remove final "comma" and add "newline"
ou.push(row.join(node.sep)); // add separator
}
}
}
msg.payload = ou;
// join lines, don't forget to add the last new line
msg.payload = ou.join(node.ret) + node.ret;
msg.columns = template.map(v => v.indexOf(',')!==-1 ? '"'+v+'"' : v).join(',');
if (msg.payload !== '') { send(msg); }
done();

View File

@@ -41,8 +41,8 @@
color:"#DEBD5C",
defaults: {
name: {value:""},
property: {value:"payload"},
outproperty: {value:"payload"},
property: {value:"payload", validate: RED.validators.typedInput({ type: 'msg', allowUndefined: true }) },
outproperty: {value:"payload", validate: RED.validators.typedInput({ type: 'msg', allowUndefined: true }) },
tag: {value:""},
ret: {value:"html"},
as: {value:"single"}

View File

@@ -32,6 +32,7 @@
defaults: {
name: {value:""},
property: {value:"payload",required:true,
validate: RED.validators.typedInput({ type: 'msg', allowUndefined: true}),
label:RED._("node-red:json.label.property")},
action: {value:""},
pretty: {value:false}

View File

@@ -27,7 +27,8 @@
defaults: {
name: {value:""},
property: {value:"payload",required:true,
label:RED._("node-red:common.label.property")},
label:RED._("node-red:common.label.property"),
validate: RED.validators.typedInput({ type: 'msg', allowUndefined: true })},
attr: {value:""},
chr: {value:""}
},

View File

@@ -16,6 +16,7 @@
color:"#DEBD5C",
defaults: {
property: {value:"payload",required:true,
validate: RED.validators.typedInput({ type: 'msg', allowUndefined: true }),
label:RED._("node-red:common.label.property")},
name: {value:""}
},

View File

@@ -57,7 +57,7 @@
arraySplt: {value:1},
arraySpltType: {value:"len"},
stream: {value:false},
addname: {value:""}
addname: {value:"", validate: RED.validators.typedInput({ type: 'msg', allowBlank: true })}
},
inputs:1,
outputs:1,
@@ -208,7 +208,22 @@
validate:RED.validators.typedInput("propertyType", false)
},
propertyType: { value:"msg"},
key: {value:"topic"},
key: {value:"topic", validate: (function () {
const typeValidator = RED.validators.typedInput({ type: 'msg' })
return function(v, opt) {
const joinMode = $("#node-input-mode").val() || this.mode
if (joinMode !== 'custom') {
return true
}
const buildType = $("#node-input-build").val() || this.build
if (buildType !== 'object') {
return true
} else {
return typeValidator(v, opt)
}
}
})()
},
joiner: { value:"\\n"},
joinerType: { value:"str"},
accumulate: { value:"false" },

View File

@@ -198,7 +198,7 @@
category: 'storage',
defaults: {
name: {value:""},
filename: {value:""},
filename: {value:"", validate: RED.validators.typedInput({ typeField: 'filenameType' })},
filenameType: {value:"str"},
appendNewline: {value:true},
createDir: {value:false},
@@ -297,7 +297,7 @@
category: 'storage',
defaults: {
name: {value:""},
filename: {value:""},
filename: {value:"", validate: RED.validators.typedInput({ typeField: 'filenameType' }) },
filenameType: {value:"str"},
format: {value:"utf8"},
chunk: {value:false},

Binary file not shown.

Before

Width:  |  Height:  |  Size: 603 B

View File

@@ -0,0 +1 @@
<svg width="40" height="60" viewBox="0, 0, 40, 60" xmlns="http://www.w3.org/2000/svg"><g fill="none" stroke="#fff"><path d="m9.7884 22.379c-5.2427-0.41732-9.6475 5.7885-7.4975 10.585 2.0949 5.2041 9.9782 6.6154 13.727 2.4477 3.633-3.5613 5.0332-9.0411 9.4821-11.853 4.5205-3.0872 11.797-0.172 12.68 5.3144 0.86 5.2537-4.8017 10.364-9.9231 8.8205-3.7873-0.85449-6.5051-4.0905-8.0487-7.4975-1.9019-3.2526-4.3882-6.7257-8.2693-7.6077-0.6891-0.15656-1.4003-0.21831-2.1059-0.21721z" stroke-width="3.3"/><path d="m6.7012 29.821h6.6154" stroke-width="1.4"/><path d="m26.988 29.821h5.5128m-2.8115-2.7564v5.5128" stroke-width="1.8"/></g></svg>

After

Width:  |  Height:  |  Size: 635 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

View File

@@ -0,0 +1 @@
<svg width="40" height="60" viewBox="0, 0, 40, 60" xmlns="http://www.w3.org/2000/svg"><path d="m8.3474 17.75 22.298 22.444-10.747 13.013v-46.497l10.747 12.428-22.298 21.859" fill="none" stroke="#fff" stroke-width="4"/></svg>

After

Width:  |  Height:  |  Size: 225 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

View File

@@ -0,0 +1 @@
<svg width="40" height="60" viewBox="0, 0, 40, 60" xmlns="http://www.w3.org/2000/svg"><path d="m2.7078 12.986c0 7.7994-0.36386 21.569 0 32.545s35.118 9.8751 34.848 0c-0.26959-9.8751 0-24.82 0-32.545 0-7.7243-34.848-7.7995-34.848 0z" fill="none" stroke="#fff"/><g fill="#fff"><path d="m3.8741 13.406v8.955c0.021834 3.5781 19.543 5.0789 25.575 3.2543 0 0 0.02229-2.6683 0.02998-2.6673l5.5325 0.7238c0.64508 0.0844 1.1345-0.74597 1.134-1.3284v-8.573l-0.99896 0.93349-15.217-2.2765c4.5883 2.1798 9.808 4.1312 9.808 4.1312-9.3667 3.1562-25.846-0.31965-25.864-3.1525z"/><path d="m3.886 26.607v8.1052c3.2188 6.1087 29.901 5.8574 32.272 0v-8.1052c-3.3598 4.6685-29.204 5.1534-32.272 0z"/><path d="m4.0032 39.082v7.1522c2.556 7.4622 28.918 7.6072 32.272 0v-7.1522c-3.2345 4.9471-29.087 5.359-32.272 0z"/></g></svg>

After

Width:  |  Height:  |  Size: 806 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 414 B

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