mirror of
https://github.com/node-red/node-red.git
synced 2025-03-01 10:36:34 +00:00
Compare commits
1365 Commits
0.17.1
...
file-node-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7844c4faf6 | ||
|
|
f19025455b | ||
|
|
d1cc3da14d | ||
|
|
7f5d47f39d | ||
|
|
6031f146aa | ||
|
|
020a469f3b | ||
|
|
091de3aa66 | ||
|
|
b837f7608c | ||
|
|
afe9367bac | ||
|
|
9bd9023cb6 | ||
|
|
8502cf8498 | ||
|
|
33dade0584 | ||
|
|
84cc2ad0fa | ||
|
|
dc2d3bc7c0 | ||
|
|
64df557423 | ||
|
|
715cc77e76 | ||
|
|
b80d1af3d7 | ||
|
|
f05f534fd2 | ||
|
|
c0837ead0e | ||
|
|
a1f135bd66 | ||
|
|
978f4ecc58 | ||
|
|
46a8d96997 | ||
|
|
c283224000 | ||
|
|
a6ef755139 | ||
|
|
29a257d17a | ||
|
|
368b76a183 | ||
|
|
8bb861124d | ||
|
|
2f884ec778 | ||
|
|
8c561e92c8 | ||
|
|
633b9180d7 | ||
|
|
0e2d0e1b6f | ||
|
|
ea4d65ceee | ||
|
|
d47ac84d2e | ||
|
|
a97759aa35 | ||
|
|
3fcfd4abdd | ||
|
|
6d771da9a9 | ||
|
|
6201247875 | ||
|
|
8c367bcc53 | ||
|
|
8198132ca7 | ||
|
|
cf3b4e9e63 | ||
|
|
987dbf8a92 | ||
|
|
acf8c9bc4a | ||
|
|
7173895d36 | ||
|
|
43530d4a5f | ||
|
|
fefabef9ee | ||
|
|
0dd40a941b | ||
|
|
24b6670bc4 | ||
|
|
76661abbf5 | ||
|
|
e9dc9eff9b | ||
|
|
2f160743bc | ||
|
|
98616e772c | ||
|
|
bc014fec9b | ||
|
|
732598d9d2 | ||
|
|
2979acd5b8 | ||
|
|
fd20cd524e | ||
|
|
7b80ae42e1 | ||
|
|
b7012674c6 | ||
|
|
c76bd39280 | ||
|
|
09cd710f66 | ||
|
|
d9aadf9d98 | ||
|
|
86716b5ffb | ||
|
|
96e3aab3b4 | ||
|
|
72c78fe3ad | ||
|
|
abe746020b | ||
|
|
8e1c15419c | ||
|
|
ee47646cf7 | ||
|
|
32d9acdaa5 | ||
|
|
4eb3bd496b | ||
|
|
3c4f4d27d6 | ||
|
|
2060af8a92 | ||
|
|
21bf74a467 | ||
|
|
677833a277 | ||
|
|
0b5e4f2dd7 | ||
|
|
06a1f30350 | ||
|
|
c1ff241550 | ||
|
|
5717f75eac | ||
|
|
6b3b68a4e5 | ||
|
|
8bda2d0add | ||
|
|
bc02c9573c | ||
|
|
8167608f04 | ||
|
|
514e31aef9 | ||
|
|
20a31a6d38 | ||
|
|
4f0aa1bc02 | ||
|
|
be0ef6e594 | ||
|
|
93a8dbd31a | ||
|
|
cf931e8ddf | ||
|
|
510bfbf268 | ||
|
|
2f93bb969b | ||
|
|
27365c9f7b | ||
|
|
b1d2e188f5 | ||
|
|
e4f67df2a1 | ||
|
|
e094ea3d2a | ||
|
|
7515b745b5 | ||
|
|
0e902a7e71 | ||
|
|
2dfb443625 | ||
|
|
e6e7747ae1 | ||
|
|
d80ea6c0f5 | ||
|
|
ac6e3988a8 | ||
|
|
bfd98f3767 | ||
|
|
cc8bc1339f | ||
|
|
542d1dc600 | ||
|
|
1c66c88f95 | ||
|
|
dc880c672a | ||
|
|
073f38c68c | ||
|
|
6a6d13b075 | ||
|
|
9bb7e72c69 | ||
|
|
7436e01188 | ||
|
|
3d272d0f10 | ||
|
|
ee66a12dad | ||
|
|
47de85b012 | ||
|
|
f85b63a972 | ||
|
|
e630919ef8 | ||
|
|
2e3fd49b40 | ||
|
|
dd54af2c08 | ||
|
|
737bf411ff | ||
|
|
5070b1a6b5 | ||
|
|
c849da92cf | ||
|
|
6a4e7201fe | ||
|
|
ffa6dea452 | ||
|
|
30c1d31a99 | ||
|
|
6934a2d5c3 | ||
|
|
b9906ced9a | ||
|
|
5500b4fe35 | ||
|
|
2353f12cd6 | ||
|
|
1b8cab0f58 | ||
|
|
869c1d4ea4 | ||
|
|
9b938195a8 | ||
|
|
bb3c52821a | ||
|
|
81c8ae95e2 | ||
|
|
6098570ab7 | ||
|
|
d033c24fe5 | ||
|
|
4995e52dd6 | ||
|
|
c685a31056 | ||
|
|
c32ce3bb7b | ||
|
|
c0d8f904b3 | ||
|
|
8dba0dac9e | ||
|
|
d0bf4a5329 | ||
|
|
7b28ba6078 | ||
|
|
e6466c3c3a | ||
|
|
d96d3064d6 | ||
|
|
d4589ed7e3 | ||
|
|
5cfc52ea18 | ||
|
|
3fcacd8339 | ||
|
|
49fe13f22f | ||
|
|
4d27ba1bda | ||
|
|
b715ac8bf4 | ||
|
|
d96049416f | ||
|
|
1c4df785fd | ||
|
|
8f94c5efeb | ||
|
|
7cffa1ece7 | ||
|
|
1ac18d7b33 | ||
|
|
1111d2518b | ||
|
|
ba7416450e | ||
|
|
3b02d36acb | ||
|
|
c2aa9a5337 | ||
|
|
70fb181b7b | ||
|
|
e64f4e3f39 | ||
|
|
e4d518749f | ||
|
|
7dcca2c907 | ||
|
|
4a027b8a79 | ||
|
|
c2c6e6080e | ||
|
|
4f87ebdf0a | ||
|
|
09abec15b1 | ||
|
|
33d0d12bc8 | ||
|
|
f488869635 | ||
|
|
6382564727 | ||
|
|
7476b4c7db | ||
|
|
daf3e6a47a | ||
|
|
19b6cba398 | ||
|
|
5bd3d12c7b | ||
|
|
c9db74ebca | ||
|
|
f8a88cc1a4 | ||
|
|
4a081bf125 | ||
|
|
8a68a3e861 | ||
|
|
7a9dd9ad9c | ||
|
|
6c01d0f9d8 | ||
|
|
45a53ac168 | ||
|
|
dabb2790c9 | ||
|
|
c66c5ea53c | ||
|
|
0a98ba6985 | ||
|
|
bb8e491856 | ||
|
|
5590d31336 | ||
|
|
dc7e48dc53 | ||
|
|
371d357218 | ||
|
|
f22960ad59 | ||
|
|
34ead436b0 | ||
|
|
808d5a75ae | ||
|
|
55e897faac | ||
|
|
5a5dda21e4 | ||
|
|
f085655daa | ||
|
|
5cf9c07b73 | ||
|
|
9751089807 | ||
|
|
211eeea05d | ||
|
|
b2516117f5 | ||
|
|
2816b3edae | ||
|
|
242398c724 | ||
|
|
289583325d | ||
|
|
0f793ebd65 | ||
|
|
ce014044ea | ||
|
|
1064e531f0 | ||
|
|
dc3128fb3e | ||
|
|
51a3521834 | ||
|
|
d40aa7260f | ||
|
|
fc8c4063f2 | ||
|
|
f204c77ba3 | ||
|
|
7a8545273c | ||
|
|
6a9575e9f4 | ||
|
|
c13e79e9c3 | ||
|
|
62088259ae | ||
|
|
925ebcc06e | ||
|
|
a20eaf852f | ||
|
|
84a6a5235e | ||
|
|
8235b7b96d | ||
|
|
0376e0d711 | ||
|
|
6bd0682e8c | ||
|
|
e24c22f9be | ||
|
|
673a6bbe2c | ||
|
|
cf32a33984 | ||
|
|
f4ca8cd738 | ||
|
|
98c1bc276d | ||
|
|
629536b562 | ||
|
|
422109868d | ||
|
|
bcc7834650 | ||
|
|
1161e4f6c1 | ||
|
|
14435c24ac | ||
|
|
22ede79799 | ||
|
|
6cb3699ee9 | ||
|
|
6c65d3830e | ||
|
|
cdcf39fe82 | ||
|
|
1441042458 | ||
|
|
71403e5acd | ||
|
|
3d70bc722a | ||
|
|
b2f50da322 | ||
|
|
2a50c66df8 | ||
|
|
8de47c0a6e | ||
|
|
023391e22a | ||
|
|
a4ddfd404f | ||
|
|
7307e558cb | ||
|
|
47356f5221 | ||
|
|
c6f8950b64 | ||
|
|
58c8311d56 | ||
|
|
071f4eacde | ||
|
|
f96bdc578e | ||
|
|
e03a0fffa9 | ||
|
|
8e2c12f8d9 | ||
|
|
114420e8fd | ||
|
|
ba49b2c681 | ||
|
|
5391fc962a | ||
|
|
7cec7ae608 | ||
|
|
d6211af5bd | ||
|
|
ef114e31c2 | ||
|
|
fd74a03479 | ||
|
|
428bf634e9 | ||
|
|
c49f722e4f | ||
|
|
d4d95a43b6 | ||
|
|
8789d983ed | ||
|
|
10faa96bcf | ||
|
|
42d31b9ee6 | ||
|
|
c9dc9b4fe9 | ||
|
|
a345089c8b | ||
|
|
67c268e13d | ||
|
|
f13e02a1a9 | ||
|
|
d887ab126b | ||
|
|
1a7868159a | ||
|
|
c6a1c8e8c4 | ||
|
|
fba339f666 | ||
|
|
09d41a9708 | ||
|
|
ce85c8d986 | ||
|
|
4630a162af | ||
|
|
fde157ff50 | ||
|
|
51f875c02d | ||
|
|
f0957c838f | ||
|
|
f5bebef37f | ||
|
|
80a15089b4 | ||
|
|
cb35604ef5 | ||
|
|
61681bb1d6 | ||
|
|
8edf399631 | ||
|
|
d5ffd1432f | ||
|
|
e73bf03615 | ||
|
|
665fe0e01e | ||
|
|
1a226c4dc6 | ||
|
|
a866aa9c18 | ||
|
|
d9089b798c | ||
|
|
d34ebd4d1b | ||
|
|
716aa74004 | ||
|
|
2aae76c9bc | ||
|
|
5fc3ca0e23 | ||
|
|
5bb27109bf | ||
|
|
7406ab6017 | ||
|
|
08fccc4e77 | ||
|
|
c1d50e82e1 | ||
|
|
9777af7cb5 | ||
|
|
fd86035865 | ||
|
|
a8ec032553 | ||
|
|
66ee27c5fa | ||
|
|
17a737ca88 | ||
|
|
f30ff7a2fd | ||
|
|
c102828a99 | ||
|
|
cb0e631b85 | ||
|
|
75e7c0e50d | ||
|
|
62b2adab78 | ||
|
|
fc0cf1ff51 | ||
|
|
0f4d46671f | ||
|
|
048f9c0294 | ||
|
|
0529eed0c9 | ||
|
|
ca77842b5b | ||
|
|
8c169dc82b | ||
|
|
195342f7db | ||
|
|
cfaaef7860 | ||
|
|
e939d5e96e | ||
|
|
6fa8b7f5f1 | ||
|
|
a2d03c14ae | ||
|
|
c667a0e74c | ||
|
|
8123828113 | ||
|
|
72b8dbb45b | ||
|
|
9f4628cf0a | ||
|
|
ec4d24af91 | ||
|
|
7703875740 | ||
|
|
6442bb8a13 | ||
|
|
51373f59e2 | ||
|
|
6cc56879d3 | ||
|
|
f29d7c9252 | ||
|
|
2f7f53ed96 | ||
|
|
da89460830 | ||
|
|
9e006d42bb | ||
|
|
4c02bab4ee | ||
|
|
5800ed41f1 | ||
|
|
18b5b4901f | ||
|
|
368418cf56 | ||
|
|
94031a52a5 | ||
|
|
d67f91e7ed | ||
|
|
3e6cadf3d8 | ||
|
|
f37697c4fb | ||
|
|
0c5a76b391 | ||
|
|
69448c7329 | ||
|
|
8e9815fb91 | ||
|
|
bf1afcfe8a | ||
|
|
2980818f0d | ||
|
|
9da58dbaf0 | ||
|
|
4cdd7978cf | ||
|
|
40d81358f4 | ||
|
|
c7b62aed91 | ||
|
|
55d71659f8 | ||
|
|
c0e7d6d826 | ||
|
|
f809377de8 | ||
|
|
9767bd9697 | ||
|
|
3a55528552 | ||
|
|
56197ffe3a | ||
|
|
0f0d0c046c | ||
|
|
8d5b546763 | ||
|
|
19c9707d62 | ||
|
|
ecc4973645 | ||
|
|
79e004a040 | ||
|
|
3169f93cc2 | ||
|
|
c1a1a73599 | ||
|
|
48308db45b | ||
|
|
3f37e96f78 | ||
|
|
db1b0ccb79 | ||
|
|
df161ce672 | ||
|
|
4e21a5e557 | ||
|
|
72fe30892e | ||
|
|
19fa69811b | ||
|
|
0ddb4c625d | ||
|
|
d373105b32 | ||
|
|
36dc1d2f97 | ||
|
|
11fa2cb35d | ||
|
|
546f07156f | ||
|
|
7e7117632d | ||
|
|
954226da0d | ||
|
|
38a1291c5b | ||
|
|
998bf92ad4 | ||
|
|
974ba40f28 | ||
|
|
e57d8ba0ef | ||
|
|
6b79c6135f | ||
|
|
28b311b7ed | ||
|
|
dcda513901 | ||
|
|
72c400794c | ||
|
|
a747d8c2d5 | ||
|
|
a3aec6b939 | ||
|
|
042409f870 | ||
|
|
5b8f4f4069 | ||
|
|
d132d63c1d | ||
|
|
4374506981 | ||
|
|
ef8b936069 | ||
|
|
36e3bfffb4 | ||
|
|
91a38bdb60 | ||
|
|
f169a68319 | ||
|
|
ee886f98dd | ||
|
|
a3826cc6a7 | ||
|
|
ba33b832ba | ||
|
|
f6c017176b | ||
|
|
7a01b115bb | ||
|
|
1dc021e871 | ||
|
|
c9f916ebab | ||
|
|
ff627fd128 | ||
|
|
bba57f8d2b | ||
|
|
695873d35a | ||
|
|
15da19dcea | ||
|
|
4312a01707 | ||
|
|
ecd8f97d8b | ||
|
|
d5bdc1600b | ||
|
|
dfa077fd5f | ||
|
|
06abe63fb1 | ||
|
|
5155770213 | ||
|
|
9d507b09ca | ||
|
|
9c4a712dc7 | ||
|
|
f1d5bbb036 | ||
|
|
69ed0aebc3 | ||
|
|
549e56e220 | ||
|
|
450f4d9a5a | ||
|
|
6533a9793c | ||
|
|
2000cadb17 | ||
|
|
083c321efa | ||
|
|
f64c4a981f | ||
|
|
3ac8ce03bf | ||
|
|
66fca8710e | ||
|
|
1e245ece46 | ||
|
|
81efce03ba | ||
|
|
4e549dd426 | ||
|
|
52f74ff7e0 | ||
|
|
3c71b815f5 | ||
|
|
9efd48fe51 | ||
|
|
4609ee75b6 | ||
|
|
963ea4177e | ||
|
|
17e6940a42 | ||
|
|
315a9ceba3 | ||
|
|
a2bdeedb09 | ||
|
|
da5700d2d7 | ||
|
|
90e7f30247 | ||
|
|
3ccf6ba892 | ||
|
|
e50cd5b745 | ||
|
|
db77be5d72 | ||
|
|
c36870c23e | ||
|
|
e9be007040 | ||
|
|
9e400d9aa6 | ||
|
|
490c8dae75 | ||
|
|
3bcffe375d | ||
|
|
9f81a591e1 | ||
|
|
3db5306c70 | ||
|
|
45029dd084 | ||
|
|
b01cd30339 | ||
|
|
09329e1104 | ||
|
|
ab0fc2ecfa | ||
|
|
bf5d36d6bd | ||
|
|
a29527ec96 | ||
|
|
45e7ad8049 | ||
|
|
4d54663efd | ||
|
|
29d386cc51 | ||
|
|
ba1a67969b | ||
|
|
390ea5419e | ||
|
|
0fdeec7cc4 | ||
|
|
e34d883e50 | ||
|
|
507871687b | ||
|
|
ed58f62cd1 | ||
|
|
94bc4e7125 | ||
|
|
5832f7930d | ||
|
|
0066a20c22 | ||
|
|
774e4bfced | ||
|
|
054c7a76a4 | ||
|
|
c7f3b77aac | ||
|
|
a6a4620374 | ||
|
|
5148c62d1c | ||
|
|
6fc863a91e | ||
|
|
e066a154a1 | ||
|
|
d432edaed2 | ||
|
|
8f34f4e80b | ||
|
|
39b751acf5 | ||
|
|
bd5e8ba961 | ||
|
|
ed20327c41 | ||
|
|
991c68c394 | ||
|
|
2acc31a4e7 | ||
|
|
b9733e3dfa | ||
|
|
bb106bfce7 | ||
|
|
daf1388a6a | ||
|
|
8226f1fa75 | ||
|
|
e675512fa3 | ||
|
|
65e67b6c3e | ||
|
|
7612481570 | ||
|
|
f6c7cb5804 | ||
|
|
2201c9062f | ||
|
|
ca3da262da | ||
|
|
5847f92bef | ||
|
|
31ee1be81e | ||
|
|
6bccdd015f | ||
|
|
cecea318da | ||
|
|
8663ec6880 | ||
|
|
9b03f128aa | ||
|
|
8a51f97616 | ||
|
|
ee74ed9ce9 | ||
|
|
0f947c756e | ||
|
|
cae7949a48 | ||
|
|
be58b614e1 | ||
|
|
b0a01fa4b2 | ||
|
|
9734228001 | ||
|
|
9df1d44bc4 | ||
|
|
13d887028a | ||
|
|
83a8979309 | ||
|
|
75c29f1cb7 | ||
|
|
d9d15e41c7 | ||
|
|
d3598d5854 | ||
|
|
3a8aaee5d7 | ||
|
|
4fcf57d42c | ||
|
|
adb0891335 | ||
|
|
d21e719cc1 | ||
|
|
5807ab82c1 | ||
|
|
65cb04da63 | ||
|
|
312e3611b1 | ||
|
|
46acc62279 | ||
|
|
529b358c9b | ||
|
|
7fca04404e | ||
|
|
3a1cc6a2be | ||
|
|
5b76c91004 | ||
|
|
cf87837f7d | ||
|
|
5a0a7b907b | ||
|
|
6a2b1669b3 | ||
|
|
ca8264b3f4 | ||
|
|
b44ecd8819 | ||
|
|
987942959e | ||
|
|
91992b48c1 | ||
|
|
c9a335a6f9 | ||
|
|
b7ed159b50 | ||
|
|
c72961a52a | ||
|
|
afe6afca36 | ||
|
|
050acd239c | ||
|
|
24505ee4f5 | ||
|
|
63a249aba3 | ||
|
|
7bd94df2a0 | ||
|
|
761161a8e5 | ||
|
|
513579a7ee | ||
|
|
7165483d83 | ||
|
|
f8bcf219cb | ||
|
|
590506e306 | ||
|
|
9a5439c580 | ||
|
|
6b2f5fbb19 | ||
|
|
051c147b41 | ||
|
|
9111adf15f | ||
|
|
ba18b27371 | ||
|
|
2a287b2ae6 | ||
|
|
fc9040f715 | ||
|
|
0029022ef6 | ||
|
|
94f728d3fd | ||
|
|
d53ced7830 | ||
|
|
053d8c44c2 | ||
|
|
9f5767ea16 | ||
|
|
e8d76b0555 | ||
|
|
c2675600f6 | ||
|
|
6f087b4ec1 | ||
|
|
e94708606d | ||
|
|
c248f1a762 | ||
|
|
28402b0894 | ||
|
|
7dd98e99f9 | ||
|
|
dba195b396 | ||
|
|
88b153bc12 | ||
|
|
d4a47dc974 | ||
|
|
fe3ea6edfd | ||
|
|
6c8fc4846b | ||
|
|
b14a0e0dde | ||
|
|
e982f5076f | ||
|
|
54d9656f09 | ||
|
|
42188b9f49 | ||
|
|
49da324c5d | ||
|
|
9bf87697fd | ||
|
|
f368f5a9c4 | ||
|
|
eea85485e6 | ||
|
|
1a544b3b82 | ||
|
|
8b38fe9fe0 | ||
|
|
1bf4addf63 | ||
|
|
407e16e900 | ||
|
|
6e9fe3248a | ||
|
|
d8cf86fd6f | ||
|
|
f8aa4a9588 | ||
|
|
c249907846 | ||
|
|
57c1524a9a | ||
|
|
d8d82e2ba3 | ||
|
|
807b512ef7 | ||
|
|
b2f06b6777 | ||
|
|
d7adff9a65 | ||
|
|
b0d7e11d48 | ||
|
|
fc9cdb61f2 | ||
|
|
9c00492dc2 | ||
|
|
1a6babd199 | ||
|
|
1b693eed37 | ||
|
|
afb566b6b4 | ||
|
|
f870e9ed3e | ||
|
|
4bcf13cb58 | ||
|
|
50e2dcbcd5 | ||
|
|
6104bb98f1 | ||
|
|
946a6d6041 | ||
|
|
372c213c2c | ||
|
|
a5a79d3ab7 | ||
|
|
e6c5cfb703 | ||
|
|
7843eccae8 | ||
|
|
7ca153abd0 | ||
|
|
33b4774c49 | ||
|
|
c243481432 | ||
|
|
80873e4ea9 | ||
|
|
4e4a1f11e6 | ||
|
|
9bbe405cd0 | ||
|
|
c440a4c730 | ||
|
|
a1251371d7 | ||
|
|
7d702e8332 | ||
|
|
43d7c8d48c | ||
|
|
7423583508 | ||
|
|
08b0838f9a | ||
|
|
038d821a7c | ||
|
|
6a218814d3 | ||
|
|
905f89b0f5 | ||
|
|
14882bda78 | ||
|
|
781fa4634b | ||
|
|
cdb173fd6e | ||
|
|
466cb4be89 | ||
|
|
c39e2ffd56 | ||
|
|
17bf09e276 | ||
|
|
bc01f9f8fd | ||
|
|
c0870c5694 | ||
|
|
3b5174a2ea | ||
|
|
af6885f3e8 | ||
|
|
e01996095f | ||
|
|
5d86f7b6ba | ||
|
|
8d6ac6406d | ||
|
|
40ff54f67e | ||
|
|
cce7ac09d0 | ||
|
|
73a18891c5 | ||
|
|
fe22cedc1d | ||
|
|
fa09c7c8b2 | ||
|
|
15e28e3cc0 | ||
|
|
2cb4f6b1fc | ||
|
|
b17a483b85 | ||
|
|
7c3e5443ab | ||
|
|
f95a2851c8 | ||
|
|
2b2eee352f | ||
|
|
11569d8056 | ||
|
|
bdf87452b6 | ||
|
|
0c6bf81c24 | ||
|
|
f2fa26fb07 | ||
|
|
f5e212ff1e | ||
|
|
461e6562ca | ||
|
|
fd67d08402 | ||
|
|
e6411d11b1 | ||
|
|
dd81d947fc | ||
|
|
23b887c30e | ||
|
|
c4eae3f130 | ||
|
|
41a04a2849 | ||
|
|
ed1d34e678 | ||
|
|
f44487338d | ||
|
|
7aced85a31 | ||
|
|
fbe0e2d6eb | ||
|
|
6e34f0697c | ||
|
|
a835f9f0cb | ||
|
|
16715673c3 | ||
|
|
c48c74f173 | ||
|
|
f262348497 | ||
|
|
7185bcd51f | ||
|
|
28d05e2449 | ||
|
|
7fafa21a1b | ||
|
|
84f598e143 | ||
|
|
e30f8628db | ||
|
|
0be9c88106 | ||
|
|
e046fc1ac5 | ||
|
|
3a476ac493 | ||
|
|
e33ec0cf50 | ||
|
|
b4b70a988e | ||
|
|
e66b381070 | ||
|
|
771b598c09 | ||
|
|
cd44f13171 | ||
|
|
aa6b72ac87 | ||
|
|
a467fe5ed7 | ||
|
|
467411c6c3 | ||
|
|
2648b7ca54 | ||
|
|
de35c7024a | ||
|
|
9d219c163d | ||
|
|
f7434b5ec8 | ||
|
|
5ed3360c0b | ||
|
|
6f5974f875 | ||
|
|
56db1da3cf | ||
|
|
fef71f29c4 | ||
|
|
d46b66878a | ||
|
|
6cad80c4ad | ||
|
|
68779caa2e | ||
|
|
2a122ed283 | ||
|
|
17c5fdf0d5 | ||
|
|
0835fdd0d1 | ||
|
|
f6274445a2 | ||
|
|
3b0300b834 | ||
|
|
4fbf1fe780 | ||
|
|
dcf44fed58 | ||
|
|
7136dc1c72 | ||
|
|
0e4cedbc5e | ||
|
|
dc139bcc30 | ||
|
|
b204b183de | ||
|
|
ab788bc1e3 | ||
|
|
95b4c8d515 | ||
|
|
b025644525 | ||
|
|
9e87a60597 | ||
|
|
5a70bea67a | ||
|
|
2a95af3928 | ||
|
|
0a0ca380d3 | ||
|
|
4cfbf7f71c | ||
|
|
de43148341 | ||
|
|
0a2aab7d68 | ||
|
|
745821c420 | ||
|
|
57c4c754d0 | ||
|
|
4b5c437533 | ||
|
|
8d63b6a1ed | ||
|
|
245a8adbf9 | ||
|
|
4f7d98aace | ||
|
|
b0c693cc3a | ||
|
|
b2cca10e8b | ||
|
|
a84b2ab5bb | ||
|
|
4565342b05 | ||
|
|
0ad54cc2d1 | ||
|
|
865853da19 | ||
|
|
392ed706fd | ||
|
|
0ff0f25aaf | ||
|
|
c157960846 | ||
|
|
a5c00b5c81 | ||
|
|
472bbdb59f | ||
|
|
7877093713 | ||
|
|
8cb2e51407 | ||
|
|
d5cee81fb6 | ||
|
|
bca020bc4d | ||
|
|
5069f2844c | ||
|
|
252df81f59 | ||
|
|
7f89a4a26f | ||
|
|
40f4167894 | ||
|
|
0ef16989cd | ||
|
|
3df3d6f516 | ||
|
|
10395ef254 | ||
|
|
83854c28db | ||
|
|
fcbea2629c | ||
|
|
522360dcb7 | ||
|
|
26bc142cc2 | ||
|
|
a4eb8e11c3 | ||
|
|
9fd5d1db56 | ||
|
|
1d05b4c981 | ||
|
|
61f6535be8 | ||
|
|
7dd329b5ee | ||
|
|
b761904424 | ||
|
|
36105412b1 | ||
|
|
184b1b018c | ||
|
|
f3e1b85d82 | ||
|
|
626d012775 | ||
|
|
9ad9c0ec6a | ||
|
|
e13fed9fc6 | ||
|
|
eb6d093e56 | ||
|
|
979713c4db | ||
|
|
af1ea610ea | ||
|
|
d4d9190919 | ||
|
|
4d3d1a02a8 | ||
|
|
30c2aa96d6 | ||
|
|
4edb1f80b0 | ||
|
|
0a82459233 | ||
|
|
db87b0dfa5 | ||
|
|
e41d5c249f | ||
|
|
f82a779817 | ||
|
|
cd42cf7583 | ||
|
|
2d5980ff2a | ||
|
|
df8a8ea204 | ||
|
|
8957d33e49 | ||
|
|
d49c7a3adb | ||
|
|
28fe1e4c8f | ||
|
|
0c7f4e2168 | ||
|
|
4fdd09a262 | ||
|
|
d6878512c4 | ||
|
|
8b1b8250ff | ||
|
|
9dccbf747e | ||
|
|
08727e1938 | ||
|
|
7584820987 | ||
|
|
d572356642 | ||
|
|
3b5a2815a9 | ||
|
|
f3cf01df25 | ||
|
|
63e6e64ad3 | ||
|
|
e8d7b48bff | ||
|
|
12944d1ebd | ||
|
|
fa1ff6e393 | ||
|
|
98546b6e6a | ||
|
|
2fef6fd1fa | ||
|
|
20cf91f1dc | ||
|
|
2efa78d590 | ||
|
|
880af0671a | ||
|
|
62471e4531 | ||
|
|
b15f8535f8 | ||
|
|
7a3a4493da | ||
|
|
11078235c4 | ||
|
|
f3e05cd08a | ||
|
|
0ca3cabbe8 | ||
|
|
44a75c1291 | ||
|
|
4a4513a746 | ||
|
|
60ff8660de | ||
|
|
6fa0d671c0 | ||
|
|
f478d7c9f0 | ||
|
|
53e3e08d70 | ||
|
|
c4d1ccb6f5 | ||
|
|
e3520309fc | ||
|
|
27bf72372e | ||
|
|
ae4b1b17a9 | ||
|
|
94cb03f4b5 | ||
|
|
e691351976 | ||
|
|
3190de873e | ||
|
|
b22956bd99 | ||
|
|
42516206d9 | ||
|
|
fc4edde6e6 | ||
|
|
54cc04fd96 | ||
|
|
80062b6a62 | ||
|
|
99af79fcf3 | ||
|
|
11d87205d7 | ||
|
|
5866d414ce | ||
|
|
9a972b0b8a | ||
|
|
e6aeeea8c1 | ||
|
|
5d064aa1d7 | ||
|
|
34832d5942 | ||
|
|
e3b1179a21 | ||
|
|
f94a36613c | ||
|
|
efc3cc24f4 | ||
|
|
b47f8aaf70 | ||
|
|
94ca4607bc | ||
|
|
2dab1d3e6e | ||
|
|
825b0fb22f | ||
|
|
1cdb039ea2 | ||
|
|
7409cb3abb | ||
|
|
e8e8f70c27 | ||
|
|
e8a637498d | ||
|
|
e1195ac00a | ||
|
|
6cd9ccc37c | ||
|
|
25345302e8 | ||
|
|
eccd5e9801 | ||
|
|
ff355af9f2 | ||
|
|
5967f4b0d4 | ||
|
|
ff18618032 | ||
|
|
20f03c356c | ||
|
|
27fdc9e56e | ||
|
|
52d9578a19 | ||
|
|
f4c2938b41 | ||
|
|
9f703de5ec | ||
|
|
a327fd85e2 | ||
|
|
9d22a86ec8 | ||
|
|
29e0b194dd | ||
|
|
ae9cf13fc2 | ||
|
|
64ae67586a | ||
|
|
838c7a5e89 | ||
|
|
89bfc90f40 | ||
|
|
acad9f57f9 | ||
|
|
0d08dc410e | ||
|
|
ebb3fb96cd | ||
|
|
f31f23ff07 | ||
|
|
d2aa3d1868 | ||
|
|
c9e2fce94d | ||
|
|
8b0e76dd55 | ||
|
|
884618adfe | ||
|
|
6e2e36e7a0 | ||
|
|
9994df9601 | ||
|
|
98f7271ac8 | ||
|
|
087cd121b8 | ||
|
|
2d52527fb4 | ||
|
|
fe289e62b5 | ||
|
|
2845475e3f | ||
|
|
b307492487 | ||
|
|
d48284f7ea | ||
|
|
7e416797e9 | ||
|
|
5d54ca7477 | ||
|
|
b979b4e61a | ||
|
|
2527f7984a | ||
|
|
d9350b2362 | ||
|
|
bd0b903f1a | ||
|
|
f243c0df19 | ||
|
|
7482978953 | ||
|
|
77966689d4 | ||
|
|
cf43939d65 | ||
|
|
391ac4b351 | ||
|
|
e1e48aadd9 | ||
|
|
0681f206c4 | ||
|
|
d257c6f3d3 | ||
|
|
fa45c82cdc | ||
|
|
e805b58da6 | ||
|
|
943976d207 | ||
|
|
3a2e5a6ccd | ||
|
|
35ef036246 | ||
|
|
e09c3bbdd3 | ||
|
|
3b12076d4b | ||
|
|
cfcf78ae28 | ||
|
|
341ff9bf5c | ||
|
|
10d8ca30b0 | ||
|
|
4ebb5d099e | ||
|
|
1e82b66bf0 | ||
|
|
06a5e4273b | ||
|
|
e123e7b0b0 | ||
|
|
aeadc40c65 | ||
|
|
7ef418ec52 | ||
|
|
2ed52820b6 | ||
|
|
e8fd7484b6 | ||
|
|
ce5242cfe8 | ||
|
|
af947879d8 | ||
|
|
3ed112cde6 | ||
|
|
99c6a9eccd | ||
|
|
2029f6ea0a | ||
|
|
e984e1f30f | ||
|
|
f21260370f | ||
|
|
fdae75c99b | ||
|
|
a0489f2a0d | ||
|
|
0123eacbdb | ||
|
|
53401b6aa7 | ||
|
|
9a5139f452 | ||
|
|
2ee0c8c228 | ||
|
|
c53562cc9c | ||
|
|
ec5d7c2e5c | ||
|
|
d6fc258485 | ||
|
|
f953612695 | ||
|
|
2ab93acca8 | ||
|
|
326c6c496e | ||
|
|
9f7f50664c | ||
|
|
f6f1436123 | ||
|
|
c3c519419d | ||
|
|
e569a80b72 | ||
|
|
284f437c1a | ||
|
|
1fd44a9958 | ||
|
|
cad34742f6 | ||
|
|
323359b3c8 | ||
|
|
35db8b45f0 | ||
|
|
50ae815ceb | ||
|
|
1a4389c90d | ||
|
|
fdaa5ce1da | ||
|
|
09d9936aed | ||
|
|
b3f6109b1c | ||
|
|
5fb3ffc240 | ||
|
|
360db252bb | ||
|
|
0b6e290271 | ||
|
|
7f0174e6db | ||
|
|
a25dad6c2e | ||
|
|
6191a49ed3 | ||
|
|
6252b075bc | ||
|
|
7face138fd | ||
|
|
382b83b093 | ||
|
|
691687d1bc | ||
|
|
5814b80a72 | ||
|
|
e147fbb1fa | ||
|
|
b9e256adfa | ||
|
|
3b7bf04e22 | ||
|
|
43408a724c | ||
|
|
5fbd5bf9e2 | ||
|
|
5e87828b29 | ||
|
|
9066cedc29 | ||
|
|
aa1cf0b228 | ||
|
|
06a6a4408f | ||
|
|
d5619d2b9d | ||
|
|
2f6ac42efe | ||
|
|
0bba3dd83d | ||
|
|
abe60b62e6 | ||
|
|
555b7df986 | ||
|
|
b3786700e6 | ||
|
|
ce9643d21b | ||
|
|
4a5cb7f2f5 | ||
|
|
42a7e902e6 | ||
|
|
aebe080e85 | ||
|
|
c316284924 | ||
|
|
8d98b228ab | ||
|
|
5b4c42ff05 | ||
|
|
a596a4551a | ||
|
|
0968f96982 | ||
|
|
5931e13b9c | ||
|
|
415c768ae4 | ||
|
|
b4c8bf21d5 | ||
|
|
5fe5db603d | ||
|
|
9f7dd7f5d4 | ||
|
|
e6d32aab7b | ||
|
|
08bd6d963c | ||
|
|
ff05fb14a6 | ||
|
|
22d942b705 | ||
|
|
0526372f28 | ||
|
|
f99051906a | ||
|
|
d1f7fd8bfd | ||
|
|
fc1436a96d | ||
|
|
d21568497b | ||
|
|
df4beef060 | ||
|
|
a52f195d41 | ||
|
|
419019a656 | ||
|
|
42b5635485 | ||
|
|
a8fc5b01f3 | ||
|
|
ead841d844 | ||
|
|
67d7930aef | ||
|
|
6f69995f4e | ||
|
|
05252fa239 | ||
|
|
1377439bb0 | ||
|
|
407123a280 | ||
|
|
750dd590c8 | ||
|
|
44112a9d18 | ||
|
|
b220bf0d99 | ||
|
|
d0d93d7070 | ||
|
|
4117961236 | ||
|
|
68a3d71ee6 | ||
|
|
bf5d741f0d | ||
|
|
55a33bc408 | ||
|
|
3ec35ed119 | ||
|
|
3d8d6953ec | ||
|
|
528db67c34 | ||
|
|
b847e962aa | ||
|
|
bbb9a3c63b | ||
|
|
322cebc48c | ||
|
|
1cceb3d880 | ||
|
|
effc64db9a | ||
|
|
7e5bd5f2c1 | ||
|
|
e32cc4d1af | ||
|
|
09a3cd850e | ||
|
|
b0c876019a | ||
|
|
6725f870d2 | ||
|
|
0e5adc1f0a | ||
|
|
57ebb93dc0 | ||
|
|
05dc0bfa1d | ||
|
|
2d0264116c | ||
|
|
3938550ea8 | ||
|
|
9f0c567794 | ||
|
|
8672fcd2bb | ||
|
|
3f2a92e801 | ||
|
|
771e43583a | ||
|
|
9353d5c1c4 | ||
|
|
5e462f0f02 | ||
|
|
a25f6fec9f | ||
|
|
519edce0ed | ||
|
|
0bc7702d95 | ||
|
|
18be0d6d26 | ||
|
|
1d4a435f20 | ||
|
|
34e46fc6d3 | ||
|
|
50956c51f7 | ||
|
|
dd7bb28b6a | ||
|
|
8516f41ba8 | ||
|
|
15c3cc60f6 | ||
|
|
716bca211b | ||
|
|
8179813fe1 | ||
|
|
d355de509b | ||
|
|
b04a2d4c08 | ||
|
|
6d3232a4f0 | ||
|
|
2753075180 | ||
|
|
d0166b25e4 | ||
|
|
73ee657d74 | ||
|
|
45913e5ee8 | ||
|
|
e6369820a9 | ||
|
|
22a5b339f7 | ||
|
|
2cea3b6435 | ||
|
|
5d2d06fb3e | ||
|
|
0dd7bc7fb9 | ||
|
|
0b0005337c | ||
|
|
d26fb02bb9 | ||
|
|
af683835d9 | ||
|
|
c43647ca86 | ||
|
|
6d02e70025 | ||
|
|
5498c6f87d | ||
|
|
11f59bc3ac | ||
|
|
94cb7de79f | ||
|
|
838f45775b | ||
|
|
1c1422e4b5 | ||
|
|
cd8ca6fc62 | ||
|
|
b7a0a9d7c2 | ||
|
|
7822ab113a | ||
|
|
e250a91f09 | ||
|
|
92a65dcda5 | ||
|
|
4b129d94e4 | ||
|
|
e7960d1d44 | ||
|
|
95589307cd | ||
|
|
20a0e4f3e0 | ||
|
|
6a9213da64 | ||
|
|
7a89e3cf33 | ||
|
|
64607df929 | ||
|
|
a62a1012fa | ||
|
|
14efd0b2f9 | ||
|
|
7ad2192df8 | ||
|
|
3cb5cbd8d5 | ||
|
|
cc9011cd68 | ||
|
|
dc3d89008d | ||
|
|
1893642187 | ||
|
|
a9ece5772d | ||
|
|
cf34716a57 | ||
|
|
1337831061 | ||
|
|
757e72100d | ||
|
|
a75b819858 | ||
|
|
da4a0f09ed | ||
|
|
87d847a074 | ||
|
|
84711beec0 | ||
|
|
f3cf58c8ff | ||
|
|
cf40497e6e | ||
|
|
dfebc4b78d | ||
|
|
15f41a2e7c | ||
|
|
ad6e55ca17 | ||
|
|
6b466d217a | ||
|
|
00dcb304c7 | ||
|
|
c6fb3d6f41 | ||
|
|
ac3143811f | ||
|
|
7e27dd7678 | ||
|
|
c2508296a5 | ||
|
|
a9b50ce6fc | ||
|
|
eac98a6d4d | ||
|
|
7e2b2a9a02 | ||
|
|
353de471eb | ||
|
|
85fc20b52d | ||
|
|
cc25a781f8 | ||
|
|
fc3012ba72 | ||
|
|
d93a92c1c8 | ||
|
|
f7f795f58a | ||
|
|
2700f8cdd2 | ||
|
|
6310de0d20 | ||
|
|
218794be77 | ||
|
|
af71ae649b | ||
|
|
9bc72c1a06 | ||
|
|
8d7c157751 | ||
|
|
558a66fbe5 | ||
|
|
f95b414d22 | ||
|
|
e793a1e1aa | ||
|
|
b76010cb5a | ||
|
|
52475df783 | ||
|
|
1f3f32d377 | ||
|
|
3f5ba10354 | ||
|
|
25f4a018d9 | ||
|
|
a11a279c00 | ||
|
|
fd4fdb31b5 | ||
|
|
1921796d6d | ||
|
|
543a2b9dc7 | ||
|
|
dd23e03342 | ||
|
|
5307c74f85 | ||
|
|
d701c406e2 | ||
|
|
3ba56a0a65 | ||
|
|
4adafb6d1e | ||
|
|
4453a51211 | ||
|
|
14429d2943 | ||
|
|
1a62a7831b | ||
|
|
242e35c212 | ||
|
|
ea763fdfd5 | ||
|
|
e762b7ff48 | ||
|
|
298068b2b9 | ||
|
|
cb4120ec4b | ||
|
|
5cfbb87bee | ||
|
|
9e472ed83c | ||
|
|
ebca753fc4 | ||
|
|
548f45cd56 | ||
|
|
8ffabf1813 | ||
|
|
1f40d4f941 | ||
|
|
41582045d0 | ||
|
|
fd9e3fc03a | ||
|
|
8c42b2bdb4 | ||
|
|
7b1787fdbb | ||
|
|
71fee0025d | ||
|
|
1204cf1ba0 | ||
|
|
7bd8d8c3ae | ||
|
|
2c4d5fa38d | ||
|
|
bedb2d943e | ||
|
|
a3640bd9bf | ||
|
|
7c0b9ffe06 | ||
|
|
161c7d30ca | ||
|
|
4ff6e792cd | ||
|
|
af5df890a5 | ||
|
|
9ba011003a | ||
|
|
bb168d35a8 | ||
|
|
3306d30094 | ||
|
|
6516e0dfd2 | ||
|
|
00a396014b | ||
|
|
13356047dc | ||
|
|
8a6488b067 | ||
|
|
1c2ea56f42 | ||
|
|
1d7ae300e2 | ||
|
|
6013e186ed | ||
|
|
207d3d3340 | ||
|
|
5a6cde1446 | ||
|
|
63f7d826bc | ||
|
|
ff8773f6bd | ||
|
|
a868cb97d9 | ||
|
|
915d73e6f2 | ||
|
|
5f4f6e37b5 | ||
|
|
9c350311e8 | ||
|
|
3c6ba72a2a | ||
|
|
816442f5f0 | ||
|
|
3b51d18ce7 | ||
|
|
6696b6661a | ||
|
|
8c87478636 | ||
|
|
d870b072d7 | ||
|
|
2ea2af7d2a | ||
|
|
f737ea96f3 | ||
|
|
05f90394db | ||
|
|
c24b0c6bb4 | ||
|
|
e07a4dc7ba | ||
|
|
fc6748a46b | ||
|
|
7697c46652 | ||
|
|
ed52e5afd1 | ||
|
|
33a5b84181 | ||
|
|
c09a407f4c | ||
|
|
d35784ec61 | ||
|
|
53e012f296 | ||
|
|
2a9d0a5e7d | ||
|
|
474f4572f2 | ||
|
|
bf57cb209f | ||
|
|
9bc41c1709 | ||
|
|
fe10b8650f | ||
|
|
3a311c9584 | ||
|
|
d1106f53e0 | ||
|
|
a3a1bba5ef | ||
|
|
028d66befc | ||
|
|
bb59cd5742 | ||
|
|
604e3068b2 | ||
|
|
27f1d3b704 | ||
|
|
d007623347 | ||
|
|
6a5cf7a1fa | ||
|
|
3adfe249b0 | ||
|
|
923893e160 | ||
|
|
256e5360d4 | ||
|
|
304c597a2f | ||
|
|
f86d3a69d2 | ||
|
|
d7c8adfd82 | ||
|
|
55cd069043 | ||
|
|
3ca0e9c420 | ||
|
|
1dd4323613 | ||
|
|
d78916f85f | ||
|
|
1840d15397 | ||
|
|
b98d1216b1 | ||
|
|
27db727321 | ||
|
|
3f6b1f6ccb | ||
|
|
6d633b372a | ||
|
|
91352e855a | ||
|
|
8bb9b594cf | ||
|
|
6d2fd2e641 | ||
|
|
422fbcb0b7 | ||
|
|
afce106186 | ||
|
|
f21c8154ed | ||
|
|
3988a648d6 | ||
|
|
1b632894d3 | ||
|
|
5e128f89f6 | ||
|
|
fff0b15ae5 | ||
|
|
a7e14f1093 | ||
|
|
94eeaeb8d3 | ||
|
|
64191e8303 | ||
|
|
21cfb71617 | ||
|
|
806457063f | ||
|
|
b9213b73bd | ||
|
|
d7f0102aa2 | ||
|
|
f09e61a59a | ||
|
|
d426aaa88a | ||
|
|
19e45389e1 | ||
|
|
6d2389945b | ||
|
|
14c48253f6 | ||
|
|
e5ff25b92d | ||
|
|
5c88888e02 | ||
|
|
10057de9b3 | ||
|
|
cc88ebd2b9 | ||
|
|
6baedf909d | ||
|
|
f39d9d6f1b | ||
|
|
ab61a95f83 | ||
|
|
10ceed30c6 | ||
|
|
2b9aa94f3a | ||
|
|
848fb975ed | ||
|
|
d7f59dac84 | ||
|
|
dd47e615ee | ||
|
|
8f2f7ea1a5 | ||
|
|
80a8efd8ce | ||
|
|
d9dce77ef4 | ||
|
|
ce7053a1fe | ||
|
|
0db1530171 | ||
|
|
3745504107 | ||
|
|
57533fd831 | ||
|
|
f57a0d4d6b | ||
|
|
22772ca33e | ||
|
|
dba6ff1d51 | ||
|
|
40146dedaf | ||
|
|
387b822f53 | ||
|
|
b9a3563e5b | ||
|
|
3d6468326a | ||
|
|
298e37ec53 | ||
|
|
5b137c457b | ||
|
|
5218a3fbac | ||
|
|
4569cb432d | ||
|
|
611e598756 | ||
|
|
937d79d28f | ||
|
|
23c2a771d3 | ||
|
|
58a890e836 | ||
|
|
6a869e120c | ||
|
|
ae7c298b1a | ||
|
|
53bfe12ac1 | ||
|
|
140ea683a6 | ||
|
|
0634a97598 | ||
|
|
3479c794de | ||
|
|
89cad116f7 | ||
|
|
19c84eb694 | ||
|
|
eae390acf5 | ||
|
|
10567afbb9 | ||
|
|
51bad3bf3c | ||
|
|
9134d8841d | ||
|
|
e9a026c131 | ||
|
|
9a2fd0e2b2 | ||
|
|
522f7e6844 | ||
|
|
cb4f46decc | ||
|
|
81256279a8 | ||
|
|
039bd1ddc0 | ||
|
|
0791d4797f | ||
|
|
6a06142e1e | ||
|
|
ef53dca062 | ||
|
|
6ce761edda | ||
|
|
d8fd218409 | ||
|
|
edc2310599 | ||
|
|
b1cd13d629 | ||
|
|
b81940351f | ||
|
|
a42e99c4aa | ||
|
|
ff40b521b7 | ||
|
|
85392496e7 | ||
|
|
29cae9975e | ||
|
|
170d6b28f8 | ||
|
|
9a8b404054 | ||
|
|
41af5187aa | ||
|
|
a844ca161f | ||
|
|
e09efba313 | ||
|
|
96a0dbea2d | ||
|
|
5b3b5271ad | ||
|
|
d7d13c12fe | ||
|
|
54220d0e71 | ||
|
|
4a2e3586f1 | ||
|
|
f808e85da9 | ||
|
|
1671d1f580 | ||
|
|
7de1bf9d95 | ||
|
|
7368b0cefb | ||
|
|
4af43d676a | ||
|
|
67dc848b2d | ||
|
|
7ec8f0d26b | ||
|
|
eaf08a9971 | ||
|
|
5bdb9e972e | ||
|
|
d4d87054c4 | ||
|
|
0f93929544 | ||
|
|
1c0e794f87 | ||
|
|
f9bce5a5f9 | ||
|
|
797ae096c8 | ||
|
|
6d76918424 | ||
|
|
2aced893c6 | ||
|
|
f0373cd789 | ||
|
|
2f88dc64fc | ||
|
|
781ca77794 | ||
|
|
c6e453fb00 | ||
|
|
a40b3dd377 | ||
|
|
096b3534d8 | ||
|
|
5324244c55 | ||
|
|
993f1dc853 | ||
|
|
d8a4e9e1ab | ||
|
|
b3ffd33507 | ||
|
|
c93870316c | ||
|
|
fc9906624e | ||
|
|
ba6209ba54 | ||
|
|
f9769a73fe | ||
|
|
3a2f56cb95 | ||
|
|
a4d33879dc | ||
|
|
e2a91d1ea9 | ||
|
|
f30f80d117 | ||
|
|
266274135e | ||
|
|
a10439b67c | ||
|
|
0fd8d0e2bf | ||
|
|
47e2707fd3 | ||
|
|
f7bb4a7d60 | ||
|
|
6102a31a31 | ||
|
|
1692c3b102 | ||
|
|
ac60725d2a | ||
|
|
1542f73fa5 | ||
|
|
70a22187f7 | ||
|
|
347e598715 | ||
|
|
a737810c50 | ||
|
|
92654a71fb | ||
|
|
18615640e0 | ||
|
|
b8c80a2310 | ||
|
|
c34c98386e | ||
|
|
d8a3d2793f | ||
|
|
360b0d9997 | ||
|
|
356f46aaf4 | ||
|
|
87ac0507d9 | ||
|
|
8dcc114873 | ||
|
|
8cc9aeba4a | ||
|
|
ba0823c38c |
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/packages/node_modules/** linguist-generated=false
|
||||
34
.github/ISSUE_TEMPLATE.md
vendored
Normal file
34
.github/ISSUE_TEMPLATE.md
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
<!--
|
||||
## Before you hit that Submit button....
|
||||
|
||||
This issue tracker is for problems with the Node-RED runtime, the editor or the core nodes.
|
||||
|
||||
If your issue is:
|
||||
- a general 'how-to' type question,
|
||||
- a feature request or suggestion for a change,
|
||||
- or problems with 3rd party (`node-red-contrib-`) nodes
|
||||
|
||||
please use the [Node-RED Forum](https://discourse.nodered.org) or [slack team](https://nodered.org/slack).
|
||||
|
||||
You could also consider asking a question on [Stack Overflow](https://stackoverflow.com/questions/tagged/node-red) and tag it `node-red`.
|
||||
|
||||
That way the whole Node-RED user community can help, rather than rely on the core development team.
|
||||
|
||||
## So you have a real issue to raise...
|
||||
|
||||
To help us understand the issue, please fill-in as much of the following information as you can:
|
||||
-->
|
||||
|
||||
### What are the steps to reproduce?
|
||||
|
||||
### What happens?
|
||||
|
||||
### What do you expect to happen?
|
||||
|
||||
### Please tell us about your environment:
|
||||
|
||||
- [ ] Node-RED version:
|
||||
- [ ] node.js version:
|
||||
- [ ] npm version:
|
||||
- [ ] Platform/OS:
|
||||
- [ ] Browser:
|
||||
34
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
34
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
<!--
|
||||
## Before you hit that Submit button....
|
||||
|
||||
Please read our [contribution guidelines](https://github.com/node-red/node-red/blob/master/CONTRIBUTING.md)
|
||||
before submitting a pull-request.
|
||||
|
||||
## Types of changes
|
||||
|
||||
What types of changes does your code introduce?
|
||||
Put an `x` in the boxes that apply
|
||||
-->
|
||||
|
||||
- [ ] Bugfix (non-breaking change which fixes an issue)
|
||||
- [ ] New feature (non-breaking change which adds functionality)
|
||||
|
||||
<!--
|
||||
If you want to raise a pull-request with a new feature, or a refactoring
|
||||
of existing code, it **may well get rejected** if it hasn't been discussed on
|
||||
the [forum](https://discourse.nodered.org) or
|
||||
[slack team](https://nodered.org/slack) first.
|
||||
|
||||
-->
|
||||
|
||||
## Proposed changes
|
||||
|
||||
<!-- Describe the nature of this change. What problem does it address? -->
|
||||
|
||||
## Checklist
|
||||
<!-- Put an `x` in the boxes that apply -->
|
||||
|
||||
- [ ] 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 mailing list/slack team.
|
||||
- [ ] I have run `grunt` to verify the unit tests pass
|
||||
- [ ] I have added suitable unit tests to cover the new/changed functionality
|
||||
5
.gitignore
vendored
5
.gitignore
vendored
@@ -17,3 +17,8 @@ node_modules
|
||||
public
|
||||
locales/zz-ZZ
|
||||
nodes/core/locales/zz-ZZ
|
||||
!packages/node_modules
|
||||
packages/node_modules/@node-red/editor-client/public
|
||||
!test/**/node_modules
|
||||
docs
|
||||
!packages/node_modules/**/docs
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
/Gruntfile.js
|
||||
/.git/*
|
||||
/lib/*
|
||||
*.backup
|
||||
/public/*
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
.settings
|
||||
.jshintignore
|
||||
.jshintrc
|
||||
.project
|
||||
.tern-project
|
||||
.travis.yml
|
||||
.git
|
||||
27
.travis.yml
27
.travis.yml
@@ -1,21 +1,10 @@
|
||||
sudo: false
|
||||
language: node_js
|
||||
env:
|
||||
- CXX="g++-4.8"
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- g++-4.8
|
||||
- gcc-4.8
|
||||
node_js:
|
||||
- "8"
|
||||
- "7"
|
||||
- "6"
|
||||
- "4"
|
||||
script:
|
||||
- istanbul cover ./node_modules/.bin/grunt --report lcovonly && istanbul report text && ( cat coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js || true ) && rm -rf coverage
|
||||
before_script:
|
||||
- npm install -g istanbul
|
||||
- npm install coveralls
|
||||
matrix:
|
||||
include:
|
||||
- node_js: "10"
|
||||
script:
|
||||
- ./node_modules/.bin/grunt && istanbul report text && ( cat coverage/lcov.info | $(npm get prefix)/bin/coveralls || true ) && rm -rf coverage
|
||||
before_script:
|
||||
- npm install -g istanbul coveralls
|
||||
- node_js: "8"
|
||||
|
||||
578
CHANGELOG.md
578
CHANGELOG.md
@@ -1,3 +1,545 @@
|
||||
#### 0.20.0-beta.2: Beta Release
|
||||
|
||||
- Split Node-RED internals into multiple sub-modules
|
||||
|
||||
Editor
|
||||
|
||||
- Allow the editor to use a custom admin api url root
|
||||
- Improve performance of Flow Diff dialog - @TothiViseo #1989
|
||||
- Add 'open project' option to Projects Welcome dialog
|
||||
- Add 'type already registered' check in palette editor
|
||||
- Handle missing tab.disabled property
|
||||
- Handle missing wires prop and string x/y props on import
|
||||
- Add RED.notifications.hide flag - for UI testing
|
||||
- Improve alignment of node label edit inputs
|
||||
- Show arrow-in node when invalid font-awesome icon name was specified for default icon
|
||||
- Add ability to delete context values from sidebar
|
||||
- Allow copy-to-clipboard copy whole tabs
|
||||
- Make disabled flows more obvious in editor
|
||||
- Allow import/export from file in editor
|
||||
- Allow config nodes to be selected in sidebar and deleted
|
||||
- Show port label of subflow with input port
|
||||
- Support ctrl-click selection of flow tabs
|
||||
- Allow left-hand node button to act as toggle
|
||||
- Support dbl-click in tab bar to add new flow in position
|
||||
- Fix duplicate subflow detection on import
|
||||
- Add import notification with info on what has been imported Closes #1862
|
||||
- Show error details when trying to import invalid json
|
||||
- Show default icon when non-existent font-awesome icon was specified
|
||||
- Add configurable option for showing node label
|
||||
- Avoid http redirects as Safari doesn't reuse Auth header Fixes #1903
|
||||
- Tidy up ace tooltip styling
|
||||
- Add event log to editor
|
||||
- Add tooltips to multiple editor elements
|
||||
- Allow palette to be hidden
|
||||
- Add node module into to sidebar and palette popover
|
||||
- Mark all newly imported nodes as changed
|
||||
- Allow a node label to be hidden
|
||||
- Add markdown formatting toolbar
|
||||
- Add markdown toolbar to various editors
|
||||
- Fix i18n handling for ja-JP locale on Safari/MacOS
|
||||
- Add node body tooltip
|
||||
- Decrease opacity of flow-navigator
|
||||
- Update tooltip style
|
||||
- Update ACE to 1.4.1-src-min-noconflict
|
||||
- Cache node locales by language
|
||||
- Show icon element with either icon image or fa-icon
|
||||
- Added font-awesome icons to user defined icon
|
||||
- Update info side bar with node description section
|
||||
- One-click search of config node users
|
||||
- Redesign node edit dialog to tabbed style
|
||||
- Add 'restart flows' option to deploy menu
|
||||
- Add node description property UI
|
||||
|
||||
|
||||
Runtime
|
||||
|
||||
- Allow a project to be loaded from cmdline
|
||||
- Handle lookup of undefined property in Global context Fixes #1978
|
||||
- Refuse to enable Manage Palette if npm too old
|
||||
- Remove restriction on upgrading non-local modules
|
||||
- Remove deprecated Buffer constructor usage Fixes #1709
|
||||
- Update httpServerOptions doc in settings.js
|
||||
- Exclude non-testable .js files from the unit tests
|
||||
- Add --safe mode flag to allow starting without flows running
|
||||
- Add setting-defined accessToken for automated access to the adminAPI - #1789
|
||||
|
||||
Nodes
|
||||
|
||||
- Move all core node EN help to their own locale files - #1990
|
||||
- CSV: better regex for number detection
|
||||
- Debug: hide button if not configured to send to sidebar
|
||||
- Delay: report queue activity when in by-topic mode
|
||||
- Delay: add msg.flush mode
|
||||
- Exec: Preserve existing properties on msg object
|
||||
- File: remove CR/LF from incoming filename
|
||||
- Function: create custom ace javascript mode to handle ES6 Fixes #1911
|
||||
- Function: add env.get
|
||||
- HTTP Request: Add http-proxy config #1913
|
||||
- HTTP Request: add msg.redirectList to output
|
||||
- HTTP Request: add msg.requestTimeout option for per-message setting - @natcl #1959
|
||||
- MQTT: add auto-detect and base64 output to mqtt node Fixes #1912 - @DurandA
|
||||
- MQTT: only unsubscribe node that is being removed
|
||||
- Sentiment: move to node-red-node-sentiment
|
||||
- Switch: add missing edit dialog icon
|
||||
- Tail: move to node-red-node-tail
|
||||
- TCPGet: clear status if user changes target per message
|
||||
- Template: tidy up edit dialog
|
||||
- UDP: more resilient binding to correct port for udp, give input side priority
|
||||
- Split/Join: add msg.reset to info panel
|
||||
- Split/Join: reset join without sending part array
|
||||
- Watch: add msg.filename so can feed direct to file in node
|
||||
- WebSocket: preserve \_session on msg but don't send as part of wholemsg
|
||||
|
||||
|
||||
#### 0.19.5: Maintenance Release
|
||||
|
||||
- Recognize pip installs of RPi.GPIO (#1934)
|
||||
- Merge pull request #1941 from node-red-hitachi/master-batch
|
||||
- Merge pull request #1931 from node-red-hitachi/master-typedinput
|
||||
- Set min value of properties and spinners for batch
|
||||
- Fix that unnecessary optionMenu remains
|
||||
- Merge pull request #1894 from node-red-hitachi/fix-overlapping-file-node-execution
|
||||
- Merge pull request #1924 from imZack/patch-1
|
||||
- Add missing comma
|
||||
- Do not disable context sidebar during node edit Fixes #1921
|
||||
- Don't allow virtual links to be spliced Fixes #1920
|
||||
- Merge project package changes to avoid overwritten changes
|
||||
- Handle manually added project deps that are unused Fixes #1908
|
||||
- update close & input handling of File node
|
||||
- make close handler argument only one
|
||||
- Merge pull request #1907 from amilajack/patch-2
|
||||
- Change repo badge to point to master branch
|
||||
- invoke callbacks if async handler is specified
|
||||
- Merge pull request #1891 from camlow325/resolve-example-path-for-windows-support
|
||||
- Merge pull request #1900 from kazuhitoyokoi/master-addtestcases4settings.js
|
||||
- wait closing while pending messages exist
|
||||
- Add test cases for red/api/editor/settings.js
|
||||
- Ensure all palette categories are opened properly Closes #1893
|
||||
- Resolve path when sending example file for Windows support
|
||||
- fix multiple input message processing of file node
|
||||
|
||||
#### 0.19.4: Maintenance Release
|
||||
|
||||
- Fix race condition in non-cache lfs context Fixes #1888
|
||||
- LocalFileSystem Context: Remove extra flush code
|
||||
- Prevent race condition in caching mode of lfs context (#1889)
|
||||
- Allow context store name to be provided in the key
|
||||
- Switch node: only use promises when absolutely necessary
|
||||
- Fix dbl-click handling on webkit-based browsers
|
||||
- Ensure context.flow/global cannot be deleted or enumerated
|
||||
- Handle context.get with multiple levels of unknown key Fixes #1883
|
||||
- Fix global.get("foo.bar") for functionGlobalContext set values
|
||||
- Fix node color bug (#1877)
|
||||
- Merge pull request #1857 from cclauss/patch-1
|
||||
- Define raw_input() in Python 3 & fix time.sleep()
|
||||
|
||||
#### 0.19.3: Maintenance Release
|
||||
|
||||
- Split node - fix complete to send msg for k/v object
|
||||
- Remove unused Join node merged object key typed input
|
||||
- Set the JavaScript editor to full-screen
|
||||
- Filter global modules installed locally
|
||||
- Add svg to permitted icon extension list
|
||||
- Debug node - indicate status all the time if selected to do so
|
||||
- pi nodes - increase test coverage slightly
|
||||
- TCP-request node - only write payload
|
||||
- JSON schema: perform validation when obj -> obj or str -> str
|
||||
- JSON schema: add draft-06 support (via $schema keyword)
|
||||
- Mqtt proxy configuration for websocket connection, #1651.
|
||||
- Allows MQTT Shared Subscriptions for MQTT-In core node
|
||||
- Fix use of HTML tag or CSS class specification as icon of typedInput
|
||||
|
||||
#### 0.19.2: Maintenance Release
|
||||
|
||||
- Ensure node default colour is used if palette.theme has no match
|
||||
- fix lost messages / properties in TCPRequest Node; closes #1863 (#1864)
|
||||
- Fix typo in template.html
|
||||
- Improve error reporting from context plugin loading
|
||||
- Prevent no-op edit of node marking as changed due to icon
|
||||
- Change node must handle empty rule set
|
||||
|
||||
#### 0.19.1: Maintenance Release
|
||||
|
||||
- Pull in latest twitter node
|
||||
- Handle windows paths for context storage
|
||||
- Handle persisting objects with circular refs in context
|
||||
- Ensure js editor can expand to fill available space
|
||||
- Add example localfilesystem contextStorage to settings
|
||||
- Fix template node handling of nested context tags
|
||||
|
||||
#### 0.19: Milestone Release
|
||||
|
||||
Editor
|
||||
|
||||
- Add editorTheme.palette.theme to allow overriding colours
|
||||
- Index all node properties when searching Fixes #1446
|
||||
- Handle NaN and Infinity properly in debug sidebar Fixes #1778 #1779
|
||||
- Prevent horizontal scroll when palette name cannot wrap
|
||||
- Ignore middle-click on node/ports to enable panning
|
||||
- Better wire layout when looping back
|
||||
- fix appearence of retry button of remote branch management dialog
|
||||
- Handle releasing ctrl when using quick-add node dialog
|
||||
- Add $env function to JSONata expressions
|
||||
- Widen support for env var to use ${} or $() syntax
|
||||
- Add env-var support to TypedInput
|
||||
- Show unknown node properties in info tab
|
||||
- Add node icon picker widget
|
||||
- Only edit nodes on dbl click on primary button with no modifiers
|
||||
- Allow subflows to be put in any palette category
|
||||
- Add flow navigator widget
|
||||
- Cache flow library result to improve response time Fixes #1753
|
||||
- Add middle-button-drag to pan the workspace
|
||||
- allow multi-line category name in editor
|
||||
- Redesign sidebar tabs
|
||||
- Do not disable the export-clipboard menu option with empty selection
|
||||
|
||||
Nodes
|
||||
|
||||
- Change: Ensure runtime errors in Change node can be caught Fixes #1769
|
||||
- File: Add output to File Out node
|
||||
- Function: add expandable JavaScript editor pane
|
||||
- Function: allow id and name reference in function node code (#1731)
|
||||
- HTTP Request: Move to request module
|
||||
- HTTP: Ensure apiMaxLength applies to HTTP Nodes Fixes #1278
|
||||
- Join: accumulate top level properties
|
||||
- Join: allow environment variable as reduce init value
|
||||
- JSON: add JSON schema validation via msg.schema
|
||||
- Pi: Let nrgpio code work with python 3
|
||||
- Pi: let Pi nodes be visible/editable on all platforms
|
||||
- Switch: add isEmpty rule
|
||||
- TCP: queue messages while connecting; closes #1414
|
||||
- TLS: Add servername option to TLS config node for SNI Fixes #1805
|
||||
- UDP: Don't accidentally re-use udp port when set to not do so
|
||||
|
||||
Persistent Context
|
||||
|
||||
- Add Context data sidebar
|
||||
- Add persistable context option
|
||||
- Add default memory store
|
||||
- Add file-based context store
|
||||
- Add async mode to evaluateJSONataExpression
|
||||
- Update RED.util.evaluateNodeProperty to support context stores
|
||||
|
||||
Runtime
|
||||
|
||||
- Support flow.disabled and .info in /flow API
|
||||
- Node errors should be Strings not Errors Fixes #1781
|
||||
- Add detection of connection timeout in git communication Fixes #1770
|
||||
- Handle loading empty nodesDir
|
||||
- Add 'private' property to userDir generated package.json
|
||||
- Add RED.require to allow nodes to access other modules
|
||||
- Ensure add/remove modules are run sequentially
|
||||
|
||||
#### 0.18.7: Maintenance Release
|
||||
|
||||
Editor Fixes
|
||||
|
||||
- Do not trim wires if node declares outputs in defaults but misses value Fixes #1737
|
||||
|
||||
Node Fixes
|
||||
|
||||
- Relax twitter node version ready for major version bump
|
||||
- Pass Date into the Function node sandbox to fix instanceof tests
|
||||
- let TCP in node report remote ip and port when in single packet mode
|
||||
- typo fix in node help (#1735)
|
||||
|
||||
Other Fixes
|
||||
- Tidy up default grunt task and fixup test break due to reorder Fixes #1738
|
||||
- Bump jsonata version
|
||||
|
||||
#### 0.18.6: Maintenance Release
|
||||
|
||||
Editor Fixes
|
||||
|
||||
- Handle a node having wires in the editor on ports it no longer has Fixes #1724
|
||||
- Add missing ACE snippet files
|
||||
- Fix wireClippedNodes is not defined Fixes #1726
|
||||
- Split node html to isolate bad nodes when loading
|
||||
- Avoid unnecessary use of .html() where .text() will do
|
||||
|
||||
- Add editorTheme.projects.enabled to default settings.js"
|
||||
|
||||
#### 0.18.5: Maintenance Release
|
||||
|
||||
Projects
|
||||
|
||||
- Add clone project to welcome screen
|
||||
- Handle cloning a project without package.json
|
||||
- Keep remote branch state in sync between editor and runtime
|
||||
|
||||
New Features
|
||||
|
||||
- Add type checks to switch node options (#1714)
|
||||
- add output property select to HTML parse node (#1701)
|
||||
- Add Prevent Following Redirect to HTTP Request node (#615) (#1684)
|
||||
- Add debug and trace functions to function node (#1654)
|
||||
- Enable user defined icon for subflow
|
||||
- Add MQTT disconnect message and rework broker node UI (#1719)
|
||||
- Japanese message catalogue updates (#1723)
|
||||
- Show node load errors in the Palette Manager view
|
||||
|
||||
Editor Fixes
|
||||
|
||||
- Highlight subflow node when log msg comes from inside Fixes #1698
|
||||
- Ensure node wires array is not longer than outputs value Fixes #1678
|
||||
- Allow importing an unknown config node to be undone Fixes #1681
|
||||
- Ensure keyboard shortcuts get saved in runtime settings Fixes #1696
|
||||
- Don't mark a subflow changed when actually modified nothing (#1665)
|
||||
|
||||
Node Fixes
|
||||
|
||||
- bind to correct port when doing udp broadcast/multicast (#1686)
|
||||
- Provide full error stack in Function node log message (#1700)
|
||||
- Fix http request doc type Fixes #1690
|
||||
- Make debug slightly larger to pass WCAG AA rating
|
||||
- Make core nodes labels more consistent, to close #1673
|
||||
- Allow template node to be updated more than once Fixes #1671
|
||||
- Fix the problem that output labels of switch node sometimes disappear (#1664)
|
||||
- Chinese translations for core nodes (#1607)
|
||||
|
||||
Runtime Fixes
|
||||
|
||||
- Handle and display for invalid flow credentials when project is disabled #1689 (#1694)
|
||||
- node-red-pi: fix behavior with old bash version (#1713)
|
||||
- Fix ENOENT error on first start when no user dir (#1711)
|
||||
- Handle null error object in Flow.handleError Fixes #1721
|
||||
- update settings comments to describe how to setup for ipv6 (#1675)
|
||||
- Remove credential props after diffing flow to prevent future false positives Fixes #1359
|
||||
- Log error if settings unavailable when saving user settings Fixes #1645
|
||||
- Keep backup of .config.json
|
||||
- Add warning if using \_credentialSecret from .config.json
|
||||
- Filter req.user in /settings to prevent potentially leaking info
|
||||
|
||||
#### 0.18.4: Maintenance Release
|
||||
|
||||
Projects
|
||||
|
||||
- Ensure sshkey file path is properly escaped on Windows
|
||||
- Normalize ssh key paths for Windows file names
|
||||
- Ensure userDir is an absolute path when used with sshkeygen
|
||||
- Detect if there are no existing flows to migrate into a project
|
||||
- Use relative urls when retriving flow history
|
||||
- Add credentialSecret to clone pane
|
||||
- Delay clearing inflight when changing credentials key
|
||||
- Mark deploy inflight when reverting a file change
|
||||
- Handle missing_flow_file error on clone properly
|
||||
- Remote project from cached list on delete so it can be reused
|
||||
- Fix tests for existing file flag in settings
|
||||
|
||||
Editor Fixes
|
||||
|
||||
- Fix merging a remote diff
|
||||
- Fixed the problems when using a node without defaults
|
||||
- Disable user defined icon for subflow
|
||||
- getDefaultNodeIcon should handle subflow instance nodes Fixes #1635
|
||||
- Add Japanese info text for core nodes
|
||||
- Fix message lookup for core nodes in case of i18 locales directory exists
|
||||
- Prevent the last tab from being deleted
|
||||
|
||||
Node Fixes
|
||||
|
||||
- Ensure trigger gets reset when 2nd output is null
|
||||
|
||||
|
||||
#### 0.18.3: Maintenance Release
|
||||
|
||||
Projects
|
||||
|
||||
- Fix permissions on git/ssh scripts
|
||||
- Add support for GIT_SSH on older levels of git
|
||||
- Handle host key verification as auth error
|
||||
- Ensure commit list has a refs object even if empty
|
||||
- Make git error detection case-insensitive
|
||||
- Fix up merge conflict handling
|
||||
- Use flow-diff when looking at flow file changes
|
||||
|
||||
Node Fixes
|
||||
|
||||
- Ensure debug tools show for 'complete msg object'
|
||||
- Fix msg.parts handling in concat mode of Batch node
|
||||
|
||||
Editor Fixes
|
||||
|
||||
- Fix offset calculation when dragging node from palette
|
||||
- Allow a library entry to use non-default node-input- prefixes
|
||||
- Change remote-diff shortcut and add it to keymap Fixes #1628
|
||||
|
||||
#### 0.18.2: Maintenance Release
|
||||
|
||||
Projects
|
||||
|
||||
- Filter out %D from git log command for older git versions
|
||||
- Ensure projects are created as logged in user
|
||||
- Better error handling/reporting in project creation
|
||||
- Add Project Settings menu option
|
||||
- Refresh vc sidebar on remote add/remove
|
||||
- Fix auth prompt for ssh repos
|
||||
- Prevent http git urls from including username/pword
|
||||
- Fix fetch auth handling on non-default remote
|
||||
- Avoid exception if git not installed
|
||||
- Check version of git client on startup
|
||||
- Fix pull/push when no tracked branch
|
||||
- Add git_pull_unrelated_history handling
|
||||
- Handle delete of last remote in project settings
|
||||
|
||||
Node Fixes
|
||||
|
||||
- Fix and Add some Chinese translations
|
||||
- Update sort/batch docs
|
||||
- Don't assume node has defaults when exporting icon property
|
||||
- Ensure send is last thing trigger does
|
||||
- Ensure trigger doesn't set two simultaneous timeouts
|
||||
- Add missing property select var to HTML node
|
||||
- Add a default keepalive to tcp client mode
|
||||
- Move node.send in exec and httprequest nodes
|
||||
|
||||
|
||||
#### 0.18.1: Maintenance Release
|
||||
|
||||
Projects
|
||||
|
||||
- Handle more repo clone error cases
|
||||
- Relax validation of git urls
|
||||
- Revalidate project name on return to project-details view
|
||||
- Avoid unnecessary project refresh on branch-switch Fixes #1597
|
||||
- Add support for file:// git urls
|
||||
- Handle project first-run without existing flow file
|
||||
- Handle delete of last remote in project settings
|
||||
- Add git_pull_unrelated_history handling
|
||||
- Fix pull/push when no tracked branch
|
||||
- Remember to disable projects in editor when git not found
|
||||
|
||||
Node Fixes
|
||||
|
||||
- Trigger node migration - ensure bytopic not blank
|
||||
- Add HEAD to list of methods with no body in http req node #1598
|
||||
- Do not include payload in GET requests Fixes #1598
|
||||
- Update sort/batch docs Fixes #1601
|
||||
- Don't assume node has defaults when exporting icon property
|
||||
|
||||
|
||||
#### 0.18: Milestone Release
|
||||
|
||||
Runtime
|
||||
|
||||
- Beta: Projects - must be enabled in settings file
|
||||
- Allow port zero for Express (#1363)
|
||||
- Better error reporting when module provides duplicate type
|
||||
- Update jsonata to 1.5.0
|
||||
- add express-session memorystore without leaks (#1435)
|
||||
- Allow adminAuth.user to be a Function Fixes #1461
|
||||
- Ensure RED.server is set even if admin api disabled
|
||||
- Ensure strategy login button uses relative URL Fixes #1481
|
||||
- ignore `_msgid` when merging full objects
|
||||
- Move node install to spawn to allow for big stdout Fixes #1488
|
||||
- SIGINT handler should wait for stop to complete before exit
|
||||
|
||||
Editor
|
||||
|
||||
- allow a node's icon to be set dynamically (#1490)
|
||||
- Batch messages sent over comms to increase throughput
|
||||
- Migrate deploy confirmations to notifications
|
||||
- `oneditdelete` should be available to all node types Closes #1346
|
||||
- Sort typeSearch results based on position of match
|
||||
- Update ACE to test and add python highlighter (#1373)
|
||||
- Clear mouse state when typeSearch cancelled Fixes #1517
|
||||
- Handle scoped modules via palette editor
|
||||
- TypedInput: handle user defined value/labels options Fixes #1549
|
||||
|
||||
Nodes
|
||||
|
||||
- add msg. select to range and yaml nodes
|
||||
- add property choice to xml, sentiment nodes
|
||||
- mqtt: Add 'name' to mqtt-broker node, and label it by this if it is set. (#1364)
|
||||
- Add option to JSON node to ensure particular encoding
|
||||
- add parts support for HTML node (#1495)
|
||||
- Add passphrase to TLS node
|
||||
- Add rc property to exec node outputs 1 and 2 (#1401)
|
||||
- Add skip first n lines capability to csv node (#1535)
|
||||
- Add support for rejectUnauthorized msg property
|
||||
- Add TLS options to WebSocket client
|
||||
- Added parsed YAML support for template node (#1443)
|
||||
- Allow delay node in rate-limit mode to be reset Fixes #1360
|
||||
- Allow setTimeout in Function node to be promisified in node 8
|
||||
- Debug to status option (#1499)
|
||||
- enable template config via msg.template for stored or generated templates (#1503)
|
||||
- HTTP REQUEST: Adding PROPPATCH and PROPFIND http methods (#1531)
|
||||
- Initial support of merge & reduce mode for JOIN node (#1546)
|
||||
- Initial support of new BATCH node (#1548)
|
||||
- Initial support of sequence rules for SWITCH node (#1545)
|
||||
- initial support of SORT node (#1500)
|
||||
- Inject node - let once delay be editable (#1541)
|
||||
- Introduce `nodeMaxMessageBufferLength` setting for msg sequence nodes
|
||||
- Let CSV correct parts if we remove header row.
|
||||
- let default apply if msg.delay not set in override mode. (#1397)
|
||||
- let trigger node be reset by boolean message (#1554)
|
||||
- Let trigger node support per topic mode (#1398)
|
||||
- let HTML node return empty array for no matching input (#1582)
|
||||
- MQTT node - if Server/URL config contains '//' use it as a complete url; enabled ws:// and wss://
|
||||
- clone messages before delayed send (#1474)
|
||||
- Decrement connected client count rather than show disconnected
|
||||
- Don't end mqtt client on first error Fixes #1566
|
||||
- File out - create dirs synchronously to ensure they exist Fixes #1489
|
||||
- Fix debug message format for Buffer (#1444)
|
||||
- Fix global.keys() bug in function node (#1417)
|
||||
- Handle escape characters in template node which uses Mustache format and JSON output mode (#1377)
|
||||
- Move all node.send to end of timer functions in trigger node (issue #1527) (#1539)
|
||||
- Publish null/undefined to mqtt as blank not toString Fixes #1521
|
||||
- remove inject node at specific time spinner
|
||||
- restrict inject interval to less that 2^31 millisecs
|
||||
- tag UDP ports in use properly so they get closed correctly (#1508)
|
||||
|
||||
#### 0.17.5: Maintenance Release
|
||||
|
||||
- Add express-session missing dependency for oauth
|
||||
- Fix improper type tests is core test cases
|
||||
- File node: recreate write stream when file deleted Fixes #1351
|
||||
- Add flow stopping trace messages
|
||||
- Fix userDir test case when .config.json exists (#1350)
|
||||
- Do not try to send msg after http request error handled Fixes #1344
|
||||
- Fix boundary problem in range node (#1338)
|
||||
- Modify messages in node properties to refer messages.json (#1339)
|
||||
- Fix settings.js replacing webSocketVerifyClient by webSocketNodeVerifyClient (#1343)
|
||||
|
||||
|
||||
#### 0.17.4: Maintenance Release
|
||||
|
||||
- Add request node test case for POSTing 0
|
||||
- Allow false and 0 in payload for httprequest (#1334)
|
||||
- Add file extension into flow name of library automatically (#1331)
|
||||
- Fix accessing global context from jsonata expressions Fixes #1335
|
||||
- Disable editor whilst a deploy is inflight Fixes #1332
|
||||
- Replace Unknown nodes with their real versions when node loaded
|
||||
- Retry auto-install of modules that fail
|
||||
- Fix column name in link nodes to refer language file (#1330)
|
||||
- Use namespaces with link node title attributes i18n name Fixes #1329
|
||||
- Tidy up GPIO pin table presentation Fixes #1328
|
||||
- Join: count of 0 should not send on every msg
|
||||
- Handle importing only one end of a link node pair
|
||||
- Make sending to Debug synchronous again Fixes #1323
|
||||
- Make send-error behaviour optional in file node
|
||||
- Restore File In node behaviour of sending msg on error
|
||||
- Expose context.keys within Function node
|
||||
- JSON parser default should be not formatting output
|
||||
|
||||
|
||||
#### 0.17.3: Maintenance Release
|
||||
|
||||
- Fix flow library in menu to support period characters as flow name (#1320)
|
||||
- editorTheme not setting custom css/scripts properly
|
||||
- Fix missing icons for some nodes (#1321)
|
||||
- Add reformat button to JSONata test data editor
|
||||
- Update delay node status without spawning unnecessary intervals
|
||||
- Avoid stringify ServerResponse and Socket in Debug node Fixes #1311
|
||||
- Fix creating userDir other than system drive on Windows (#1317)
|
||||
- Trigger node not handling a duration of 0 as block mode Fixes #1316
|
||||
- Unable to config GPIO Pin 13 Fixes #1314
|
||||
|
||||
#### 0.17.2: Maintenance Release
|
||||
|
||||
- Fix GPIO node labels
|
||||
|
||||
#### 0.17.1: Maintenance Release
|
||||
|
||||
- Fix PI gpio to use BCM
|
||||
@@ -839,7 +1381,7 @@ Fixes
|
||||
#### 0.10.10: Maintenance Release
|
||||
|
||||
- Fix permissions issue with packaged nrgpio script
|
||||
- Add better help message if deprecated node missing
|
||||
- Add better help message if deprecated node missing
|
||||
|
||||
|
||||
|
||||
@@ -851,16 +1393,16 @@ Fix packaging of bin scripts
|
||||
|
||||
#### 0.10.8: Maintenance Release
|
||||
|
||||
- Nodes moved out of core
|
||||
- still included as a dependency: twitter, serial, email, feedparser
|
||||
- Nodes moved out of core
|
||||
- still included as a dependency: twitter, serial, email, feedparser
|
||||
- no longer included: mongo, arduino, irc, redis
|
||||
- node icon defn can be a function
|
||||
- http_proxy support
|
||||
- httpNodeMiddleware setting
|
||||
- Trigger node ui refresh
|
||||
- editorTheme setting
|
||||
- Warn on deploy of unused config nodes
|
||||
- catch node prevents error loops
|
||||
- node icon defn can be a function
|
||||
- http_proxy support
|
||||
- httpNodeMiddleware setting
|
||||
- Trigger node ui refresh
|
||||
- editorTheme setting
|
||||
- Warn on deploy of unused config nodes
|
||||
- catch node prevents error loops
|
||||
|
||||
|
||||
|
||||
@@ -883,14 +1425,14 @@ Changes:
|
||||
|
||||
Changes:
|
||||
|
||||
- http request node passes on request url as msg.url
|
||||
- handle config nodes appearing out of order in flow file - don't assume they are always at the start
|
||||
- move subflow palette category to the top, to make it more obvious
|
||||
- fix labelling of Raspberry Pi pins
|
||||
- allow email node to mark mail as read
|
||||
- fix saving library content
|
||||
- add node-red and node-red-pi start scripts
|
||||
- use $HOME/.node-red for user data unless specified otherwise (or existing data is found in install dir)
|
||||
- http request node passes on request url as msg.url
|
||||
- handle config nodes appearing out of order in flow file - don't assume they are always at the start
|
||||
- move subflow palette category to the top, to make it more obvious
|
||||
- fix labelling of Raspberry Pi pins
|
||||
- allow email node to mark mail as read
|
||||
- fix saving library content
|
||||
- add node-red and node-red-pi start scripts
|
||||
- use $HOME/.node-red for user data unless specified otherwise (or existing data is found in install dir)
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ We welcome contributions, but request you follow these guidelines.
|
||||
|
||||
This project adheres to the [Contributor Covenant 1.4](http://contributor-covenant.org/version/1/4/).
|
||||
By participating, you are expected to uphold this code. Please report unacceptable
|
||||
behavior to any of the [project's core team](https://github.com/orgs/node-red/teams/core).
|
||||
behavior to the project's core team at team@nodered.org.
|
||||
|
||||
## Raising issues
|
||||
|
||||
@@ -30,13 +30,13 @@ At a minimum, please include:
|
||||
|
||||
## Feature requests
|
||||
|
||||
For feature requests, please raise them on the [mailing list](https://groups.google.com/forum/#!forum/node-red).
|
||||
For feature requests, please raise them on the [forum](https://discourse.nodered.org).
|
||||
|
||||
## 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 [mailing list](https://groups.google.com/forum/#!forum/node-red) first.
|
||||
the [forum](https://discourse.nodered.org) first.
|
||||
|
||||
All contributors need to sign the JS Foundation's Contributor License Agreement.
|
||||
It is an online process and quick to do. You can read the details of the agreement
|
||||
|
||||
383
Gruntfile.js
383
Gruntfile.js
@@ -24,6 +24,10 @@ module.exports = function(grunt) {
|
||||
nodemonArgs.push(flowFile);
|
||||
}
|
||||
|
||||
var nonHeadless = grunt.option('non-headless');
|
||||
if (nonHeadless) {
|
||||
process.env.NODE_RED_NON_HEADLESS = 'true';
|
||||
}
|
||||
grunt.initConfig({
|
||||
pkg: grunt.file.readJSON('package.json'),
|
||||
paths: {
|
||||
@@ -38,19 +42,27 @@ module.exports = function(grunt) {
|
||||
reporter: 'spec'
|
||||
},
|
||||
all: { src: ['test/**/*_spec.js'] },
|
||||
core: { src: ["test/_spec.js","test/red/**/*_spec.js"]},
|
||||
core: { src: ["test/_spec.js","test/unit/**/*_spec.js"]},
|
||||
nodes: { src: ["test/nodes/**/*_spec.js"]}
|
||||
},
|
||||
webdriver: {
|
||||
all: {
|
||||
configFile: 'test/editor/wdio.conf.js'
|
||||
}
|
||||
},
|
||||
mocha_istanbul: {
|
||||
options: {
|
||||
globals: ['expect'],
|
||||
timeout: 3000,
|
||||
ignoreLeaks: false,
|
||||
ui: 'bdd',
|
||||
reportFormats: ['lcov'],
|
||||
print: 'both'
|
||||
reportFormats: ['lcov','html'],
|
||||
print: 'both',
|
||||
istanbulOptions: ['--no-default-excludes', '-i','**/packages/node_modules/**']
|
||||
},
|
||||
coverage: { src: ['test/**/*_spec.js'] }
|
||||
all: { src: ["test/unit/_spec.js","test/unit/**/*_spec.js","test/nodes/**/*_spec.js"] },
|
||||
core: { src: ["test/unit/_spec.js","test/unit/**/*_spec.js"]},
|
||||
nodes: { src: ["test/nodes/**/*_spec.js"]}
|
||||
},
|
||||
jshint: {
|
||||
options: {
|
||||
@@ -69,16 +81,14 @@ module.exports = function(grunt) {
|
||||
all: [
|
||||
'Gruntfile.js',
|
||||
'red.js',
|
||||
'red/**/*.js',
|
||||
'nodes/core/*/*.js',
|
||||
'editor/js/**/*.js'
|
||||
'packages/**/*.js'
|
||||
],
|
||||
core: {
|
||||
files: {
|
||||
src: [
|
||||
'Gruntfile.js',
|
||||
'red.js',
|
||||
'red/**/*.js'
|
||||
'packages/**/*.js',
|
||||
]
|
||||
}
|
||||
},
|
||||
@@ -109,74 +119,85 @@ module.exports = function(grunt) {
|
||||
src: [
|
||||
// Ensure editor source files are concatenated in
|
||||
// the right order
|
||||
"editor/js/red.js",
|
||||
"editor/js/events.js",
|
||||
"editor/js/i18n.js",
|
||||
"editor/js/settings.js",
|
||||
"editor/js/user.js",
|
||||
"editor/js/comms.js",
|
||||
"editor/js/text/bidi.js",
|
||||
"editor/js/text/format.js",
|
||||
"editor/js/ui/state.js",
|
||||
"editor/js/nodes.js",
|
||||
"editor/js/history.js",
|
||||
"editor/js/validators.js",
|
||||
"editor/js/ui/utils.js",
|
||||
"editor/js/ui/common/editableList.js",
|
||||
"editor/js/ui/common/checkboxSet.js",
|
||||
"editor/js/ui/common/menu.js",
|
||||
"editor/js/ui/common/panels.js",
|
||||
"editor/js/ui/common/popover.js",
|
||||
"editor/js/ui/common/searchBox.js",
|
||||
"editor/js/ui/common/tabs.js",
|
||||
"editor/js/ui/common/stack.js",
|
||||
"editor/js/ui/common/typedInput.js",
|
||||
"editor/js/ui/actions.js",
|
||||
"editor/js/ui/deploy.js",
|
||||
"editor/js/ui/diff.js",
|
||||
"editor/js/ui/keyboard.js",
|
||||
"editor/js/ui/workspaces.js",
|
||||
"editor/js/ui/view.js",
|
||||
"editor/js/ui/sidebar.js",
|
||||
"editor/js/ui/palette.js",
|
||||
"editor/js/ui/tab-info.js",
|
||||
"editor/js/ui/tab-config.js",
|
||||
"editor/js/ui/palette-editor.js",
|
||||
"editor/js/ui/editor.js",
|
||||
"editor/js/ui/tray.js",
|
||||
"editor/js/ui/clipboard.js",
|
||||
"editor/js/ui/library.js",
|
||||
"editor/js/ui/notifications.js",
|
||||
"editor/js/ui/search.js",
|
||||
"editor/js/ui/typeSearch.js",
|
||||
"editor/js/ui/subflow.js",
|
||||
"editor/js/ui/userSettings.js",
|
||||
"editor/js/ui/touch/radialMenu.js"
|
||||
"packages/node_modules/@node-red/editor-client/src/js/jquery-addons.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/red.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/events.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/i18n.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/settings.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/user.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/comms.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/text/bidi.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/text/format.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/state.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/nodes.js",
|
||||
"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/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",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/common/checkboxSet.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/common/menu.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/common/panels.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/common/popover.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/common/searchBox.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/common/tabs.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/common/stack.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/common/typedInput.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/actions.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/deploy.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/diff.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/keyboard.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/workspaces.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/view.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/view-navigator.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/sidebar.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/palette.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/tab-info.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/tab-config.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/tab-context.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/palette-editor.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/editor.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/editors/*.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/event-log.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/tray.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/clipboard.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/library.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/notifications.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/search.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/typeSearch.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/subflow.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/userSettings.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/projects/projects.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/projects/projectSettings.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/projects/projectUserSettings.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/projects/tab-versionControl.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/touch/radialMenu.js"
|
||||
],
|
||||
dest: "public/red/red.js"
|
||||
dest: "packages/node_modules/@node-red/editor-client/public/red/red.js"
|
||||
},
|
||||
vendor: {
|
||||
files: {
|
||||
"public/vendor/vendor.js": [
|
||||
"editor/vendor/jquery/js/jquery-1.11.3.min.js",
|
||||
"editor/vendor/bootstrap/js/bootstrap.min.js",
|
||||
"editor/vendor/jquery/js/jquery-ui-1.10.3.custom.min.js",
|
||||
"editor/vendor/jquery/js/jquery.ui.touch-punch.min.js",
|
||||
"editor/vendor/marked/marked.min.js",
|
||||
"editor/vendor/d3/d3.v3.min.js",
|
||||
"editor/vendor/i18next/i18next.min.js"
|
||||
"packages/node_modules/@node-red/editor-client/public/vendor/vendor.js": [
|
||||
"packages/node_modules/@node-red/editor-client/src/vendor/jquery/js/jquery-1.11.3.min.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/vendor/bootstrap/js/bootstrap.min.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/vendor/jquery/js/jquery-ui-1.10.3.custom.min.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/vendor/jquery/js/jquery.ui.touch-punch.min.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/vendor/marked/marked.min.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/vendor/d3/d3.v3.min.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/vendor/i18next/i18next.min.js"
|
||||
],
|
||||
"public/vendor/vendor.css": [
|
||||
"packages/node_modules/@node-red/editor-client/public/vendor/vendor.css": [
|
||||
// TODO: resolve relative resource paths in
|
||||
// bootstrap/FA/jquery
|
||||
],
|
||||
"public/vendor/jsonata/jsonata.min.js": [
|
||||
"packages/node_modules/@node-red/editor-client/public/vendor/jsonata/jsonata.min.js": [
|
||||
"node_modules/jsonata/jsonata-es5.min.js",
|
||||
"editor/vendor/jsonata/formatter.js"
|
||||
"packages/node_modules/@node-red/editor-client/src/vendor/jsonata/formatter.js"
|
||||
],
|
||||
"public/vendor/ace/worker-jsonata.js": [
|
||||
"packages/node_modules/@node-red/editor-client/public/vendor/ace/worker-jsonata.js": [
|
||||
"node_modules/jsonata/jsonata-es5.min.js",
|
||||
"editor/vendor/jsonata/worker-jsonata.js"
|
||||
"packages/node_modules/@node-red/editor-client/src/vendor/jsonata/worker-jsonata.js"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -184,10 +205,10 @@ module.exports = function(grunt) {
|
||||
uglify: {
|
||||
build: {
|
||||
files: {
|
||||
'public/red/red.min.js': 'public/red/red.js',
|
||||
'public/red/main.min.js': 'public/red/main.js',
|
||||
'public/vendor/ace/mode-jsonata.js': 'editor/vendor/jsonata/mode-jsonata.js',
|
||||
'public/vendor/ace/snippets/jsonata.js': 'editor/vendor/jsonata/snippets-jsonata.js'
|
||||
'packages/node_modules/@node-red/editor-client/public/red/red.min.js': 'packages/node_modules/@node-red/editor-client/public/red/red.js',
|
||||
'packages/node_modules/@node-red/editor-client/public/red/main.min.js': 'packages/node_modules/@node-red/editor-client/public/red/main.js',
|
||||
'packages/node_modules/@node-red/editor-client/public/vendor/ace/mode-jsonata.js': 'packages/node_modules/@node-red/editor-client/src/vendor/jsonata/mode-jsonata.js',
|
||||
'packages/node_modules/@node-red/editor-client/public/vendor/ace/snippets/jsonata.js': 'packages/node_modules/@node-red/editor-client/src/vendor/jsonata/snippets-jsonata.js'
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -197,50 +218,50 @@ module.exports = function(grunt) {
|
||||
outputStyle: 'compressed'
|
||||
},
|
||||
files: [{
|
||||
dest: 'public/red/style.min.css',
|
||||
src: 'editor/sass/style.scss'
|
||||
dest: 'packages/node_modules/@node-red/editor-client/public/red/style.min.css',
|
||||
src: 'packages/node_modules/@node-red/editor-client/src/sass/style.scss'
|
||||
},
|
||||
{
|
||||
dest: 'public/vendor/bootstrap/css/bootstrap.min.css',
|
||||
src: 'editor/vendor/bootstrap/css/bootstrap.css'
|
||||
dest: 'packages/node_modules/@node-red/editor-client/public/vendor/bootstrap/css/bootstrap.min.css',
|
||||
src: 'packages/node_modules/@node-red/editor-client/src/vendor/bootstrap/css/bootstrap.css'
|
||||
}]
|
||||
}
|
||||
},
|
||||
jsonlint: {
|
||||
messages: {
|
||||
src: [
|
||||
'nodes/core/locales/en-US/messages.json',
|
||||
'red/api/locales/en-US/editor.json',
|
||||
'red/runtime/locales/en-US/runtime.json'
|
||||
'packages/node_modules/@node-red/nodes/locales/**/*.json',
|
||||
'packages/node_modules/@node-red/editor-client/locales/**/*.json',
|
||||
'packages/node_modules/@node-red/runtime/locales/**/*.json'
|
||||
]
|
||||
},
|
||||
keymaps: {
|
||||
src: [
|
||||
'editor/js/keymap.json'
|
||||
'packages/node_modules/@node-red/editor-client/src/js/keymap.json'
|
||||
]
|
||||
}
|
||||
},
|
||||
attachCopyright: {
|
||||
js: {
|
||||
src: [
|
||||
'public/red/red.min.js',
|
||||
'public/red/main.min.js'
|
||||
'packages/node_modules/@node-red/editor-client/public/red/red.min.js',
|
||||
'packages/node_modules/@node-red/editor-client/public/red/main.min.js'
|
||||
]
|
||||
},
|
||||
css: {
|
||||
src: [
|
||||
'public/red/style.min.css'
|
||||
'packages/node_modules/@node-red/editor-client/public/red/style.min.css'
|
||||
]
|
||||
}
|
||||
},
|
||||
clean: {
|
||||
build: {
|
||||
src: [
|
||||
"public/red",
|
||||
"public/index.html",
|
||||
"public/favicon.ico",
|
||||
"public/icons",
|
||||
"public/vendor"
|
||||
"packages/node_modules/@node-red/editor-client/public/red",
|
||||
"packages/node_modules/@node-red/editor-client/public/index.html",
|
||||
"packages/node_modules/@node-red/editor-client/public/favicon.ico",
|
||||
"packages/node_modules/@node-red/editor-client/public/icons",
|
||||
"packages/node_modules/@node-red/editor-client/public/vendor"
|
||||
]
|
||||
},
|
||||
release: {
|
||||
@@ -252,27 +273,27 @@ module.exports = function(grunt) {
|
||||
watch: {
|
||||
js: {
|
||||
files: [
|
||||
'editor/js/**/*.js'
|
||||
'packages/node_modules/@node-red/editor-client/src/js/**/*.js'
|
||||
],
|
||||
tasks: ['copy:build','concat','uglify','attachCopyright:js']
|
||||
},
|
||||
sass: {
|
||||
files: [
|
||||
'editor/sass/**/*.scss'
|
||||
'packages/node_modules/@node-red/editor-client/src/sass/**/*.scss'
|
||||
],
|
||||
tasks: ['sass','attachCopyright:css']
|
||||
},
|
||||
json: {
|
||||
files: [
|
||||
'nodes/core/locales/en-US/messages.json',
|
||||
'red/api/locales/en-US/editor.json',
|
||||
'red/runtime/locales/en-US/runtime.json'
|
||||
'packages/node_modules/@node-red/nodes/locales/**/*.json',
|
||||
'packages/node_modules/@node-red/editor-client/locales/**/*.json',
|
||||
'packages/node_modules/@node-red/runtime/locales/**/*.json'
|
||||
],
|
||||
tasks: ['jsonlint:messages']
|
||||
},
|
||||
keymaps: {
|
||||
files: [
|
||||
'editor/js/keymap.json'
|
||||
'packages/node_modules/@node-red/editor-client/src/js/keymap.json'
|
||||
],
|
||||
tasks: ['jsonlint:keymaps','copy:build']
|
||||
},
|
||||
@@ -287,12 +308,13 @@ module.exports = function(grunt) {
|
||||
nodemon: {
|
||||
/* uses .nodemonignore */
|
||||
dev: {
|
||||
script: 'red.js',
|
||||
script: 'packages/node_modules/node-red/red.js',
|
||||
options: {
|
||||
args: nodemonArgs,
|
||||
ext: 'js,html,json',
|
||||
watch: [
|
||||
'red','nodes'
|
||||
'packages/node_modules',
|
||||
'!packages/node_modules/@node-red/editor-client'
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -311,21 +333,21 @@ module.exports = function(grunt) {
|
||||
build: {
|
||||
files:[
|
||||
{
|
||||
src: 'editor/js/main.js',
|
||||
dest: 'public/red/main.js'
|
||||
src: 'packages/node_modules/@node-red/editor-client/src/js/main.js',
|
||||
dest: 'packages/node_modules/@node-red/editor-client/public/red/main.js'
|
||||
},
|
||||
{
|
||||
src: 'editor/js/keymap.json',
|
||||
dest: 'public/red/keymap.json'
|
||||
src: 'packages/node_modules/@node-red/editor-client/src/js/keymap.json',
|
||||
dest: 'packages/node_modules/@node-red/editor-client/public/red/keymap.json'
|
||||
},
|
||||
{
|
||||
cwd: 'editor/images',
|
||||
cwd: 'packages/node_modules/@node-red/editor-client/src/images',
|
||||
src: '**',
|
||||
expand: true,
|
||||
dest: 'public/red/images/'
|
||||
dest: 'packages/node_modules/@node-red/editor-client/public/red/images/'
|
||||
},
|
||||
{
|
||||
cwd: 'editor/vendor',
|
||||
cwd: 'packages/node_modules/@node-red/editor-client/src/vendor',
|
||||
src: [
|
||||
'ace/**',
|
||||
//'bootstrap/css/**',
|
||||
@@ -334,46 +356,35 @@ module.exports = function(grunt) {
|
||||
'font-awesome/**'
|
||||
],
|
||||
expand: true,
|
||||
dest: 'public/vendor/'
|
||||
dest: 'packages/node_modules/@node-red/editor-client/public/vendor/'
|
||||
},
|
||||
{
|
||||
cwd: 'editor/icons',
|
||||
cwd: 'packages/node_modules/@node-red/editor-client/src/icons',
|
||||
src: '**',
|
||||
expand: true,
|
||||
dest: 'public/icons/'
|
||||
dest: 'packages/node_modules/@node-red/editor-client/public/icons/'
|
||||
},
|
||||
{
|
||||
expand: true,
|
||||
src: ['editor/index.html','editor/favicon.ico'],
|
||||
dest: 'public/',
|
||||
src: ['packages/node_modules/@node-red/editor-client/src/index.html','packages/node_modules/@node-red/editor-client/src/favicon.ico'],
|
||||
dest: 'packages/node_modules/@node-red/editor-client/public/',
|
||||
flatten: true
|
||||
},
|
||||
{
|
||||
src: 'CHANGELOG.md',
|
||||
dest: 'public/red/about'
|
||||
dest: 'packages/node_modules/@node-red/editor-client/public/red/about'
|
||||
},
|
||||
{
|
||||
src: 'CHANGELOG.md',
|
||||
dest: 'packages/node_modules/node-red/'
|
||||
},
|
||||
{
|
||||
cwd: 'packages/node_modules/@node-red/editor-client/src/ace/bin/',
|
||||
src: '**',
|
||||
expand: true,
|
||||
dest: 'packages/node_modules/@node-red/editor-client/public/vendor/ace/'
|
||||
}
|
||||
]
|
||||
},
|
||||
release: {
|
||||
files: [{
|
||||
mode: true,
|
||||
expand: true,
|
||||
src: [
|
||||
'*.md',
|
||||
'LICENSE',
|
||||
'package.json',
|
||||
'settings.js',
|
||||
'red.js',
|
||||
'lib/.gitignore',
|
||||
'nodes/*.demo',
|
||||
'nodes/core/**',
|
||||
'red/**',
|
||||
'public/**',
|
||||
'editor/templates/**',
|
||||
'bin/**'
|
||||
],
|
||||
dest: path.resolve('<%= paths.dist %>/node-red-<%= pkg.version %>')
|
||||
}]
|
||||
}
|
||||
},
|
||||
chmod: {
|
||||
@@ -381,20 +392,90 @@ module.exports = function(grunt) {
|
||||
mode: '755'
|
||||
},
|
||||
release: {
|
||||
// Target-specific file/dir lists and/or options go here.
|
||||
src: [
|
||||
path.resolve('<%= paths.dist %>/node-red-<%= pkg.version %>/nodes/core/hardware/nrgpio*')
|
||||
"packages/node_modules/@node-red/nodes/core/hardware/nrgpio",
|
||||
"packages/node_modules/@node-red/runtime/lib/storage/localfilesystem/projects/git/node-red-*sh"
|
||||
]
|
||||
}
|
||||
},
|
||||
'npm-command': {
|
||||
options: {
|
||||
cmd: "pack",
|
||||
cwd: "<%= paths.dist %>/modules"
|
||||
},
|
||||
'node-red': { options: { args: [__dirname+'/packages/node_modules/node-red'] } },
|
||||
'@node-red/editor-api': { options: { args: [__dirname+'/packages/node_modules/@node-red/editor-api'] } },
|
||||
'@node-red/editor-client': { options: { args: [__dirname+'/packages/node_modules/@node-red/editor-client'] } },
|
||||
'@node-red/nodes': { options: { args: [__dirname+'/packages/node_modules/@node-red/nodes'] } },
|
||||
'@node-red/registry': { options: { args: [__dirname+'/packages/node_modules/@node-red/registry'] } },
|
||||
'@node-red/runtime': { options: { args: [__dirname+'/packages/node_modules/@node-red/runtime'] } },
|
||||
'@node-red/util': { options: { args: [__dirname+'/packages/node_modules/@node-red/util'] } }
|
||||
|
||||
|
||||
},
|
||||
mkdir: {
|
||||
release: {
|
||||
options: {
|
||||
create: ['<%= paths.dist %>/modules']
|
||||
},
|
||||
},
|
||||
},
|
||||
compress: {
|
||||
release: {
|
||||
options: {
|
||||
archive: '<%= paths.dist %>/node-red-<%= pkg.version %>.zip'
|
||||
},
|
||||
expand: true,
|
||||
cwd: '<%= paths.dist %>/',
|
||||
src: ['node-red-<%= pkg.version %>/**']
|
||||
cwd: 'packages/node_modules/',
|
||||
src: [
|
||||
'**',
|
||||
'!@node-red/editor-client/src/**'
|
||||
]
|
||||
}
|
||||
},
|
||||
jsdoc : {
|
||||
modules: {
|
||||
src: [
|
||||
'packages/node_modules/node-red/lib/red.js',
|
||||
'packages/node_modules/@node-red/runtime/lib/index.js',
|
||||
'packages/node_modules/@node-red/runtime/lib/api/*.js',
|
||||
'packages/node_modules/@node-red/runtime/lib/events.js',
|
||||
'packages/node_modules/@node-red/util/**/*.js',
|
||||
],
|
||||
options: {
|
||||
destination: 'docs',
|
||||
configure: './jsdoc.json'
|
||||
}
|
||||
},
|
||||
editor: {
|
||||
src: [
|
||||
'packages/node_modules/@node-red/editor-client/src/js'
|
||||
],
|
||||
options: {
|
||||
destination: 'packages/node_modules/@node-red/editor-client/docs',
|
||||
configure: './jsdoc.json'
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
jsdoc2md: {
|
||||
runtimeAPI: {
|
||||
options: {
|
||||
separators: true
|
||||
},
|
||||
src: [
|
||||
'packages/node_modules/@node-red/runtime/lib/index.js',
|
||||
'packages/node_modules/@node-red/runtime/lib/api/*.js',
|
||||
'packages/node_modules/@node-red/runtime/lib/events.js'
|
||||
],
|
||||
dest: 'packages/node_modules/@node-red/runtime/docs/api.md'
|
||||
},
|
||||
nodeREDUtil: {
|
||||
options: {
|
||||
separators: true
|
||||
},
|
||||
src: 'packages/node_modules/@node-red/util/**/*.js',
|
||||
dest: 'packages/node_modules/@node-red/util/docs/api.md'
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -413,6 +494,11 @@ module.exports = function(grunt) {
|
||||
grunt.loadNpmTasks('grunt-chmod');
|
||||
grunt.loadNpmTasks('grunt-jsonlint');
|
||||
grunt.loadNpmTasks('grunt-mocha-istanbul');
|
||||
grunt.loadNpmTasks('grunt-webdriver');
|
||||
grunt.loadNpmTasks('grunt-jsdoc');
|
||||
grunt.loadNpmTasks('grunt-jsdoc-to-markdown');
|
||||
grunt.loadNpmTasks('grunt-npm-command');
|
||||
grunt.loadNpmTasks('grunt-mkdir');
|
||||
|
||||
grunt.registerMultiTask('attachCopyright', function() {
|
||||
var files = this.data.src;
|
||||
@@ -454,6 +540,18 @@ module.exports = function(grunt) {
|
||||
}
|
||||
});
|
||||
|
||||
grunt.registerTask('verifyPackageDependencies', function() {
|
||||
var done = this.async();
|
||||
var verifyDependencies = require("./scripts/verify-package-dependencies.js");
|
||||
verifyDependencies().then(function(failures) {
|
||||
if (failures.length > 0) {
|
||||
failures.forEach(f => grunt.log.error(f));
|
||||
grunt.fail.fatal("Failed to verify package dependencies");
|
||||
}
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
grunt.registerTask('setDevEnv',
|
||||
'Sets NODE_ENV=development so non-minified assets are used',
|
||||
function () {
|
||||
@@ -462,19 +560,23 @@ module.exports = function(grunt) {
|
||||
|
||||
grunt.registerTask('default',
|
||||
'Builds editor content then runs code style checks and unit tests on all components',
|
||||
['build','test-core','test-editor','test-nodes']);
|
||||
['build','verifyPackageDependencies','jshint:editor','mocha_istanbul:all']);
|
||||
|
||||
grunt.registerTask('test-core',
|
||||
'Runs code style check and unit tests on core runtime code',
|
||||
['jshint:core','simplemocha:core']);
|
||||
['build','mocha_istanbul:core']);
|
||||
|
||||
grunt.registerTask('test-editor',
|
||||
'Runs code style check on editor code',
|
||||
['jshint:editor']);
|
||||
|
||||
grunt.registerTask('test-ui',
|
||||
'Builds editor content then runs unit tests on editor ui',
|
||||
['build','jshint:editor','webdriver:all']);
|
||||
|
||||
grunt.registerTask('test-nodes',
|
||||
'Runs unit tests on core nodes',
|
||||
['simplemocha:nodes']);
|
||||
['build','mocha_istanbul:nodes']);
|
||||
|
||||
grunt.registerTask('build',
|
||||
'Builds editor content',
|
||||
@@ -486,9 +588,18 @@ module.exports = function(grunt) {
|
||||
|
||||
grunt.registerTask('release',
|
||||
'Create distribution zip file',
|
||||
['build','clean:release','copy:release','chmod:release','compress:release']);
|
||||
['build','verifyPackageDependencies','clean:release','mkdir:release','chmod:release','compress:release','pack-modules']);
|
||||
|
||||
grunt.registerTask('pack-modules',
|
||||
'Create module pack files for release',
|
||||
['mkdir:release','npm-command']);
|
||||
|
||||
|
||||
grunt.registerTask('coverage',
|
||||
'Run Istanbul code test coverage task',
|
||||
['build','mocha_istanbul']);
|
||||
['build','mocha_istanbul:all']);
|
||||
|
||||
grunt.registerTask('docs',
|
||||
'Generates API documentation',
|
||||
['jsdoc','jsdoc2md']);
|
||||
};
|
||||
|
||||
12
README.md
12
README.md
@@ -2,7 +2,7 @@
|
||||
|
||||
http://nodered.org
|
||||
|
||||
[](https://travis-ci.org/node-red/node-red)
|
||||
[](https://travis-ci.org/node-red/node-red)
|
||||
[](https://coveralls.io/r/node-red/node-red?branch=master)
|
||||
|
||||
A visual tool for wiring the Internet of Things.
|
||||
@@ -14,7 +14,7 @@ A visual tool for wiring the Internet of Things.
|
||||
Check out http://nodered.org/docs/getting-started/ for full instructions on getting
|
||||
started.
|
||||
|
||||
1. `sudo npm install -g node-red`
|
||||
1. `sudo npm install -g --unsafe-perm node-red`
|
||||
2. `node-red`
|
||||
3. Open <http://localhost:1880>
|
||||
|
||||
@@ -22,8 +22,7 @@ started.
|
||||
|
||||
More documentation can be found [here](http://nodered.org/docs).
|
||||
|
||||
For further help, or general discussion, please use the
|
||||
[mailing list](https://groups.google.com/forum/#!forum/node-red).
|
||||
For further help, or general discussion, please use the [Node-RED Forum](https://discourse.nodered.org) or [slack team](https://nodered.org/slack).
|
||||
|
||||
## Developers
|
||||
|
||||
@@ -45,9 +44,6 @@ If you want to run the latest code from git, here's how to get started:
|
||||
4. Run
|
||||
|
||||
npm start
|
||||
or
|
||||
|
||||
node red.js
|
||||
|
||||
## Contributing
|
||||
|
||||
@@ -56,7 +52,7 @@ Before raising a pull-request, please read our
|
||||
|
||||
This project adheres to the [Contributor Covenant 1.4](http://contributor-covenant.org/version/1/4/).
|
||||
By participating, you are expected to uphold this code. Please report unacceptable
|
||||
behavior to any of the [project's core team](https://github.com/orgs/node-red/teams/core).
|
||||
behavior to any of the project's core team at team@nodered.org.
|
||||
|
||||
## Authors
|
||||
|
||||
|
||||
@@ -1,274 +0,0 @@
|
||||
/**
|
||||
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
(function() {
|
||||
|
||||
function loadNodeList() {
|
||||
$.ajax({
|
||||
headers: {
|
||||
"Accept":"application/json"
|
||||
},
|
||||
cache: false,
|
||||
url: 'nodes',
|
||||
success: function(data) {
|
||||
RED.nodes.setNodeList(data);
|
||||
RED.i18n.loadNodeCatalogs(loadNodes);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function loadNodes() {
|
||||
$.ajax({
|
||||
headers: {
|
||||
"Accept":"text/html"
|
||||
},
|
||||
cache: false,
|
||||
url: 'nodes',
|
||||
success: function(data) {
|
||||
$("body").append(data);
|
||||
$("body").i18n();
|
||||
$("#palette > .palette-spinner").hide();
|
||||
$(".palette-scroll").removeClass("hide");
|
||||
$("#palette-search").removeClass("hide");
|
||||
loadFlows();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function loadFlows() {
|
||||
$.ajax({
|
||||
headers: {
|
||||
"Accept":"application/json",
|
||||
},
|
||||
cache: false,
|
||||
url: 'flows',
|
||||
success: function(nodes) {
|
||||
var currentHash = window.location.hash;
|
||||
RED.nodes.version(nodes.rev);
|
||||
RED.nodes.import(nodes.flows);
|
||||
RED.nodes.dirty(false);
|
||||
RED.view.redraw(true);
|
||||
if (/^#flow\/.+$/.test(currentHash)) {
|
||||
RED.workspaces.show(currentHash.substring(6));
|
||||
}
|
||||
|
||||
var persistentNotifications = {};
|
||||
RED.comms.subscribe("notification/#",function(topic,msg) {
|
||||
var parts = topic.split("/");
|
||||
var notificationId = parts[1];
|
||||
if (notificationId === "runtime-deploy") {
|
||||
// handled in ui/deploy.js
|
||||
return;
|
||||
}
|
||||
if (msg.text) {
|
||||
var text = RED._(msg.text,{default:msg.text});
|
||||
if (!persistentNotifications.hasOwnProperty(notificationId)) {
|
||||
persistentNotifications[notificationId] = RED.notify(text,msg.type,msg.timeout === undefined,msg.timeout);
|
||||
} else {
|
||||
persistentNotifications[notificationId].update(text,msg.timeout);
|
||||
}
|
||||
} else if (persistentNotifications.hasOwnProperty(notificationId)) {
|
||||
persistentNotifications[notificationId].close();
|
||||
delete persistentNotifications[notificationId];
|
||||
}
|
||||
});
|
||||
RED.comms.subscribe("status/#",function(topic,msg) {
|
||||
var parts = topic.split("/");
|
||||
var node = RED.nodes.node(parts[1]);
|
||||
if (node) {
|
||||
if (msg.hasOwnProperty("text")) {
|
||||
if (msg.text[0] !== ".") {
|
||||
msg.text = node._(msg.text.toString(),{defaultValue:msg.text.toString()});
|
||||
}
|
||||
}
|
||||
node.status = msg;
|
||||
node.dirty = true;
|
||||
RED.view.redraw();
|
||||
}
|
||||
});
|
||||
RED.comms.subscribe("node/#",function(topic,msg) {
|
||||
var i,m;
|
||||
var typeList;
|
||||
var info;
|
||||
if (topic == "node/added") {
|
||||
var addedTypes = [];
|
||||
msg.forEach(function(m) {
|
||||
var id = m.id;
|
||||
RED.nodes.addNodeSet(m);
|
||||
addedTypes = addedTypes.concat(m.types);
|
||||
RED.i18n.loadCatalog(id, function() {
|
||||
$.get('nodes/'+id, function(data) {
|
||||
$("body").append(data);
|
||||
});
|
||||
});
|
||||
});
|
||||
if (addedTypes.length) {
|
||||
typeList = "<ul><li>"+addedTypes.join("</li><li>")+"</li></ul>";
|
||||
RED.notify(RED._("palette.event.nodeAdded", {count:addedTypes.length})+typeList,"success");
|
||||
}
|
||||
} else if (topic == "node/removed") {
|
||||
for (i=0;i<msg.length;i++) {
|
||||
m = msg[i];
|
||||
info = RED.nodes.removeNodeSet(m.id);
|
||||
if (info.added) {
|
||||
typeList = "<ul><li>"+m.types.join("</li><li>")+"</li></ul>";
|
||||
RED.notify(RED._("palette.event.nodeRemoved", {count:m.types.length})+typeList,"success");
|
||||
}
|
||||
}
|
||||
} else if (topic == "node/enabled") {
|
||||
if (msg.types) {
|
||||
info = RED.nodes.getNodeSet(msg.id);
|
||||
if (info.added) {
|
||||
RED.nodes.enableNodeSet(msg.id);
|
||||
typeList = "<ul><li>"+msg.types.join("</li><li>")+"</li></ul>";
|
||||
RED.notify(RED._("palette.event.nodeEnabled", {count:msg.types.length})+typeList,"success");
|
||||
} else {
|
||||
$.get('nodes/'+msg.id, function(data) {
|
||||
$("body").append(data);
|
||||
typeList = "<ul><li>"+msg.types.join("</li><li>")+"</li></ul>";
|
||||
RED.notify(RED._("palette.event.nodeAdded", {count:msg.types.length})+typeList,"success");
|
||||
});
|
||||
}
|
||||
}
|
||||
} else if (topic == "node/disabled") {
|
||||
if (msg.types) {
|
||||
RED.nodes.disableNodeSet(msg.id);
|
||||
typeList = "<ul><li>"+msg.types.join("</li><li>")+"</li></ul>";
|
||||
RED.notify(RED._("palette.event.nodeDisabled", {count:msg.types.length})+typeList,"success");
|
||||
}
|
||||
} else if (topic == "node/upgraded") {
|
||||
RED.notify(RED._("palette.event.nodeUpgraded", {module:msg.module,version:msg.version}),"success");
|
||||
RED.nodes.registry.setModulePendingUpdated(msg.module,msg.version);
|
||||
}
|
||||
// Refresh flow library to ensure any examples are updated
|
||||
RED.library.loadFlowLibrary();
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function showAbout() {
|
||||
$.get('red/about', function(data) {
|
||||
var aboutHeader = '<div style="text-align:center;">'+
|
||||
'<img width="50px" src="red/images/node-red-icon.svg" />'+
|
||||
'</div>';
|
||||
|
||||
RED.sidebar.info.set(aboutHeader+marked(data));
|
||||
RED.sidebar.info.show();
|
||||
});
|
||||
}
|
||||
|
||||
function loadEditor() {
|
||||
var menuOptions = [];
|
||||
menuOptions.push({id:"menu-item-view-menu",label:RED._("menu.label.view.view"),options:[
|
||||
// {id:"menu-item-view-show-grid",setting:"view-show-grid",label:RED._("menu.label.view.showGrid"),toggle:true,onselect:"core:toggle-show-grid"},
|
||||
// {id:"menu-item-view-snap-grid",setting:"view-snap-grid",label:RED._("menu.label.view.snapGrid"),toggle:true,onselect:"core:toggle-snap-grid"},
|
||||
// {id:"menu-item-status",setting:"node-show-status",label:RED._("menu.label.displayStatus"),toggle:true,onselect:"core:toggle-status", selected: true},
|
||||
//null,
|
||||
// {id:"menu-item-bidi",label:RED._("menu.label.view.textDir"),options:[
|
||||
// {id:"menu-item-bidi-default",toggle:"text-direction",label:RED._("menu.label.view.defaultDir"),selected: true, onselect:function(s) { if(s){RED.text.bidi.setTextDirection("")}}},
|
||||
// {id:"menu-item-bidi-ltr",toggle:"text-direction",label:RED._("menu.label.view.ltr"), onselect:function(s) { if(s){RED.text.bidi.setTextDirection("ltr")}}},
|
||||
// {id:"menu-item-bidi-rtl",toggle:"text-direction",label:RED._("menu.label.view.rtl"), onselect:function(s) { if(s){RED.text.bidi.setTextDirection("rtl")}}},
|
||||
// {id:"menu-item-bidi-auto",toggle:"text-direction",label:RED._("menu.label.view.auto"), onselect:function(s) { if(s){RED.text.bidi.setTextDirection("auto")}}}
|
||||
// ]},
|
||||
// null,
|
||||
{id:"menu-item-sidebar",label:RED._("menu.label.sidebar.show"),toggle:true,onselect:"core:toggle-sidebar", selected: true},
|
||||
null
|
||||
]});
|
||||
menuOptions.push(null);
|
||||
menuOptions.push({id:"menu-item-import",label:RED._("menu.label.import"),options:[
|
||||
{id:"menu-item-import-clipboard",label:RED._("menu.label.clipboard"),onselect:"core:show-import-dialog"},
|
||||
{id:"menu-item-import-library",label:RED._("menu.label.library"),options:[]}
|
||||
]});
|
||||
menuOptions.push({id:"menu-item-export",label:RED._("menu.label.export"),disabled:true,options:[
|
||||
{id:"menu-item-export-clipboard",label:RED._("menu.label.clipboard"),disabled:true,onselect:"core:show-export-dialog"},
|
||||
{id:"menu-item-export-library",label:RED._("menu.label.library"),disabled:true,onselect:"core:library-export"}
|
||||
]});
|
||||
menuOptions.push(null);
|
||||
menuOptions.push({id:"menu-item-search",label:RED._("menu.label.search"),onselect:"core:search"});
|
||||
menuOptions.push(null);
|
||||
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-delete",label:RED._("menu.label.delete"),onselect:"core:remove-flow"}
|
||||
]});
|
||||
menuOptions.push({id:"menu-item-subflow",label:RED._("menu.label.subflows"), options: [
|
||||
{id:"menu-item-subflow-create",label:RED._("menu.label.createSubflow"),onselect:"core:create-subflow"},
|
||||
{id:"menu-item-subflow-convert",label:RED._("menu.label.selectionToSubflow"),disabled:true,onselect:"core:convert-to-subflow"},
|
||||
]});
|
||||
menuOptions.push(null);
|
||||
if (RED.settings.theme('palette.editable') !== false) {
|
||||
menuOptions.push({id:"menu-item-edit-palette",label:RED._("menu.label.editPalette"),onselect:"core:manage-palette"});
|
||||
menuOptions.push(null);
|
||||
}
|
||||
|
||||
menuOptions.push({id:"menu-item-user-settings",label:RED._("menu.label.userSettings"),onselect:"core:show-user-settings"});
|
||||
menuOptions.push(null);
|
||||
|
||||
menuOptions.push({id:"menu-item-keyboard-shortcuts",label:RED._("menu.label.keyboardShortcuts"),onselect:"core:show-help"});
|
||||
menuOptions.push({id:"menu-item-help",
|
||||
label: RED.settings.theme("menu.menu-item-help.label","Node-RED website"),
|
||||
href: RED.settings.theme("menu.menu-item-help.url","http://nodered.org/docs")
|
||||
});
|
||||
menuOptions.push({id:"menu-item-node-red-version", label:"v"+RED.settings.version, onselect: "core:show-about" });
|
||||
|
||||
|
||||
RED.view.init();
|
||||
RED.userSettings.init();
|
||||
RED.user.init();
|
||||
RED.library.init();
|
||||
RED.keyboard.init();
|
||||
RED.palette.init();
|
||||
if (RED.settings.theme('palette.editable') !== false) {
|
||||
RED.palette.editor.init();
|
||||
}
|
||||
|
||||
RED.sidebar.init();
|
||||
RED.subflow.init();
|
||||
RED.workspaces.init();
|
||||
RED.clipboard.init();
|
||||
RED.search.init();
|
||||
RED.editor.init();
|
||||
RED.diff.init();
|
||||
|
||||
RED.menu.init({id:"btn-sidemenu",options: menuOptions});
|
||||
|
||||
RED.deploy.init(RED.settings.theme("deployButton",null));
|
||||
|
||||
RED.actions.add("core:show-about", showAbout);
|
||||
|
||||
RED.comms.connect();
|
||||
|
||||
$("#main-container").show();
|
||||
$(".header-toolbar").show();
|
||||
|
||||
|
||||
loadNodeList();
|
||||
}
|
||||
|
||||
$(function() {
|
||||
|
||||
if ((window.location.hostname !== "localhost") && (window.location.hostname !== "127.0.0.1")) {
|
||||
document.title = document.title+" : "+window.location.hostname;
|
||||
}
|
||||
|
||||
ace.require("ace/ext/language_tools");
|
||||
|
||||
RED.i18n.init(function() {
|
||||
RED.settings.init(loadEditor);
|
||||
})
|
||||
});
|
||||
})();
|
||||
@@ -1,81 +0,0 @@
|
||||
/**
|
||||
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
|
||||
RED.panels = (function() {
|
||||
|
||||
function createPanel(options) {
|
||||
var container = options.container || $("#"+options.id);
|
||||
var children = container.children();
|
||||
if (children.length !== 2) {
|
||||
throw new Error("Container must have exactly two children");
|
||||
}
|
||||
|
||||
container.addClass("red-ui-panels");
|
||||
var separator = $('<div class="red-ui-panels-separator"></div>').insertAfter(children[0]);
|
||||
var startPosition;
|
||||
var panelHeights = [];
|
||||
var modifiedHeights = false;
|
||||
var panelRatio;
|
||||
|
||||
separator.draggable({
|
||||
axis: "y",
|
||||
containment: container,
|
||||
scroll: false,
|
||||
start:function(event,ui) {
|
||||
var height = container.height();
|
||||
startPosition = ui.position.top;
|
||||
panelHeights = [$(children[0]).height(),$(children[1]).height()];
|
||||
},
|
||||
drag: function(event,ui) {
|
||||
var height = container.height();
|
||||
var delta = ui.position.top-startPosition;
|
||||
var newHeights = [panelHeights[0]+delta,panelHeights[1]-delta];
|
||||
$(children[0]).height(newHeights[0]);
|
||||
$(children[1]).height(newHeights[1]);
|
||||
if (options.resize) {
|
||||
options.resize(newHeights[0],newHeights[1]);
|
||||
}
|
||||
ui.position.top -= delta;
|
||||
panelRatio = newHeights[0]/height;
|
||||
},
|
||||
stop:function(event,ui) {
|
||||
modifiedHeights = true;
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
resize: function(height) {
|
||||
var panelHeights = [$(children[0]).height(),$(children[1]).height()];
|
||||
container.height(height);
|
||||
if (modifiedHeights) {
|
||||
var topPanelHeight = panelRatio*height;
|
||||
var bottomPanelHeight = height - topPanelHeight - 48;
|
||||
panelHeights = [topPanelHeight,bottomPanelHeight];
|
||||
$(children[0]).height(panelHeights[0]);
|
||||
$(children[1]).height(panelHeights[1]);
|
||||
}
|
||||
if (options.resize) {
|
||||
options.resize(panelHeights[0],panelHeights[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
create: createPanel
|
||||
}
|
||||
})();
|
||||
@@ -1,135 +0,0 @@
|
||||
/**
|
||||
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
RED.popover = (function() {
|
||||
var deltaSizes = {
|
||||
"default": {
|
||||
top: 10,
|
||||
leftRight: 17,
|
||||
leftLeft: 25
|
||||
},
|
||||
"small": {
|
||||
top: 5,
|
||||
leftRight: 8,
|
||||
leftLeft: 16
|
||||
}
|
||||
}
|
||||
function createPopover(options) {
|
||||
var target = options.target;
|
||||
var direction = options.direction || "right";
|
||||
var trigger = options.trigger;
|
||||
var content = options.content;
|
||||
var delay = options.delay;
|
||||
var width = options.width||"auto";
|
||||
var size = options.size||"default";
|
||||
if (!deltaSizes[size]) {
|
||||
throw new Error("Invalid RED.popover size value:",size);
|
||||
}
|
||||
|
||||
var timer = null;
|
||||
var active;
|
||||
var div;
|
||||
|
||||
var openPopup = function() {
|
||||
if (active) {
|
||||
div = $('<div class="red-ui-popover red-ui-popover-'+direction+'"></div>').appendTo("body");
|
||||
if (size !== "default") {
|
||||
div.addClass("red-ui-popover-size-"+size);
|
||||
}
|
||||
if (typeof content === 'function') {
|
||||
content.call(res).appendTo(div);
|
||||
} else {
|
||||
div.html(content);
|
||||
}
|
||||
if (width !== "auto") {
|
||||
div.width(width);
|
||||
}
|
||||
|
||||
|
||||
var targetPos = target.offset();
|
||||
var targetWidth = target.width();
|
||||
var targetHeight = target.height();
|
||||
|
||||
var divHeight = div.height();
|
||||
var divWidth = div.width();
|
||||
if (direction === 'right') {
|
||||
div.css({top: targetPos.top+targetHeight/2-divHeight/2-deltaSizes[size].top,left:targetPos.left+targetWidth+deltaSizes[size].leftRight});
|
||||
} else if (direction === 'left') {
|
||||
div.css({top: targetPos.top+targetHeight/2-divHeight/2-deltaSizes[size].top,left:targetPos.left-deltaSizes[size].leftLeft-divWidth});
|
||||
}
|
||||
|
||||
div.fadeIn("fast");
|
||||
}
|
||||
}
|
||||
var closePopup = function() {
|
||||
if (!active) {
|
||||
if (div) {
|
||||
div.fadeOut("fast",function() {
|
||||
$(this).remove();
|
||||
});
|
||||
div = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (trigger === 'hover') {
|
||||
|
||||
target.on('mouseenter',function(e) {
|
||||
clearTimeout(timer);
|
||||
active = true;
|
||||
timer = setTimeout(openPopup,delay.show);
|
||||
});
|
||||
target.on('mouseleave', function(e) {
|
||||
if (timer) {
|
||||
clearTimeout(timer);
|
||||
}
|
||||
active = false;
|
||||
setTimeout(closePopup,delay.hide);
|
||||
});
|
||||
} else if (trigger === 'click') {
|
||||
target.click(function(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
active = !active;
|
||||
if (!active) {
|
||||
closePopup();
|
||||
} else {
|
||||
openPopup();
|
||||
}
|
||||
});
|
||||
}
|
||||
var res = {
|
||||
setContent: function(_content) {
|
||||
content = _content;
|
||||
},
|
||||
open: function () {
|
||||
active = true;
|
||||
openPopup();
|
||||
},
|
||||
close: function () {
|
||||
active = false;
|
||||
closePopup();
|
||||
}
|
||||
}
|
||||
return res;
|
||||
|
||||
}
|
||||
|
||||
return {
|
||||
create: createPopover
|
||||
}
|
||||
|
||||
})();
|
||||
@@ -1,379 +0,0 @@
|
||||
/**
|
||||
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
|
||||
|
||||
RED.tabs = (function() {
|
||||
function createTabs(options) {
|
||||
var tabs = {};
|
||||
var currentTabWidth;
|
||||
var currentActiveTabWidth = 0;
|
||||
|
||||
var ul = options.element || $("#"+options.id);
|
||||
var wrapper = ul.wrap( "<div>" ).parent();
|
||||
var scrollContainer = ul.wrap( "<div>" ).parent();
|
||||
wrapper.addClass("red-ui-tabs");
|
||||
if (options.vertical) {
|
||||
wrapper.addClass("red-ui-tabs-vertical");
|
||||
}
|
||||
if (options.addButton && typeof options.addButton === 'function') {
|
||||
wrapper.addClass("red-ui-tabs-add");
|
||||
var addButton = $('<div class="red-ui-tab-button"><a href="#"><i class="fa fa-plus"></i></a></div>').appendTo(wrapper);
|
||||
addButton.find('a').click(function(evt) {
|
||||
evt.preventDefault();
|
||||
options.addButton();
|
||||
})
|
||||
|
||||
}
|
||||
var scrollLeft;
|
||||
var scrollRight;
|
||||
|
||||
if (options.scrollable) {
|
||||
wrapper.addClass("red-ui-tabs-scrollable");
|
||||
scrollContainer.addClass("red-ui-tabs-scroll-container");
|
||||
scrollContainer.scroll(updateScroll);
|
||||
scrollLeft = $('<div class="red-ui-tab-button red-ui-tab-scroll red-ui-tab-scroll-left"><a href="#" style="display:none;"><i class="fa fa-caret-left"></i></a></div>').appendTo(wrapper).find("a");
|
||||
scrollLeft.on('mousedown',function(evt) { scrollEventHandler(evt,'-=150') }).on('click',function(evt){ evt.preventDefault();});
|
||||
scrollRight = $('<div class="red-ui-tab-button red-ui-tab-scroll red-ui-tab-scroll-right"><a href="#" style="display:none;"><i class="fa fa-caret-right"></i></a></div>').appendTo(wrapper).find("a");
|
||||
scrollRight.on('mousedown',function(evt) { scrollEventHandler(evt,'+=150') }).on('click',function(evt){ evt.preventDefault();});
|
||||
}
|
||||
function scrollEventHandler(evt,dir) {
|
||||
evt.preventDefault();
|
||||
if ($(this).hasClass('disabled')) {
|
||||
return;
|
||||
}
|
||||
var currentScrollLeft = scrollContainer.scrollLeft();
|
||||
scrollContainer.animate( { scrollLeft: dir }, 100);
|
||||
var interval = setInterval(function() {
|
||||
var newScrollLeft = scrollContainer.scrollLeft()
|
||||
if (newScrollLeft === currentScrollLeft) {
|
||||
clearInterval(interval);
|
||||
return;
|
||||
}
|
||||
currentScrollLeft = newScrollLeft;
|
||||
scrollContainer.animate( { scrollLeft: dir }, 100);
|
||||
},100);
|
||||
$(this).one('mouseup',function() {
|
||||
clearInterval(interval);
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
ul.children().first().addClass("active");
|
||||
ul.children().addClass("red-ui-tab");
|
||||
|
||||
function onTabClick() {
|
||||
if (options.onclick) {
|
||||
options.onclick(tabs[$(this).attr('href').slice(1)]);
|
||||
}
|
||||
activateTab($(this));
|
||||
return false;
|
||||
}
|
||||
|
||||
function updateScroll() {
|
||||
if (ul.children().length !== 0) {
|
||||
var sl = scrollContainer.scrollLeft();
|
||||
var scWidth = scrollContainer.width();
|
||||
var ulWidth = ul.width();
|
||||
if (sl === 0) {
|
||||
scrollLeft.hide();
|
||||
} else {
|
||||
scrollLeft.show();
|
||||
}
|
||||
if (sl === ulWidth-scWidth) {
|
||||
scrollRight.hide();
|
||||
} else {
|
||||
scrollRight.show();
|
||||
}
|
||||
}
|
||||
}
|
||||
function onTabDblClick() {
|
||||
if (options.ondblclick) {
|
||||
options.ondblclick(tabs[$(this).attr('href').slice(1)]);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function activateTab(link) {
|
||||
if (typeof link === "string") {
|
||||
link = ul.find("a[href='#"+link+"']");
|
||||
}
|
||||
if (link.length === 0) {
|
||||
return;
|
||||
}
|
||||
if (!link.parent().hasClass("active")) {
|
||||
ul.children().removeClass("active");
|
||||
ul.children().css({"transition": "width 100ms"});
|
||||
link.parent().addClass("active");
|
||||
if (options.scrollable) {
|
||||
var pos = link.parent().position().left;
|
||||
if (pos-21 < 0) {
|
||||
scrollContainer.animate( { scrollLeft: '+='+(pos-50) }, 300);
|
||||
} else if (pos + 120 > scrollContainer.width()) {
|
||||
scrollContainer.animate( { scrollLeft: '+='+(pos + 140-scrollContainer.width()) }, 300);
|
||||
}
|
||||
}
|
||||
if (options.onchange) {
|
||||
options.onchange(tabs[link.attr('href').slice(1)]);
|
||||
}
|
||||
updateTabWidths();
|
||||
setTimeout(function() {
|
||||
ul.children().css({"transition": ""});
|
||||
},100);
|
||||
}
|
||||
}
|
||||
function activatePreviousTab() {
|
||||
var previous = ul.find("li.active").prev();
|
||||
if (previous.length > 0) {
|
||||
activateTab(previous.find("a"));
|
||||
}
|
||||
}
|
||||
function activateNextTab() {
|
||||
var next = ul.find("li.active").next();
|
||||
if (next.length > 0) {
|
||||
activateTab(next.find("a"));
|
||||
}
|
||||
}
|
||||
|
||||
function updateTabWidths() {
|
||||
if (options.vertical) {
|
||||
return;
|
||||
}
|
||||
var tabs = ul.find("li.red-ui-tab");
|
||||
var width = wrapper.width();
|
||||
var tabCount = tabs.size();
|
||||
var tabWidth = (width-12-(tabCount*6))/tabCount;
|
||||
currentTabWidth = (100*tabWidth/width)+"%";
|
||||
currentActiveTabWidth = currentTabWidth+"%";
|
||||
if (options.scrollable) {
|
||||
tabWidth = Math.max(tabWidth,140);
|
||||
currentTabWidth = tabWidth+"px";
|
||||
currentActiveTabWidth = 0;
|
||||
var listWidth = Math.max(wrapper.width(),12+(tabWidth+6)*tabCount);
|
||||
ul.width(listWidth);
|
||||
updateScroll();
|
||||
} else if (options.hasOwnProperty("minimumActiveTabWidth")) {
|
||||
if (tabWidth < options.minimumActiveTabWidth) {
|
||||
tabCount -= 1;
|
||||
tabWidth = (width-12-options.minimumActiveTabWidth-(tabCount*6))/tabCount;
|
||||
currentTabWidth = (100*tabWidth/width)+"%";
|
||||
currentActiveTabWidth = options.minimumActiveTabWidth+"px";
|
||||
} else {
|
||||
currentActiveTabWidth = 0;
|
||||
}
|
||||
}
|
||||
tabs.css({width:currentTabWidth});
|
||||
if (tabWidth < 50) {
|
||||
ul.find(".red-ui-tab-close").hide();
|
||||
ul.find(".red-ui-tab-icon").hide();
|
||||
ul.find(".red-ui-tab-label").css({paddingLeft:Math.min(12,Math.max(0,tabWidth-38))+"px"})
|
||||
} else {
|
||||
ul.find(".red-ui-tab-close").show();
|
||||
ul.find(".red-ui-tab-icon").show();
|
||||
ul.find(".red-ui-tab-label").css({paddingLeft:""})
|
||||
}
|
||||
if (currentActiveTabWidth !== 0) {
|
||||
ul.find("li.red-ui-tab.active").css({"width":options.minimumActiveTabWidth});
|
||||
ul.find("li.red-ui-tab.active .red-ui-tab-close").show();
|
||||
ul.find("li.red-ui-tab.active .red-ui-tab-icon").show();
|
||||
ul.find("li.red-ui-tab.active .red-ui-tab-label").css({paddingLeft:""})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ul.find("li.red-ui-tab a").on("click",onTabClick).on("dblclick",onTabDblClick);
|
||||
setTimeout(function() {
|
||||
updateTabWidths();
|
||||
},0);
|
||||
|
||||
|
||||
function removeTab(id) {
|
||||
var li = ul.find("a[href='#"+id+"']").parent();
|
||||
if (li.hasClass("active")) {
|
||||
var tab = li.prev();
|
||||
if (tab.size() === 0) {
|
||||
tab = li.next();
|
||||
}
|
||||
activateTab(tab.find("a"));
|
||||
}
|
||||
li.remove();
|
||||
if (options.onremove) {
|
||||
options.onremove(tabs[id]);
|
||||
}
|
||||
delete tabs[id];
|
||||
updateTabWidths();
|
||||
}
|
||||
|
||||
return {
|
||||
addTab: function(tab) {
|
||||
tabs[tab.id] = tab;
|
||||
var li = $("<li/>",{class:"red-ui-tab"}).appendTo(ul);
|
||||
li.attr('id',"red-ui-tab-"+(tab.id.replace(".","-")));
|
||||
li.data("tabId",tab.id);
|
||||
var link = $("<a/>",{href:"#"+tab.id, class:"red-ui-tab-label"}).appendTo(li);
|
||||
if (tab.icon) {
|
||||
$('<img src="'+tab.icon+'" class="red-ui-tab-icon"/>').appendTo(link);
|
||||
}
|
||||
var span = $('<span/>',{class:"bidiAware"}).text(tab.label).appendTo(link);
|
||||
span.attr('dir', RED.text.bidi.resolveBaseTextDir(tab.label));
|
||||
|
||||
link.on("click",onTabClick);
|
||||
link.on("dblclick",onTabDblClick);
|
||||
if (tab.closeable) {
|
||||
var closeLink = $("<a/>",{href:"#",class:"red-ui-tab-close"}).appendTo(li);
|
||||
closeLink.append('<i class="fa fa-times" />');
|
||||
|
||||
closeLink.on("click",function(event) {
|
||||
event.preventDefault();
|
||||
removeTab(tab.id);
|
||||
});
|
||||
}
|
||||
updateTabWidths();
|
||||
if (options.onadd) {
|
||||
options.onadd(tab);
|
||||
}
|
||||
link.attr("title",tab.label);
|
||||
if (ul.find("li.red-ui-tab").size() == 1) {
|
||||
activateTab(link);
|
||||
}
|
||||
if (options.onreorder) {
|
||||
var originalTabOrder;
|
||||
var tabDragIndex;
|
||||
var tabElements = [];
|
||||
var startDragIndex;
|
||||
|
||||
li.draggable({
|
||||
axis:"x",
|
||||
distance: 20,
|
||||
start: function(event,ui) {
|
||||
originalTabOrder = [];
|
||||
tabElements = [];
|
||||
ul.children().each(function(i) {
|
||||
tabElements[i] = {
|
||||
el:$(this),
|
||||
text: $(this).text(),
|
||||
left: $(this).position().left,
|
||||
width: $(this).width()
|
||||
};
|
||||
if ($(this).is(li)) {
|
||||
tabDragIndex = i;
|
||||
startDragIndex = i;
|
||||
}
|
||||
originalTabOrder.push($(this).data("tabId"));
|
||||
});
|
||||
ul.children().each(function(i) {
|
||||
if (i!==tabDragIndex) {
|
||||
$(this).css({
|
||||
position: 'absolute',
|
||||
left: tabElements[i].left+"px",
|
||||
width: tabElements[i].width+2,
|
||||
transition: "left 0.3s"
|
||||
});
|
||||
}
|
||||
|
||||
})
|
||||
if (!li.hasClass('active')) {
|
||||
li.css({'zIndex':1});
|
||||
}
|
||||
},
|
||||
drag: function(event,ui) {
|
||||
ui.position.left += tabElements[tabDragIndex].left+scrollContainer.scrollLeft();
|
||||
var tabCenter = ui.position.left + tabElements[tabDragIndex].width/2 - scrollContainer.scrollLeft();
|
||||
for (var i=0;i<tabElements.length;i++) {
|
||||
if (i === tabDragIndex) {
|
||||
continue;
|
||||
}
|
||||
if (tabCenter > tabElements[i].left && tabCenter < tabElements[i].left+tabElements[i].width) {
|
||||
if (i < tabDragIndex) {
|
||||
tabElements[i].left += tabElements[tabDragIndex].width+8;
|
||||
tabElements[tabDragIndex].el.detach().insertBefore(tabElements[i].el);
|
||||
} else {
|
||||
tabElements[i].left -= tabElements[tabDragIndex].width+8;
|
||||
tabElements[tabDragIndex].el.detach().insertAfter(tabElements[i].el);
|
||||
}
|
||||
tabElements[i].el.css({left:tabElements[i].left+"px"});
|
||||
|
||||
tabElements.splice(i, 0, tabElements.splice(tabDragIndex, 1)[0]);
|
||||
|
||||
tabDragIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
stop: function(event,ui) {
|
||||
ul.children().css({position:"relative",left:"",transition:""});
|
||||
if (!li.hasClass('active')) {
|
||||
li.css({zIndex:""});
|
||||
}
|
||||
updateTabWidths();
|
||||
if (startDragIndex !== tabDragIndex) {
|
||||
options.onreorder(originalTabOrder, $.makeArray(ul.children().map(function() { return $(this).data('tabId');})));
|
||||
}
|
||||
activateTab(tabElements[tabDragIndex].el.data('tabId'));
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
removeTab: removeTab,
|
||||
activateTab: activateTab,
|
||||
nextTab: activateNextTab,
|
||||
previousTab: activatePreviousTab,
|
||||
resize: updateTabWidths,
|
||||
count: function() {
|
||||
return ul.find("li.red-ui-tab").size();
|
||||
},
|
||||
contains: function(id) {
|
||||
return ul.find("a[href='#"+id+"']").length > 0;
|
||||
},
|
||||
renameTab: function(id,label) {
|
||||
tabs[id].label = label;
|
||||
var tab = ul.find("a[href='#"+id+"']");
|
||||
tab.attr("title",label);
|
||||
tab.find("span.bidiAware").text(label).attr('dir', RED.text.bidi.resolveBaseTextDir(label));
|
||||
updateTabWidths();
|
||||
},
|
||||
order: function(order) {
|
||||
var existingTabOrder = $.makeArray(ul.children().map(function() { return $(this).data('tabId');}));
|
||||
if (existingTabOrder.length !== order.length) {
|
||||
return
|
||||
}
|
||||
var i;
|
||||
var match = true;
|
||||
for (i=0;i<order.length;i++) {
|
||||
if (order[i] !== existingTabOrder[i]) {
|
||||
match = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (match) {
|
||||
return;
|
||||
}
|
||||
var existingTabMap = {};
|
||||
var existingTabs = ul.children().detach().each(function() {
|
||||
existingTabMap[$(this).data("tabId")] = $(this);
|
||||
});
|
||||
for (i=0;i<order.length;i++) {
|
||||
existingTabMap[order[i]].appendTo(ul);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
create: createTabs
|
||||
}
|
||||
})();
|
||||
1271
editor/js/ui/diff.js
1271
editor/js/ui/diff.js
File diff suppressed because it is too large
Load Diff
@@ -1,87 +0,0 @@
|
||||
/**
|
||||
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
RED.notify = (function() {
|
||||
var currentNotifications = [];
|
||||
var c = 0;
|
||||
return function(msg,type,fixed,timeout) {
|
||||
if (currentNotifications.length > 4) {
|
||||
var ll = currentNotifications.length;
|
||||
for (var i = 0;ll > 4 && i<currentNotifications.length;i+=1) {
|
||||
var notifiction = currentNotifications[i];
|
||||
if (!notifiction.fixed) {
|
||||
window.clearTimeout(notifiction.timeoutid);
|
||||
notifiction.close();
|
||||
ll -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
var n = document.createElement("div");
|
||||
n.id="red-notification-"+c;
|
||||
n.className = "notification";
|
||||
n.fixed = fixed;
|
||||
if (type) {
|
||||
n.className = "notification notification-"+type;
|
||||
}
|
||||
n.style.display = "none";
|
||||
if (typeof msg === "string") {
|
||||
n.innerHTML = msg;
|
||||
} else {
|
||||
$(n).append(msg);
|
||||
}
|
||||
$("#notifications").append(n);
|
||||
$(n).slideDown(300);
|
||||
n.close = (function() {
|
||||
var nn = n;
|
||||
return function() {
|
||||
currentNotifications.splice(currentNotifications.indexOf(nn),1);
|
||||
$(nn).slideUp(300, function() {
|
||||
nn.parentNode.removeChild(nn);
|
||||
});
|
||||
};
|
||||
})();
|
||||
|
||||
n.update = (function() {
|
||||
var nn = n;
|
||||
return function(msg,timeout) {
|
||||
if (typeof msg === "string") {
|
||||
nn.innerHTML = msg;
|
||||
} else {
|
||||
$(nn).empty().append(msg);
|
||||
}
|
||||
if (timeout !== undefined && timeout > 0) {
|
||||
window.clearTimeout(nn.timeoutid);
|
||||
nn.timeoutid = window.setTimeout(nn.close,timeout);
|
||||
} else {
|
||||
window.clearTimeout(nn.timeoutid);
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
||||
if (!fixed) {
|
||||
$(n).click((function() {
|
||||
var nn = n;
|
||||
return function() {
|
||||
nn.close();
|
||||
window.clearTimeout(nn.timeoutid);
|
||||
};
|
||||
})());
|
||||
n.timeoutid = window.setTimeout(n.close,timeout||3000);
|
||||
}
|
||||
currentNotifications.push(n);
|
||||
c+=1;
|
||||
return n;
|
||||
}
|
||||
})();
|
||||
@@ -1,394 +0,0 @@
|
||||
/**
|
||||
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
RED.sidebar.info = (function() {
|
||||
|
||||
marked.setOptions({
|
||||
renderer: new marked.Renderer(),
|
||||
gfm: true,
|
||||
tables: true,
|
||||
breaks: false,
|
||||
pedantic: false,
|
||||
sanitize: true,
|
||||
smartLists: true,
|
||||
smartypants: false
|
||||
});
|
||||
|
||||
var content;
|
||||
var sections;
|
||||
var nodeSection;
|
||||
var infoSection;
|
||||
var tipBox;
|
||||
|
||||
var expandedSections = {
|
||||
"property": false
|
||||
};
|
||||
|
||||
function init() {
|
||||
|
||||
content = document.createElement("div");
|
||||
content.className = "sidebar-node-info"
|
||||
|
||||
RED.actions.add("core:show-info-tab",show);
|
||||
|
||||
var stackContainer = $("<div>",{class:"sidebar-node-info-stack"}).appendTo(content);
|
||||
|
||||
sections = RED.stack.create({
|
||||
container: stackContainer
|
||||
}).hide();
|
||||
|
||||
nodeSection = sections.add({
|
||||
title: "Node",
|
||||
collapsible: false
|
||||
});
|
||||
infoSection = sections.add({
|
||||
title: "Information",
|
||||
collapsible: false
|
||||
});
|
||||
infoSection.content.css("padding","6px");
|
||||
infoSection.container.css("border-bottom","none");
|
||||
|
||||
var tipContainer = $('<div class="node-info-tips"></div>').appendTo(content);
|
||||
tipBox = $('<div class="node-info-tip"></div>').appendTo(tipContainer);
|
||||
var tipButtons = $('<div class="node-info-tips-buttons"></div>').appendTo(tipContainer);
|
||||
|
||||
var tipRefresh = $('<a href="#" class="workspace-footer-button"><i class="fa fa-refresh"></a>').appendTo(tipButtons);
|
||||
tipRefresh.click(function(e) {
|
||||
e.preventDefault();
|
||||
tips.next();
|
||||
})
|
||||
|
||||
var tipClose = $('<a href="#" class="workspace-footer-button"><i class="fa fa-times"></a>').appendTo(tipButtons);
|
||||
tipClose.click(function(e) {
|
||||
e.preventDefault();
|
||||
RED.actions.invoke("core:toggle-show-tips");
|
||||
RED.notify(RED._("sidebar.info.showTips"));
|
||||
});
|
||||
|
||||
RED.sidebar.addTab({
|
||||
id: "info",
|
||||
label: RED._("sidebar.info.label"),
|
||||
name: RED._("sidebar.info.name"),
|
||||
content: content,
|
||||
enableOnEdit: true
|
||||
});
|
||||
if (tips.enabled()) {
|
||||
tips.start();
|
||||
} else {
|
||||
tips.stop();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function show() {
|
||||
RED.sidebar.show("info");
|
||||
}
|
||||
|
||||
function jsonFilter(key,value) {
|
||||
if (key === "") {
|
||||
return value;
|
||||
}
|
||||
var t = typeof value;
|
||||
if ($.isArray(value)) {
|
||||
return "[array:"+value.length+"]";
|
||||
} else if (t === "object") {
|
||||
return "[object]"
|
||||
} else if (t === "string") {
|
||||
if (value.length > 30) {
|
||||
return value.substring(0,30)+" ...";
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
function addTargetToExternalLinks(el) {
|
||||
$(el).find("a").each(function(el) {
|
||||
var href = $(this).attr('href');
|
||||
if (/^https?:/.test(href)) {
|
||||
$(this).attr('target','_blank');
|
||||
}
|
||||
});
|
||||
return el;
|
||||
}
|
||||
function refresh(node) {
|
||||
sections.show();
|
||||
$(nodeSection.content).empty();
|
||||
$(infoSection.content).empty();
|
||||
|
||||
var table = $('<table class="node-info"></table>');
|
||||
var tableBody = $('<tbody>').appendTo(table);
|
||||
var propRow;
|
||||
var subflowNode;
|
||||
if (node.type === "tab") {
|
||||
nodeSection.title.html("Flow");
|
||||
propRow = $('<tr class="node-info-node-row"><td>Name</td><td></td></tr>').appendTo(tableBody);
|
||||
$(propRow.children()[1]).html(' '+(node.label||""))
|
||||
propRow = $('<tr class="node-info-node-row"><td>'+RED._("sidebar.info.id")+"</td><td></td></tr>").appendTo(tableBody);
|
||||
RED.utils.createObjectElement(node.id).appendTo(propRow.children()[1]);
|
||||
propRow = $('<tr class="node-info-node-row"><td>Status</td><td></td></tr>').appendTo(tableBody);
|
||||
$(propRow.children()[1]).html((!!!node.disabled)?"Enabled":"Disabled")
|
||||
} else {
|
||||
nodeSection.title.html("Node");
|
||||
if (node.type !== "subflow" && node.name) {
|
||||
$('<tr class="node-info-node-row"><td>'+RED._("common.label.name")+'</td><td> <span class="bidiAware" dir="'+RED.text.bidi.resolveBaseTextDir(node.name)+'">'+node.name+'</span></td></tr>').appendTo(tableBody);
|
||||
}
|
||||
$('<tr class="node-info-node-row"><td>'+RED._("sidebar.info.type")+"</td><td> "+node.type+"</td></tr>").appendTo(tableBody);
|
||||
propRow = $('<tr class="node-info-node-row"><td>'+RED._("sidebar.info.id")+"</td><td></td></tr>").appendTo(tableBody);
|
||||
RED.utils.createObjectElement(node.id).appendTo(propRow.children()[1]);
|
||||
|
||||
var m = /^subflow(:(.+))?$/.exec(node.type);
|
||||
|
||||
if (!m && node.type != "subflow" && node.type != "comment") {
|
||||
if (node._def) {
|
||||
var count = 0;
|
||||
var defaults = node._def.defaults;
|
||||
for (var n in defaults) {
|
||||
if (n != "name" && defaults.hasOwnProperty(n)) {
|
||||
var val = node[n];
|
||||
var type = typeof val;
|
||||
count++;
|
||||
propRow = $('<tr class="node-info-property-row'+(expandedSections.property?"":" hide")+'"><td>'+n+"</td><td></td></tr>").appendTo(tableBody);
|
||||
if (defaults[n].type) {
|
||||
var configNode = RED.nodes.node(val);
|
||||
if (!configNode) {
|
||||
RED.utils.createObjectElement(undefined).appendTo(propRow.children()[1]);
|
||||
} else {
|
||||
var configLabel = RED.utils.getNodeLabel(configNode,val);
|
||||
var container = propRow.children()[1];
|
||||
|
||||
var div = $('<span>',{class:""}).appendTo(container);
|
||||
var nodeDiv = $('<div>',{class:"palette_node palette_node_small"}).appendTo(div);
|
||||
var colour = configNode._def.color;
|
||||
var icon_url = RED.utils.getNodeIcon(configNode._def);
|
||||
nodeDiv.css({'backgroundColor':colour, "cursor":"pointer"});
|
||||
var iconContainer = $('<div/>',{class:"palette_icon_container"}).appendTo(nodeDiv);
|
||||
$('<div/>',{class:"palette_icon",style:"background-image: url("+icon_url+")"}).appendTo(iconContainer);
|
||||
var nodeContainer = $('<span></span>').css({"verticalAlign":"top","marginLeft":"6px"}).html(configLabel).appendTo(container);
|
||||
|
||||
nodeDiv.on('dblclick',function() {
|
||||
RED.editor.editConfig("", configNode.type, configNode.id);
|
||||
})
|
||||
|
||||
}
|
||||
} else {
|
||||
RED.utils.createObjectElement(val).appendTo(propRow.children()[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (count > 0) {
|
||||
$('<tr class="node-info-property-expand blank"><td colspan="2"><a href="#" class=" node-info-property-header'+(expandedSections.property?" expanded":"")+'"><span class="node-info-property-show-more">show more</span><span class="node-info-property-show-less">show less</span> <i class="fa fa-caret-down"></i></a></td></tr>').appendTo(tableBody);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m) {
|
||||
if (m[2]) {
|
||||
subflowNode = RED.nodes.subflow(m[2]);
|
||||
} else {
|
||||
subflowNode = node;
|
||||
}
|
||||
|
||||
$('<tr class="blank"><th colspan="2">'+RED._("sidebar.info.subflow")+'</th></tr>').appendTo(tableBody);
|
||||
|
||||
var userCount = 0;
|
||||
var subflowType = "subflow:"+subflowNode.id;
|
||||
RED.nodes.eachNode(function(n) {
|
||||
if (n.type === subflowType) {
|
||||
userCount++;
|
||||
}
|
||||
});
|
||||
$('<tr class="node-info-subflow-row"><td>'+RED._("common.label.name")+'</td><td><span class="bidiAware" dir=\"'+RED.text.bidi.resolveBaseTextDir(subflowNode.name)+'">'+subflowNode.name+'</span></td></tr>').appendTo(tableBody);
|
||||
$('<tr class="node-info-subflow-row"><td>'+RED._("sidebar.info.instances")+"</td><td>"+userCount+'</td></tr>').appendTo(tableBody);
|
||||
}
|
||||
}
|
||||
$(table).appendTo(nodeSection.content);
|
||||
|
||||
var infoText = "";
|
||||
|
||||
if (!subflowNode && node.type !== "comment" && node.type !== "tab") {
|
||||
var helpText = $("script[data-help-name='"+node.type+"']").html()||"";
|
||||
infoText = helpText;
|
||||
} else if (node.type === "tab") {
|
||||
infoText = marked(node.info||"");
|
||||
}
|
||||
|
||||
if (subflowNode) {
|
||||
infoText = infoText + marked(subflowNode.info||"");
|
||||
} else if (node._def && node._def.info) {
|
||||
var info = node._def.info;
|
||||
var textInfo = (typeof info === "function" ? info.call(node) : info);
|
||||
// TODO: help
|
||||
infoText = infoText + marked(textInfo);
|
||||
}
|
||||
if (infoText) {
|
||||
setInfoText(infoText);
|
||||
}
|
||||
|
||||
|
||||
$(".node-info-property-header").click(function(e) {
|
||||
e.preventDefault();
|
||||
expandedSections["property"] = !expandedSections["property"];
|
||||
$(this).toggleClass("expanded",expandedSections["property"]);
|
||||
$(".node-info-property-row").toggle(expandedSections["property"]);
|
||||
});
|
||||
}
|
||||
function setInfoText(infoText) {
|
||||
var info = addTargetToExternalLinks($('<div class="node-help"><span class="bidiAware" dir=\"'+RED.text.bidi.resolveBaseTextDir(infoText)+'">'+infoText+'</span></div>')).appendTo(infoSection.content);
|
||||
info.find(".bidiAware").contents().filter(function() { return this.nodeType === 3 && this.textContent.trim() !== "" }).wrap( "<span></span>" );
|
||||
var foldingHeader = "H3";
|
||||
info.find(foldingHeader).wrapInner('<a class="node-info-header expanded" href="#"></a>')
|
||||
.find("a").prepend('<i class="fa fa-angle-right">').click(function(e) {
|
||||
e.preventDefault();
|
||||
var isExpanded = $(this).hasClass('expanded');
|
||||
var el = $(this).parent().next();
|
||||
while(el.length === 1 && el[0].nodeName !== foldingHeader) {
|
||||
el.toggle(!isExpanded);
|
||||
el = el.next();
|
||||
}
|
||||
$(this).toggleClass('expanded',!isExpanded);
|
||||
})
|
||||
}
|
||||
var tips = (function() {
|
||||
var enabled = true;
|
||||
var startDelay = 1000;
|
||||
var cycleDelay = 15000;
|
||||
var startTimeout;
|
||||
var refreshTimeout;
|
||||
var tipCount = -1;
|
||||
|
||||
RED.actions.add("core:toggle-show-tips",function(state) {
|
||||
if (state === undefined) {
|
||||
RED.userSettings.toggle("view-show-tips");
|
||||
} else {
|
||||
enabled = state;
|
||||
if (enabled) {
|
||||
startTips();
|
||||
} else {
|
||||
stopTips();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function setTip() {
|
||||
var r = Math.floor(Math.random() * tipCount);
|
||||
var tip = RED._("infotips:info.tip"+r);
|
||||
|
||||
var m;
|
||||
while ((m=/({{(.*?)}})/.exec(tip))) {
|
||||
var shortcut = RED.keyboard.getShortcut(m[2]);
|
||||
if (shortcut) {
|
||||
tip = tip.replace(m[1],RED.keyboard.formatKey(shortcut.key));
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
while ((m=/(\[(.*?)\])/.exec(tip))) {
|
||||
tip = tip.replace(m[1],RED.keyboard.formatKey(m[2]));
|
||||
}
|
||||
tipBox.html(tip).fadeIn(200);
|
||||
if (startTimeout) {
|
||||
startTimeout = null;
|
||||
refreshTimeout = setInterval(cycleTips,cycleDelay);
|
||||
}
|
||||
}
|
||||
function cycleTips() {
|
||||
tipBox.fadeOut(300,function() {
|
||||
setTip();
|
||||
})
|
||||
}
|
||||
function startTips() {
|
||||
$(".sidebar-node-info").addClass('show-tips');
|
||||
if (enabled) {
|
||||
if (!startTimeout && !refreshTimeout) {
|
||||
if (tipCount === -1) {
|
||||
do {
|
||||
tipCount++;
|
||||
} while(RED._("infotips:info.tip"+tipCount)!=="infotips:info.tip"+tipCount);
|
||||
}
|
||||
startTimeout = setTimeout(setTip,startDelay);
|
||||
}
|
||||
}
|
||||
}
|
||||
function stopTips() {
|
||||
$(".sidebar-node-info").removeClass('show-tips');
|
||||
clearInterval(refreshTimeout);
|
||||
clearTimeout(startTimeout);
|
||||
refreshTimeout = null;
|
||||
startTimeout = null;
|
||||
}
|
||||
function nextTip() {
|
||||
clearInterval(refreshTimeout);
|
||||
startTimeout = true;
|
||||
setTip();
|
||||
}
|
||||
return {
|
||||
start: startTips,
|
||||
stop: stopTips,
|
||||
next: nextTip,
|
||||
enabled: function() { return enabled; }
|
||||
}
|
||||
})();
|
||||
|
||||
function clear() {
|
||||
sections.hide();
|
||||
//
|
||||
}
|
||||
|
||||
function set(html) {
|
||||
// tips.stop();
|
||||
sections.show();
|
||||
nodeSection.container.hide();
|
||||
$(infoSection.content).empty();
|
||||
setInfoText(html);
|
||||
$(".sidebar-node-info-stack").scrollTop(0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
RED.events.on("view:selection-changed",function(selection) {
|
||||
if (selection.nodes) {
|
||||
if (selection.nodes.length == 1) {
|
||||
var node = selection.nodes[0];
|
||||
if (node.type === "subflow" && node.direction) {
|
||||
refresh(RED.nodes.subflow(node.z));
|
||||
} else {
|
||||
refresh(node);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var activeWS = RED.workspaces.active();
|
||||
|
||||
var flow = RED.nodes.workspace(activeWS) || RED.nodes.subflow(activeWS);
|
||||
if (flow) {
|
||||
refresh(flow);
|
||||
} else {
|
||||
var workspace = RED.nodes.workspace(RED.workspaces.active());
|
||||
if (workspace && workspace.info) {
|
||||
refresh(workspace);
|
||||
} else {
|
||||
clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
init: init,
|
||||
show: show,
|
||||
refresh: refresh,
|
||||
clear: clear,
|
||||
set: set
|
||||
}
|
||||
})();
|
||||
@@ -1,8 +0,0 @@
|
||||
.ace_gutter {
|
||||
border-top-left-radius: 4px;
|
||||
border-bottom-left-radius: 4px;
|
||||
}
|
||||
.ace_scroller {
|
||||
border-top-right-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
}
|
||||
@@ -1,96 +0,0 @@
|
||||
/**
|
||||
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
|
||||
.red-ui-popover {
|
||||
display: none;
|
||||
position: absolute;
|
||||
width: auto;
|
||||
padding: 10px;
|
||||
height: auto;
|
||||
background: #fff;
|
||||
|
||||
z-index: 1000;
|
||||
font-size: 14px;
|
||||
line-height: 1.4em;
|
||||
@include component-shadow;
|
||||
}
|
||||
|
||||
.red-ui-popover:after, .red-ui-popover:before {
|
||||
top: 50%;
|
||||
border: solid transparent;
|
||||
content: " ";
|
||||
height: 0;
|
||||
width: 0;
|
||||
position: absolute;
|
||||
pointer-events: none;
|
||||
}
|
||||
.red-ui-popover.red-ui-popover-right:after, .red-ui-popover.red-ui-popover-right:before {
|
||||
right: 100%;
|
||||
}
|
||||
.red-ui-popover.red-ui-popover-left:after, .red-ui-popover.red-ui-popover-left:before {
|
||||
left: 100%;
|
||||
}
|
||||
|
||||
|
||||
.red-ui-popover.red-ui-popover-right:after {
|
||||
border-color: rgba(136, 183, 213, 0);
|
||||
border-right-color: #fff;
|
||||
border-width: 10px;
|
||||
margin-top: -10px;
|
||||
}
|
||||
.red-ui-popover.red-ui-popover-right:before {
|
||||
border-color: rgba(194, 225, 245, 0);
|
||||
border-right-color: $primary-border-color;
|
||||
border-width: 11px;
|
||||
margin-top: -11px;
|
||||
}
|
||||
|
||||
.red-ui-popover.red-ui-popover-left:after {
|
||||
border-color: rgba(136, 183, 213, 0);
|
||||
border-left-color: #fff;
|
||||
border-width: 10px;
|
||||
margin-top: -10px;
|
||||
}
|
||||
.red-ui-popover.red-ui-popover-left:before {
|
||||
border-color: rgba(194, 225, 245, 0);
|
||||
border-left-color: $primary-border-color;
|
||||
border-width: 11px;
|
||||
margin-top: -11px;
|
||||
}
|
||||
|
||||
.red-ui-popover-size-small {
|
||||
font-size: 11px;
|
||||
padding: 5px;
|
||||
|
||||
&.red-ui-popover-right:after {
|
||||
border-width: 5px;
|
||||
margin-top: -5px;
|
||||
}
|
||||
&.red-ui-popover-right:before {
|
||||
border-width: 6px;
|
||||
margin-top: -6px;
|
||||
}
|
||||
|
||||
&.red-ui-popover-left:after {
|
||||
border-width: 5px;
|
||||
margin-top: -5px;
|
||||
}
|
||||
&.red-ui-popover-left:before {
|
||||
border-width: 6px;
|
||||
margin-top: -6px;
|
||||
}
|
||||
}
|
||||
@@ -1,238 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0"/>
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="mobile-web-app-capable" content="yes">
|
||||
<!--
|
||||
Copyright JS Foundation and other contributors, http://js.foundation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<head>
|
||||
<title>{{ page.title }}</title>
|
||||
<link rel="icon" type="image/png" href="{{ page.favicon }}">
|
||||
<link rel="mask-icon" href="{{ page.tabicon }}" color="#8f0000">
|
||||
<link href="vendor/bootstrap/css/bootstrap.min.css" rel="stylesheet" media="screen">
|
||||
<link href="vendor/jquery/css/smoothness/jquery-ui-1.10.3.custom.min.css" rel="stylesheet" media="screen">
|
||||
<link rel="stylesheet" href="vendor/font-awesome/css/font-awesome.min.css">
|
||||
<link rel="stylesheet" href="vendor/vendor.css">
|
||||
<link rel="stylesheet" href="red/style.min.css">
|
||||
{{#page.css}}
|
||||
<link rel="stylesheet" href="{{.}}">
|
||||
{{/page.css}}
|
||||
|
||||
</head>
|
||||
<body spellcheck="false">
|
||||
<div id="header">
|
||||
<span class="logo">{{#header.url}}<a href="{{.}}">{{/header.url}}{{#header.image}}<img src="{{.}}" title="{{version}}">{{/header.image}} <span>{{ header.title }}</span>{{#header.url}}</a>{{/header.url}}</span>
|
||||
<ul class="header-toolbar hide">
|
||||
<li><a id="btn-sidemenu" class="button" data-toggle="dropdown" href="#"><i class="fa fa-bars"></i></a></li>
|
||||
</ul>
|
||||
<div id="header-shade" class="hide"></div>
|
||||
</div>
|
||||
<div id="main-container" class="sidebar-closed hide">
|
||||
<div id="workspace">
|
||||
<ul id="workspace-tabs"></ul>
|
||||
<div id="chart" tabindex="1"></div>
|
||||
<div id="workspace-toolbar"></div>
|
||||
<div id="workspace-footer">
|
||||
<a class="workspace-footer-button" id="btn-zoom-out" href="#"><i class="fa fa-minus"></i></a>
|
||||
<a class="workspace-footer-button" id="btn-zoom-zero" href="#"><i class="fa fa-circle-o"></i></a>
|
||||
<a class="workspace-footer-button" id="btn-zoom-in" href="#"><i class="fa fa-plus"></i></a>
|
||||
</div>
|
||||
<div id="editor-shade" class="hide"></div>
|
||||
</div>
|
||||
<div id="editor-stack"></div>
|
||||
<div id="palette">
|
||||
<img src="red/images/spin.svg" class="palette-spinner hide"/>
|
||||
<div id="palette-search" class="palette-search hide">
|
||||
<input type="text" data-i18n="[placeholder]palette.filter"></input>
|
||||
</div>
|
||||
<div id="palette-container" class="palette-scroll hide"></div>
|
||||
<div id="palette-footer">
|
||||
<a class="palette-button" id="palette-collapse-all" href="#"><i class="fa fa-angle-double-up"></i></a>
|
||||
<a class="palette-button" id="palette-expand-all" href="#"><i class="fa fa-angle-double-down"></i></a>
|
||||
</div>
|
||||
<div id="palette-shade" class="hide"></div>
|
||||
</div><!-- /palette -->
|
||||
<div id="sidebar">
|
||||
<ul id="sidebar-tabs"></ul>
|
||||
<div id="sidebar-content"></div>
|
||||
<div id="sidebar-footer"></div>
|
||||
<div id="sidebar-shade" class="hide"></div>
|
||||
</div>
|
||||
|
||||
<div id="sidebar-separator"></div>
|
||||
|
||||
</div>
|
||||
|
||||
<div id="notifications"></div>
|
||||
<div id="dropTarget"><div data-i18n="[append]workspace.dropFlowHere"><br/><i class="fa fa-download"></i></div></div>
|
||||
|
||||
<div id="node-dialog-confirm-deploy" class="hide">
|
||||
<form class="form-horizontal">
|
||||
<div id="node-dialog-confirm-deploy-config" class="node-dialog-confirm-row" data-i18n="[prepend]deploy.confirm.improperlyConfigured;[append]deploy.confirm.confirm">
|
||||
<ul id="node-dialog-confirm-deploy-invalid-list"></ul>
|
||||
</div>
|
||||
<div id="node-dialog-confirm-deploy-unknown" class="node-dialog-confirm-row" data-i18n="[prepend]deploy.confirm.unknown;[append]deploy.confirm.confirm">
|
||||
<ul id="node-dialog-confirm-deploy-unknown-list"></ul>
|
||||
</div>
|
||||
<div id="node-dialog-confirm-deploy-conflict" class="node-dialog-confirm-row">
|
||||
<div style="margin-left: 40px; margin-bottom: 10px;">
|
||||
<span data-i18n="deploy.confirm.conflict"></span>
|
||||
</div>
|
||||
<div id="node-dialog-confirm-deploy-conflict-checking" class="node-dialog-confirm-conflict-row">
|
||||
<img src="red/images/spin.svg"/><div data-i18n="deploy.confirm.conflictChecking"></div>
|
||||
</div>
|
||||
<div id="node-dialog-confirm-deploy-conflict-auto-merge" class="node-dialog-confirm-conflict-row">
|
||||
<i style="color: #3a3;" class="fa fa-check"></i><div data-i18n="deploy.confirm.conflictAutoMerge"></div>
|
||||
</div>
|
||||
<div id="node-dialog-confirm-deploy-conflict-manual-merge" class="node-dialog-confirm-conflict-row">
|
||||
<i style="color: #999;" class="fa fa-exclamation"></i><div data-i18n="deploy.confirm.conflictManualMerge"></div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div id="node-dialog-library-save-confirm" class="hide">
|
||||
<form class="form-horizontal">
|
||||
<div style="text-align: center; padding-top: 30px;" id="node-dialog-library-save-content">
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div id="node-dialog-library-save" class="hide">
|
||||
<form class="form-horizontal">
|
||||
<div class="form-row">
|
||||
<label for="node-dialog-library-save-folder" data-i18n="[append]library.folder"><i class="fa fa-folder-open"></i> </label>
|
||||
<input type="text" id="node-dialog-library-save-folder" data-i18n="[placeholder]library.folderPlaceholder">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-dialog-library-save-filename" data-i18n="[append]library.filename"><i class="fa fa-file"></i> </label>
|
||||
<input type="text" id="node-dialog-library-save-filename" data-i18n="[placeholder]library.filenamePlaceholder">
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div id="node-dialog-library-lookup" class="hide">
|
||||
<form class="form-horizontal">
|
||||
<div class="form-row">
|
||||
<ul id="node-dialog-library-breadcrumbs" class="breadcrumb">
|
||||
<li class="active"><a href="#" data-i18n="[append]library.breadcrumb"></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div style="vertical-align: top; display: inline-block; height: 100%; width: 30%; padding-right: 20px;">
|
||||
<div id="node-select-library" style="border: 1px solid #999; width: 100%; height: 100%; overflow:scroll;"><ul></ul></div>
|
||||
</div>
|
||||
<div style="vertical-align: top; display: inline-block;width: 65%; height: 100%;">
|
||||
<div style="height: 100%; width: 95%;" class="node-text-editor" id="node-select-library-text" ></div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<script type="text/x-red" data-template-name="subflow">
|
||||
<div class="form-row">
|
||||
<label for="node-input-name" data-i18n="[append]editor:common.label.name"><i class="fa fa-tag"></i> </label>
|
||||
<input type="text" id="node-input-name">
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-template-name="subflow-template">
|
||||
<div class="form-row">
|
||||
<i class="fa fa-tag"></i>
|
||||
<label for="subflow-input-name" data-i18n="common.label.name"></label><input type="text" id="subflow-input-name">
|
||||
</div>
|
||||
<div class="form-row" style="margin-bottom: 0px;">
|
||||
<label for="subflow-input-info" data-i18n="editor:subflow.info"></label>
|
||||
<a href="https://help.github.com/articles/markdown-basics/" style="font-size: 0.8em; float: right;" data-i18n="[html]subflow.format"></a>
|
||||
</div>
|
||||
<div class="form-row node-text-editor-row">
|
||||
<div style="height: 250px;" class="node-text-editor" id="subflow-input-info-editor"></div>
|
||||
</div>
|
||||
<div class="form-row form-tips" id="subflow-dialog-user-count"></div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-template-name="_expression">
|
||||
<div id="node-input-expression-panels">
|
||||
<div id="node-input-expression-panel-expr" class="red-ui-panel">
|
||||
<div class="form-row" style="margin-bottom: 3px; text-align: right;">
|
||||
<span class="node-input-expression-legacy"><i class="fa fa-exclamation-circle"></i> <span data-i18n="expressionEditor.compatMode"></span></span>
|
||||
<button id="node-input-expression-reformat" class="editor-button editor-button-small"><span data-i18n="expressionEditor.format"></span></button>
|
||||
</div>
|
||||
<div class="form-row node-text-editor-row">
|
||||
<div class="node-text-editor" id="node-input-expression"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="node-input-expression-panel-info" class="red-ui-panel">
|
||||
<div class="form-row">
|
||||
<ul id="node-input-expression-tabs"></ul>
|
||||
<div id="node-input-expression-tab-help" class="node-input-expression-tab-content hide">
|
||||
<div>
|
||||
<select id="node-input-expression-func"></select>
|
||||
<button id="node-input-expression-func-insert" class="editor-button" data-i18n="expressionEditor.insert"></button>
|
||||
</div>
|
||||
<div id="node-input-expression-help"></div>
|
||||
</div>
|
||||
<div id="node-input-expression-tab-test" class="node-input-expression-tab-content hide">
|
||||
<div>
|
||||
<span style="display: inline-block; width: calc(50% - 5px);" data-i18n="expressionEditor.data"></span>
|
||||
<span style="display: inline-block; width: calc(50% - 5px);" data-i18n="expressionEditor.result"></span>
|
||||
</div>
|
||||
<div style="display: inline-block; width: calc(50% - 5px);" class="node-text-editor" id="node-input-expression-test-data"></div>
|
||||
<div style="display: inline-block; width: calc(50% - 5px);" class="node-text-editor" id="node-input-expression-test-result"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
<script type="text/x-red" data-template-name="_json">
|
||||
<div class="form-row" style="margin-bottom: 3px; text-align: right;">
|
||||
<button id="node-input-expression-reformat" class="editor-button editor-button-small"><span data-i18n="jsonEditor.format"></span></button>
|
||||
</div>
|
||||
<div class="form-row node-text-editor-row">
|
||||
<div style="height: 200px;min-height: 150px;" class="node-text-editor" id="node-input-json"></div>
|
||||
</div>
|
||||
</script>
|
||||
<script type="text/x-red" data-template-name="_buffer">
|
||||
<div id="node-input-buffer-panels">
|
||||
<div id="node-input-buffer-panel-str" class="red-ui-panel">
|
||||
<div class="form-row" style="margin-bottom: 3px; text-align: right;">
|
||||
<span class="node-input-buffer-type"><i class="fa fa-exclamation-circle"></i> <span id="node-input-buffer-type-string" data-i18n="bufferEditor.modeString"></span><span id="node-input-buffer-type-array" data-i18n="bufferEditor.modeArray"></span></span>
|
||||
</div>
|
||||
<div class="form-row node-text-editor-row">
|
||||
<div class="node-text-editor" id="node-input-buffer-str"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="node-input-buffer-panel-bin" class="red-ui-panel">
|
||||
<div class="form-row node-text-editor-row" style="margin-top: 10px">
|
||||
<div class="node-text-editor" id="node-input-buffer-bin"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script src="vendor/vendor.js"></script>
|
||||
<script src="vendor/jsonata/jsonata.min.js"></script>
|
||||
<script src="vendor/ace/ace.js"></script>
|
||||
<script src="vendor/ace/ext-language_tools.js"></script>
|
||||
<script src="{{ asset.red }}"></script>
|
||||
<script src="{{ asset.main }}"></script>
|
||||
{{# page.scripts }}
|
||||
<script src="{{.}}"></script>
|
||||
{{/ page.scripts }}
|
||||
|
||||
</body>
|
||||
</html>
|
||||
14
editor/vendor/ace/ace.js
vendored
14
editor/vendor/ace/ace.js
vendored
File diff suppressed because one or more lines are too long
5
editor/vendor/ace/ext-language_tools.js
vendored
5
editor/vendor/ace/ext-language_tools.js
vendored
File diff suppressed because one or more lines are too long
5
editor/vendor/ace/ext-searchbox.js
vendored
5
editor/vendor/ace/ext-searchbox.js
vendored
File diff suppressed because one or more lines are too long
1
editor/vendor/ace/mode-css.js
vendored
1
editor/vendor/ace/mode-css.js
vendored
File diff suppressed because one or more lines are too long
1
editor/vendor/ace/mode-handlebars.js
vendored
1
editor/vendor/ace/mode-handlebars.js
vendored
File diff suppressed because one or more lines are too long
1
editor/vendor/ace/mode-html.js
vendored
1
editor/vendor/ace/mode-html.js
vendored
File diff suppressed because one or more lines are too long
1
editor/vendor/ace/mode-javascript.js
vendored
1
editor/vendor/ace/mode-javascript.js
vendored
File diff suppressed because one or more lines are too long
1
editor/vendor/ace/mode-json.js
vendored
1
editor/vendor/ace/mode-json.js
vendored
File diff suppressed because one or more lines are too long
1
editor/vendor/ace/mode-markdown.js
vendored
1
editor/vendor/ace/mode-markdown.js
vendored
File diff suppressed because one or more lines are too long
1
editor/vendor/ace/mode-swift.js
vendored
1
editor/vendor/ace/mode-swift.js
vendored
File diff suppressed because one or more lines are too long
1
editor/vendor/ace/mode-yaml.js
vendored
1
editor/vendor/ace/mode-yaml.js
vendored
@@ -1 +0,0 @@
|
||||
ace.define("ace/mode/yaml_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){"use strict";var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=function(){this.$rules={start:[{token:"comment",regex:"#.*$"},{token:"list.markup",regex:/^(?:-{3}|\.{3})\s*(?=#|$)/},{token:"list.markup",regex:/^\s*[\-?](?:$|\s)/},{token:"constant",regex:"!![\\w//]+"},{token:"constant.language",regex:"[&\\*][a-zA-Z0-9-_]+"},{token:["meta.tag","keyword"],regex:/^(\s*\w.*?)(:(?:\s+|$))/},{token:["meta.tag","keyword"],regex:/(\w+?)(\s*:(?:\s+|$))/},{token:"keyword.operator",regex:"<<\\w*:\\w*"},{token:"keyword.operator",regex:"-\\s*(?=[{])"},{token:"string",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'},{token:"string",regex:/[|>][-+\d\s]*$/,onMatch:function(e,t,n,r){var i=/^\s*/.exec(r)[0];return n.length<1?n.push(this.next):n[0]="mlString",n.length<2?n.push(i.length):n[1]=i.length,this.token},next:"mlString"},{token:"string",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"constant.numeric",regex:/(\b|[+\-\.])[\d_]+(?:(?:\.[\d_]*)?(?:[eE][+\-]?[\d_]+)?)/},{token:"constant.numeric",regex:/[+\-]?\.inf\b|NaN\b|0x[\dA-Fa-f_]+|0b[10_]+/},{token:"constant.language.boolean",regex:"\\b(?:true|false|TRUE|FALSE|True|False|yes|no)\\b"},{token:"paren.lparen",regex:"[[({]"},{token:"paren.rparen",regex:"[\\])}]"}],mlString:[{token:"indent",regex:/^\s*$/},{token:"indent",regex:/^\s*/,onMatch:function(e,t,n){var r=n[1];return r>=e.length?(this.next="start",n.splice(0)):this.next="mlString",this.token},next:"mlString"},{token:"string",regex:".+"}]},this.normalizeRules()};r.inherits(s,i),t.YamlHighlightRules=s}),ace.define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(e,t,n){"use strict";var r=e("../range").Range,i=function(){};(function(){this.checkOutdent=function(e,t){return/^\s+$/.test(e)?/^\s*\}/.test(t):!1},this.autoOutdent=function(e,t){var n=e.getLine(t),i=n.match(/^(\s*\})/);if(!i)return 0;var s=i[1].length,o=e.findMatchingBracket({row:t,column:s});if(!o||o.row==t)return 0;var u=this.$getIndent(e.getLine(o.row));e.replace(new r(t,0,t,s-1),u)},this.$getIndent=function(e){return e.match(/^\s*/)[0]}}).call(i.prototype),t.MatchingBraceOutdent=i}),ace.define("ace/mode/folding/coffee",["require","exports","module","ace/lib/oop","ace/mode/folding/fold_mode","ace/range"],function(e,t,n){"use strict";var r=e("../../lib/oop"),i=e("./fold_mode").FoldMode,s=e("../../range").Range,o=t.FoldMode=function(){};r.inherits(o,i),function(){this.getFoldWidgetRange=function(e,t,n){var r=this.indentationBlock(e,n);if(r)return r;var i=/\S/,o=e.getLine(n),u=o.search(i);if(u==-1||o[u]!="#")return;var a=o.length,f=e.getLength(),l=n,c=n;while(++n<f){o=e.getLine(n);var h=o.search(i);if(h==-1)continue;if(o[h]!="#")break;c=n}if(c>l){var p=e.getLine(c).length;return new s(l,a,c,p)}},this.getFoldWidget=function(e,t,n){var r=e.getLine(n),i=r.search(/\S/),s=e.getLine(n+1),o=e.getLine(n-1),u=o.search(/\S/),a=s.search(/\S/);if(i==-1)return e.foldWidgets[n-1]=u!=-1&&u<a?"start":"","";if(u==-1){if(i==a&&r[i]=="#"&&s[i]=="#")return e.foldWidgets[n-1]="",e.foldWidgets[n+1]="","start"}else if(u==i&&r[i]=="#"&&o[i]=="#"&&e.getLine(n-2).search(/\S/)==-1)return e.foldWidgets[n-1]="start",e.foldWidgets[n+1]="","";return u!=-1&&u<i?e.foldWidgets[n-1]="start":e.foldWidgets[n-1]="",i<a?"start":""}}.call(o.prototype)}),ace.define("ace/mode/yaml",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/yaml_highlight_rules","ace/mode/matching_brace_outdent","ace/mode/folding/coffee"],function(e,t,n){"use strict";var r=e("../lib/oop"),i=e("./text").Mode,s=e("./yaml_highlight_rules").YamlHighlightRules,o=e("./matching_brace_outdent").MatchingBraceOutdent,u=e("./folding/coffee").FoldMode,a=function(){this.HighlightRules=s,this.$outdent=new o,this.foldingRules=new u,this.$behaviour=this.$defaultBehaviour};r.inherits(a,i),function(){this.lineCommentStart="#",this.getNextLineIndent=function(e,t,n){var r=this.$getIndent(t);if(e=="start"){var i=t.match(/^.*[\{\(\[]\s*$/);i&&(r+=n)}return r},this.checkOutdent=function(e,t,n){return this.$outdent.checkOutdent(t,n)},this.autoOutdent=function(e,t,n){this.$outdent.autoOutdent(t,n)},this.$id="ace/mode/yaml"}.call(a.prototype),t.Mode=a})
|
||||
1
editor/vendor/ace/snippets/handlebars.js
vendored
1
editor/vendor/ace/snippets/handlebars.js
vendored
@@ -1 +0,0 @@
|
||||
ace.define("ace/snippets/handlebars",["require","exports","module"],function(e,t,n){"use strict";t.snippetText=undefined,t.scope="handlebars"})
|
||||
835
editor/vendor/ace/snippets/html.js
vendored
835
editor/vendor/ace/snippets/html.js
vendored
@@ -1,835 +0,0 @@
|
||||
ace.define("ace/snippets/html",["require","exports","module"], function(require, exports, module) {
|
||||
"use strict";
|
||||
|
||||
exports.snippetText = "# Some useful Unicode entities\n\
|
||||
# Non-Breaking Space\n\
|
||||
snippet nbs\n\
|
||||
\n\
|
||||
# ←\n\
|
||||
snippet left\n\
|
||||
←\n\
|
||||
# →\n\
|
||||
snippet right\n\
|
||||
→\n\
|
||||
# ↑\n\
|
||||
snippet up\n\
|
||||
↑\n\
|
||||
# ↓\n\
|
||||
snippet down\n\
|
||||
↓\n\
|
||||
# ↩\n\
|
||||
snippet return\n\
|
||||
↩\n\
|
||||
# ⇤\n\
|
||||
snippet backtab\n\
|
||||
⇤\n\
|
||||
# ⇥\n\
|
||||
snippet tab\n\
|
||||
⇥\n\
|
||||
# ⇧\n\
|
||||
snippet shift\n\
|
||||
⇧\n\
|
||||
# ⌃\n\
|
||||
snippet ctrl\n\
|
||||
⌃\n\
|
||||
# ⌅\n\
|
||||
snippet enter\n\
|
||||
⌅\n\
|
||||
# ⌘\n\
|
||||
snippet cmd\n\
|
||||
⌘\n\
|
||||
# ⌥\n\
|
||||
snippet option\n\
|
||||
⌥\n\
|
||||
# ⌦\n\
|
||||
snippet delete\n\
|
||||
⌦\n\
|
||||
# ⌫\n\
|
||||
snippet backspace\n\
|
||||
⌫\n\
|
||||
# ⎋\n\
|
||||
snippet esc\n\
|
||||
⎋\n\
|
||||
# Generic Doctype\n\
|
||||
snippet doctype HTML 4.01 Strict\n\
|
||||
<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\"\n\
|
||||
\"http://www.w3.org/TR/html4/strict.dtd\">\n\
|
||||
snippet doctype HTML 4.01 Transitional\n\
|
||||
<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\n\
|
||||
\"http://www.w3.org/TR/html4/loose.dtd\">\n\
|
||||
snippet doctype HTML 5\n\
|
||||
<!DOCTYPE HTML>\n\
|
||||
snippet doctype XHTML 1.0 Frameset\n\
|
||||
<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"\n\
|
||||
\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n\
|
||||
snippet doctype XHTML 1.0 Strict\n\
|
||||
<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"\n\
|
||||
\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n\
|
||||
snippet doctype XHTML 1.0 Transitional\n\
|
||||
<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n\
|
||||
\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n\
|
||||
snippet doctype XHTML 1.1\n\
|
||||
<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\"\n\
|
||||
\"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">\n\
|
||||
# HTML Doctype 4.01 Strict\n\
|
||||
snippet docts\n\
|
||||
<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\"\n\
|
||||
\"http://www.w3.org/TR/html4/strict.dtd\">\n\
|
||||
# HTML Doctype 4.01 Transitional\n\
|
||||
snippet doct\n\
|
||||
<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\n\
|
||||
\"http://www.w3.org/TR/html4/loose.dtd\">\n\
|
||||
# HTML Doctype 5\n\
|
||||
snippet doct5\n\
|
||||
<!DOCTYPE HTML>\n\
|
||||
# XHTML Doctype 1.0 Frameset\n\
|
||||
snippet docxf\n\
|
||||
<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Frameset//EN\"\n\
|
||||
\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd\">\n\
|
||||
# XHTML Doctype 1.0 Strict\n\
|
||||
snippet docxs\n\
|
||||
<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"\n\
|
||||
\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n\
|
||||
# XHTML Doctype 1.0 Transitional\n\
|
||||
snippet docxt\n\
|
||||
<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n\
|
||||
\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n\
|
||||
# XHTML Doctype 1.1\n\
|
||||
snippet docx\n\
|
||||
<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\"\n\
|
||||
\"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">\n\
|
||||
# Attributes\n\
|
||||
snippet attr\n\
|
||||
${1:attribute}=\"${2:property}\"\n\
|
||||
snippet attr+\n\
|
||||
${1:attribute}=\"${2:property}\" attr+${3}\n\
|
||||
snippet .\n\
|
||||
class=\"${1}\"${2}\n\
|
||||
snippet #\n\
|
||||
id=\"${1}\"${2}\n\
|
||||
snippet alt\n\
|
||||
alt=\"${1}\"${2}\n\
|
||||
snippet charset\n\
|
||||
charset=\"${1:utf-8}\"${2}\n\
|
||||
snippet data\n\
|
||||
data-${1}=\"${2:$1}\"${3}\n\
|
||||
snippet for\n\
|
||||
for=\"${1}\"${2}\n\
|
||||
snippet height\n\
|
||||
height=\"${1}\"${2}\n\
|
||||
snippet href\n\
|
||||
href=\"${1:#}\"${2}\n\
|
||||
snippet lang\n\
|
||||
lang=\"${1:en}\"${2}\n\
|
||||
snippet media\n\
|
||||
media=\"${1}\"${2}\n\
|
||||
snippet name\n\
|
||||
name=\"${1}\"${2}\n\
|
||||
snippet rel\n\
|
||||
rel=\"${1}\"${2}\n\
|
||||
snippet scope\n\
|
||||
scope=\"${1:row}\"${2}\n\
|
||||
snippet src\n\
|
||||
src=\"${1}\"${2}\n\
|
||||
snippet title=\n\
|
||||
title=\"${1}\"${2}\n\
|
||||
snippet type\n\
|
||||
type=\"${1}\"${2}\n\
|
||||
snippet value\n\
|
||||
value=\"${1}\"${2}\n\
|
||||
snippet width\n\
|
||||
width=\"${1}\"${2}\n\
|
||||
# Elements\n\
|
||||
snippet a\n\
|
||||
<a href=\"${1:#}\">${2:$1}</a>\n\
|
||||
snippet a.\n\
|
||||
<a class=\"${1}\" href=\"${2:#}\">${3:$1}</a>\n\
|
||||
snippet a#\n\
|
||||
<a id=\"${1}\" href=\"${2:#}\">${3:$1}</a>\n\
|
||||
snippet a:ext\n\
|
||||
<a href=\"http://${1:example.com}\">${2:$1}</a>\n\
|
||||
snippet a:mail\n\
|
||||
<a href=\"mailto:${1:joe@example.com}?subject=${2:feedback}\">${3:email me}</a>\n\
|
||||
snippet abbr\n\
|
||||
<abbr title=\"${1}\">${2}</abbr>\n\
|
||||
snippet address\n\
|
||||
<address>\n\
|
||||
${1}\n\
|
||||
</address>\n\
|
||||
snippet area\n\
|
||||
<area shape=\"${1:rect}\" coords=\"${2}\" href=\"${3}\" alt=\"${4}\" />\n\
|
||||
snippet area+\n\
|
||||
<area shape=\"${1:rect}\" coords=\"${2}\" href=\"${3}\" alt=\"${4}\" />\n\
|
||||
area+${5}\n\
|
||||
snippet area:c\n\
|
||||
<area shape=\"circle\" coords=\"${1}\" href=\"${2}\" alt=\"${3}\" />\n\
|
||||
snippet area:d\n\
|
||||
<area shape=\"default\" coords=\"${1}\" href=\"${2}\" alt=\"${3}\" />\n\
|
||||
snippet area:p\n\
|
||||
<area shape=\"poly\" coords=\"${1}\" href=\"${2}\" alt=\"${3}\" />\n\
|
||||
snippet area:r\n\
|
||||
<area shape=\"rect\" coords=\"${1}\" href=\"${2}\" alt=\"${3}\" />\n\
|
||||
snippet article\n\
|
||||
<article>\n\
|
||||
${1}\n\
|
||||
</article>\n\
|
||||
snippet article.\n\
|
||||
<article class=\"${1}\">\n\
|
||||
${2}\n\
|
||||
</article>\n\
|
||||
snippet article#\n\
|
||||
<article id=\"${1}\">\n\
|
||||
${2}\n\
|
||||
</article>\n\
|
||||
snippet aside\n\
|
||||
<aside>\n\
|
||||
${1}\n\
|
||||
</aside>\n\
|
||||
snippet aside.\n\
|
||||
<aside class=\"${1}\">\n\
|
||||
${2}\n\
|
||||
</aside>\n\
|
||||
snippet aside#\n\
|
||||
<aside id=\"${1}\">\n\
|
||||
${2}\n\
|
||||
</aside>\n\
|
||||
snippet audio\n\
|
||||
<audio src=\"${1}>${2}</audio>\n\
|
||||
snippet b\n\
|
||||
<b>${1}</b>\n\
|
||||
snippet base\n\
|
||||
<base href=\"${1}\" target=\"${2}\" />\n\
|
||||
snippet bdi\n\
|
||||
<bdi>${1}</bdo>\n\
|
||||
snippet bdo\n\
|
||||
<bdo dir=\"${1}\">${2}</bdo>\n\
|
||||
snippet bdo:l\n\
|
||||
<bdo dir=\"ltr\">${1}</bdo>\n\
|
||||
snippet bdo:r\n\
|
||||
<bdo dir=\"rtl\">${1}</bdo>\n\
|
||||
snippet blockquote\n\
|
||||
<blockquote>\n\
|
||||
${1}\n\
|
||||
</blockquote>\n\
|
||||
snippet body\n\
|
||||
<body>\n\
|
||||
${1}\n\
|
||||
</body>\n\
|
||||
snippet br\n\
|
||||
<br />${1}\n\
|
||||
snippet button\n\
|
||||
<button type=\"${1:submit}\">${2}</button>\n\
|
||||
snippet button.\n\
|
||||
<button class=\"${1:button}\" type=\"${2:submit}\">${3}</button>\n\
|
||||
snippet button#\n\
|
||||
<button id=\"${1}\" type=\"${2:submit}\">${3}</button>\n\
|
||||
snippet button:s\n\
|
||||
<button type=\"submit\">${1}</button>\n\
|
||||
snippet button:r\n\
|
||||
<button type=\"reset\">${1}</button>\n\
|
||||
snippet canvas\n\
|
||||
<canvas>\n\
|
||||
${1}\n\
|
||||
</canvas>\n\
|
||||
snippet caption\n\
|
||||
<caption>${1}</caption>\n\
|
||||
snippet cite\n\
|
||||
<cite>${1}</cite>\n\
|
||||
snippet code\n\
|
||||
<code>${1}</code>\n\
|
||||
snippet col\n\
|
||||
<col />${1}\n\
|
||||
snippet col+\n\
|
||||
<col />\n\
|
||||
col+${1}\n\
|
||||
snippet colgroup\n\
|
||||
<colgroup>\n\
|
||||
${1}\n\
|
||||
</colgroup>\n\
|
||||
snippet colgroup+\n\
|
||||
<colgroup>\n\
|
||||
<col />\n\
|
||||
col+${1}\n\
|
||||
</colgroup>\n\
|
||||
snippet command\n\
|
||||
<command type=\"command\" label=\"${1}\" icon=\"${2}\" />\n\
|
||||
snippet command:c\n\
|
||||
<command type=\"checkbox\" label=\"${1}\" icon=\"${2}\" />\n\
|
||||
snippet command:r\n\
|
||||
<command type=\"radio\" radiogroup=\"${1}\" label=\"${2}\" icon=\"${3}\" />\n\
|
||||
snippet datagrid\n\
|
||||
<datagrid>\n\
|
||||
${1}\n\
|
||||
</datagrid>\n\
|
||||
snippet datalist\n\
|
||||
<datalist>\n\
|
||||
${1}\n\
|
||||
</datalist>\n\
|
||||
snippet datatemplate\n\
|
||||
<datatemplate>\n\
|
||||
${1}\n\
|
||||
</datatemplate>\n\
|
||||
snippet dd\n\
|
||||
<dd>${1}</dd>\n\
|
||||
snippet dd.\n\
|
||||
<dd class=\"${1}\">${2}</dd>\n\
|
||||
snippet dd#\n\
|
||||
<dd id=\"${1}\">${2}</dd>\n\
|
||||
snippet del\n\
|
||||
<del>${1}</del>\n\
|
||||
snippet details\n\
|
||||
<details>${1}</details>\n\
|
||||
snippet dfn\n\
|
||||
<dfn>${1}</dfn>\n\
|
||||
snippet dialog\n\
|
||||
<dialog>\n\
|
||||
${1}\n\
|
||||
</dialog>\n\
|
||||
snippet div\n\
|
||||
<div>\n\
|
||||
${1}\n\
|
||||
</div>\n\
|
||||
snippet div.\n\
|
||||
<div class=\"${1}\">\n\
|
||||
${2}\n\
|
||||
</div>\n\
|
||||
snippet div#\n\
|
||||
<div id=\"${1}\">\n\
|
||||
${2}\n\
|
||||
</div>\n\
|
||||
snippet dl\n\
|
||||
<dl>\n\
|
||||
${1}\n\
|
||||
</dl>\n\
|
||||
snippet dl.\n\
|
||||
<dl class=\"${1}\">\n\
|
||||
${2}\n\
|
||||
</dl>\n\
|
||||
snippet dl#\n\
|
||||
<dl id=\"${1}\">\n\
|
||||
${2}\n\
|
||||
</dl>\n\
|
||||
snippet dl+\n\
|
||||
<dl>\n\
|
||||
<dt>${1}</dt>\n\
|
||||
<dd>${2}</dd>\n\
|
||||
dt+${3}\n\
|
||||
</dl>\n\
|
||||
snippet dt\n\
|
||||
<dt>${1}</dt>\n\
|
||||
snippet dt.\n\
|
||||
<dt class=\"${1}\">${2}</dt>\n\
|
||||
snippet dt#\n\
|
||||
<dt id=\"${1}\">${2}</dt>\n\
|
||||
snippet dt+\n\
|
||||
<dt>${1}</dt>\n\
|
||||
<dd>${2}</dd>\n\
|
||||
dt+${3}\n\
|
||||
snippet em\n\
|
||||
<em>${1}</em>\n\
|
||||
snippet embed\n\
|
||||
<embed src=${1} type=\"${2} />\n\
|
||||
snippet fieldset\n\
|
||||
<fieldset>\n\
|
||||
${1}\n\
|
||||
</fieldset>\n\
|
||||
snippet fieldset.\n\
|
||||
<fieldset class=\"${1}\">\n\
|
||||
${2}\n\
|
||||
</fieldset>\n\
|
||||
snippet fieldset#\n\
|
||||
<fieldset id=\"${1}\">\n\
|
||||
${2}\n\
|
||||
</fieldset>\n\
|
||||
snippet fieldset+\n\
|
||||
<fieldset>\n\
|
||||
<legend><span>${1}</span></legend>\n\
|
||||
${2}\n\
|
||||
</fieldset>\n\
|
||||
fieldset+${3}\n\
|
||||
snippet figcaption\n\
|
||||
<figcaption>${1}</figcaption>\n\
|
||||
snippet figure\n\
|
||||
<figure>${1}</figure>\n\
|
||||
snippet footer\n\
|
||||
<footer>\n\
|
||||
${1}\n\
|
||||
</footer>\n\
|
||||
snippet footer.\n\
|
||||
<footer class=\"${1}\">\n\
|
||||
${2}\n\
|
||||
</footer>\n\
|
||||
snippet footer#\n\
|
||||
<footer id=\"${1}\">\n\
|
||||
${2}\n\
|
||||
</footer>\n\
|
||||
snippet form\n\
|
||||
<form action=\"${1}\" method=\"${2:get}\" accept-charset=\"utf-8\">\n\
|
||||
${3}\n\
|
||||
</form>\n\
|
||||
snippet form.\n\
|
||||
<form class=\"${1}\" action=\"${2}\" method=\"${3:get}\" accept-charset=\"utf-8\">\n\
|
||||
${4}\n\
|
||||
</form>\n\
|
||||
snippet form#\n\
|
||||
<form id=\"${1}\" action=\"${2}\" method=\"${3:get}\" accept-charset=\"utf-8\">\n\
|
||||
${4}\n\
|
||||
</form>\n\
|
||||
snippet h1\n\
|
||||
<h1>${1}</h1>\n\
|
||||
snippet h1.\n\
|
||||
<h1 class=\"${1}\">${2}</h1>\n\
|
||||
snippet h1#\n\
|
||||
<h1 id=\"${1}\">${2}</h1>\n\
|
||||
snippet h2\n\
|
||||
<h2>${1}</h2>\n\
|
||||
snippet h2.\n\
|
||||
<h2 class=\"${1}\">${2}</h2>\n\
|
||||
snippet h2#\n\
|
||||
<h2 id=\"${1}\">${2}</h2>\n\
|
||||
snippet h3\n\
|
||||
<h3>${1}</h3>\n\
|
||||
snippet h3.\n\
|
||||
<h3 class=\"${1}\">${2}</h3>\n\
|
||||
snippet h3#\n\
|
||||
<h3 id=\"${1}\">${2}</h3>\n\
|
||||
snippet h4\n\
|
||||
<h4>${1}</h4>\n\
|
||||
snippet h4.\n\
|
||||
<h4 class=\"${1}\">${2}</h4>\n\
|
||||
snippet h4#\n\
|
||||
<h4 id=\"${1}\">${2}</h4>\n\
|
||||
snippet h5\n\
|
||||
<h5>${1}</h5>\n\
|
||||
snippet h5.\n\
|
||||
<h5 class=\"${1}\">${2}</h5>\n\
|
||||
snippet h5#\n\
|
||||
<h5 id=\"${1}\">${2}</h5>\n\
|
||||
snippet h6\n\
|
||||
<h6>${1}</h6>\n\
|
||||
snippet h6.\n\
|
||||
<h6 class=\"${1}\">${2}</h6>\n\
|
||||
snippet h6#\n\
|
||||
<h6 id=\"${1}\">${2}</h6>\n\
|
||||
snippet head\n\
|
||||
<head>\n\
|
||||
<meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\" />\n\
|
||||
\n\
|
||||
<title>${1:`substitute(Filename('', 'Page Title'), '^.', '\\u&', '')`}</title>\n\
|
||||
${2}\n\
|
||||
</head>\n\
|
||||
snippet header\n\
|
||||
<header>\n\
|
||||
${1}\n\
|
||||
</header>\n\
|
||||
snippet header.\n\
|
||||
<header class=\"${1}\">\n\
|
||||
${2}\n\
|
||||
</header>\n\
|
||||
snippet header#\n\
|
||||
<header id=\"${1}\">\n\
|
||||
${2}\n\
|
||||
</header>\n\
|
||||
snippet hgroup\n\
|
||||
<hgroup>\n\
|
||||
${1}\n\
|
||||
</hgroup>\n\
|
||||
snippet hgroup.\n\
|
||||
<hgroup class=\"${1}>\n\
|
||||
${2}\n\
|
||||
</hgroup>\n\
|
||||
snippet hr\n\
|
||||
<hr />${1}\n\
|
||||
snippet html\n\
|
||||
<html>\n\
|
||||
${1}\n\
|
||||
</html>\n\
|
||||
snippet xhtml\n\
|
||||
<html xmlns=\"http://www.w3.org/1999/xhtml\">\n\
|
||||
${1}\n\
|
||||
</html>\n\
|
||||
snippet html5\n\
|
||||
<!DOCTYPE html>\n\
|
||||
<html>\n\
|
||||
<head>\n\
|
||||
<meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\" />\n\
|
||||
<title>${1:`substitute(Filename('', 'Page Title'), '^.', '\\u&', '')`}</title>\n\
|
||||
${2:meta}\n\
|
||||
</head>\n\
|
||||
<body>\n\
|
||||
${3:body}\n\
|
||||
</body>\n\
|
||||
</html>\n\
|
||||
snippet i\n\
|
||||
<i>${1}</i>\n\
|
||||
snippet iframe\n\
|
||||
<iframe src=\"${1}\" frameborder=\"0\"></iframe>${2}\n\
|
||||
snippet iframe.\n\
|
||||
<iframe class=\"${1}\" src=\"${2}\" frameborder=\"0\"></iframe>${3}\n\
|
||||
snippet iframe#\n\
|
||||
<iframe id=\"${1}\" src=\"${2}\" frameborder=\"0\"></iframe>${3}\n\
|
||||
snippet img\n\
|
||||
<img src=\"${1}\" alt=\"${2}\" />${3}\n\
|
||||
snippet img.\n\
|
||||
<img class=\"${1}\" src=\"${2}\" alt=\"${3}\" />${4}\n\
|
||||
snippet img#\n\
|
||||
<img id=\"${1}\" src=\"${2}\" alt=\"${3}\" />${4}\n\
|
||||
snippet input\n\
|
||||
<input type=\"${1:text/submit/hidden/button/image}\" name=\"${2}\" id=\"${3:$2}\" value=\"${4}\" />${5}\n\
|
||||
snippet input.\n\
|
||||
<input class=\"${1}\" type=\"${2:text/submit/hidden/button/image}\" name=\"${3}\" id=\"${4:$3}\" value=\"${5}\" />${6}\n\
|
||||
snippet input:text\n\
|
||||
<input type=\"text\" name=\"${1}\" id=\"${2:$1}\" value=\"${3}\" />${4}\n\
|
||||
snippet input:submit\n\
|
||||
<input type=\"submit\" name=\"${1}\" id=\"${2:$1}\" value=\"${3}\" />${4}\n\
|
||||
snippet input:hidden\n\
|
||||
<input type=\"hidden\" name=\"${1}\" id=\"${2:$1}\" value=\"${3}\" />${4}\n\
|
||||
snippet input:button\n\
|
||||
<input type=\"button\" name=\"${1}\" id=\"${2:$1}\" value=\"${3}\" />${4}\n\
|
||||
snippet input:image\n\
|
||||
<input type=\"image\" name=\"${1}\" id=\"${2:$1}\" src=\"${3}\" alt=\"${4}\" />${5}\n\
|
||||
snippet input:checkbox\n\
|
||||
<input type=\"checkbox\" name=\"${1}\" id=\"${2:$1}\" />${3}\n\
|
||||
snippet input:radio\n\
|
||||
<input type=\"radio\" name=\"${1}\" id=\"${2:$1}\" />${3}\n\
|
||||
snippet input:color\n\
|
||||
<input type=\"color\" name=\"${1}\" id=\"${2:$1}\" value=\"${3}\" />${4}\n\
|
||||
snippet input:date\n\
|
||||
<input type=\"date\" name=\"${1}\" id=\"${2:$1}\" value=\"${3}\" />${4}\n\
|
||||
snippet input:datetime\n\
|
||||
<input type=\"datetime\" name=\"${1}\" id=\"${2:$1}\" value=\"${3}\" />${4}\n\
|
||||
snippet input:datetime-local\n\
|
||||
<input type=\"datetime-local\" name=\"${1}\" id=\"${2:$1}\" value=\"${3}\" />${4}\n\
|
||||
snippet input:email\n\
|
||||
<input type=\"email\" name=\"${1}\" id=\"${2:$1}\" value=\"${3}\" />${4}\n\
|
||||
snippet input:file\n\
|
||||
<input type=\"file\" name=\"${1}\" id=\"${2:$1}\" value=\"${3}\" />${4}\n\
|
||||
snippet input:month\n\
|
||||
<input type=\"month\" name=\"${1}\" id=\"${2:$1}\" value=\"${3}\" />${4}\n\
|
||||
snippet input:number\n\
|
||||
<input type=\"number\" name=\"${1}\" id=\"${2:$1}\" value=\"${3}\" />${4}\n\
|
||||
snippet input:password\n\
|
||||
<input type=\"password\" name=\"${1}\" id=\"${2:$1}\" value=\"${3}\" />${4}\n\
|
||||
snippet input:range\n\
|
||||
<input type=\"range\" name=\"${1}\" id=\"${2:$1}\" value=\"${3}\" />${4}\n\
|
||||
snippet input:reset\n\
|
||||
<input type=\"reset\" name=\"${1}\" id=\"${2:$1}\" value=\"${3}\" />${4}\n\
|
||||
snippet input:search\n\
|
||||
<input type=\"search\" name=\"${1}\" id=\"${2:$1}\" value=\"${3}\" />${4}\n\
|
||||
snippet input:time\n\
|
||||
<input type=\"time\" name=\"${1}\" id=\"${2:$1}\" value=\"${3}\" />${4}\n\
|
||||
snippet input:url\n\
|
||||
<input type=\"url\" name=\"${1}\" id=\"${2:$1}\" value=\"${3}\" />${4}\n\
|
||||
snippet input:week\n\
|
||||
<input type=\"week\" name=\"${1}\" id=\"${2:$1}\" value=\"${3}\" />${4}\n\
|
||||
snippet ins\n\
|
||||
<ins>${1}</ins>\n\
|
||||
snippet kbd\n\
|
||||
<kbd>${1}</kbd>\n\
|
||||
snippet keygen\n\
|
||||
<keygen>${1}</keygen>\n\
|
||||
snippet label\n\
|
||||
<label for=\"${2:$1}\">${1}</label>\n\
|
||||
snippet label:i\n\
|
||||
<label for=\"${2:$1}\">${1}</label>\n\
|
||||
<input type=\"${3:text/submit/hidden/button}\" name=\"${4:$2}\" id=\"${5:$2}\" value=\"${6}\" />${7}\n\
|
||||
snippet label:s\n\
|
||||
<label for=\"${2:$1}\">${1}</label>\n\
|
||||
<select name=\"${3:$2}\" id=\"${4:$2}\">\n\
|
||||
<option value=\"${5}\">${6:$5}</option>\n\
|
||||
</select>\n\
|
||||
snippet legend\n\
|
||||
<legend>${1}</legend>\n\
|
||||
snippet legend+\n\
|
||||
<legend><span>${1}</span></legend>\n\
|
||||
snippet li\n\
|
||||
<li>${1}</li>\n\
|
||||
snippet li.\n\
|
||||
<li class=\"${1}\">${2}</li>\n\
|
||||
snippet li+\n\
|
||||
<li>${1}</li>\n\
|
||||
li+${2}\n\
|
||||
snippet lia\n\
|
||||
<li><a href=\"${2:#}\">${1}</a></li>\n\
|
||||
snippet lia+\n\
|
||||
<li><a href=\"${2:#}\">${1}</a></li>\n\
|
||||
lia+${3}\n\
|
||||
snippet link\n\
|
||||
<link rel=\"${1}\" href=\"${2}\" title=\"${3}\" type=\"${4}\" />${5}\n\
|
||||
snippet link:atom\n\
|
||||
<link rel=\"alternate\" href=\"${1:atom.xml}\" title=\"Atom\" type=\"application/atom+xml\" />${2}\n\
|
||||
snippet link:css\n\
|
||||
<link rel=\"stylesheet\" href=\"${2:style.css}\" type=\"text/css\" media=\"${3:all}\" />${4}\n\
|
||||
snippet link:favicon\n\
|
||||
<link rel=\"shortcut icon\" href=\"${1:favicon.ico}\" type=\"image/x-icon\" />${2}\n\
|
||||
snippet link:rss\n\
|
||||
<link rel=\"alternate\" href=\"${1:rss.xml}\" title=\"RSS\" type=\"application/atom+xml\" />${2}\n\
|
||||
snippet link:touch\n\
|
||||
<link rel=\"apple-touch-icon\" href=\"${1:favicon.png}\" />${2}\n\
|
||||
snippet map\n\
|
||||
<map name=\"${1}\">\n\
|
||||
${2}\n\
|
||||
</map>\n\
|
||||
snippet map.\n\
|
||||
<map class=\"${1}\" name=\"${2}\">\n\
|
||||
${3}\n\
|
||||
</map>\n\
|
||||
snippet map#\n\
|
||||
<map name=\"${1}\" id=\"${2:$1}>\n\
|
||||
${3}\n\
|
||||
</map>\n\
|
||||
snippet map+\n\
|
||||
<map name=\"${1}\">\n\
|
||||
<area shape=\"${2}\" coords=\"${3}\" href=\"${4}\" alt=\"${5}\" />${6}\n\
|
||||
</map>${7}\n\
|
||||
snippet mark\n\
|
||||
<mark>${1}</mark>\n\
|
||||
snippet menu\n\
|
||||
<menu>\n\
|
||||
${1}\n\
|
||||
</menu>\n\
|
||||
snippet menu:c\n\
|
||||
<menu type=\"context\">\n\
|
||||
${1}\n\
|
||||
</menu>\n\
|
||||
snippet menu:t\n\
|
||||
<menu type=\"toolbar\">\n\
|
||||
${1}\n\
|
||||
</menu>\n\
|
||||
snippet meta\n\
|
||||
<meta http-equiv=\"${1}\" content=\"${2}\" />${3}\n\
|
||||
snippet meta:compat\n\
|
||||
<meta http-equiv=\"X-UA-Compatible\" content=\"IE=${1:7,8,edge}\" />${3}\n\
|
||||
snippet meta:refresh\n\
|
||||
<meta http-equiv=\"refresh\" content=\"text/html;charset=UTF-8\" />${3}\n\
|
||||
snippet meta:utf\n\
|
||||
<meta http-equiv=\"content-type\" content=\"text/html;charset=UTF-8\" />${3}\n\
|
||||
snippet meter\n\
|
||||
<meter>${1}</meter>\n\
|
||||
snippet nav\n\
|
||||
<nav>\n\
|
||||
${1}\n\
|
||||
</nav>\n\
|
||||
snippet nav.\n\
|
||||
<nav class=\"${1}\">\n\
|
||||
${2}\n\
|
||||
</nav>\n\
|
||||
snippet nav#\n\
|
||||
<nav id=\"${1}\">\n\
|
||||
${2}\n\
|
||||
</nav>\n\
|
||||
snippet noscript\n\
|
||||
<noscript>\n\
|
||||
${1}\n\
|
||||
</noscript>\n\
|
||||
snippet object\n\
|
||||
<object data=\"${1}\" type=\"${2}\">\n\
|
||||
${3}\n\
|
||||
</object>${4}\n\
|
||||
# Embed QT Movie\n\
|
||||
snippet movie\n\
|
||||
<object width=\"$2\" height=\"$3\" classid=\"clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B\"\n\
|
||||
codebase=\"http://www.apple.com/qtactivex/qtplugin.cab\">\n\
|
||||
<param name=\"src\" value=\"$1\" />\n\
|
||||
<param name=\"controller\" value=\"$4\" />\n\
|
||||
<param name=\"autoplay\" value=\"$5\" />\n\
|
||||
<embed src=\"${1:movie.mov}\"\n\
|
||||
width=\"${2:320}\" height=\"${3:240}\"\n\
|
||||
controller=\"${4:true}\" autoplay=\"${5:true}\"\n\
|
||||
scale=\"tofit\" cache=\"true\"\n\
|
||||
pluginspage=\"http://www.apple.com/quicktime/download/\" />\n\
|
||||
</object>${6}\n\
|
||||
snippet ol\n\
|
||||
<ol>\n\
|
||||
${1}\n\
|
||||
</ol>\n\
|
||||
snippet ol.\n\
|
||||
<ol class=\"${1}>\n\
|
||||
${2}\n\
|
||||
</ol>\n\
|
||||
snippet ol#\n\
|
||||
<ol id=\"${1}>\n\
|
||||
${2}\n\
|
||||
</ol>\n\
|
||||
snippet ol+\n\
|
||||
<ol>\n\
|
||||
<li>${1}</li>\n\
|
||||
li+${2}\n\
|
||||
</ol>\n\
|
||||
snippet opt\n\
|
||||
<option value=\"${1}\">${2:$1}</option>\n\
|
||||
snippet opt+\n\
|
||||
<option value=\"${1}\">${2:$1}</option>\n\
|
||||
opt+${3}\n\
|
||||
snippet optt\n\
|
||||
<option>${1}</option>\n\
|
||||
snippet optgroup\n\
|
||||
<optgroup>\n\
|
||||
<option value=\"${1}\">${2:$1}</option>\n\
|
||||
opt+${3}\n\
|
||||
</optgroup>\n\
|
||||
snippet output\n\
|
||||
<output>${1}</output>\n\
|
||||
snippet p\n\
|
||||
<p>${1}</p>\n\
|
||||
snippet param\n\
|
||||
<param name=\"${1}\" value=\"${2}\" />${3}\n\
|
||||
snippet pre\n\
|
||||
<pre>\n\
|
||||
${1}\n\
|
||||
</pre>\n\
|
||||
snippet progress\n\
|
||||
<progress>${1}</progress>\n\
|
||||
snippet q\n\
|
||||
<q>${1}</q>\n\
|
||||
snippet rp\n\
|
||||
<rp>${1}</rp>\n\
|
||||
snippet rt\n\
|
||||
<rt>${1}</rt>\n\
|
||||
snippet ruby\n\
|
||||
<ruby>\n\
|
||||
<rp><rt>${1}</rt></rp>\n\
|
||||
</ruby>\n\
|
||||
snippet s\n\
|
||||
<s>${1}</s>\n\
|
||||
snippet samp\n\
|
||||
<samp>\n\
|
||||
${1}\n\
|
||||
</samp>\n\
|
||||
snippet script\n\
|
||||
<script type=\"text/javascript\" charset=\"utf-8\">\n\
|
||||
${1}\n\
|
||||
</script>\n\
|
||||
snippet scriptsrc\n\
|
||||
<script src=\"${1}.js\" type=\"text/javascript\" charset=\"utf-8\"></script>\n\
|
||||
snippet section\n\
|
||||
<section>\n\
|
||||
${1}\n\
|
||||
</section>\n\
|
||||
snippet section.\n\
|
||||
<section class=\"${1}\">\n\
|
||||
${2}\n\
|
||||
</section>\n\
|
||||
snippet section#\n\
|
||||
<section id=\"${1}\">\n\
|
||||
${2}\n\
|
||||
</section>\n\
|
||||
snippet select\n\
|
||||
<select name=\"${1}\" id=\"${2:$1}\">\n\
|
||||
${3}\n\
|
||||
</select>\n\
|
||||
snippet select.\n\
|
||||
<select name=\"${1}\" id=\"${2:$1}\" class=\"${3}>\n\
|
||||
${4}\n\
|
||||
</select>\n\
|
||||
snippet select+\n\
|
||||
<select name=\"${1}\" id=\"${2:$1}\">\n\
|
||||
<option value=\"${3}\">${4:$3}</option>\n\
|
||||
opt+${5}\n\
|
||||
</select>\n\
|
||||
snippet small\n\
|
||||
<small>${1}</small>\n\
|
||||
snippet source\n\
|
||||
<source src=\"${1}\" type=\"${2}\" media=\"${3}\" />\n\
|
||||
snippet span\n\
|
||||
<span>${1}</span>\n\
|
||||
snippet strong\n\
|
||||
<strong>${1}</strong>\n\
|
||||
snippet style\n\
|
||||
<style type=\"text/css\" media=\"${1:all}\">\n\
|
||||
${2}\n\
|
||||
</style>\n\
|
||||
snippet sub\n\
|
||||
<sub>${1}</sub>\n\
|
||||
snippet summary\n\
|
||||
<summary>\n\
|
||||
${1}\n\
|
||||
</summary>\n\
|
||||
snippet sup\n\
|
||||
<sup>${1}</sup>\n\
|
||||
snippet table\n\
|
||||
<table border=\"${1:0}\">\n\
|
||||
${2}\n\
|
||||
</table>\n\
|
||||
snippet table.\n\
|
||||
<table class=\"${1}\" border=\"${2:0}\">\n\
|
||||
${3}\n\
|
||||
</table>\n\
|
||||
snippet table#\n\
|
||||
<table id=\"${1}\" border=\"${2:0}\">\n\
|
||||
${3}\n\
|
||||
</table>\n\
|
||||
snippet tbody\n\
|
||||
<tbody>\n\
|
||||
${1}\n\
|
||||
</tbody>\n\
|
||||
snippet td\n\
|
||||
<td>${1}</td>\n\
|
||||
snippet td.\n\
|
||||
<td class=\"${1}\">${2}</td>\n\
|
||||
snippet td#\n\
|
||||
<td id=\"${1}\">${2}</td>\n\
|
||||
snippet td+\n\
|
||||
<td>${1}</td>\n\
|
||||
td+${2}\n\
|
||||
snippet textarea\n\
|
||||
<textarea name=\"${1}\" id=${2:$1} rows=\"${3:8}\" cols=\"${4:40}\">${5}</textarea>${6}\n\
|
||||
snippet tfoot\n\
|
||||
<tfoot>\n\
|
||||
${1}\n\
|
||||
</tfoot>\n\
|
||||
snippet th\n\
|
||||
<th>${1}</th>\n\
|
||||
snippet th.\n\
|
||||
<th class=\"${1}\">${2}</th>\n\
|
||||
snippet th#\n\
|
||||
<th id=\"${1}\">${2}</th>\n\
|
||||
snippet th+\n\
|
||||
<th>${1}</th>\n\
|
||||
th+${2}\n\
|
||||
snippet thead\n\
|
||||
<thead>\n\
|
||||
${1}\n\
|
||||
</thead>\n\
|
||||
snippet time\n\
|
||||
<time datetime=\"${1}\" pubdate=\"${2:$1}>${3:$1}</time>\n\
|
||||
snippet title\n\
|
||||
<title>${1:`substitute(Filename('', 'Page Title'), '^.', '\\u&', '')`}</title>\n\
|
||||
snippet tr\n\
|
||||
<tr>\n\
|
||||
${1}\n\
|
||||
</tr>\n\
|
||||
snippet tr+\n\
|
||||
<tr>\n\
|
||||
<td>${1}</td>\n\
|
||||
td+${2}\n\
|
||||
</tr>\n\
|
||||
snippet track\n\
|
||||
<track src=\"${1}\" srclang=\"${2}\" label=\"${3}\" default=\"${4:default}>${5}</track>${6}\n\
|
||||
snippet ul\n\
|
||||
<ul>\n\
|
||||
${1}\n\
|
||||
</ul>\n\
|
||||
snippet ul.\n\
|
||||
<ul class=\"${1}\">\n\
|
||||
${2}\n\
|
||||
</ul>\n\
|
||||
snippet ul#\n\
|
||||
<ul id=\"${1}\">\n\
|
||||
${2}\n\
|
||||
</ul>\n\
|
||||
snippet ul+\n\
|
||||
<ul>\n\
|
||||
<li>${1}</li>\n\
|
||||
li+${2}\n\
|
||||
</ul>\n\
|
||||
snippet var\n\
|
||||
<var>${1}</var>\n\
|
||||
snippet video\n\
|
||||
<video src=\"${1} height=\"${2}\" width=\"${3}\" preload=\"${5:none}\" autoplay=\"${6:autoplay}>${7}</video>${8}\n\
|
||||
snippet wbr\n\
|
||||
<wbr />${1}\n\
|
||||
";
|
||||
exports.scope = "html";
|
||||
|
||||
});
|
||||
1
editor/vendor/ace/snippets/properties.js
vendored
1
editor/vendor/ace/snippets/properties.js
vendored
@@ -1 +0,0 @@
|
||||
ace.define("ace/snippets/properties",["require","exports","module"],function(e,t,n){"use strict";t.snippetText=undefined,t.scope="properties"})
|
||||
1
editor/vendor/ace/snippets/text.js
vendored
1
editor/vendor/ace/snippets/text.js
vendored
@@ -1 +0,0 @@
|
||||
ace.define("ace/snippets/text",["require","exports","module"],function(e,t,n){"use strict";t.snippetText=undefined,t.scope="text"})
|
||||
1
editor/vendor/ace/snippets/yaml.js
vendored
1
editor/vendor/ace/snippets/yaml.js
vendored
@@ -1 +0,0 @@
|
||||
ace.define("ace/snippets/yaml",["require","exports","module"],function(e,t,n){"use strict";t.snippetText=undefined,t.scope="yaml"})
|
||||
1
editor/vendor/ace/worker-html.js
vendored
1
editor/vendor/ace/worker-html.js
vendored
File diff suppressed because one or more lines are too long
1
editor/vendor/ace/worker-javascript.js
vendored
1
editor/vendor/ace/worker-javascript.js
vendored
File diff suppressed because one or more lines are too long
1
editor/vendor/ace/worker-json.js
vendored
1
editor/vendor/ace/worker-json.js
vendored
File diff suppressed because one or more lines are too long
26
jsdoc.json
Normal file
26
jsdoc.json
Normal file
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"opts": {
|
||||
"template": "./node_modules/jsdoc-nr-template",
|
||||
"destination": "./docs",
|
||||
"recurse": true
|
||||
},
|
||||
"tags": {
|
||||
"allowUnknownTags": false,
|
||||
"dictionaries": ["jsdoc"]
|
||||
},
|
||||
"source": {
|
||||
"_include": [
|
||||
"./packages/node_modules/@node-red/runtime/lib/api"
|
||||
]
|
||||
},
|
||||
"templates": {
|
||||
"systemName": "Node-RED Runtime API",
|
||||
"theme":"yeti",
|
||||
"footer": "",
|
||||
"copyright": "Released under the Apache License v2.0",
|
||||
"default": {
|
||||
"outputSourceFiles": false
|
||||
}
|
||||
},
|
||||
"plugins": ["plugins/markdown"]
|
||||
}
|
||||
1
lib/.gitignore
vendored
1
lib/.gitignore
vendored
@@ -1 +0,0 @@
|
||||
*
|
||||
@@ -1,61 +0,0 @@
|
||||
<!--
|
||||
Copyright JS Foundation and other contributors, http://js.foundation
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<script type="text/x-red" data-template-name="sentiment">
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
|
||||
<input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="sentiment">
|
||||
<p>Analyses the <code>payload</code> and adds a <code>sentiment</code> object.</p>
|
||||
<h3>Outputs</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>sentiment <span class="property-type">object</span></dt>
|
||||
<dd>contains the resulting AFINN-111 sentiment.</dd>
|
||||
<dt>sentiment.score <span class="property-type">number</span></dt>
|
||||
<dd>the sentiment score.</dd>
|
||||
</dl>
|
||||
<h3>Inputs</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>overrides <span class="property-type">object</span></dt>
|
||||
<dd>an object of word score overrides can be supplied - <code>{ word:score,... }</code>.</dd>
|
||||
</dl>
|
||||
<h3>Details</h3>
|
||||
<p>A score greater than zero is positive and less than zero is negative.</p>
|
||||
<p>The score typically ranges from -5 to +5, but can go higher and lower.</p>
|
||||
<p>See <a href="https://github.com/thisandagain/sentiment/blob/master/README.md" target="_blank">the Sentiment docs here</a>.</p>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('sentiment',{
|
||||
category: 'analysis-function',
|
||||
color:"#E6E0F8",
|
||||
defaults: {
|
||||
name: {value:""},
|
||||
},
|
||||
inputs:1,
|
||||
outputs:1,
|
||||
icon: "arrow-in.png",
|
||||
label: function() {
|
||||
return this.name||"sentiment";
|
||||
},
|
||||
labelStyle: function() {
|
||||
return this.name?"node_label_italic":"";
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@@ -1,99 +0,0 @@
|
||||
/**
|
||||
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
module.exports = function(RED) {
|
||||
"use strict";
|
||||
var cron = require("cron");
|
||||
|
||||
function InjectNode(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
this.topic = n.topic;
|
||||
this.payload = n.payload;
|
||||
this.payloadType = n.payloadType;
|
||||
this.repeat = n.repeat;
|
||||
this.crontab = n.crontab;
|
||||
this.once = n.once;
|
||||
var node = this;
|
||||
this.interval_id = null;
|
||||
this.cronjob = null;
|
||||
|
||||
if (this.repeat && !isNaN(this.repeat) && this.repeat > 0) {
|
||||
this.repeat = this.repeat * 1000;
|
||||
if (RED.settings.verbose) { this.log(RED._("inject.repeat",this)); }
|
||||
this.interval_id = setInterval( function() {
|
||||
node.emit("input",{});
|
||||
}, this.repeat );
|
||||
} else if (this.crontab) {
|
||||
if (RED.settings.verbose) { this.log(RED._("inject.crontab",this)); }
|
||||
this.cronjob = new cron.CronJob(this.crontab,
|
||||
function() {
|
||||
node.emit("input",{});
|
||||
},
|
||||
null,true);
|
||||
}
|
||||
|
||||
if (this.once) {
|
||||
setTimeout( function() { node.emit("input",{}); }, 100 );
|
||||
}
|
||||
|
||||
this.on("input",function(msg) {
|
||||
try {
|
||||
msg.topic = this.topic;
|
||||
if ( (this.payloadType == null && this.payload === "") || this.payloadType === "date") {
|
||||
msg.payload = Date.now();
|
||||
} else if (this.payloadType == null) {
|
||||
msg.payload = this.payload;
|
||||
} else if (this.payloadType == 'none') {
|
||||
msg.payload = "";
|
||||
} else {
|
||||
msg.payload = RED.util.evaluateNodeProperty(this.payload,this.payloadType,this,msg);
|
||||
}
|
||||
this.send(msg);
|
||||
msg = null;
|
||||
} catch(err) {
|
||||
this.error(err,msg);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
RED.nodes.registerType("inject",InjectNode);
|
||||
|
||||
InjectNode.prototype.close = function() {
|
||||
if (this.interval_id != null) {
|
||||
clearInterval(this.interval_id);
|
||||
if (RED.settings.verbose) { this.log(RED._("inject.stopped")); }
|
||||
} else if (this.cronjob != null) {
|
||||
this.cronjob.stop();
|
||||
if (RED.settings.verbose) { this.log(RED._("inject.stopped")); }
|
||||
delete this.cronjob;
|
||||
}
|
||||
}
|
||||
|
||||
RED.httpAdmin.post("/inject/:id", RED.auth.needsPermission("inject.write"), function(req,res) {
|
||||
var node = RED.nodes.getNode(req.params.id);
|
||||
if (node != null) {
|
||||
try {
|
||||
node.receive();
|
||||
res.sendStatus(200);
|
||||
} catch(err) {
|
||||
res.sendStatus(500);
|
||||
node.error(RED._("inject.failed",{error:err.toString()}));
|
||||
}
|
||||
} else {
|
||||
res.sendStatus(404);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -1,219 +0,0 @@
|
||||
|
||||
module.exports = function(RED) {
|
||||
"use strict";
|
||||
var util = require("util");
|
||||
var events = require("events");
|
||||
var path = require("path");
|
||||
var safeJSONStringify = require("json-stringify-safe");
|
||||
var debuglength = RED.settings.debugMaxLength||1000;
|
||||
var useColors = RED.settings.debugUseColors || false;
|
||||
util.inspect.styles.boolean = "red";
|
||||
|
||||
function DebugNode(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
this.name = n.name;
|
||||
this.complete = (n.complete||"payload").toString();
|
||||
|
||||
if (this.complete === "false") {
|
||||
this.complete = "payload";
|
||||
}
|
||||
|
||||
this.console = n.console;
|
||||
this.active = (n.active === null || typeof n.active === "undefined") || n.active;
|
||||
var node = this;
|
||||
|
||||
this.on("input",function(msg) {
|
||||
if (this.complete === "true") {
|
||||
// debug complete msg object
|
||||
if (this.console === "true") {
|
||||
node.log("\n"+util.inspect(msg, {colors:useColors, depth:10}));
|
||||
}
|
||||
if (this.active) {
|
||||
setTimeout(function() {
|
||||
sendDebug({id:node.id,name:node.name,topic:msg.topic,msg:msg,_path:msg._path});
|
||||
},0);
|
||||
}
|
||||
} else {
|
||||
// debug user defined msg property
|
||||
var property = "payload";
|
||||
var output = msg[property];
|
||||
if (this.complete !== "false" && typeof this.complete !== "undefined") {
|
||||
property = this.complete;
|
||||
try {
|
||||
output = RED.util.getMessageProperty(msg,this.complete);
|
||||
} catch(err) {
|
||||
output = undefined;
|
||||
}
|
||||
}
|
||||
if (this.console === "true") {
|
||||
if (typeof output === "string") {
|
||||
node.log((output.indexOf("\n") !== -1 ? "\n" : "") + output);
|
||||
} else if (typeof output === "object") {
|
||||
node.log("\n"+util.inspect(output, {colors:useColors, depth:10}));
|
||||
} else {
|
||||
node.log(util.inspect(output, {colors:useColors}));
|
||||
}
|
||||
}
|
||||
if (this.active) {
|
||||
setTimeout(function() {
|
||||
sendDebug({id:node.id,z:node.z,name:node.name,topic:msg.topic,property:property,msg:output,_path:msg._path});
|
||||
},0);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
RED.nodes.registerType("debug",DebugNode, {
|
||||
settings: {
|
||||
debugUseColors: {
|
||||
value: false,
|
||||
},
|
||||
debugMaxLength: {
|
||||
value: 1000,
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function sendDebug(msg) {
|
||||
// don't put blank errors in sidebar (but do add to logs)
|
||||
//if ((msg.msg === "") && (msg.hasOwnProperty("level")) && (msg.level === 20)) { return; }
|
||||
if (msg.msg instanceof Error) {
|
||||
msg.format = "error";
|
||||
var errorMsg = {};
|
||||
if (msg.msg.name) {
|
||||
errorMsg.name = msg.msg.name;
|
||||
}
|
||||
if (msg.msg.hasOwnProperty('message')) {
|
||||
errorMsg.message = msg.msg.message;
|
||||
} else {
|
||||
errorMsg.message = msg.msg.toString();
|
||||
}
|
||||
msg.msg = JSON.stringify(errorMsg);
|
||||
} else if (msg.msg instanceof Buffer) {
|
||||
msg.format = "buffer["+msg.msg.length+"]";
|
||||
msg.msg = msg.msg.toString('hex');
|
||||
if (msg.msg.length > debuglength) {
|
||||
msg.msg = msg.msg.substring(0,debuglength);
|
||||
}
|
||||
} else if (msg.msg && typeof msg.msg === 'object') {
|
||||
try {
|
||||
msg.format = msg.msg.constructor.name || "Object";
|
||||
// Handle special case of msg.req/res objects from HTTP In node
|
||||
if (msg.format === "IncomingMessage" || msg.format === "ServerResponse") {
|
||||
msg.format = "Object";
|
||||
}
|
||||
} catch(err) {
|
||||
msg.format = "Object";
|
||||
}
|
||||
if (/error/i.test(msg.format)) {
|
||||
msg.msg = JSON.stringify({
|
||||
name: msg.msg.name,
|
||||
message: msg.msg.message
|
||||
});
|
||||
} else {
|
||||
var isArray = util.isArray(msg.msg);
|
||||
if (isArray) {
|
||||
msg.format = "array["+msg.msg.length+"]";
|
||||
if (msg.msg.length > debuglength) {
|
||||
// msg.msg = msg.msg.slice(0,debuglength);
|
||||
msg.msg = {
|
||||
__encoded__: true,
|
||||
type: "array",
|
||||
data: msg.msg.slice(0,debuglength),
|
||||
length: msg.msg.length
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isArray || (msg.format === "Object")) {
|
||||
msg.msg = safeJSONStringify(msg.msg, function(key, value) {
|
||||
if (key === '_req' || key === '_res') {
|
||||
value = "[internal]"
|
||||
} else if (value instanceof Error) {
|
||||
value = value.toString()
|
||||
} else if (util.isArray(value) && value.length > debuglength) {
|
||||
value = {
|
||||
__encoded__: true,
|
||||
type: "array",
|
||||
data: value.slice(0,debuglength),
|
||||
length: value.length
|
||||
}
|
||||
} else if (typeof value === 'string') {
|
||||
if (value.length > debuglength) {
|
||||
value = value.substring(0,debuglength)+"...";
|
||||
}
|
||||
} else if (value !== null && typeof value === 'object' && value.type === "Buffer") {
|
||||
value.__encoded__ = true;
|
||||
value.length = value.data.length;
|
||||
if (value.length > debuglength) {
|
||||
value.data = value.data.slice(0,debuglength);
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}," ");
|
||||
} else {
|
||||
try { msg.msg = msg.msg.toString(); }
|
||||
catch(e) { msg.msg = "[Type not printable]"; }
|
||||
}
|
||||
}
|
||||
} else if (typeof msg.msg === "boolean") {
|
||||
msg.format = "boolean";
|
||||
msg.msg = msg.msg.toString();
|
||||
} else if (typeof msg.msg === "number") {
|
||||
msg.format = "number";
|
||||
msg.msg = msg.msg.toString();
|
||||
} else if (msg.msg === 0) {
|
||||
msg.format = "number";
|
||||
msg.msg = "0";
|
||||
} else if (msg.msg === null || typeof msg.msg === "undefined") {
|
||||
msg.format = (msg.msg === null)?"null":"undefined";
|
||||
msg.msg = "(undefined)";
|
||||
} else {
|
||||
msg.format = "string["+msg.msg.length+"]";
|
||||
if (msg.msg.length > debuglength) {
|
||||
msg.msg = msg.msg.substring(0,debuglength)+"...";
|
||||
}
|
||||
}
|
||||
// if (msg.msg.length > debuglength) {
|
||||
// msg.msg = msg.msg.substr(0,debuglength) +" ....";
|
||||
// }
|
||||
RED.comms.publish("debug",msg);
|
||||
}
|
||||
|
||||
DebugNode.logHandler = new events.EventEmitter();
|
||||
DebugNode.logHandler.on("log",function(msg) {
|
||||
if (msg.level === RED.log.WARN || msg.level === RED.log.ERROR) {
|
||||
setTimeout(function() {
|
||||
sendDebug(msg);
|
||||
},0);
|
||||
}
|
||||
});
|
||||
RED.log.addHandler(DebugNode.logHandler);
|
||||
|
||||
RED.httpAdmin.post("/debug/:id/:state", RED.auth.needsPermission("debug.write"), function(req,res) {
|
||||
var node = RED.nodes.getNode(req.params.id);
|
||||
var state = req.params.state;
|
||||
if (node !== null && typeof node !== "undefined" ) {
|
||||
if (state === "enable") {
|
||||
node.active = true;
|
||||
res.sendStatus(200);
|
||||
} else if (state === "disable") {
|
||||
node.active = false;
|
||||
res.sendStatus(201);
|
||||
} else {
|
||||
res.sendStatus(404);
|
||||
}
|
||||
} else {
|
||||
res.sendStatus(404);
|
||||
}
|
||||
});
|
||||
|
||||
// As debug/view/debug-utils.js is loaded via <script> tag, it won't get
|
||||
// the auth header attached. So do not use RED.auth.needsPermission here.
|
||||
RED.httpAdmin.get("/debug/view/*",function(req,res) {
|
||||
var options = {
|
||||
root: __dirname + '/lib/debug/',
|
||||
dotfiles: 'deny'
|
||||
};
|
||||
res.sendFile(req.params[0], options);
|
||||
});
|
||||
};
|
||||
@@ -1,319 +0,0 @@
|
||||
|
||||
<script type="text/x-red" data-template-name="link in">
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
|
||||
<input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
|
||||
</div>
|
||||
<div class="form-row node-input-link-row"></div>
|
||||
</script>
|
||||
<script type="text/x-red" data-template-name="link out">
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
|
||||
<input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
|
||||
</div>
|
||||
<div class="form-row node-input-link-row"></div>
|
||||
</script>
|
||||
<script type="text/x-red" data-help-name="link in">
|
||||
<p>Create virtual wires between flows.</p>
|
||||
<h3>Details</h3>
|
||||
<p>The node can be connected to any <code>link out</code> node that exists on any tab.
|
||||
Once connected, they behave as if they were wired together.</p>
|
||||
<p>The wires between link nodes are only displayed when a link node is selected.
|
||||
If there are any wires to other tabs, a virtual node is shown that can be clicked
|
||||
on to jump to the appropriate tab.</p>
|
||||
<p><b>Note: </b>Links cannot be created going into, or out of, a subflow.</p>
|
||||
</script>
|
||||
<script type="text/x-red" data-help-name="link out">
|
||||
<p>Create virtual wires between flows.</p>
|
||||
<h3>Details</h3>
|
||||
<p>The node can be connected to any <code>link in</code> node that exists on any tab.
|
||||
Once connected, they behave as if they were wired together.</p>
|
||||
<p>The wires between link nodes are only displayed when a link node is selected.
|
||||
If there are any wires to other tabs, a virtual node is show that can be clicked
|
||||
on to jump to the appropriate tab.</p>
|
||||
<p><b>Note: </b>Links cannot be created going into, or out of, a subflow.</p>
|
||||
</script>
|
||||
<style>
|
||||
#node-input-link-container {
|
||||
position: relative;
|
||||
}
|
||||
#node-input-link-container li {
|
||||
padding: 2px 5px;
|
||||
background: none;
|
||||
font-size: 0.8em;
|
||||
margin:0;
|
||||
white-space: nowrap;
|
||||
}
|
||||
#node-input-link-container li label {
|
||||
margin-bottom: 0;
|
||||
width: 100%;
|
||||
}
|
||||
#node-input-link-container li label input {
|
||||
vertical-align: top;
|
||||
width:15px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
#node-input-link-container li:hover,
|
||||
#node-input-link-container li:hover .node-input-target-node-sublabel {
|
||||
background: #f0f0f0;
|
||||
}
|
||||
.node-input-link-node-sublabel {
|
||||
position:absolute;
|
||||
right: 0px;
|
||||
padding-right: 10px;
|
||||
padding-left: 10px;
|
||||
font-size: 0.8em;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script type="text/javascript">
|
||||
(function() {
|
||||
|
||||
function sortNodeList(nodeList,sortOn,sortOnSecond) {
|
||||
var currentSort = nodeList.data('currentSort');
|
||||
var currentSortOrder = nodeList.data('currentSortOrder');
|
||||
|
||||
if (!currentSort) {
|
||||
currentSort = sortOn;
|
||||
currentSortOrder = 'a';
|
||||
} else {
|
||||
if (currentSort === sortOn) {
|
||||
currentSortOrder = (currentSortOrder === 'a'?'d':'a');
|
||||
} else {
|
||||
currentSortOrder = 'a';
|
||||
}
|
||||
currentSort = sortOn;
|
||||
}
|
||||
nodeList.data('currentSort',currentSort);
|
||||
nodeList.data('currentSortOrder',currentSortOrder);
|
||||
|
||||
$("#node-input-link-container-div .fa").hide();
|
||||
$(".node-input-link-sort-"+currentSort+"-"+currentSortOrder).show();
|
||||
|
||||
|
||||
var items = nodeList.find("li").get();
|
||||
items.sort(function(a,b) {
|
||||
var labelA = $(a).find(".node-input-link-node-"+currentSort).text().toLowerCase();
|
||||
var labelB = $(b).find(".node-input-link-node-"+currentSort).text().toLowerCase();
|
||||
if (labelA < labelB) { return currentSortOrder==='a'?-1:1; }
|
||||
if (labelA > labelB) { return currentSortOrder==='a'?1:-1; }
|
||||
|
||||
if (sortOnSecond) {
|
||||
labelA = $(a).find(".node-input-link-node-"+sortOnSecond).text().toLowerCase();
|
||||
labelB = $(b).find(".node-input-link-node-"+sortOnSecond).text().toLowerCase();
|
||||
if (labelA < labelB) { return currentSortOrder==='a'?-1:1; }
|
||||
if (labelA > labelB) { return currentSortOrder==='a'?1:-1; }
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
$.each(items, function(i, li) {
|
||||
nodeList.append(li);
|
||||
});
|
||||
}
|
||||
function onEditPrepare(node,targetType) {
|
||||
if (!node.links) {
|
||||
node.links = [];
|
||||
}
|
||||
node.oldLinks = [];
|
||||
|
||||
$('<div id="node-input-link-container-div" style="min-height: 100px;position: relative; box-sizing: border-box; border-radius: 2px; height: 180px; border: 1px solid #ccc;overflow:hidden; ">'+
|
||||
' <div style="box-sizing: border-box; line-height: 20px; font-size: 0.8em; border-bottom: 1px solid #ddd; height: 20px;">'+
|
||||
' <div style="display: inline-block;margin-left: 5px;"><a id="node-input-link-sort-label" href="#" data-i18n="[title]link.label.sortByLabel"><span data-i18n="link.label.node">name</span> <i class="node-input-link-sort-label-a fa fa-caret-down"></i><i class="node-input-link-sort-label-d fa fa-caret-up"></i></a></div>'+
|
||||
' <div style="position: absolute; right: 10px; width: 50px; display: inline-block; text-align: right;"><a id="node-input-link-sort-type" href="#" data-i18n="[title]link.label.sortByFlow"><i class="node-input-link-sort-sublabel-a fa fa-caret-down"></i><i class="node-input-link-sort-sublabel-d fa fa-caret-up"></i> <span data-i18n="link.label.type">flow</span></a></div>'+
|
||||
' </div>'+
|
||||
' <div style="background: #fbfbfb; box-sizing: border-box; position:absolute; top:20px;bottom:0;left:0px;right:0px; overflow-y: scroll; overflow-x: hidden;">'+
|
||||
' <ul id="node-input-link-container" style=" list-style-type:none; margin: 0;"></ul>'+
|
||||
' </div>'+
|
||||
'</div>').appendTo('.node-input-link-row');
|
||||
|
||||
var nodeList = $("#node-input-link-container");
|
||||
var candidateNodes = RED.nodes.filterNodes({type:targetType});
|
||||
var inSubflow = !!RED.nodes.subflow(node.z);
|
||||
candidateNodes.forEach(function(n) {
|
||||
if (inSubflow) {
|
||||
if (n.z !== node.z) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (!!RED.nodes.subflow(n.z)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
var isChecked = false;
|
||||
|
||||
isChecked = (node.links.indexOf(n.id) !== -1) || (n.links||[]).indexOf(node.id) !== -1;
|
||||
|
||||
if (isChecked) {
|
||||
node.oldLinks.push(n.id);
|
||||
}
|
||||
|
||||
var container = $('<li/>',{class:"node-input-link-node"});
|
||||
var row = $('<label/>',{for:"node-input-link-node-"+n.id}).appendTo(container);
|
||||
$('<input>',{type:"checkbox",class:"node-input-link-node-checkbox",id:"node-input-link-node-"+n.id})
|
||||
.data('node-id',n.id)
|
||||
.prop('checked', isChecked)
|
||||
.appendTo(row);
|
||||
container.on('mouseover',function(e) {
|
||||
n.highlighted = true;
|
||||
n.dirty = true;
|
||||
RED.view.redraw();
|
||||
});
|
||||
container.on('mouseout',function(e) {
|
||||
n.highlighted = false;
|
||||
n.dirty = true;
|
||||
RED.view.redraw();
|
||||
});
|
||||
var labelSpan = $('<span>');
|
||||
var label = n.name||n.id;
|
||||
var sublabel;
|
||||
var tab = RED.nodes.workspace(n.z);
|
||||
if (tab) {
|
||||
sublabel = tab.label||tab.id;
|
||||
} else {
|
||||
tab = RED.nodes.subflow(n.z);
|
||||
sublabel = "subflow : "+tab.name;
|
||||
}
|
||||
$('<span>',{class:"node-input-link-node-label",style:"white-space:nowrap"}).text(label).appendTo(row);
|
||||
if (sublabel) {
|
||||
$('<span>',{class:"node-input-link-node-sublabel"}).text(sublabel).appendTo(row);
|
||||
}
|
||||
container.appendTo(nodeList);
|
||||
});
|
||||
|
||||
sortNodeList(nodeList,'sublabel','label');
|
||||
|
||||
$("#node-input-link-sort-label").click(function(e) {
|
||||
e.preventDefault();
|
||||
sortNodeList(nodeList,'label');
|
||||
});
|
||||
|
||||
$("#node-input-link-sort-type").click(function(e) {
|
||||
e.preventDefault();
|
||||
sortNodeList(nodeList,'sublabel');
|
||||
});
|
||||
}
|
||||
|
||||
function resizeNodeList() {
|
||||
var rows = $("#dialog-form>div:not(.node-input-link-row)");
|
||||
var height = $("#dialog-form").height();
|
||||
for (var i=0;i<rows.size();i++) {
|
||||
height -= $(rows[i]).outerHeight(true);
|
||||
}
|
||||
var editorRow = $("#dialog-form>div.node-input-link-row");
|
||||
height -= (parseInt(editorRow.css("marginTop"))+parseInt(editorRow.css("marginBottom")));
|
||||
$("#node-input-link-container-div").css("height",height+"px");
|
||||
}
|
||||
|
||||
function onEditSave(node) {
|
||||
node.links = [];
|
||||
$(".node-input-link-node-checkbox").each(function(n) {
|
||||
if ($(this).prop("checked")) {
|
||||
node.links.push($(this).data('node-id'));
|
||||
}
|
||||
});
|
||||
node.oldLinks.sort();
|
||||
node.links.sort();
|
||||
var nodeMap = {};
|
||||
var length = Math.max(node.oldLinks.length,node.links.length);
|
||||
for (var i=0;i<length;i++) {
|
||||
if (i<node.oldLinks.length) {
|
||||
nodeMap[node.oldLinks[i]] = nodeMap[node.oldLinks[i]]||{};
|
||||
nodeMap[node.oldLinks[i]].old = true;
|
||||
}
|
||||
if (i<node.links.length) {
|
||||
nodeMap[node.links[i]] = nodeMap[node.links[i]]||{};
|
||||
nodeMap[node.links[i]].new = true;
|
||||
}
|
||||
}
|
||||
var n;
|
||||
for (var id in nodeMap) {
|
||||
if (nodeMap.hasOwnProperty(id)) {
|
||||
n = RED.nodes.node(id);
|
||||
if (n) {
|
||||
if (nodeMap[id].old && !nodeMap[id].new) {
|
||||
// Removed id
|
||||
i = n.links.indexOf(node.id);
|
||||
if (i > -1) {
|
||||
n.links.splice(i,1);
|
||||
}
|
||||
} else if (!nodeMap[id].old && nodeMap[id].new) {
|
||||
// Added id
|
||||
i = n.links.indexOf(id);
|
||||
if (i === -1) {
|
||||
n.links.push(node.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function onAdd() {
|
||||
for (var i=0;i<this.links.length;i++) {
|
||||
var n = RED.nodes.node(this.links[i]);
|
||||
if (n.links.indexOf(this.id) === -1) {
|
||||
n.links.push(this.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RED.nodes.registerType('link in',{
|
||||
category: 'input',
|
||||
color:"#ddd",//"#87D8CF",
|
||||
defaults: {
|
||||
name: {value:""},
|
||||
links: { value: [] }
|
||||
},
|
||||
inputs:0,
|
||||
outputs:1,
|
||||
icon: "link-out.png",
|
||||
outputLabels: function(i) {
|
||||
return this.name||this._("link.linkIn");
|
||||
},
|
||||
label: function() {
|
||||
return this.name||this._("link.linkIn");
|
||||
},
|
||||
labelStyle: function() {
|
||||
return this.name?"node_label_italic":"";
|
||||
},
|
||||
oneditprepare: function() {
|
||||
onEditPrepare(this,"link out");
|
||||
},
|
||||
oneditsave: function() {
|
||||
onEditSave(this);
|
||||
},
|
||||
onadd: onAdd,
|
||||
oneditresize: resizeNodeList
|
||||
});
|
||||
|
||||
RED.nodes.registerType('link out',{
|
||||
category: 'output',
|
||||
color:"#ddd",//"#87D8CF",
|
||||
defaults: {
|
||||
name: {value:""},
|
||||
links: { value: []}
|
||||
},
|
||||
align:"right",
|
||||
inputs:1,
|
||||
outputs:0,
|
||||
icon: "link-out.png",
|
||||
inputLabels: function(i) {
|
||||
return this.name||this._("link.linkOut");
|
||||
},
|
||||
label: function() {
|
||||
return this.name||this._("link.linkOut");
|
||||
},
|
||||
labelStyle: function() {
|
||||
return this.name?"node_label_italic":"";
|
||||
},
|
||||
oneditprepare: function() {
|
||||
onEditPrepare(this,"link in");
|
||||
},
|
||||
oneditsave: function() {
|
||||
onEditSave(this);
|
||||
},
|
||||
onadd: onAdd,
|
||||
oneditresize: resizeNodeList
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
@@ -1,100 +0,0 @@
|
||||
/**
|
||||
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
module.exports = function(RED) {
|
||||
"use strict";
|
||||
var mustache = require("mustache");
|
||||
|
||||
/**
|
||||
* Custom Mustache Context capable to resolve message property and node
|
||||
* flow and global context
|
||||
*/
|
||||
function NodeContext(msg, nodeContext,parent) {
|
||||
this.msgContext = new mustache.Context(msg,parent);
|
||||
this.nodeContext = nodeContext;
|
||||
}
|
||||
|
||||
NodeContext.prototype = new mustache.Context();
|
||||
|
||||
NodeContext.prototype.lookup = function (name) {
|
||||
// try message first:
|
||||
try {
|
||||
var value = this.msgContext.lookup(name);
|
||||
if (value !== undefined) {
|
||||
return value;
|
||||
}
|
||||
|
||||
// try node context:
|
||||
var dot = name.indexOf(".");
|
||||
if (dot > 0) {
|
||||
var contextName = name.substr(0, dot);
|
||||
var variableName = name.substr(dot + 1);
|
||||
|
||||
if (contextName === "flow" && this.nodeContext.flow) {
|
||||
return this.nodeContext.flow.get(variableName);
|
||||
}
|
||||
else if (contextName === "global" && this.nodeContext.global) {
|
||||
return this.nodeContext.global.get(variableName);
|
||||
}
|
||||
}
|
||||
}catch(err) {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
NodeContext.prototype.push = function push (view) {
|
||||
return new NodeContext(view, this.nodeContext,this.msgContext);
|
||||
};
|
||||
|
||||
function TemplateNode(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
this.name = n.name;
|
||||
this.field = n.field || "payload";
|
||||
this.template = n.template;
|
||||
this.syntax = n.syntax || "mustache";
|
||||
this.fieldType = n.fieldType || "msg";
|
||||
this.outputFormat = n.output || "str";
|
||||
|
||||
var node = this;
|
||||
node.on("input", function(msg) {
|
||||
try {
|
||||
var value;
|
||||
if (node.syntax === "mustache") {
|
||||
value = mustache.render(node.template,new NodeContext(msg, node.context()));
|
||||
} else {
|
||||
value = node.template;
|
||||
}
|
||||
if (node.outputFormat === "json") {
|
||||
value = JSON.parse(value);
|
||||
}
|
||||
|
||||
if (node.fieldType === 'msg') {
|
||||
RED.util.setMessageProperty(msg,node.field,value);
|
||||
} else if (node.fieldType === 'flow') {
|
||||
node.context().flow.set(node.field,value);
|
||||
} else if (node.fieldType === 'global') {
|
||||
node.context().global.set(node.field,value);
|
||||
}
|
||||
node.send(msg);
|
||||
} catch(err) {
|
||||
node.error(err.message);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
RED.nodes.registerType("template",TemplateNode);
|
||||
RED.library.register("templates");
|
||||
}
|
||||
@@ -1,153 +0,0 @@
|
||||
/**
|
||||
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
module.exports = function(RED) {
|
||||
"use strict";
|
||||
var mustache = require("mustache");
|
||||
function TriggerNode(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
this.op1 = n.op1 || "1";
|
||||
this.op2 = n.op2 || "0";
|
||||
this.op1type = n.op1type || "str";
|
||||
this.op2type = n.op2type || "str";
|
||||
|
||||
if (this.op1type === 'val') {
|
||||
if (this.op1 === 'true' || this.op1 === 'false') {
|
||||
this.op1type = 'bool'
|
||||
} else if (this.op1 === 'null') {
|
||||
this.op1type = 'null';
|
||||
this.op1 = null;
|
||||
} else {
|
||||
this.op1type = 'str';
|
||||
}
|
||||
}
|
||||
if (this.op2type === 'val') {
|
||||
if (this.op2 === 'true' || this.op2 === 'false') {
|
||||
this.op2type = 'bool'
|
||||
} else if (this.op2 === 'null') {
|
||||
this.op2type = 'null';
|
||||
this.op2 = null;
|
||||
} else {
|
||||
this.op2type = 'str';
|
||||
}
|
||||
}
|
||||
this.extend = n.extend || "false";
|
||||
this.units = n.units || "ms";
|
||||
this.reset = n.reset || '';
|
||||
this.duration = n.duration || 250;
|
||||
if (this.duration < 0) {
|
||||
this.loop = true;
|
||||
this.duration = this.duration * -1;
|
||||
this.extend = false;
|
||||
}
|
||||
|
||||
if (this.units == "s") { this.duration = this.duration * 1000; }
|
||||
if (this.units == "min") { this.duration = this.duration * 1000 * 60; }
|
||||
if (this.units == "hr") { this.duration = this.duration * 1000 *60 * 60; }
|
||||
|
||||
this.op1Templated = (this.op1type === 'str' && this.op1.indexOf("{{") != -1);
|
||||
this.op2Templated = (this.op2type === 'str' && this.op2.indexOf("{{") != -1);
|
||||
if ((this.op1type === "num") && (!isNaN(this.op1))) { this.op1 = Number(this.op1); }
|
||||
if ((this.op2type === "num") && (!isNaN(this.op2))) { this.op2 = Number(this.op2); }
|
||||
if (this.op1 == "null") { this.op1 = null; }
|
||||
if (this.op2 == "null") { this.op2 = null; }
|
||||
//try { this.op1 = JSON.parse(this.op1); }
|
||||
//catch(e) { this.op1 = this.op1; }
|
||||
//try { this.op2 = JSON.parse(this.op2); }
|
||||
//catch(e) { this.op2 = this.op2; }
|
||||
|
||||
var node = this;
|
||||
var tout = null;
|
||||
var m2;
|
||||
this.on("input", function(msg) {
|
||||
if (msg.hasOwnProperty("reset") || ((node.reset !== '') && (msg.payload == node.reset)) ) {
|
||||
if (node.loop === true) { clearInterval(tout); }
|
||||
else { clearTimeout(tout); }
|
||||
tout = null;
|
||||
node.status({});
|
||||
}
|
||||
else {
|
||||
if (((!tout) && (tout !== 0)) || (node.loop === true)) {
|
||||
if (node.op2type === "pay" || node.op2type === "payl") { m2 = msg.payload; }
|
||||
else if (node.op2Templated) { m2 = mustache.render(node.op2,msg); }
|
||||
else if (node.op2type !== "nul") {
|
||||
m2 = RED.util.evaluateNodeProperty(node.op2,node.op2type,node,msg);
|
||||
}
|
||||
|
||||
if (node.op1type === "pay") { }
|
||||
else if (node.op1Templated) { msg.payload = mustache.render(node.op1,msg); }
|
||||
else if (node.op1type !== "nul") {
|
||||
msg.payload = RED.util.evaluateNodeProperty(node.op1,node.op1type,node,msg);
|
||||
}
|
||||
|
||||
if (node.op1type !== "nul") { node.send(msg); }
|
||||
|
||||
if (node.duration === 0) { tout = 0; }
|
||||
else if (node.loop === true) {
|
||||
if (tout) { clearInterval(tout); }
|
||||
if (node.op1type !== "nul") {
|
||||
var msg2 = RED.util.cloneMessage(msg);
|
||||
tout = setInterval(function() { node.send(msg2); },node.duration);
|
||||
}
|
||||
}
|
||||
else {
|
||||
tout = setTimeout(function() {
|
||||
if (node.op2type !== "nul") {
|
||||
var msg2 = RED.util.cloneMessage(msg);
|
||||
if (node.op2type === "flow" || node.op2type === "global") {
|
||||
m2 = RED.util.evaluateNodeProperty(node.op2,node.op2type,node,msg);
|
||||
}
|
||||
msg2.payload = m2;
|
||||
node.send(msg2);
|
||||
}
|
||||
tout = null;
|
||||
node.status({});
|
||||
},node.duration);
|
||||
}
|
||||
node.status({fill:"blue",shape:"dot",text:" "});
|
||||
}
|
||||
else if ((node.extend === "true" || node.extend === true) && (node.duration > 0)) {
|
||||
if (tout) { clearTimeout(tout); }
|
||||
if (node.op2type === "payl") { m2 = msg.payload; }
|
||||
tout = setTimeout(function() {
|
||||
if (node.op2type !== "nul") {
|
||||
var msg2 = RED.util.cloneMessage(msg);
|
||||
if (node.op2type === "flow" || node.op2type === "global") {
|
||||
m2 = RED.util.evaluateNodeProperty(node.op2,node.op2type,node,msg);
|
||||
}
|
||||
msg2.payload = m2;
|
||||
node.send(msg2);
|
||||
}
|
||||
tout = null;
|
||||
node.status({});
|
||||
},node.duration);
|
||||
}
|
||||
else {
|
||||
if (node.op2type === "payl") { m2 = msg.payload; }
|
||||
}
|
||||
}
|
||||
});
|
||||
this.on("close", function() {
|
||||
if (tout) {
|
||||
if (node.loop === true) { clearInterval(tout); }
|
||||
else { clearTimeout(tout); }
|
||||
tout = null;
|
||||
}
|
||||
node.status({});
|
||||
});
|
||||
}
|
||||
RED.nodes.registerType("trigger",TriggerNode);
|
||||
}
|
||||
@@ -1,646 +0,0 @@
|
||||
|
||||
<script type="text/x-red" data-template-name="rpi-gpio in">
|
||||
<style>
|
||||
.pinTable {
|
||||
width: 300px;
|
||||
display: inline-table;
|
||||
font-size: 13px;
|
||||
height: 380px;
|
||||
min-height: 380px;
|
||||
max-height: 380px;
|
||||
}
|
||||
.pinTableBody {
|
||||
width: 300px;
|
||||
display: table-row-group;
|
||||
line-height: 12px;
|
||||
}
|
||||
.pinTableRow {
|
||||
width: 300;
|
||||
display: table-row;
|
||||
height: 14px;
|
||||
}
|
||||
.pinTableCellL {
|
||||
width: 150px;
|
||||
display: table-cell;
|
||||
text-align: right;
|
||||
padding-right: 4px;
|
||||
vertical-align: top;
|
||||
border: 1px solid #444;
|
||||
}
|
||||
.pinTableCellR {
|
||||
width: 150px;
|
||||
display: table-cell;
|
||||
text-align: left;
|
||||
padding-left: 4px;
|
||||
vertical-align: top;
|
||||
border: 1px solid #000;
|
||||
}
|
||||
.pinColorPower {
|
||||
background-color:#FECBCE;
|
||||
}
|
||||
.pinColorGround {
|
||||
background-color:#DDDDDD;
|
||||
}
|
||||
.pinColorGPIO {
|
||||
background-color:#BFEBBF;
|
||||
}
|
||||
.pinColorDual {
|
||||
background-color:#D0E6F4;
|
||||
}
|
||||
.pinColorSD {
|
||||
background-color:#FFFDD0;
|
||||
}
|
||||
</style>
|
||||
<div class="form-row">
|
||||
<label><i class="fa fa-circle"></i> <span data-i18n="rpi-gpio.pinname"></span></label>
|
||||
<input type="text" id="node-input-pin" style="display:none;">
|
||||
<div class="pinTable">
|
||||
<div class="pinTableBody"><form id="pinform" style="height:380px; max-height:380px; margin:initial;">
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorPower">3.3V Power - 1 <input disabled type="radio" name="pins" value="" style="width:auto;"></div>
|
||||
<div class="pinTableCellR pinColorPower"><input disabled type="radio" name="pins" value="" style="width:auto;"> 2 - 5V Power</div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorDual">SDA1 - GPIO02 - 3 <input type="radio" name="pins" value="3" style="width:auto;"></div>
|
||||
<div class="pinTableCellR pinColorPower"><input disabled type="radio" name="pins" value="" style="width:auto;"> 4 - 5V Power</div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorDual">SCL1 - GPIO03 - 5 <input type="radio" name="pins" value="5" style="width:auto;"></div>
|
||||
<div class="pinTableCellR pinColorGround"><input disabled type="radio" name="pins" value="" style="width:auto;"> 6 - Ground</div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorGPIO">GPIO04 - 7 <input type="radio" name="pins" value="7" style="width:auto;"></div>
|
||||
<div class="pinTableCellR pinColorDual"><input type="radio" name="pins" value="8" style="width:auto;"> 8 - GPIO14 - TxD</div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorGround">Ground - 9 <input disabled type="radio" name="pins" value="" style="width:auto;"></div>
|
||||
<div class="pinTableCellR pinColorDual"><input type="radio" name="pins" value="10" style="width:auto;"> 10 - GPIO15 - RxD</div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorGPIO">GPIO17 - 11 <input type="radio" name="pins" value="11" style="width:auto;"></div>
|
||||
<div class="pinTableCellR pinColorGPIO"><input type="radio" name="pins" value="12" style="width:auto;"> 12 - GPIO18</div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorGPIO">GPIO27 - 13 <input type="radio" name="pins" value="12" style="width:auto;"></div>
|
||||
<div class="pinTableCellR pinColorGround"><input disabled type="radio" name="pins" value="" style="width:auto;"> 14 - Ground</div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorGPIO">GPIO22 - 15 <input type="radio" name="pins" value="15" style="width:auto;"></div>
|
||||
<div class="pinTableCellR pinColorGPIO"><input type="radio" name="pins" value="16" style="width:auto;"> 16 - GPIO23</div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorPower">3.3V Power - 17 <input disabled type="radio" name="pins" value="" style="width:auto;"></div>
|
||||
<div class="pinTableCellR pinColorGPIO"><input type="radio" name="pins" value="18" style="width:auto;"> 18 - GPIO24</div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorDual">MOSI - GPIO10 - 19 <input type="radio" name="pins" value="19" style="width:auto;"></div>
|
||||
<div class="pinTableCellR pinColorGround"><input disabled type="radio" name="pins" value="" style="width:auto;"> 20 - Ground</div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorDual">MISO - GPIO09 - 21 <input type="radio" name="pins" value="21" style="width:auto;"></div>
|
||||
<div class="pinTableCellR pinColorGPIO"><input type="radio" name="pins" value="22" style="width:auto;"> 22 - GPIO25</div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorDual">SCLK - GPIO11 - 23 <input type="radio" name="pins" value="23" style="width:auto;"></div>
|
||||
<div class="pinTableCellR pinColorDual"><input type="radio" name="pins" value="24" style="width:auto;"> 24 - GPIO8 - CE0</div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorGround">Ground - 25 <input disabled type="radio" name="pins" value="" style="width:auto;"></div>
|
||||
<div class="pinTableCellR pinColorDual"><input type="radio" name="pins" value="26" style="width:auto;"> 26 - GPIO7 - CE1</div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorSD">SD - 27 <input disabled type="radio" name="pins" value="" style="width:auto;"></div>
|
||||
<div class="pinTableCellR pinColorSD"><input disabled type="radio" name="pins" value="" style="width:auto;"> 28 - SC</div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorGPIO">GPIO05 - 29 <input type="radio" name="pins" value="29" style="width:auto;"></div>
|
||||
<div class="pinTableCellR pinColorGround"><input disabled type="radio" name="pins" value="" style="width:auto;"> 30 - Ground</div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorGPIO">GPIO06 - 31 <input type="radio" name="pins" value="31" style="width:auto;"></div>
|
||||
<div class="pinTableCellR pinColorGPIO"><input type="radio" name="pins" value="32" style="width:auto;"> 32 - GPIO12</div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorGPIO">GPIO13 - 33 <input type="radio" name="pins" value="33" style="width:auto;"></div>
|
||||
<div class="pinTableCellR pinColorGround"><input disabled type="radio" name="pins" value="" style="width:auto;"> 34 - Ground</div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorGPIO">GPIO19 - 35 <input type="radio" name="pins" value="35" style="width:auto;"></div>
|
||||
<div class="pinTableCellR pinColorGPIO"><input type="radio" name="pins" value="36" style="width:auto;"> 36 - GPIO16</div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorGPIO">GPIO26 - 37 <input type="radio" name="pins" value="37" style="width:auto;"></div>
|
||||
<div class="pinTableCellR pinColorGPIO"><input type="radio" name="pins" value="38" style="width:auto;"> 38 - GPIO20</div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorGround">Ground - 39 <input disabled type="radio" name="pins" value="" style="width:auto;"></div>
|
||||
<div class="pinTableCellR pinColorGPIO"><input type="radio" name="pins" value="40" style="width:auto;"> 40 - GPIO21</div>
|
||||
</div>
|
||||
</form></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-intype"><i class="fa fa-level-up"></i> <span data-i18n="rpi-gpio.label.resistor"></span></label>
|
||||
<select type="text" id="node-input-intype" style="width:100px;">
|
||||
<option value="tri" data-i18n="rpi-gpio.resistor.none"></option>
|
||||
<option value="up" data-i18n="rpi-gpio.resistor.pullup"></option>
|
||||
<option value="down" data-i18n="rpi-gpio.resistor.pulldown"></option>
|
||||
</select>
|
||||
<span data-i18n="rpi-gpio.label.debounce"></span>
|
||||
<input type="text" id="node-input-debounce" style="width:47px; text-align:right"/> mS
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label> </label>
|
||||
<input type="checkbox" id="node-input-read" style="display: inline-block; width: auto; vertical-align: top;">
|
||||
<label for="node-input-read" style="width:70%;"><span data-i18n="rpi-gpio.label.readinitial"></span></label>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
|
||||
<input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
|
||||
</div>
|
||||
<div class="form-tips" id="pin-tip"><span data-i18n="[html]rpi-gpio.tip.pin"></span></div>
|
||||
<div class="form-tips"><span data-i18n="[html]rpi-gpio.tip.in"></span></div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="rpi-gpio in">
|
||||
<p>Raspberry Pi input node. Generates a <code>msg.payload</code> with either a
|
||||
0 or 1 depending on the state of the input pin.</p>
|
||||
<h3>Outputs</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>payload <span class="property-type">number</span></dt>
|
||||
<dd>the payload will be a 1 or a 0.</dd>
|
||||
<dt>topic <span class="property-type">string</span></dt>
|
||||
<dd>the topic will be set to `pi/{the pin number}`.</dd>
|
||||
</dl>
|
||||
<h3>Details</h3>
|
||||
<p>You may also enable the input pullup resistor or the pulldown resistor.</p>
|
||||
<p>Requires the RPi.GPIO python library version 0.5.10 (or better) in order to work.</p>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
var bcm2pin = {
|
||||
"2":"3", "3":"5", "4":"7", "14":"8", "15":"10", "17":"11", "18":"12", "27":"13", "22":"15",
|
||||
"23":"16", "24":"18", "10":"19", "9":"21", "25":"22", "11":"23", "8":"24", "7":"26",
|
||||
"5":"29", "6":"31", "12":"32", "13":"33", "19":"35", "16":"36", "26":"37", "20":"38", "21":"40"
|
||||
};
|
||||
var pinsInUse = {};
|
||||
RED.nodes.registerType('rpi-gpio in',{
|
||||
category: 'Raspberry Pi',
|
||||
color:"#c6dbef",
|
||||
defaults: {
|
||||
name: { value:"" },
|
||||
pin: { value:"tri",required:true,validate:RED.validators.number() },
|
||||
intype: { value:"tri" },
|
||||
debounce: { value:"25" },
|
||||
read: { value:false }
|
||||
},
|
||||
inputs:0,
|
||||
outputs:1,
|
||||
icon: "rpi.png",
|
||||
info: function() {
|
||||
if ( Object.keys(pinsInUse).length !== 0 ) {
|
||||
return "**Pins in use** : "+Object.keys(pinsInUse);
|
||||
}
|
||||
else { return ""; }
|
||||
},
|
||||
label: function() {
|
||||
var suf = "";
|
||||
if (this.intype === "up") { suf = "↑ "}
|
||||
if (this.intype === "down") { suf = "↓ "}
|
||||
return this.name || "PIN: "+suf+bcm2pin[this.pin] ;
|
||||
},
|
||||
labelStyle: function() {
|
||||
return this.name?"node_label_italic":"";
|
||||
},
|
||||
outputLabels: function() { return "GPIO"+this.pin; },
|
||||
oneditprepare: function() {
|
||||
var pinnow = this.pin;
|
||||
var pintip = this._("rpi-gpio.tip.pin");
|
||||
var pinname = this._("rpi-gpio.pinname");
|
||||
var alreadyuse = this._("rpi-gpio.alreadyuse");
|
||||
var alreadyset = this._("rpi-gpio.alreadyset");
|
||||
|
||||
$.getJSON('rpi-pins/'+this.id,function(data) {
|
||||
pinsInUse = data || {};
|
||||
$('#pin-tip').html(pintip + Object.keys(data));
|
||||
});
|
||||
$("#node-input-pin").change(function() {
|
||||
if ($("#node-input-pin").val()) {
|
||||
$("#pinform input[value="+$("#node-input-pin").val()+"]").prop('checked', true);
|
||||
}
|
||||
var pinnew = $("#node-input-pin").val();
|
||||
if ((pinnew) && (pinnew !== pinnow)) {
|
||||
if (pinsInUse.hasOwnProperty(pinnew)) {
|
||||
RED.notify(pinname+" "+pinnew+" "+alreadyuse,"warn");
|
||||
}
|
||||
pinnow = pinnew;
|
||||
}
|
||||
});
|
||||
$("#node-input-intype").change(function() {
|
||||
var newtype = $("#node-input-intype").val();
|
||||
if ((pinsInUse.hasOwnProperty(pinnow)) && (pinsInUse[pinnow] !== newtype)) {
|
||||
RED.notify(pinname+" "+pinnow+" "+alreadyset+" "+pinsInUse[pinnow],"error");
|
||||
}
|
||||
});
|
||||
$('#pinform input').on('change', function() {
|
||||
this.pin = $("#pinform input[type='radio']:checked").val();
|
||||
$("#node-input-pin").val(this.pin);
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-template-name="rpi-gpio out">
|
||||
<style>
|
||||
.pinTable {
|
||||
width: 300px;
|
||||
display: inline-table;
|
||||
font-size: 13px;
|
||||
height: 380px;
|
||||
min-height: 380px;
|
||||
max-height: 380px;
|
||||
}
|
||||
.pinTableBody {
|
||||
width: 300px;
|
||||
display: table-row-group;
|
||||
line-height: 12px;
|
||||
}
|
||||
.pinTableRow {
|
||||
width: 300;
|
||||
display: table-row;
|
||||
height: 14px;
|
||||
}
|
||||
.pinTableCellL {
|
||||
width: 150px;
|
||||
display: table-cell;
|
||||
text-align: right;
|
||||
padding-right: 4px;
|
||||
vertical-align: top;
|
||||
border: 1px solid #444;
|
||||
}
|
||||
.pinTableCellR {
|
||||
width: 150px;
|
||||
display: table-cell;
|
||||
text-align: left;
|
||||
padding-left: 4px;
|
||||
vertical-align: top;
|
||||
border: 1px solid #000;
|
||||
}
|
||||
.pinColorPower {
|
||||
background-color:#FECBCE;
|
||||
}
|
||||
.pinColorGround {
|
||||
background-color:#DDDDDD;
|
||||
}
|
||||
.pinColorGPIO {
|
||||
background-color:#BFEBBF;
|
||||
}
|
||||
.pinColorDual {
|
||||
background-color:#D0E6F4;
|
||||
}
|
||||
.pinColorSD {
|
||||
background-color:#FFFDD0;
|
||||
}
|
||||
</style>
|
||||
<div class="form-row">
|
||||
<label><i class="fa fa-circle"></i> <span data-i18n="rpi-gpio.pinname"></span></label>
|
||||
<input type="text" id="node-input-pin" style="display:none;">
|
||||
<div class="pinTable">
|
||||
<div class="pinTableBody"><form id="pinform" style="height:380px; max-height:380px; margin:initial;">
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorPower">3.3V Power - 1 <input disabled type="radio" name="pins" value="" style="width:auto;"></div>
|
||||
<div class="pinTableCellR pinColorPower"><input disabled type="radio" name="pins" value="" style="width:auto;"> 2 - 5V Power</div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorDual">SDA1 - GPIO02 - 3 <input type="radio" name="pins" value="3" style="width:auto;"></div>
|
||||
<div class="pinTableCellR pinColorPower"><input disabled type="radio" name="pins" value="" style="width:auto;"> 4 - 5V Power</div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorDual">SCL1 - GPIO03 - 5 <input type="radio" name="pins" value="5" style="width:auto;"></div>
|
||||
<div class="pinTableCellR pinColorGround"><input disabled type="radio" name="pins" value="" style="width:auto;"> 6 - Ground</div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorGPIO">GPIO04 - 7 <input type="radio" name="pins" value="7" style="width:auto;"></div>
|
||||
<div class="pinTableCellR pinColorDual"><input type="radio" name="pins" value="8" style="width:auto;"> 8 - GPIO14 - TxD</div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorGround">Ground - 9 <input disabled type="radio" name="pins" value="" style="width:auto;"></div>
|
||||
<div class="pinTableCellR pinColorDual"><input type="radio" name="pins" value="10" style="width:auto;"> 10 - GPIO15 - RxD</div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorGPIO">GPIO17 - 11 <input type="radio" name="pins" value="11" style="width:auto;"></div>
|
||||
<div class="pinTableCellR pinColorGPIO"><input type="radio" name="pins" value="12" style="width:auto;"> 12 - GPIO18</div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorGPIO">GPIO27 - 13 <input type="radio" name="pins" value="12" style="width:auto;"></div>
|
||||
<div class="pinTableCellR pinColorGround"><input disabled type="radio" name="pins" value="" style="width:auto;"> 14 - Ground</div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorGPIO">GPIO22 - 15 <input type="radio" name="pins" value="15" style="width:auto;"></div>
|
||||
<div class="pinTableCellR pinColorGPIO"><input type="radio" name="pins" value="16" style="width:auto;"> 16 - GPIO23</div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorPower">3.3V Power - 17 <input disabled type="radio" name="pins" value="" style="width:auto;"></div>
|
||||
<div class="pinTableCellR pinColorGPIO"><input type="radio" name="pins" value="18" style="width:auto;"> 18 - GPIO24</div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorDual">MOSI - GPIO10 - 19 <input type="radio" name="pins" value="19" style="width:auto;"></div>
|
||||
<div class="pinTableCellR pinColorGround"><input disabled type="radio" name="pins" value="" style="width:auto;"> 20 - Ground</div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorDual">MISO - GPIO09 - 21 <input type="radio" name="pins" value="21" style="width:auto;"></div>
|
||||
<div class="pinTableCellR pinColorGPIO"><input type="radio" name="pins" value="22" style="width:auto;"> 22 - GPIO25</div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorDual">SCLK - GPIO11 - 23 <input type="radio" name="pins" value="23" style="width:auto;"></div>
|
||||
<div class="pinTableCellR pinColorDual"><input type="radio" name="pins" value="24" style="width:auto;"> 24 - GPIO8 - CE0</div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorGround">Ground - 25 <input disabled type="radio" name="pins" value="" style="width:auto;"></div>
|
||||
<div class="pinTableCellR pinColorDual"><input type="radio" name="pins" value="26" style="width:auto;"> 26 - GPIO7 - CE1</div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorSD">SD - 27 <input disabled type="radio" name="pins" value="" style="width:auto;"></div>
|
||||
<div class="pinTableCellR pinColorSD"><input disabled type="radio" name="pins" value="" style="width:auto;"> 28 - SC</div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorGPIO">GPIO05 - 29 <input type="radio" name="pins" value="29" style="width:auto;"></div>
|
||||
<div class="pinTableCellR pinColorGround"><input disabled type="radio" name="pins" value="" style="width:auto;"> 30 - Ground</div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorGPIO">GPIO06 - 31 <input type="radio" name="pins" value="31" style="width:auto;"></div>
|
||||
<div class="pinTableCellR pinColorGPIO"><input type="radio" name="pins" value="32" style="width:auto;"> 32 - GPIO12</div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorGPIO">GPIO13 - 33 <input type="radio" name="pins" value="33" style="width:auto;"></div>
|
||||
<div class="pinTableCellR pinColorGround"><input disabled type="radio" name="pins" value="" style="width:auto;"> 34 - Ground</div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorGPIO">GPIO19 - 35 <input type="radio" name="pins" value="35" style="width:auto;"></div>
|
||||
<div class="pinTableCellR pinColorGPIO"><input type="radio" name="pins" value="36" style="width:auto;"> 36 - GPIO16</div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorGPIO">GPIO26 - 37 <input type="radio" name="pins" value="37" style="width:auto;"></div>
|
||||
<div class="pinTableCellR pinColorGPIO"><input type="radio" name="pins" value="38" style="width:auto;"> 38 - GPIO20</div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorGround">Ground - 39 <input disabled type="radio" name="pins" value="" style="width:auto;"></div>
|
||||
<div class="pinTableCellR pinColorGPIO"><input type="radio" name="pins" value="40" style="width:auto;"> 40 - GPIO21</div>
|
||||
</div>
|
||||
</form></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row" id="node-set-pwm">
|
||||
<label> <span data-i18n="rpi-gpio.label.type"></span></label>
|
||||
<select id="node-input-out" style="width: 250px;">
|
||||
<option value="out" data-i18n="rpi-gpio.digout"></option>
|
||||
<option value="pwm" data-i18n="rpi-gpio.pwmout"></option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-row" id="node-set-tick">
|
||||
<label> </label>
|
||||
<input type="checkbox" id="node-input-set" style="display: inline-block; width: auto; vertical-align: top;">
|
||||
<label for="node-input-set" style="width: 70%;"><span data-i18n="rpi-gpio.label.initpin"></span></label>
|
||||
</div>
|
||||
<div class="form-row" id="node-set-state">
|
||||
<label for="node-input-level"> </label>
|
||||
<select id="node-input-level" style="width: 250px;">
|
||||
<option value="0" data-i18n="rpi-gpio.initpin0"></option>
|
||||
<option value="1" data-i18n="rpi-gpio.initpin1"></option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-row" id="node-set-freq">
|
||||
<label for="node-input-freq"> <span data-i18n="rpi-gpio.label.freq"></span></label>
|
||||
<input type="text" id="node-input-freq" placeholder="100"> Hz
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
|
||||
<input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
|
||||
</div>
|
||||
<div class="form-tips" id="pin-tip"><span data-i18n="[html]rpi-gpio.tip.pin"></span></div>
|
||||
<div class="form-tips" id="dig-tip"><span data-i18n="[html]rpi-gpio.tip.dig"></span></div>
|
||||
<div class="form-tips" id="pwm-tip"><span data-i18n="[html]rpi-gpio.tip.pwm"></span></div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="rpi-gpio out">
|
||||
<p>Raspberry Pi output node. Can be used in Digital or PWM modes.
|
||||
<h3>Inputs</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>payload <span class="property-type">number | string | boolean</span></dt>
|
||||
</dl>
|
||||
<h3>Details</h3>
|
||||
<p>Digital mode - expects a <code>msg.payload</code> with either a 0 or 1 (or true or false),
|
||||
and will set the selected physical pin high or low depending on the value passed in.</p>
|
||||
<p>The initial value of the pin at deploy time can also be set to 0 or 1.</p>
|
||||
<p>PWM mode - expects an input value of a number 0 - 100. It can be floating point.</p>
|
||||
<p>PWM mode can be used to drive a servo using input values between 10 and 20 only,
|
||||
but will accept floating point values.
|
||||
The GPIO2 pin is best for this as it uses hardware to do the PWM. For better servo support
|
||||
consider the alternative node-red-node-pi-gpiod node.</p>
|
||||
<p>Requires the RPi.GPIO python library version 0.5.10 (or better) in order to work.</p>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
var bcm2pin = {
|
||||
"2":"3", "3":"5", "4":"7", "14":"8", "15":"10", "17":"11", "18":"12", "27":"13", "22":"15",
|
||||
"23":"16", "24":"18", "10":"19", "9":"21", "25":"22", "11":"23", "8":"24", "7":"26",
|
||||
"5":"29", "6":"31", "12":"32", "13":"33", "19":"35", "16":"36", "26":"37", "20":"38", "21":"40"
|
||||
};
|
||||
var pinsInUse = {};
|
||||
RED.nodes.registerType('rpi-gpio out',{
|
||||
category: 'Raspberry Pi',
|
||||
color:"#c6dbef",
|
||||
defaults: {
|
||||
name: { value:"" },
|
||||
pin: { value:"",required:true,validate:RED.validators.number() },
|
||||
set: { value:"" },
|
||||
level: { value:"0" },
|
||||
freq: {value:""},
|
||||
out: { value:"out" }
|
||||
},
|
||||
inputs:1,
|
||||
outputs:0,
|
||||
icon: "rpi.png",
|
||||
info: function() {
|
||||
if ( Object.keys(pinsInUse).length !== 0 ) {
|
||||
return "**Pins in use** : "+Object.keys(pinsInUse);
|
||||
}
|
||||
else { return ""; }
|
||||
},
|
||||
align: "right",
|
||||
label: function() {
|
||||
if (this.out === "pwm") { return this.name || "PWM: "+bcm2pin[this.pin]; }
|
||||
else if (this.out === "ser") { return this.name || "Servo: "+bcm2pin[this.pin]; }
|
||||
else {
|
||||
var suf = "";
|
||||
if (this.set == true) { suf = (this.level === "1") ? " ¹" : " ₀"; }
|
||||
return this.name||"PIN: "+ bcm2pin[this.pin] + suf ;
|
||||
}
|
||||
},
|
||||
labelStyle: function() {
|
||||
return this.name?"node_label_italic":"";
|
||||
},
|
||||
inputLabels: function() { return "GPIO"+this.pin; },
|
||||
oneditprepare: function() {
|
||||
var pinnow = this.pin;
|
||||
var pintip = this._("rpi-gpio.tip.pin");
|
||||
var pinname = this._("rpi-gpio.pinname");
|
||||
var alreadyuse = this._("rpi-gpio.alreadyuse");
|
||||
var alreadyset = this._("rpi-gpio.alreadyset");
|
||||
if (!$("#node-input-out").val()) { $("#node-input-out").val("out"); }
|
||||
|
||||
$.getJSON('rpi-pins/'+this.id,function(data) {
|
||||
pinsInUse = data || {};
|
||||
$('#pin-tip').html(pintip + Object.keys(data));
|
||||
});
|
||||
|
||||
$("#node-input-pin").change(function() {
|
||||
if ($("#node-input-pin").val()) {
|
||||
$("#pinform input[value="+$("#node-input-pin").val()+"]").prop('checked', true);
|
||||
}
|
||||
var pinnew = $("#node-input-pin").val();
|
||||
if ((pinnew) && (pinnew !== pinnow)) {
|
||||
if (pinsInUse.hasOwnProperty(pinnew)) {
|
||||
RED.notify(pinname+" "+pinnew+" "+alreadyuse,"warn");
|
||||
}
|
||||
pinnow = pinnew;
|
||||
}
|
||||
});
|
||||
|
||||
$("#node-input-out").change(function() {
|
||||
var newtype = $("#node-input-out").val();
|
||||
if ((pinsInUse.hasOwnProperty(pinnow)) && (pinsInUse[pinnow] !== newtype)) {
|
||||
RED.notify(pinname+" "+pinnow+" "+alreadyset+" "+pinsInUse[pinnow],"error");
|
||||
}
|
||||
});
|
||||
|
||||
var hidestate = function () {
|
||||
if ($("#node-input-out").val() === "pwm") {
|
||||
$('#node-set-tick').hide();
|
||||
$('#node-set-state').hide();
|
||||
$('#node-input-set').prop('checked', false);
|
||||
$("#dig-tip").hide();
|
||||
$("#pwm-tip").show();
|
||||
$('#node-set-freq').show();
|
||||
}
|
||||
else {
|
||||
$('#node-set-tick').show();
|
||||
$("#dig-tip").show();
|
||||
$("#pwm-tip").hide();
|
||||
$('#node-set-freq').hide();
|
||||
}
|
||||
};
|
||||
$("#node-input-out").change(function () { hidestate(); });
|
||||
hidestate();
|
||||
|
||||
var setstate = function () {
|
||||
if ($('#node-input-set').is(":checked")) {
|
||||
$("#node-set-state").show();
|
||||
} else {
|
||||
$("#node-set-state").hide();
|
||||
}
|
||||
};
|
||||
$("#node-input-set").change(function () { setstate(); });
|
||||
setstate();
|
||||
|
||||
$('#pinform input').on('change', function() {
|
||||
this.pin = $("#pinform input[type='radio']:checked").val();
|
||||
$("#node-input-pin").val(this.pin);
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-template-name="rpi-mouse">
|
||||
<div class="form-row">
|
||||
<label for="node-input-butt"><i class="fa fa-circle"></i> <span data-i18n="rpi-gpio.label.button"></span></label>
|
||||
<select type="text" id="node-input-butt" style="width: 250px;">
|
||||
<option value="1" data-i18n="rpi-gpio.left"></option>
|
||||
<option value="2" data-i18n="rpi-gpio.right"></option>
|
||||
<option value="4" data-i18n="rpi-gpio.middle"></option>
|
||||
<option value="7" data-i18n="rpi-gpio.any"></option>
|
||||
</select>
|
||||
</div>
|
||||
<br/>
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
|
||||
<input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="rpi-mouse">
|
||||
<p>Raspberry Pi mouse button node. Requires a USB mouse.</p>
|
||||
<h3>Outputs</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>payload <span class="property-type">number</span></dt>
|
||||
<dd>1 or 0 when the selected mouse button is pressed and released.</dd>
|
||||
<dt>button <span class="property-type">number</span></dt>
|
||||
<dd>1, 2, 4 corresponding to left, right and middle buttons, so you
|
||||
can work out which button or combination was pressed.</dd>
|
||||
<dt>topic <span class="property-type">string</span></dt>
|
||||
<dd>set to <code>pi/mouse</code></dd>
|
||||
</dl>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('rpi-mouse',{
|
||||
category: 'Raspberry Pi',
|
||||
color:"#c6dbef",
|
||||
defaults: {
|
||||
name: { value:"" },
|
||||
butt: { value:"1",required:true }
|
||||
},
|
||||
inputs:0,
|
||||
outputs:1,
|
||||
icon: "rpi.png",
|
||||
label: function() {
|
||||
var na = this._("rpi-gpio.label.pimouse");
|
||||
if (this.butt === "1") { na += " "+this._("rpi-gpio.label.left"); }
|
||||
if (this.butt === "2") { na += " "+this._("rpi-gpio.label.right"); }
|
||||
if (this.butt === "4") { na += " "+this._("rpi-gpio.label.middle"); }
|
||||
return this.name||na;
|
||||
},
|
||||
labelStyle: function() {
|
||||
return this.name?"node_label_italic":"";
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-template-name="rpi-keyboard">
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
|
||||
<input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="rpi-keyboard">
|
||||
<p>Raspberry Pi keyboard handling node. Requires a USB keyboard.</p>
|
||||
<h3>Outputs</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>payload <span class="property-type">number</span></dt>
|
||||
<dd>contains the keycode value</dd>
|
||||
<dt>action <span class="property-type">string</span></dt>
|
||||
<dd>set to "up", "down", or "repeat"</dd>
|
||||
<dt>topic <span class="property-type">string</span></dt>
|
||||
<dd>set to <code>pi/key</code></dd>
|
||||
</dl>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('rpi-keyboard',{
|
||||
category: 'Raspberry Pi',
|
||||
color:"#c6dbef",
|
||||
defaults: {
|
||||
name: { value:"" }
|
||||
},
|
||||
inputs:0,
|
||||
outputs:1,
|
||||
icon: "rpi.png",
|
||||
label: function() {
|
||||
return this.name || this._("rpi-gpio.label.pikeyboard");
|
||||
},
|
||||
labelStyle: function() {
|
||||
return this.name?"node_label_italic":"";
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@@ -1,332 +0,0 @@
|
||||
|
||||
module.exports = function(RED) {
|
||||
"use strict";
|
||||
var exec = require('child_process').exec;
|
||||
var spawn = require('child_process').spawn;
|
||||
var fs = require('fs');
|
||||
|
||||
var gpioCommand = __dirname+'/nrgpio';
|
||||
|
||||
try {
|
||||
var cpuinfo = fs.readFileSync("/proc/cpuinfo").toString();
|
||||
if (cpuinfo.indexOf(": BCM") === -1) { throw "Info : "+RED._("rpi-gpio.errors.ignorenode"); }
|
||||
} catch(err) {
|
||||
throw "Info : "+RED._("rpi-gpio.errors.ignorenode");
|
||||
}
|
||||
|
||||
try {
|
||||
fs.statSync("/usr/share/doc/python-rpi.gpio"); // test on Raspbian
|
||||
// /usr/lib/python2.7/dist-packages/RPi/GPIO
|
||||
} catch(err) {
|
||||
try {
|
||||
fs.statSync("/usr/lib/python2.7/site-packages/RPi/GPIO"); // test on Arch
|
||||
}
|
||||
catch(err) {
|
||||
try {
|
||||
fs.statSync("/usr/lib/python2.7/dist-packages/RPi/GPIO"); // test on Hypriot
|
||||
}
|
||||
catch(err) {
|
||||
RED.log.warn(RED._("rpi-gpio.errors.libnotfound"));
|
||||
throw "Warning : "+RED._("rpi-gpio.errors.libnotfound");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( !(1 & parseInt((fs.statSync(gpioCommand).mode & parseInt("777", 8)).toString(8)[0]) )) {
|
||||
RED.log.error(RED._("rpi-gpio.errors.needtobeexecutable",{command:gpioCommand}));
|
||||
throw "Error : "+RED._("rpi-gpio.errors.mustbeexecutable");
|
||||
}
|
||||
|
||||
// the magic to make python print stuff immediately
|
||||
process.env.PYTHONUNBUFFERED = 1;
|
||||
|
||||
var pinsInUse = {};
|
||||
var pinTypes = {"out":RED._("rpi-gpio.types.digout"), "tri":RED._("rpi-gpio.types.input"), "up":RED._("rpi-gpio.types.pullup"), "down":RED._("rpi-gpio.types.pulldown"), "pwm":RED._("rpi-gpio.types.pwmout")};
|
||||
|
||||
function GPIOInNode(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
this.buttonState = -1;
|
||||
this.pin = n.pin;
|
||||
this.intype = n.intype;
|
||||
this.read = n.read || false;
|
||||
this.debounce = Number(n.debounce || 25);
|
||||
if (this.read) { this.buttonState = -2; }
|
||||
var node = this;
|
||||
if (!pinsInUse.hasOwnProperty(this.pin)) {
|
||||
pinsInUse[this.pin] = this.intype;
|
||||
}
|
||||
else {
|
||||
if ((pinsInUse[this.pin] !== this.intype)||(pinsInUse[this.pin] === "pwm")) {
|
||||
node.warn(RED._("rpi-gpio.errors.alreadyset",{pin:this.pin,type:pinTypes[pinsInUse[this.pin]]}));
|
||||
}
|
||||
}
|
||||
|
||||
if (node.pin !== undefined) {
|
||||
node.child = spawn(gpioCommand, ["in",node.pin,node.intype,node.debounce]);
|
||||
node.running = true;
|
||||
node.status({fill:"green",shape:"dot",text:"common.status.ok"});
|
||||
|
||||
node.child.stdout.on('data', function (data) {
|
||||
var d = data.toString().trim().split("\n");
|
||||
for (var i = 0; i < d.length; i++) {
|
||||
if (d[i] === '') { return; }
|
||||
if (node.running && node.buttonState !== -1 && !isNaN(Number(d[i])) && node.buttonState !== d[i]) {
|
||||
node.send({ topic:"pi/"+node.pin, payload:Number(d[i]) });
|
||||
}
|
||||
node.buttonState = d[i];
|
||||
node.status({fill:"green",shape:"dot",text:d[i]});
|
||||
if (RED.settings.verbose) { node.log("out: "+d[i]+" :"); }
|
||||
}
|
||||
});
|
||||
|
||||
node.child.stderr.on('data', function (data) {
|
||||
if (RED.settings.verbose) { node.log("err: "+data+" :"); }
|
||||
});
|
||||
|
||||
node.child.on('close', function (code) {
|
||||
node.running = false;
|
||||
node.child = null;
|
||||
if (RED.settings.verbose) { node.log(RED._("rpi-gpio.status.closed")); }
|
||||
if (node.done) {
|
||||
node.status({fill:"grey",shape:"ring",text:"rpi-gpio.status.closed"});
|
||||
node.done();
|
||||
}
|
||||
else { node.status({fill:"red",shape:"ring",text:"rpi-gpio.status.stopped"}); }
|
||||
});
|
||||
|
||||
node.child.on('error', function (err) {
|
||||
if (err.errno === "ENOENT") { node.error(RED._("rpi-gpio.errors.commandnotfound")); }
|
||||
else if (err.errno === "EACCES") { node.error(RED._("rpi-gpio.errors.commandnotexecutable")); }
|
||||
else { node.error(RED._("rpi-gpio.errors.error",{error:err.errno})) }
|
||||
});
|
||||
|
||||
}
|
||||
else {
|
||||
node.warn(RED._("rpi-gpio.errors.invalidpin")+": "+node.pin);
|
||||
}
|
||||
|
||||
node.on("close", function(done) {
|
||||
node.status({fill:"grey",shape:"ring",text:"rpi-gpio.status.closed"});
|
||||
delete pinsInUse[node.pin];
|
||||
if (node.child != null) {
|
||||
node.done = done;
|
||||
node.child.stdin.write("close "+node.pin);
|
||||
node.child.kill('SIGKILL');
|
||||
}
|
||||
else { done(); }
|
||||
});
|
||||
}
|
||||
RED.nodes.registerType("rpi-gpio in",GPIOInNode);
|
||||
|
||||
function GPIOOutNode(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
this.pin = n.pin;
|
||||
this.set = n.set || false;
|
||||
this.level = n.level || 0;
|
||||
this.freq = n.freq || 100;
|
||||
this.out = n.out || "out";
|
||||
var node = this;
|
||||
if (!pinsInUse.hasOwnProperty(this.pin)) {
|
||||
pinsInUse[this.pin] = this.out;
|
||||
}
|
||||
else {
|
||||
if ((pinsInUse[this.pin] !== this.out)||(pinsInUse[this.pin] === "pwm")) {
|
||||
node.warn(RED._("rpi-gpio.errors.alreadyset",{pin:this.pin,type:pinTypes[pinsInUse[this.pin]]}));
|
||||
}
|
||||
}
|
||||
|
||||
function inputlistener(msg) {
|
||||
if (msg.payload === "true") { msg.payload = true; }
|
||||
if (msg.payload === "false") { msg.payload = false; }
|
||||
var out = Number(msg.payload);
|
||||
var limit = 1;
|
||||
if (node.out === "pwm") { limit = 100; }
|
||||
if ((out >= 0) && (out <= limit)) {
|
||||
if (RED.settings.verbose) { node.log("out: "+msg.payload); }
|
||||
if (node.child !== null) {
|
||||
node.child.stdin.write(msg.payload+"\n");
|
||||
node.status({fill:"green",shape:"dot",text:msg.payload.toString()});
|
||||
}
|
||||
else {
|
||||
node.error(RED._("rpi-gpio.errors.pythoncommandnotfound"),msg);
|
||||
node.status({fill:"red",shape:"ring",text:"rpi-gpio.status.not-running"});
|
||||
}
|
||||
}
|
||||
else { node.warn(RED._("rpi-gpio.errors.invalidinput")+": "+out); }
|
||||
}
|
||||
|
||||
if (node.pin !== undefined) {
|
||||
if (node.set && (node.out === "out")) {
|
||||
node.child = spawn(gpioCommand, [node.out,node.pin,node.level]);
|
||||
node.status({fill:"green",shape:"dot",text:node.level});
|
||||
} else {
|
||||
node.child = spawn(gpioCommand, [node.out,node.pin,node.freq]);
|
||||
node.status({fill:"green",shape:"dot",text:"common.status.ok"});
|
||||
}
|
||||
node.running = true;
|
||||
|
||||
node.on("input", inputlistener);
|
||||
|
||||
node.child.stdout.on('data', function (data) {
|
||||
if (RED.settings.verbose) { node.log("out: "+data+" :"); }
|
||||
});
|
||||
|
||||
node.child.stderr.on('data', function (data) {
|
||||
if (RED.settings.verbose) { node.log("err: "+data+" :"); }
|
||||
});
|
||||
|
||||
node.child.on('close', function (code) {
|
||||
node.child = null;
|
||||
node.running = false;
|
||||
if (RED.settings.verbose) { node.log(RED._("rpi-gpio.status.closed")); }
|
||||
if (node.done) {
|
||||
node.status({fill:"grey",shape:"ring",text:"rpi-gpio.status.closed"});
|
||||
node.done();
|
||||
}
|
||||
else { node.status({fill:"red",shape:"ring",text:"rpi-gpio.status.stopped"}); }
|
||||
});
|
||||
|
||||
node.child.on('error', function (err) {
|
||||
if (err.errno === "ENOENT") { node.error(RED._("rpi-gpio.errors.commandnotfound")); }
|
||||
else if (err.errno === "EACCES") { node.error(RED._("rpi-gpio.errors.commandnotexecutable")); }
|
||||
else { node.error(RED._("rpi-gpio.errors.error")+': ' + err.errno); }
|
||||
});
|
||||
|
||||
}
|
||||
else {
|
||||
node.warn(RED._("rpi-gpio.errors.invalidpin")+": "+node.pin);
|
||||
}
|
||||
|
||||
node.on("close", function(done) {
|
||||
node.status({fill:"grey",shape:"ring",text:"rpi-gpio.status.closed"});
|
||||
delete pinsInUse[node.pin];
|
||||
if (node.child != null) {
|
||||
node.done = done;
|
||||
node.child.stdin.write("close "+node.pin);
|
||||
node.child.kill('SIGKILL');
|
||||
}
|
||||
else { done(); }
|
||||
});
|
||||
|
||||
}
|
||||
RED.nodes.registerType("rpi-gpio out",GPIOOutNode);
|
||||
|
||||
function PiMouseNode(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
this.butt = n.butt || 7;
|
||||
var node = this;
|
||||
|
||||
node.child = spawn(gpioCommand+".py", ["mouse",node.butt]);
|
||||
node.status({fill:"green",shape:"dot",text:"common.status.ok"});
|
||||
|
||||
node.child.stdout.on('data', function (data) {
|
||||
data = Number(data);
|
||||
if (data === 1) { node.send({ topic:"pi/mouse", button:data, payload:1 }); }
|
||||
else { node.send({ topic:"pi/mouse", button:data, payload:0 }); }
|
||||
});
|
||||
|
||||
node.child.stderr.on('data', function (data) {
|
||||
if (RED.settings.verbose) { node.log("err: "+data+" :"); }
|
||||
});
|
||||
|
||||
node.child.on('close', function (code) {
|
||||
node.child = null;
|
||||
node.running = false;
|
||||
if (RED.settings.verbose) { node.log(RED._("rpi-gpio.status.closed")); }
|
||||
if (node.done) {
|
||||
node.status({fill:"grey",shape:"ring",text:"rpi-gpio.status.closed"});
|
||||
node.done();
|
||||
}
|
||||
else { node.status({fill:"red",shape:"ring",text:"rpi-gpio.status.stopped"}); }
|
||||
});
|
||||
|
||||
node.child.on('error', function (err) {
|
||||
if (err.errno === "ENOENT") { node.error(RED._("rpi-gpio.errors.commandnotfound")); }
|
||||
else if (err.errno === "EACCES") { node.error(RED._("rpi-gpio.errors.commandnotexecutable")); }
|
||||
else { node.error(RED._("rpi-gpio.errors.error")+': ' + err.errno); }
|
||||
});
|
||||
|
||||
node.on("close", function(done) {
|
||||
node.status({fill:"grey",shape:"ring",text:"rpi-gpio.status.closed"});
|
||||
if (node.child != null) {
|
||||
node.done = done;
|
||||
node.child.kill('SIGINT');
|
||||
node.child = null;
|
||||
}
|
||||
else { done(); }
|
||||
});
|
||||
}
|
||||
RED.nodes.registerType("rpi-mouse",PiMouseNode);
|
||||
|
||||
function PiKeyboardNode(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
var node = this;
|
||||
|
||||
node.child = spawn(gpioCommand+".py", ["kbd","0"]);
|
||||
node.status({fill:"green",shape:"dot",text:"common.status.ok"});
|
||||
|
||||
node.child.stdout.on('data', function (data) {
|
||||
var b = data.toString().trim().split(",");
|
||||
var act = "up";
|
||||
if (b[1] === "1") { act = "down"; }
|
||||
if (b[1] === "2") { act = "repeat"; }
|
||||
node.send({ topic:"pi/key", payload:Number(b[0]), action:act });
|
||||
});
|
||||
|
||||
node.child.stderr.on('data', function (data) {
|
||||
if (RED.settings.verbose) { node.log("err: "+data+" :"); }
|
||||
});
|
||||
|
||||
node.child.on('close', function (code) {
|
||||
node.running = false;
|
||||
node.child = null;
|
||||
if (RED.settings.verbose) { node.log(RED._("rpi-gpio.status.closed")); }
|
||||
if (node.done) {
|
||||
node.status({fill:"grey",shape:"ring",text:"rpi-gpio.status.closed"});
|
||||
node.done();
|
||||
}
|
||||
else { node.status({fill:"red",shape:"ring",text:"rpi-gpio.status.stopped"}); }
|
||||
});
|
||||
|
||||
node.child.on('error', function (err) {
|
||||
if (err.errno === "ENOENT") { node.error(RED._("rpi-gpio.errors.commandnotfound")); }
|
||||
else if (err.errno === "EACCES") { node.error(RED._("rpi-gpio.errors.commandnotexecutable")); }
|
||||
else { node.error(RED._("rpi-gpio.errors.error")+': ' + err.errno); }
|
||||
});
|
||||
|
||||
node.on("close", function(done) {
|
||||
node.status({});
|
||||
if (node.child != null) {
|
||||
node.done = done;
|
||||
node.child.kill('SIGINT');
|
||||
node.child = null;
|
||||
}
|
||||
else { done(); }
|
||||
});
|
||||
}
|
||||
RED.nodes.registerType("rpi-keyboard",PiKeyboardNode);
|
||||
|
||||
var pitype = { type:"" };
|
||||
exec(gpioCommand+" info", function(err,stdout,stderr) {
|
||||
if (err) {
|
||||
RED.log.info(RED._("rpi-gpio.errors.version"));
|
||||
}
|
||||
else {
|
||||
try {
|
||||
var info = JSON.parse( stdout.trim().replace(/\'/g,"\"") );
|
||||
pitype.type = info["TYPE"];
|
||||
}
|
||||
catch(e) {
|
||||
RED.log.info(RED._("rpi-gpio.errors.sawpitype"),stdout.trim());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
RED.httpAdmin.get('/rpi-gpio/:id', RED.auth.needsPermission('rpi-gpio.read'), function(req,res) {
|
||||
res.json(pitype);
|
||||
});
|
||||
|
||||
RED.httpAdmin.get('/rpi-pins/:id', RED.auth.needsPermission('rpi-gpio.read'), function(req,res) {
|
||||
res.json(pinsInUse);
|
||||
});
|
||||
}
|
||||
@@ -1,213 +0,0 @@
|
||||
/**
|
||||
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
module.exports = function(RED) {
|
||||
"use strict";
|
||||
var dgram = require('dgram');
|
||||
var udpInputPortsInUse = {};
|
||||
|
||||
// The Input Node
|
||||
function UDPin(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
this.group = n.group;
|
||||
this.port = n.port;
|
||||
this.datatype = n.datatype;
|
||||
this.iface = n.iface || null;
|
||||
this.multicast = n.multicast;
|
||||
this.ipv = n.ipv || "udp4";
|
||||
var node = this;
|
||||
|
||||
var opts = {type:node.ipv, reuseAddr:true};
|
||||
if (process.version.indexOf("v0.10") === 0) { opts = node.ipv; }
|
||||
var server;
|
||||
|
||||
if (!udpInputPortsInUse.hasOwnProperty(this.port)) {
|
||||
server = dgram.createSocket(opts); // default to udp4
|
||||
udpInputPortsInUse[this.port] = server;
|
||||
}
|
||||
else {
|
||||
node.warn(RED._("udp.errors.alreadyused",node.port));
|
||||
server = udpInputPortsInUse[this.port]; // re-use existing
|
||||
}
|
||||
|
||||
if (process.version.indexOf("v0.10") === 0) { opts = node.ipv; }
|
||||
|
||||
server.on("error", function (err) {
|
||||
if ((err.code == "EACCES") && (node.port < 1024)) {
|
||||
node.error(RED._("udp.errors.access-error"));
|
||||
} else {
|
||||
node.error(RED._("udp.errors.error",{error:err.code}));
|
||||
}
|
||||
server.close();
|
||||
});
|
||||
|
||||
server.on('message', function (message, remote) {
|
||||
var msg;
|
||||
if (node.datatype =="base64") {
|
||||
msg = { payload:message.toString('base64'), fromip:remote.address+':'+remote.port, ip:remote.address, port:remote.port };
|
||||
} else if (node.datatype =="utf8") {
|
||||
msg = { payload:message.toString('utf8'), fromip:remote.address+':'+remote.port, ip:remote.address, port:remote.port };
|
||||
} else {
|
||||
msg = { payload:message, fromip:remote.address+':'+remote.port, ip:remote.address, port:remote.port };
|
||||
}
|
||||
node.send(msg);
|
||||
});
|
||||
|
||||
server.on('listening', function () {
|
||||
var address = server.address();
|
||||
node.log(RED._("udp.status.listener-at",{host:address.address,port:address.port}));
|
||||
if (node.multicast == "true") {
|
||||
server.setBroadcast(true);
|
||||
try {
|
||||
server.setMulticastTTL(128);
|
||||
server.addMembership(node.group,node.iface);
|
||||
node.log(RED._("udp.status.mc-group",{group:node.group}));
|
||||
} catch (e) {
|
||||
if (e.errno == "EINVAL") {
|
||||
node.error(RED._("udp.errors.bad-mcaddress"));
|
||||
} else if (e.errno == "ENODEV") {
|
||||
node.error(RED._("udp.errors.interface"));
|
||||
} else {
|
||||
node.error(RED._("udp.errors.error",{error:e.errno}));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
node.on("close", function() {
|
||||
if (udpInputPortsInUse.hasOwnProperty(node.port)) {
|
||||
delete udpInputPortsInUse[node.port];
|
||||
}
|
||||
try {
|
||||
server.close();
|
||||
node.log(RED._("udp.status.listener-stopped"));
|
||||
} catch (err) {
|
||||
//node.error(err);
|
||||
}
|
||||
});
|
||||
|
||||
try { server.bind(node.port,node.iface); }
|
||||
catch(e) { } // Don't worry if already bound
|
||||
}
|
||||
RED.httpAdmin.get('/udp-ports/:id', RED.auth.needsPermission('udp-ports.read'), function(req,res) {
|
||||
res.json(Object.keys(udpInputPortsInUse));
|
||||
});
|
||||
RED.nodes.registerType("udp in",UDPin);
|
||||
|
||||
|
||||
// The Output Node
|
||||
function UDPout(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
//this.group = n.group;
|
||||
this.port = n.port;
|
||||
this.outport = n.outport||"";
|
||||
this.base64 = n.base64;
|
||||
this.addr = n.addr;
|
||||
this.iface = n.iface || null;
|
||||
this.multicast = n.multicast;
|
||||
this.ipv = n.ipv || "udp4";
|
||||
var node = this;
|
||||
|
||||
var opts = {type:node.ipv, reuseAddr:true};
|
||||
if (process.version.indexOf("v0.10") === 0) { opts = node.ipv; }
|
||||
|
||||
var sock;
|
||||
if (udpInputPortsInUse[this.outport]) {
|
||||
sock = udpInputPortsInUse[this.outport];
|
||||
}
|
||||
else {
|
||||
sock = dgram.createSocket(opts); // default to udp4
|
||||
sock.on("error", function(err) {
|
||||
// Any async error will also get reported in the sock.send call.
|
||||
// This handler is needed to ensure the error marked as handled to
|
||||
// prevent it going to the global error handler and shutting node-red
|
||||
// down.
|
||||
});
|
||||
udpInputPortsInUse[this.outport] = sock;
|
||||
}
|
||||
|
||||
if (node.multicast != "false") {
|
||||
if (node.outport === "") { node.outport = node.port; }
|
||||
sock.bind(node.outport, function() { // have to bind before you can enable broadcast...
|
||||
sock.setBroadcast(true); // turn on broadcast
|
||||
if (node.multicast == "multi") {
|
||||
try {
|
||||
sock.setMulticastTTL(128);
|
||||
sock.addMembership(node.addr,node.iface); // Add to the multicast group
|
||||
node.log(RED._("udp.status.mc-ready",{outport:node.outport,host:node.addr,port:node.port}));
|
||||
} catch (e) {
|
||||
if (e.errno == "EINVAL") {
|
||||
node.error(RED._("udp.errors.bad-mcaddress"));
|
||||
} else if (e.errno == "ENODEV") {
|
||||
node.error(RED._("udp.errors.interface"));
|
||||
} else {
|
||||
node.error(RED._("udp.errors.error",{error:e.errno}));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
node.log(RED._("udp.status.bc-ready",{outport:node.outport,host:node.addr,port:node.port}));
|
||||
}
|
||||
});
|
||||
} else if ((node.outport !== "") && (!udpInputPortsInUse[this.outport])) {
|
||||
sock.bind(node.outport);
|
||||
node.log(RED._("udp.status.ready",{outport:node.outport,host:node.addr,port:node.port}));
|
||||
} else {
|
||||
node.log(RED._("udp.status.ready-nolocal",{host:node.addr,port:node.port}));
|
||||
}
|
||||
|
||||
node.on("input", function(msg) {
|
||||
if (msg.hasOwnProperty("payload")) {
|
||||
var add = node.addr || msg.ip || "";
|
||||
var por = node.port || msg.port || 0;
|
||||
if (add === "") {
|
||||
node.warn(RED._("udp.errors.ip-notset"));
|
||||
} else if (por === 0) {
|
||||
node.warn(RED._("udp.errors.port-notset"));
|
||||
} else if (isNaN(por) || (por < 1) || (por > 65535)) {
|
||||
node.warn(RED._("udp.errors.port-invalid"));
|
||||
} else {
|
||||
var message;
|
||||
if (node.base64) {
|
||||
message = Buffer.from(msg.payload, 'base64');
|
||||
} else if (msg.payload instanceof Buffer) {
|
||||
message = msg.payload;
|
||||
} else {
|
||||
message = Buffer.from(""+msg.payload);
|
||||
}
|
||||
sock.send(message, 0, message.length, por, add, function(err, bytes) {
|
||||
if (err) {
|
||||
node.error("udp : "+err,msg);
|
||||
}
|
||||
message = null;
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
node.on("close", function() {
|
||||
if (udpInputPortsInUse.hasOwnProperty(node.outport)) {
|
||||
delete udpInputPortsInUse[node.outport];
|
||||
}
|
||||
try {
|
||||
sock.close();
|
||||
node.log(RED._("udp.status.output-stopped"));
|
||||
} catch (err) {
|
||||
//node.error(err);
|
||||
}
|
||||
});
|
||||
}
|
||||
RED.nodes.registerType("udp out",UDPout);
|
||||
}
|
||||
@@ -1,159 +0,0 @@
|
||||
/**
|
||||
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
var util = require("util");
|
||||
var mqtt = require("./mqtt");
|
||||
var settings = require(process.env.NODE_RED_HOME+"/red/red").settings;
|
||||
|
||||
util.log("[warn] nodes/core/io/lib/mqttConnectionPool.js is deprecated and will be removed in a future release of Node-RED. Please report this usage to the Node-RED mailing list.");
|
||||
|
||||
var connections = {};
|
||||
|
||||
function matchTopic(ts,t) {
|
||||
if (ts == "#") {
|
||||
return true;
|
||||
}
|
||||
var re = new RegExp("^"+ts.replace(/([\[\]\?\(\)\\\\$\^\*\.|])/g,"\\$1").replace(/\+/g,"[^/]+").replace(/\/#$/,"(\/.*)?")+"$");
|
||||
return re.test(t);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
get: function(broker,port,clientid,username,password,will) {
|
||||
var id = "["+(username||"")+":"+(password||"")+"]["+(clientid||"")+"]@"+broker+":"+port;
|
||||
if (!connections[id]) {
|
||||
connections[id] = function() {
|
||||
var uid = (1+Math.random()*4294967295).toString(16);
|
||||
var client = mqtt.createClient(port,broker);
|
||||
client.uid = uid;
|
||||
client.setMaxListeners(0);
|
||||
var options = {keepalive:15};
|
||||
options.clientId = clientid || 'mqtt_' + (1+Math.random()*4294967295).toString(16);
|
||||
options.username = username;
|
||||
options.password = password;
|
||||
options.will = will;
|
||||
var queue = [];
|
||||
var subscriptions = {};
|
||||
var connecting = false;
|
||||
var obj = {
|
||||
_instances: 0,
|
||||
publish: function(msg) {
|
||||
if (client.isConnected()) {
|
||||
client.publish(msg.topic,msg.payload,msg.qos,msg.retain);
|
||||
} else {
|
||||
if (!connecting) {
|
||||
connecting = true;
|
||||
client.connect(options);
|
||||
}
|
||||
queue.push(msg);
|
||||
}
|
||||
},
|
||||
subscribe: function(topic,qos,callback,ref) {
|
||||
ref = ref||0;
|
||||
subscriptions[topic] = subscriptions[topic]||{};
|
||||
|
||||
var sub = {
|
||||
topic:topic,
|
||||
qos:qos,
|
||||
handler:function(mtopic,mpayload,mqos,mretain) {
|
||||
if (matchTopic(topic,mtopic)) {
|
||||
callback(mtopic,mpayload,mqos,mretain);
|
||||
}
|
||||
},
|
||||
ref: ref
|
||||
};
|
||||
subscriptions[topic][ref] = sub;
|
||||
client.on('message',sub.handler);
|
||||
if (client.isConnected()) {
|
||||
client.subscribe(topic,qos);
|
||||
}
|
||||
},
|
||||
unsubscribe: function(topic,ref) {
|
||||
ref = ref||0;
|
||||
var sub = subscriptions[topic];
|
||||
if (sub) {
|
||||
if (sub[ref]) {
|
||||
client.removeListener('message',sub[ref].handler);
|
||||
delete sub[ref];
|
||||
}
|
||||
if (Object.keys(sub).length == 0) {
|
||||
delete subscriptions[topic];
|
||||
client.unsubscribe(topic);
|
||||
}
|
||||
}
|
||||
},
|
||||
on: function(a,b){
|
||||
client.on(a,b);
|
||||
},
|
||||
once: function(a,b){
|
||||
client.once(a,b);
|
||||
},
|
||||
connect: function() {
|
||||
if (client && !client.isConnected() && !connecting) {
|
||||
connecting = true;
|
||||
client.connect(options);
|
||||
}
|
||||
},
|
||||
disconnect: function(ref) {
|
||||
|
||||
this._instances -= 1;
|
||||
if (this._instances == 0) {
|
||||
client.disconnect();
|
||||
client = null;
|
||||
delete connections[id];
|
||||
}
|
||||
},
|
||||
isConnected: function() {
|
||||
return client.isConnected();
|
||||
}
|
||||
};
|
||||
client.on('connect',function() {
|
||||
if (client) {
|
||||
util.log('[mqtt] ['+uid+'] connected to broker tcp://'+broker+':'+port);
|
||||
connecting = false;
|
||||
for (var s in subscriptions) {
|
||||
var topic = s;
|
||||
var qos = 0;
|
||||
for (var r in subscriptions[s]) {
|
||||
qos = Math.max(qos,subscriptions[s][r].qos);
|
||||
}
|
||||
client.subscribe(topic,qos);
|
||||
}
|
||||
//console.log("connected - publishing",queue.length,"messages");
|
||||
while(queue.length) {
|
||||
var msg = queue.shift();
|
||||
//console.log(msg);
|
||||
client.publish(msg.topic,msg.payload,msg.qos,msg.retain);
|
||||
}
|
||||
}
|
||||
});
|
||||
client.on('connectionlost', function(err) {
|
||||
util.log('[mqtt] ['+uid+'] connection lost to broker tcp://'+broker+':'+port);
|
||||
connecting = false;
|
||||
setTimeout(function() {
|
||||
obj.connect();
|
||||
}, settings.mqttReconnectTime||5000);
|
||||
});
|
||||
client.on('disconnect', function() {
|
||||
connecting = false;
|
||||
util.log('[mqtt] ['+uid+'] disconnected from broker tcp://'+broker+':'+port);
|
||||
});
|
||||
|
||||
return obj
|
||||
}();
|
||||
}
|
||||
connections[id]._instances += 1;
|
||||
return connections[id];
|
||||
}
|
||||
};
|
||||
@@ -1,166 +0,0 @@
|
||||
/**
|
||||
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
module.exports = function(RED) {
|
||||
"use strict";
|
||||
|
||||
var operators = {
|
||||
'eq': function(a, b) { return a == b; },
|
||||
'neq': function(a, b) { return a != b; },
|
||||
'lt': function(a, b) { return a < b; },
|
||||
'lte': function(a, b) { return a <= b; },
|
||||
'gt': function(a, b) { return a > b; },
|
||||
'gte': function(a, b) { return a >= b; },
|
||||
'btwn': function(a, b, c) { return a >= b && a <= c; },
|
||||
'cont': function(a, b) { return (a + "").indexOf(b) != -1; },
|
||||
'regex': function(a, b, c, d) { return (a + "").match(new RegExp(b,d?'i':'')); },
|
||||
'true': function(a) { return a === true; },
|
||||
'false': function(a) { return a === false; },
|
||||
'null': function(a) { return (typeof a == "undefined" || a === null); },
|
||||
'nnull': function(a) { return (typeof a != "undefined" && a !== null); },
|
||||
'else': function(a) { return a === true; }
|
||||
};
|
||||
|
||||
function SwitchNode(n) {
|
||||
RED.nodes.createNode(this, n);
|
||||
this.rules = n.rules || [];
|
||||
this.property = n.property;
|
||||
this.propertyType = n.propertyType || "msg";
|
||||
|
||||
if (this.propertyType === 'jsonata') {
|
||||
try {
|
||||
this.property = RED.util.prepareJSONataExpression(this.property,this);
|
||||
} catch(err) {
|
||||
this.error(RED._("switch.errors.invalid-expr",{error:err.message}));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this.checkall = n.checkall || "true";
|
||||
this.previousValue = null;
|
||||
var node = this;
|
||||
var valid = true;
|
||||
for (var i=0; i<this.rules.length; i+=1) {
|
||||
var rule = this.rules[i];
|
||||
if (!rule.vt) {
|
||||
if (!isNaN(Number(rule.v))) {
|
||||
rule.vt = 'num';
|
||||
} else {
|
||||
rule.vt = 'str';
|
||||
}
|
||||
}
|
||||
if (rule.vt === 'num') {
|
||||
if (!isNaN(Number(rule.v))) {
|
||||
rule.v = Number(rule.v);
|
||||
}
|
||||
} else if (rule.vt === "jsonata") {
|
||||
try {
|
||||
rule.v = RED.util.prepareJSONataExpression(rule.v,node);
|
||||
} catch(err) {
|
||||
this.error(RED._("switch.errors.invalid-expr",{error:err.message}));
|
||||
valid = false;
|
||||
}
|
||||
}
|
||||
if (typeof rule.v2 !== 'undefined') {
|
||||
if (!rule.v2t) {
|
||||
if (!isNaN(Number(rule.v2))) {
|
||||
rule.v2t = 'num';
|
||||
} else {
|
||||
rule.v2t = 'str';
|
||||
}
|
||||
}
|
||||
if (rule.v2t === 'num') {
|
||||
rule.v2 = Number(rule.v2);
|
||||
} else if (rule.v2t === 'jsonata') {
|
||||
try {
|
||||
rule.v2 = RED.util.prepareJSONataExpression(rule.v2,node);
|
||||
} catch(err) {
|
||||
this.error(RED._("switch.errors.invalid-expr",{error:err.message}));
|
||||
valid = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!valid) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.on('input', function (msg) {
|
||||
var onward = [];
|
||||
try {
|
||||
var prop;
|
||||
if (node.propertyType === 'jsonata') {
|
||||
prop = RED.util.evaluateJSONataExpression(node.property,msg);
|
||||
} else {
|
||||
prop = RED.util.evaluateNodeProperty(node.property,node.propertyType,node,msg);
|
||||
}
|
||||
var elseflag = true;
|
||||
for (var i=0; i<node.rules.length; i+=1) {
|
||||
var rule = node.rules[i];
|
||||
var test = prop;
|
||||
var v1,v2;
|
||||
if (rule.vt === 'prev') {
|
||||
v1 = node.previousValue;
|
||||
} else if (rule.vt === 'jsonata') {
|
||||
try {
|
||||
v1 = RED.util.evaluateJSONataExpression(rule.v,msg);
|
||||
} catch(err) {
|
||||
node.error(RED._("switch.errors.invalid-expr",{error:err.message}));
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
v1 = RED.util.evaluateNodeProperty(rule.v,rule.vt,node,msg);
|
||||
} catch(err) {
|
||||
v1 = undefined;
|
||||
}
|
||||
}
|
||||
v2 = rule.v2;
|
||||
if (rule.v2t === 'prev') {
|
||||
v2 = node.previousValue;
|
||||
} else if (rule.v2t === 'jsonata') {
|
||||
try {
|
||||
v2 = RED.util.evaluateJSONataExpression(rule.v2,msg);
|
||||
} catch(err) {
|
||||
node.error(RED._("switch.errors.invalid-expr",{error:err.message}));
|
||||
return;
|
||||
}
|
||||
} else if (typeof v2 !== 'undefined') {
|
||||
try {
|
||||
v2 = RED.util.evaluateNodeProperty(rule.v2,rule.v2t,node,msg);
|
||||
} catch(err) {
|
||||
v2 = undefined;
|
||||
}
|
||||
}
|
||||
if (rule.t == "else") { test = elseflag; elseflag = true; }
|
||||
if (operators[rule.t](test,v1,v2,rule.case)) {
|
||||
onward.push(msg);
|
||||
elseflag = false;
|
||||
if (node.checkall == "false") { break; }
|
||||
} else {
|
||||
onward.push(null);
|
||||
}
|
||||
}
|
||||
node.previousValue = prop;
|
||||
this.send(onward);
|
||||
} catch(err) {
|
||||
node.warn(err);
|
||||
}
|
||||
});
|
||||
}
|
||||
RED.nodes.registerType("switch", SwitchNode);
|
||||
}
|
||||
@@ -1,256 +0,0 @@
|
||||
/**
|
||||
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
module.exports = function(RED) {
|
||||
"use strict";
|
||||
|
||||
function ChangeNode(n) {
|
||||
RED.nodes.createNode(this, n);
|
||||
var node = this;
|
||||
|
||||
this.rules = n.rules;
|
||||
var rule;
|
||||
if (!this.rules) {
|
||||
rule = {
|
||||
t:(n.action=="replace"?"set":n.action),
|
||||
p:n.property||""
|
||||
}
|
||||
|
||||
if ((rule.t === "set")||(rule.t === "move")) {
|
||||
rule.to = n.to||"";
|
||||
} else if (rule.t === "change") {
|
||||
rule.from = n.from||"";
|
||||
rule.to = n.to||"";
|
||||
rule.re = (n.reg===null||n.reg);
|
||||
}
|
||||
this.rules = [rule];
|
||||
}
|
||||
|
||||
var valid = true;
|
||||
for (var i=0;i<this.rules.length;i++) {
|
||||
rule = this.rules[i];
|
||||
// Migrate to type-aware rules
|
||||
if (!rule.pt) {
|
||||
rule.pt = "msg";
|
||||
}
|
||||
if (rule.t === "change" && rule.re) {
|
||||
rule.fromt = 're';
|
||||
delete rule.re;
|
||||
}
|
||||
if (rule.t === "set" && !rule.tot) {
|
||||
if (rule.to.indexOf("msg.") === 0 && !rule.tot) {
|
||||
rule.to = rule.to.substring(4);
|
||||
rule.tot = "msg";
|
||||
}
|
||||
}
|
||||
if (!rule.tot) {
|
||||
rule.tot = "str";
|
||||
}
|
||||
if (!rule.fromt) {
|
||||
rule.fromt = "str";
|
||||
}
|
||||
if (rule.t === "change" && rule.fromt !== 'msg' && rule.fromt !== 'flow' && rule.fromt !== 'global') {
|
||||
rule.fromRE = rule.from;
|
||||
if (rule.fromt !== 're') {
|
||||
rule.fromRE = rule.fromRE.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
|
||||
}
|
||||
try {
|
||||
rule.fromRE = new RegExp(rule.fromRE, "g");
|
||||
} catch (e) {
|
||||
valid = false;
|
||||
this.error(RED._("change.errors.invalid-from",{error:e.message}));
|
||||
}
|
||||
}
|
||||
if (rule.tot === 'num') {
|
||||
rule.to = Number(rule.to);
|
||||
} else if (rule.tot === 'json' || rule.tot === 'bin') {
|
||||
try {
|
||||
// check this is parsable JSON
|
||||
JSON.parse(rule.to);
|
||||
} catch(e2) {
|
||||
valid = false;
|
||||
this.error(RED._("change.errors.invalid-json"));
|
||||
}
|
||||
} else if (rule.tot === 'bool') {
|
||||
rule.to = /^true$/i.test(rule.to);
|
||||
} else if (rule.tot === 'jsonata') {
|
||||
try {
|
||||
rule.to = RED.util.prepareJSONataExpression(rule.to,this);
|
||||
} catch(e) {
|
||||
valid = false;
|
||||
this.error(RED._("change.errors.invalid-expr",{error:e.message}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function applyRule(msg,rule) {
|
||||
try {
|
||||
var property = rule.p;
|
||||
var value = rule.to;
|
||||
if (rule.tot === 'json') {
|
||||
value = JSON.parse(rule.to);
|
||||
} else if (rule.tot === 'bin') {
|
||||
value = Buffer.from(JSON.parse(rule.to))
|
||||
}
|
||||
var current;
|
||||
var fromValue;
|
||||
var fromType;
|
||||
var fromRE;
|
||||
if (rule.tot === "msg") {
|
||||
value = RED.util.getMessageProperty(msg,rule.to);
|
||||
} else if (rule.tot === 'flow') {
|
||||
value = node.context().flow.get(rule.to);
|
||||
} else if (rule.tot === 'global') {
|
||||
value = node.context().global.get(rule.to);
|
||||
} else if (rule.tot === 'date') {
|
||||
value = Date.now();
|
||||
} else if (rule.tot === 'jsonata') {
|
||||
try{
|
||||
value = RED.util.evaluateJSONataExpression(rule.to,msg);
|
||||
} catch(err) {
|
||||
node.error(RED._("change.errors.invalid-expr",{error:err.message}));
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (rule.t === 'change') {
|
||||
if (rule.fromt === 'msg' || rule.fromt === 'flow' || rule.fromt === 'global') {
|
||||
if (rule.fromt === "msg") {
|
||||
fromValue = RED.util.getMessageProperty(msg,rule.from);
|
||||
} else if (rule.tot === 'flow') {
|
||||
fromValue = node.context().flow.get(rule.from);
|
||||
} else if (rule.tot === 'global') {
|
||||
fromValue = node.context().global.get(rule.from);
|
||||
}
|
||||
if (typeof fromValue === 'number' || fromValue instanceof Number) {
|
||||
fromType = 'num';
|
||||
} else if (typeof fromValue === 'boolean') {
|
||||
fromType = 'bool'
|
||||
} else if (fromValue instanceof RegExp) {
|
||||
fromType = 're';
|
||||
fromRE = fromValue;
|
||||
} else if (typeof fromValue === 'string') {
|
||||
fromType = 'str';
|
||||
fromRE = fromValue.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
|
||||
try {
|
||||
fromRE = new RegExp(fromRE, "g");
|
||||
} catch (e) {
|
||||
valid = false;
|
||||
node.error(RED._("change.errors.invalid-from",{error:e.message}));
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
node.error(RED._("change.errors.invalid-from",{error:"unsupported type: "+(typeof fromValue)}));
|
||||
return
|
||||
}
|
||||
} else {
|
||||
fromType = rule.fromt;
|
||||
fromValue = rule.from;
|
||||
fromRE = rule.fromRE;
|
||||
}
|
||||
}
|
||||
if (rule.pt === 'msg') {
|
||||
if (rule.t === 'delete') {
|
||||
RED.util.setMessageProperty(msg,property,undefined);
|
||||
} else if (rule.t === 'set') {
|
||||
RED.util.setMessageProperty(msg,property,value);
|
||||
} else if (rule.t === 'change') {
|
||||
current = RED.util.getMessageProperty(msg,property);
|
||||
if (typeof current === 'string') {
|
||||
if ((fromType === 'num' || fromType === 'bool' || fromType === 'str') && current === fromValue) {
|
||||
// str representation of exact from number/boolean
|
||||
// only replace if they match exactly
|
||||
RED.util.setMessageProperty(msg,property,value);
|
||||
} else {
|
||||
current = current.replace(fromRE,value);
|
||||
RED.util.setMessageProperty(msg,property,current);
|
||||
}
|
||||
} else if ((typeof current === 'number' || current instanceof Number) && fromType === 'num') {
|
||||
if (current == Number(fromValue)) {
|
||||
RED.util.setMessageProperty(msg,property,value);
|
||||
}
|
||||
} else if (typeof current === 'boolean' && fromType === 'bool') {
|
||||
if (current.toString() === fromValue) {
|
||||
RED.util.setMessageProperty(msg,property,value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
var target;
|
||||
if (rule.pt === 'flow') {
|
||||
target = node.context().flow;
|
||||
} else if (rule.pt === 'global') {
|
||||
target = node.context().global;
|
||||
}
|
||||
if (target) {
|
||||
if (rule.t === 'delete') {
|
||||
target.set(property,undefined);
|
||||
} else if (rule.t === 'set') {
|
||||
target.set(property,value);
|
||||
} else if (rule.t === 'change') {
|
||||
current = target.get(msg,property);
|
||||
if (typeof current === 'string') {
|
||||
if ((fromType === 'num' || fromType === 'bool' || fromType === 'str') && current === fromValue) {
|
||||
// str representation of exact from number/boolean
|
||||
// only replace if they match exactly
|
||||
target.set(property,value);
|
||||
} else {
|
||||
current = current.replace(fromRE,value);
|
||||
target.set(property,current);
|
||||
}
|
||||
} else if ((typeof current === 'number' || current instanceof Number) && fromType === 'num') {
|
||||
if (current == Number(fromValue)) {
|
||||
target.set(property,value);
|
||||
}
|
||||
} else if (typeof current === 'boolean' && fromType === 'bool') {
|
||||
if (current.toString() === fromValue) {
|
||||
target.set(property,value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch(err) {/*console.log(err.stack)*/}
|
||||
return msg;
|
||||
}
|
||||
if (valid) {
|
||||
this.on('input', function(msg) {
|
||||
for (var i=0; i<this.rules.length; i++) {
|
||||
if (this.rules[i].t === "move") {
|
||||
var r = this.rules[i];
|
||||
if ((r.tot !== r.pt) || (r.p.indexOf(r.to) !== -1)) {
|
||||
msg = applyRule(msg,{t:"set", p:r.to, pt:r.tot, to:r.p, tot:r.pt});
|
||||
applyRule(msg,{t:"delete", p:r.p, pt:r.pt});
|
||||
}
|
||||
else { // 2 step move if we are moving from a child
|
||||
msg = applyRule(msg,{t:"set", p:"_temp_move", pt:r.tot, to:r.p, tot:r.pt});
|
||||
applyRule(msg,{t:"delete", p:r.p, pt:r.pt});
|
||||
msg = applyRule(msg,{t:"set", p:r.to, pt:r.tot, to:"_temp_move", tot:r.pt});
|
||||
applyRule(msg,{t:"delete", p:"_temp_move", pt:r.pt});
|
||||
}
|
||||
} else {
|
||||
msg = applyRule(msg,this.rules[i]);
|
||||
}
|
||||
if (msg === null) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
node.send(msg);
|
||||
});
|
||||
}
|
||||
}
|
||||
RED.nodes.registerType("change", ChangeNode);
|
||||
};
|
||||
@@ -1,53 +0,0 @@
|
||||
|
||||
<script type="text/x-red" data-template-name="json">
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
|
||||
<input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
|
||||
</div>
|
||||
<hr align="middle"/>
|
||||
<div class="form-row">
|
||||
<label style="width:100%; border-bottom: 1px solid #eee;"><span data-i18n="json.label.o2j"></span></label>
|
||||
</div>
|
||||
<div class="form-row" style="padding-left: 20px;">
|
||||
<input style="width:20px; vertical-align:top; margin-right: 5px;" type="checkbox" id="node-input-pretty"><label style="width: auto;" for="node-input-pretty" data-i18n="json.label.pretty"></span>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="json">
|
||||
<p>Converts between a JSON string and its JavaScript object representation, in either direction.</p>
|
||||
<h3>Inputs</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>payload<span class="property-type">object | string</span></dt>
|
||||
<dd>A JavaScript object or JSON string.</dd>
|
||||
</dl>
|
||||
<h3>Outputs</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>payload<span class="property-type">object | string</span></dt>
|
||||
<dd>
|
||||
<ul>
|
||||
<li>If the input is a JSON string it tries to parse it to a JavaScript object.</li>
|
||||
<li>If the input is a JavaScript object it creates a JSON string. The string can optionally be well-formatted.</li>
|
||||
</ul>
|
||||
</dd>
|
||||
</dl>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('json',{
|
||||
category: 'function',
|
||||
color:"#DEBD5C",
|
||||
defaults: {
|
||||
name: {value:""},
|
||||
pretty: {value:"false"}
|
||||
},
|
||||
inputs:1,
|
||||
outputs:1,
|
||||
icon: "parser-json.png",
|
||||
label: function() {
|
||||
return this.name||"json";
|
||||
},
|
||||
labelStyle: function() {
|
||||
return this.name?"node_label_italic":"";
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@@ -1,49 +0,0 @@
|
||||
/**
|
||||
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
module.exports = function(RED) {
|
||||
"use strict";
|
||||
|
||||
function JSONNode(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
this.indent = n.pretty ? 4 : 0;
|
||||
var node = this;
|
||||
this.on("input", function(msg) {
|
||||
if (msg.hasOwnProperty("payload")) {
|
||||
if (typeof msg.payload === "string") {
|
||||
try {
|
||||
msg.payload = JSON.parse(msg.payload);
|
||||
node.send(msg);
|
||||
}
|
||||
catch(e) { node.error(e.message,msg); }
|
||||
}
|
||||
else if (typeof msg.payload === "object") {
|
||||
if (!Buffer.isBuffer(msg.payload)) {
|
||||
try {
|
||||
msg.payload = JSON.stringify(msg.payload,null,node.indent);
|
||||
node.send(msg);
|
||||
}
|
||||
catch(e) { node.error(RED._("json.errors.dropped-error")); }
|
||||
}
|
||||
else { node.warn(RED._("json.errors.dropped-object")); }
|
||||
}
|
||||
else { node.warn(RED._("json.errors.dropped")); }
|
||||
}
|
||||
else { node.send(msg); } // If no payload - just pass it on.
|
||||
});
|
||||
}
|
||||
RED.nodes.registerType("json",JSONNode);
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
|
||||
<script type="text/x-red" data-template-name="tail">
|
||||
<div class="form-row">
|
||||
<label for="node-input-filename"><i class="fa fa-file"></i> <span data-i18n="tail.label.filename"></span></label>
|
||||
<input id="node-input-filename" type="text">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-filetype"><i class="fa fa-file-text-o"></i> <span data-i18n="tail.label.type"></span></label>
|
||||
<select type="text" id="node-input-filetype">
|
||||
<option value="text" data-i18n="tail.action.text"></option>
|
||||
<option value="binary" data-i18n="tail.action.binary"></option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-row" id="node-tail-split">
|
||||
<label> </label>
|
||||
<input type="checkbox" id="node-input-split" placeholder="Name" style="display: inline-block; width: auto; vertical-align: top;">
|
||||
<label for="node-input-split" style="width: 70%;"><span data-i18n="tail.label.splitlines"></span></label>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
|
||||
<input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="tail">
|
||||
<p>Tails (watches for things to be added) to the configured file. (Linux/Mac ONLY)</p>
|
||||
<p>This will not work on Windows filesystems, as it relies on the <b>tail -F</b> command.</p>
|
||||
<h3>Outputs</h3>
|
||||
<ul>
|
||||
<li>Text (UTF-8) files will be returned as strings.</li>
|
||||
<li>Binary files will be returned as Buffer objects.</li>
|
||||
</ul>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('tail',{
|
||||
category: 'storage-input',
|
||||
defaults: {
|
||||
name: {value:""},
|
||||
filetype: {value:"text"},
|
||||
split: {value:false},
|
||||
filename: {value:"",required:true}
|
||||
},
|
||||
color:"BurlyWood",
|
||||
inputs:0,
|
||||
outputs:1,
|
||||
icon: "file.png",
|
||||
label: function() {
|
||||
return this.name||this.filename||"tail";
|
||||
},
|
||||
labelStyle: function() {
|
||||
return this.name?"node_label_italic":"";
|
||||
},
|
||||
oneditprepare: function() {
|
||||
$("#node-input-filetype").on("change",function() {
|
||||
if (this.value === "text") { $("#node-tail-split").show(); }
|
||||
else { $("#node-tail-split").hide(); }
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@@ -1,75 +0,0 @@
|
||||
/**
|
||||
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
module.exports = function(RED) {
|
||||
"use strict";
|
||||
var spawn = require('child_process').spawn;
|
||||
var plat = require('os').platform();
|
||||
|
||||
if (plat.match(/^win/)) {
|
||||
throw RED._("tail.errors.windowsnotsupport");
|
||||
}
|
||||
|
||||
function TailNode(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
|
||||
this.filename = n.filename;
|
||||
this.filetype = n.filetype || "text";
|
||||
this.split = n.split || false;
|
||||
var node = this;
|
||||
|
||||
var err = "";
|
||||
// TODO: rewrite to use node-tail
|
||||
var tail = spawn("tail", ["-F", "-n", "0", this.filename]);
|
||||
tail.stdout.on("data", function (data) {
|
||||
var msg = { topic:node.filename };
|
||||
if (node.filetype === "text") {
|
||||
if (node.split) {
|
||||
// TODO: allow customisation of the line break - as we do elsewhere
|
||||
var strings = data.toString().split("\n");
|
||||
for (var s in strings) {
|
||||
//TODO: should we really filter blanks? Is that expected?
|
||||
if (strings[s] !== "") {
|
||||
node.send({
|
||||
topic: node.filename,
|
||||
payload: strings[s]
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
msg.payload = data.toString();
|
||||
node.send(msg);
|
||||
}
|
||||
}
|
||||
else {
|
||||
msg.payload = data;
|
||||
node.send(msg);
|
||||
}
|
||||
});
|
||||
|
||||
tail.stderr.on("data", function(data) {
|
||||
node.error(data.toString());
|
||||
});
|
||||
|
||||
this.on("close", function() {
|
||||
/* istanbul ignore else */
|
||||
if (tail) { tail.kill(); }
|
||||
});
|
||||
}
|
||||
|
||||
RED.nodes.registerType("tail",TailNode);
|
||||
}
|
||||
@@ -1,195 +0,0 @@
|
||||
/**
|
||||
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
module.exports = function(RED) {
|
||||
"use strict";
|
||||
var fs = require("fs-extra");
|
||||
var os = require("os");
|
||||
var path = require("path");
|
||||
|
||||
function FileNode(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
this.filename = n.filename;
|
||||
this.appendNewline = n.appendNewline;
|
||||
this.overwriteFile = n.overwriteFile.toString();
|
||||
this.createDir = n.createDir || false;
|
||||
var node = this;
|
||||
node.wstream = null;
|
||||
node.data = [];
|
||||
|
||||
this.on("input",function(msg) {
|
||||
var filename = node.filename || msg.filename || "";
|
||||
if ((!node.filename) && (!node.tout)) {
|
||||
node.tout = setTimeout(function() {
|
||||
node.status({fill:"grey",shape:"dot",text:filename});
|
||||
clearTimeout(node.tout);
|
||||
node.tout = null;
|
||||
},333);
|
||||
}
|
||||
if (filename === "") { node.warn(RED._("file.errors.nofilename")); }
|
||||
else if (node.overwriteFile === "delete") {
|
||||
fs.unlink(filename, function (err) {
|
||||
if (err) { node.error(RED._("file.errors.deletefail",{error:err.toString()}),msg); }
|
||||
else if (RED.settings.verbose) { node.log(RED._("file.status.deletedfile",{file:filename})); }
|
||||
});
|
||||
}
|
||||
else if (msg.hasOwnProperty("payload") && (typeof msg.payload !== "undefined")) {
|
||||
var dir = path.dirname(filename);
|
||||
if (node.createDir) {
|
||||
fs.ensureDir(dir, function(err) {
|
||||
if (err) { node.error(RED._("file.errors.createfail",{error:err.toString()}),msg); }
|
||||
});
|
||||
}
|
||||
|
||||
var data = msg.payload;
|
||||
if ((typeof data === "object") && (!Buffer.isBuffer(data))) {
|
||||
data = JSON.stringify(data);
|
||||
}
|
||||
if (typeof data === "boolean") { data = data.toString(); }
|
||||
if (typeof data === "number") { data = data.toString(); }
|
||||
if ((this.appendNewline) && (!Buffer.isBuffer(data))) { data += os.EOL; }
|
||||
node.data.push(Buffer.from(data));
|
||||
|
||||
while (node.data.length > 0) {
|
||||
if (this.overwriteFile === "true") {
|
||||
node.wstream = fs.createWriteStream(filename, { encoding:'binary', flags:'w', autoClose:true });
|
||||
node.wstream.on("error", function(err) {
|
||||
node.error(RED._("file.errors.writefail",{error:err.toString()}),msg);
|
||||
});
|
||||
node.wstream.end(node.data.shift());
|
||||
}
|
||||
else {
|
||||
if ((!node.wstream) || (!node.filename)) {
|
||||
node.wstream = fs.createWriteStream(filename, { encoding:'binary', flags:'a', autoClose:true });
|
||||
node.wstream.on("error", function(err) {
|
||||
node.error(RED._("file.errors.appendfail",{error:err.toString()}),msg);
|
||||
});
|
||||
}
|
||||
if (node.filename) { node.wstream.write(node.data.shift()); }
|
||||
else { node.wstream.end(node.data.shift()); }
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
this.on('close', function() {
|
||||
if (node.wstream) { node.wstream.end(); }
|
||||
if (node.tout) { clearTimeout(node.tout); }
|
||||
node.status({});
|
||||
});
|
||||
}
|
||||
RED.nodes.registerType("file",FileNode);
|
||||
|
||||
|
||||
function FileInNode(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
this.filename = n.filename;
|
||||
this.format = n.format;
|
||||
this.chunk = false;
|
||||
if (this.format === "lines") { this.chunk = true; }
|
||||
if (this.format === "stream") { this.chunk = true; }
|
||||
var node = this;
|
||||
|
||||
this.on("input",function(msg) {
|
||||
var filename = node.filename || msg.filename || "";
|
||||
if (!node.filename) {
|
||||
node.status({fill:"grey",shape:"dot",text:filename});
|
||||
}
|
||||
if (filename === "") {
|
||||
node.warn(RED._("file.errors.nofilename"));
|
||||
}
|
||||
else {
|
||||
msg.filename = filename;
|
||||
var lines = Buffer.from([]);
|
||||
var spare = "";
|
||||
var count = 0;
|
||||
var type = "buffer";
|
||||
var ch = "";
|
||||
if (node.format === "lines") {
|
||||
ch = "\n";
|
||||
type = "string";
|
||||
}
|
||||
var hwm;
|
||||
var getout = false;
|
||||
|
||||
var rs = fs.createReadStream(filename)
|
||||
.on('readable', function () {
|
||||
var chunk;
|
||||
var hwm = rs._readableState.highWaterMark;
|
||||
while (null !== (chunk = rs.read())) {
|
||||
if (node.chunk === true) {
|
||||
getout = true;
|
||||
if (node.format === "lines") {
|
||||
spare += chunk.toString();
|
||||
var bits = spare.split("\n");
|
||||
for (var i=0; i < bits.length - 1; i++) {
|
||||
var m = {
|
||||
payload:bits[i],
|
||||
topic:msg.topic,
|
||||
filename:msg.filename,
|
||||
parts:{index:count, ch:ch, type:type, id:msg._msgid}
|
||||
}
|
||||
count += 1;
|
||||
if ((chunk.length < hwm) && (bits[i+1].length === 0)) {
|
||||
m.parts.count = count;
|
||||
}
|
||||
node.send(m);
|
||||
}
|
||||
spare = bits[i];
|
||||
if (chunk.length !== hwm) { getout = false; }
|
||||
//console.log("LEFT",bits[i].length,bits[i]);
|
||||
}
|
||||
if (node.format === "stream") {
|
||||
var m = {
|
||||
payload:chunk,
|
||||
topic:msg.topic,
|
||||
filename:msg.filename,
|
||||
parts:{index:count, ch:ch, type:type, id:msg._msgid}
|
||||
}
|
||||
count += 1;
|
||||
if (chunk.length < hwm) { // last chunk is smaller that high water mark = eof
|
||||
getout = false;
|
||||
m.parts.count = count;
|
||||
}
|
||||
node.send(m);
|
||||
}
|
||||
}
|
||||
else {
|
||||
lines = Buffer.concat([lines,chunk]);
|
||||
}
|
||||
}
|
||||
})
|
||||
.on('error', function(err) {
|
||||
node.error('Error while reading file.', msg);
|
||||
})
|
||||
.on('end', function() {
|
||||
if (node.chunk === false) {
|
||||
if (node.format === "utf8") { msg.payload = lines.toString(); }
|
||||
else { msg.payload = lines; }
|
||||
node.send(msg);
|
||||
}
|
||||
else if (getout) { // last chunk same size as high water mark - have to send empty extra packet.
|
||||
var m = { parts:{index:count, count:count, ch:ch, type:type, id:msg._msgid} };
|
||||
node.send(m);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
this.on('close', function() {
|
||||
node.status({});
|
||||
});
|
||||
}
|
||||
RED.nodes.registerType("file in",FileInNode);
|
||||
}
|
||||
165
package.json
165
package.json
@@ -1,99 +1,122 @@
|
||||
{
|
||||
"name" : "node-red",
|
||||
"version" : "0.17.1",
|
||||
"description" : "A visual tool for wiring the Internet of Things",
|
||||
"homepage" : "http://nodered.org",
|
||||
"license" : "Apache-2.0",
|
||||
"repository" : {
|
||||
"type":"git",
|
||||
"url":"https://github.com/node-red/node-red.git"
|
||||
"name": "node-red",
|
||||
"version": "0.20.0-beta.2",
|
||||
"description": "A visual tool for wiring the Internet of Things",
|
||||
"homepage": "http://nodered.org",
|
||||
"license": "Apache-2.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/node-red/node-red.git"
|
||||
},
|
||||
"main" : "red/red.js",
|
||||
"scripts" : {
|
||||
"start": "node red.js",
|
||||
"private": "true",
|
||||
"scripts": {
|
||||
"start": "node packages/node_modules/node-red/red.js",
|
||||
"test": "grunt",
|
||||
"build": "grunt build"
|
||||
},
|
||||
"bin" : {
|
||||
"node-red": "./red.js",
|
||||
"node-red-pi": "bin/node-red-pi"
|
||||
"build": "grunt build",
|
||||
"docs": "grunt docs"
|
||||
},
|
||||
"contributors": [
|
||||
{"name": "Nick O'Leary"},
|
||||
{"name": "Dave Conway-Jones"}
|
||||
],
|
||||
"keywords": [
|
||||
"editor", "messaging", "iot", "flow"
|
||||
{
|
||||
"name": "Nick O'Leary"
|
||||
},
|
||||
{
|
||||
"name": "Dave Conway-Jones"
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"basic-auth": "1.1.0",
|
||||
"ajv": "6.6.1",
|
||||
"basic-auth": "2.0.1",
|
||||
"bcryptjs": "2.4.3",
|
||||
"body-parser": "1.17.2",
|
||||
"cheerio":"0.22.0",
|
||||
"clone": "2.1.1",
|
||||
"body-parser": "1.18.3",
|
||||
"cheerio": "0.22.0",
|
||||
"clone": "2.1.2",
|
||||
"cookie": "0.3.1",
|
||||
"cookie-parser": "1.4.3",
|
||||
"cors":"2.8.3",
|
||||
"cron":"1.2.1",
|
||||
"express": "4.15.3",
|
||||
"follow-redirects":"1.2.4",
|
||||
"fs-extra": "1.0.0",
|
||||
"fs.notify":"0.0.4",
|
||||
"hash-sum":"1.0.2",
|
||||
"i18next":"1.10.6",
|
||||
"is-utf8":"0.2.1",
|
||||
"js-yaml": "3.8.4",
|
||||
"json-stringify-safe":"5.0.1",
|
||||
"jsonata":"1.2.6",
|
||||
"media-typer": "0.3.0",
|
||||
"mqtt": "2.9.0",
|
||||
"multer": "1.3.0",
|
||||
"mustache": "2.3.0",
|
||||
"nopt": "3.0.6",
|
||||
"oauth2orize":"1.8.0",
|
||||
"on-headers":"1.0.1",
|
||||
"passport":"0.3.2",
|
||||
"passport-http-bearer":"1.0.1",
|
||||
"passport-oauth2-client-password":"0.1.2",
|
||||
"raw-body":"2.2.0",
|
||||
"semver": "5.3.0",
|
||||
"sentiment":"2.1.0",
|
||||
"uglify-js":"3.0.20",
|
||||
"cors": "2.8.5",
|
||||
"cron": "1.5.1",
|
||||
"denque": "1.4.0",
|
||||
"express": "4.16.4",
|
||||
"express-session": "1.15.6",
|
||||
"fs-extra": "7.0.1",
|
||||
"fs.notify": "0.0.4",
|
||||
"hash-sum": "1.0.2",
|
||||
"https-proxy-agent": "2.2.1",
|
||||
"i18next": "12.1.0",
|
||||
"is-utf8": "0.2.1",
|
||||
"js-yaml": "3.12.0",
|
||||
"json-stringify-safe": "5.0.1",
|
||||
"jsonata": "1.5.4",
|
||||
"media-typer": "1.0.1",
|
||||
"memorystore": "1.6.0",
|
||||
"micromatch": "3.1.10",
|
||||
"mime": "2.4.0",
|
||||
"mqtt": "2.18.8",
|
||||
"multer": "1.4.1",
|
||||
"mustache": "3.0.1",
|
||||
"node-red-node-email": "1.0.*",
|
||||
"node-red-node-feedparser": "^0.1.14",
|
||||
"node-red-node-rbe": "0.2.*",
|
||||
"node-red-node-sentiment": "^0.1.0",
|
||||
"node-red-node-tail": "^0.0.1",
|
||||
"node-red-node-twitter": "^1.1.0",
|
||||
"nopt": "4.0.1",
|
||||
"oauth2orize": "1.11.0",
|
||||
"on-headers": "1.0.1",
|
||||
"passport": "0.4.0",
|
||||
"passport-http-bearer": "1.0.1",
|
||||
"passport-oauth2-client-password": "0.1.2",
|
||||
"raw-body": "2.3.3",
|
||||
"request": "2.88.0",
|
||||
"semver": "5.6.0",
|
||||
"sentiment": "2.1.0",
|
||||
"uglify-js": "3.4.9",
|
||||
"when": "3.7.8",
|
||||
"ws": "1.1.1",
|
||||
"xml2js":"0.4.17",
|
||||
"node-red-node-feedparser":"0.1.*",
|
||||
"node-red-node-email":"0.1.*",
|
||||
"node-red-node-twitter":"0.1.*",
|
||||
"node-red-node-rbe":"0.1.*"
|
||||
"ws": "1.1.5",
|
||||
"xml2js": "0.4.19"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"bcrypt":"~1.0.1"
|
||||
"bcrypt": "~2.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"grunt": "~1.0.1",
|
||||
"chromedriver": "2.43.1",
|
||||
"grunt": "~1.0.3",
|
||||
"grunt-chmod": "~1.1.1",
|
||||
"grunt-cli": "~1.2.0",
|
||||
"grunt-concurrent":"~2.3.1",
|
||||
"grunt-contrib-clean":"~1.1.0",
|
||||
"grunt-cli": "~1.3.2",
|
||||
"grunt-concurrent": "~2.3.1",
|
||||
"grunt-contrib-clean": "~1.1.0",
|
||||
"grunt-contrib-compress": "~1.4.0",
|
||||
"grunt-contrib-concat":"~1.0.1",
|
||||
"grunt-contrib-concat": "~1.0.1",
|
||||
"grunt-contrib-copy": "~1.0.0",
|
||||
"grunt-contrib-jshint": "~1.1.0",
|
||||
"grunt-contrib-uglify": "~3.0.1",
|
||||
"grunt-contrib-watch":"~1.0.0",
|
||||
"grunt-jsonlint":"~1.1.0",
|
||||
"grunt-contrib-uglify": "~3.4.0",
|
||||
"grunt-contrib-watch": "~1.1.0",
|
||||
"grunt-jsdoc": "^2.2.1",
|
||||
"grunt-jsdoc-to-markdown": "^4.0.0",
|
||||
"grunt-jsonlint": "~1.1.0",
|
||||
"grunt-mkdir": "~1.0.0",
|
||||
"grunt-mocha-istanbul": "5.0.2",
|
||||
"grunt-nodemon":"~0.4.2",
|
||||
"grunt-sass":"~1.2.1",
|
||||
"grunt-nodemon": "~0.4.2",
|
||||
"grunt-npm-command": "~0.1.2",
|
||||
"grunt-sass": "~2.0.0",
|
||||
"grunt-simple-mocha": "~0.4.1",
|
||||
"grunt-webdriver": "^2.0.3",
|
||||
"http-proxy": "^1.16.2",
|
||||
"istanbul": "0.4.5",
|
||||
"mocha": "~3.4.2",
|
||||
"minami": "1.2.3",
|
||||
"mocha": "^5.2.0",
|
||||
"mosca": "^2.8.3",
|
||||
"should": "^8.4.0",
|
||||
"sinon": "1.17.7",
|
||||
"supertest": "3.0.0"
|
||||
"stoppable": "^1.1.0",
|
||||
"supertest": "3.3.0",
|
||||
"wdio-chromedriver-service": "^0.1.5",
|
||||
"wdio-mocha-framework": "^0.6.4",
|
||||
"wdio-spec-reporter": "^0.1.5",
|
||||
"webdriverio": "^4.14.1",
|
||||
"node-red-node-test-helper": "node-red/node-red-node-test-helper",
|
||||
"jsdoc-nr-template": "node-red/jsdoc-nr-template"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
"node": ">=8"
|
||||
}
|
||||
}
|
||||
|
||||
2
packages/node_modules/@node-red/editor-api/.npmignore
vendored
Normal file
2
packages/node_modules/@node-red/editor-api/.npmignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
src
|
||||
docs
|
||||
178
packages/node_modules/@node-red/editor-api/LICENSE
vendored
Normal file
178
packages/node_modules/@node-red/editor-api/LICENSE
vendored
Normal file
@@ -0,0 +1,178 @@
|
||||
Copyright JS Foundation and other contributors, http://js.foundation
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
12
packages/node_modules/@node-red/editor-api/README.md
vendored
Normal file
12
packages/node_modules/@node-red/editor-api/README.md
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
@node-red/editor-api
|
||||
====================
|
||||
|
||||
Node-RED editor api module.
|
||||
|
||||
This provides an Express application that can be used to serve the Node-RED
|
||||
editor.
|
||||
|
||||
|
||||
### Source
|
||||
|
||||
The main Node-RED modules are maintained as a monorepo on [GitHub](https://github.com/node-red/node-red).
|
||||
56
packages/node_modules/@node-red/editor-api/lib/admin/context.js
vendored
Normal file
56
packages/node_modules/@node-red/editor-api/lib/admin/context.js
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
var apiUtils = require("../util");
|
||||
|
||||
var runtimeAPI;
|
||||
|
||||
|
||||
module.exports = {
|
||||
init: function(_runtimeAPI) {
|
||||
runtimeAPI = _runtimeAPI;
|
||||
},
|
||||
|
||||
get: function(req,res) {
|
||||
var opts = {
|
||||
user: req.user,
|
||||
scope: req.params.scope,
|
||||
id: req.params.id,
|
||||
key: req.params[0],
|
||||
store: req.query['store']
|
||||
}
|
||||
runtimeAPI.context.getValue(opts).then(function(result) {
|
||||
res.json(result);
|
||||
}).catch(function(err) {
|
||||
apiUtils.rejectHandler(req,res,err);
|
||||
})
|
||||
},
|
||||
|
||||
delete: function(req,res) {
|
||||
var opts = {
|
||||
user: req.user,
|
||||
scope: req.params.scope,
|
||||
id: req.params.id,
|
||||
key: req.params[0],
|
||||
store: req.query['store']
|
||||
}
|
||||
runtimeAPI.context.delete(opts).then(function(result) {
|
||||
res.status(204).end();
|
||||
}).catch(function(err) {
|
||||
apiUtils.rejectHandler(req,res,err);
|
||||
})
|
||||
}
|
||||
}
|
||||
69
packages/node_modules/@node-red/editor-api/lib/admin/flow.js
vendored
Normal file
69
packages/node_modules/@node-red/editor-api/lib/admin/flow.js
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
/**
|
||||
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
var runtimeAPI;
|
||||
var apiUtils = require("../util");
|
||||
|
||||
module.exports = {
|
||||
init: function(_runtimeAPI) {
|
||||
runtimeAPI = _runtimeAPI;
|
||||
},
|
||||
get: function(req,res) {
|
||||
var opts = {
|
||||
user: req.user,
|
||||
id: req.params.id
|
||||
}
|
||||
runtimeAPI.flows.getFlow(opts).then(function(result) {
|
||||
return res.json(result);
|
||||
}).catch(function(err) {
|
||||
apiUtils.rejectHandler(req,res,err);
|
||||
})
|
||||
},
|
||||
post: function(req,res) {
|
||||
var opts = {
|
||||
user: req.user,
|
||||
flow: req.body
|
||||
}
|
||||
runtimeAPI.flows.addFlow(opts).then(function(id) {
|
||||
return res.json({id:id});
|
||||
}).catch(function(err) {
|
||||
apiUtils.rejectHandler(req,res,err);
|
||||
})
|
||||
},
|
||||
put: function(req,res) {
|
||||
var opts = {
|
||||
user: req.user,
|
||||
id: req.params.id,
|
||||
flow: req.body
|
||||
}
|
||||
runtimeAPI.flows.updateFlow(opts).then(function(id) {
|
||||
return res.json({id:id});
|
||||
}).catch(function(err) {
|
||||
apiUtils.rejectHandler(req,res,err);
|
||||
})
|
||||
},
|
||||
delete: function(req,res) {
|
||||
var opts = {
|
||||
user: req.user,
|
||||
id: req.params.id
|
||||
}
|
||||
runtimeAPI.flows.deleteFlow(opts).then(function() {
|
||||
res.status(204).end();
|
||||
}).catch(function(err) {
|
||||
apiUtils.rejectHandler(req,res,err);
|
||||
})
|
||||
}
|
||||
}
|
||||
70
packages/node_modules/@node-red/editor-api/lib/admin/flows.js
vendored
Normal file
70
packages/node_modules/@node-red/editor-api/lib/admin/flows.js
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
/**
|
||||
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
var runtimeAPI;
|
||||
var apiUtils = require("../util");
|
||||
|
||||
module.exports = {
|
||||
init: function(_runtimeAPI) {
|
||||
runtimeAPI = _runtimeAPI;
|
||||
},
|
||||
get: function(req,res) {
|
||||
var version = req.get("Node-RED-API-Version")||"v1";
|
||||
if (!/^v[12]$/.test(version)) {
|
||||
return res.status(400).json({code:"invalid_api_version", message:"Invalid API Version requested"});
|
||||
}
|
||||
var opts = {
|
||||
user: req.user
|
||||
}
|
||||
runtimeAPI.flows.getFlows(opts).then(function(result) {
|
||||
if (version === "v1") {
|
||||
res.json(result.flows);
|
||||
} else if (version === "v2") {
|
||||
res.json(result);
|
||||
}
|
||||
}).catch(function(err) {
|
||||
apiUtils.rejectHandler(req,res,err);
|
||||
})
|
||||
},
|
||||
post: function(req,res) {
|
||||
var version = req.get("Node-RED-API-Version")||"v1";
|
||||
if (!/^v[12]$/.test(version)) {
|
||||
return res.status(400).json({code:"invalid_api_version", message:"Invalid API Version requested"});
|
||||
}
|
||||
var opts = {
|
||||
user: req.user,
|
||||
deploymentType: req.get("Node-RED-Deployment-Type")||"full"
|
||||
}
|
||||
|
||||
if (opts.deploymentType !== 'reload') {
|
||||
if (version === "v1") {
|
||||
opts.flows = {flows: req.body}
|
||||
} else {
|
||||
opts.flows = req.body;
|
||||
}
|
||||
}
|
||||
|
||||
runtimeAPI.flows.setFlows(opts).then(function(result) {
|
||||
if (version === "v1") {
|
||||
res.status(204).end();
|
||||
} else {
|
||||
res.json(result);
|
||||
}
|
||||
}).catch(function(err) {
|
||||
apiUtils.rejectHandler(req,res,err);
|
||||
})
|
||||
}
|
||||
}
|
||||
72
packages/node_modules/@node-red/editor-api/lib/admin/index.js
vendored
Normal file
72
packages/node_modules/@node-red/editor-api/lib/admin/index.js
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
/**
|
||||
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
var express = require("express");
|
||||
|
||||
var nodes = require("./nodes");
|
||||
var flows = require("./flows");
|
||||
var flow = require("./flow");
|
||||
var context = require("./context");
|
||||
var auth = require("../auth");
|
||||
|
||||
var apiUtil = require("../util");
|
||||
|
||||
module.exports = {
|
||||
init: function(runtimeAPI) {
|
||||
flows.init(runtimeAPI);
|
||||
flow.init(runtimeAPI);
|
||||
nodes.init(runtimeAPI);
|
||||
context.init(runtimeAPI);
|
||||
|
||||
var needsPermission = auth.needsPermission;
|
||||
|
||||
var adminApp = express();
|
||||
|
||||
// Flows
|
||||
adminApp.get("/flows",needsPermission("flows.read"),flows.get,apiUtil.errorHandler);
|
||||
adminApp.post("/flows",needsPermission("flows.write"),flows.post,apiUtil.errorHandler);
|
||||
|
||||
// Flow
|
||||
adminApp.get("/flow/:id",needsPermission("flows.read"),flow.get,apiUtil.errorHandler);
|
||||
adminApp.post("/flow",needsPermission("flows.write"),flow.post,apiUtil.errorHandler);
|
||||
adminApp.delete("/flow/:id",needsPermission("flows.write"),flow.delete,apiUtil.errorHandler);
|
||||
adminApp.put("/flow/:id",needsPermission("flows.write"),flow.put,apiUtil.errorHandler);
|
||||
|
||||
// Nodes
|
||||
adminApp.get("/nodes",needsPermission("nodes.read"),nodes.getAll,apiUtil.errorHandler);
|
||||
adminApp.post("/nodes",needsPermission("nodes.write"),nodes.post,apiUtil.errorHandler);
|
||||
adminApp.get(/\/nodes\/messages/,needsPermission("nodes.read"),nodes.getModuleCatalogs,apiUtil.errorHandler);
|
||||
adminApp.get(/\/nodes\/((@[^\/]+\/)?[^\/]+\/[^\/]+)\/messages/,needsPermission("nodes.read"),nodes.getModuleCatalog,apiUtil.errorHandler);
|
||||
adminApp.get(/\/nodes\/((@[^\/]+\/)?[^\/]+)$/,needsPermission("nodes.read"),nodes.getModule,apiUtil.errorHandler);
|
||||
adminApp.put(/\/nodes\/((@[^\/]+\/)?[^\/]+)$/,needsPermission("nodes.write"),nodes.putModule,apiUtil.errorHandler);
|
||||
adminApp.delete(/\/nodes\/((@[^\/]+\/)?[^\/]+)$/,needsPermission("nodes.write"),nodes.delete,apiUtil.errorHandler);
|
||||
adminApp.get(/\/nodes\/((@[^\/]+\/)?[^\/]+)\/([^\/]+)$/,needsPermission("nodes.read"),nodes.getSet,apiUtil.errorHandler);
|
||||
adminApp.put(/\/nodes\/((@[^\/]+\/)?[^\/]+)\/([^\/]+)$/,needsPermission("nodes.write"),nodes.putSet,apiUtil.errorHandler);
|
||||
|
||||
// Context
|
||||
adminApp.get("/context/:scope(global)",needsPermission("context.read"),context.get,apiUtil.errorHandler);
|
||||
adminApp.get("/context/:scope(global)/*",needsPermission("context.read"),context.get,apiUtil.errorHandler);
|
||||
adminApp.get("/context/:scope(node|flow)/:id",needsPermission("context.read"),context.get,apiUtil.errorHandler);
|
||||
adminApp.get("/context/:scope(node|flow)/:id/*",needsPermission("context.read"),context.get,apiUtil.errorHandler);
|
||||
|
||||
// adminApp.delete("/context/:scope(global)",needsPermission("context.write"),context.delete,apiUtil.errorHandler);
|
||||
adminApp.delete("/context/:scope(global)/*",needsPermission("context.write"),context.delete,apiUtil.errorHandler);
|
||||
// adminApp.delete("/context/:scope(node|flow)/:id",needsPermission("context.write"),context.delete,apiUtil.errorHandler);
|
||||
adminApp.delete("/context/:scope(node|flow)/:id/*",needsPermission("context.write"),context.delete,apiUtil.errorHandler);
|
||||
|
||||
return adminApp;
|
||||
}
|
||||
}
|
||||
173
packages/node_modules/@node-red/editor-api/lib/admin/nodes.js
vendored
Normal file
173
packages/node_modules/@node-red/editor-api/lib/admin/nodes.js
vendored
Normal file
@@ -0,0 +1,173 @@
|
||||
/**
|
||||
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
var apiUtils = require("../util");
|
||||
|
||||
var runtimeAPI;
|
||||
|
||||
module.exports = {
|
||||
init: function(_runtimeAPI) {
|
||||
runtimeAPI = _runtimeAPI;
|
||||
},
|
||||
getAll: function(req,res) {
|
||||
var opts = {
|
||||
user: req.user
|
||||
}
|
||||
if (req.get("accept") == "application/json") {
|
||||
runtimeAPI.nodes.getNodeList(opts).then(function(list) {
|
||||
res.json(list);
|
||||
})
|
||||
} else {
|
||||
opts.lang = apiUtils.determineLangFromHeaders(req.acceptsLanguages());
|
||||
runtimeAPI.nodes.getNodeConfigs(opts).then(function(configs) {
|
||||
res.send(configs);
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
post: function(req,res) {
|
||||
var opts = {
|
||||
user: req.user,
|
||||
module: req.body.module,
|
||||
version: req.body.version
|
||||
}
|
||||
runtimeAPI.nodes.addModule(opts).then(function(info) {
|
||||
res.json(info);
|
||||
}).catch(function(err) {
|
||||
apiUtils.rejectHandler(req,res,err);
|
||||
})
|
||||
},
|
||||
|
||||
delete: function(req,res) {
|
||||
var opts = {
|
||||
user: req.user,
|
||||
module: req.params[0]
|
||||
}
|
||||
runtimeAPI.nodes.removeModule(opts).then(function() {
|
||||
res.status(204).end();
|
||||
}).catch(function(err) {
|
||||
apiUtils.rejectHandler(req,res,err);
|
||||
})
|
||||
},
|
||||
|
||||
getSet: function(req,res) {
|
||||
var opts = {
|
||||
user: req.user,
|
||||
id: req.params[0] + "/" + req.params[2]
|
||||
}
|
||||
if (req.get("accept") === "application/json") {
|
||||
runtimeAPI.nodes.getNodeInfo(opts).then(function(result) {
|
||||
res.send(result);
|
||||
}).catch(function(err) {
|
||||
apiUtils.rejectHandler(req,res,err);
|
||||
})
|
||||
} else {
|
||||
opts.lang = apiUtils.determineLangFromHeaders(req.acceptsLanguages());
|
||||
runtimeAPI.nodes.getNodeConfig(opts).then(function(result) {
|
||||
return res.send(result);
|
||||
}).catch(function(err) {
|
||||
apiUtils.rejectHandler(req,res,err);
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
getModule: function(req,res) {
|
||||
var opts = {
|
||||
user: req.user,
|
||||
module: req.params[0]
|
||||
}
|
||||
runtimeAPI.nodes.getModuleInfo(opts).then(function(result) {
|
||||
res.send(result);
|
||||
}).catch(function(err) {
|
||||
apiUtils.rejectHandler(req,res,err);
|
||||
})
|
||||
},
|
||||
|
||||
putSet: function(req,res) {
|
||||
var body = req.body;
|
||||
if (!body.hasOwnProperty("enabled")) {
|
||||
// log.audit({event: "nodes.module.set",error:"invalid_request"},req);
|
||||
res.status(400).json({code:"invalid_request", message:"Invalid request"});
|
||||
return;
|
||||
}
|
||||
var opts = {
|
||||
user: req.user,
|
||||
id: req.params[0] + "/" + req.params[2],
|
||||
enabled: body.enabled
|
||||
}
|
||||
runtimeAPI.nodes.setNodeSetState(opts).then(function(result) {
|
||||
res.send(result);
|
||||
}).catch(function(err) {
|
||||
apiUtils.rejectHandler(req,res,err);
|
||||
})
|
||||
},
|
||||
|
||||
putModule: function(req,res) {
|
||||
var body = req.body;
|
||||
if (!body.hasOwnProperty("enabled")) {
|
||||
// log.audit({event: "nodes.module.set",error:"invalid_request"},req);
|
||||
res.status(400).json({code:"invalid_request", message:"Invalid request"});
|
||||
return;
|
||||
}
|
||||
var opts = {
|
||||
user: req.user,
|
||||
module: req.params[0],
|
||||
enabled: body.enabled
|
||||
}
|
||||
runtimeAPI.nodes.setModuleState(opts).then(function(result) {
|
||||
res.send(result);
|
||||
}).catch(function(err) {
|
||||
apiUtils.rejectHandler(req,res,err);
|
||||
})
|
||||
|
||||
},
|
||||
|
||||
getModuleCatalog: function(req,res) {
|
||||
var opts = {
|
||||
user: req.user,
|
||||
module: req.params[0],
|
||||
lang: req.query.lng
|
||||
}
|
||||
runtimeAPI.nodes.getModuleCatalog(opts).then(function(result) {
|
||||
res.json(result);
|
||||
}).catch(function(err) {
|
||||
console.log(err.stack);
|
||||
apiUtils.rejectHandler(req,res,err);
|
||||
})
|
||||
},
|
||||
|
||||
getModuleCatalogs: function(req,res) {
|
||||
var opts = {
|
||||
user: req.user,
|
||||
lang: req.query.lng
|
||||
}
|
||||
runtimeAPI.nodes.getModuleCatalogs(opts).then(function(result) {
|
||||
res.json(result);
|
||||
}).catch(function(err) {
|
||||
console.log(err.stack);
|
||||
apiUtils.rejectHandler(req,res,err);
|
||||
})
|
||||
},
|
||||
|
||||
getIcons: function(req,res) {
|
||||
var opts = {
|
||||
user: req.user
|
||||
}
|
||||
runtimeAPI.nodes.getIconList(opts).then(function(list) {
|
||||
res.json(list);
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -13,8 +13,6 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
var when = require("when");
|
||||
|
||||
var clients = [
|
||||
{id:"node-red-editor",secret:"not_available"},
|
||||
@@ -25,9 +23,9 @@ module.exports = {
|
||||
get: function(id) {
|
||||
for (var i=0;i<clients.length;i++) {
|
||||
if (clients[i].id == id) {
|
||||
return when.resolve(clients[i]);
|
||||
return Promise.resolve(clients[i]);
|
||||
}
|
||||
}
|
||||
return when.resolve(null);
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
}
|
||||
@@ -22,10 +22,10 @@ var Tokens = require("./tokens");
|
||||
var Users = require("./users");
|
||||
var permissions = require("./permissions");
|
||||
|
||||
var theme = require("../theme");
|
||||
var theme = require("../editor/theme");
|
||||
|
||||
var settings = null;
|
||||
var log = null
|
||||
var log = require("@node-red/util").log; // TODO: separate module
|
||||
|
||||
|
||||
passport.use(strategies.bearerStrategy.BearerStrategy);
|
||||
@@ -36,13 +36,12 @@ var server = oauth2orize.createServer();
|
||||
|
||||
server.exchange(oauth2orize.exchange.password(strategies.passwordTokenExchange));
|
||||
|
||||
function init(runtime) {
|
||||
settings = runtime.settings;
|
||||
log = runtime.log;
|
||||
function init(_settings,storage) {
|
||||
settings = _settings;
|
||||
if (settings.adminAuth) {
|
||||
Users.init(settings.adminAuth);
|
||||
Tokens.init(settings.adminAuth,runtime.storage);
|
||||
strategies.init(runtime);
|
||||
var mergedAdminAuth = Object.assign({}, settings.adminAuth, settings.adminAuth.module);
|
||||
Users.init(mergedAdminAuth);
|
||||
Tokens.init(mergedAdminAuth,storage);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,21 +80,24 @@ function getToken(req,res,next) {
|
||||
function login(req,res) {
|
||||
var response = {};
|
||||
if (settings.adminAuth) {
|
||||
if (settings.adminAuth.type === "credentials") {
|
||||
var mergedAdminAuth = Object.assign({}, settings.adminAuth, settings.adminAuth.module);
|
||||
if (mergedAdminAuth.type === "credentials") {
|
||||
response = {
|
||||
"type":"credentials",
|
||||
"prompts":[{id:"username",type:"text",label:"Username"},{id:"password",type:"password",label:"Password"}]
|
||||
"prompts":[{id:"username",type:"text",label:"user.username"},{id:"password",type:"password",label:"user.password"}]
|
||||
}
|
||||
} else if (settings.adminAuth.type === "strategy") {
|
||||
} else if (mergedAdminAuth.type === "strategy") {
|
||||
|
||||
var urlPrefix = (settings.httpAdminRoot==='/')?"":settings.httpAdminRoot;
|
||||
response = {
|
||||
"type":"strategy",
|
||||
"prompts":[{type:"button",label:settings.adminAuth.strategy.label, url:"/auth/strategy"}]
|
||||
"prompts":[{type:"button",label:mergedAdminAuth.strategy.label, url: urlPrefix + "auth/strategy"}]
|
||||
}
|
||||
if (settings.adminAuth.strategy.icon) {
|
||||
response.prompts[0].icon = settings.adminAuth.strategy.icon;
|
||||
if (mergedAdminAuth.strategy.icon) {
|
||||
response.prompts[0].icon = mergedAdminAuth.strategy.icon;
|
||||
}
|
||||
if (settings.adminAuth.strategy.image) {
|
||||
response.prompts[0].image = theme.serveFile('/login/',settings.adminAuth.strategy.image);
|
||||
if (mergedAdminAuth.strategy.image) {
|
||||
response.prompts[0].image = theme.serveFile('/login/',mergedAdminAuth.strategy.image);
|
||||
}
|
||||
}
|
||||
if (theme.context().login && theme.context().login.image) {
|
||||
@@ -133,6 +135,71 @@ function completeVerify(profile,done) {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function genericStrategy(adminApp,strategy) {
|
||||
var crypto = require("crypto")
|
||||
var session = require('express-session')
|
||||
var MemoryStore = require('memorystore')(session)
|
||||
|
||||
adminApp.use(session({
|
||||
// As the session is only used across the life-span of an auth
|
||||
// hand-shake, we can use a instance specific random string
|
||||
secret: crypto.randomBytes(20).toString('hex'),
|
||||
resave: false,
|
||||
saveUninitialized: false,
|
||||
store: new MemoryStore({
|
||||
checkPeriod: 86400000 // prune expired entries every 24h
|
||||
})
|
||||
}));
|
||||
//TODO: all passport references ought to be in ./auth
|
||||
adminApp.use(passport.initialize());
|
||||
adminApp.use(passport.session());
|
||||
|
||||
var options = strategy.options;
|
||||
|
||||
passport.use(new strategy.strategy(options,
|
||||
function() {
|
||||
var originalDone = arguments[arguments.length-1];
|
||||
if (options.verify) {
|
||||
var args = Array.from(arguments);
|
||||
args[args.length-1] = function(err,profile) {
|
||||
if (err) {
|
||||
return originalDone(err);
|
||||
} else {
|
||||
return completeVerify(profile,originalDone);
|
||||
}
|
||||
};
|
||||
options.verify.apply(null,args);
|
||||
} else {
|
||||
var profile = arguments[arguments.length - 2];
|
||||
return completeVerify(profile,originalDone);
|
||||
}
|
||||
|
||||
}
|
||||
));
|
||||
|
||||
adminApp.get('/auth/strategy',
|
||||
passport.authenticate(strategy.name, {session:false, failureRedirect: settings.httpAdminRoot }),
|
||||
completeGenerateStrategyAuth
|
||||
);
|
||||
|
||||
var callbackMethodFunc = adminApp.get;
|
||||
if (/^post$/i.test(options.callbackMethod)) {
|
||||
callbackMethodFunc = adminApp.post;
|
||||
}
|
||||
callbackMethodFunc('/auth/strategy/callback',
|
||||
passport.authenticate(strategy.name, {session:false, failureRedirect: settings.httpAdminRoot }),
|
||||
completeGenerateStrategyAuth
|
||||
);
|
||||
|
||||
}
|
||||
function completeGenerateStrategyAuth(req,res) {
|
||||
var tokens = req.user.tokens;
|
||||
delete req.user.tokens;
|
||||
// Successful authentication, redirect home.
|
||||
res.redirect(settings.httpAdminRoot + '?access_token='+tokens.accessToken);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
init: init,
|
||||
needsPermission: needsPermission,
|
||||
@@ -147,53 +214,5 @@ module.exports = {
|
||||
},
|
||||
login: login,
|
||||
revoke: revoke,
|
||||
genericStrategy: function(adminApp,strategy) {
|
||||
var session = require('express-session');
|
||||
var crypto = require("crypto");
|
||||
adminApp.use(session({
|
||||
// As the session is only used across the life-span of an auth
|
||||
// hand-shake, we can use a instance specific random string
|
||||
secret: crypto.randomBytes(20).toString('hex'),
|
||||
resave: false,
|
||||
saveUninitialized:false
|
||||
}));
|
||||
//TODO: all passport references ought to be in ./auth
|
||||
adminApp.use(passport.initialize());
|
||||
adminApp.use(passport.session());
|
||||
|
||||
var options = strategy.options;
|
||||
|
||||
passport.use(new strategy.strategy(options,
|
||||
function() {
|
||||
var originalDone = arguments[arguments.length-1];
|
||||
if (options.verify) {
|
||||
var args = Array.prototype.slice.call(arguments);
|
||||
args[args.length-1] = function(err,profile) {
|
||||
if (err) {
|
||||
return originalDone(err);
|
||||
} else {
|
||||
return completeVerify(profile,originalDone);
|
||||
}
|
||||
};
|
||||
options.verify.apply(null,args);
|
||||
} else {
|
||||
var profile = arguments[arguments.length - 2];
|
||||
return completeVerify(profile,originalDone);
|
||||
}
|
||||
|
||||
}
|
||||
));
|
||||
|
||||
adminApp.get('/auth/strategy', passport.authenticate(strategy.name));
|
||||
adminApp.get('/auth/strategy/callback',
|
||||
passport.authenticate(strategy.name, {session:false, failureRedirect: '/' }),
|
||||
function(req, res) {
|
||||
var tokens = req.user.tokens;
|
||||
delete req.user.tokens;
|
||||
// Successful authentication, redirect home.
|
||||
res.redirect('/?access_token='+tokens.accessToken);
|
||||
}
|
||||
);
|
||||
|
||||
}
|
||||
genericStrategy: genericStrategy
|
||||
}
|
||||
@@ -26,7 +26,7 @@ var Users = require("./users");
|
||||
var Clients = require("./clients");
|
||||
var permissions = require("./permissions");
|
||||
|
||||
var log;
|
||||
var log = require("@node-red/util").log; // TODO: separate module
|
||||
|
||||
var bearerStrategy = function (accessToken, done) {
|
||||
// is this a valid token?
|
||||
@@ -124,9 +124,6 @@ AnonymousStrategy.prototype.authenticate = function(req) {
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
init: function(runtime) {
|
||||
log = runtime.log;
|
||||
},
|
||||
bearerStrategy: bearerStrategy,
|
||||
clientPasswordStrategy: clientPasswordStrategy,
|
||||
passwordTokenExchange: passwordTokenExchange,
|
||||
@@ -14,8 +14,6 @@
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
var when = require("when");
|
||||
|
||||
function generateToken(length) {
|
||||
var c = "ABCDEFGHIJKLMNOPQRSTUZWXYZabcdefghijklmnopqrstuvwxyz1234567890";
|
||||
var token = [];
|
||||
@@ -27,29 +25,43 @@ function generateToken(length) {
|
||||
|
||||
|
||||
var storage;
|
||||
|
||||
var sessionExpiryTime
|
||||
|
||||
var sessions = {};
|
||||
|
||||
var loadedSessions = null;
|
||||
var apiAccessTokens;
|
||||
var sessionExpiryListeners = [];
|
||||
var expiryTimeout;
|
||||
|
||||
function expireSessions() {
|
||||
if (expiryTimeout) {
|
||||
clearTimeout(expiryTimeout);
|
||||
expiryTimeout = null;
|
||||
}
|
||||
var nextExpiry = Number.MAX_SAFE_INTEGER;
|
||||
var now = Date.now();
|
||||
var modified = false;
|
||||
for (var t in sessions) {
|
||||
if (sessions.hasOwnProperty(t)) {
|
||||
var session = sessions[t];
|
||||
if (!session.hasOwnProperty("expires") || session.expires < now) {
|
||||
sessionExpiryListeners.forEach(listener => { listener(session) })
|
||||
delete sessions[t];
|
||||
modified = true;
|
||||
} else {
|
||||
if (session.expires < nextExpiry) {
|
||||
nextExpiry = session.expires;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (nextExpiry < Number.MAX_SAFE_INTEGER) {
|
||||
// Allow 5 seconds grace
|
||||
expiryTimeout = setTimeout(expireSessions,(nextExpiry - Date.now()) + 5000)
|
||||
}
|
||||
if (modified) {
|
||||
return storage.saveSessions(sessions);
|
||||
} else {
|
||||
return when.resolve();
|
||||
return Promise.resolve();
|
||||
}
|
||||
}
|
||||
function loadSessions() {
|
||||
@@ -65,20 +77,40 @@ function loadSessions() {
|
||||
module.exports = {
|
||||
init: function(adminAuthSettings, _storage) {
|
||||
storage = _storage;
|
||||
|
||||
sessionExpiryListeners = [];
|
||||
|
||||
sessionExpiryTime = adminAuthSettings.sessionExpiryTime || 604800; // 1 week in seconds
|
||||
// At this point, storage will not have been initialised, so defer loading
|
||||
// the sessions until there's a request for them.
|
||||
loadedSessions = null;
|
||||
return when.resolve();
|
||||
|
||||
apiAccessTokens = {};
|
||||
if ( Array.isArray(adminAuthSettings.tokens) ) {
|
||||
apiAccessTokens = adminAuthSettings.tokens.reduce(function(prev, current) {
|
||||
prev[current.token] = {
|
||||
user: current.user,
|
||||
scope: current.scope
|
||||
};
|
||||
return prev;
|
||||
}, {});
|
||||
}
|
||||
return Promise.resolve();
|
||||
},
|
||||
get: function(token) {
|
||||
return loadSessions().then(function() {
|
||||
if (sessions[token]) {
|
||||
if (sessions[token].expires < Date.now()) {
|
||||
return expireSessions().then(function() { return null });
|
||||
var info = apiAccessTokens[token] || null;
|
||||
|
||||
if (info) {
|
||||
return Promise.resolve(info);
|
||||
} else {
|
||||
if (sessions[token]) {
|
||||
if (sessions[token].expires < Date.now()) {
|
||||
return expireSessions().then(function() { return null });
|
||||
}
|
||||
}
|
||||
return Promise.resolve(sessions[token]);
|
||||
}
|
||||
return when.resolve(sessions[token]);
|
||||
});
|
||||
},
|
||||
create: function(user,client,scope) {
|
||||
@@ -95,6 +127,11 @@ module.exports = {
|
||||
expires: accessTokenExpiresAt
|
||||
};
|
||||
sessions[accessToken] = session;
|
||||
|
||||
if (!expiryTimeout) {
|
||||
expiryTimeout = setTimeout(expireSessions,(accessTokenExpiresAt - Date.now()) + 5000)
|
||||
}
|
||||
|
||||
return storage.saveSessions(sessions).then(function() {
|
||||
return {
|
||||
accessToken: accessToken,
|
||||
@@ -108,5 +145,8 @@ module.exports = {
|
||||
delete sessions[token];
|
||||
return storage.saveSessions(sessions);
|
||||
});
|
||||
},
|
||||
onSessionExpiry: function(callback) {
|
||||
sessionExpiryListeners.push(callback);
|
||||
}
|
||||
}
|
||||
@@ -14,13 +14,12 @@
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
var when = require("when");
|
||||
var util = require("util");
|
||||
var clone = require("clone");
|
||||
var bcrypt;
|
||||
try { bcrypt = require('bcrypt'); }
|
||||
catch(e) { bcrypt = require('bcryptjs'); }
|
||||
var users = {};
|
||||
var passwords = {};
|
||||
var defaultUser = null;
|
||||
|
||||
function authenticate() {
|
||||
@@ -28,31 +27,33 @@ function authenticate() {
|
||||
if (typeof username !== 'string') {
|
||||
username = username.username;
|
||||
}
|
||||
var user = users[username];
|
||||
if (user) {
|
||||
if (arguments.length === 2) {
|
||||
// Username/password authentication
|
||||
var password = arguments[1];
|
||||
return when.promise(function(resolve,reject) {
|
||||
bcrypt.compare(password, passwords[username], function(err, res) {
|
||||
resolve(res?user:null);
|
||||
const args = Array.from(arguments);
|
||||
return api.get(username).then(function(user) {
|
||||
if (user) {
|
||||
if (args.length === 2) {
|
||||
// Username/password authentication
|
||||
var password = args[1];
|
||||
return new Promise(function(resolve,reject) {
|
||||
bcrypt.compare(password, user.password, function(err, res) {
|
||||
resolve(res?cleanUser(user):null);
|
||||
});
|
||||
});
|
||||
});
|
||||
} else {
|
||||
// Try to extract common profile information
|
||||
if (arguments[0].hasOwnProperty('photos') && arguments[0].photos.length > 0) {
|
||||
user.image = arguments[0].photos[0].value;
|
||||
} else {
|
||||
// Try to extract common profile information
|
||||
if (args[0].hasOwnProperty('photos') && args[0].photos.length > 0) {
|
||||
user.image = args[0].photos[0].value;
|
||||
}
|
||||
return cleanUser(user);
|
||||
}
|
||||
return when.resolve(user);
|
||||
}
|
||||
}
|
||||
return when.resolve(null);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
function get(username) {
|
||||
return when.resolve(users[username]);
|
||||
return Promise.resolve(users[username]);
|
||||
}
|
||||
function getDefaultUser() {
|
||||
return when.resolve(null);
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
|
||||
var api = {
|
||||
@@ -63,7 +64,6 @@ var api = {
|
||||
|
||||
function init(config) {
|
||||
users = {};
|
||||
passwords = {};
|
||||
defaultUser = null;
|
||||
if (config.type == "credentials" || config.type == "strategy") {
|
||||
if (config.users) {
|
||||
@@ -77,11 +77,7 @@ function init(config) {
|
||||
}
|
||||
for (var i=0;i<us.length;i++) {
|
||||
var u = us[i];
|
||||
users[u.username] = {
|
||||
"username":u.username,
|
||||
"permissions":u.permissions
|
||||
};
|
||||
passwords[u.username] = u.password;
|
||||
users[u.username] = clone(u);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -90,13 +86,17 @@ function init(config) {
|
||||
} else {
|
||||
api.authenticate = authenticate;
|
||||
}
|
||||
} else {
|
||||
api.get = get;
|
||||
api.authenticate = authenticate;
|
||||
api.default = api.default;
|
||||
}
|
||||
if (config.default) {
|
||||
if (typeof config.default === "function") {
|
||||
api.default = config.default;
|
||||
} else {
|
||||
api.default = function() {
|
||||
return when.resolve({
|
||||
return Promise.resolve({
|
||||
"anonymous": true,
|
||||
"permissions":config.default.permissions
|
||||
});
|
||||
@@ -106,10 +106,17 @@ function init(config) {
|
||||
api.default = getDefaultUser;
|
||||
}
|
||||
}
|
||||
function cleanUser(user) {
|
||||
if (user && user.hasOwnProperty('password')) {
|
||||
user = clone(user);
|
||||
delete user.password;
|
||||
}
|
||||
return user;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
init: init,
|
||||
get: function(username) { return api.get(username) },
|
||||
get: function(username) { return api.get(username).then(cleanUser)},
|
||||
authenticate: function() { return api.authenticate.apply(null, arguments) },
|
||||
default: function() { return api.default(); }
|
||||
};
|
||||
252
packages/node_modules/@node-red/editor-api/lib/editor/comms.js
vendored
Normal file
252
packages/node_modules/@node-red/editor-api/lib/editor/comms.js
vendored
Normal file
@@ -0,0 +1,252 @@
|
||||
/**
|
||||
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
var ws = require("ws");
|
||||
|
||||
var log = require("@node-red/util").log; // TODO: separate module
|
||||
var Tokens;
|
||||
var Users;
|
||||
var Permissions;
|
||||
|
||||
var server;
|
||||
var settings;
|
||||
var runtimeAPI;
|
||||
|
||||
var wsServer;
|
||||
var activeConnections = [];
|
||||
|
||||
var anonymousUser;
|
||||
|
||||
var retained = {};
|
||||
|
||||
var heartbeatTimer;
|
||||
var lastSentTime;
|
||||
|
||||
function init(_server,_settings,_runtimeAPI) {
|
||||
server = _server;
|
||||
settings = _settings;
|
||||
runtimeAPI = _runtimeAPI;
|
||||
Tokens = require("../auth/tokens");
|
||||
Tokens.onSessionExpiry(handleSessionExpiry);
|
||||
Users = require("../auth/users");
|
||||
Permissions = require("../auth/permissions");
|
||||
|
||||
}
|
||||
function handleSessionExpiry(session) {
|
||||
activeConnections.forEach(connection => {
|
||||
if (connection.token === session.accessToken) {
|
||||
connection.ws.send(JSON.stringify({auth:"fail"}));
|
||||
connection.ws.close();
|
||||
}
|
||||
})
|
||||
}
|
||||
function generateSession(length) {
|
||||
var c = "ABCDEFGHIJKLMNOPQRSTUZWXYZabcdefghijklmnopqrstuvwxyz1234567890";
|
||||
var token = [];
|
||||
for (var i=0;i<length;i++) {
|
||||
token.push(c[Math.floor(Math.random()*c.length)]);
|
||||
}
|
||||
return token.join("");
|
||||
}
|
||||
|
||||
function CommsConnection(ws) {
|
||||
this.session = generateSession(32);
|
||||
this.ws = ws;
|
||||
this.stack = [];
|
||||
this.user = null;
|
||||
this.lastSentTime = 0;
|
||||
var self = this;
|
||||
|
||||
log.audit({event: "comms.open"});
|
||||
log.trace("comms.open "+self.session);
|
||||
var pendingAuth = (settings.adminAuth != null);
|
||||
|
||||
if (!pendingAuth) {
|
||||
addActiveConnection(self);
|
||||
}
|
||||
ws.on('close',function() {
|
||||
log.audit({event: "comms.close",user:self.user, session: self.session});
|
||||
log.trace("comms.close "+self.session);
|
||||
removeActiveConnection(self);
|
||||
});
|
||||
ws.on('message', function(data,flags) {
|
||||
var msg = null;
|
||||
try {
|
||||
msg = JSON.parse(data);
|
||||
} catch(err) {
|
||||
log.trace("comms received malformed message : "+err.toString());
|
||||
return;
|
||||
}
|
||||
if (!pendingAuth) {
|
||||
if (msg.subscribe) {
|
||||
self.subscribe(msg.subscribe);
|
||||
// handleRemoteSubscription(ws,msg.subscribe);
|
||||
}
|
||||
} else {
|
||||
var completeConnection = function(userScope,session,sendAck) {
|
||||
try {
|
||||
if (!userScope || !Permissions.hasPermission(userScope,"status.read")) {
|
||||
ws.send(JSON.stringify({auth:"fail"}));
|
||||
ws.close();
|
||||
} else {
|
||||
pendingAuth = false;
|
||||
addActiveConnection(self);
|
||||
self.token = msg.auth;
|
||||
if (sendAck) {
|
||||
ws.send(JSON.stringify({auth:"ok"}));
|
||||
}
|
||||
}
|
||||
} catch(err) {
|
||||
console.log(err.stack);
|
||||
// Just in case the socket closes before we attempt
|
||||
// to send anything.
|
||||
}
|
||||
}
|
||||
if (msg.auth) {
|
||||
Tokens.get(msg.auth).then(function(client) {
|
||||
if (client) {
|
||||
Users.get(client.user).then(function(user) {
|
||||
if (user) {
|
||||
self.user = user;
|
||||
log.audit({event: "comms.auth",user:self.user});
|
||||
completeConnection(client.scope,msg.auth,true);
|
||||
} else {
|
||||
log.audit({event: "comms.auth.fail"});
|
||||
completeConnection(null,null,false);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
log.audit({event: "comms.auth.fail"});
|
||||
completeConnection(null,null,false);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (anonymousUser) {
|
||||
log.audit({event: "comms.auth",user:anonymousUser});
|
||||
self.user = anonymousUser;
|
||||
completeConnection(anonymousUser.permissions,null,false);
|
||||
//TODO: duplicated code - pull non-auth message handling out
|
||||
if (msg.subscribe) {
|
||||
self.subscribe(msg.subscribe);
|
||||
}
|
||||
} else {
|
||||
log.audit({event: "comms.auth.fail"});
|
||||
completeConnection(null,null,false);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
ws.on('error', function(err) {
|
||||
log.warn(log._("comms.error",{message:err.toString()}));
|
||||
});
|
||||
}
|
||||
|
||||
CommsConnection.prototype.send = function(topic,data) {
|
||||
var self = this;
|
||||
if (topic && data) {
|
||||
this.stack.push({topic:topic,data:data});
|
||||
}
|
||||
if (!this._xmitTimer) {
|
||||
this._xmitTimer = setTimeout(function() {
|
||||
try {
|
||||
self.ws.send(JSON.stringify(self.stack));
|
||||
self.lastSentTime = Date.now();
|
||||
} catch(err) {
|
||||
removeActiveConnection(self);
|
||||
log.warn(log._("comms.error-send",{message:err.toString()}));
|
||||
}
|
||||
delete self._xmitTimer;
|
||||
self.stack = [];
|
||||
},50);
|
||||
}
|
||||
}
|
||||
|
||||
CommsConnection.prototype.subscribe = function(topic) {
|
||||
runtimeAPI.comms.subscribe({
|
||||
user: this.user,
|
||||
client: this,
|
||||
topic: topic
|
||||
})
|
||||
}
|
||||
|
||||
function start() {
|
||||
if (!settings.disableEditor) {
|
||||
Users.default().then(function(_anonymousUser) {
|
||||
anonymousUser = _anonymousUser;
|
||||
var webSocketKeepAliveTime = settings.webSocketKeepAliveTime || 15000;
|
||||
var path = settings.httpAdminRoot || "/";
|
||||
path = (path.slice(0,1) != "/" ? "/":"") + path + (path.slice(-1) == "/" ? "":"/") + "comms";
|
||||
wsServer = new ws.Server({
|
||||
server:server,
|
||||
path:path,
|
||||
// Disable the deflate option due to this issue
|
||||
// https://github.com/websockets/ws/pull/632
|
||||
// that is fixed in the 1.x release of the ws module
|
||||
// that we cannot currently pickup as it drops node 0.10 support
|
||||
//perMessageDeflate: false
|
||||
});
|
||||
|
||||
wsServer.on('connection',function(ws) {
|
||||
var commsConnection = new CommsConnection(ws);
|
||||
});
|
||||
|
||||
|
||||
wsServer.on('error', function(err) {
|
||||
log.warn(log._("comms.error-server",{message:err.toString()}));
|
||||
});
|
||||
|
||||
lastSentTime = Date.now();
|
||||
|
||||
heartbeatTimer = setInterval(function() {
|
||||
var now = Date.now();
|
||||
if (now-lastSentTime > webSocketKeepAliveTime) {
|
||||
activeConnections.forEach(connection => connection.send("hb",lastSentTime));
|
||||
}
|
||||
}, webSocketKeepAliveTime);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function stop() {
|
||||
if (heartbeatTimer) {
|
||||
clearInterval(heartbeatTimer);
|
||||
heartbeatTimer = null;
|
||||
}
|
||||
if (wsServer) {
|
||||
wsServer.close();
|
||||
wsServer = null;
|
||||
}
|
||||
}
|
||||
|
||||
function addActiveConnection(connection) {
|
||||
activeConnections.push(connection);
|
||||
runtimeAPI.comms.addConnection({client: connection});
|
||||
}
|
||||
function removeActiveConnection(connection) {
|
||||
for (var i=0;i<activeConnections.length;i++) {
|
||||
if (activeConnections[i] === connection) {
|
||||
activeConnections.splice(i,1);
|
||||
runtimeAPI.comms.removeConnection({client:connection})
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
init:init,
|
||||
start:start,
|
||||
stop:stop
|
||||
}
|
||||
36
packages/node_modules/@node-red/editor-api/lib/editor/credentials.js
vendored
Normal file
36
packages/node_modules/@node-red/editor-api/lib/editor/credentials.js
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
var runtimeAPI;
|
||||
var apiUtils = require("../util");
|
||||
|
||||
module.exports = {
|
||||
init: function(_runtimeAPI) {
|
||||
runtimeAPI = _runtimeAPI
|
||||
},
|
||||
get: function (req, res) {
|
||||
var opts = {
|
||||
user: req.user,
|
||||
type: req.params.type,
|
||||
id: req.params.id
|
||||
}
|
||||
runtimeAPI.flows.getNodeCredentials(opts).then(function(result) {
|
||||
res.json(result);
|
||||
}).catch(function(err) {
|
||||
apiUtils.rejectHandler(req,res,err);
|
||||
})
|
||||
}
|
||||
}
|
||||
129
packages/node_modules/@node-red/editor-api/lib/editor/index.js
vendored
Normal file
129
packages/node_modules/@node-red/editor-api/lib/editor/index.js
vendored
Normal file
@@ -0,0 +1,129 @@
|
||||
/**
|
||||
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* 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");
|
||||
var nodes = require("../admin/nodes"); // TODO: move /icons into here
|
||||
var needsPermission;
|
||||
var runtimeAPI;
|
||||
var log = require("@node-red/util").log; // TODO: separate module
|
||||
var i18n = require("@node-red/util").i18n; // TODO: separate module
|
||||
|
||||
var apiUtil = require("../util");
|
||||
|
||||
var ensureRuntimeStarted = function(req,res,next) {
|
||||
runtimeAPI.isStarted().then( started => {
|
||||
if (!started) {
|
||||
log.error("Node-RED runtime not started");
|
||||
res.status(503).send("Not started");
|
||||
} else {
|
||||
next()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
init: function(server, settings, _runtimeAPI) {
|
||||
runtimeAPI = _runtimeAPI;
|
||||
needsPermission = auth.needsPermission;
|
||||
if (!settings.disableEditor) {
|
||||
info.init(runtimeAPI);
|
||||
comms.init(server,settings,runtimeAPI);
|
||||
|
||||
var ui = require("./ui");
|
||||
|
||||
ui.init(runtimeAPI);
|
||||
|
||||
var editorApp = express();
|
||||
if (settings.requireHttps === true) {
|
||||
editorApp.enable('trust proxy');
|
||||
editorApp.use(function (req, res, next) {
|
||||
if (req.secure) {
|
||||
next();
|
||||
} else {
|
||||
res.redirect('https://' + req.headers.host + req.originalUrl);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (settings.httpServerOptions) {
|
||||
for (var eOption in settings.httpServerOptions) {
|
||||
editorApp.set(eOption, settings.httpServerOptions[eOption]);
|
||||
}
|
||||
}
|
||||
editorApp.get("/",ensureRuntimeStarted,ui.ensureSlash,ui.editor);
|
||||
|
||||
editorApp.get("/icons",needsPermission("nodes.read"),nodes.getIcons,apiUtil.errorHandler);
|
||||
editorApp.get("/icons/:module/:icon",ui.icon);
|
||||
editorApp.get("/icons/:scope/:module/:icon",ui.icon);
|
||||
|
||||
var theme = require("./theme");
|
||||
theme.init(settings);
|
||||
editorApp.use("/theme",theme.app());
|
||||
editorApp.use("/",ui.editorResources);
|
||||
|
||||
//Projects
|
||||
var projects = require("./projects");
|
||||
projects.init(runtimeAPI);
|
||||
editorApp.use("/projects",projects.app());
|
||||
|
||||
// Locales
|
||||
var locales = require("./locales");
|
||||
locales.init(runtimeAPI);
|
||||
editorApp.get(/locales\/(.+)\/?$/,locales.get,apiUtil.errorHandler);
|
||||
|
||||
// Library
|
||||
var library = require("./library");
|
||||
library.init(runtimeAPI);
|
||||
editorApp.get("/library/flows",needsPermission("library.read"),library.getAll,apiUtil.errorHandler);
|
||||
editorApp.get(/library\/([^\/]+)(?:$|\/(.*))/,needsPermission("library.read"),library.getEntry);
|
||||
editorApp.post(/library\/([^\/]+)\/(.*)/,needsPermission("library.write"),library.saveEntry);
|
||||
|
||||
|
||||
// Credentials
|
||||
var credentials = require("./credentials");
|
||||
credentials.init(runtimeAPI);
|
||||
editorApp.get('/credentials/:type/:id', needsPermission("credentials.read"),credentials.get,apiUtil.errorHandler);
|
||||
|
||||
// Settings
|
||||
editorApp.get("/settings",needsPermission("settings.read"),info.runtimeSettings,apiUtil.errorHandler);
|
||||
// User Settings
|
||||
editorApp.get("/settings/user",needsPermission("settings.read"),info.userSettings,apiUtil.errorHandler);
|
||||
// User Settings
|
||||
editorApp.post("/settings/user",needsPermission("settings.write"),info.updateUserSettings,apiUtil.errorHandler);
|
||||
// SSH keys
|
||||
editorApp.use("/settings/user/keys",needsPermission("settings.write"),info.sshkeys());
|
||||
|
||||
return editorApp;
|
||||
}
|
||||
},
|
||||
start: function() {
|
||||
var catalogPath = path.resolve(path.join(path.dirname(require.resolve("@node-red/editor-client")),"locales"));
|
||||
return i18n.registerMessageCatalogs([
|
||||
{namespace: "editor", dir: catalogPath, file:"editor.json"},
|
||||
{namespace: "jsonata", dir: catalogPath, file:"jsonata.json"},
|
||||
{namespace: "infotips", dir: catalogPath, file:"infotips.json"}
|
||||
]).then(function(){
|
||||
comms.start();
|
||||
});
|
||||
},
|
||||
stop: comms.stop
|
||||
}
|
||||
83
packages/node_modules/@node-red/editor-api/lib/editor/library.js
vendored
Normal file
83
packages/node_modules/@node-red/editor-api/lib/editor/library.js
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
/**
|
||||
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
var apiUtils = require("../util");
|
||||
var fs = require('fs');
|
||||
var fspath = require('path');
|
||||
var when = require('when');
|
||||
|
||||
var runtimeAPI;
|
||||
|
||||
module.exports = {
|
||||
init: function(_runtimeAPI) {
|
||||
runtimeAPI = _runtimeAPI;
|
||||
},
|
||||
|
||||
getAll: function(req,res) {
|
||||
var opts = {
|
||||
user: req.user,
|
||||
type: 'flows'
|
||||
}
|
||||
runtimeAPI.library.getEntries(opts).then(function(result) {
|
||||
res.json(result);
|
||||
}).catch(function(err) {
|
||||
apiUtils.rejectHandler(req,res,err);
|
||||
});
|
||||
},
|
||||
getEntry: function(req,res) {
|
||||
var opts = {
|
||||
user: req.user,
|
||||
type: req.params[0],
|
||||
path: req.params[1]||""
|
||||
}
|
||||
runtimeAPI.library.getEntry(opts).then(function(result) {
|
||||
if (typeof result === "string") {
|
||||
if (opts.type === 'flows') {
|
||||
res.writeHead(200, {'Content-Type': 'application/json'});
|
||||
} else {
|
||||
res.writeHead(200, {'Content-Type': 'text/plain'});
|
||||
}
|
||||
res.write(result);
|
||||
res.end();
|
||||
} else {
|
||||
res.json(result);
|
||||
}
|
||||
}).catch(function(err) {
|
||||
apiUtils.rejectHandler(req,res,err);
|
||||
});
|
||||
},
|
||||
saveEntry: function(req,res) {
|
||||
var opts = {
|
||||
user: req.user,
|
||||
type: req.params[0],
|
||||
path: req.params[1]||""
|
||||
}
|
||||
// TODO: horrible inconsistencies between flows and all other types
|
||||
if (opts.type === "flows") {
|
||||
opts.meta = {};
|
||||
opts.body = JSON.stringify(req.body);
|
||||
} else {
|
||||
opts.meta = req.body;
|
||||
opts.body = opts.meta.text;
|
||||
delete opts.meta.text;
|
||||
}
|
||||
runtimeAPI.library.saveEntry(opts).then(function(result) {
|
||||
res.status(204).end();
|
||||
}).catch(function(err) {
|
||||
apiUtils.rejectHandler(req,res,err);
|
||||
});
|
||||
}
|
||||
}
|
||||
53
packages/node_modules/@node-red/editor-api/lib/editor/locales.js
vendored
Normal file
53
packages/node_modules/@node-red/editor-api/lib/editor/locales.js
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* 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
|
||||
|
||||
var runtimeAPI;
|
||||
|
||||
function loadResource(lang, namespace) {
|
||||
var catalog = i18n.i.getResourceBundle(lang, namespace);
|
||||
if (!catalog) {
|
||||
var parts = lang.split("-");
|
||||
if (parts.length == 2) {
|
||||
var new_lang = parts[0];
|
||||
return i18n.i.getResourceBundle(new_lang, namespace);
|
||||
}
|
||||
}
|
||||
return catalog;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
init: function(_runtimeAPI) {
|
||||
runtimeAPI = _runtimeAPI;
|
||||
},
|
||||
get: function(req,res) {
|
||||
var namespace = req.params[0];
|
||||
var lngs = req.query.lng;
|
||||
namespace = namespace.replace(/\.json$/,"");
|
||||
var lang = req.query.lng; //apiUtil.determineLangFromHeaders(req.acceptsLanguages() || []);
|
||||
var prevLang = i18n.i.language;
|
||||
// Trigger a load from disk of the language if it is not the default
|
||||
i18n.i.changeLanguage(lang, function(){
|
||||
var catalog = loadResource(lang, namespace);
|
||||
res.json(catalog||{});
|
||||
});
|
||||
i18n.i.changeLanguage(prevLang);
|
||||
}
|
||||
}
|
||||
511
packages/node_modules/@node-red/editor-api/lib/editor/projects.js
vendored
Normal file
511
packages/node_modules/@node-red/editor-api/lib/editor/projects.js
vendored
Normal file
@@ -0,0 +1,511 @@
|
||||
/**
|
||||
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
var express = require("express");
|
||||
var apiUtils = require("../util");
|
||||
|
||||
var runtimeAPI;
|
||||
var needsPermission = require("../auth").needsPermission;
|
||||
|
||||
function listProjects(req,res) {
|
||||
var opts = {
|
||||
user: req.user
|
||||
}
|
||||
runtimeAPI.projects.listProjects(opts).then(function(result) {
|
||||
res.json(result);
|
||||
}).catch(function(err) {
|
||||
apiUtils.rejectHandler(req,res,err);
|
||||
});
|
||||
}
|
||||
function getProject(req,res) {
|
||||
var opts = {
|
||||
user: req.user,
|
||||
id: req.params.id
|
||||
}
|
||||
runtimeAPI.projects.getProject(opts).then(function(data) {
|
||||
if (data) {
|
||||
res.json(data);
|
||||
} else {
|
||||
res.status(404).end();
|
||||
}
|
||||
}).catch(function(err) {
|
||||
apiUtils.rejectHandler(req,res,err);
|
||||
})
|
||||
}
|
||||
function getProjectStatus(req,res) {
|
||||
var opts = {
|
||||
user: req.user,
|
||||
id: req.params.id,
|
||||
remote: req.query.remote
|
||||
}
|
||||
runtimeAPI.projects.getStatus(opts).then(function(data){
|
||||
if (data) {
|
||||
res.json(data);
|
||||
} else {
|
||||
res.status(404).end();
|
||||
}
|
||||
}).catch(function(err) {
|
||||
apiUtils.rejectHandler(req,res,err);
|
||||
})
|
||||
}
|
||||
function getProjectRemotes(req,res) {
|
||||
var opts = {
|
||||
user: req.user,
|
||||
id: req.params.id
|
||||
}
|
||||
runtimeAPI.projects.getRemotes(opts).then(function(data) {
|
||||
res.json(data);
|
||||
}).catch(function(err) {
|
||||
apiUtils.rejectHandler(req,res,err);
|
||||
})
|
||||
}
|
||||
module.exports = {
|
||||
init: function(_runtimeAPI) {
|
||||
runtimeAPI = _runtimeAPI;
|
||||
},
|
||||
app: function() {
|
||||
var app = express();
|
||||
|
||||
app.use(function(req,res,next) {
|
||||
runtimeAPI.projects.available().then(function(available) {
|
||||
if (!available) {
|
||||
res.status(404).end();
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
// Projects
|
||||
|
||||
// List all projects
|
||||
app.get("/", needsPermission("projects.read"),listProjects);
|
||||
|
||||
// Create project
|
||||
app.post("/", needsPermission("projects.write"), function(req,res) {
|
||||
var opts = {
|
||||
user: req.user,
|
||||
project: req.body
|
||||
}
|
||||
runtimeAPI.projects.createProject(opts).then(function(result) {
|
||||
res.json(result);
|
||||
}).catch(function(err) {
|
||||
apiUtils.rejectHandler(req,res,err);
|
||||
});
|
||||
});
|
||||
|
||||
// Update a project
|
||||
app.put("/:id", needsPermission("projects.write"), function(req,res) {
|
||||
var opts = {
|
||||
user: req.user,
|
||||
id: req.params.id,
|
||||
project: req.body
|
||||
}
|
||||
|
||||
if (req.body.active) {
|
||||
runtimeAPI.projects.setActiveProject(opts).then(function() {
|
||||
listProjects(req,res);
|
||||
}).catch(function(err) {
|
||||
apiUtils.rejectHandler(req,res,err);
|
||||
})
|
||||
} else if (req.body.initialise) {
|
||||
runtimeAPI.projects.initialiseProject(opts).then(function() {
|
||||
getProject(req,res);
|
||||
}).catch(function(err) {
|
||||
apiUtils.rejectHandler(req,res,err);
|
||||
})
|
||||
} else if (req.body.hasOwnProperty('credentialSecret') ||
|
||||
req.body.hasOwnProperty('description') ||
|
||||
req.body.hasOwnProperty('dependencies')||
|
||||
req.body.hasOwnProperty('summary') ||
|
||||
req.body.hasOwnProperty('files') ||
|
||||
req.body.hasOwnProperty('git')) {
|
||||
runtimeAPI.projects.updateProject(opts).then(function() {
|
||||
getProject(req,res);
|
||||
}).catch(function(err) {
|
||||
apiUtils.rejectHandler(req,res,err);
|
||||
})
|
||||
} else {
|
||||
res.status(400).json({error:"unexpected_error", message:"invalid_request"});
|
||||
}
|
||||
});
|
||||
|
||||
// Get project metadata
|
||||
app.get("/:id", needsPermission("projects.read"), getProject);
|
||||
|
||||
// Delete project
|
||||
app.delete("/:id", needsPermission("projects.write"), function(req,res) {
|
||||
var opts = {
|
||||
user: req.user,
|
||||
id: req.params.id
|
||||
}
|
||||
runtimeAPI.projects.deleteProject(opts).then(function() {
|
||||
res.status(204).end();
|
||||
}).catch(function(err) {
|
||||
apiUtils.rejectHandler(req,res,err);
|
||||
})
|
||||
});
|
||||
|
||||
|
||||
// Get project status - files, commit counts, branch info
|
||||
app.get("/:id/status", needsPermission("projects.read"), getProjectStatus);
|
||||
|
||||
|
||||
// Project file listing
|
||||
app.get("/:id/files", needsPermission("projects.read"), function(req,res) {
|
||||
var opts = {
|
||||
user: req.user,
|
||||
id: req.params.id
|
||||
}
|
||||
runtimeAPI.projects.getFiles(opts).then(function(data) {
|
||||
res.json(data);
|
||||
}).catch(function(err) {
|
||||
apiUtils.rejectHandler(req,res,err);
|
||||
})
|
||||
|
||||
});
|
||||
|
||||
|
||||
// Get file content in a given tree (index/stage)
|
||||
app.get("/:id/files/:treeish/*", needsPermission("projects.read"), function(req,res) {
|
||||
var opts = {
|
||||
user: req.user,
|
||||
id: req.params.id,
|
||||
path: req.params[0],
|
||||
tree: req.params.treeish
|
||||
}
|
||||
runtimeAPI.projects.getFile(opts).then(function(data) {
|
||||
res.json({content:data});
|
||||
}).catch(function(err) {
|
||||
apiUtils.rejectHandler(req,res,err);
|
||||
})
|
||||
});
|
||||
|
||||
// Revert a file
|
||||
app.delete("/:id/files/_/*", needsPermission("projects.write"), function(req,res) {
|
||||
var opts = {
|
||||
user: req.user,
|
||||
id: req.params.id,
|
||||
path: req.params[0]
|
||||
}
|
||||
|
||||
runtimeAPI.projects.revertFile(opts).then(function() {
|
||||
res.status(204).end();
|
||||
}).catch(function(err) {
|
||||
apiUtils.rejectHandler(req,res,err);
|
||||
})
|
||||
});
|
||||
|
||||
// Stage a file
|
||||
app.post("/:id/stage/*", needsPermission("projects.write"), function(req,res) {
|
||||
var opts = {
|
||||
user: req.user,
|
||||
id: req.params.id,
|
||||
path: req.params[0]
|
||||
}
|
||||
runtimeAPI.projects.stageFile(opts).then(function() {
|
||||
getProjectStatus(req,res);
|
||||
}).catch(function(err) {
|
||||
apiUtils.rejectHandler(req,res,err);
|
||||
})
|
||||
});
|
||||
|
||||
// Stage multiple files
|
||||
app.post("/:id/stage", needsPermission("projects.write"), function(req,res) {
|
||||
var opts = {
|
||||
user: req.user,
|
||||
id: req.params.id,
|
||||
path: req.body.files
|
||||
}
|
||||
runtimeAPI.projects.stageFile(opts).then(function() {
|
||||
getProjectStatus(req,res);
|
||||
}).catch(function(err) {
|
||||
apiUtils.rejectHandler(req,res,err);
|
||||
})
|
||||
});
|
||||
|
||||
// Commit changes
|
||||
app.post("/:id/commit", needsPermission("projects.write"), function(req,res) {
|
||||
var opts = {
|
||||
user: req.user,
|
||||
id: req.params.id,
|
||||
message: req.body.message
|
||||
}
|
||||
runtimeAPI.projects.commit(opts).then(function() {
|
||||
getProjectStatus(req,res);
|
||||
}).catch(function(err) {
|
||||
apiUtils.rejectHandler(req,res,err);
|
||||
})
|
||||
});
|
||||
|
||||
// Unstage a file
|
||||
app.delete("/:id/stage/*", needsPermission("projects.write"), function(req,res) {
|
||||
var opts = {
|
||||
user: req.user,
|
||||
id: req.params.id,
|
||||
path: req.params[0]
|
||||
}
|
||||
runtimeAPI.projects.unstageFile(opts).then(function() {
|
||||
getProjectStatus(req,res);
|
||||
}).catch(function(err) {
|
||||
apiUtils.rejectHandler(req,res,err);
|
||||
})
|
||||
});
|
||||
|
||||
// Unstage multiple files
|
||||
app.delete("/:id/stage", needsPermission("projects.write"), function(req, res) {
|
||||
var opts = {
|
||||
user: req.user,
|
||||
id: req.params.id
|
||||
}
|
||||
runtimeAPI.projects.unstageFile(opts).then(function() {
|
||||
getProjectStatus(req,res);
|
||||
}).catch(function(err) {
|
||||
apiUtils.rejectHandler(req,res,err);
|
||||
})
|
||||
});
|
||||
|
||||
// Get a file diff
|
||||
app.get("/:id/diff/:type/*", needsPermission("projects.read"), function(req,res) {
|
||||
var opts = {
|
||||
user: req.user,
|
||||
id: req.params.id,
|
||||
path: req.params[0],
|
||||
type: req.params.type
|
||||
}
|
||||
runtimeAPI.projects.getFileDiff(opts).then(function(data) {
|
||||
res.json({
|
||||
diff: data
|
||||
})
|
||||
}).catch(function(err) {
|
||||
apiUtils.rejectHandler(req,res,err);
|
||||
})
|
||||
});
|
||||
|
||||
// Get a list of commits
|
||||
app.get("/:id/commits", needsPermission("projects.read"), function(req, res) {
|
||||
var opts = {
|
||||
user: req.user,
|
||||
id: req.params.id,
|
||||
limit: req.query.limit || 20,
|
||||
before: req.query.before
|
||||
}
|
||||
runtimeAPI.projects.getCommits(opts).then(function(data) {
|
||||
res.json(data);
|
||||
}).catch(function(err) {
|
||||
apiUtils.rejectHandler(req,res,err);
|
||||
})
|
||||
});
|
||||
|
||||
// Get an individual commit details
|
||||
app.get("/:id/commits/:sha", needsPermission("projects.read"), function(req, res) {
|
||||
var opts = {
|
||||
user: req.user,
|
||||
id: req.params.id,
|
||||
sha: req.params.sha
|
||||
}
|
||||
runtimeAPI.projects.getCommit(opts).then(function(data) {
|
||||
res.json({commit:data});
|
||||
}).catch(function(err) {
|
||||
apiUtils.rejectHandler(req,res,err);
|
||||
})
|
||||
});
|
||||
|
||||
// Push local commits to remote
|
||||
app.post("/:id/push/?*", needsPermission("projects.write"), function(req,res) {
|
||||
var opts = {
|
||||
user: req.user,
|
||||
id: req.params.id,
|
||||
remote: req.params[0],
|
||||
track: req.query.u
|
||||
}
|
||||
runtimeAPI.projects.push(opts).then(function(data) {
|
||||
res.status(204).end();
|
||||
}).catch(function(err) {
|
||||
apiUtils.rejectHandler(req,res,err);
|
||||
})
|
||||
});
|
||||
|
||||
// Pull remote commits
|
||||
app.post("/:id/pull/?*", needsPermission("projects.write"), function(req,res) {
|
||||
var opts = {
|
||||
user: req.user,
|
||||
id: req.params.id,
|
||||
remote: req.params[0],
|
||||
track: req.query.setUpstream,
|
||||
allowUnrelatedHistories: req.query.allowUnrelatedHistories
|
||||
}
|
||||
runtimeAPI.projects.pull(opts).then(function(data) {
|
||||
res.status(204).end();
|
||||
}).catch(function(err) {
|
||||
apiUtils.rejectHandler(req,res,err);
|
||||
})
|
||||
});
|
||||
|
||||
// Abort an ongoing merge
|
||||
app.delete("/:id/merge", needsPermission("projects.write"), function(req, res) {
|
||||
var opts = {
|
||||
user: req.user,
|
||||
id: req.params.id
|
||||
}
|
||||
runtimeAPI.projects.abortMerge(opts).then(function() {
|
||||
res.status(204).end();
|
||||
}).catch(function(err) {
|
||||
apiUtils.rejectHandler(req,res,err);
|
||||
})
|
||||
});
|
||||
|
||||
// Resolve a merge
|
||||
app.post("/:id/resolve/*", needsPermission("projects.write"), function(req, res) {
|
||||
var opts = {
|
||||
user: req.user,
|
||||
id: req.params.id,
|
||||
path: req.params[0],
|
||||
resolution: req.body.resolutions
|
||||
}
|
||||
runtimeAPI.projects.resolveMerge(opts).then(function() {
|
||||
res.status(204).end();
|
||||
}).catch(function(err) {
|
||||
apiUtils.rejectHandler(req,res,err);
|
||||
})
|
||||
});
|
||||
|
||||
// Get a list of local branches
|
||||
app.get("/:id/branches", needsPermission("projects.read"), function(req, res) {
|
||||
var opts = {
|
||||
user: req.user,
|
||||
id: req.params.id,
|
||||
remote: false
|
||||
}
|
||||
runtimeAPI.projects.getBranches(opts).then(function(data) {
|
||||
res.json(data);
|
||||
}).catch(function(err) {
|
||||
apiUtils.rejectHandler(req,res,err);
|
||||
})
|
||||
});
|
||||
|
||||
// Delete a local branch - ?force=true
|
||||
app.delete("/:id/branches/:branchName", needsPermission("projects.write"), function(req, res) {
|
||||
var opts = {
|
||||
user: req.user,
|
||||
id: req.params.id,
|
||||
branch: req.params.branchName,
|
||||
force: !!req.query.force
|
||||
}
|
||||
runtimeAPI.projects.deleteBranch(opts).then(function(data) {
|
||||
res.status(204).end();
|
||||
}).catch(function(err) {
|
||||
apiUtils.rejectHandler(req,res,err);
|
||||
})
|
||||
});
|
||||
|
||||
// Get a list of remote branches
|
||||
app.get("/:id/branches/remote", needsPermission("projects.read"), function(req, res) {
|
||||
var opts = {
|
||||
user: req.user,
|
||||
id: req.params.id,
|
||||
remote: true
|
||||
}
|
||||
runtimeAPI.projects.getBranches(opts).then(function(data) {
|
||||
res.json(data);
|
||||
}).catch(function(err) {
|
||||
apiUtils.rejectHandler(req,res,err);
|
||||
})
|
||||
});
|
||||
|
||||
// Get branch status - commit counts/ahead/behind
|
||||
app.get("/:id/branches/remote/*/status", needsPermission("projects.read"), function(req, res) {
|
||||
var opts = {
|
||||
user: req.user,
|
||||
id: req.params.id,
|
||||
branch: req.params[0]
|
||||
}
|
||||
runtimeAPI.projects.getBranchStatus(opts).then(function(data) {
|
||||
res.json(data);
|
||||
}).catch(function(err) {
|
||||
apiUtils.rejectHandler(req,res,err);
|
||||
})
|
||||
});
|
||||
|
||||
// Set the active local branch
|
||||
app.post("/:id/branches", needsPermission("projects.write"), function(req, res) {
|
||||
var opts = {
|
||||
user: req.user,
|
||||
id: req.params.id,
|
||||
branch: req.body.name,
|
||||
create: req.body.create
|
||||
}
|
||||
runtimeAPI.projects.setBranch(opts).then(function(data) {
|
||||
res.json(data);
|
||||
}).catch(function(err) {
|
||||
apiUtils.rejectHandler(req,res,err);
|
||||
})
|
||||
});
|
||||
|
||||
// Get a list of remotes
|
||||
app.get("/:id/remotes", needsPermission("projects.read"), getProjectRemotes);
|
||||
|
||||
// Add a remote
|
||||
app.post("/:id/remotes", needsPermission("projects.write"), function(req,res) {
|
||||
var opts = {
|
||||
user: req.user,
|
||||
id: req.params.id,
|
||||
remote: req.body
|
||||
}
|
||||
if (/^https?:\/\/[^/]+@/i.test(req.body.url)) {
|
||||
res.status(400).json({error:"unexpected_error", message:"Git http url must not include username/password"});
|
||||
return;
|
||||
}
|
||||
runtimeAPI.projects.addRemote(opts).then(function(data) {
|
||||
getProjectRemotes(req,res);
|
||||
}).catch(function(err) {
|
||||
apiUtils.rejectHandler(req,res,err);
|
||||
})
|
||||
});
|
||||
|
||||
// Delete a remote
|
||||
app.delete("/:id/remotes/:remoteName", needsPermission("projects.write"), function(req, res) {
|
||||
var opts = {
|
||||
user: req.user,
|
||||
id: req.params.id,
|
||||
remote: req.params.remoteName
|
||||
}
|
||||
runtimeAPI.projects.removeRemote(opts).then(function(data) {
|
||||
getProjectRemotes(req,res);
|
||||
}).catch(function(err) {
|
||||
apiUtils.rejectHandler(req,res,err);
|
||||
})
|
||||
});
|
||||
|
||||
// Update a remote
|
||||
app.put("/:id/remotes/:remoteName", needsPermission("projects.write"), function(req,res) {
|
||||
var remote = req.body || {};
|
||||
remote.name = req.params.remoteName;
|
||||
var opts = {
|
||||
user: req.user,
|
||||
id: req.params.id,
|
||||
remote: remote
|
||||
}
|
||||
runtimeAPI.projects.updateRemote(opts).then(function() {
|
||||
res.status(204).end();
|
||||
}).catch(function(err) {
|
||||
apiUtils.rejectHandler(req,res,err);
|
||||
})
|
||||
});
|
||||
|
||||
return app;
|
||||
}
|
||||
}
|
||||
87
packages/node_modules/@node-red/editor-api/lib/editor/settings.js
vendored
Normal file
87
packages/node_modules/@node-red/editor-api/lib/editor/settings.js
vendored
Normal file
@@ -0,0 +1,87 @@
|
||||
/**
|
||||
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
var apiUtils = require("../util");
|
||||
var runtimeAPI;
|
||||
var sshkeys = require("./sshkeys");
|
||||
var theme = require("./theme");
|
||||
var clone = require("clone");
|
||||
|
||||
function extend(target, source) {
|
||||
var keys = Object.keys(source);
|
||||
var i = keys.length;
|
||||
while(i--) {
|
||||
var value = source[keys[i]]
|
||||
var type = typeof value;
|
||||
if (type === 'string' || type === 'number' || type === 'boolean' || Array.isArray(value)) {
|
||||
target[keys[i]] = value;
|
||||
} else if (value === null) {
|
||||
if (target.hasOwnProperty(keys[i])) {
|
||||
delete target[keys[i]];
|
||||
}
|
||||
} else {
|
||||
// Object
|
||||
if (target.hasOwnProperty(keys[i])) {
|
||||
target[keys[i]] = extend(target[keys[i]],value);
|
||||
} else {
|
||||
target[keys[i]] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
init: function(_runtimeAPI) {
|
||||
runtimeAPI = _runtimeAPI;
|
||||
sshkeys.init(runtimeAPI);
|
||||
},
|
||||
runtimeSettings: function(req,res) {
|
||||
var opts = {
|
||||
user: req.user
|
||||
}
|
||||
runtimeAPI.settings.getRuntimeSettings(opts).then(function(result) {
|
||||
var themeSettings = theme.settings();
|
||||
if (themeSettings) {
|
||||
// result.editorTheme may already exist with the palette
|
||||
// disabled. Need to merge that into the receive settings
|
||||
result.editorTheme = extend(clone(themeSettings),result.editorTheme||{});
|
||||
}
|
||||
res.json(result);
|
||||
});
|
||||
},
|
||||
userSettings: function(req, res) {
|
||||
var opts = {
|
||||
user: req.user
|
||||
}
|
||||
runtimeAPI.settings.getUserSettings(opts).then(function(result) {
|
||||
res.json(result);
|
||||
});
|
||||
},
|
||||
updateUserSettings: function(req,res) {
|
||||
var opts = {
|
||||
user: req.user,
|
||||
settings: req.body
|
||||
}
|
||||
runtimeAPI.settings.updateUserSettings(opts).then(function(result) {
|
||||
res.status(204).end();
|
||||
}).catch(function(err) {
|
||||
apiUtils.rejectHandler(req,res,err);
|
||||
});
|
||||
},
|
||||
sshkeys: function() {
|
||||
return sshkeys.app()
|
||||
}
|
||||
}
|
||||
101
packages/node_modules/@node-red/editor-api/lib/editor/sshkeys.js
vendored
Normal file
101
packages/node_modules/@node-red/editor-api/lib/editor/sshkeys.js
vendored
Normal file
@@ -0,0 +1,101 @@
|
||||
/**
|
||||
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
var apiUtils = require("../util");
|
||||
var express = require("express");
|
||||
var runtimeAPI;
|
||||
|
||||
function getUsername(userObj) {
|
||||
var username = '__default';
|
||||
if ( userObj && userObj.name ) {
|
||||
username = userObj.name;
|
||||
}
|
||||
return username;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
init: function(_runtimeAPI) {
|
||||
runtimeAPI = _runtimeAPI;
|
||||
},
|
||||
app: function() {
|
||||
var app = express();
|
||||
|
||||
// List all SSH keys
|
||||
app.get("/", function(req,res) {
|
||||
var opts = {
|
||||
user: req.user
|
||||
}
|
||||
runtimeAPI.settings.getUserKeys(opts).then(function(list) {
|
||||
res.json({
|
||||
keys: list
|
||||
});
|
||||
}).catch(function(err) {
|
||||
apiUtils.rejectHandler(req,res,err);
|
||||
});
|
||||
});
|
||||
|
||||
// Get SSH key detail
|
||||
app.get("/:id", function(req,res) {
|
||||
var opts = {
|
||||
user: req.user,
|
||||
id: req.params.id
|
||||
}
|
||||
runtimeAPI.settings.getUserKey(opts).then(function(data) {
|
||||
res.json({
|
||||
publickey: data
|
||||
});
|
||||
}).catch(function(err) {
|
||||
apiUtils.rejectHandler(req,res,err);
|
||||
});
|
||||
});
|
||||
|
||||
// Generate a SSH key
|
||||
app.post("/", function(req,res) {
|
||||
var opts = {
|
||||
user: req.user,
|
||||
id: req.params.id
|
||||
}
|
||||
// TODO: validate params
|
||||
opts.name = req.body.name;
|
||||
opts.password = req.body.password;
|
||||
opts.comment = req.body.comment;
|
||||
opts.size = req.body.size;
|
||||
|
||||
runtimeAPI.settings.generateUserKey(opts).then(function(name) {
|
||||
res.json({
|
||||
name: name
|
||||
});
|
||||
}).catch(function(err) {
|
||||
apiUtils.rejectHandler(req,res,err);
|
||||
});
|
||||
});
|
||||
|
||||
// Delete a SSH key
|
||||
app.delete("/:id", function(req,res) {
|
||||
var opts = {
|
||||
user: req.user,
|
||||
id: req.params.id
|
||||
}
|
||||
runtimeAPI.settings.removeUserKey(opts).then(function(name) {
|
||||
res.status(204).end();
|
||||
}).catch(function(err) {
|
||||
apiUtils.rejectHandler(req,res,err);
|
||||
});
|
||||
});
|
||||
|
||||
return app;
|
||||
}
|
||||
}
|
||||
@@ -40,7 +40,6 @@ var defaultContext = {
|
||||
var theme = null;
|
||||
var themeContext = clone(defaultContext);
|
||||
var themeSettings = null;
|
||||
var runtime = null;
|
||||
|
||||
var themeApp;
|
||||
|
||||
@@ -67,8 +66,8 @@ function serveFilesFromTheme(themeValue, themeApp, directory) {
|
||||
array = [array];
|
||||
}
|
||||
|
||||
for (i=0;i<array.length;i++) {
|
||||
url = serveFile(themeApp,directory,array[i]);
|
||||
for (var i=0;i<array.length;i++) {
|
||||
var url = serveFile(themeApp,directory,array[i]);
|
||||
if (url) {
|
||||
result.push(url);
|
||||
}
|
||||
@@ -78,12 +77,8 @@ function serveFilesFromTheme(themeValue, themeApp, directory) {
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
init: function(runtime) {
|
||||
var settings = runtime.settings;
|
||||
init: function(settings) {
|
||||
themeContext = clone(defaultContext);
|
||||
if (runtime.version) {
|
||||
themeContext.version = runtime.version();
|
||||
}
|
||||
themeSettings = null;
|
||||
theme = settings.editorTheme || {};
|
||||
},
|
||||
@@ -98,11 +93,11 @@ module.exports = {
|
||||
if (theme.page) {
|
||||
|
||||
themeContext.page.css = serveFilesFromTheme(
|
||||
themeContext.page.css,
|
||||
theme.page.css,
|
||||
themeApp,
|
||||
"/css/")
|
||||
themeContext.page.scripts = serveFilesFromTheme(
|
||||
themeContext.page.scripts,
|
||||
theme.page.scripts,
|
||||
themeApp,
|
||||
"/scripts/")
|
||||
|
||||
@@ -182,6 +177,12 @@ module.exports = {
|
||||
if (theme.hasOwnProperty("palette")) {
|
||||
themeSettings.palette = theme.palette;
|
||||
}
|
||||
|
||||
if (theme.hasOwnProperty("projects")) {
|
||||
themeSettings.projects = theme.projects;
|
||||
}
|
||||
|
||||
|
||||
return themeApp;
|
||||
},
|
||||
context: function() {
|
||||
@@ -17,18 +17,22 @@ var express = require('express');
|
||||
var fs = require("fs");
|
||||
var path = require("path");
|
||||
var Mustache = require("mustache");
|
||||
var mime = require("mime");
|
||||
|
||||
var apiUtils = require("../util");
|
||||
|
||||
var theme = require("./theme");
|
||||
|
||||
var redNodes;
|
||||
|
||||
var templateDir = path.resolve(__dirname+"/../../editor/templates");
|
||||
var runtimeAPI;
|
||||
var editorClientDir = path.dirname(require.resolve("@node-red/editor-client"));
|
||||
var defaultNodeIcon = path.join(editorClientDir,"public","red","images","icons","arrow-in.png");
|
||||
var editorTemplatePath = path.join(editorClientDir,"templates","index.mst");
|
||||
var editorTemplate;
|
||||
|
||||
module.exports = {
|
||||
init: function(runtime) {
|
||||
redNodes = runtime.nodes;
|
||||
editorTemplate = fs.readFileSync(path.join(templateDir,"index.mst"),"utf8");
|
||||
init: function(_runtimeAPI) {
|
||||
runtimeAPI = _runtimeAPI;
|
||||
editorTemplate = fs.readFileSync(editorTemplatePath,"utf8");
|
||||
Mustache.parse(editorTemplate);
|
||||
},
|
||||
|
||||
@@ -46,11 +50,26 @@ module.exports = {
|
||||
var icon = req.params.icon;
|
||||
var scope = req.params.scope;
|
||||
var module = scope ? scope + '/' + req.params.module : req.params.module;
|
||||
var iconPath = redNodes.getNodeIconPath(module,icon);
|
||||
res.sendFile(iconPath);
|
||||
var opts = {
|
||||
user: req.user,
|
||||
module: module,
|
||||
icon: icon
|
||||
}
|
||||
runtimeAPI.nodes.getIcon(opts).then(function(data) {
|
||||
if (data) {
|
||||
var contentType = mime.getType(icon);
|
||||
res.set("Content-Type", contentType);
|
||||
res.send(data);
|
||||
} else {
|
||||
res.sendFile(defaultNodeIcon);
|
||||
}
|
||||
}).catch(function(err) {
|
||||
console.log(err.stack);
|
||||
apiUtils.rejectHandler(req,res,err);
|
||||
})
|
||||
},
|
||||
editor: function(req,res) {
|
||||
res.send(Mustache.render(editorTemplate,theme.context()));
|
||||
},
|
||||
editorResources: express.static(__dirname + '/../../public')
|
||||
editorResources: express.static(path.join(editorClientDir,'public'))
|
||||
};
|
||||
104
packages/node_modules/@node-red/editor-api/lib/index.js
vendored
Normal file
104
packages/node_modules/@node-red/editor-api/lib/index.js
vendored
Normal file
@@ -0,0 +1,104 @@
|
||||
/**
|
||||
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
var express = require("express");
|
||||
var bodyParser = require("body-parser");
|
||||
var util = require('util');
|
||||
var passport = require('passport');
|
||||
var when = require('when');
|
||||
var cors = require('cors');
|
||||
|
||||
var auth = require("./auth");
|
||||
var apiUtil = require("./util");
|
||||
|
||||
var adminApp;
|
||||
var server;
|
||||
var editor;
|
||||
|
||||
function init(settings,_server,storage,runtimeAPI) {
|
||||
server = _server;
|
||||
if (settings.httpAdminRoot !== false) {
|
||||
adminApp = express();
|
||||
|
||||
var cors = require('cors');
|
||||
var corsHandler = cors({
|
||||
origin: "*",
|
||||
methods: "GET,PUT,POST,DELETE"
|
||||
});
|
||||
adminApp.use(corsHandler);
|
||||
|
||||
auth.init(settings,storage);
|
||||
|
||||
var maxApiRequestSize = settings.apiMaxLength || '5mb';
|
||||
adminApp.use(bodyParser.json({limit:maxApiRequestSize}));
|
||||
adminApp.use(bodyParser.urlencoded({limit:maxApiRequestSize,extended:true}));
|
||||
|
||||
adminApp.get("/auth/login",auth.login,apiUtil.errorHandler);
|
||||
if (settings.adminAuth) {
|
||||
if (settings.adminAuth.type === "strategy") {
|
||||
auth.genericStrategy(adminApp,settings.adminAuth.strategy);
|
||||
} else if (settings.adminAuth.type === "credentials") {
|
||||
adminApp.use(passport.initialize());
|
||||
adminApp.post("/auth/token",
|
||||
auth.ensureClientSecret,
|
||||
auth.authenticateClient,
|
||||
auth.getToken,
|
||||
auth.errorHandler
|
||||
);
|
||||
}
|
||||
adminApp.post("/auth/revoke",auth.needsPermission(""),auth.revoke,apiUtil.errorHandler);
|
||||
}
|
||||
|
||||
// Editor
|
||||
if (!settings.disableEditor) {
|
||||
editor = require("./editor");
|
||||
var editorApp = editor.init(server, settings, runtimeAPI);
|
||||
adminApp.use(editorApp);
|
||||
}
|
||||
|
||||
if (settings.httpAdminCors) {
|
||||
var corsHandler = cors(settings.httpAdminCors);
|
||||
adminApp.use(corsHandler);
|
||||
}
|
||||
|
||||
var adminApiApp = require("./admin").init(runtimeAPI);
|
||||
adminApp.use(adminApiApp);
|
||||
} else {
|
||||
adminApp = null;
|
||||
}
|
||||
}
|
||||
function start() {
|
||||
if (editor) {
|
||||
return editor.start();
|
||||
} else {
|
||||
return when.resolve();
|
||||
}
|
||||
}
|
||||
function stop() {
|
||||
if (editor) {
|
||||
editor.stop();
|
||||
}
|
||||
return when.resolve();
|
||||
}
|
||||
module.exports = {
|
||||
init: init,
|
||||
start: start,
|
||||
stop: stop,
|
||||
auth: {
|
||||
needsPermission: auth.needsPermission
|
||||
},
|
||||
get httpAdmin() { return adminApp; }
|
||||
};
|
||||
47
packages/node_modules/@node-red/editor-api/lib/util.js
vendored
Normal file
47
packages/node_modules/@node-red/editor-api/lib/util.js
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
|
||||
var log = require("@node-red/util").log; // TODO: separate module
|
||||
var i18n = require("@node-red/util").i18n; // TODO: separate module
|
||||
|
||||
|
||||
module.exports = {
|
||||
errorHandler: function(err,req,res,next) {
|
||||
if (err.message === "request entity too large") {
|
||||
log.error(err);
|
||||
} else {
|
||||
log.error(err.stack);
|
||||
}
|
||||
log.audit({event: "api.error",error:err.code||"unexpected_error",message:err.toString()},req);
|
||||
res.status(400).json({error:"unexpected_error", message:err.toString()});
|
||||
},
|
||||
|
||||
determineLangFromHeaders: function(acceptedLanguages){
|
||||
var lang = i18n.defaultLang;
|
||||
acceptedLanguages = acceptedLanguages || [];
|
||||
if (acceptedLanguages.length >= 1) {
|
||||
lang = acceptedLanguages[0];
|
||||
}
|
||||
return lang;
|
||||
},
|
||||
rejectHandler: function(req,res,err) {
|
||||
res.status(err.status||500).json({
|
||||
code: err.code||"unexpected_error",
|
||||
message: err.message||err.toString()
|
||||
});
|
||||
}
|
||||
}
|
||||
37
packages/node_modules/@node-red/editor-api/package.json
vendored
Normal file
37
packages/node_modules/@node-red/editor-api/package.json
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"name": "@node-red/editor-api",
|
||||
"version": "0.20.0-beta.2",
|
||||
"license": "Apache-2.0",
|
||||
"main": "./lib/index.js",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/node-red/node-red.git"
|
||||
},
|
||||
"contributors": [
|
||||
{
|
||||
"name": "Nick O'Leary"
|
||||
},
|
||||
{
|
||||
"name": "Dave Conway-Jones"
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"@node-red/util": "0.20.0-beta.2",
|
||||
"@node-red/editor-client": "0.20.0-beta.2",
|
||||
"bcryptjs": "2.4.3",
|
||||
"body-parser": "1.18.3",
|
||||
"clone": "2.1.2",
|
||||
"cors": "2.8.5",
|
||||
"express-session": "1.15.6",
|
||||
"express": "4.16.4",
|
||||
"memorystore": "1.6.0",
|
||||
"mime": "2.4.0",
|
||||
"mustache": "3.0.1",
|
||||
"oauth2orize": "1.11.0",
|
||||
"passport-http-bearer": "1.0.1",
|
||||
"passport-oauth2-client-password": "0.1.2",
|
||||
"passport": "0.4.0",
|
||||
"when": "3.7.8",
|
||||
"ws": "1.1.5"
|
||||
}
|
||||
}
|
||||
2
packages/node_modules/@node-red/editor-client/.npmignore
vendored
Normal file
2
packages/node_modules/@node-red/editor-client/.npmignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
src
|
||||
docs
|
||||
178
packages/node_modules/@node-red/editor-client/LICENSE
vendored
Normal file
178
packages/node_modules/@node-red/editor-client/LICENSE
vendored
Normal file
@@ -0,0 +1,178 @@
|
||||
Copyright JS Foundation and other contributors, http://js.foundation
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
10
packages/node_modules/@node-red/editor-client/README.md
vendored
Normal file
10
packages/node_modules/@node-red/editor-client/README.md
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
@node-red/editor-client
|
||||
====================
|
||||
|
||||
Node-RED editor resources module.
|
||||
|
||||
This provides all of the client-side resources of the Node-RED editor application.
|
||||
|
||||
### Source
|
||||
|
||||
The main Node-RED modules are maintained as a monorepo on [GitHub](https://github.com/node-red/node-red).
|
||||
@@ -13,4 +13,5 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
var RED = {};
|
||||
|
||||
module.exports = false
|
||||
906
packages/node_modules/@node-red/editor-client/locales/en-US/editor.json
vendored
Executable file
906
packages/node_modules/@node-red/editor-client/locales/en-US/editor.json
vendored
Executable file
@@ -0,0 +1,906 @@
|
||||
{
|
||||
"common": {
|
||||
"label": {
|
||||
"name": "Name",
|
||||
"ok": "Ok",
|
||||
"done":"Done",
|
||||
"cancel": "Cancel",
|
||||
"delete": "Delete",
|
||||
"close": "Close",
|
||||
"load": "Load",
|
||||
"save": "Save",
|
||||
"import": "Import",
|
||||
"export": "Export",
|
||||
"back": "Back",
|
||||
"next": "Next",
|
||||
"clone": "Clone project",
|
||||
"cont": "Continue"
|
||||
}
|
||||
},
|
||||
"workspace": {
|
||||
"defaultName": "Flow __number__",
|
||||
"editFlow": "Edit flow: __name__",
|
||||
"confirmDelete": "Confirm delete",
|
||||
"delete": "Are you sure you want to delete '__label__'?",
|
||||
"dropFlowHere": "Drop the flow here",
|
||||
"addFlow": "Add Flow",
|
||||
"status": "Status",
|
||||
"enabled": "Enabled",
|
||||
"disabled":"Disabled",
|
||||
"info": "Description"
|
||||
},
|
||||
"menu": {
|
||||
"label": {
|
||||
"view": {
|
||||
"view": "View",
|
||||
"grid": "Grid",
|
||||
"showGrid": "Show grid",
|
||||
"snapGrid": "Snap to grid",
|
||||
"gridSize": "Grid size",
|
||||
"textDir": "Text Direction",
|
||||
"defaultDir": "Default",
|
||||
"ltr": "Left-to-right",
|
||||
"rtl": "Right-to-left",
|
||||
"auto": "Contextual"
|
||||
},
|
||||
"sidebar": {
|
||||
"show": "Show sidebar"
|
||||
},
|
||||
"palette": {
|
||||
"show": "Show palette"
|
||||
},
|
||||
"settings": "Settings",
|
||||
"userSettings": "User Settings",
|
||||
"nodes": "Nodes",
|
||||
"displayStatus": "Show node status",
|
||||
"displayConfig": "Configuration nodes",
|
||||
"import": "Import",
|
||||
"export": "Export",
|
||||
"search": "Search flows",
|
||||
"searchInput": "search your flows",
|
||||
"clipboard": "Clipboard",
|
||||
"library": "Library",
|
||||
"examples": "Examples",
|
||||
"subflows": "Subflows",
|
||||
"createSubflow": "Create Subflow",
|
||||
"selectionToSubflow": "Selection to Subflow",
|
||||
"flows": "Flows",
|
||||
"add": "Add",
|
||||
"rename": "Rename",
|
||||
"delete": "Delete",
|
||||
"keyboardShortcuts": "Keyboard shortcuts",
|
||||
"login": "Login",
|
||||
"logout": "Logout",
|
||||
"editPalette":"Manage palette",
|
||||
"other": "Other",
|
||||
"showTips": "Show tips",
|
||||
"help": "Node-RED website",
|
||||
"projects": "Projects",
|
||||
"projects-new": "New",
|
||||
"projects-open": "Open",
|
||||
"projects-settings": "Project Settings",
|
||||
"showNodeLabelDefault": "Show label of newly added nodes"
|
||||
}
|
||||
},
|
||||
"actions": {
|
||||
"toggle-navigator": "Toggle navigator",
|
||||
"zoom-out": "Zoom out",
|
||||
"zoom-reset": "Reset zoom",
|
||||
"zoom-in": "Zoom in"
|
||||
},
|
||||
"user": {
|
||||
"loggedInAs": "Logged in as __name__",
|
||||
"username": "Username",
|
||||
"password": "Password",
|
||||
"login": "Login",
|
||||
"loginFailed": "Login failed",
|
||||
"notAuthorized": "Not authorized",
|
||||
"errors": {
|
||||
"settings": "You must be logged in to access settings",
|
||||
"deploy": "You must be logged in to deploy changes",
|
||||
"notAuthorized": "You must be logged in to perform this action"
|
||||
}
|
||||
},
|
||||
"notification": {
|
||||
"warning": "<strong>Warning</strong>: __message__",
|
||||
"warnings": {
|
||||
"undeployedChanges": "node has undeployed changes",
|
||||
"nodeActionDisabled": "node actions disabled",
|
||||
"nodeActionDisabledSubflow": "node actions disabled within subflow",
|
||||
"missing-types": "<p>Flows stopped due to missing node types.</p>",
|
||||
"safe-mode":"<p>Flows stopped in safe mode.</p><p>You can modify your flows and deploy the changes to restart.</p>",
|
||||
"restartRequired": "Node-RED must be restarted to enable upgraded modules",
|
||||
"credentials_load_failed": "<p>Flows stopped as the credentials could not be decrypted.</p><p>The flow credential file is encrypted, but the project's encryption key is missing or invalid.</p>",
|
||||
"credentials_load_failed_reset":"<p>Credentials could not be decrypted</p><p>The flow credential file is encrypted, but the project's encryption key is missing or invalid.</p><p>The flow credential file will be reset on the next deployment. Any existing flow credentials will be cleared.</p>",
|
||||
"missing_flow_file": "<p>Project flow file not found.</p><p>The project is not configured with a flow file.</p>",
|
||||
"missing_package_file": "<p>Project package file not found.</p><p>The project is missing a package.json file.</p>",
|
||||
"project_empty": "<p>The project is empty.</p><p>Do you want to create a default set of project files?<br/>Otherwise, you will have to manually add files to the project outside of the editor.</p>",
|
||||
"project_not_found": "<p>Project '__project__' not found.</p>",
|
||||
"git_merge_conflict": "<p>Automatic merging of changes failed.</p><p>Fix the unmerged conflicts then commit the results.</p>"
|
||||
},
|
||||
"error": "<strong>Error</strong>: __message__",
|
||||
"errors": {
|
||||
"lostConnection": "Lost connection to server, reconnecting...",
|
||||
"lostConnectionReconnect": "Lost connection to server, reconnecting in __time__s.",
|
||||
"lostConnectionTry": "Try now",
|
||||
"cannotAddSubflowToItself": "Cannot add subflow to itself",
|
||||
"cannotAddCircularReference": "Cannot add subflow - circular reference detected",
|
||||
"unsupportedVersion": "<p>Using an unsupported version of Node.js</p><p>You should upgrade to the latest Node.js LTS release</p>",
|
||||
"failedToAppendNode": "<p>Failed to load '__module__'</p><p>__error__</p>"
|
||||
},
|
||||
"project": {
|
||||
"change-branch": "Change to local branch '__project__'",
|
||||
"merge-abort": "Git merge aborted",
|
||||
"loaded": "Project '__project__' loaded",
|
||||
"updated": "Project '__project__' updated",
|
||||
"pull": "Project '__project__' reloaded",
|
||||
"revert": "Project '__project__' reverted",
|
||||
"merge-complete": "Git merge completed"
|
||||
},
|
||||
"label": {
|
||||
"manage-project-dep": "Manage project dependencies",
|
||||
"setup-cred": "Setup credentials",
|
||||
"setup-project": "Setup project files",
|
||||
"create-default-package": "Create default package file",
|
||||
"no-thanks": "No thanks",
|
||||
"create-default-project": "Create default project files",
|
||||
"show-merge-conflicts": "Show merge conflicts"
|
||||
}
|
||||
},
|
||||
"clipboard": {
|
||||
"nodes": "Nodes",
|
||||
"node": "__count__ node",
|
||||
"node_plural": "__count__ nodes",
|
||||
"configNode": "__count__ configuration node",
|
||||
"configNode_plural": "__count__ configuration nodes",
|
||||
"flow": "__count__ flow",
|
||||
"flow_plural": "__count__ flows",
|
||||
"subflow": "__count__ subflow",
|
||||
"subflow_plural": "__count__ subflows",
|
||||
"selectNodes": "Select the text above and copy to the clipboard.",
|
||||
"pasteNodes": "Paste flow json or",
|
||||
"selectFile": "select a file to import",
|
||||
"importNodes": "Import nodes",
|
||||
"exportNodes": "Export nodes",
|
||||
"download": "Download",
|
||||
"importUnrecognised": "Imported unrecognised type:",
|
||||
"importUnrecognised_plural": "Imported unrecognised types:",
|
||||
"nodesExported": "Nodes exported to clipboard",
|
||||
"nodesImported": "Imported:",
|
||||
"nodeCopied": "__count__ node copied",
|
||||
"nodeCopied_plural": "__count__ nodes copied",
|
||||
"invalidFlow": "Invalid flow: __message__",
|
||||
"export": {
|
||||
"selected":"selected nodes",
|
||||
"current":"current flow",
|
||||
"all":"all flows",
|
||||
"compact":"compact",
|
||||
"formatted":"formatted",
|
||||
"copy": "Export to clipboard"
|
||||
},
|
||||
"import": {
|
||||
"import": "Import to",
|
||||
"newFlow": "new flow",
|
||||
"errors": {
|
||||
"notArray": "Input not a JSON Array",
|
||||
"itemNotObject": "Input not a valid flow - item __index__ not a node object",
|
||||
"missingId": "Input not a valid flow - item __index__ missing 'id' property",
|
||||
"missingType": "Input not a valid flow - item __index__ missing 'type' property"
|
||||
}
|
||||
},
|
||||
"copyMessagePath": "Path copied",
|
||||
"copyMessageValue": "Value copied",
|
||||
"copyMessageValue_truncated": "Truncated value copied"
|
||||
},
|
||||
"deploy": {
|
||||
"deploy": "Deploy",
|
||||
"full": "Full",
|
||||
"fullDesc": "Deploys everything in the workspace",
|
||||
"modifiedFlows": "Modified Flows",
|
||||
"modifiedFlowsDesc": "Only deploys flows that contain changed nodes",
|
||||
"modifiedNodes": "Modified Nodes",
|
||||
"modifiedNodesDesc": "Only deploys nodes that have changed",
|
||||
"restartFlows": "Restart Flows",
|
||||
"restartFlowsDesc": "Restarts the current deployed flows",
|
||||
"successfulDeploy": "Successfully deployed",
|
||||
"successfulRestart": "Successfully restarted flows",
|
||||
"deployFailed": "Deploy failed: __message__",
|
||||
"unusedConfigNodes":"You have some unused configuration nodes.",
|
||||
"unusedConfigNodesLink":"Click here to see them",
|
||||
"errors": {
|
||||
"noResponse": "no response from server"
|
||||
},
|
||||
"confirm": {
|
||||
"button": {
|
||||
"ignore": "Ignore",
|
||||
"confirm": "Confirm deploy",
|
||||
"review": "Review changes",
|
||||
"cancel": "Cancel",
|
||||
"merge": "Merge",
|
||||
"overwrite": "Ignore & deploy"
|
||||
},
|
||||
"undeployedChanges": "You have undeployed changes.\n\nLeaving this page will lose these changes.",
|
||||
"improperlyConfigured": "The workspace contains some nodes that are not properly configured:",
|
||||
"unknown": "The workspace contains some unknown node types:",
|
||||
"confirm": "Are you sure you want to deploy?",
|
||||
"doNotWarn": "do not warn about this again",
|
||||
"conflict": "The server is running a more recent set of flows.",
|
||||
"backgroundUpdate": "The flows on the server have been updated.",
|
||||
"conflictChecking": "Checking to see if the changes can be merged automatically",
|
||||
"conflictAutoMerge": "The changes include no conflicts and can be merged automatically.",
|
||||
"conflictManualMerge": "The changes include conflicts that must be resolved before they can be deployed.",
|
||||
"plusNMore": "+ __count__ more"
|
||||
}
|
||||
},
|
||||
"eventLog": {
|
||||
"title": "Event log",
|
||||
"view": "View log"
|
||||
},
|
||||
"diff": {
|
||||
"unresolvedCount": "__count__ unresolved conflict",
|
||||
"unresolvedCount_plural": "__count__ unresolved conflicts",
|
||||
"globalNodes": "Global nodes",
|
||||
"flowProperties": "Flow Properties",
|
||||
"type": {
|
||||
"added": "added",
|
||||
"changed": "changed",
|
||||
"unchanged": "unchanged",
|
||||
"deleted": "deleted",
|
||||
"flowDeleted": "flow deleted",
|
||||
"flowAdded": "flow added",
|
||||
"movedTo": "moved to __id__",
|
||||
"movedFrom": "moved from __id__"
|
||||
},
|
||||
"nodeCount": "__count__ node",
|
||||
"nodeCount_plural": "__count__ nodes",
|
||||
"local":"Local changes",
|
||||
"remote":"Remote changes",
|
||||
"reviewChanges": "Review Changes",
|
||||
"noBinaryFileShowed": "Cannot show binary file contents",
|
||||
"viewCommitDiff": "View Commit Changes",
|
||||
"compareChanges": "Compare Changes",
|
||||
"saveConflict": "Save conflict resolution",
|
||||
"conflictHeader": "<span>__resolved__</span> of <span>__unresolved__</span> conflicts resolved",
|
||||
"commonVersionError": "Common Version doesn't contain valid JSON:",
|
||||
"oldVersionError": "Old Version doesn't contain valid JSON:",
|
||||
"newVersionError": "New Version doesn't contain valid JSON:"
|
||||
},
|
||||
"subflow": {
|
||||
"editSubflow": "Edit flow template: __name__",
|
||||
"edit": "Edit flow template",
|
||||
"subflowInstances": "There is __count__ instance of this subflow template",
|
||||
"subflowInstances_plural": "There are __count__ instances of this subflow template",
|
||||
"editSubflowProperties": "edit properties",
|
||||
"input": "inputs:",
|
||||
"output": "outputs:",
|
||||
"deleteSubflow": "delete subflow",
|
||||
"info": "Description",
|
||||
"category": "Category",
|
||||
"errors": {
|
||||
"noNodesSelected": "<strong>Cannot create subflow</strong>: no nodes selected",
|
||||
"multipleInputsToSelection": "<strong>Cannot create subflow</strong>: multiple inputs to selection"
|
||||
}
|
||||
},
|
||||
"editor": {
|
||||
"configEdit": "Edit",
|
||||
"configAdd": "Add",
|
||||
"configUpdate": "Update",
|
||||
"configDelete": "Delete",
|
||||
"nodesUse": "__count__ node uses this config",
|
||||
"nodesUse_plural": "__count__ nodes use this config",
|
||||
"addNewConfig": "Add new __type__ config node",
|
||||
"editNode": "Edit __type__ node",
|
||||
"editConfig": "Edit __type__ config node",
|
||||
"addNewType": "Add new __type__...",
|
||||
"nodeProperties": "node properties",
|
||||
"label": "Label",
|
||||
"portLabels": "Port labels",
|
||||
"labelInputs": "Inputs",
|
||||
"labelOutputs": "Outputs",
|
||||
"settingIcon": "Icon",
|
||||
"noDefaultLabel": "none",
|
||||
"defaultLabel": "use default label",
|
||||
"searchIcons": "Search icons",
|
||||
"useDefault": "use default",
|
||||
"description": "Description",
|
||||
"show": "Show",
|
||||
"hide": "Hide",
|
||||
"errors": {
|
||||
"scopeChange": "Changing the scope will make it unavailable to nodes in other flows that use it"
|
||||
}
|
||||
},
|
||||
"keyboard": {
|
||||
"title": "Keyboard Shortcuts",
|
||||
"keyboard": "Keyboard",
|
||||
"filterActions": "filter actions",
|
||||
"shortcut": "shortcut",
|
||||
"scope": "scope",
|
||||
"unassigned": "Unassigned",
|
||||
"global": "global",
|
||||
"workspace": "workspace",
|
||||
"selectAll": "Select all nodes",
|
||||
"selectAllConnected": "Select all connected nodes",
|
||||
"addRemoveNode": "Add/remove node from selection",
|
||||
"editSelected": "Edit selected node",
|
||||
"deleteSelected": "Delete selected nodes or link",
|
||||
"importNode": "Import nodes",
|
||||
"exportNode": "Export nodes",
|
||||
"nudgeNode": "Move selected nodes (1px)",
|
||||
"moveNode": "Move selected nodes (20px)",
|
||||
"toggleSidebar": "Toggle sidebar",
|
||||
"togglePalette": "Toggle palette",
|
||||
"copyNode": "Copy selected nodes",
|
||||
"cutNode": "Cut selected nodes",
|
||||
"pasteNode": "Paste nodes",
|
||||
"undoChange": "Undo the last change performed",
|
||||
"searchBox": "Open search box",
|
||||
"managePalette": "Manage palette"
|
||||
},
|
||||
"library": {
|
||||
"openLibrary": "Open Library...",
|
||||
"saveToLibrary": "Save to Library...",
|
||||
"typeLibrary": "__type__ library",
|
||||
"unnamedType": "Unnamed __type__",
|
||||
"exportToLibrary": "Export nodes to library",
|
||||
"dialogSaveOverwrite": "A __libraryType__ called __libraryName__ already exists. Overwrite?",
|
||||
"invalidFilename": "Invalid filename",
|
||||
"savedNodes": "Saved nodes",
|
||||
"savedType": "Saved __type__",
|
||||
"saveFailed": "Save failed: __message__",
|
||||
"filename": "Filename",
|
||||
"folder": "Folder",
|
||||
"filenamePlaceholder": "file",
|
||||
"fullFilenamePlaceholder": "a/b/file",
|
||||
"folderPlaceholder": "a/b",
|
||||
"breadcrumb": "Library"
|
||||
},
|
||||
"palette": {
|
||||
"noInfo": "no information available",
|
||||
"filter": "filter nodes",
|
||||
"search": "search modules",
|
||||
"addCategory": "Add new...",
|
||||
"label": {
|
||||
"subflows": "subflows",
|
||||
"input": "input",
|
||||
"output": "output",
|
||||
"function": "function",
|
||||
"social": "social",
|
||||
"storage": "storage",
|
||||
"analysis": "analysis",
|
||||
"advanced": "advanced"
|
||||
},
|
||||
"actions": {
|
||||
"collapse-all": "Collapse all categories",
|
||||
"expand-all": "Expand all categories"
|
||||
},
|
||||
"event": {
|
||||
"nodeAdded": "Node added to palette:",
|
||||
"nodeAdded_plural": "Nodes added to palette",
|
||||
"nodeRemoved": "Node removed from palette:",
|
||||
"nodeRemoved_plural": "Nodes removed from palette:",
|
||||
"nodeEnabled": "Node enabled:",
|
||||
"nodeEnabled_plural": "Nodes enabled:",
|
||||
"nodeDisabled": "Node disabled:",
|
||||
"nodeDisabled_plural": "Nodes disabled:",
|
||||
"nodeUpgraded": "Node module __module__ upgraded to version __version__"
|
||||
},
|
||||
"editor": {
|
||||
"title": "Manage palette",
|
||||
"palette": "Palette",
|
||||
"times": {
|
||||
"seconds": "seconds ago",
|
||||
"minutes": "minutes ago",
|
||||
"minutesV": "__count__ minutes ago",
|
||||
"hoursV": "__count__ hour ago",
|
||||
"hoursV_plural": "__count__ hours ago",
|
||||
"daysV": "__count__ day ago",
|
||||
"daysV_plural": "__count__ days ago",
|
||||
"weeksV": "__count__ week ago",
|
||||
"weeksV_plural": "__count__ weeks ago",
|
||||
"monthsV": "__count__ month ago",
|
||||
"monthsV_plural": "__count__ months ago",
|
||||
"yearsV": "__count__ year ago",
|
||||
"yearsV_plural": "__count__ years ago",
|
||||
"yearMonthsV": "__y__ year, __count__ month ago",
|
||||
"yearMonthsV_plural": "__y__ year, __count__ months ago",
|
||||
"yearsMonthsV": "__y__ years, __count__ month ago",
|
||||
"yearsMonthsV_plural": "__y__ years, __count__ months ago"
|
||||
},
|
||||
"nodeCount": "__label__ node",
|
||||
"nodeCount_plural": "__label__ nodes",
|
||||
"moduleCount": "__count__ module available",
|
||||
"moduleCount_plural": "__count__ modules available",
|
||||
"inuse": "in use",
|
||||
"enableall": "enable all",
|
||||
"disableall": "disable all",
|
||||
"enable": "enable",
|
||||
"disable": "disable",
|
||||
"remove": "remove",
|
||||
"update": "update to __version__",
|
||||
"updated": "updated",
|
||||
"install": "install",
|
||||
"installed": "installed",
|
||||
"conflict": "conflict",
|
||||
"conflictTip": "<p>This module cannot be installed as it includes a<br/>node type that has already been installed</p><p>Conflicts with <code>__module__</code></p>",
|
||||
"loading": "Loading catalogues...",
|
||||
"tab-nodes": "Nodes",
|
||||
"tab-install": "Install",
|
||||
"sort": "sort:",
|
||||
"sortAZ": "a-z",
|
||||
"sortRecent": "recent",
|
||||
"more": "+ __count__ more",
|
||||
"errors": {
|
||||
"catalogLoadFailed": "<p>Failed to load node catalogue.</p><p>Check the browser console for more information</p>",
|
||||
"installFailed": "<p>Failed to install: __module__</p><p>__message__</p><p>Check the log for more information</p>",
|
||||
"removeFailed": "<p>Failed to remove: __module__</p><p>__message__</p><p>Check the log for more information</p>",
|
||||
"updateFailed": "<p>Failed to update: __module__</p><p>__message__</p><p>Check the log for more information</p>",
|
||||
"enableFailed": "<p>Failed to enable: __module__</p><p>__message__</p><p>Check the log for more information</p>",
|
||||
"disableFailed": "<p>Failed to disable: __module__</p><p>__message__</p><p>Check the log for more information</p>"
|
||||
},
|
||||
"confirm": {
|
||||
"install": {
|
||||
"body":"<p>Installing '__module__'</p><p>Before installing, please read the node's documentation. Some nodes have dependencies that cannot be automatically resolved and can require a restart of Node-RED.</p>",
|
||||
"title": "Install nodes"
|
||||
},
|
||||
"remove": {
|
||||
"body":"<p>Removing '__module__'</p><p>Removing the node will uninstall it from Node-RED. The node may continue to use resources until Node-RED is restarted.</p>",
|
||||
"title": "Remove nodes"
|
||||
},
|
||||
"update": {
|
||||
"body":"<p>Updating '__module__'</p><p>Updating the node will require a restart of Node-RED to complete the update. This must be done manually.</p>",
|
||||
"title": "Update nodes"
|
||||
},
|
||||
"cannotUpdate": {
|
||||
"body":"An update for this node is available, but it is not installed in a location that the palette manager can update.<br/><br/>Please refer to the documentation for how to update this node."
|
||||
},
|
||||
"button": {
|
||||
"review": "Open node information",
|
||||
"install": "Install",
|
||||
"remove": "Remove",
|
||||
"update": "Update"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"sidebar": {
|
||||
"info": {
|
||||
"name": "Node information",
|
||||
"tabName": "Name",
|
||||
"label": "info",
|
||||
"node": "Node",
|
||||
"type": "Type",
|
||||
"module": "Module",
|
||||
"id": "ID",
|
||||
"status": "Status",
|
||||
"enabled": "Enabled",
|
||||
"disabled": "Disabled",
|
||||
"subflow": "Subflow",
|
||||
"instances": "Instances",
|
||||
"properties": "Properties",
|
||||
"info": "Information",
|
||||
"desc": "Description",
|
||||
"blank": "blank",
|
||||
"null": "null",
|
||||
"showMore": "show more",
|
||||
"showLess": "show less",
|
||||
"flow": "Flow",
|
||||
"selection":"Selection",
|
||||
"nodes":"__count__ nodes",
|
||||
"flowDesc": "Flow Description",
|
||||
"subflowDesc": "Subflow Description",
|
||||
"nodeHelp": "Node Help",
|
||||
"none":"None",
|
||||
"arrayItems": "__count__ items",
|
||||
"showTips":"You can open the tips from the settings panel"
|
||||
},
|
||||
"config": {
|
||||
"name": "Configuration nodes",
|
||||
"label": "config",
|
||||
"global": "On all flows",
|
||||
"none": "none",
|
||||
"subflows": "subflows",
|
||||
"flows": "flows",
|
||||
"filterUnused":"unused",
|
||||
"filterAll":"all",
|
||||
"filtered": "__count__ hidden"
|
||||
},
|
||||
"context": {
|
||||
"name":"Context Data",
|
||||
"label":"context",
|
||||
"none": "none selected",
|
||||
"refresh": "refresh to load",
|
||||
"empty": "empty",
|
||||
"node": "Node",
|
||||
"flow": "Flow",
|
||||
"global": "Global",
|
||||
"deleteConfirm": "Are you sure you want to delete this item?"
|
||||
},
|
||||
"palette": {
|
||||
"name": "Palette management",
|
||||
"label": "palette"
|
||||
},
|
||||
"project": {
|
||||
"label": "project",
|
||||
"name": "Project",
|
||||
"description": "Description",
|
||||
"dependencies": "Dependencies",
|
||||
"settings": "Settings",
|
||||
"noSummaryAvailable": "No summary available",
|
||||
"editDescription": "Edit project description",
|
||||
"editDependencies": "Edit project dependencies",
|
||||
"editReadme": "Edit README.md",
|
||||
"showProjectSettings": "Show project settings",
|
||||
"projectSettings": {
|
||||
"title": "Project Settings",
|
||||
"edit": "edit",
|
||||
"none": "None",
|
||||
"install": "install",
|
||||
"removeFromProject": "remove from project",
|
||||
"addToProject": "add to project",
|
||||
"files": "Files",
|
||||
"flow": "Flow",
|
||||
"credentials": "Credentials",
|
||||
"invalidEncryptionKey": "Invalid encryption key",
|
||||
"encryptionEnabled": "Encryption enabled",
|
||||
"encryptionDisabled": "Encryption disabled",
|
||||
"setTheEncryptionKey": "Set the encryption key:",
|
||||
"resetTheEncryptionKey": "Reset the encryption key:",
|
||||
"changeTheEncryptionKey": "Change the encryption key:",
|
||||
"currentKey": "Current key",
|
||||
"newKey": "New key",
|
||||
"credentialsAlert": "This will delete all existing credentials",
|
||||
"versionControl": "Version Control",
|
||||
"branches": "Branches",
|
||||
"noBranches": "No branches",
|
||||
"deleteConfirm": "Are you sure you want to delete the local branch '__name__'? This cannot be undone.",
|
||||
"unmergedConfirm": "The local branch '__name__' has unmerged changes that will be lost. Are you sure you want to delete it?",
|
||||
"deleteUnmergedBranch": "Delete unmerged branch",
|
||||
"gitRemotes": "Git remotes",
|
||||
"addRemote": "add remote",
|
||||
"addRemote2": "Add remote",
|
||||
"remoteName": "Remote name",
|
||||
"nameRule": "Must contain only A-Z 0-9 _ -",
|
||||
"url": "URL",
|
||||
"urlRule": "https://, ssh:// or file://",
|
||||
"urlRule2": "Do not include the username/password in the URL",
|
||||
"noRemotes": "No remotes",
|
||||
"deleteRemoteConfrim": "Are you sure you want to delete the remote '__name__'?",
|
||||
"deleteRemote": "Delete remote"
|
||||
},
|
||||
"userSettings": {
|
||||
"committerDetail": "Committer Details",
|
||||
"committerTip": "Leave blank to use system default",
|
||||
"userName": "Username",
|
||||
"email": "Email",
|
||||
"sshKeys": "SSH Keys",
|
||||
"sshKeysTip": "Allows you to create secure connections to remote git repositories.",
|
||||
"add": "add key",
|
||||
"addSshKey": "Add SSH Key",
|
||||
"addSshKeyTip": "Generate a new public/private key pair",
|
||||
"name": "Name",
|
||||
"nameRule": "Must contain only A-Z 0-9 _ -",
|
||||
"passphrase": "Passphrase",
|
||||
"passphraseShort": "Passphrase too short",
|
||||
"optional": "Optional",
|
||||
"cancel": "Cancel",
|
||||
"generate": "Generate key",
|
||||
"noSshKeys": "No SSH keys",
|
||||
"copyPublicKey": "Copy public key to clipboard",
|
||||
"delete": "Delete key",
|
||||
"gitConfig": "Git config",
|
||||
"deleteConfirm": "Are you sure you want to delete the SSH key __name__? This cannot be undone."
|
||||
},
|
||||
"versionControl": {
|
||||
"unstagedChanges": "Unstaged changes",
|
||||
"stagedChanges": "Staged changes",
|
||||
"unstageChange": "Unstage change",
|
||||
"stageChange": "Stage change",
|
||||
"unstageAllChange": "Unstage all changes",
|
||||
"stageAllChange": "Stage all changes",
|
||||
"commitChanges": "Commit changes",
|
||||
"resolveConflicts": "Resolve conflicts",
|
||||
"head": "HEAD",
|
||||
"staged": "Staged",
|
||||
"unstaged": "Unstaged",
|
||||
"local": "Local",
|
||||
"remote": "Remote",
|
||||
"revert": "Are you sure you want to revert the changes to '__file__'? This cannot be undone.",
|
||||
"revertChanges": "Revert changes",
|
||||
"localChanges": "Local Changes",
|
||||
"none": "None",
|
||||
"conflictResolve": "All conflicts resolved. Commit the changes to complete the merge.",
|
||||
"localFiles": "Local files",
|
||||
"all": "all",
|
||||
"unmergedChanges": "Unmerged changes",
|
||||
"abortMerge": "abort merge",
|
||||
"commit": "commit",
|
||||
"changeToCommit": "Changes to commit",
|
||||
"commitPlaceholder": "Enter your commit message",
|
||||
"cancelCapital": "Cancel",
|
||||
"commitCapital": "Commit",
|
||||
"commitHistory": "Commit History",
|
||||
"branch": "Branch:",
|
||||
"moreCommits": " more commit(s)",
|
||||
"changeLocalBranch": "Change local branch",
|
||||
"createBranchPlaceholder": "Find or create a branch",
|
||||
"upstream": "upstream",
|
||||
"localOverwrite": "You have local changes that would be overwritten by changing the branch. You must either commit or undo those changes first.",
|
||||
"manageRemoteBranch": "Manage remote branch",
|
||||
"unableToAccess": "Unable to access remote repository",
|
||||
"retry": "Retry",
|
||||
"setUpstreamBranch": "Set as upstream branch",
|
||||
"createRemoteBranchPlaceholder": "Find or create a remote branch",
|
||||
"trackedUpstreamBranch": "The created branch will be set as the tracked upstream branch.",
|
||||
"selectUpstreamBranch": "The branch will be created. Select below to set it as the tracked upstream branch.",
|
||||
"pushFailed": "Push failed as the remote has more recent commits. Pull and merge first, then push again.",
|
||||
"push": "push",
|
||||
"pull": "pull",
|
||||
"unablePull": "<p>Unable to pull remote changes; your unstaged local changes would be overwritten.</p><p>Commit your changes and try again.</p>",
|
||||
"showUnstagedChanges": "Show unstaged changes",
|
||||
"connectionFailed": "Could not connect to remote repository: ",
|
||||
"pullUnrelatedHistory": "<p>The remote has an unrelated history of commits.</p><p>Are you sure you want to pull the changes into your local repository?</p>",
|
||||
"pullChanges": "Pull changes",
|
||||
"history": "history",
|
||||
"projectHistory": "Project History",
|
||||
"daysAgo": "__count__ day ago",
|
||||
"daysAgo_plural": "__count__ days ago",
|
||||
"hoursAgo": "__count__ hour ago",
|
||||
"hoursAgo_plural": "__count__ hours ago",
|
||||
"minsAgo": "__count__ min ago",
|
||||
"minsAgo_plural": "__count__ mins ago",
|
||||
"secondsAgo": "Seconds ago",
|
||||
"notTracking": "Your local branch is not currently tracking a remote branch.",
|
||||
"statusUnmergedChanged": "Your repository has unmerged changes. You need to fix the conflicts and commit the result.",
|
||||
"repositoryUpToDate": "Your repository is up to date.",
|
||||
"commitsAhead": "Your repository is __count__ commit ahead of the remote. You can push this commit now.",
|
||||
"commitsAhead_plural": "Your repository is __count__ commits ahead of the remote. You can push these commits now.",
|
||||
"commitsBehind": "Your repository is __count__ commit behind of the remote. You can pull this commit now.",
|
||||
"commitsBehind_plural": "Your repository is __count__ commits behind of the remote. You can pull these commits now.",
|
||||
"commitsAheadAndBehind1": "Your repository is __count__ commit behind and ",
|
||||
"commitsAheadAndBehind1_plural": "Your repository is __count__ commits behind and ",
|
||||
"commitsAheadAndBehind2": "__count__ commit ahead of the remote. ",
|
||||
"commitsAheadAndBehind2_plural": "__count__ commits ahead of the remote. ",
|
||||
"commitsAheadAndBehind3": "You must pull the remote commit down before pushing.",
|
||||
"commitsAheadAndBehind3_plural": "You must pull the remote commits down before pushing.",
|
||||
"refreshCommitHistory": "Refresh commit history",
|
||||
"refreshChanges": "Refresh changes"
|
||||
}
|
||||
}
|
||||
},
|
||||
"typedInput": {
|
||||
"type": {
|
||||
"str": "string",
|
||||
"num": "number",
|
||||
"re": "regular expression",
|
||||
"bool": "boolean",
|
||||
"json": "JSON",
|
||||
"bin": "buffer",
|
||||
"date": "timestamp",
|
||||
"jsonata": "expression",
|
||||
"env": "env variable"
|
||||
}
|
||||
},
|
||||
"editableList": {
|
||||
"add": "add"
|
||||
},
|
||||
"search": {
|
||||
"empty": "No matches found",
|
||||
"addNode": "add a node..."
|
||||
},
|
||||
"expressionEditor": {
|
||||
"functions": "Functions",
|
||||
"functionReference": "Function reference",
|
||||
"insert": "Insert",
|
||||
"title": "JSONata Expression editor",
|
||||
"test": "Test",
|
||||
"data": "Example message",
|
||||
"result": "Result",
|
||||
"format": "format expression",
|
||||
"compatMode": "Compatibility mode enabled",
|
||||
"compatModeDesc": "<h3>JSONata compatibility mode</h3><p> The current expression appears to still reference <code>msg</code> so will be evaluated in compatibility mode. Please update the expression to not use <code>msg</code> as this mode will be removed in the future.</p><p> When JSONata support was first added to Node-RED, it required the expression to reference the <code>msg</code> object. For example <code>msg.payload</code> would be used to access the payload.</p><p> That is no longer necessary as the expression will be evaluated against the message directly. To access the payload, the expression should be just <code>payload</code>.</p>",
|
||||
"noMatch": "No matching result",
|
||||
"errors": {
|
||||
"invalid-expr": "Invalid JSONata expression:\n __message__",
|
||||
"invalid-msg": "Invalid example JSON message:\n __message__",
|
||||
"context-unsupported": "Cannot test context functions\n $flowContext or $globalContext",
|
||||
"eval": "Error evaluating expression:\n __message__"
|
||||
}
|
||||
},
|
||||
"jsEditor": {
|
||||
"title": "JavaScript editor"
|
||||
},
|
||||
"jsonEditor": {
|
||||
"title": "JSON editor",
|
||||
"format": "format JSON"
|
||||
},
|
||||
"markdownEditor": {
|
||||
"title": "Markdown editor",
|
||||
"format": "Formatted with markdown",
|
||||
"heading1": "Heading 1",
|
||||
"heading2": "Heading 2",
|
||||
"heading3": "Heading 3",
|
||||
"bold": "Bold",
|
||||
"italic": "Italic",
|
||||
"code": "Code",
|
||||
"ordered-list": "Ordered list",
|
||||
"unordered-list": "Unordered list",
|
||||
"quote": "Quote",
|
||||
"link": "Link",
|
||||
"horizontal-rule": "Horizontal rule",
|
||||
"toggle-preview": "Toggle preview"
|
||||
},
|
||||
"bufferEditor": {
|
||||
"title": "Buffer editor",
|
||||
"modeString": "Handle as UTF-8 String",
|
||||
"modeArray": "Handle as JSON array",
|
||||
"modeDesc":"<h3>Buffer editor</h3><p>The Buffer type is stored as a JSON array of byte values. The editor will attempt to parse the entered value as a JSON array. If it is not valid JSON, it will be treated as a UTF-8 String and converted to an array of the individual character code points.</p><p>For example, a value of <code>Hello World</code> will be converted to the JSON array:<pre>[72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100]</pre></p>"
|
||||
},
|
||||
"projects": {
|
||||
"config-git": "Configure Git client",
|
||||
"welcome": {
|
||||
"hello": "Hello! We have introduced 'projects' to Node-RED.",
|
||||
"desc0": "This is a new way for you to manage your flow files and includes version control of your flows.",
|
||||
"desc1": "To get started you can create your first project or clone an existing project from a git repository.",
|
||||
"desc2": "If you are not sure, you can skip this for now. You will still be able to create your first project from the 'Projects' menu at any time.",
|
||||
"create": "Create Project",
|
||||
"clone": "Clone Repository",
|
||||
"not-right-now": "Not right now"
|
||||
},
|
||||
"git-config": {
|
||||
"setup": "Setup your version control client",
|
||||
"desc0": "Node-RED uses the open source tool Git for version control. It tracks changes to your project files and lets you push them to remote repositories.",
|
||||
"desc1": "When you commit a set of changes, Git records who made the changes with a username and email address. The Username can be anything you want - it does not need to be your real name.",
|
||||
"desc2": "Your Git client is already configured with the details below.",
|
||||
"desc3": "You can change these settings later under the 'Git config' tab of the settings dialog.",
|
||||
"username": "Username",
|
||||
"email": "Email"
|
||||
},
|
||||
"project-details": {
|
||||
"create": "Create your project",
|
||||
"desc0": "A project is maintained as a Git repository. It makes it much easier to share your flows with others and to collaborate on them.",
|
||||
"desc1": "You can create multiple projects and quickly switch between them from the editor.",
|
||||
"desc2": "To begin, your project needs a name and an optional description.",
|
||||
"already-exists": "Project already exists",
|
||||
"must-contain": "Must contain only A-Z 0-9 _ -",
|
||||
"project-name": "Project name",
|
||||
"desc": "Description",
|
||||
"opt": "Optional"
|
||||
},
|
||||
"clone-project": {
|
||||
"clone": "Clone a project",
|
||||
"desc0": "If you already have a git repository containing a project, you can clone it to get started.",
|
||||
"already-exists": "Project already exists",
|
||||
"must-contain": "Must contain only A-Z 0-9 _ -",
|
||||
"project-name": "Project name",
|
||||
"no-info-in-url": "Do not include the username/password in the url",
|
||||
"git-url": "Git repository URL",
|
||||
"protocols": "https://, ssh:// or file://",
|
||||
"auth-failed": "Authentication failed",
|
||||
"username": "Username",
|
||||
"passwd": "Password",
|
||||
"ssh-key": "SSH Key",
|
||||
"passphrase": "Passphrase",
|
||||
"ssh-key-desc": "Before you can clone a repository over ssh you must add an SSH key to access it.",
|
||||
"ssh-key-add": "Add an ssh key",
|
||||
"credential-key": "Credentials encryption key",
|
||||
"cant-get-ssh-key": "Error! Can't get selected SSH key path.",
|
||||
"already-exists2": "already exists",
|
||||
"git-error": "git error",
|
||||
"connection-failed": "Connection failed",
|
||||
"not-git-repo": "Not a git repository",
|
||||
"repo-not-found": "Repository not found"
|
||||
},
|
||||
"default-files": {
|
||||
"create": "Create your project files",
|
||||
"desc0": "A project contains your flow files, a README file and a package.json file.",
|
||||
"desc1": "It can contain any other files you want to maintain in the Git repository.",
|
||||
"desc2": "Your existing flow and credential files will be copied into the project.",
|
||||
"flow-file": "Flow file",
|
||||
"credentials-file": "Credentials file"
|
||||
},
|
||||
"encryption-config": {
|
||||
"setup": "Setup encryption of your credentials file",
|
||||
"desc0": "Your flow credentials file can be encrypted to keep its contents secure.",
|
||||
"desc1": "If you want to store these credentials in a public Git repository, you must encrypt them by providing a secret key phrase.",
|
||||
"desc2": "Your flow credentials file is not currently encrypted.",
|
||||
"desc3": "That means its contents, such as passwords and access tokens, can be read by anyone with access to the file.",
|
||||
"desc4": "If you want to store these credentials in a public Git repository, you must encrypt them by providing a secret key phrase.",
|
||||
"desc5": "Your flow credentials file is currently encrypted using the credentialSecret property from your settings file as the key.",
|
||||
"desc6": "Your flow credentials file is currently encrypted using a system-generated key. You should provide a new secret key for this project.",
|
||||
"desc7": "The key will be stored separately from your project files. You will need to provide the key to use this project in another instance of Node-RED.",
|
||||
"credentials": "Credentials",
|
||||
"enable": "Enable encryption",
|
||||
"disable": "Disable encryption",
|
||||
"disabled": "disabled",
|
||||
"copy": "Copy over existing key",
|
||||
"use-custom": "Use custom key",
|
||||
"desc8": "The credentials file will not be encrypted and its contents easily read",
|
||||
"create-project-files": "Create project files",
|
||||
"create-project": "Create project",
|
||||
"already-exists": "already exists",
|
||||
"git-error": "git error",
|
||||
"git-auth-error": "git auth error"
|
||||
},
|
||||
"create-success": {
|
||||
"success": "You have successfully created your first project!",
|
||||
"desc0": "You can now continue to use Node-RED just as you always have.",
|
||||
"desc1": "The 'info' tab in the sidebar shows you what your current active project is. The button next to the name can be used to access the project settings view.",
|
||||
"desc2": "The 'history' tab in the sidebar can be used to view files that have changed in your project and to commit them. It shows you a complete history of your commits and allows you to push your changes to a remote repository."
|
||||
},
|
||||
"create": {
|
||||
"projects": "Projects",
|
||||
"already-exists": "Project already exists",
|
||||
"must-contain": "Must contain only A-Z 0-9 _ -",
|
||||
"no-info-in-url": "Do not include the username/password in the url",
|
||||
"open": "Open Project",
|
||||
"create": "Create Project",
|
||||
"clone": "Clone Repository",
|
||||
"project-name": "Project name",
|
||||
"desc": "Description",
|
||||
"opt": "Optional",
|
||||
"flow-file": "Flow file",
|
||||
"credentials": "Credentials",
|
||||
"enable-encryption": "Enable encryption",
|
||||
"disable-encryption": "Disable encryption",
|
||||
"encryption-key": "Encryption key",
|
||||
"desc0": "A phrase to secure your credentials with",
|
||||
"desc1": "The credentials file will not be encrypted and its contents easily read",
|
||||
"git-url": "Git repository URL",
|
||||
"protocols": "https://, ssh:// or file://",
|
||||
"auth-failed": "Authentication failed",
|
||||
"username": "Username",
|
||||
"password": "Password",
|
||||
"ssh-key": "SSH Key",
|
||||
"passphrase": "Passphrase",
|
||||
"desc2": "Before you can clone a repository over ssh you must add an SSH key to access it.",
|
||||
"add-ssh-key": "Add an ssh key",
|
||||
"credentials-encryption-key": "Credentials encryption key",
|
||||
"already-exists-2": "already exists",
|
||||
"git-error": "git error",
|
||||
"con-failed": "Connection failed",
|
||||
"not-git": "Not a git repository",
|
||||
"no-resource": "Repository not found",
|
||||
"cant-get-ssh-key-path": "Error! Can't get selected SSH key path.",
|
||||
"unexpected_error": "unexpected_error"
|
||||
},
|
||||
"delete": {
|
||||
"confirm": "Are you sure you want to delete this project?"
|
||||
},
|
||||
"create-project-list": {
|
||||
"search": "search your projects",
|
||||
"current": "current"
|
||||
},
|
||||
"require-clean": {
|
||||
"confirm": "<p>You have undeployed changes that will be lost.</p><p>Do you want to continue?</p>"
|
||||
},
|
||||
"send-req": {
|
||||
"auth-req": "Authentication required for repository",
|
||||
"username": "Username",
|
||||
"password": "Password",
|
||||
"passphrase": "Passphrase",
|
||||
"retry": "Retry",
|
||||
"update-failed": "Failed to update auth",
|
||||
"unhandled": "Unhandled error response"
|
||||
},
|
||||
"create-branch-list": {
|
||||
"invalid": "Invalid branch",
|
||||
"create": "Create branch",
|
||||
"current": "current"
|
||||
},
|
||||
"create-default-file-set": {
|
||||
"no-active": "Cannot create default file set without an active project",
|
||||
"no-empty": "Cannot create default file set on a non-empty project",
|
||||
"git-error": "git error"
|
||||
},
|
||||
"errors" : {
|
||||
"no-username-email": "Your Git client is not configured with a username/email.",
|
||||
"unexpected": "An unexpected error occurred",
|
||||
"code": "code"
|
||||
}
|
||||
},
|
||||
"editor-tab": {
|
||||
"properties": "Properties",
|
||||
"description": "Description",
|
||||
"appearance": "Appearance"
|
||||
}
|
||||
}
|
||||
41
red/api/locales/en-US/jsonata.json → packages/node_modules/@node-red/editor-client/locales/en-US/jsonata.json
vendored
Normal file → Executable file
41
red/api/locales/en-US/jsonata.json → packages/node_modules/@node-red/editor-client/locales/en-US/jsonata.json
vendored
Normal file → Executable file
@@ -95,6 +95,10 @@
|
||||
"args":"",
|
||||
"desc":"Returns a pseudo random number greater than or equal to zero and less than one."
|
||||
},
|
||||
"$millis": {
|
||||
"args":"",
|
||||
"desc":"Returns the number of milliseconds since the Unix Epoch (1 January, 1970 UTC) as a number. All invocations of `$millis()` within an evaluation of an expression will all return the same value."
|
||||
},
|
||||
"$sum": {
|
||||
"args": "array",
|
||||
"desc": "Returns the arithmetic sum of an `array` of numbers. It is an error if the input `array` contains an item which isn't a number."
|
||||
@@ -111,7 +115,6 @@
|
||||
"args": "array",
|
||||
"desc": "Returns the mean value of an `array` of numbers. It is an error if the input `array` contains an item which isn't a number."
|
||||
},
|
||||
|
||||
"$boolean": {
|
||||
"args": "arg",
|
||||
"desc": "Casts the argument to a Boolean using the following rules:\n\n - `Boolean` : unchanged\n - `string`: empty : `false`\n - `string`: non-empty : `true`\n - `number`: `0` : `false`\n - `number`: non-zero : `true`\n - `null` : `false`\n - `array`: empty : `false`\n - `array`: contains a member that casts to `true` : `true`\n - `array`: all members cast to `false` : `false`\n - `object`: empty : `false`\n - `object`: non-empty : `true`\n - `function` : `false`"
|
||||
@@ -160,6 +163,10 @@
|
||||
"args": "object",
|
||||
"desc": "Splits an object containing key/value pairs into an array of objects, each of which has a single key/value pair from the input object. If the parameter is an array of objects, then the resultant array contains an object for every key/value pair in every object in the supplied array."
|
||||
},
|
||||
"$merge": {
|
||||
"args": "array<object>",
|
||||
"desc": "Merges an array of `objects` into a single `object` containing all the key/value pairs from each of the objects in the input array. If any of the input objects contain the same key, then the returned `object` will contain the value of the last one in the array. It is an error if the input array contains an item that is not an object."
|
||||
},
|
||||
"$sift": {
|
||||
"args":"object, function",
|
||||
"desc":"Returns an object that contains only the key/value pairs from the `object` parameter that satisfy the predicate `function` passed in as the second parameter.\n\nThe `function` that is supplied as the second parameter must have the following signature:\n\n`function(value [, key [, object]])`"
|
||||
@@ -181,11 +188,35 @@
|
||||
"desc":"Returns an aggregated value derived from applying the `function` parameter successively to each value in `array` in combination with the result of the previous application of the function.\n\nThe function must accept two arguments, and behaves like an infix operator between each value within the `array`.\n\nThe optional `init` parameter is used as the initial value in the aggregation."
|
||||
},
|
||||
"$flowContext": {
|
||||
"args": "string",
|
||||
"desc": "Retrieves a flow context property."
|
||||
"args": "string[, string]",
|
||||
"desc": "Retrieves a flow context property.\n\nThis is a Node-RED defined function."
|
||||
},
|
||||
"$globalContext": {
|
||||
"args": "string",
|
||||
"desc": "Retrieves a global context property."
|
||||
"args": "string[, string]",
|
||||
"desc": "Retrieves a global context property.\n\nThis is a Node-RED defined function."
|
||||
},
|
||||
"$pad": {
|
||||
"args": "string, width [, char]",
|
||||
"desc": "Returns a copy of the `string` with extra padding, if necessary, so that its total number of characters is at least the absolute value of the `width` parameter.\n\nIf `width` is a positive number, then the string is padded to the right; if negative, it is padded to the left.\n\nThe optional `char` argument specifies the padding character(s) to use. If not specified, it defaults to the space character."
|
||||
},
|
||||
"$fromMillis": {
|
||||
"args": "number",
|
||||
"desc": "Convert a number representing milliseconds since the Unix Epoch (1 January, 1970 UTC) to a timestamp string in the ISO 8601 format."
|
||||
},
|
||||
"$formatNumber": {
|
||||
"args": "number, picture [, options]",
|
||||
"desc": "Casts the `number` to a string and formats it to a decimal representation as specified by the `picture` string.\n\n The behaviour of this function is consistent with the XPath/XQuery function fn:format-number as defined in the XPath F&O 3.1 specification. The picture string parameter defines how the number is formatted and has the same syntax as fn:format-number.\n\nThe optional third argument `options` is used to override the default locale specific formatting characters such as the decimal separator. If supplied, this argument must be an object containing name/value pairs specified in the decimal format section of the XPath F&O 3.1 specification."
|
||||
},
|
||||
"$formatBase": {
|
||||
"args": "number [, radix]",
|
||||
"desc": "Casts the `number` to a string and formats it to an integer represented in the number base specified by the `radix` argument. If `radix` is not specified, then it defaults to base 10. `radix` can be between 2 and 36, otherwise an error is thrown."
|
||||
},
|
||||
"$toMillis": {
|
||||
"args": "timestamp",
|
||||
"desc": "Convert a `timestamp` string in the ISO 8601 format to the number of milliseconds since the Unix Epoch (1 January, 1970 UTC) as a number. An error is thrown if the string is not in the correct format."
|
||||
},
|
||||
"$env": {
|
||||
"args": "arg",
|
||||
"desc": "Returns the value of an environment variable.\n\nThis is a Node-RED defined function."
|
||||
}
|
||||
}
|
||||
906
packages/node_modules/@node-red/editor-client/locales/ja/editor.json
vendored
Executable file
906
packages/node_modules/@node-red/editor-client/locales/ja/editor.json
vendored
Executable file
@@ -0,0 +1,906 @@
|
||||
{
|
||||
"common": {
|
||||
"label": {
|
||||
"name": "名前",
|
||||
"ok": "OK",
|
||||
"done": "完了",
|
||||
"cancel": "中止",
|
||||
"delete": "削除",
|
||||
"close": "閉じる",
|
||||
"load": "読み込み",
|
||||
"save": "保存",
|
||||
"import": "読み込み",
|
||||
"export": "書き出し",
|
||||
"back": "戻る",
|
||||
"next": "進む",
|
||||
"clone": "プロジェクトをクローン",
|
||||
"cont": "続ける"
|
||||
}
|
||||
},
|
||||
"workspace": {
|
||||
"defaultName": "フロー __number__",
|
||||
"editFlow": "フローを編集: __name__",
|
||||
"confirmDelete": "削除の確認",
|
||||
"delete": "本当に '__label__' を削除しますか?",
|
||||
"dropFlowHere": "ここにフローをドロップしてください",
|
||||
"addFlow": "フローの追加",
|
||||
"status": "状態",
|
||||
"enabled": "有効",
|
||||
"disabled": "無効",
|
||||
"info": "詳細"
|
||||
},
|
||||
"menu": {
|
||||
"label": {
|
||||
"view": {
|
||||
"view": "表示",
|
||||
"grid": "グリッド",
|
||||
"showGrid": "グリッドを表示",
|
||||
"snapGrid": "ノードの配置を補助",
|
||||
"gridSize": "グリッドの大きさ",
|
||||
"textDir": "テキストの方向",
|
||||
"defaultDir": "標準",
|
||||
"ltr": "左から右",
|
||||
"rtl": "右から左",
|
||||
"auto": "文脈"
|
||||
},
|
||||
"sidebar": {
|
||||
"show": "サイドバーを表示"
|
||||
},
|
||||
"palette": {
|
||||
"show": "パレットを表示"
|
||||
},
|
||||
"settings": "設定",
|
||||
"userSettings": "ユーザ設定",
|
||||
"nodes": "ノード",
|
||||
"displayStatus": "ノードの状態を表示",
|
||||
"displayConfig": "ノードの設定",
|
||||
"import": "読み込み",
|
||||
"export": "書き出し",
|
||||
"search": "ノードを検索",
|
||||
"searchInput": "ノードを検索",
|
||||
"clipboard": "クリップボード",
|
||||
"library": "ライブラリ",
|
||||
"examples": "サンプル",
|
||||
"subflows": "サブフロー",
|
||||
"createSubflow": "サブフローを作成",
|
||||
"selectionToSubflow": "選択部分をサブフロー化",
|
||||
"flows": "フロー",
|
||||
"add": "フローを新規追加",
|
||||
"rename": "フロー名を変更",
|
||||
"delete": "フローを削除",
|
||||
"keyboardShortcuts": "ショートカットキーの説明",
|
||||
"login": "ログイン",
|
||||
"logout": "ログアウト",
|
||||
"editPalette": "パレットの管理",
|
||||
"other": "その他",
|
||||
"showTips": "ヒントを表示",
|
||||
"help": "Node-REDウェブサイト",
|
||||
"projects": "プロジェクト",
|
||||
"projects-new": "新規",
|
||||
"projects-open": "開く",
|
||||
"projects-settings": "設定",
|
||||
"showNodeLabelDefault": "追加したノードのラベルを表示する"
|
||||
}
|
||||
},
|
||||
"actions": {
|
||||
"toggle-navigator": "ナビゲータの表示/非表示を切替",
|
||||
"zoom-out": "縮小",
|
||||
"zoom-reset": "拡大/縮小を初期化",
|
||||
"zoom-in": "拡大"
|
||||
},
|
||||
"user": {
|
||||
"loggedInAs": "__name__ としてログインしました",
|
||||
"username": "ユーザ名",
|
||||
"password": "パスワード",
|
||||
"login": "ログイン",
|
||||
"loginFailed": "ログインに失敗しました",
|
||||
"notAuthorized": "権限がありません",
|
||||
"errors": {
|
||||
"settings": "設定を参照するには、ログインする必要があります",
|
||||
"deploy": "変更をデプロイするには、ログインする必要があります",
|
||||
"notAuthorized": "本アクションを行うには、ログインする必要があります"
|
||||
}
|
||||
},
|
||||
"notification": {
|
||||
"warning": "<strong>警告</strong>: __message__",
|
||||
"warnings": {
|
||||
"undeployedChanges": "ノードの変更をデプロイしていません",
|
||||
"nodeActionDisabled": "ノードのアクションは無効になっています",
|
||||
"nodeActionDisabledSubflow": "ノードのアクションは、サブフロー内で無効になっています",
|
||||
"missing-types": "不明なノードが存在するため、フローを停止しました。詳細はログを確認してください。",
|
||||
"safe-mode": "<p>セーフモードでフローを停止しました</p><p>フローを変更し、再起動するために変更をデプロイできます</p>",
|
||||
"restartRequired": "更新されたモジュールを有効化するため、Node-REDを再起動する必要があります",
|
||||
"credentials_load_failed": "<p>認証情報を復号できないため、フローを停止しました</p><p>フローの認証情報ファイルは暗号化されています。しかし、プロジェクトの暗号鍵が存在しない、または不正です</p>",
|
||||
"credentials_load_failed_reset": "<p>認証情報を復号できません</p><p>フローの認証情報ファイルは暗号化されています。しかし、プロジェクトの暗号鍵が存在しない、または不正です。</p><p>次回のデプロイでフローの認証情報ファイルがリセットされます。既存フローの認証情報は削除されます。</p>",
|
||||
"missing_flow_file": "<p>プロジェクトのフローファイルが存在しません</p><p>本プロジェクトにフローファイルが登録されていません</p>",
|
||||
"missing_package_file": "<p>プロジェクトのパッケージファイルが存在しません</p><p>本プロジェクトにはpackage.jsonファイルがありません</p>",
|
||||
"project_empty": "<p>空のプロジェクトです</p><p>デフォルトのプロジェクトファイルを作成しますか?<br/>作成しない場合、エディタの外でファイルをプロジェクトへ手動で追加する必要があります</p>",
|
||||
"project_not_found": "<p>プロジェクト '__project__' が存在しません</p>",
|
||||
"git_merge_conflict": "<p>変更の自動マージが失敗しました</p><p>マージされていない競合を解決し、コミットしてください</p>"
|
||||
},
|
||||
"error": "<strong>エラー</strong>: __message__",
|
||||
"errors": {
|
||||
"lostConnection": "サーバとの接続が切断されました: 再接続しています",
|
||||
"lostConnectionReconnect": "サーバとの接続が切断されました: __time__ 秒後に再接続します",
|
||||
"lostConnectionTry": "すぐに接続",
|
||||
"cannotAddSubflowToItself": "サブフロー自身を追加できません",
|
||||
"cannotAddCircularReference": "循環参照を検出したため、サブフローを追加できません",
|
||||
"unsupportedVersion": "<p>サポートされていないバージョンのNode.jsを使用しています。</p><p><br/>最新のNode.js LTSに更新してください。</p>",
|
||||
"failedToAppendNode": "<p>'__module__'がロードできませんでした。</p><p>__error__</p>"
|
||||
},
|
||||
"project": {
|
||||
"change-branch": "ローカルブランチ'__project__'に変更しました",
|
||||
"merge-abort": "Gitマージを中止しました",
|
||||
"loaded": "プロジェクト'__project__'をロードしました",
|
||||
"updated": "プロジェクト'__project__'を更新しました",
|
||||
"pull": "プロジェクト'__project__'を再ロードしました",
|
||||
"revert": "プロジェクト'__project__'を取り消しました",
|
||||
"merge-complete": "Gitマージが完了しました"
|
||||
},
|
||||
"label": {
|
||||
"manage-project-dep": "プロジェクトの依存関係の管理",
|
||||
"setup-cred": "認証情報の設定",
|
||||
"setup-project": "プロジェクトファイルの設定",
|
||||
"create-default-package": "デフォルトパッケージファイルの作成",
|
||||
"no-thanks": "不要",
|
||||
"create-default-project": "デフォルトプロジェクトファイルの作成",
|
||||
"show-merge-conflicts": "マージ競合を表示"
|
||||
}
|
||||
},
|
||||
"clipboard": {
|
||||
"nodes": "ノード",
|
||||
"node": "__count__ 個のノード",
|
||||
"node_plural": "__count__ 個のノード",
|
||||
"configNode": "__count__ 個の設定ノード",
|
||||
"configNode_plural": "__count__ 個の設定ノード",
|
||||
"flow": "__count__ 個のフロー",
|
||||
"flow_plural": "__count__ 個のフロー",
|
||||
"subflow": "__count__ 個のサブフロー",
|
||||
"subflow_plural": "__count__ 個のサブフロー",
|
||||
"selectNodes": "上のテキストを選択し、クリップボードへコピーしてください",
|
||||
"pasteNodes": "JSON形式のフローデータを貼り付けてください",
|
||||
"selectFile": "読み込むファイルを選択してください",
|
||||
"importNodes": "フローをクリップボートから読み込み",
|
||||
"exportNodes": "フローをクリップボードへ書き出し",
|
||||
"download": "ダウンロード",
|
||||
"importUnrecognised": "認識できない型が読み込まれました:",
|
||||
"importUnrecognised_plural": "認識できない型が読み込まれました:",
|
||||
"nodesExported": "クリップボードへフローを書き出しました",
|
||||
"nodesImported": "読み込みました:",
|
||||
"nodeCopied": "__count__ 個のノードをコピーしました",
|
||||
"nodeCopied_plural": "__count__ 個のノードをコピーしました",
|
||||
"invalidFlow": "不正なフロー: __message__",
|
||||
"export": {
|
||||
"selected": "選択したフロー",
|
||||
"current": "現在のタブ",
|
||||
"all": "全てのタブ",
|
||||
"compact": "インデントのないJSONフォーマット",
|
||||
"formatted": "インデント付きのJSONフォーマット",
|
||||
"copy": "書き出し"
|
||||
},
|
||||
"import": {
|
||||
"import": "読み込み先",
|
||||
"newFlow": "新規のタブ",
|
||||
"errors": {
|
||||
"notArray": "JSON形式の配列ではありません",
|
||||
"itemNotObject": "不正なフロー - __index__ 番目の要素はノードオブジェクトではありません",
|
||||
"missingId": "不正なフロー - __index__ 番目の要素に'id'プロパティがありません",
|
||||
"missingType": "不正なフロー - __index__ 番目の要素に'type'プロパティがありません"
|
||||
}
|
||||
},
|
||||
"copyMessagePath": "パスをコピーしました",
|
||||
"copyMessageValue": "値をコピーしました",
|
||||
"copyMessageValue_truncated": "切り捨てられた値をコピーしました"
|
||||
},
|
||||
"deploy": {
|
||||
"deploy": "デプロイ",
|
||||
"full": "全て",
|
||||
"fullDesc": "ワークスペースを全てデプロイ",
|
||||
"modifiedFlows": "変更したフロー",
|
||||
"modifiedFlowsDesc": "変更したノードを含むフローのみデプロイ",
|
||||
"modifiedNodes": "変更したノード",
|
||||
"modifiedNodesDesc": "変更したノードのみデプロイ",
|
||||
"restartFlows": "フローを再起動",
|
||||
"restartFlowsDesc": "デプロイされた現在のフローを再起動",
|
||||
"successfulDeploy": "デプロイが成功しました",
|
||||
"successfulRestart": "フローの再起動が成功しました",
|
||||
"deployFailed": "デプロイが失敗しました: __message__",
|
||||
"unusedConfigNodes": "使われていない「ノードの設定」があります。",
|
||||
"unusedConfigNodesLink": "設定を参照する",
|
||||
"errors": {
|
||||
"noResponse": "サーバの応答がありません"
|
||||
},
|
||||
"confirm": {
|
||||
"button": {
|
||||
"ignore": "無視",
|
||||
"confirm": "デプロイの確認",
|
||||
"review": "差分を確認",
|
||||
"cancel": "中止",
|
||||
"merge": "変更をマージ",
|
||||
"overwrite": "無視してデプロイ"
|
||||
},
|
||||
"undeployedChanges": "デプロイしていない変更があります。このページを抜けると変更が削除されます。",
|
||||
"improperlyConfigured": "以下のノードは、正しくプロパティが設定されていません:",
|
||||
"unknown": "ワークスペースに未知の型のノードがあります。",
|
||||
"confirm": "このままデプロイしても良いですか?",
|
||||
"doNotWarn": "この警告を再度表示しない",
|
||||
"conflict": "フローを編集している間に、他のブラウザがフローをデプロイしました。",
|
||||
"backgroundUpdate": "サーバ上のフローが更新されました",
|
||||
"conflictChecking": "変更を自動的にマージしてよいか確認してください。",
|
||||
"conflictAutoMerge": "変更の衝突がないため、自動的にマージできます。",
|
||||
"conflictManualMerge": "変更に衝突があるため、デプロイ前に解決する必要があります。",
|
||||
"plusNMore": "さらに __count__ 個"
|
||||
}
|
||||
},
|
||||
"eventLog": {
|
||||
"title": "イベントログ",
|
||||
"view": "ログを確認"
|
||||
},
|
||||
"diff": {
|
||||
"unresolvedCount": "未解決の衝突 __count__",
|
||||
"unresolvedCount_plural": "未解決の衝突 __count__",
|
||||
"globalNodes": "グローバルノード",
|
||||
"flowProperties": "フロープロパティ",
|
||||
"type": {
|
||||
"added": "追加",
|
||||
"changed": "変更",
|
||||
"unchanged": "変更なし",
|
||||
"deleted": "削除",
|
||||
"flowDeleted": "削除されたフロー",
|
||||
"flowAdded": "追加されたフロー",
|
||||
"movedTo": "__id__ へ移動",
|
||||
"movedFrom": "__id__ から移動"
|
||||
},
|
||||
"nodeCount": "__count__ 個のノード",
|
||||
"nodeCount_plural": "__count__ 個のノード",
|
||||
"local": "ローカルの変更",
|
||||
"remote": "リモートの変更",
|
||||
"reviewChanges": "変更を表示",
|
||||
"noBinaryFileShowed": "バイナリファイルの中身は表示することができません",
|
||||
"viewCommitDiff": "コミットの内容を表示",
|
||||
"compareChanges": "変更を比較",
|
||||
"saveConflict": "解決して保存",
|
||||
"conflictHeader": "<span>__unresolved__</span> 個中 <span>__resolved__</span> 個のコンフリクトを解決",
|
||||
"commonVersionError": "共通バージョンは正しいJSON形式ではありません:",
|
||||
"oldVersionError": "古いバージョンは正しいJSON形式ではありません:",
|
||||
"newVersionError": "新しいバージョンは正しいJSON形式ではありません:"
|
||||
},
|
||||
"subflow": {
|
||||
"editSubflow": "フローのテンプレートを編集: __name__",
|
||||
"edit": "フローのテンプレートを編集",
|
||||
"subflowInstances": "このサブフローのテンプレートのインスタンスが __count__ 個存在します",
|
||||
"subflowInstances_plural": "このサブフローのテンプレートのインスタンスが __count__ 個存在します",
|
||||
"editSubflowProperties": "プロパティを編集",
|
||||
"input": "入力:",
|
||||
"output": "出力:",
|
||||
"deleteSubflow": "サブフローを削除",
|
||||
"info": "詳細",
|
||||
"category": "カテゴリ",
|
||||
"errors": {
|
||||
"noNodesSelected": "<strong>サブフローを作成できません</strong>: ノードが選択されていません",
|
||||
"multipleInputsToSelection": "<strong>サブフローを作成できません</strong>: 複数の入力が選択されています"
|
||||
}
|
||||
},
|
||||
"editor": {
|
||||
"configEdit": "編集",
|
||||
"configAdd": "追加",
|
||||
"configUpdate": "更新",
|
||||
"configDelete": "削除",
|
||||
"nodesUse": "__count__ 個のノードが、この設定を使用しています",
|
||||
"nodesUse_plural": "__count__ 個のノードが、この設定を使用しています",
|
||||
"addNewConfig": "新規に __type__ ノードの設定を追加",
|
||||
"editNode": "__type__ ノードを編集",
|
||||
"editConfig": "__type__ ノードの設定を編集",
|
||||
"addNewType": "新規に __type__ を追加...",
|
||||
"nodeProperties": "プロパティ",
|
||||
"label": "ラベル",
|
||||
"portLabels": "ポートラベル",
|
||||
"labelInputs": "入力",
|
||||
"labelOutputs": "出力",
|
||||
"settingIcon": "アイコン",
|
||||
"noDefaultLabel": "なし",
|
||||
"defaultLabel": "既定のラベルを使用",
|
||||
"searchIcons": "アイコンを検索",
|
||||
"useDefault": "デフォルトを使用",
|
||||
"description": "詳細",
|
||||
"show": "表示",
|
||||
"hide": "非表示",
|
||||
"errors": {
|
||||
"scopeChange": "スコープの変更は、他のフローで使われているノードを無効にします"
|
||||
}
|
||||
},
|
||||
"keyboard": {
|
||||
"title": "キーボードショートカット",
|
||||
"keyboard": "キーボード",
|
||||
"filterActions": "動作を検索",
|
||||
"shortcut": "ショートカット",
|
||||
"scope": "範囲",
|
||||
"unassigned": "未割当",
|
||||
"global": "グローバル",
|
||||
"workspace": "ワークスペース",
|
||||
"selectAll": "全てのノードを選択",
|
||||
"selectAllConnected": "接続された全てのノードを選択",
|
||||
"addRemoveNode": "ノードの選択、選択解除",
|
||||
"editSelected": "選択したノードを編集",
|
||||
"deleteSelected": "選択したノードや接続を削除",
|
||||
"importNode": "フローの読み込み",
|
||||
"exportNode": "フローの書き出し",
|
||||
"nudgeNode": "選択したノードを移動(移動量小)",
|
||||
"moveNode": "選択したノードを移動(移動量大)",
|
||||
"toggleSidebar": "サイドバーの表示/非表示",
|
||||
"togglePalette": "パレットの表示/非表示",
|
||||
"copyNode": "選択したノードをコピー",
|
||||
"cutNode": "選択したノードを切り取り",
|
||||
"pasteNode": "ノードを貼り付け",
|
||||
"undoChange": "変更操作を戻す",
|
||||
"searchBox": "ノードを検索",
|
||||
"managePalette": "パレットの管理"
|
||||
},
|
||||
"library": {
|
||||
"openLibrary": "ライブラリを開く",
|
||||
"saveToLibrary": "ライブラリへ保存",
|
||||
"typeLibrary": "__type__ ライブラリ",
|
||||
"unnamedType": "名前なし __type__",
|
||||
"exportToLibrary": "ライブラリへフローを書き出す",
|
||||
"dialogSaveOverwrite": "__libraryName__ という __libraryType__ は既に存在しています 上書きしますか?",
|
||||
"invalidFilename": "不正なファイル名",
|
||||
"savedNodes": "フローを保存しました",
|
||||
"savedType": "__type__ を保存しました",
|
||||
"saveFailed": "保存に失敗しました: __message__",
|
||||
"filename": "ファイル名",
|
||||
"folder": "フォルダ",
|
||||
"filenamePlaceholder": "ファイル",
|
||||
"fullFilenamePlaceholder": "a/b/file",
|
||||
"folderPlaceholder": "a/b",
|
||||
"breadcrumb": "ライブラリ"
|
||||
},
|
||||
"palette": {
|
||||
"noInfo": "情報がありません",
|
||||
"filter": "ノードを検索",
|
||||
"search": "ノードを検索",
|
||||
"addCategory": "新規追加...",
|
||||
"label": {
|
||||
"subflows": "サブフロー",
|
||||
"input": "入力",
|
||||
"output": "出力",
|
||||
"function": "機能",
|
||||
"social": "ソーシャル",
|
||||
"storage": "ストレージ",
|
||||
"analysis": "分析",
|
||||
"advanced": "その他"
|
||||
},
|
||||
"actions": {
|
||||
"collapse-all": "全カテゴリを折畳む",
|
||||
"expand-all": "全カテゴリを展開"
|
||||
},
|
||||
"event": {
|
||||
"nodeAdded": "ノードをパレットへ追加しました:",
|
||||
"nodeAdded_plural": "ノードをパレットへ追加しました",
|
||||
"nodeRemoved": "ノードをパレットから削除しました:",
|
||||
"nodeRemoved_plural": "ノードをパレットから削除しました:",
|
||||
"nodeEnabled": "ノードを有効化しました:",
|
||||
"nodeEnabled_plural": "ノードを有効化しました:",
|
||||
"nodeDisabled": "ノードを無効化しました:",
|
||||
"nodeDisabled_plural": "ノードを無効化しました:",
|
||||
"nodeUpgraded": "ノードモジュール __module__ をバージョン __version__ へ更新しました"
|
||||
},
|
||||
"editor": {
|
||||
"title": "パレットの管理",
|
||||
"palette": "パレット",
|
||||
"times": {
|
||||
"seconds": "秒前",
|
||||
"minutes": "分前",
|
||||
"minutesV": "__count__ 分前",
|
||||
"hoursV": "__count__ 時間前",
|
||||
"hoursV_plural": "__count__ 時間前",
|
||||
"daysV": "__count__ 日前",
|
||||
"daysV_plural": "__count__ 日前",
|
||||
"weeksV": "__count__ 週間前",
|
||||
"weeksV_plural": "__count__ 週間前",
|
||||
"monthsV": "__count__ ヵ月前",
|
||||
"monthsV_plural": "__count__ ヵ月前",
|
||||
"yearsV": "__count__ 年前",
|
||||
"yearsV_plural": "__count__ 年前",
|
||||
"yearMonthsV": "__y__ 年 __count__ ヵ月前",
|
||||
"yearMonthsV_plural": "__y__ 年 __count__ ヵ月前",
|
||||
"yearsMonthsV": "__y__ 年 __count__ ヵ月前",
|
||||
"yearsMonthsV_plural": "__y__ 年 __count__ ヵ月前"
|
||||
},
|
||||
"nodeCount": "__label__ 個のノード",
|
||||
"nodeCount_plural": "__label__ 個のノード",
|
||||
"moduleCount": "__count__ 個のモジュール",
|
||||
"moduleCount_plural": "__count__ 個のモジュール",
|
||||
"inuse": "使用中",
|
||||
"enableall": "全て有効化",
|
||||
"disableall": "全て無効化",
|
||||
"enable": "有効化",
|
||||
"disable": "無効化",
|
||||
"remove": "削除",
|
||||
"update": "__version__ へ更新",
|
||||
"updated": "更新済",
|
||||
"install": "ノードを追加",
|
||||
"installed": "追加しました",
|
||||
"conflict": "競合",
|
||||
"conflictTip": "<p>インストール済みのノードの種別と競合しているため<br/>ノードをインストールできません</p><p>競合: <code>__module__</code></p>",
|
||||
"loading": "カタログを読み込み中",
|
||||
"tab-nodes": "現在のノード",
|
||||
"tab-install": "ノードを追加",
|
||||
"sort": "並べ替え:",
|
||||
"sortAZ": "辞書順",
|
||||
"sortRecent": "日付順",
|
||||
"more": "+ さらに __count__ 個",
|
||||
"errors": {
|
||||
"catalogLoadFailed": "<p>ノードのカタログの読み込みに失敗しました。</p><p>詳細はブラウザのコンソールを確認してください。</p>",
|
||||
"installFailed": "<p.追加処理が失敗しました: __module__</p><p>__message__</p><p>詳細はログを確認してください。</p>",
|
||||
"removeFailed": "<p>削除処理が失敗しました: __module__</p><p>__message__</p><p>詳細はログを確認してください。</p>",
|
||||
"updateFailed": "<p>更新処理が失敗しました: __module__</p><p>__message__</p><p>詳細はログを確認してください。</p>",
|
||||
"enableFailed": "<p>有効化処理が失敗しました: __module__</p><p>__message__</p><p>詳細はログを確認してください。</p>",
|
||||
"disableFailed": "<p>無効化処理が失敗しました: __module__</p><p>__message__</p><p>詳細はログを確認してください。</p>"
|
||||
},
|
||||
"confirm": {
|
||||
"install": {
|
||||
"body": "<p>__module__ をインストールします。</p><p>ノードを追加する前に、ドキュメントを確認してください。ノードによっては、モジュールの依存関係を自動的に解決できない場合や、Node-REDの再起動が必要となる場合があります。</p>",
|
||||
"title": "ノードを追加"
|
||||
},
|
||||
"remove": {
|
||||
"body": "<p>__module__ を削除します。</p><p>Node-REDからノードを削除します。ノードはNode-REDが再起動されるまで、リソースを使い続ける可能性があります。</p>",
|
||||
"title": "ノードを削除"
|
||||
},
|
||||
"update": {
|
||||
"body": "<p>__module__ を更新します。</p><p>更新を完了するには手動でNode-REDを再起動する必要があります。</p>",
|
||||
"title": "ノードの更新"
|
||||
},
|
||||
"cannotUpdate": {
|
||||
"body": "ノードの更新があります。「パレットの管理」の画面では更新されません。<br/><br/>ドキュメントを参照し、ノードの更新手順を確認してください。"
|
||||
},
|
||||
"button": {
|
||||
"review": "ノードの情報を参照",
|
||||
"install": "追加",
|
||||
"remove": "削除",
|
||||
"update": "更新"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"sidebar": {
|
||||
"info": {
|
||||
"name": "ノードの情報を表示",
|
||||
"tabName": "名前",
|
||||
"label": "情報",
|
||||
"node": "ノード",
|
||||
"type": "型",
|
||||
"module": "モジュール",
|
||||
"id": "ID",
|
||||
"status": "状態",
|
||||
"enabled": "有効",
|
||||
"disabled": "無効",
|
||||
"subflow": "サブフロー",
|
||||
"instances": "インスタンス",
|
||||
"properties": "プロパティ",
|
||||
"info": "情報",
|
||||
"desc": "詳細",
|
||||
"blank": "ブランク",
|
||||
"null": "ヌル",
|
||||
"showMore": "さらに表示",
|
||||
"showLess": "表示を省略",
|
||||
"flow": "フロー",
|
||||
"selection": "選択",
|
||||
"nodes": "__count__ 個のノード",
|
||||
"flowDesc": "フローの詳細",
|
||||
"subflowDesc": "サブフローの詳細",
|
||||
"nodeHelp": "ノードのヘルプ",
|
||||
"none": "なし",
|
||||
"arrayItems": "__count__ 要素",
|
||||
"showTips": "設定からヒントを表示できます"
|
||||
},
|
||||
"config": {
|
||||
"name": "ノードの設定を表示",
|
||||
"label": "ノードの設定",
|
||||
"global": "全てのフロー上",
|
||||
"none": "なし",
|
||||
"subflows": "サブフロー",
|
||||
"flows": "フロー",
|
||||
"filterUnused": "未使用",
|
||||
"filterAll": "全て",
|
||||
"filtered": "__count__ 個が無効"
|
||||
},
|
||||
"context": {
|
||||
"name": "コンテキストデータ",
|
||||
"label": "コンテキストデータ",
|
||||
"none": "選択されていません",
|
||||
"refresh": "読み込みのため更新してください",
|
||||
"empty": "データが存在しません",
|
||||
"node": "Node",
|
||||
"flow": "Flow",
|
||||
"global": "Global",
|
||||
"deleteConfirm": "データを削除しても良いですか?"
|
||||
},
|
||||
"palette": {
|
||||
"name": "パレットの管理",
|
||||
"label": "パレット"
|
||||
},
|
||||
"project": {
|
||||
"label": "プロジェクト",
|
||||
"name": "プロジェクト",
|
||||
"description": "詳細",
|
||||
"dependencies": "依存関係",
|
||||
"settings": "設定",
|
||||
"noSummaryAvailable": "サマリが存在しません",
|
||||
"editDescription": "プロジェクトの詳細を編集",
|
||||
"editDependencies": "プロジェクトの依存関係を編集",
|
||||
"editReadme": "README.mdを編集",
|
||||
"showProjectSettings": "プロジェクト設定を表示",
|
||||
"projectSettings": {
|
||||
"title": "プロジェクト設定",
|
||||
"edit": "編集",
|
||||
"none": "なし",
|
||||
"install": "インストール",
|
||||
"removeFromProject": "プロジェクトから削除",
|
||||
"addToProject": "プロジェクトへ追加",
|
||||
"files": "ファイル",
|
||||
"flow": "フロー",
|
||||
"credentials": "認証情報",
|
||||
"invalidEncryptionKey": "不正な暗号化キー",
|
||||
"encryptionEnabled": "暗号化が有効になっています",
|
||||
"encryptionDisabled": "暗号化が無効になっています",
|
||||
"setTheEncryptionKey": "暗号化キーを設定:",
|
||||
"resetTheEncryptionKey": "暗号化キーを初期化:",
|
||||
"changeTheEncryptionKey": "暗号化キーを変更:",
|
||||
"currentKey": "現在のキー",
|
||||
"newKey": "新規のキー",
|
||||
"credentialsAlert": "既存の認証情報は全て削除されます",
|
||||
"versionControl": "バージョン管理",
|
||||
"branches": "ブランチ",
|
||||
"noBranches": "ブランチなし",
|
||||
"deleteConfirm": "本当にローカルブランチ'__name__'を削除しますか?削除すると元に戻すことはできません。",
|
||||
"unmergedConfirm": "ローカルブランチ'__name__'にはマージされていない変更があります。この変更は削除されます。本当に削除しますか?",
|
||||
"deleteUnmergedBranch": "マージされていないブランチを削除",
|
||||
"gitRemotes": "Gitリモート",
|
||||
"addRemote": "リモートを追加",
|
||||
"addRemote2": "リモートを追加",
|
||||
"remoteName": "リモート名",
|
||||
"nameRule": "A-Z 0-9 _ - のみを含む",
|
||||
"url": "URL",
|
||||
"urlRule": "https://、ssh:// または file://",
|
||||
"urlRule2": "URLにユーザ名、パスワードを含んではいけません",
|
||||
"noRemotes": "リモートなし",
|
||||
"deleteRemoteConfrim": "本当にリモート'__name__'を削除しますか?",
|
||||
"deleteRemote": "リモートを削除"
|
||||
},
|
||||
"userSettings": {
|
||||
"committerDetail": "コミッター詳細",
|
||||
"committerTip": "システムのデフォルトを使用する場合、空白のままにしてください",
|
||||
"userName": "ユーザ名",
|
||||
"email": "メールアドレス",
|
||||
"sshKeys": "SSH キー",
|
||||
"sshKeysTip": "gitリポジトリへのセキュアな接続を作成できます。",
|
||||
"add": "キーを追加",
|
||||
"addSshKey": "SSHキーを追加",
|
||||
"addSshKeyTip": "新しい公開鍵/秘密鍵ペアを生成します",
|
||||
"name": "名前",
|
||||
"nameRule": "A-Z 0-9 _ - のみを含む",
|
||||
"passphrase": "パスフレーズ",
|
||||
"passphraseShort": "パスフレーズが短すぎます",
|
||||
"optional": "任意",
|
||||
"cancel": "中止",
|
||||
"generate": "キーを生成",
|
||||
"noSshKeys": "SSHキーがありません",
|
||||
"copyPublicKey": "公開鍵をクリップボードにコピー",
|
||||
"delete": "キーを削除",
|
||||
"gitConfig": "Git設定",
|
||||
"deleteConfirm": "SSHキー __name__ を削除してもよいですか? 削除したSSHキーを元に戻すことはできません。"
|
||||
},
|
||||
"versionControl": {
|
||||
"unstagedChanges": "ステージングされていない変更",
|
||||
"stagedChanges": "ステージングされた変更",
|
||||
"unstageChange": "ステージングした変更の取り消し",
|
||||
"stageChange": "変更をステージング",
|
||||
"unstageAllChange": "ステージングした全ての変更の取り消し",
|
||||
"stageAllChange": "全ての変更をステージング",
|
||||
"commitChanges": "変更をコミット",
|
||||
"resolveConflicts": "コンフリクトの解決",
|
||||
"head": "最新",
|
||||
"staged": "ステージング",
|
||||
"unstaged": "未ステージング",
|
||||
"local": "ローカル",
|
||||
"remote": "リモート",
|
||||
"revert": "'__file__'への変更を本当に戻しますか?この操作は元に戻せません。",
|
||||
"revertChanges": "変更を戻す",
|
||||
"localChanges": "ローカルの変更",
|
||||
"none": "なし",
|
||||
"conflictResolve": "全てのコンフリクトが解消されました。マージを完了するため、変更をコミットしてください。",
|
||||
"localFiles": "ローカルファイル",
|
||||
"all": "全て",
|
||||
"unmergedChanges": "マージされていない変更",
|
||||
"abortMerge": "マージ中止",
|
||||
"commit": "コミット",
|
||||
"changeToCommit": "コミット対象とする変更",
|
||||
"commitPlaceholder": "コミットメッセージを入力してください。",
|
||||
"cancelCapital": "キャンセル",
|
||||
"commitCapital": "コミット",
|
||||
"commitHistory": "コミット履歴",
|
||||
"branch": "ブランチ:",
|
||||
"moreCommits": "個のコミット",
|
||||
"changeLocalBranch": "ローカルブランチの変更",
|
||||
"createBranchPlaceholder": "ブランチの検索または作成",
|
||||
"upstream": "アップストリーム",
|
||||
"localOverwrite": "ブランチの変更によって上書きされたローカルの変更があります。これらの変更を先にコミットするか、あるいは元に戻さなければなりません。",
|
||||
"manageRemoteBranch": "リモートブランチの管理",
|
||||
"unableToAccess": "リモートのリポジトリにアクセスできません。",
|
||||
"retry": "リトライ",
|
||||
"setUpstreamBranch": "アップストリームとして設定する",
|
||||
"createRemoteBranchPlaceholder": "リモートブランチの検索または作成",
|
||||
"trackedUpstreamBranch": "作成されたブランチは、トラッキングされたアップストリームブランチとなります。",
|
||||
"selectUpstreamBranch": "ブランチが作成されました。トラッキングするアップストリームブランチを選択してください。",
|
||||
"pushFailed": "リモートに新しいコミットがあるため、プッシュに失敗しました。プルしてマージしてから、再度プッシュしてください。",
|
||||
"push": "プッシュ",
|
||||
"pull": "プル",
|
||||
"unablePull": "<p>リモートの変更のプル失敗:ステージングされていないローカルの変更を上書きされてしまいます。</p><p>変更をコミットしてから再度実行してください。</p>",
|
||||
"showUnstagedChanges": "ステージングされていない変更を表示",
|
||||
"connectionFailed": "リモートリポジトリに接続できません: ",
|
||||
"pullUnrelatedHistory": "<p>リモートに関連のないコミット履歴があります。</p><p>本当に変更をプルしてローカルリポジトリに反映しますか?</p>",
|
||||
"pullChanges": "プル変更",
|
||||
"history": "履歴",
|
||||
"projectHistory": "プロジェクト履歴",
|
||||
"daysAgo": "__count__ 日前",
|
||||
"daysAgo_plural": "__count__ 日前",
|
||||
"hoursAgo": "__count__ 時間前",
|
||||
"hoursAgo_plural": "__count__ 時間前",
|
||||
"minsAgo": "__count__ 分前",
|
||||
"minsAgo_plural": "__count__ 分前",
|
||||
"secondsAgo": "数秒前",
|
||||
"notTracking": "ローカルブランチは現在リモートブランチをトラッキングしていません。",
|
||||
"statusUnmergedChanged": "リポジトリ内にマージされていない変更があります。コンフリクトを解決してコミットしてください。",
|
||||
"repositoryUpToDate": "リポジトリは最新です。",
|
||||
"commitsAhead": "あなたのリポジトリはリモートより__count__コミット進んでいます。現在のコミットをプッシュできます。",
|
||||
"commitsAhead_plural": "あなたのリポジトリはリモートより__count__コミット進んでいます。現在のコミットをプッシュできます。",
|
||||
"commitsBehind": "あなたのリポジトリはリモートより__count__コミット遅れています。現在のコミットをプルできます。",
|
||||
"commitsBehind_plural": "あなたのリポジトリはリモートより__count__コミット遅れています。現在のコミットをプルできます。",
|
||||
"commitsAheadAndBehind1": "あなたのリポジトリはリモートより__count__コミット遅れており、かつ",
|
||||
"commitsAheadAndBehind1_plural": "あなたのリポジトリはリモートより__count__コミット遅れており、かつ",
|
||||
"commitsAheadAndBehind2": "__count__コミット進んでいます。 ",
|
||||
"commitsAheadAndBehind2_plural": "__count__コミット進んでいます。 ",
|
||||
"commitsAheadAndBehind3": "プッシュする前にリモートのコミットをプルしてください。",
|
||||
"commitsAheadAndBehind3_plural": "プッシュする前にリモートのコミットをプルしてください。",
|
||||
"refreshCommitHistory": "コミット履歴を更新",
|
||||
"refreshChanges": "変更を更新"
|
||||
}
|
||||
}
|
||||
},
|
||||
"typedInput": {
|
||||
"type": {
|
||||
"str": "文字列",
|
||||
"num": "数値",
|
||||
"re": "正規表現",
|
||||
"bool": "真偽",
|
||||
"json": "JSON",
|
||||
"bin": "バッファ",
|
||||
"date": "日時",
|
||||
"jsonata": "JSONata式",
|
||||
"env": "環境変数"
|
||||
}
|
||||
},
|
||||
"editableList": {
|
||||
"add": "追加"
|
||||
},
|
||||
"search": {
|
||||
"empty": "一致したものが見つかりませんでした",
|
||||
"addNode": "ノードを追加..."
|
||||
},
|
||||
"expressionEditor": {
|
||||
"functions": "関数",
|
||||
"functionReference": "関数リファレンス",
|
||||
"insert": "挿入",
|
||||
"title": "JSONata式エディタ",
|
||||
"test": "テスト",
|
||||
"data": "メッセージ例",
|
||||
"result": "結果",
|
||||
"format": "整形",
|
||||
"compatMode": "互換モードが有効になっています",
|
||||
"compatModeDesc": "<h3>JSONata互換モード</h3><p> 入力された式では <code>msg</code> を参照しているため、互換モードで評価します。このモードは将来廃止予定のため、式で <code>msg</code> を使わないよう修正してください。</p><p> JSONataをNode-REDで最初にサポートした際には、 <code>msg</code> オブジェクトの参照が必要でした。例えば <code>msg.payload</code> がペイロードを参照するために使われていました。</p><p> 直接メッセージに対して式を評価するようになったため、この形式は使えなくなります。ペイロードを参照するには、単に <code>payload</code> にしてください。</p>",
|
||||
"noMatch": "一致した結果なし",
|
||||
"errors": {
|
||||
"invalid-expr": "不正なJSONata式:\n __message__",
|
||||
"invalid-msg": "不正なJSONメッセージ例:\n __message__",
|
||||
"context-unsupported": "$flowContext や $globalContextの\nコンテキスト機能をテストできません",
|
||||
"eval": "表現評価エラー:\n __message__"
|
||||
}
|
||||
},
|
||||
"jsEditor": {
|
||||
"title": "JavaScriptエディタ"
|
||||
},
|
||||
"jsonEditor": {
|
||||
"title": "JSONエディタ",
|
||||
"format": "JSONフォーマット"
|
||||
},
|
||||
"markdownEditor": {
|
||||
"title": "マークダウンエディタ",
|
||||
"format": "マークダウン形式で記述",
|
||||
"heading1": "見出しレベル1",
|
||||
"heading2": "見出しレベル2",
|
||||
"heading3": "見出しレベル3",
|
||||
"bold": "太字",
|
||||
"italic": "斜体",
|
||||
"code": "コード",
|
||||
"ordered-list": "箇条書き(番号付き)",
|
||||
"unordered-list": "箇条書き",
|
||||
"quote": "引用",
|
||||
"link": "リンク",
|
||||
"horizontal-rule": "区切り線",
|
||||
"toggle-preview": "プレビュー表示切替え"
|
||||
},
|
||||
"bufferEditor": {
|
||||
"title": "バッファエディタ",
|
||||
"modeString": "UTF-8文字列として処理",
|
||||
"modeArray": "JSON配列として処理",
|
||||
"modeDesc": "<h3>バッファエディタ</h3><p>バッファ型は、バイト値から成るJSON配列として格納されます。このエディタは、入力値をJSON配列として構文解析します。もし不正なJSON配列の場合、UTF-8文字列として扱い、各文字コード番号から成る配列へ変換します。</p><p>例えば、 <code>Hello World</code> という値を、以下のJSON配列へ変換します。<pre>[72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100]</pre></p>"
|
||||
},
|
||||
"projects": {
|
||||
"config-git": "Gitクライアントの設定",
|
||||
"welcome": {
|
||||
"hello": "こんにちは! Node-REDで「プロジェクト」機能が利用できるようになりました。",
|
||||
"desc0": "フローファイルの管理方法が刷新され、バージョン管理も可能です。",
|
||||
"desc1": "まず最初にプロジェクトを作成するか、既存のGitリポジトリからプロジェクトをクローンしてください。",
|
||||
"desc2": "とりあえずこの処理をスキップしてもかまいません。「プロジェクト」メニューから、いつでもプロジェクトの作成を開始できます。",
|
||||
"create": "プロジェクトの作成",
|
||||
"clone": "プロジェクトのクローン",
|
||||
"not-right-now": "後にする"
|
||||
},
|
||||
"git-config": {
|
||||
"setup": "バージョン管理クライアントの設定",
|
||||
"desc0": "Node-REDはオープンソースツールのGitを使ってバージョン管理を行います。Gitによりプロジェクトファイルに対する変化を記録し、外部リポジトリに保存することができます。",
|
||||
"desc1": "変更をコミットする際、変更を行った人物の情報としてユーザ名とEmailアドレスをGitが記憶します。ユーザ名は本名でなくても構いません。好きな名前を使ってください。",
|
||||
"desc2": "Gitクライアントの現在の設定は以下の通りです。",
|
||||
"desc3": "設定ダイアログの「Git設定」タブから別途変更することもできます。",
|
||||
"username": "ユーザ名",
|
||||
"email": "Email"
|
||||
},
|
||||
"project-details": {
|
||||
"create": "プロジェクトの作成",
|
||||
"desc0": "プロジェクトはGitリポジトリとして管理します。Gitリポジトリを使ってフローの共有やコラボレーションが簡単にできます。",
|
||||
"desc1": "複数のプロジェクトを作成し、エディタから即座に変更できます。",
|
||||
"desc2": "まず、プロジェクト名と説明(任意)を指定してください。",
|
||||
"already-exists": "既に存在するプロジェクトです",
|
||||
"must-contain": "A-Z 0-9 _ - のみ指定可能",
|
||||
"project-name": "プロジェクト名",
|
||||
"desc": "説明",
|
||||
"opt": "任意"
|
||||
},
|
||||
"clone-project": {
|
||||
"clone": "プロジェクトをクローン",
|
||||
"desc0": "プロジェクトを含んだGitリポジトリを作成済みの場合、クローンを作成することができます。",
|
||||
"already-exists": "既に存在するプロジェクトです",
|
||||
"must-contain": "A-Z 0-9 _ - のみ指定可能",
|
||||
"project-name": "プロジェクト名",
|
||||
"no-info-in-url": "URLにユーザ名/パスワードを含めないようにしてください",
|
||||
"git-url": "GitリポジトリのURL",
|
||||
"protocols": "https://, ssh:// もしくは file://",
|
||||
"auth-failed": "認証に失敗しました",
|
||||
"username": "ユーザ名",
|
||||
"passwd": "パスワード",
|
||||
"ssh-key": "SSHキー",
|
||||
"passphrase": "パスフレーズ",
|
||||
"ssh-key-desc": "SSHでリポジトリをクローンする前にSSHキーを追加してください。",
|
||||
"ssh-key-add": "SSHキーの追加",
|
||||
"credential-key": "認証情報の暗号化キー",
|
||||
"cant-get-ssh-key": "エラー! 選択したSSHキーのパスを取得できません。",
|
||||
"already-exists2": "既に存在します",
|
||||
"git-error": "Gitエラー",
|
||||
"connection-failed": "接続に失敗しました",
|
||||
"not-git-repo": "Gitリポジトリではありません",
|
||||
"repo-not-found": "リポジトリが見つかりません"
|
||||
},
|
||||
"default-files": {
|
||||
"create": "プロジェクト関連ファイルの作成",
|
||||
"desc0": "プロジェクトはフローファイル、README、package.jsonを含みます。",
|
||||
"desc1": "その他、Gitリポジトリで管理したいファイルを含めても構いません。",
|
||||
"desc2": "既存のフローと認証情報ファイルをプロジェクトにコピーします。",
|
||||
"flow-file": "フローファイル",
|
||||
"credentials-file": "認証情報ファイル"
|
||||
},
|
||||
"encryption-config": {
|
||||
"setup": "認証情報ファイルの暗号化設定",
|
||||
"desc0": "フロー認証情報ファイルを暗号化して内容の安全性を担保できます。",
|
||||
"desc1": "認証情報を公開Gitリポジトリに保存する際には、秘密キーフレーズによって暗号化します。",
|
||||
"desc2": "認証情報ファイルは暗号化されていません。",
|
||||
"desc3": "パスワードやアクセストークンといった認証情報を他人が参照できます。",
|
||||
"desc4": "認証情報を公開Gitリポジトリに保存する際には、秘密キーフレーズによって暗号化します。",
|
||||
"desc5": "フロー認証情報ファイルはsettingsファイルのcredentialSecretプロパティで暗号化されています。",
|
||||
"desc6": "フロー認証情報ファイルはシステムが生成したキーによって暗号化されています。このプロジェクト用に新しい秘密キーを指定してください。",
|
||||
"desc7": "キーはプロジェクトファイルとは別に保存されます。他のNode-REDでこのプロジェクトを利用するには、このプロジェクトのキーが必要です。",
|
||||
"credentials": "認証情報",
|
||||
"enable": "暗号化を有効にする",
|
||||
"disable": "暗号化を無効にする",
|
||||
"disabled": "無効",
|
||||
"copy": "既存のキーをコピー",
|
||||
"use-custom": "カスタムキーを使用",
|
||||
"desc8": "認証情報ファイルが暗号化されないため、簡単に読み出すことができます。",
|
||||
"create-project-files": "プロジェクト関連ファイル作成",
|
||||
"create-project": "プロジェクト作成",
|
||||
"already-exists": "既に存在",
|
||||
"git-error": "Gitエラー",
|
||||
"git-auth-error": "Git認証エラー"
|
||||
},
|
||||
"create-success": {
|
||||
"success": "最初のプロジェクトの作成が成功しました!",
|
||||
"desc0": "以降は、これまでと同様にNode-REDを利用できます。",
|
||||
"desc1": "サイドバーの「情報」タブに現在選択されたプロジェクトを表示します。プロジェクト名の隣のボタンでプロジェクト設定画面を呼び出すことができます。",
|
||||
"desc2": "サイドバーの「履歴」タブで変更が加えられたプロジェクト内のファイルを確認しコミットできます。このサイドバーでは、全てのコミット履歴を確認し、変更を外部リポジトリにプッシュすることが可能です。"
|
||||
},
|
||||
"create": {
|
||||
"projects": "プロジェクト",
|
||||
"already-exists": "プロジェクトは既に存在します",
|
||||
"must-contain": "A-Z 0-9 _ - のみ指定可能",
|
||||
"no-info-in-url": "URLにユーザ名/パスワードを含めないようにしてください",
|
||||
"open": "プロジェクトを開く",
|
||||
"create": "プロジェクトを作成",
|
||||
"clone": "プロジェクトをクローン",
|
||||
"project-name": "プロジェクト名",
|
||||
"desc": "説明",
|
||||
"opt": "任意",
|
||||
"flow-file": "フローファイル",
|
||||
"credentials": "認証情報",
|
||||
"enable-encryption": "暗号化を有効にする",
|
||||
"disable-encryption": "暗号化を無効にする",
|
||||
"encryption-key": "暗号化キー",
|
||||
"desc0": "認証情報をセキュアにするためのフレーズ",
|
||||
"desc1": "認証情報ファイルが暗号化されないため、簡単に読み出すことができます",
|
||||
"git-url": "GitリポジトリのURL",
|
||||
"protocols": "https://, ssh:// もしくは file://",
|
||||
"auth-failed": "認証に失敗しました",
|
||||
"username": "ユーザ名",
|
||||
"password": "パスワード",
|
||||
"ssh-key": "SSHキー",
|
||||
"passphrase": "パスフレーズ",
|
||||
"desc2": "SSHでリポジトリをクローンする前にSSHキーを追加してください。",
|
||||
"add-ssh-key": "SSHキーの追加",
|
||||
"credentials-encryption-key": "認証情報の暗号化キー",
|
||||
"already-exists-2": "既に存在します",
|
||||
"git-error": "Gitエラー",
|
||||
"con-failed": "接続に失敗しました",
|
||||
"not-git": "Gitリポジトリではありません",
|
||||
"no-resource": "リポジトリが見つかりません",
|
||||
"cant-get-ssh-key-path": "エラー! 選択したSSHキーのパスを取得できません。",
|
||||
"unexpected_error": "予期しないエラー"
|
||||
},
|
||||
"delete": {
|
||||
"confirm": "プロジェクトを削除しても良いですか?"
|
||||
},
|
||||
"create-project-list": {
|
||||
"search": "プロジェクトを検索",
|
||||
"current": "有効"
|
||||
},
|
||||
"require-clean": {
|
||||
"confirm": "<p>デプロイされていない変更は失われます。</p><p>続けますか?</p>"
|
||||
},
|
||||
"send-req": {
|
||||
"auth-req": "リポジトリ対する認証が必要です",
|
||||
"username": "ユーザ名",
|
||||
"password": "パスワード",
|
||||
"passphrase": "パスフレーズ",
|
||||
"retry": "リトライ",
|
||||
"update-failed": "認証の更新に失敗しました",
|
||||
"unhandled": "エラー応答が処理されませんでした"
|
||||
},
|
||||
"create-branch-list": {
|
||||
"invalid": "不正なブランチ",
|
||||
"create": "ブランチの作成",
|
||||
"current": "有効"
|
||||
},
|
||||
"create-default-file-set": {
|
||||
"no-active": "有効なプロジェクトが無い場合、デフォルトのファイル群を作成できません。",
|
||||
"no-empty": "デフォルトのファイル群を空でないプロジェクトに作成することはできません。",
|
||||
"git-error": "Gitエラー"
|
||||
},
|
||||
"errors": {
|
||||
"no-username-email": "Gitクライアントのユーザ名/emailが設定されていません。",
|
||||
"unexpected": "予期しないエラーが発生しました",
|
||||
"code": "コード"
|
||||
}
|
||||
},
|
||||
"editor-tab": {
|
||||
"properties": "プロパティ",
|
||||
"description": "説明",
|
||||
"appearance": "外観"
|
||||
}
|
||||
}
|
||||
@@ -95,6 +95,10 @@
|
||||
"args": "",
|
||||
"desc": "0以上、1未満の疑似乱数を返します。"
|
||||
},
|
||||
"$millis": {
|
||||
"args": "",
|
||||
"desc": "Unixエポック(1 January, 1970 UTC)からの経過ミリ秒を数値として返します。評価対象式に含まれる `$millis()` の呼び出しは、全て同じ値を返します。"
|
||||
},
|
||||
"$sum": {
|
||||
"args": "array",
|
||||
"desc": "数値の配列 `array` の合計値を返します。 `array` が数値でない要素を含む場合、エラーになります。"
|
||||
@@ -159,6 +163,10 @@
|
||||
"args": "object",
|
||||
"desc": "key/valueのペアを持つオブジェクトを、各要素が1つのkey/valueのペアを持つオブジェクトの配列に分割します。引数がオブジェクトの配列の場合、結果の配列は各オブジェクトから得た各key/valueのペアのオブジェクトを持ちます。"
|
||||
},
|
||||
"$merge": {
|
||||
"args": "array<object>",
|
||||
"desc": "`object` の配列を1つの `object` へマージします。 マージ結果のオブジェクトは入力配列内の各オブジェクトのkey/valueペアを含みます。入力のオブジェクトが同じキーを持つ場合、戻り値の `object` には配列の最後のオブジェクトのkey/value値が格納されます。入力の配列がオブジェクトでない要素を含む場合、エラーとなります。"
|
||||
},
|
||||
"$sift": {
|
||||
"args": "object, function",
|
||||
"desc": "引数 `object` が持つkey/valueのペアのうち、関数 `function` によってふるい分けたオブジェクトのみを返します。\n\n関数 `function` は、以下の引数を持つ必要があります。\n\n`function(value [, key [, object]])`"
|
||||
@@ -186,5 +194,29 @@
|
||||
"$globalContext": {
|
||||
"args": "string",
|
||||
"desc": "グローバルコンテキストのプロパティを取得します。"
|
||||
},
|
||||
"$pad": {
|
||||
"args": "string, width [, char]",
|
||||
"desc": "文字数が引数 `width` の絶対値以上となるよう、必要に応じて追加文字を付け足した `string` のコピーを返します。\n\n`width` が正の値の場合、文字列の右側に追加文字を付け足します。もし負の値の場合、文字列の左側に追加文字を付け足します。\n\n任意の引数 `char` には、本関数で用いる追加文字を指定します。もし追加文字を指定しない場合は、既定値として空白文字を使用します。"
|
||||
},
|
||||
"$fromMillis": {
|
||||
"args": "number",
|
||||
"desc": "Unixエポック(1 January, 1970 UTC)からの経過ミリ秒を表す数値を、ISO 8601形式のタイムスタンプの文字列に変換します。"
|
||||
},
|
||||
"$formatNumber": {
|
||||
"args": "number, picture [, options]",
|
||||
"desc": "`number` を文字列へ変換し、文字列 `picture` に指定した数値表現になるよう書式を変更します。\n\nこの関数の動作は、XPath F&O 3.1の仕様に定義されているXPath/XQuery関数のfn:format-numberの動作と同じです。引数の文字列 picture は、fn:format-numberと同じ構文で数値の書式を定義します。\n\n任意の第三引数 `options` は、小数点記号の様な既定のロケール固有の書式設定文字を上書きするために使用します。この引数を指定する場合、XPath F&O 3.1の仕様の数値形式の項に記述されているname/valueペアを含むオブジェクトでなければなりません。"
|
||||
},
|
||||
"$formatBase": {
|
||||
"args": "number [, radix]",
|
||||
"desc": "`number` を引数 `radix` に指定した値を基数とした形式の文字列に変換します。 `radix` が指定されていない場合、基数10を既定値として設定します。 `radix` には2~36の値を設定でき、それ以外の値の場合はエラーになります。"
|
||||
},
|
||||
"$toMillis": {
|
||||
"args": "timestamp",
|
||||
"desc": "ISO 8601形式の文字列 `timestamp` を、Unixエポック(1 January, 1970 UTC)からの経過ミリ秒を表す数値へ変換します。 文字列が正しい形式でない場合、エラーとなります。"
|
||||
},
|
||||
"$env": {
|
||||
"args": "arg",
|
||||
"desc": "環境変数の値を返します。\n\n本関数はNode-REDの定義関数です。"
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
"common": {
|
||||
"label": {
|
||||
"name": "姓名",
|
||||
"ok": "Ok",
|
||||
"ok": "确认",
|
||||
"done": "完成",
|
||||
"cancel": "取消",
|
||||
"delete": "删除",
|
||||
@@ -22,18 +22,18 @@
|
||||
"status": "状态",
|
||||
"enabled": "有效",
|
||||
"disabled": "无效",
|
||||
"info": "详细描述",
|
||||
"tip": "详细描述支持Markdown轻量级标记语言,并将出现在信息标签中。"
|
||||
"info": "详细描述"
|
||||
},
|
||||
"menu": {
|
||||
"label": {
|
||||
"view": {
|
||||
"view": "表示",
|
||||
"showGrid": "表示网格",
|
||||
"view": "显示",
|
||||
"grid": "网格",
|
||||
"showGrid": "显示网格",
|
||||
"snapGrid": "对齐网格",
|
||||
"gridSize": "网格尺寸",
|
||||
"textDir": "文本方向",
|
||||
"defaultDir": "默认",
|
||||
"defaultDir": "默认方向",
|
||||
"ltr": "从左到右",
|
||||
"rtl": "从右到左",
|
||||
"auto": "上下文"
|
||||
@@ -41,12 +41,15 @@
|
||||
"sidebar": {
|
||||
"show": "显示侧边栏"
|
||||
},
|
||||
"userSettings": "设定",
|
||||
"displayStatus": "表示节点状态",
|
||||
"displayConfig": "配置节点设定",
|
||||
"settings": "设置",
|
||||
"userSettings": "用户设置",
|
||||
"nodes": "节点",
|
||||
"displayStatus": "显示节点状态",
|
||||
"displayConfig": "修改节点配置",
|
||||
"import": "导入",
|
||||
"export": "导出",
|
||||
"search": "查询",
|
||||
"search": "查找流程",
|
||||
"searchInput": "查找流程",
|
||||
"clipboard": "剪贴板",
|
||||
"library": "库",
|
||||
"examples": "例子",
|
||||
@@ -60,21 +63,29 @@
|
||||
"keyboardShortcuts": "键盘快捷方式",
|
||||
"login": "登陆",
|
||||
"logout": "退出",
|
||||
"editPalette": "编辑调面板",
|
||||
"editPalette":"节点管理",
|
||||
"other": "其他",
|
||||
"showTips": "显示小提示"
|
||||
}
|
||||
},
|
||||
"user": {
|
||||
"loggedInAs": "作为__name__登陆",
|
||||
"username": "账号",
|
||||
"password": "密码",
|
||||
"login": "登陆",
|
||||
"loginFailed": "登陆失败",
|
||||
"notAuthorized": "未授权"
|
||||
"notAuthorized": "未授权",
|
||||
"errors": {
|
||||
"settings": "设置信息需要登陆后才能访问",
|
||||
"deploy": "改动需要登陆后才能部署",
|
||||
"notAuthorized": "此操作需要登陆后才能执行"
|
||||
}
|
||||
},
|
||||
"notification": {
|
||||
"warning": "<strong>警告</strong>: __message__",
|
||||
"warnings": {
|
||||
"undeployedChanges": "节点中存在未部署的更改",
|
||||
"nodeActionDisabled": "节点动作在子流程中被禁用",
|
||||
"nodeActionDisabledSubflow": "节点动作在子流程中被禁用",
|
||||
"missing-types": "流程由于缺少节点类型而停止。请检查日志的详细信息",
|
||||
"restartRequired": "Node-RED必须重新启动,以启用升级的模块"
|
||||
},
|
||||
@@ -179,7 +190,6 @@
|
||||
"output": "输出:",
|
||||
"deleteSubflow": "删除子流程",
|
||||
"info": "详细描述",
|
||||
"format": "标记格式",
|
||||
"errors": {
|
||||
"noNodesSelected": "<strong>无法创建子流程</strong>: 未选择节点",
|
||||
"multipleInputsToSelection": "<strong>无法创建子流程</strong>: 多个输入到了选择"
|
||||
@@ -192,10 +202,10 @@
|
||||
"configDelete": "删除",
|
||||
"nodesUse": "__count__个节点使用此配置",
|
||||
"nodesUse_plural": "__count__个节点使用此配置",
|
||||
"addNewConfig": "添加新的__type__配置节点",
|
||||
"addNewConfig": "添加新的__type__配置",
|
||||
"editNode": "编辑__type__节点",
|
||||
"editConfig": "编辑__type__配置节点",
|
||||
"addNewType": "添加新节点__type__...",
|
||||
"editConfig": "编辑__type__配置",
|
||||
"addNewType": "添加新的__type__节点",
|
||||
"nodeProperties": "节点属性",
|
||||
"portLabels": "端口标签",
|
||||
"labelInputs": "输入",
|
||||
@@ -227,7 +237,7 @@
|
||||
"managePalette": "管理面板"
|
||||
},
|
||||
"library": {
|
||||
"openLibrary": "“打开库...",
|
||||
"openLibrary": "打开库...",
|
||||
"saveToLibrary": "保存到库...",
|
||||
"typeLibrary": "__type__类型库",
|
||||
"unnamedType": "无名__type__",
|
||||
@@ -256,7 +266,7 @@
|
||||
"social": "社交",
|
||||
"storage": "存储",
|
||||
"analysis": "分析",
|
||||
"advanced": "高级的"
|
||||
"advanced": "高级"
|
||||
},
|
||||
"event": {
|
||||
"nodeAdded": "添加到面板中的节点:",
|
||||
@@ -347,18 +357,31 @@
|
||||
"sidebar": {
|
||||
"info": {
|
||||
"name": "节点信息",
|
||||
"tabName": "名称",
|
||||
"label": "信息",
|
||||
"node": "节点",
|
||||
"type": "类型",
|
||||
"id": "ID",
|
||||
"status": "状态",
|
||||
"enabled": "启用",
|
||||
"disabled": "禁用",
|
||||
"subflow": "子流程",
|
||||
"instances": "实例",
|
||||
"properties": "属性",
|
||||
"info": "信息",
|
||||
"blank": "空白",
|
||||
"null": "空",
|
||||
"showMore": "展开",
|
||||
"showLess": "收起",
|
||||
"flow": "流程",
|
||||
"selection":"选择",
|
||||
"nodes":"__count__ 个节点",
|
||||
"flowDesc": "流程描述",
|
||||
"subflowDesc": "子流程描述",
|
||||
"nodeHelp": "节点帮助",
|
||||
"none":"无",
|
||||
"arrayItems": "__count__个项目",
|
||||
"showTips": "您可以从设置面板打开提示"
|
||||
"showTips": "您可以从设置面板启用提示信息"
|
||||
},
|
||||
"config": {
|
||||
"name": "配置节点",
|
||||
@@ -369,11 +392,20 @@
|
||||
"flows": "流程",
|
||||
"filterUnused": "未使用",
|
||||
"filterAll": "所有",
|
||||
"filtered": "__count__个隐藏"
|
||||
"filtered": "__count__ 个隐藏"
|
||||
},
|
||||
"palette": {
|
||||
"name": "面板管理",
|
||||
"label": "面板"
|
||||
"name": "节点管理",
|
||||
"label": "节点"
|
||||
},
|
||||
"project": {
|
||||
"label": "项目",
|
||||
"name": "项目",
|
||||
"description": "描述",
|
||||
"dependencies": "依赖",
|
||||
"settings": "设置",
|
||||
"editDescription": "编辑项目描述",
|
||||
"editDependencies": "编辑项目依赖"
|
||||
}
|
||||
},
|
||||
"typedInput": {
|
||||
@@ -381,8 +413,9 @@
|
||||
"str": "文字列",
|
||||
"num": "数字",
|
||||
"re": "正则表达式",
|
||||
"bool": "真伪判断",
|
||||
"bool": "布尔",
|
||||
"json": "JSON",
|
||||
"bin": "二进制流",
|
||||
"date": "时间戳"
|
||||
}
|
||||
},
|
||||
23
packages/node_modules/@node-red/editor-client/locales/zh-CN/infotips.json
vendored
Normal file
23
packages/node_modules/@node-red/editor-client/locales/zh-CN/infotips.json
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"info": {
|
||||
"tip0" : "您可以用 {{core:delete-selection}} 删除选择的节点或链接。",
|
||||
"tip1" : "{{core:search}} 可以在流程内搜索节点。",
|
||||
"tip2": "{{core:toggle-sidebar}} 可以显示或隐藏边栏。",
|
||||
"tip3": "您可以在 {{core:manage-palette}} 中管理节点的控制面板。",
|
||||
"tip4": "边栏中会列出流程中所有的配置节点。您可以通过菜单或者 {{core:show-config-tab}} 来访问这些节点。",
|
||||
"tip5": "您可以在设定中选择显示或隐藏这些提示。",
|
||||
"tip6": "您可以用[left] [up] [down] [right]键来移动被选中的节点。按住[shift]可以更快地移动节点。",
|
||||
"tip7": "把节点拖到连接上可以向连接中插入节点。",
|
||||
"tip8": "您可以用 {{core:show-export-dialog}} 来导出被选中的节点或标签页中的流程。",
|
||||
"tip9": "您可以将流程的json文件拖入编辑框或 {{core:show-import-dialog}} 来导入流程。",
|
||||
"tip10": "按住[shift]后单击并拖动节点可以将该节点的多个连接一并移动到其他节点的端口。",
|
||||
"tip11": "{{core:show-info-tab}} 可以显示「信息」标签页。 {{core:show-debug-tab}} 可以显示「调试」标签页。",
|
||||
"tip12": "按住[ctrl]的同时点击工作界面可以在节点的对话栏中快速添加节点。",
|
||||
"tip13": "按住[ctrl]的同时点击节点的端口或后续节点可以快速连接多个节点。",
|
||||
"tip14": "按住[shift]的同时点击节点会选中所有被连接的节点。",
|
||||
"tip15": "按住[ctrl]的同时点击节点可以在选中或取消选中节点。",
|
||||
"tip16": "{{core:show-previous-tab}} 和 {{core:show-next-tab}} 可以切换标签页。",
|
||||
"tip17": "您可以在节点的属性配置画面中通过 {{core:confirm-edit-tray}} 来更改设置,或者用 {{core:cancel-edit-tray}} 来取消更改。",
|
||||
"tip18": "您可以通过点击 {{core:edit-selected-node}} 来显示被选中节点的属性设置画面。"
|
||||
}
|
||||
}
|
||||
218
packages/node_modules/@node-red/editor-client/locales/zh-CN/jsonata.json
vendored
Normal file
218
packages/node_modules/@node-red/editor-client/locales/zh-CN/jsonata.json
vendored
Normal file
@@ -0,0 +1,218 @@
|
||||
{
|
||||
"$string": {
|
||||
"args": "arg",
|
||||
"desc": "通过以下的类型转换规则将参数*arg*转换成字符串:\n\n - 字符串不转换。\n -函数转换成空的字符串。\n - JSON的值无法用数字表示所以用无限大或者NaN(非数)表示。\n - 用’JSON.stringify’函数将其他值转换成JSON字符串。"
|
||||
},
|
||||
"$length": {
|
||||
"args": "str",
|
||||
"desc": "输出字符串’str’的字数。如果’str’不是字符串,抛出错误。"
|
||||
},
|
||||
"$substring": {
|
||||
"args": "str, start[, length]",
|
||||
"desc": "输出`start`位置后的的首次出现的包括`str`的子字符串。 如果`length`被指定,那么的字符串中将只包括前`length`个文字。如果`start`是负数则输出从`str`末尾开始的`length`个文字"
|
||||
},
|
||||
"$substringBefore": {
|
||||
"args": "str, chars",
|
||||
"desc": "输出’str’中首次出现的’chars’之前的子字符串,如果’str’中不包括’chars’则输出’str’。"
|
||||
},
|
||||
"$substringAfter": {
|
||||
"args": "str, chars",
|
||||
"desc": "输出’str’中首次出现的’chars’之后的子字符串,如果’str’中不包括’chars’则输出’str’。"
|
||||
},
|
||||
"$uppercase": {
|
||||
"args": "str",
|
||||
"desc": "`将’str’中的所有字母变为大写后输出。"
|
||||
},
|
||||
"$lowercase": {
|
||||
"args": "str",
|
||||
"desc": "将’str’中的所有字母变为小写后输出。"
|
||||
},
|
||||
"$trim": {
|
||||
"args": "str",
|
||||
"desc": "将以下步骤应用于`str`来去除所有空白文字并实现标准化。\n\n – 将全部tab制表符、回车键、换行字符用空白代替。\n- 将连续的空白文字变成一个空白文字。\n- 消除开头和末尾的空白文字。\n\n如果`str`没有被指定(即在无输入参数的情况下调用本函数),将上下文的值作为`str`来使用。 如果`str` 不是字符串则抛出错误。"
|
||||
},
|
||||
"$contains": {
|
||||
"args": "str, pattern",
|
||||
"desc": "字符串`str` 和 `pattern`匹配的话输出`true`,不匹配的情况下输出 `false`。 不指定`str`的情况下(比如用一个参数调用本函数时)、将上下文的值作为`str`来使用。参数 `pattern`可以为字符串或正则表达。"
|
||||
},
|
||||
"$split": {
|
||||
"args": "str[, separator][, limit]",
|
||||
"desc": "将参数`str`分解成由子字符串组成的数组。 如果`str`不是字符串抛出错误。可以省略的参数 `separator`中指定字符串`str`的分隔符。分隔符可以是文字或正则表达式。在不指定`separator`的情况下、将分隔符看作空的字符串并把`str`拆分成由单个字母组成的数组。如果`separator`不是字符串则抛出错误。在可省略的参数`limit`中指定分割后的子字符串的最大个数。超出个数的子字符串将被舍弃。如果`limit`没有被指定,`str` 将不考虑子字符串的个数而将字符串完全分隔。如果`limit`是负数则抛出错误。"
|
||||
},
|
||||
"$join": {
|
||||
"args": "array[, separator]",
|
||||
"desc": "用可以省略的参数 `separator`来把多个字符串连接。如果`array`不是字符串则抛出错误。 如果没有指定`separator`,则用空字符串来连接字符(即字符串之间没有`separator`)。 如果`separator`不是字符则抛出错误。"
|
||||
},
|
||||
"$match": {
|
||||
"args": "str, pattern [, limit]",
|
||||
"desc": "对字符串`str`使用正则表达式`pattern`并输出与`str`相匹配的部分信息。"
|
||||
},
|
||||
"$replace": {
|
||||
"args": "str, pattern, replacement [, limit]",
|
||||
"desc": "在字符串`str`中搜索`pattern`并用`replacement`来替换。\n\n可选参数`limit`用来指定替换次数的上限。"
|
||||
},
|
||||
"$now": {
|
||||
"args": "",
|
||||
"desc": "生成ISO 8601互換格式的时刻,并作为字符串输出。"
|
||||
},
|
||||
"$base64encode": {
|
||||
"args": "string",
|
||||
"desc": "将ASCII格式的字符串转换为Base 64格式。将字符串中的文字视作二进制形式的数据处理。包含URI编码在内的字符串文字必须在0x00到0xFF的范围内,否则不会被支持。"
|
||||
},
|
||||
"$base64decode": {
|
||||
"args": "string",
|
||||
"desc": "用UTF-8代码页将Base 64形式二进制值转换为字符串。"
|
||||
},
|
||||
"$number": {
|
||||
"args": "arg",
|
||||
"desc": "用下述的规则将参数 `arg`转换为数值。:\n\n – 数值不做转换。\n – 将字符串中合法的JSON数値表示转换成数値。\n – 其他形式的值则抛出错误。"
|
||||
},
|
||||
"$abs": {
|
||||
"args": "number",
|
||||
"desc": "输出参数`number`的绝对值。"
|
||||
},
|
||||
"$floor": {
|
||||
"args": "number",
|
||||
"desc": "输出比`number`的值小的最大整数。"
|
||||
},
|
||||
"$ceil": {
|
||||
"args": "number",
|
||||
"desc": "输出比`number`的值大的最小整数。"
|
||||
},
|
||||
"$round": {
|
||||
"args": "number [, precision]",
|
||||
"desc": "输出四舍五入后的参数`number`。可省略的参数 `precision`指定四舍五入后小数点下的位数。"
|
||||
},
|
||||
"$power": {
|
||||
"args": "base, exponent",
|
||||
"desc": "输出底数`base`的`exponent`次幂。"
|
||||
},
|
||||
"$sqrt": {
|
||||
"args": "number",
|
||||
"desc": "输出参数 `number`的平方根。"
|
||||
},
|
||||
"$random": {
|
||||
"args": "",
|
||||
"desc": "输出比0大,比1小的伪随机数。"
|
||||
},
|
||||
"$millis": {
|
||||
"args": "",
|
||||
"desc": "返回从UNIX时间 (1970年1月1日 UTC/GMT的午夜)开始到现在的毫秒数。在同一个表达式的测试中所有对`$millis()`的调用将会返回相同的值。"
|
||||
},
|
||||
"$sum": {
|
||||
"args": "array",
|
||||
"desc": "输出数组`array`的总和。如果`array`不是数值则抛出错误。"
|
||||
},
|
||||
"$max": {
|
||||
"args": "array",
|
||||
"desc": "输出数组`array`的最大值。如果`array`不是数值则抛出错误。"
|
||||
},
|
||||
"$min": {
|
||||
"args": "array",
|
||||
"desc": "输出数组`array`的最小值。如果`array`不是数值则抛出错误。。"
|
||||
},
|
||||
"$average": {
|
||||
"args": "array",
|
||||
"desc": "输出数组`array`的平均数。如果`array`不是数值则抛出错误。。"
|
||||
},
|
||||
"$boolean": {
|
||||
"args": "arg",
|
||||
"desc": "用下述规则将数据转换成布尔值。:\n\n - 不转换布尔值`Boolean`。\n – 将空的字符串`string`转换为`false`\n – 将不为空的字符串`string`转换为`true`\n – 将为0的数字`number`转换成`false`\n –将不为0的数字`number`转换成`true`\n –将`null`转换成`false`\n –将空的数组`array`转换成`false`\n –如果数组`array`中含有可以转换成`true`的要素则转换成`true`\n –如果`array`中没有可转换成`true`的要素则转换成`false`\n – 空的对象`object`转换成`false`\n – 非空的对象`object`转换成`true`\n –将函数`function`转换成`false`"
|
||||
},
|
||||
"$not": {
|
||||
"args": "arg",
|
||||
"desc": "输出做取反运算后的布尔值。首先将`arg`转换为布尔值。"
|
||||
},
|
||||
"$exists": {
|
||||
"args": "arg",
|
||||
"desc": "如果算式`arg`的值存在则输出`true`。如果算式的值不存在(比如指向不存在区域的引用)则输出`false`。"
|
||||
},
|
||||
"$count": {
|
||||
"args": "array",
|
||||
"desc": "输出数组中的元素数。"
|
||||
},
|
||||
"$append": {
|
||||
"args": "array, array",
|
||||
"desc": "将两个数组连接。"
|
||||
},
|
||||
"$sort": {
|
||||
"args": "array [, function]",
|
||||
"desc": "输出排序后的数组`array`。\n\n如果使用了比较函数`function`,则下述两个参数需要被指定。\n\n`function(left, right)`\n\n该比较函数是为了比较left和right两个值而被排序算法调用的。如果用户希望left的值被置于right的值之后,那么该函数必须输出布尔值`true`来表示位置交换。而在不需要位置交换时函数必须输出`false`。"
|
||||
},
|
||||
"$reverse": {
|
||||
"args": "array",
|
||||
"desc": "输出倒序后的数组`array`。"
|
||||
},
|
||||
"$shuffle": {
|
||||
"args": "array",
|
||||
"desc": "输出随机排序后的数组 `array`。"
|
||||
},
|
||||
"$zip": {
|
||||
"args": "array, ...",
|
||||
"desc": "将数组中的值按索引顺序打包后输出。"
|
||||
},
|
||||
"$keys": {
|
||||
"args": "object",
|
||||
"desc": "输出由对象内的键组成的数组。如果参数是对象的数组则输出由所有对象中的键去重后组成的队列。"
|
||||
},
|
||||
"$lookup": {
|
||||
"args": "object, key",
|
||||
"desc": "输出对象中与参数`key`对应的值。如果第一个参数`object`是数组,那么数组中所有的对象都将被搜索并输出这些对象中与参数`key`对应的值。"
|
||||
},
|
||||
"$spread": {
|
||||
"args": "object",
|
||||
"desc": "将对象中的键值对分隔成每个要素中只含有一个键值对的数组。如果参数`object`是数组,那么返回值的数组中包含所有对象中的键值对。"
|
||||
},
|
||||
"$merge": {
|
||||
"args": "array<object>",
|
||||
"desc": "将输入数组`objects`中所有的键值对合并到一个`object`中并返回。如果输入数组的要素中含有重复的键,则返回的`object`中将只包含数组中最后出现要素的值。如果输入数组中包括对象以外的元素,则抛出错误。"
|
||||
},
|
||||
"$sift": {
|
||||
"args": "object, function",
|
||||
"desc": "输出参数`object`中符合`function`的键值对。\n\n`function`必须含有下述参数。\n\n`function(value [, key [, object]])`"
|
||||
},
|
||||
"$each": {
|
||||
"args": "object, function",
|
||||
"desc": "将函数`function`应用于`object`中的所有键值对并输出由所有返回值组成的数组。"
|
||||
},
|
||||
"$map": {
|
||||
"args": "array, function",
|
||||
"desc": "将函数`function`应用于数组`array`中所有的值并输出由返回值组成的数组。\n\n`function`中必须含有下述参数。\n\n`function(value [, index [, array]])`"
|
||||
},
|
||||
"$filter": {
|
||||
"args": "array, function",
|
||||
"desc": "输出数组`array`中符合函数`function`条件的值组成的数组。\n\n`function`必须包括下述参数。\n\n`function(value [, index [, array]])`"
|
||||
},
|
||||
"$reduce": {
|
||||
"args": "array, function [, init]",
|
||||
"desc": "将`function`依次应用于数组中的各要素值。 其中,前一个要素值的计算结果将参与到下一次的函数运算中。。\n\n函数`function`接受两个参数并作为中缀表示法中的操作符。\n\n可省略的参数`init`将作为运算的初始值。"
|
||||
},
|
||||
"$flowContext": {
|
||||
"args": "string",
|
||||
"desc": "获取流上下文(流等级的上下文,可以让所有节点共享)的属性。"
|
||||
},
|
||||
"$globalContext": {
|
||||
"args": "string",
|
||||
"desc": "获取全局上下文的属性。"
|
||||
},
|
||||
"$pad": {
|
||||
"args": "string, width [, char]",
|
||||
"desc": "根据需要,向字符串`string`的副本中填充文字使该字符串的字数达到`width`的绝对值并返回填充文字后的字符串。\n\n如果`width`的值为正,则向字符串`string`的右侧填充文字,如果`width`为负,则向字符串`string`的左侧填充文字。\n\n可选参数`char`用来指定填充的文字。如果未指定该参数,则填充空白文字。"
|
||||
},
|
||||
"$fromMillis": {
|
||||
"args": "number",
|
||||
"desc": "将表示从UNIX时间 (1970年1月1日 UTC/GMT的午夜)开始到现在的毫秒数的数值转换成ISO 8601形式时间戳的字符串。"
|
||||
},
|
||||
"$formatNumber": {
|
||||
"args": "number, picture [, options]",
|
||||
"desc": "将`number`转换成具有`picture`所指定的数值格式的字符串。\n\n此函数的功能与XPath F&O 3.1规格中定义的XPath/XQuery函数的fn:format-number功能相一致。参数`picture`用于指定数值的转换格式,其语法与fn:format-number中的定义一致。\n\n可选的第三参数`options`用来覆盖默认的局部环境格式,如小数点分隔符。如果指定该参数,那么该参数必须是包含name/value对的对象,并且name/value对必须符合XPath F&O 3.1规格中记述的数值格式。"
|
||||
},
|
||||
"$formatBase": {
|
||||
"args": "number [, radix]",
|
||||
"desc": "将`number`变换为以参数`radix`的值为基数形式的字符串。如果不指定`radix`的值,则默认基数为10。指定的`radix`值必须在2~36之间,否则抛出错误。"
|
||||
},
|
||||
"$toMillis": {
|
||||
"args": "timestamp",
|
||||
"desc": "将ISO 8601格式的字符串`timestamp`转换为从UNIX时间 (1970年1月1日 UTC/GMT的午夜)开始到现在的毫秒数。如果该字符串的格式不正确,则抛出错误。"
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user