mirror of
https://github.com/Eugeny/tabby.git
synced 2025-08-18 15:21:51 +00:00
Compare commits
72 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
b1752bd0b4 | ||
![]() |
1e697a952a | ||
![]() |
6bad2a2167 | ||
![]() |
61a46e3b4a | ||
![]() |
cba90cec0a | ||
![]() |
7583d92747 | ||
![]() |
e2b99d71ad | ||
![]() |
aac38fa190 | ||
![]() |
7098622c8f | ||
![]() |
8695003c74 | ||
![]() |
43a27a7b7c | ||
![]() |
dd2d2ce20d | ||
![]() |
73574374f0 | ||
![]() |
5bd1bfd565 | ||
![]() |
0611afa8b5 | ||
![]() |
91c9e8affd | ||
![]() |
322ffc5847 | ||
![]() |
21084b5d24 | ||
![]() |
e0efb4073a | ||
![]() |
c42b62afe6 | ||
![]() |
e2b11c83d5 | ||
![]() |
891fa5770a | ||
![]() |
6b395cc2b3 | ||
![]() |
448a1a094f | ||
![]() |
788dd61a13 | ||
![]() |
467684d9ab | ||
![]() |
5069070040 | ||
![]() |
ecf5297bc3 | ||
![]() |
78bd90ac55 | ||
![]() |
712589eb93 | ||
![]() |
f103e71285 | ||
![]() |
0cf883cc4a | ||
![]() |
2b0ad0d558 | ||
![]() |
67bacb9dd3 | ||
![]() |
d0a597634d | ||
![]() |
322014c409 | ||
![]() |
c751a8725b | ||
![]() |
5417efe558 | ||
![]() |
bf356fcd19 | ||
![]() |
10ee66b9dd | ||
![]() |
763da0d80c | ||
![]() |
8d46bb2181 | ||
![]() |
fe936c7726 | ||
![]() |
2f3e32990a | ||
![]() |
22344f8d54 | ||
![]() |
f6d37a39f4 | ||
![]() |
0e4c60ad4b | ||
![]() |
e8c2171d8f | ||
![]() |
f7a5be2c67 | ||
![]() |
39fa0424a6 | ||
![]() |
bcb1b6a13b | ||
![]() |
a19f35ac44 | ||
![]() |
ea92f1a700 | ||
![]() |
b5701cf9f9 | ||
![]() |
4742530cf3 | ||
![]() |
a8d78ce185 | ||
![]() |
bba1eaccbe | ||
![]() |
cd6d05aa69 | ||
![]() |
412403c72a | ||
![]() |
93ae907dd1 | ||
![]() |
ce24b9cc52 | ||
![]() |
dc68372d76 | ||
![]() |
e0fe125cf2 | ||
![]() |
e594fcd0e7 | ||
![]() |
0219da4d85 | ||
![]() |
5e06b2248b | ||
![]() |
cdc3623986 | ||
![]() |
6d016002c0 | ||
![]() |
f3569f5d2d | ||
![]() |
4125582ef2 | ||
![]() |
c6331c9b1c | ||
![]() |
aaab475e5f |
@@ -334,6 +334,15 @@
|
|||||||
"contributions": [
|
"contributions": [
|
||||||
"code"
|
"code"
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "frauhottelmann",
|
||||||
|
"name": "frauhottelmann",
|
||||||
|
"avatar_url": "https://avatars2.githubusercontent.com/u/902705?v=4",
|
||||||
|
"profile": "https://github.com/frauhottelmann",
|
||||||
|
"contributions": [
|
||||||
|
"code"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"contributorsPerLine": 7,
|
"contributorsPerLine": 7,
|
||||||
|
@@ -1,6 +1,8 @@
|
|||||||
parser: '@typescript-eslint/parser'
|
parser: '@typescript-eslint/parser'
|
||||||
parserOptions:
|
parserOptions:
|
||||||
project: tsconfig.json
|
project:
|
||||||
|
- tsconfig.json
|
||||||
|
- '*/tsconfig.typings.json'
|
||||||
extends:
|
extends:
|
||||||
- 'plugin:@typescript-eslint/all'
|
- 'plugin:@typescript-eslint/all'
|
||||||
plugins:
|
plugins:
|
||||||
@@ -37,6 +39,7 @@ rules:
|
|||||||
'@typescript-eslint/no-misused-promises': off
|
'@typescript-eslint/no-misused-promises': off
|
||||||
'@typescript-eslint/typedef': off
|
'@typescript-eslint/typedef': off
|
||||||
'@typescript-eslint/consistent-type-imports': off
|
'@typescript-eslint/consistent-type-imports': off
|
||||||
|
'@typescript-eslint/sort-type-union-intersection-members': off
|
||||||
'@typescript-eslint/no-use-before-define':
|
'@typescript-eslint/no-use-before-define':
|
||||||
- error
|
- error
|
||||||
- classes: false
|
- classes: false
|
||||||
@@ -81,7 +84,8 @@ rules:
|
|||||||
argsIgnorePattern: ^_
|
argsIgnorePattern: ^_
|
||||||
no-undef: error
|
no-undef: error
|
||||||
no-var: error
|
no-var: error
|
||||||
object-curly-spacing:
|
object-curly-spacing: off
|
||||||
|
'@typescript-eslint/object-curly-spacing':
|
||||||
- error
|
- error
|
||||||
- always
|
- always
|
||||||
quote-props:
|
quote-props:
|
||||||
|
9
.github/workflows/linux.yml
vendored
9
.github/workflows/linux.yml
vendored
@@ -38,6 +38,15 @@ jobs:
|
|||||||
GH_TOKEN: ${{ secrets.GH_TOKEN }}
|
GH_TOKEN: ${{ secrets.GH_TOKEN }}
|
||||||
USE_HARD_LINKS: false
|
USE_HARD_LINKS: false
|
||||||
|
|
||||||
|
- name: Upload symbols
|
||||||
|
run: |
|
||||||
|
sudo npm install -g @sentry/cli --unsafe-perm
|
||||||
|
./scripts/sentry-upload.js
|
||||||
|
env:
|
||||||
|
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
|
||||||
|
SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
|
||||||
|
SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }}
|
||||||
|
|
||||||
- name: Package artifacts
|
- name: Package artifacts
|
||||||
run: |
|
run: |
|
||||||
mkdir artifact-deb
|
mkdir artifact-deb
|
||||||
|
13
.github/workflows/macos.yml
vendored
13
.github/workflows/macos.yml
vendored
@@ -26,6 +26,10 @@ jobs:
|
|||||||
cd ..
|
cd ..
|
||||||
rm app/node_modules/.yarn-integrity
|
rm app/node_modules/.yarn-integrity
|
||||||
yarn
|
yarn
|
||||||
|
./node_modules/.bin/patch-package
|
||||||
|
cd app
|
||||||
|
../node_modules/.bin/patch-package
|
||||||
|
cd ..
|
||||||
|
|
||||||
- name: Build native deps
|
- name: Build native deps
|
||||||
run: scripts/build-native.js
|
run: scripts/build-native.js
|
||||||
@@ -62,6 +66,15 @@ jobs:
|
|||||||
ARCH: ${{matrix.arch}}
|
ARCH: ${{matrix.arch}}
|
||||||
# DEBUG: electron-builder,electron-builder:*
|
# DEBUG: electron-builder,electron-builder:*
|
||||||
|
|
||||||
|
- name: Upload symbols
|
||||||
|
run: |
|
||||||
|
sudo npm install -g @sentry/cli --unsafe-perm
|
||||||
|
./scripts/sentry-upload.js
|
||||||
|
env:
|
||||||
|
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
|
||||||
|
SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
|
||||||
|
SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }}
|
||||||
|
|
||||||
- name: Package artifacts
|
- name: Package artifacts
|
||||||
run: |
|
run: |
|
||||||
mkdir artifact-pkg
|
mkdir artifact-pkg
|
||||||
|
9
.github/workflows/windows.yml
vendored
9
.github/workflows/windows.yml
vendored
@@ -34,6 +34,15 @@ jobs:
|
|||||||
run: node scripts/build-windows.js
|
run: node scripts/build-windows.js
|
||||||
if: github.repository != 'Eugeny/terminus' || github.event_name != 'push'
|
if: github.repository != 'Eugeny/terminus' || github.event_name != 'push'
|
||||||
|
|
||||||
|
- name: Upload symbols
|
||||||
|
run: |
|
||||||
|
npm install @sentry/cli
|
||||||
|
node scripts/sentry-upload.js
|
||||||
|
env:
|
||||||
|
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
|
||||||
|
SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
|
||||||
|
SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }}
|
||||||
|
|
||||||
- name: Package artifacts
|
- name: Package artifacts
|
||||||
run: |
|
run: |
|
||||||
mkdir artifact-setup
|
mkdir artifact-setup
|
||||||
|
78
README.md
78
README.md
@@ -1,4 +1,4 @@
|
|||||||
****
|

|
||||||
|
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
@@ -74,57 +74,59 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
|
|||||||
<!-- markdownlint-disable -->
|
<!-- markdownlint-disable -->
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<td align="center"><a href="http://www.russellmyers.com"><img src="https://avatars2.githubusercontent.com/u/184085?v=4" width="100px;" alt=""/><br /><sub><b>Russell Myers</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=mezner" title="Code">💻</a></td>
|
<td align="center"><a href="http://www.russellmyers.com"><img src="https://avatars2.githubusercontent.com/u/184085?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Russell Myers</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=mezner" title="Code">💻</a></td>
|
||||||
<td align="center"><a href="http://www.morwire.com"><img src="https://avatars1.githubusercontent.com/u/3991658?v=4" width="100px;" alt=""/><br /><sub><b>Austin Warren</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=ehwarren" title="Code">💻</a></td>
|
<td align="center"><a href="http://www.morwire.com"><img src="https://avatars1.githubusercontent.com/u/3991658?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Austin Warren</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=ehwarren" title="Code">💻</a></td>
|
||||||
<td align="center"><a href="https://github.com/Drachenkaetzchen"><img src="https://avatars1.githubusercontent.com/u/162974?v=4" width="100px;" alt=""/><br /><sub><b>Felicia Hummel</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=Drachenkaetzchen" title="Code">💻</a></td>
|
<td align="center"><a href="https://github.com/Drachenkaetzchen"><img src="https://avatars1.githubusercontent.com/u/162974?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Felicia Hummel</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=Drachenkaetzchen" title="Code">💻</a></td>
|
||||||
<td align="center"><a href="https://github.com/mikemaccana"><img src="https://avatars2.githubusercontent.com/u/172594?v=4" width="100px;" alt=""/><br /><sub><b>Mike MacCana</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=mikemaccana" title="Tests">⚠️</a> <a href="#design-mikemaccana" title="Design">🎨</a></td>
|
<td align="center"><a href="https://github.com/mikemaccana"><img src="https://avatars2.githubusercontent.com/u/172594?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Mike MacCana</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=mikemaccana" title="Tests">⚠️</a> <a href="#design-mikemaccana" title="Design">🎨</a></td>
|
||||||
<td align="center"><a href="https://github.com/yxuko"><img src="https://avatars1.githubusercontent.com/u/1786317?v=4" width="100px;" alt=""/><br /><sub><b>Yacine Kanzari</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=yxuko" title="Code">💻</a></td>
|
<td align="center"><a href="https://github.com/yxuko"><img src="https://avatars1.githubusercontent.com/u/1786317?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Yacine Kanzari</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=yxuko" title="Code">💻</a></td>
|
||||||
<td align="center"><a href="https://github.com/BBJip"><img src="https://avatars2.githubusercontent.com/u/32908927?v=4" width="100px;" alt=""/><br /><sub><b>BBJip</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=BBJip" title="Code">💻</a></td>
|
<td align="center"><a href="https://github.com/BBJip"><img src="https://avatars2.githubusercontent.com/u/32908927?v=4?s=100" width="100px;" alt=""/><br /><sub><b>BBJip</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=BBJip" title="Code">💻</a></td>
|
||||||
<td align="center"><a href="https://github.com/Futagirl"><img src="https://avatars2.githubusercontent.com/u/33533958?v=4" width="100px;" alt=""/><br /><sub><b>Futagirl</b></sub></a><br /><a href="#design-Futagirl" title="Design">🎨</a></td>
|
<td align="center"><a href="https://github.com/Futagirl"><img src="https://avatars2.githubusercontent.com/u/33533958?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Futagirl</b></sub></a><br /><a href="#design-Futagirl" title="Design">🎨</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td align="center"><a href="https://www.levrik.io"><img src="https://avatars3.githubusercontent.com/u/9491603?v=4" width="100px;" alt=""/><br /><sub><b>Levin Rickert</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=levrik" title="Code">💻</a></td>
|
<td align="center"><a href="https://www.levrik.io"><img src="https://avatars3.githubusercontent.com/u/9491603?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Levin Rickert</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=levrik" title="Code">💻</a></td>
|
||||||
<td align="center"><a href="https://kwonoj.github.io"><img src="https://avatars2.githubusercontent.com/u/1210596?v=4" width="100px;" alt=""/><br /><sub><b>OJ Kwon</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=kwonoj" title="Code">💻</a></td>
|
<td align="center"><a href="https://kwonoj.github.io"><img src="https://avatars2.githubusercontent.com/u/1210596?v=4?s=100" width="100px;" alt=""/><br /><sub><b>OJ Kwon</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=kwonoj" title="Code">💻</a></td>
|
||||||
<td align="center"><a href="https://github.com/Domain"><img src="https://avatars2.githubusercontent.com/u/903197?v=4" width="100px;" alt=""/><br /><sub><b>domain</b></sub></a><br /><a href="#plugin-Domain" title="Plugin/utility libraries">🔌</a> <a href="https://github.com/Eugeny/terminus/commits?author=Domain" title="Code">💻</a></td>
|
<td align="center"><a href="https://github.com/Domain"><img src="https://avatars2.githubusercontent.com/u/903197?v=4?s=100" width="100px;" alt=""/><br /><sub><b>domain</b></sub></a><br /><a href="#plugin-Domain" title="Plugin/utility libraries">🔌</a> <a href="https://github.com/Eugeny/terminus/commits?author=Domain" title="Code">💻</a></td>
|
||||||
<td align="center"><a href="http://www.jbrumond.me"><img src="https://avatars1.githubusercontent.com/u/195127?v=4" width="100px;" alt=""/><br /><sub><b>James Brumond</b></sub></a><br /><a href="#plugin-kbjr" title="Plugin/utility libraries">🔌</a></td>
|
<td align="center"><a href="http://www.jbrumond.me"><img src="https://avatars1.githubusercontent.com/u/195127?v=4?s=100" width="100px;" alt=""/><br /><sub><b>James Brumond</b></sub></a><br /><a href="#plugin-kbjr" title="Plugin/utility libraries">🔌</a></td>
|
||||||
<td align="center"><a href="http://www.growingwiththeweb.com"><img src="https://avatars0.githubusercontent.com/u/2193314?v=4" width="100px;" alt=""/><br /><sub><b>Daniel Imms</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=Tyriar" title="Code">💻</a> <a href="#plugin-Tyriar" title="Plugin/utility libraries">🔌</a> <a href="https://github.com/Eugeny/terminus/commits?author=Tyriar" title="Tests">⚠️</a></td>
|
<td align="center"><a href="http://www.growingwiththeweb.com"><img src="https://avatars0.githubusercontent.com/u/2193314?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Daniel Imms</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=Tyriar" title="Code">💻</a> <a href="#plugin-Tyriar" title="Plugin/utility libraries">🔌</a> <a href="https://github.com/Eugeny/terminus/commits?author=Tyriar" title="Tests">⚠️</a></td>
|
||||||
<td align="center"><a href="https://github.com/baflo"><img src="https://avatars2.githubusercontent.com/u/834350?v=4" width="100px;" alt=""/><br /><sub><b>Florian Bachmann</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=baflo" title="Code">💻</a></td>
|
<td align="center"><a href="https://github.com/baflo"><img src="https://avatars2.githubusercontent.com/u/834350?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Florian Bachmann</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=baflo" title="Code">💻</a></td>
|
||||||
<td align="center"><a href="http://michael-kuehnel.de"><img src="https://avatars2.githubusercontent.com/u/441011?v=4" width="100px;" alt=""/><br /><sub><b>Michael Kühnel</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=mischah" title="Code">💻</a> <a href="#design-mischah" title="Design">🎨</a></td>
|
<td align="center"><a href="http://michael-kuehnel.de"><img src="https://avatars2.githubusercontent.com/u/441011?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Michael Kühnel</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=mischah" title="Code">💻</a> <a href="#design-mischah" title="Design">🎨</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td align="center"><a href="https://github.com/NieLeben"><img src="https://avatars3.githubusercontent.com/u/47182955?v=4" width="100px;" alt=""/><br /><sub><b>Tilmann Meyer</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=NieLeben" title="Code">💻</a></td>
|
<td align="center"><a href="https://github.com/NieLeben"><img src="https://avatars3.githubusercontent.com/u/47182955?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Tilmann Meyer</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=NieLeben" title="Code">💻</a></td>
|
||||||
<td align="center"><a href="http://www.jubeat.net"><img src="https://avatars3.githubusercontent.com/u/11289158?v=4" width="100px;" alt=""/><br /><sub><b>PM Extra</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/issues?q=author%3APMExtra" title="Bug reports">🐛</a></td>
|
<td align="center"><a href="http://www.jubeat.net"><img src="https://avatars3.githubusercontent.com/u/11289158?v=4?s=100" width="100px;" alt=""/><br /><sub><b>PM Extra</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/issues?q=author%3APMExtra" title="Bug reports">🐛</a></td>
|
||||||
<td align="center"><a href="https://jjuhas.keybase.pub//"><img src="https://avatars1.githubusercontent.com/u/6438760?v=4" width="100px;" alt=""/><br /><sub><b>Jonathan</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=IgnusG" title="Code">💻</a></td>
|
<td align="center"><a href="https://jjuhas.keybase.pub//"><img src="https://avatars1.githubusercontent.com/u/6438760?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Jonathan</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=IgnusG" title="Code">💻</a></td>
|
||||||
<td align="center"><a href="https://hans-koch.me"><img src="https://avatars0.githubusercontent.com/u/1093709?v=4" width="100px;" alt=""/><br /><sub><b>Hans Koch</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=hammster" title="Code">💻</a></td>
|
<td align="center"><a href="https://hans-koch.me"><img src="https://avatars0.githubusercontent.com/u/1093709?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Hans Koch</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=hammster" title="Code">💻</a></td>
|
||||||
<td align="center"><a href="http://thepuzzlemaker.info"><img src="https://avatars3.githubusercontent.com/u/12666617?v=4" width="100px;" alt=""/><br /><sub><b>Dak Smyth</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=ThePuzzlemaker" title="Code">💻</a></td>
|
<td align="center"><a href="http://thepuzzlemaker.info"><img src="https://avatars3.githubusercontent.com/u/12666617?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Dak Smyth</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=ThePuzzlemaker" title="Code">💻</a></td>
|
||||||
<td align="center"><a href="http://yfwz100.github.io"><img src="https://avatars2.githubusercontent.com/u/983211?v=4" width="100px;" alt=""/><br /><sub><b>Wang Zhi</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=yfwz100" title="Code">💻</a></td>
|
<td align="center"><a href="http://yfwz100.github.io"><img src="https://avatars2.githubusercontent.com/u/983211?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Wang Zhi</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=yfwz100" title="Code">💻</a></td>
|
||||||
<td align="center"><a href="https://github.com/jack1142"><img src="https://avatars0.githubusercontent.com/u/6032823?v=4" width="100px;" alt=""/><br /><sub><b>jack1142</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=jack1142" title="Code">💻</a></td>
|
<td align="center"><a href="https://github.com/jack1142"><img src="https://avatars0.githubusercontent.com/u/6032823?v=4?s=100" width="100px;" alt=""/><br /><sub><b>jack1142</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=jack1142" title="Code">💻</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td align="center"><a href="https://github.com/hdougie"><img src="https://avatars1.githubusercontent.com/u/450799?v=4" width="100px;" alt=""/><br /><sub><b>Howie Douglas</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=hdougie" title="Code">💻</a></td>
|
<td align="center"><a href="https://github.com/hdougie"><img src="https://avatars1.githubusercontent.com/u/450799?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Howie Douglas</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=hdougie" title="Code">💻</a></td>
|
||||||
<td align="center"><a href="https://chriskaczor.com"><img src="https://avatars2.githubusercontent.com/u/180906?v=4" width="100px;" alt=""/><br /><sub><b>Chris Kaczor</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=ckaczor" title="Code">💻</a></td>
|
<td align="center"><a href="https://chriskaczor.com"><img src="https://avatars2.githubusercontent.com/u/180906?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Chris Kaczor</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=ckaczor" title="Code">💻</a></td>
|
||||||
<td align="center"><a href="https://www.boxmein.net"><img src="https://avatars1.githubusercontent.com/u/358714?v=4" width="100px;" alt=""/><br /><sub><b>Johannes Kadak</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=boxmein" title="Code">💻</a></td>
|
<td align="center"><a href="https://www.boxmein.net"><img src="https://avatars1.githubusercontent.com/u/358714?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Johannes Kadak</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=boxmein" title="Code">💻</a></td>
|
||||||
<td align="center"><a href="https://github.com/LeSeulArtichaut"><img src="https://avatars1.githubusercontent.com/u/38361244?v=4" width="100px;" alt=""/><br /><sub><b>LeSeulArtichaut</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=LeSeulArtichaut" title="Code">💻</a></td>
|
<td align="center"><a href="https://github.com/LeSeulArtichaut"><img src="https://avatars1.githubusercontent.com/u/38361244?v=4?s=100" width="100px;" alt=""/><br /><sub><b>LeSeulArtichaut</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=LeSeulArtichaut" title="Code">💻</a></td>
|
||||||
<td align="center"><a href="https://github.com/CyrilTaylor"><img src="https://avatars0.githubusercontent.com/u/12631466?v=4" width="100px;" alt=""/><br /><sub><b>Cyril Taylor</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=CyrilTaylor" title="Code">💻</a></td>
|
<td align="center"><a href="https://github.com/CyrilTaylor"><img src="https://avatars0.githubusercontent.com/u/12631466?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Cyril Taylor</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=CyrilTaylor" title="Code">💻</a></td>
|
||||||
<td align="center"><a href="https://github.com/nstefanou"><img src="https://avatars3.githubusercontent.com/u/51129173?v=4" width="100px;" alt=""/><br /><sub><b>nstefanou</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=nstefanou" title="Code">💻</a> <a href="#plugin-nstefanou" title="Plugin/utility libraries">🔌</a></td>
|
<td align="center"><a href="https://github.com/nstefanou"><img src="https://avatars3.githubusercontent.com/u/51129173?v=4?s=100" width="100px;" alt=""/><br /><sub><b>nstefanou</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=nstefanou" title="Code">💻</a> <a href="#plugin-nstefanou" title="Plugin/utility libraries">🔌</a></td>
|
||||||
<td align="center"><a href="https://github.com/orin220444"><img src="https://avatars3.githubusercontent.com/u/30747229?v=4" width="100px;" alt=""/><br /><sub><b>orin220444</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=orin220444" title="Code">💻</a></td>
|
<td align="center"><a href="https://github.com/orin220444"><img src="https://avatars3.githubusercontent.com/u/30747229?v=4?s=100" width="100px;" alt=""/><br /><sub><b>orin220444</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=orin220444" title="Code">💻</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td align="center"><a href="https://github.com/Goobles"><img src="https://avatars3.githubusercontent.com/u/8776771?v=4" width="100px;" alt=""/><br /><sub><b>Gobius Dolhain</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=Goobles" title="Code">💻</a></td>
|
<td align="center"><a href="https://github.com/Goobles"><img src="https://avatars3.githubusercontent.com/u/8776771?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Gobius Dolhain</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=Goobles" title="Code">💻</a></td>
|
||||||
<td align="center"><a href="https://github.com/3l0w"><img src="https://avatars2.githubusercontent.com/u/37798980?v=4" width="100px;" alt=""/><br /><sub><b>Gwilherm Folliot</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=3l0w" title="Code">💻</a></td>
|
<td align="center"><a href="https://github.com/3l0w"><img src="https://avatars2.githubusercontent.com/u/37798980?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Gwilherm Folliot</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=3l0w" title="Code">💻</a></td>
|
||||||
<td align="center"><a href="https://github.com/Dimitory"><img src="https://avatars0.githubusercontent.com/u/475955?v=4" width="100px;" alt=""/><br /><sub><b>Dmitry Pronin</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=dimitory" title="Code">💻</a></td>
|
<td align="center"><a href="https://github.com/Dimitory"><img src="https://avatars0.githubusercontent.com/u/475955?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Dmitry Pronin</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=dimitory" title="Code">💻</a></td>
|
||||||
<td align="center"><a href="https://github.com/JonathanBeverley"><img src="https://avatars1.githubusercontent.com/u/20328966?v=4" width="100px;" alt=""/><br /><sub><b>Jonathan Beverley</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=JonathanBeverley" title="Code">💻</a></td>
|
<td align="center"><a href="https://github.com/JonathanBeverley"><img src="https://avatars1.githubusercontent.com/u/20328966?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Jonathan Beverley</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=JonathanBeverley" title="Code">💻</a></td>
|
||||||
<td align="center"><a href="https://github.com/zend"><img src="https://avatars1.githubusercontent.com/u/25160?v=4" width="100px;" alt=""/><br /><sub><b>Zenghai Liang</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=zend" title="Code">💻</a></td>
|
<td align="center"><a href="https://github.com/zend"><img src="https://avatars1.githubusercontent.com/u/25160?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Zenghai Liang</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=zend" title="Code">💻</a></td>
|
||||||
<td align="center"><a href="https://about.me/matishadow"><img src="https://avatars0.githubusercontent.com/u/9083085?v=4" width="100px;" alt=""/><br /><sub><b>Mateusz Tracz</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=matishadow" title="Code">💻</a></td>
|
<td align="center"><a href="https://about.me/matishadow"><img src="https://avatars0.githubusercontent.com/u/9083085?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Mateusz Tracz</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=matishadow" title="Code">💻</a></td>
|
||||||
<td align="center"><a href="https://zergpool.com"><img src="https://avatars3.githubusercontent.com/u/36234677?v=4" width="100px;" alt=""/><br /><sub><b>pinpin</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=pinpins" title="Code">💻</a></td>
|
<td align="center"><a href="https://zergpool.com"><img src="https://avatars3.githubusercontent.com/u/36234677?v=4?s=100" width="100px;" alt=""/><br /><sub><b>pinpin</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=pinpins" title="Code">💻</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td align="center"><a href="https://github.com/TakuroOnoda"><img src="https://avatars0.githubusercontent.com/u/1407926?v=4" width="100px;" alt=""/><br /><sub><b>Takuro Onoda</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=TakuroOnoda" title="Code">💻</a></td>
|
<td align="center"><a href="https://github.com/TakuroOnoda"><img src="https://avatars0.githubusercontent.com/u/1407926?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Takuro Onoda</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=TakuroOnoda" title="Code">💻</a></td>
|
||||||
|
<td align="center"><a href="https://github.com/frauhottelmann"><img src="https://avatars2.githubusercontent.com/u/902705?v=4?s=100" width="100px;" alt=""/><br /><sub><b>frauhottelmann</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=frauhottelmann" title="Code">💻</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<!-- markdownlint-enable -->
|
<!-- markdownlint-restore -->
|
||||||
<!-- prettier-ignore-end -->
|
<!-- prettier-ignore-end -->
|
||||||
|
|
||||||
<!-- ALL-CONTRIBUTORS-LIST:END -->
|
<!-- ALL-CONTRIBUTORS-LIST:END -->
|
||||||
|
|
||||||
This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
|
This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
|
||||||
|
@@ -75,7 +75,7 @@ export class Application {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onGlobalHotkey (): void {
|
onGlobalHotkey (): void {
|
||||||
if (this.windows.some(x => x.isFocused())) {
|
if (this.windows.some(x => x.isFocused() && x.isVisible())) {
|
||||||
for (const window of this.windows) {
|
for (const window of this.windows) {
|
||||||
window.hide()
|
window.hide()
|
||||||
}
|
}
|
||||||
@@ -147,7 +147,7 @@ export class Application {
|
|||||||
|
|
||||||
handleSecondInstance (argv: string[], cwd: string): void {
|
handleSecondInstance (argv: string[], cwd: string): void {
|
||||||
this.presentAllWindows()
|
this.presentAllWindows()
|
||||||
this.windows[this.windows.length - 1].handleSecondInstance(argv, cwd)
|
this.windows[this.windows.length - 1].passCliArguments(argv, cwd, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
private setupMenu () {
|
private setupMenu () {
|
||||||
|
@@ -6,7 +6,7 @@ import { app } from 'electron'
|
|||||||
export function loadConfig (): any {
|
export function loadConfig (): any {
|
||||||
const configPath = path.join(app.getPath('userData'), 'config.yaml')
|
const configPath = path.join(app.getPath('userData'), 'config.yaml')
|
||||||
if (fs.existsSync(configPath)) {
|
if (fs.existsSync(configPath)) {
|
||||||
return yaml.safeLoad(fs.readFileSync(configPath, 'utf8'))
|
return yaml.load(fs.readFileSync(configPath, 'utf8'))
|
||||||
} else {
|
} else {
|
||||||
return {}
|
return {}
|
||||||
}
|
}
|
||||||
|
@@ -53,7 +53,7 @@ if (argv.d) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
app.on('ready', () => {
|
app.on('ready', async () => {
|
||||||
if (process.platform === 'darwin') {
|
if (process.platform === 'darwin') {
|
||||||
app.dock.setMenu(Menu.buildFromTemplate([
|
app.dock.setMenu(Menu.buildFromTemplate([
|
||||||
{
|
{
|
||||||
@@ -65,5 +65,8 @@ app.on('ready', () => {
|
|||||||
]))
|
]))
|
||||||
}
|
}
|
||||||
application.init()
|
application.init()
|
||||||
application.newWindow({ hidden: argv.hidden })
|
|
||||||
|
const window = await application.newWindow({ hidden: argv.hidden })
|
||||||
|
await window.ready
|
||||||
|
window.passCliArguments(process.argv, process.cwd(), false)
|
||||||
})
|
})
|
||||||
|
@@ -1,7 +1,4 @@
|
|||||||
import * as glasstron from 'glasstron'
|
import * as glasstron from 'glasstron'
|
||||||
if (process.platform === 'win32' || process.platform === 'linux') {
|
|
||||||
glasstron.init()
|
|
||||||
}
|
|
||||||
|
|
||||||
import { Subject, Observable } from 'rxjs'
|
import { Subject, Observable } from 'rxjs'
|
||||||
import { debounceTime } from 'rxjs/operators'
|
import { debounceTime } from 'rxjs/operators'
|
||||||
@@ -29,7 +26,7 @@ abstract class GlasstronWindow extends BrowserWindow {
|
|||||||
abstract setBlur (_: boolean)
|
abstract setBlur (_: boolean)
|
||||||
}
|
}
|
||||||
|
|
||||||
const macOSVibrancyType = compareVersions.compare(macOSRelease().version, '10.14', '>=') ? 'fullscreen-ui' : 'dark'
|
const macOSVibrancyType = process.platform === 'darwin' ? compareVersions.compare(macOSRelease().version, '10.14', '>=') ? 'fullscreen-ui' : 'dark' : null
|
||||||
|
|
||||||
export class Window {
|
export class Window {
|
||||||
ready: Promise<void>
|
ready: Promise<void>
|
||||||
@@ -39,7 +36,7 @@ export class Window {
|
|||||||
private windowConfig: ElectronConfig
|
private windowConfig: ElectronConfig
|
||||||
private windowBounds?: Rectangle
|
private windowBounds?: Rectangle
|
||||||
private closing = false
|
private closing = false
|
||||||
private lastVibrancy: {enabled: boolean, type?: string} | null = null
|
private lastVibrancy: { enabled: boolean, type?: string } | null = null
|
||||||
private disableVibrancyWhileDragging = false
|
private disableVibrancyWhileDragging = false
|
||||||
private configStore: any
|
private configStore: any
|
||||||
|
|
||||||
@@ -66,7 +63,9 @@ export class Window {
|
|||||||
preload: path.join(__dirname, 'sentry.js'),
|
preload: path.join(__dirname, 'sentry.js'),
|
||||||
backgroundThrottling: false,
|
backgroundThrottling: false,
|
||||||
enableRemoteModule: true,
|
enableRemoteModule: true,
|
||||||
|
contextIsolation: false,
|
||||||
},
|
},
|
||||||
|
maximizable: true,
|
||||||
frame: false,
|
frame: false,
|
||||||
show: false,
|
show: false,
|
||||||
backgroundColor: '#00000000',
|
backgroundColor: '#00000000',
|
||||||
@@ -149,7 +148,11 @@ export class Window {
|
|||||||
if (process.platform === 'win32') {
|
if (process.platform === 'win32') {
|
||||||
if (parseFloat(os.release()) >= 10) {
|
if (parseFloat(os.release()) >= 10) {
|
||||||
this.window.blurType = enabled ? type === 'fluent' ? 'acrylic' : 'blurbehind' : null
|
this.window.blurType = enabled ? type === 'fluent' ? 'acrylic' : 'blurbehind' : null
|
||||||
|
try {
|
||||||
this.window.setBlur(enabled)
|
this.window.setBlur(enabled)
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to set window blur', error)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
DwmEnableBlurBehindWindow(this.window, enabled)
|
DwmEnableBlurBehindWindow(this.window, enabled)
|
||||||
}
|
}
|
||||||
@@ -188,6 +191,10 @@ export class Window {
|
|||||||
return this.window.isFocused()
|
return this.window.isFocused()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isVisible (): boolean {
|
||||||
|
return this.window.isVisible()
|
||||||
|
}
|
||||||
|
|
||||||
hide (): void {
|
hide (): void {
|
||||||
if (process.platform === 'darwin') {
|
if (process.platform === 'darwin') {
|
||||||
// Lose focus
|
// Lose focus
|
||||||
@@ -223,8 +230,8 @@ export class Window {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handleSecondInstance (argv: string[], cwd: string): void {
|
passCliArguments (argv: string[], cwd: string, secondInstance: boolean): void {
|
||||||
this.send('host:second-instance', parseArgs(argv, cwd), cwd)
|
this.send('cli', parseArgs(argv, cwd), cwd, secondInstance)
|
||||||
}
|
}
|
||||||
|
|
||||||
private setupWindowManagement () {
|
private setupWindowManagement () {
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "terminus",
|
"name": "terminus",
|
||||||
"description": "A terminal for a modern age",
|
"description": "A terminal for a modern age",
|
||||||
|
"private": true,
|
||||||
"repository": "https://github.com/eugeny/terminus",
|
"repository": "https://github.com/eugeny/terminus",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "Eugene Pankov",
|
"name": "Eugene Pankov",
|
||||||
@@ -13,24 +14,25 @@
|
|||||||
"watch": "webpack --progress --color --watch"
|
"watch": "webpack --progress --color --watch"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@angular/animations": "^9.1.9",
|
"@angular/animations": "^11.1.1",
|
||||||
"@angular/common": "^9.1.11",
|
"@angular/common": "^11.1.1",
|
||||||
"@angular/compiler": "^9.1.9",
|
"@angular/compiler": "^11.1.1",
|
||||||
"@angular/core": "^9.1.9",
|
"@angular/core": "^11.1.1",
|
||||||
"@angular/forms": "^9.1.11",
|
"@angular/forms": "^11.1.1",
|
||||||
"@angular/platform-browser": "^9.1.9",
|
"@angular/platform-browser": "^11.1.1",
|
||||||
"@angular/platform-browser-dynamic": "^9.1.9",
|
"@angular/platform-browser-dynamic": "^11.1.1",
|
||||||
"@ng-bootstrap/ng-bootstrap": "^6.1.0",
|
"@ng-bootstrap/ng-bootstrap": "^6.1.0",
|
||||||
"@terminus-term/node-pty": "0.10.0-beta11",
|
"@terminus-term/node-pty": "0.10.0-terminus.2",
|
||||||
"electron-config": "2.0.0",
|
"electron-config": "2.0.0",
|
||||||
"electron-debug": "^3.0.1",
|
"electron-debug": "^3.2.0",
|
||||||
"electron-is-dev": "1.1.0",
|
"electron-is-dev": "1.2.0",
|
||||||
"electron-promise-ipc": "^2.2.4",
|
"electron-promise-ipc": "^2.2.4",
|
||||||
"fontmanager-redux": "1.0.0",
|
"fontmanager-redux": "1.0.0",
|
||||||
"glasstron": "0.0.5",
|
"glasstron": "0.0.6",
|
||||||
"js-yaml": "3.14.0",
|
"js-yaml": "4.0.0",
|
||||||
"keytar": "^7.2.0",
|
"keytar": "^7.2.0",
|
||||||
"mz": "^2.7.0",
|
"mz": "^2.7.0",
|
||||||
|
"native-process-working-directory": "^1.0.2",
|
||||||
"ngx-toastr": "^12.0.1",
|
"ngx-toastr": "^12.0.1",
|
||||||
"npm": "6",
|
"npm": "6",
|
||||||
"path": "0.12.7",
|
"path": "0.12.7",
|
||||||
|
12
app/patches/node-abi+2.19.3.patch
Normal file
12
app/patches/node-abi+2.19.3.patch
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
diff --git a/node_modules/node-abi/abi_registry.json b/node_modules/node-abi/abi_registry.json
|
||||||
|
index bc1436d..630c1b7 100644
|
||||||
|
--- a/node_modules/node-abi/abi_registry.json
|
||||||
|
+++ b/node_modules/node-abi/abi_registry.json
|
||||||
|
@@ -94,6 +94,6 @@
|
||||||
|
"future": true,
|
||||||
|
"lts": false,
|
||||||
|
"runtime": "electron",
|
||||||
|
- "target": "12.0.0-nightly.20201013"
|
||||||
|
+ "target": "12.0.0-beta.16"
|
||||||
|
}
|
||||||
|
]
|
@@ -95,3 +95,7 @@ input[type=range] {
|
|||||||
&::-moz-range-track { @include track(); }
|
&::-moz-range-track { @include track(); }
|
||||||
&::-ms-track { @include track(); }
|
&::-ms-track { @include track(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
a[ngbdropdownitem] {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
167
app/yarn.lock
167
app/yarn.lock
@@ -2,40 +2,54 @@
|
|||||||
# yarn lockfile v1
|
# yarn lockfile v1
|
||||||
|
|
||||||
|
|
||||||
"@angular/animations@^9.1.9":
|
"@angular/animations@^11.1.1":
|
||||||
version "9.1.13"
|
version "11.1.1"
|
||||||
resolved "https://registry.npmjs.org/@angular/animations/-/animations-9.1.13.tgz"
|
resolved "https://registry.yarnpkg.com/@angular/animations/-/animations-11.1.1.tgz#3ae6754e70ecf858322a432f6484a1bab1013315"
|
||||||
integrity sha512-ane1eeQmsP7fcAiLgRhle7YIDgE88WDMMvzqJYhSxwLzXNF/hwqNeskmNcjo8bLt9h/yTIjrCQbycLCHJfU8UQ==
|
integrity sha512-okideoWvlTz6VqHXDWKlMGj1beWxq/ag4n/+7y8IENQFgrKQWu4m52Igr5sJUfT1W8rXqLPaSGEpp9h+1SCDcQ==
|
||||||
|
dependencies:
|
||||||
|
tslib "^2.0.0"
|
||||||
|
|
||||||
"@angular/common@^9.1.11":
|
"@angular/common@^11.1.1":
|
||||||
version "9.1.13"
|
version "11.1.1"
|
||||||
resolved "https://registry.npmjs.org/@angular/common/-/common-9.1.13.tgz"
|
resolved "https://registry.yarnpkg.com/@angular/common/-/common-11.1.1.tgz#fcf16d3d35cdc64c40458a51f879ab61ed2ecdf2"
|
||||||
integrity sha512-QACUhJWlly/nfHUmjopVS1p6ayxxa/NqjyftdCeBJaoyM2YohqWixP/n/keu1K/srJ96aFpUNsZQgmgoRv5SOQ==
|
integrity sha512-YHAmbjmwqIv43CdzRJkXJiT7p6Xm6DpsGKLuCGPoomUk7Nf5U5LsSZm/uvyTu0O+OQp2RUFUdGqW5DzSZZnKtQ==
|
||||||
|
dependencies:
|
||||||
|
tslib "^2.0.0"
|
||||||
|
|
||||||
"@angular/compiler@^9.1.9":
|
"@angular/compiler@^11.1.1":
|
||||||
version "9.1.13"
|
version "11.1.1"
|
||||||
resolved "https://registry.npmjs.org/@angular/compiler/-/compiler-9.1.13.tgz"
|
resolved "https://registry.yarnpkg.com/@angular/compiler/-/compiler-11.1.1.tgz#cafe43b52fb69f0b9493e597baec14fcffd13d7d"
|
||||||
integrity sha512-9MLB1Xx7odKuxDoybVwiOB1ZEUZpL8FurYm4RVuW39ntsUt0IMC9Hb8UagZLTAWhaWSHydkD/KBQVVobGqd0lA==
|
integrity sha512-kybGddMBL6E2BFBOHIX39VsKVxH3yD7NA1g2mQUE9KIqLAavH0KLBr8B03R9MKb6+BElGpk/5yCyCkzkwQES7w==
|
||||||
|
dependencies:
|
||||||
|
tslib "^2.0.0"
|
||||||
|
|
||||||
"@angular/core@^9.1.9":
|
"@angular/core@^11.1.1":
|
||||||
version "9.1.13"
|
version "11.1.1"
|
||||||
resolved "https://registry.npmjs.org/@angular/core/-/core-9.1.13.tgz"
|
resolved "https://registry.yarnpkg.com/@angular/core/-/core-11.1.1.tgz#62bf9ad93d5d88afacce3ea5b03803ec5790d20b"
|
||||||
integrity sha512-mBm24Q9GjkAsxMAzqQ86U1078+yTEpr0+syMEruUtJ0HUH6Fzn3J+6xTLb+BVcGb9RkCkFaV9T5mcn6ZM0f++g==
|
integrity sha512-yBBLekXeDviZ+KW3DmGeOK0CK/yQ9gCy2uHY47KUDI4UTRRLz0NI5nS9NdKwk5bpCPId6ZPNsJtHPBFXRhAnNA==
|
||||||
|
dependencies:
|
||||||
|
tslib "^2.0.0"
|
||||||
|
|
||||||
"@angular/forms@^9.1.11":
|
"@angular/forms@^11.1.1":
|
||||||
version "9.1.13"
|
version "11.1.1"
|
||||||
resolved "https://registry.npmjs.org/@angular/forms/-/forms-9.1.13.tgz"
|
resolved "https://registry.yarnpkg.com/@angular/forms/-/forms-11.1.1.tgz#c8c468aba528f1f2764cf0bc7d9ab36636795473"
|
||||||
integrity sha512-soGVZmPq2bzkxvtTyeJB8p3ejzm4xxt+43hJw6Ag8NxpwUFPVa30oJge3JV+u8Y4yBtl5SbOZ4bBX3EkMxLcGQ==
|
integrity sha512-MVysENcKonjMowdd2SxXQGcvNVpMTWVhwr5IZ2FBZKW/FNnSBq0R3nsr25zU0h8QWQHkROPtFF0+AEaENh/yAg==
|
||||||
|
dependencies:
|
||||||
|
tslib "^2.0.0"
|
||||||
|
|
||||||
"@angular/platform-browser-dynamic@^9.1.9":
|
"@angular/platform-browser-dynamic@^11.1.1":
|
||||||
version "9.1.13"
|
version "11.1.1"
|
||||||
resolved "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-9.1.13.tgz"
|
resolved "https://registry.yarnpkg.com/@angular/platform-browser-dynamic/-/platform-browser-dynamic-11.1.1.tgz#2e05d719a1d134a9a22fb4e4a40234ac49ba122a"
|
||||||
integrity sha512-jCeHyAZ4Nap1/FOqAlKEg9UxQaSkHrxnQr6hYtWwC4ZDVUn3zLWQf6J+mbeYNOXN5yQxEiIqqhORYeOCLLqf1w==
|
integrity sha512-fI44VfQvwzNeZdSMGZEYqYZ6Q4Y1fSbyqh2hzbhVW4/Tq6s4qKdKn3TfAD6iK6te5ewZwbccfr4Y0zMbcwTSRA==
|
||||||
|
dependencies:
|
||||||
|
tslib "^2.0.0"
|
||||||
|
|
||||||
"@angular/platform-browser@^9.1.9":
|
"@angular/platform-browser@^11.1.1":
|
||||||
version "9.1.13"
|
version "11.1.1"
|
||||||
resolved "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-9.1.13.tgz"
|
resolved "https://registry.yarnpkg.com/@angular/platform-browser/-/platform-browser-11.1.1.tgz#d9940e92664b06a3c6a10221f1b9438ba94b9b5f"
|
||||||
integrity sha512-F3iTz1zNbtrs7KFKUxbj8qmTsd/fiuTNcpBExjE5TtatRiE6J8vNvN1+Z/1FgPe0UXBSdTzSwZ8/RxWKw20RMw==
|
integrity sha512-z3OmXK9viTxNp2KpGdCiFkFCI69WVYyuMQerCwjuD2oymRpltc64uujIq3+j32UJ+sTGrjMSmgMo7ReAYMp7sg==
|
||||||
|
dependencies:
|
||||||
|
tslib "^2.0.0"
|
||||||
|
|
||||||
"@iarna/cli@^1.2.0":
|
"@iarna/cli@^1.2.0":
|
||||||
version "1.2.0"
|
version "1.2.0"
|
||||||
@@ -117,12 +131,12 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
debug "^4.1.1"
|
debug "^4.1.1"
|
||||||
|
|
||||||
"@terminus-term/node-pty@0.10.0-beta11":
|
"@terminus-term/node-pty@0.10.0-terminus.2":
|
||||||
version "0.10.0-beta11"
|
version "0.10.0-terminus.2"
|
||||||
resolved "https://registry.yarnpkg.com/@terminus-term/node-pty/-/node-pty-0.10.0-beta11.tgz#9e83041bc0644f17a4329c41a13d09575653c544"
|
resolved "https://registry.yarnpkg.com/@terminus-term/node-pty/-/node-pty-0.10.0-terminus.2.tgz#028c7762d13150984bc800b8cd954ceb7dbcac68"
|
||||||
integrity sha512-ZrplD84UNV8qpCNpsG8DAo8fmoRP1Ynb9QsApIleCJjbeNvUP2ZAeR6wo0aV9B7Zqjvq5O4hoUSayIDGtORH+A==
|
integrity sha512-vcscP3jldTMZeHv0XVxQjwEtnh0usUQgUWvsXtPRMy2rMjijwC1+8xFp/FKPpLpWYNTN8WWmRjSdiw+qGGU4CQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
node-addon-api "^3.0.2"
|
nan "^2.14.0"
|
||||||
|
|
||||||
"@types/mz@0.0.32":
|
"@types/mz@0.0.32":
|
||||||
version "0.0.32"
|
version "0.0.32"
|
||||||
@@ -259,12 +273,10 @@ are-we-there-yet@~1.1.2:
|
|||||||
delegates "^1.0.0"
|
delegates "^1.0.0"
|
||||||
readable-stream "^2.0.6"
|
readable-stream "^2.0.6"
|
||||||
|
|
||||||
argparse@^1.0.7:
|
argparse@^2.0.1:
|
||||||
version "1.0.10"
|
version "2.0.1"
|
||||||
resolved "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz"
|
resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38"
|
||||||
integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==
|
integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==
|
||||||
dependencies:
|
|
||||||
sprintf-js "~1.0.2"
|
|
||||||
|
|
||||||
asap@^2.0.0:
|
asap@^2.0.0:
|
||||||
version "2.0.6"
|
version "2.0.6"
|
||||||
@@ -837,10 +849,10 @@ electron-config@2.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
conf "^1.0.0"
|
conf "^1.0.0"
|
||||||
|
|
||||||
electron-debug@^3.0.1:
|
electron-debug@^3.2.0:
|
||||||
version "3.1.0"
|
version "3.2.0"
|
||||||
resolved "https://registry.npmjs.org/electron-debug/-/electron-debug-3.1.0.tgz"
|
resolved "https://registry.yarnpkg.com/electron-debug/-/electron-debug-3.2.0.tgz#46a15b555c3b11872218c65ea01d058aa0814920"
|
||||||
integrity sha512-SWEqLj4MgfV3tGuO5eBLQ5/Nr6M+KPxsnE0bUJZvQebGJus6RAcdmvd7L+l0Ji31h2mmrN23l2tHFtCa2FvurA==
|
integrity sha512-7xZh+LfUvJ52M9rn6N+tPuDw6oRAjxUj9SoxAZfJ0hVCXhZCsdkrSt7TgXOiWiEOBgEV8qwUIO/ScxllsPS7ow==
|
||||||
dependencies:
|
dependencies:
|
||||||
electron-is-dev "^1.1.0"
|
electron-is-dev "^1.1.0"
|
||||||
electron-localshortcut "^3.1.0"
|
electron-localshortcut "^3.1.0"
|
||||||
@@ -850,7 +862,12 @@ electron-is-accelerator@^0.1.0:
|
|||||||
resolved "https://registry.npmjs.org/electron-is-accelerator/-/electron-is-accelerator-0.1.2.tgz"
|
resolved "https://registry.npmjs.org/electron-is-accelerator/-/electron-is-accelerator-0.1.2.tgz"
|
||||||
integrity sha1-UJ5RDCala1Xhf4Y6SwThEYRqsns=
|
integrity sha1-UJ5RDCala1Xhf4Y6SwThEYRqsns=
|
||||||
|
|
||||||
electron-is-dev@1.1.0, electron-is-dev@^1.1.0:
|
electron-is-dev@1.2.0:
|
||||||
|
version "1.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/electron-is-dev/-/electron-is-dev-1.2.0.tgz#2e5cea0a1b3ccf1c86f577cee77363ef55deb05e"
|
||||||
|
integrity sha512-R1oD5gMBPS7PVU8gJwH6CtT0e6VSoD0+SzSnYpNm+dBkcijgA+K7VAMHDfnRq/lkKPZArpzplTW6jfiMYosdzw==
|
||||||
|
|
||||||
|
electron-is-dev@^1.1.0:
|
||||||
version "1.1.0"
|
version "1.1.0"
|
||||||
resolved "https://registry.npmjs.org/electron-is-dev/-/electron-is-dev-1.1.0.tgz"
|
resolved "https://registry.npmjs.org/electron-is-dev/-/electron-is-dev-1.1.0.tgz"
|
||||||
integrity sha512-Z1qA/1oHNowGtSBIcWk0pcLEqYT/j+13xUw/MYOrBUOL4X7VN0i0KCTf5SqyvMPmW5pSPKbo28wkxMxzZ20YnQ==
|
integrity sha512-Z1qA/1oHNowGtSBIcWk0pcLEqYT/j+13xUw/MYOrBUOL4X7VN0i0KCTf5SqyvMPmW5pSPKbo28wkxMxzZ20YnQ==
|
||||||
@@ -972,11 +989,6 @@ escape-string-regexp@^1.0.5:
|
|||||||
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
|
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
|
||||||
integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
|
integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
|
||||||
|
|
||||||
esprima@^4.0.0:
|
|
||||||
version "4.0.1"
|
|
||||||
resolved "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz"
|
|
||||||
integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==
|
|
||||||
|
|
||||||
execa@^0.7.0:
|
execa@^0.7.0:
|
||||||
version "0.7.0"
|
version "0.7.0"
|
||||||
resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777"
|
resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777"
|
||||||
@@ -1217,10 +1229,10 @@ github-from-package@0.0.0:
|
|||||||
resolved "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz"
|
resolved "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz"
|
||||||
integrity sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=
|
integrity sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=
|
||||||
|
|
||||||
glasstron@0.0.5:
|
glasstron@0.0.6:
|
||||||
version "0.0.5"
|
version "0.0.6"
|
||||||
resolved "https://registry.yarnpkg.com/glasstron/-/glasstron-0.0.5.tgz#41ed8109d1d9980a7112ccc3bd195b1aa17088bd"
|
resolved "https://registry.yarnpkg.com/glasstron/-/glasstron-0.0.6.tgz#1438899cd49a1cda1999290be2165310b759fd62"
|
||||||
integrity sha512-1eX2wcW6AxO//gE2eE55M2JkwreHLZgYSmDb0zh//Iw8OgZbf+DTAPfGVUmMQQvGqVjNdao+epu9NISTZAa23A==
|
integrity sha512-WBE1zH3ZcYhLlfKATfKzuN05Anno2WYlVfImWteU5RM+gqdFLHGIxxM3VR16JvFF5oIYah01MBGQ2+3xTq44iQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
node-addon-api "^3.0.0"
|
node-addon-api "^3.0.0"
|
||||||
x11 "^2.3.0"
|
x11 "^2.3.0"
|
||||||
@@ -1405,7 +1417,7 @@ inherits@2.0.3:
|
|||||||
resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz"
|
resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz"
|
||||||
integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
|
integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
|
||||||
|
|
||||||
ini@^1.3.4, ini@^1.3.5, ini@~1.3.0:
|
ini@^1.3.4, ini@^1.3.5, ini@^1.3.8, ini@~1.3.0:
|
||||||
version "1.3.8"
|
version "1.3.8"
|
||||||
resolved "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz"
|
resolved "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz"
|
||||||
integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==
|
integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==
|
||||||
@@ -1581,13 +1593,12 @@ isstream@~0.1.2:
|
|||||||
resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz"
|
resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz"
|
||||||
integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=
|
integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=
|
||||||
|
|
||||||
js-yaml@3.14.0:
|
js-yaml@4.0.0:
|
||||||
version "3.14.0"
|
version "4.0.0"
|
||||||
resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz"
|
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.0.0.tgz#f426bc0ff4b4051926cd588c71113183409a121f"
|
||||||
integrity sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==
|
integrity sha512-pqon0s+4ScYUvX30wxQi3PogGFAlUyH0awepWvwkj4jD4v+ova3RiYw8bmA6x2rDrEaj8i/oWKoRxpVNW+Re8Q==
|
||||||
dependencies:
|
dependencies:
|
||||||
argparse "^1.0.7"
|
argparse "^2.0.1"
|
||||||
esprima "^4.0.0"
|
|
||||||
|
|
||||||
jsbn@~0.1.0:
|
jsbn@~0.1.0:
|
||||||
version "0.1.1"
|
version "0.1.1"
|
||||||
@@ -2073,7 +2084,7 @@ mz@^2.7.0:
|
|||||||
object-assign "^4.0.1"
|
object-assign "^4.0.1"
|
||||||
thenify-all "^1.0.0"
|
thenify-all "^1.0.0"
|
||||||
|
|
||||||
nan@^2.13.2, nan@^2.14.2:
|
nan@^2.13.2, nan@^2.14.0, nan@^2.14.2:
|
||||||
version "2.14.2"
|
version "2.14.2"
|
||||||
resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.2.tgz#f5376400695168f4cc694ac9393d0c9585eeea19"
|
resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.2.tgz#f5376400695168f4cc694ac9393d0c9585eeea19"
|
||||||
integrity sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==
|
integrity sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==
|
||||||
@@ -2083,6 +2094,13 @@ napi-build-utils@^1.0.1:
|
|||||||
resolved "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz"
|
resolved "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz"
|
||||||
integrity sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==
|
integrity sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==
|
||||||
|
|
||||||
|
native-process-working-directory@^1.0.2:
|
||||||
|
version "1.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/native-process-working-directory/-/native-process-working-directory-1.0.2.tgz#7843e2fa1490f53cf8d2c7d1913de8b275e8b89a"
|
||||||
|
integrity sha512-3a67QQV8r3YMUTSOgvtMOCjPDgCpb/8xjv93L8Cqb8bv3hOKsWis4/+8HCu3bgj8ADQV75SCYFSsAGM5G0cXmQ==
|
||||||
|
dependencies:
|
||||||
|
node-addon-api "^3.1.0"
|
||||||
|
|
||||||
ngx-toastr@^12.0.1:
|
ngx-toastr@^12.0.1:
|
||||||
version "12.1.0"
|
version "12.1.0"
|
||||||
resolved "https://registry.npmjs.org/ngx-toastr/-/ngx-toastr-12.1.0.tgz"
|
resolved "https://registry.npmjs.org/ngx-toastr/-/ngx-toastr-12.1.0.tgz"
|
||||||
@@ -2102,7 +2120,7 @@ node-addon-api@3.0.0:
|
|||||||
resolved "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.0.0.tgz"
|
resolved "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.0.0.tgz"
|
||||||
integrity sha512-sSHCgWfJ+Lui/u+0msF3oyCgvdkhxDbkCS6Q8uiJquzOimkJBvX6hl5aSSA7DR1XbMpdM8r7phjcF63sF4rkKg==
|
integrity sha512-sSHCgWfJ+Lui/u+0msF3oyCgvdkhxDbkCS6Q8uiJquzOimkJBvX6hl5aSSA7DR1XbMpdM8r7phjcF63sF4rkKg==
|
||||||
|
|
||||||
node-addon-api@^3.0.0, node-addon-api@^3.0.2:
|
node-addon-api@^3.0.0, node-addon-api@^3.0.2, node-addon-api@^3.1.0:
|
||||||
version "3.1.0"
|
version "3.1.0"
|
||||||
resolved "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.1.0.tgz"
|
resolved "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.1.0.tgz"
|
||||||
integrity sha512-flmrDNB06LIl5lywUz7YlNGZH/5p0M7W28k8hzd9Lshtdh1wshD2Y+U4h9LD6KObOy1f+fEVdgprPrEymjM5uw==
|
integrity sha512-flmrDNB06LIl5lywUz7YlNGZH/5p0M7W28k8hzd9Lshtdh1wshD2Y+U4h9LD6KObOy1f+fEVdgprPrEymjM5uw==
|
||||||
@@ -2270,9 +2288,9 @@ npm-user-validate@^1.0.1:
|
|||||||
integrity sha512-uQwcd/tY+h1jnEaze6cdX/LrhWhoBxfSknxentoqmIuStxUExxjWd3ULMLFPiFUrZKbOVMowH6Jq2FRWfmhcEw==
|
integrity sha512-uQwcd/tY+h1jnEaze6cdX/LrhWhoBxfSknxentoqmIuStxUExxjWd3ULMLFPiFUrZKbOVMowH6Jq2FRWfmhcEw==
|
||||||
|
|
||||||
npm@6:
|
npm@6:
|
||||||
version "6.14.10"
|
version "6.14.11"
|
||||||
resolved "https://registry.yarnpkg.com/npm/-/npm-6.14.10.tgz#f45c8e4244294ba793770f2ab0e9ce2d0b93fd29"
|
resolved "https://registry.yarnpkg.com/npm/-/npm-6.14.11.tgz#e0b5598d7b9a42d275e61d8bd28cd7eee0074a3b"
|
||||||
integrity sha512-FT23Qy/JMA+qxEYReMOr1MY7642fKn8Onn+72LASPi872Owvmw0svm+/DXTHOC3yO9CheEO+EslyXEpdBdRtIA==
|
integrity sha512-1Zh7LjuIoEhIyjkBflSSGzfjuPQwDlghNloppjruOH5bmj9midT9qcNT0tRUZRR04shU9ekrxNy9+UTBrqeBpQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
JSONStream "^1.3.5"
|
JSONStream "^1.3.5"
|
||||||
abbrev "~1.1.1"
|
abbrev "~1.1.1"
|
||||||
@@ -2309,7 +2327,7 @@ npm@6:
|
|||||||
infer-owner "^1.0.4"
|
infer-owner "^1.0.4"
|
||||||
inflight "~1.0.6"
|
inflight "~1.0.6"
|
||||||
inherits "^2.0.4"
|
inherits "^2.0.4"
|
||||||
ini "^1.3.5"
|
ini "^1.3.8"
|
||||||
init-package-json "^1.10.3"
|
init-package-json "^1.10.3"
|
||||||
is-cidr "^3.0.0"
|
is-cidr "^3.0.0"
|
||||||
json-parse-better-errors "^1.0.2"
|
json-parse-better-errors "^1.0.2"
|
||||||
@@ -3025,16 +3043,16 @@ rxjs@^6.5.5:
|
|||||||
dependencies:
|
dependencies:
|
||||||
tslib "^1.9.0"
|
tslib "^1.9.0"
|
||||||
|
|
||||||
safe-buffer@^5.0.1, safe-buffer@^5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
|
safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0:
|
||||||
version "5.1.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz"
|
|
||||||
integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
|
|
||||||
|
|
||||||
safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.2.0:
|
|
||||||
version "5.2.1"
|
version "5.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
|
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
|
||||||
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
|
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
|
||||||
|
|
||||||
|
safe-buffer@~5.1.0, safe-buffer@~5.1.1:
|
||||||
|
version "5.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz"
|
||||||
|
integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
|
||||||
|
|
||||||
"safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0:
|
"safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0:
|
||||||
version "2.1.2"
|
version "2.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz"
|
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz"
|
||||||
@@ -3201,11 +3219,6 @@ split-on-first@^1.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/split-on-first/-/split-on-first-1.1.0.tgz#f610afeee3b12bce1d0c30425e76398b78249a5f"
|
resolved "https://registry.yarnpkg.com/split-on-first/-/split-on-first-1.1.0.tgz#f610afeee3b12bce1d0c30425e76398b78249a5f"
|
||||||
integrity sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==
|
integrity sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==
|
||||||
|
|
||||||
sprintf-js@~1.0.2:
|
|
||||||
version "1.0.3"
|
|
||||||
resolved "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz"
|
|
||||||
integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=
|
|
||||||
|
|
||||||
sshpk@^1.7.0:
|
sshpk@^1.7.0:
|
||||||
version "1.16.1"
|
version "1.16.1"
|
||||||
resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz"
|
resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz"
|
||||||
|
@@ -8,8 +8,9 @@ afterAllArtifactBuild: "./build/mac/afterBuildHook.js"
|
|||||||
files:
|
files:
|
||||||
- '**/*'
|
- '**/*'
|
||||||
- dist
|
- dist
|
||||||
|
- '!lib'
|
||||||
- '!src'
|
- '!src'
|
||||||
- '!**/node_modules/*/{CHANGELOG.md,README.md,README,readme.md,readme}'
|
- '!**/node_modules/*/{CHANGELOG.md,README.md,README,readme.md,readme,node.lib}'
|
||||||
- '!**/node_modules/*/{test,__tests__,tests,powered-test,example,examples,docs}'
|
- '!**/node_modules/*/{test,__tests__,tests,powered-test,example,examples,docs}'
|
||||||
- '!**/node_modules/@angular/common/locales'
|
- '!**/node_modules/@angular/common/locales'
|
||||||
- '!**/node_modules/@angular/compiler/src'
|
- '!**/node_modules/@angular/compiler/src'
|
||||||
|
41
package.json
41
package.json
@@ -2,32 +2,33 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@fortawesome/fontawesome-free": "^5.13.0",
|
"@fortawesome/fontawesome-free": "^5.13.0",
|
||||||
"@sentry/cli": "^1.61.0",
|
"@sentry/cli": "^1.61.0",
|
||||||
"@sentry/electron": "^2.0.4",
|
"@sentry/electron": "^2.2.0",
|
||||||
|
"@terminus-term/to-string-loader": "1.1.7-beta.1",
|
||||||
"@types/electron-config": "^3.2.2",
|
"@types/electron-config": "^3.2.2",
|
||||||
"@types/electron-debug": "^2.1.0",
|
"@types/electron-debug": "^2.1.0",
|
||||||
"@types/fs-extra": "^8.1.1",
|
"@types/fs-extra": "^8.1.1",
|
||||||
"@types/js-yaml": "^3.12.5",
|
"@types/js-yaml": "^3.12.5",
|
||||||
"@types/node": "14.14.14",
|
"@types/node": "14.14.14",
|
||||||
"@types/webpack-env": "^1.16.0",
|
"@types/webpack-env": "^1.16.0",
|
||||||
"@typescript-eslint/eslint-plugin": "^4.11.0",
|
"@typescript-eslint/eslint-plugin": "^4.14.1",
|
||||||
"@typescript-eslint/parser": "^4.11.0",
|
"@typescript-eslint/parser": "^4.14.1",
|
||||||
"apply-loader": "2.0.0",
|
"apply-loader": "2.0.0",
|
||||||
"awesome-typescript-loader": "^5.2.1",
|
"awesome-typescript-loader": "^5.2.1",
|
||||||
"compare-versions": "^3.6.0",
|
"compare-versions": "^3.6.0",
|
||||||
"core-js": "^3.8.1",
|
"core-js": "^3.8.3",
|
||||||
"cross-env": "7.0.2",
|
"cross-env": "7.0.3",
|
||||||
"css-loader": "3.4.2",
|
"css-loader": "5.0.1",
|
||||||
"electron": "^11.1.1",
|
"electron": "12.0.0-beta.22",
|
||||||
"electron-builder": "22.10.4",
|
"electron-builder": "22.10.4",
|
||||||
"electron-download": "^4.1.1",
|
"electron-download": "^4.1.1",
|
||||||
"electron-installer-snap": "^5.1.0",
|
"electron-installer-snap": "^5.1.0",
|
||||||
"electron-notarize": "^1.0.0",
|
"electron-notarize": "^1.0.0",
|
||||||
"electron-rebuild": "^2.3.4",
|
"electron-rebuild": "^2.3.4",
|
||||||
"eslint": "^7.6.0",
|
"eslint": "^7.18.0",
|
||||||
"eslint-plugin-import": "^2.21.1",
|
"eslint-plugin-import": "^2.21.1",
|
||||||
"file-loader": "^5.1.0",
|
"file-loader": "^6.2.0",
|
||||||
"graceful-fs": "^4.2.4",
|
"graceful-fs": "^4.2.4",
|
||||||
"html-loader": "0.5.5",
|
"html-loader": "1.3.2",
|
||||||
"json-loader": "0.5.7",
|
"json-loader": "0.5.7",
|
||||||
"lru-cache": "^6.0.0",
|
"lru-cache": "^6.0.0",
|
||||||
"macos-release": "^2.4.1",
|
"macos-release": "^2.4.1",
|
||||||
@@ -36,27 +37,27 @@
|
|||||||
"node-sass": "^5.0.0",
|
"node-sass": "^5.0.0",
|
||||||
"npmlog": "4.1.2",
|
"npmlog": "4.1.2",
|
||||||
"npx": "^10.2.2",
|
"npx": "^10.2.2",
|
||||||
"pug": "^2.0.4",
|
"patch-package": "^6.2.2",
|
||||||
|
"pug": "^3.0.0",
|
||||||
"pug-html-loader": "1.1.5",
|
"pug-html-loader": "1.1.5",
|
||||||
"pug-lint": "^2.6.0",
|
"pug-lint": "^2.6.0",
|
||||||
"pug-loader": "^2.4.0",
|
"pug-loader": "^2.4.0",
|
||||||
"pug-static-loader": "2.0.0",
|
"pug-static-loader": "2.0.0",
|
||||||
"raw-loader": "4.0.1",
|
"raw-loader": "4.0.2",
|
||||||
"sass-loader": "^10.1.0",
|
"sass-loader": "^10.1.1",
|
||||||
"shelljs": "0.8.4",
|
"shelljs": "0.8.4",
|
||||||
"source-code-pro": "^2.30.2",
|
"source-code-pro": "^2.30.2",
|
||||||
"source-sans-pro": "3.6.0",
|
"source-sans-pro": "3.6.0",
|
||||||
"ssh2-streams": "^0.4.10",
|
"ssh2-streams": "^0.4.10",
|
||||||
"style-loader": "^2.0.0",
|
"style-loader": "^2.0.0",
|
||||||
"svg-inline-loader": "^0.8.2",
|
"svg-inline-loader": "^0.8.2",
|
||||||
"to-string-loader": "1.1.6",
|
|
||||||
"tslib": "^2.0.3",
|
"tslib": "^2.0.3",
|
||||||
"typedoc": "^0.18.0",
|
"typedoc": "^0.18.0",
|
||||||
"typescript": "^3.9.7",
|
"typescript": "^3.9.7",
|
||||||
"url-loader": "^3.0.0",
|
"url-loader": "^4.1.1",
|
||||||
"val-loader": "2.1.1",
|
"val-loader": "3.0.0",
|
||||||
"webpack": "^5.11.0",
|
"webpack": "^5.18.0",
|
||||||
"webpack-cli": "^4.2.0",
|
"webpack-cli": "^4.4.0",
|
||||||
"yaml-loader": "0.6.0"
|
"yaml-loader": "0.6.0"
|
||||||
},
|
},
|
||||||
"resolutions": {
|
"resolutions": {
|
||||||
@@ -74,7 +75,5 @@
|
|||||||
"lint": "eslint --ext ts */src */lib",
|
"lint": "eslint --ext ts */src */lib",
|
||||||
"postinstall": "node ./scripts/install-deps.js"
|
"postinstall": "node ./scripts/install-deps.js"
|
||||||
},
|
},
|
||||||
"repository": "eugeny/terminus",
|
"private": true
|
||||||
"author": "Eugene Pankov",
|
|
||||||
"license": "MIT"
|
|
||||||
}
|
}
|
||||||
|
12
patches/node-abi+2.19.3.patch
Normal file
12
patches/node-abi+2.19.3.patch
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
diff --git a/node_modules/node-abi/abi_registry.json b/node_modules/node-abi/abi_registry.json
|
||||||
|
index bc1436d..630c1b7 100644
|
||||||
|
--- a/node_modules/node-abi/abi_registry.json
|
||||||
|
+++ b/node_modules/node-abi/abi_registry.json
|
||||||
|
@@ -94,6 +94,6 @@
|
||||||
|
"future": true,
|
||||||
|
"lts": false,
|
||||||
|
"runtime": "electron",
|
||||||
|
- "target": "12.0.0-nightly.20201013"
|
||||||
|
+ "target": "12.0.0-beta.16"
|
||||||
|
}
|
||||||
|
]
|
@@ -1,8 +1,6 @@
|
|||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
const builder = require('electron-builder').build
|
const builder = require('electron-builder').build
|
||||||
const vars = require('./vars')
|
const vars = require('./vars')
|
||||||
const fs = require('fs')
|
|
||||||
const signHook = require('../build/mac/afterSignHook')
|
|
||||||
|
|
||||||
const isTag = (process.env.GITHUB_REF || '').startsWith('refs/tags/')
|
const isTag = (process.env.GITHUB_REF || '').startsWith('refs/tags/')
|
||||||
|
|
||||||
@@ -16,6 +14,7 @@ builder({
|
|||||||
extraMetadata: {
|
extraMetadata: {
|
||||||
version: vars.version,
|
version: vars.version,
|
||||||
},
|
},
|
||||||
|
npmRebuild: process.env.ARCH !== 'arm64',
|
||||||
},
|
},
|
||||||
publish: isTag ? 'always' : 'onTag',
|
publish: isTag ? 'always' : 'onTag',
|
||||||
}).catch(e => {
|
}).catch(e => {
|
||||||
|
24
scripts/sentry-upload.js
Executable file
24
scripts/sentry-upload.js
Executable file
@@ -0,0 +1,24 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
const sh = require('shelljs')
|
||||||
|
const vars = require('./vars')
|
||||||
|
|
||||||
|
const sentryCli = process.platform === 'win32' ? 'node_modules\\.bin\\sentry-cli.cmd' : 'sentry-cli'
|
||||||
|
|
||||||
|
sh.exec(`${sentryCli} releases new ${vars.version}`)
|
||||||
|
|
||||||
|
if (process.platform === 'darwin') {
|
||||||
|
for (const path of [
|
||||||
|
'app/node_modules/@serialport/bindings/build/Release/bindings.node',
|
||||||
|
'app/node_modules/@terminus-term/node-pty/build/Release/pty.node',
|
||||||
|
'app/node_modules/fontmanager-redux/build/Release/fontmanager.node',
|
||||||
|
'app/node_modules/macos-native-processlist/build/Release/native.node',
|
||||||
|
]) {
|
||||||
|
sh.exec('dsymutil ' + path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sh.exec(`${sentryCli} upload-dif app/node_modules`)
|
||||||
|
sh.exec(`${sentryCli} releases set-commits --auto ${vars.version}`)
|
||||||
|
for (const p of vars.builtinPlugins) {
|
||||||
|
sh.exec(`${sentryCli} releases files ${vars.version} upload-sourcemaps ${p}/dist -u ${p}/dist/ -d ${process.platform}-${p}`)
|
||||||
|
}
|
@@ -1,14 +1,14 @@
|
|||||||
import { Injectable } from '@angular/core'
|
import { Injectable } from '@angular/core'
|
||||||
import { TerminalColorSchemeProvider, TerminalColorScheme } from 'terminus-terminal'
|
import { TerminalColorSchemeProvider, TerminalColorScheme } from 'terminus-terminal'
|
||||||
|
|
||||||
const schemeContents = require.context('../schemes/', true, /.*/)
|
const schemeContents = require.context('../schemes/', false, /.*/)
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ColorSchemes extends TerminalColorSchemeProvider {
|
export class ColorSchemes extends TerminalColorSchemeProvider {
|
||||||
async getSchemes (): Promise<TerminalColorScheme[]> {
|
async getSchemes (): Promise<TerminalColorScheme[]> {
|
||||||
const schemes: TerminalColorScheme[] = []
|
const schemes: TerminalColorScheme[] = []
|
||||||
|
|
||||||
schemeContents.keys().forEach(schemeFile => {
|
schemeContents.keys().filter(x => !x.startsWith('./')).forEach(schemeFile => {
|
||||||
const lines = (schemeContents(schemeFile).default as string).split('\n')
|
const lines = (schemeContents(schemeFile).default as string).split('\n')
|
||||||
|
|
||||||
// process #define variables
|
// process #define variables
|
||||||
|
@@ -26,8 +26,8 @@ $side-tab-width: 200px;
|
|||||||
|
|
||||||
.content {
|
.content {
|
||||||
width: 100vw;
|
width: 100vw;
|
||||||
height: 100vh;
|
flex: 1 1 0;
|
||||||
flex: auto;
|
min-height: 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column-reverse;
|
flex-direction: column-reverse;
|
||||||
|
|
||||||
|
@@ -142,6 +142,8 @@ export class AppRootComponent {
|
|||||||
|
|
||||||
this.touchbar.update()
|
this.touchbar.update()
|
||||||
|
|
||||||
|
this.hostApp.useBuiltinGraphics()
|
||||||
|
|
||||||
config.changed$.subscribe(() => this.updateVibrancy())
|
config.changed$.subscribe(() => this.updateVibrancy())
|
||||||
this.updateVibrancy()
|
this.updateVibrancy()
|
||||||
|
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import { Component, Input, HostListener, ViewChildren, QueryList, ElementRef } from '@angular/core'
|
import { Component, Input, HostListener, ViewChildren, QueryList, ElementRef } from '@angular/core' // eslint-disable-line @typescript-eslint/no-unused-vars
|
||||||
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
|
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
|
||||||
import { SelectorOption } from '../api/selector'
|
import { SelectorOption } from '../api/selector'
|
||||||
|
|
||||||
|
@@ -110,7 +110,7 @@ export default class AppModule { // eslint-disable-line @typescript-eslint/no-ex
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
static forRoot (): ModuleWithProviders {
|
static forRoot (): ModuleWithProviders<AppModule> {
|
||||||
return {
|
return {
|
||||||
ngModule: AppModule,
|
ngModule: AppModule,
|
||||||
providers: PROVIDERS,
|
providers: PROVIDERS,
|
||||||
|
@@ -49,10 +49,10 @@ export class AppService {
|
|||||||
get activeTab (): BaseTabComponent|null { return this._activeTab ?? null }
|
get activeTab (): BaseTabComponent|null { return this._activeTab ?? null }
|
||||||
|
|
||||||
private lastTabIndex = 0
|
private lastTabIndex = 0
|
||||||
private _activeTab?: BaseTabComponent
|
private _activeTab: BaseTabComponent | null = null
|
||||||
private closedTabsStack: RecoveryToken[] = []
|
private closedTabsStack: RecoveryToken[] = []
|
||||||
|
|
||||||
private activeTabChange = new Subject<BaseTabComponent>()
|
private activeTabChange = new Subject<BaseTabComponent|null>()
|
||||||
private tabsChanged = new Subject<void>()
|
private tabsChanged = new Subject<void>()
|
||||||
private tabOpened = new Subject<BaseTabComponent>()
|
private tabOpened = new Subject<BaseTabComponent>()
|
||||||
private tabClosed = new Subject<BaseTabComponent>()
|
private tabClosed = new Subject<BaseTabComponent>()
|
||||||
@@ -60,7 +60,7 @@ export class AppService {
|
|||||||
|
|
||||||
private completionObservers = new Map<BaseTabComponent, CompletionObserver>()
|
private completionObservers = new Map<BaseTabComponent, CompletionObserver>()
|
||||||
|
|
||||||
get activeTabChange$ (): Observable<BaseTabComponent> { return this.activeTabChange }
|
get activeTabChange$ (): Observable<BaseTabComponent|null> { return this.activeTabChange }
|
||||||
get tabOpened$ (): Observable<BaseTabComponent> { return this.tabOpened }
|
get tabOpened$ (): Observable<BaseTabComponent> { return this.tabOpened }
|
||||||
get tabsChanged$ (): Observable<void> { return this.tabsChanged }
|
get tabsChanged$ (): Observable<void> { return this.tabsChanged }
|
||||||
get tabClosed$ (): Observable<BaseTabComponent> { return this.tabClosed }
|
get tabClosed$ (): Observable<BaseTabComponent> { return this.tabClosed }
|
||||||
@@ -185,8 +185,8 @@ export class AppService {
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
selectTab (tab: BaseTabComponent): void {
|
selectTab (tab: BaseTabComponent|null): void {
|
||||||
if (this._activeTab === tab) {
|
if (tab && this._activeTab === tab) {
|
||||||
this._activeTab.emitFocused()
|
this._activeTab.emitFocused()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -204,7 +204,7 @@ export class AppService {
|
|||||||
setImmediate(() => {
|
setImmediate(() => {
|
||||||
this._activeTab?.emitFocused()
|
this._activeTab?.emitFocused()
|
||||||
})
|
})
|
||||||
this.hostApp.setTitle(this._activeTab.title)
|
this.hostApp.setTitle(this._activeTab?.title)
|
||||||
}
|
}
|
||||||
|
|
||||||
getParentTab (tab: BaseTabComponent): SplitTabComponent|null {
|
getParentTab (tab: BaseTabComponent): SplitTabComponent|null {
|
||||||
|
@@ -144,7 +144,7 @@ export class ConfigService {
|
|||||||
|
|
||||||
load (): void {
|
load (): void {
|
||||||
if (fs.existsSync(this.path)) {
|
if (fs.existsSync(this.path)) {
|
||||||
this._store = yaml.safeLoad(fs.readFileSync(this.path, 'utf8'))
|
this._store = yaml.load(fs.readFileSync(this.path, 'utf8'))
|
||||||
} else {
|
} else {
|
||||||
this._store = {}
|
this._store = {}
|
||||||
}
|
}
|
||||||
@@ -154,7 +154,7 @@ export class ConfigService {
|
|||||||
save (): void {
|
save (): void {
|
||||||
// Scrub undefined values
|
// Scrub undefined values
|
||||||
this._store = JSON.parse(JSON.stringify(this._store))
|
this._store = JSON.parse(JSON.stringify(this._store))
|
||||||
fs.writeFileSync(this.path, yaml.safeDump(this._store), 'utf8')
|
fs.writeFileSync(this.path, yaml.dump(this._store), 'utf8')
|
||||||
this.emitChange()
|
this.emitChange()
|
||||||
this.hostApp.broadcastConfigChange(JSON.parse(JSON.stringify(this.store)))
|
this.hostApp.broadcastConfigChange(JSON.parse(JSON.stringify(this.store)))
|
||||||
}
|
}
|
||||||
@@ -163,14 +163,14 @@ export class ConfigService {
|
|||||||
* Reads config YAML as string
|
* Reads config YAML as string
|
||||||
*/
|
*/
|
||||||
readRaw (): string {
|
readRaw (): string {
|
||||||
return yaml.safeDump(this._store)
|
return yaml.dump(this._store)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Writes config YAML as string
|
* Writes config YAML as string
|
||||||
*/
|
*/
|
||||||
writeRaw (data: string): void {
|
writeRaw (data: string): void {
|
||||||
this._store = yaml.safeLoad(data)
|
this._store = yaml.load(data)
|
||||||
this.save()
|
this.save()
|
||||||
this.load()
|
this.load()
|
||||||
this.emitChange()
|
this.emitChange()
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
import type { BrowserWindow, TouchBar, MenuItemConstructorOptions } from 'electron'
|
import type { BrowserWindow, TouchBar, MenuItemConstructorOptions } from 'electron'
|
||||||
import * as path from 'path'
|
import * as path from 'path'
|
||||||
|
import * as fs from 'mz/fs'
|
||||||
import shellEscape from 'shell-escape'
|
import shellEscape from 'shell-escape'
|
||||||
import { Observable, Subject } from 'rxjs'
|
import { Observable, Subject } from 'rxjs'
|
||||||
import { Injectable, NgZone, EventEmitter } from '@angular/core'
|
import { Injectable, NgZone, EventEmitter } from '@angular/core'
|
||||||
@@ -7,6 +8,12 @@ import { ElectronService } from './electron.service'
|
|||||||
import { Logger, LogService } from './log.service'
|
import { Logger, LogService } from './log.service'
|
||||||
import { isWindowsBuild, WIN_BUILD_FLUENT_BG_SUPPORTED } from '../utils'
|
import { isWindowsBuild, WIN_BUILD_FLUENT_BG_SUPPORTED } from '../utils'
|
||||||
|
|
||||||
|
/* eslint-disable block-scoped-var */
|
||||||
|
|
||||||
|
try {
|
||||||
|
var wnr = require('windows-native-registry') // eslint-disable-line @typescript-eslint/no-var-requires, no-var
|
||||||
|
} catch (_) { }
|
||||||
|
|
||||||
export enum Platform {
|
export enum Platform {
|
||||||
Linux = 'Linux',
|
Linux = 'Linux',
|
||||||
macOS = 'macOS',
|
macOS = 'macOS',
|
||||||
@@ -150,9 +157,10 @@ export class HostAppService {
|
|||||||
this.zone.run(() => this.displaysChanged.next())
|
this.zone.run(() => this.displaysChanged.next())
|
||||||
})
|
})
|
||||||
|
|
||||||
electron.ipcRenderer.on('host:second-instance', (_$event, argv: any, cwd: string) => this.zone.run(() => {
|
electron.ipcRenderer.on('cli', (_$event, argv: any, cwd: string, secondInstance: boolean) => this.zone.run(async () => {
|
||||||
this.logger.info('Second instance', argv)
|
this.logger.info('Second instance', argv)
|
||||||
const op = argv._[0]
|
const op = argv._[0]
|
||||||
|
const opAsPath = op ? path.resolve(cwd, op) : null
|
||||||
if (op === 'open') {
|
if (op === 'open') {
|
||||||
this.cliOpenDirectory.next(path.resolve(cwd, argv.directory))
|
this.cliOpenDirectory.next(path.resolve(cwd, argv.directory))
|
||||||
} else if (op === 'run') {
|
} else if (op === 'run') {
|
||||||
@@ -165,9 +173,13 @@ export class HostAppService {
|
|||||||
this.cliPaste.next(text)
|
this.cliPaste.next(text)
|
||||||
} else if (op === 'profile') {
|
} else if (op === 'profile') {
|
||||||
this.cliOpenProfile.next(argv.profileName)
|
this.cliOpenProfile.next(argv.profileName)
|
||||||
} else if (op === undefined) {
|
} else if (secondInstance && op === undefined) {
|
||||||
this.newWindow()
|
this.newWindow()
|
||||||
} else {
|
} else if (opAsPath && (await fs.lstat(opAsPath)).isDirectory()) {
|
||||||
|
this.cliOpenDirectory.next(opAsPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (secondInstance) {
|
||||||
this.secondInstance.next()
|
this.secondInstance.next()
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
@@ -242,8 +254,8 @@ export class HostAppService {
|
|||||||
this.electron.ipcRenderer.send('window-set-vibrancy', enable, type)
|
this.electron.ipcRenderer.send('window-set-vibrancy', enable, type)
|
||||||
}
|
}
|
||||||
|
|
||||||
setTitle (title: string): void {
|
setTitle (title?: string): void {
|
||||||
this.electron.ipcRenderer.send('window-set-title', title)
|
this.electron.ipcRenderer.send('window-set-title', title ?? 'Terminus')
|
||||||
}
|
}
|
||||||
|
|
||||||
setTouchBar (touchBar: TouchBar): void {
|
setTouchBar (touchBar: TouchBar): void {
|
||||||
@@ -277,6 +289,16 @@ export class HostAppService {
|
|||||||
this.electron.ipcRenderer.send('app:register-global-hotkey', specs)
|
this.electron.ipcRenderer.send('app:register-global-hotkey', specs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
useBuiltinGraphics (): void {
|
||||||
|
const keyPath = 'SOFTWARE\\Microsoft\\DirectX\\UserGpuPreferences'
|
||||||
|
const valueName = this.electron.app.getPath('exe')
|
||||||
|
if (this.platform === Platform.Windows) {
|
||||||
|
if (!wnr.getRegistryValue(wnr.HK.CU, keyPath, valueName)) {
|
||||||
|
wnr.setRegistryValue(wnr.HK.CU, keyPath, valueName, wnr.REG.SZ, 'GpuPreference=1;')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
relaunch (): void {
|
relaunch (): void {
|
||||||
if (this.isPortable) {
|
if (this.isPortable) {
|
||||||
this.electron.app.relaunch({ execPath: process.env.PORTABLE_EXECUTABLE_FILE })
|
this.electron.app.relaunch({ execPath: process.env.PORTABLE_EXECUTABLE_FILE })
|
||||||
|
@@ -35,6 +35,10 @@ export class UpdaterService {
|
|||||||
this.logger.info('No updates')
|
this.logger.info('No updates')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
electron.autoUpdater.once('error', err => {
|
||||||
|
this.logger.error(err)
|
||||||
|
})
|
||||||
|
|
||||||
this.downloaded = new Promise<boolean>(resolve => {
|
this.downloaded = new Promise<boolean>(resolve => {
|
||||||
electron.autoUpdater.once('update-downloaded', () => resolve(true))
|
electron.autoUpdater.once('update-downloaded', () => resolve(true))
|
||||||
})
|
})
|
||||||
|
@@ -40,8 +40,8 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{ test: /\.pug$/, use: ['apply-loader', 'pug-loader'] },
|
{ test: /\.pug$/, use: ['apply-loader', 'pug-loader'] },
|
||||||
{ test: /\.scss$/, use: ['to-string-loader', 'css-loader', 'sass-loader'] },
|
{ test: /\.scss$/, use: ['@terminus-term/to-string-loader', 'css-loader', 'sass-loader'] },
|
||||||
{ test: /\.css$/, use: ['to-string-loader', 'css-loader'], include: /component\.css/ },
|
{ test: /\.css$/, use: ['@terminus-term/to-string-loader', 'css-loader'], include: /component\.css/ },
|
||||||
{ test: /\.css$/, use: ['style-loader', 'css-loader'], exclude: /component\.css/ },
|
{ test: /\.css$/, use: ['style-loader', 'css-loader'], exclude: /component\.css/ },
|
||||||
{ test: /\.yaml$/, use: ['json-loader', 'yaml-loader'] },
|
{ test: /\.yaml$/, use: ['json-loader', 'yaml-loader'] },
|
||||||
{ test: /\.svg/, use: ['svg-inline-loader'] },
|
{ test: /\.svg/, use: ['svg-inline-loader'] },
|
||||||
|
@@ -124,9 +124,9 @@ colorspace@1.1.x:
|
|||||||
text-hex "1.0.x"
|
text-hex "1.0.x"
|
||||||
|
|
||||||
core-js@^3.1.2:
|
core-js@^3.1.2:
|
||||||
version "3.7.0"
|
version "3.8.2"
|
||||||
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.7.0.tgz#b0a761a02488577afbf97179e4681bf49568520f"
|
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.8.2.tgz#0a1fd6709246da9ca8eff5bb0cbd15fba9ac7044"
|
||||||
integrity sha512-NwS7fI5M5B85EwpWuIwJN4i/fbisQUwLwiSNUWeXlkAZ0sbBjLEvLvFLf1uzAUV66PcEPt4xCGCmOZSxVf3xzA==
|
integrity sha512-FfApuSRgrR6G5s58casCBd9M2k+4ikuu4wbW6pJyYU7bd9zvFc9qf7vr5xmrZOhT9nn+8uwlH1oRR9jTnFoA3A==
|
||||||
|
|
||||||
core-util-is@~1.0.0:
|
core-util-is@~1.0.0:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
|
@@ -40,7 +40,7 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{ test: /\.pug$/, use: ['apply-loader', 'pug-loader'] },
|
{ test: /\.pug$/, use: ['apply-loader', 'pug-loader'] },
|
||||||
{ test: /\.scss$/, use: ['to-string-loader', 'css-loader', 'sass-loader'] },
|
{ test: /\.scss$/, use: ['@terminus-term/to-string-loader', 'css-loader', 'sass-loader'] },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
externals: [
|
externals: [
|
||||||
|
@@ -20,6 +20,7 @@
|
|||||||
"@types/node": "14.14.14",
|
"@types/node": "14.14.14",
|
||||||
"@types/ssh2": "^0.5.35",
|
"@types/ssh2": "^0.5.35",
|
||||||
"ansi-colors": "^4.1.1",
|
"ansi-colors": "^4.1.1",
|
||||||
|
"buffer-replace": "^1.0.0",
|
||||||
"cli-spinner": "^0.2.10"
|
"cli-spinner": "^0.2.10"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
|
@@ -1,7 +1,12 @@
|
|||||||
|
import stripAnsi from 'strip-ansi'
|
||||||
|
import bufferReplace from 'buffer-replace'
|
||||||
import { BaseSession } from 'terminus-terminal'
|
import { BaseSession } from 'terminus-terminal'
|
||||||
import { SerialPort } from 'serialport'
|
import { SerialPort } from 'serialport'
|
||||||
import { Logger } from 'terminus-core'
|
import { Logger } from 'terminus-core'
|
||||||
import { Subject, Observable } from 'rxjs'
|
import { Subject, Observable, interval } from 'rxjs'
|
||||||
|
import { debounce } from 'rxjs/operators'
|
||||||
|
import { ReadLine, createInterface as createReadline, clearLine } from 'readline'
|
||||||
|
import { PassThrough, Readable, Writable } from 'stream'
|
||||||
|
|
||||||
export interface LoginScript {
|
export interface LoginScript {
|
||||||
expect: string
|
expect: string
|
||||||
@@ -23,10 +28,13 @@ export interface SerialConnection {
|
|||||||
xany: boolean
|
xany: boolean
|
||||||
scripts?: LoginScript[]
|
scripts?: LoginScript[]
|
||||||
color?: string
|
color?: string
|
||||||
|
inputMode?: InputMode
|
||||||
|
inputNewlines?: NewlineMode
|
||||||
|
outputNewlines?: NewlineMode
|
||||||
}
|
}
|
||||||
|
|
||||||
export const BAUD_RATES = [
|
export const BAUD_RATES = [
|
||||||
110, 150, 300, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600,
|
110, 150, 300, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600, 1500000,
|
||||||
]
|
]
|
||||||
|
|
||||||
export interface SerialPortInfo {
|
export interface SerialPortInfo {
|
||||||
@@ -34,6 +42,9 @@ export interface SerialPortInfo {
|
|||||||
description?: string
|
description?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type InputMode = null | 'readline' // eslint-disable-line @typescript-eslint/no-type-alias
|
||||||
|
export type NewlineMode = null | 'cr' | 'lf' | 'crlf' // eslint-disable-line @typescript-eslint/no-type-alias
|
||||||
|
|
||||||
export class SerialSession extends BaseSession {
|
export class SerialSession extends BaseSession {
|
||||||
scripts?: LoginScript[]
|
scripts?: LoginScript[]
|
||||||
serial: SerialPort
|
serial: SerialPort
|
||||||
@@ -41,17 +52,139 @@ export class SerialSession extends BaseSession {
|
|||||||
|
|
||||||
get serviceMessage$ (): Observable<string> { return this.serviceMessage }
|
get serviceMessage$ (): Observable<string> { return this.serviceMessage }
|
||||||
private serviceMessage = new Subject<string>()
|
private serviceMessage = new Subject<string>()
|
||||||
|
private inputReadline: ReadLine
|
||||||
|
private inputPromptVisible = true
|
||||||
|
private inputReadlineInStream: Readable & Writable
|
||||||
|
private inputReadlineOutStream: Readable & Writable
|
||||||
|
|
||||||
constructor (public connection: SerialConnection) {
|
constructor (public connection: SerialConnection) {
|
||||||
super()
|
super()
|
||||||
this.scripts = connection.scripts ?? []
|
this.scripts = connection.scripts ?? []
|
||||||
|
|
||||||
|
this.inputReadlineInStream = new PassThrough()
|
||||||
|
this.inputReadlineOutStream = new PassThrough()
|
||||||
|
this.inputReadline = createReadline({
|
||||||
|
input: this.inputReadlineInStream,
|
||||||
|
output: this.inputReadlineOutStream,
|
||||||
|
terminal: true,
|
||||||
|
} as any)
|
||||||
|
this.inputReadlineOutStream.on('data', data => {
|
||||||
|
if (this.connection.inputMode === 'readline') {
|
||||||
|
this.emitOutput(data)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
this.inputReadline.on('line', line => {
|
||||||
|
this.onInput(new Buffer(line + '\n'))
|
||||||
|
})
|
||||||
|
this.output$.pipe(debounce(() => interval(500))).subscribe(() => this.onOutputSettled())
|
||||||
}
|
}
|
||||||
|
|
||||||
async start (): Promise<void> {
|
async start (): Promise<void> {
|
||||||
this.open = true
|
this.open = true
|
||||||
|
|
||||||
this.serial.on('data', data => {
|
this.serial.on('readable', () => {
|
||||||
|
this.onOutput(this.serial.read())
|
||||||
|
})
|
||||||
|
|
||||||
|
this.serial.on('end', () => {
|
||||||
|
this.logger.info('Shell session ended')
|
||||||
|
if (this.open) {
|
||||||
|
this.destroy()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
this.executeUnconditionalScripts()
|
||||||
|
}
|
||||||
|
|
||||||
|
write (data: Buffer): void {
|
||||||
|
if (this.connection.inputMode === 'readline') {
|
||||||
|
this.inputReadlineInStream.write(data)
|
||||||
|
} else {
|
||||||
|
this.onInput(data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async destroy (): Promise<void> {
|
||||||
|
this.serviceMessage.complete()
|
||||||
|
this.inputReadline.close()
|
||||||
|
await super.destroy()
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-empty-function, @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-empty-function
|
||||||
|
resize (_, __) {
|
||||||
|
this.inputReadlineOutStream.emit('resize')
|
||||||
|
}
|
||||||
|
|
||||||
|
kill (_?: string): void {
|
||||||
|
this.serial.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
emitServiceMessage (msg: string): void {
|
||||||
|
this.serviceMessage.next(msg)
|
||||||
|
this.logger.info(stripAnsi(msg))
|
||||||
|
}
|
||||||
|
|
||||||
|
async getChildProcesses (): Promise<any[]> {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
async gracefullyKillProcess (): Promise<void> {
|
||||||
|
this.kill('TERM')
|
||||||
|
}
|
||||||
|
|
||||||
|
supportsWorkingDirectory (): boolean {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
async getWorkingDirectory (): Promise<string|null> {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
private replaceNewlines (data: Buffer, mode?: NewlineMode): Buffer {
|
||||||
|
if (!mode) {
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
data = bufferReplace(data, '\r\n', '\n')
|
||||||
|
data = bufferReplace(data, '\r', '\n')
|
||||||
|
const replacement = {
|
||||||
|
strip: '',
|
||||||
|
cr: '\r',
|
||||||
|
lf: '\n',
|
||||||
|
crlf: '\r\n',
|
||||||
|
}[mode]
|
||||||
|
return bufferReplace(data, '\n', replacement)
|
||||||
|
}
|
||||||
|
|
||||||
|
private onInput (data: Buffer) {
|
||||||
|
data = this.replaceNewlines(data, this.connection.inputNewlines)
|
||||||
|
if (this.serial) {
|
||||||
|
this.serial.write(data.toString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private onOutputSettled () {
|
||||||
|
if (this.connection.inputMode === 'readline' && !this.inputPromptVisible) {
|
||||||
|
this.resetInputPrompt()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private resetInputPrompt () {
|
||||||
|
this.emitOutput(new Buffer('\r\n'))
|
||||||
|
this.inputReadline.prompt(true)
|
||||||
|
this.inputPromptVisible = true
|
||||||
|
}
|
||||||
|
|
||||||
|
private onOutput (data: Buffer) {
|
||||||
const dataString = data.toString()
|
const dataString = data.toString()
|
||||||
|
|
||||||
|
if (this.connection.inputMode === 'readline') {
|
||||||
|
if (this.inputPromptVisible) {
|
||||||
|
clearLine(this.inputReadlineOutStream, 0)
|
||||||
|
this.inputPromptVisible = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data = this.replaceNewlines(data, this.connection.outputNewlines)
|
||||||
this.emitOutput(data)
|
this.emitOutput(data)
|
||||||
|
|
||||||
if (this.scripts) {
|
if (this.scripts) {
|
||||||
@@ -61,7 +194,7 @@ export class SerialSession extends BaseSession {
|
|||||||
let cmd = ''
|
let cmd = ''
|
||||||
if (script.isRegex) {
|
if (script.isRegex) {
|
||||||
const re = new RegExp(script.expect, 'g')
|
const re = new RegExp(script.expect, 'g')
|
||||||
if (dataString.match(re)) {
|
if (re.test(dataString)) {
|
||||||
cmd = dataString.replace(re, script.send)
|
cmd = dataString.replace(re, script.send)
|
||||||
match = true
|
match = true
|
||||||
found = true
|
found = true
|
||||||
@@ -93,46 +226,6 @@ export class SerialSession extends BaseSession {
|
|||||||
this.executeUnconditionalScripts()
|
this.executeUnconditionalScripts()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
|
||||||
|
|
||||||
this.serial.on('end', () => {
|
|
||||||
this.logger.info('Shell session ended')
|
|
||||||
if (this.open) {
|
|
||||||
this.destroy()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
this.executeUnconditionalScripts()
|
|
||||||
}
|
|
||||||
|
|
||||||
write (data: Buffer): void {
|
|
||||||
if (this.serial) {
|
|
||||||
this.serial.write(data.toString())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async destroy (): Promise<void> {
|
|
||||||
this.serviceMessage.complete()
|
|
||||||
await super.destroy()
|
|
||||||
}
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-empty-function, @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-empty-function
|
|
||||||
resize (_, __) { }
|
|
||||||
|
|
||||||
kill (_?: string): void {
|
|
||||||
this.serial.close()
|
|
||||||
}
|
|
||||||
|
|
||||||
async getChildProcesses (): Promise<any[]> {
|
|
||||||
return []
|
|
||||||
}
|
|
||||||
|
|
||||||
async gracefullyKillProcess (): Promise<void> {
|
|
||||||
this.kill('TERM')
|
|
||||||
}
|
|
||||||
|
|
||||||
async getWorkingDirectory (): Promise<string|null> {
|
|
||||||
return null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private executeUnconditionalScripts () {
|
private executeUnconditionalScripts () {
|
||||||
|
@@ -11,6 +11,8 @@
|
|||||||
[(ngModel)]='connection.name',
|
[(ngModel)]='connection.name',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
.row
|
||||||
|
.col-6
|
||||||
.form-group
|
.form-group
|
||||||
label Path
|
label Path
|
||||||
input.form-control(
|
input.form-control(
|
||||||
@@ -20,6 +22,7 @@
|
|||||||
[resultFormatter]='portsFormatter',
|
[resultFormatter]='portsFormatter',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
.col-6
|
||||||
.form-group
|
.form-group
|
||||||
label Baud Rate
|
label Baud Rate
|
||||||
select.form-control(
|
select.form-control(
|
||||||
@@ -27,6 +30,66 @@
|
|||||||
)
|
)
|
||||||
option([value]='x', *ngFor='let x of baudRates') {{x}}
|
option([value]='x', *ngFor='let x of baudRates') {{x}}
|
||||||
|
|
||||||
|
.row
|
||||||
|
.col-6
|
||||||
|
.form-line
|
||||||
|
.header
|
||||||
|
.title Input mode
|
||||||
|
|
||||||
|
.d-flex(ngbDropdown)
|
||||||
|
button.btn.btn-secondary.btn-tab-bar(
|
||||||
|
ngbDropdownToggle,
|
||||||
|
) {{getInputModeName(connection.inputMode)}}
|
||||||
|
|
||||||
|
div(ngbDropdownMenu)
|
||||||
|
a.d-flex.flex-column(
|
||||||
|
*ngFor='let mode of inputModes',
|
||||||
|
(click)='connection.inputMode = mode.key',
|
||||||
|
ngbDropdownItem
|
||||||
|
)
|
||||||
|
div {{mode.name}}
|
||||||
|
.text-muted {{mode.description}}
|
||||||
|
|
||||||
|
.col-6
|
||||||
|
.form-line
|
||||||
|
.header
|
||||||
|
.title Input newlines
|
||||||
|
|
||||||
|
select.form-control(
|
||||||
|
[(ngModel)]='connection.inputNewlines',
|
||||||
|
)
|
||||||
|
option([ngValue]='mode.key', *ngFor='let mode of newlineModes') {{mode.name}}
|
||||||
|
|
||||||
|
.row
|
||||||
|
.col-6
|
||||||
|
//- .form-line
|
||||||
|
.header
|
||||||
|
.title Output mode
|
||||||
|
|
||||||
|
.d-flex(ngbDropdown)
|
||||||
|
button.btn.btn-secondary.btn-tab-bar(
|
||||||
|
ngbDropdownToggle,
|
||||||
|
) {{getInputModeName(connection.inputMode)}}
|
||||||
|
|
||||||
|
div(ngbDropdownMenu)
|
||||||
|
a.d-flex.flex-column(
|
||||||
|
*ngFor='let mode of inputModes',
|
||||||
|
(click)='connection.inputMode = mode.key',
|
||||||
|
ngbDropdownItem
|
||||||
|
)
|
||||||
|
div {{mode.name}}
|
||||||
|
.text-muted {{mode.description}}
|
||||||
|
|
||||||
|
.col-6
|
||||||
|
.form-line
|
||||||
|
.header
|
||||||
|
.title Output newlines
|
||||||
|
|
||||||
|
select.form-control(
|
||||||
|
[(ngModel)]='connection.outputNewlines',
|
||||||
|
)
|
||||||
|
option([ngValue]='mode.key', *ngFor='let mode of newlineModes') {{mode.name}}
|
||||||
|
|
||||||
ngb-tab(id='advanced')
|
ngb-tab(id='advanced')
|
||||||
ng-template(ngbTabTitle) Advanced
|
ng-template(ngbTabTitle) Advanced
|
||||||
ng-template(ngbTabContent)
|
ng-template(ngbTabContent)
|
||||||
|
@@ -15,6 +15,17 @@ export class EditConnectionModalComponent {
|
|||||||
connection: SerialConnection
|
connection: SerialConnection
|
||||||
foundPorts: SerialPortInfo[]
|
foundPorts: SerialPortInfo[]
|
||||||
baudRates = BAUD_RATES
|
baudRates = BAUD_RATES
|
||||||
|
inputModes = [
|
||||||
|
{ key: null, name: 'Normal', description: 'Input is sent as you type' },
|
||||||
|
{ key: 'readline', name: 'Line by line', description: 'Line editor, input is sent after you press Enter' },
|
||||||
|
]
|
||||||
|
newlineModes = [
|
||||||
|
{ key: null, name: 'Keep' },
|
||||||
|
{ key: 'strip', name: 'Strip' },
|
||||||
|
{ key: 'cr', name: 'Force CR' },
|
||||||
|
{ key: 'lf', name: 'Force LF' },
|
||||||
|
{ key: 'crlf', name: 'Force CRLF' },
|
||||||
|
]
|
||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
private modalInstance: NgbActiveModal,
|
private modalInstance: NgbActiveModal,
|
||||||
@@ -24,6 +35,10 @@ export class EditConnectionModalComponent {
|
|||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getInputModeName (key) {
|
||||||
|
return this.inputModes.find(x => x.key === key)?.name
|
||||||
|
}
|
||||||
|
|
||||||
portsAutocomplete = text$ => text$.pipe(map(() => {
|
portsAutocomplete = text$ => text$.pipe(map(() => {
|
||||||
return this.foundPorts.map(x => x.name)
|
return this.foundPorts.map(x => x.name)
|
||||||
}))
|
}))
|
||||||
|
@@ -34,6 +34,9 @@ export class SerialSettingsTabComponent {
|
|||||||
xany: false,
|
xany: false,
|
||||||
xoff: false,
|
xoff: false,
|
||||||
xon: false,
|
xon: false,
|
||||||
|
inputMode: null,
|
||||||
|
inputNewlines: null,
|
||||||
|
outputNewlines: null,
|
||||||
}
|
}
|
||||||
|
|
||||||
const modal = this.ngbModal.open(EditConnectionModalComponent)
|
const modal = this.ngbModal.open(EditConnectionModalComponent)
|
||||||
|
@@ -1,16 +1,16 @@
|
|||||||
.tab-toolbar
|
.tab-toolbar
|
||||||
.btn.btn-outline-secondary.reveal-button
|
.btn.btn-outline-secondary.reveal-button
|
||||||
i.fas.fa-ellipsis-h
|
i.fas.fa-ellipsis-h
|
||||||
.toolbar(*ngIf='session', [class.show]='!session.open')
|
.toolbar([class.show]='!session || !session.open')
|
||||||
i.fas.fa-circle.text-success.mr-2(*ngIf='session.open')
|
i.fas.fa-circle.text-success.mr-2(*ngIf='session && session.open')
|
||||||
i.fas.fa-circle.text-danger.mr-2(*ngIf='!session.open')
|
i.fas.fa-circle.text-danger.mr-2(*ngIf='!session || !session.open')
|
||||||
strong(*ngIf='session') {{session.connection.port}} ({{session.connection.baudrate}})
|
strong(*ngIf='session') {{session.connection.port}} ({{session.connection.baudrate}})
|
||||||
|
|
||||||
.mr-auto
|
.mr-auto
|
||||||
|
|
||||||
button.btn.btn-secondary.mr-3((click)='changeBaudRate()', *ngIf='session.open')
|
button.btn.btn-secondary.mr-3((click)='changeBaudRate()', *ngIf='session && session.open')
|
||||||
span Change baud rate
|
span Change baud rate
|
||||||
|
|
||||||
button.btn.btn-info((click)='reconnect()', *ngIf='!session.open')
|
button.btn.btn-info((click)='reconnect()', *ngIf='!session || !session.open')
|
||||||
i.fas.fa-reload
|
i.fas.fa-reload
|
||||||
span Reconnect
|
span Reconnect
|
||||||
|
@@ -11,14 +11,15 @@ import { Subscription } from 'rxjs'
|
|||||||
/** @hidden */
|
/** @hidden */
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'serial-tab',
|
selector: 'serial-tab',
|
||||||
template: BaseTerminalTabComponent.template + (require('./serialTab.component.pug') as string),
|
template: `${BaseTerminalTabComponent.template} ${require('./serialTab.component.pug')}`,
|
||||||
styles: [require('./serialTab.component.scss'), ...BaseTerminalTabComponent.styles],
|
styles: [require('./serialTab.component.scss'), ...BaseTerminalTabComponent.styles],
|
||||||
animations: BaseTerminalTabComponent.animations,
|
animations: BaseTerminalTabComponent.animations,
|
||||||
})
|
})
|
||||||
export class SerialTabComponent extends BaseTerminalTabComponent {
|
export class SerialTabComponent extends BaseTerminalTabComponent {
|
||||||
connection?: SerialConnection
|
connection?: SerialConnection
|
||||||
session?: SerialSession
|
session: SerialSession|null = null
|
||||||
serialPort: any
|
serialPort: any
|
||||||
|
private serialService: SerialService
|
||||||
private homeEndSubscription: Subscription
|
private homeEndSubscription: Subscription
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-useless-constructor
|
// eslint-disable-next-line @typescript-eslint/no-useless-constructor
|
||||||
@@ -26,6 +27,7 @@ export class SerialTabComponent extends BaseTerminalTabComponent {
|
|||||||
injector: Injector,
|
injector: Injector,
|
||||||
) {
|
) {
|
||||||
super(injector)
|
super(injector)
|
||||||
|
this.serialService = injector.get(SerialService)
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit () {
|
ngOnInit () {
|
||||||
@@ -62,12 +64,8 @@ export class SerialTabComponent extends BaseTerminalTabComponent {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
this.session = this.injector.get(SerialService).createSession(this.connection)
|
const session = this.serialService.createSession(this.connection)
|
||||||
this.session.serviceMessage$.subscribe(msg => {
|
this.setSession(session)
|
||||||
this.write(`\r\n${colors.black.bgWhite(' serial ')} ${msg}\r\n`)
|
|
||||||
this.session?.resize(this.size.columns, this.size.rows)
|
|
||||||
})
|
|
||||||
this.attachSessionHandlers()
|
|
||||||
this.write(`Connecting to `)
|
this.write(`Connecting to `)
|
||||||
|
|
||||||
const spinner = new Spinner({
|
const spinner = new Spinner({
|
||||||
@@ -80,15 +78,32 @@ export class SerialTabComponent extends BaseTerminalTabComponent {
|
|||||||
spinner.start()
|
spinner.start()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this.serialPort = await this.injector.get(SerialService).connectSession(this.session)
|
this.serialPort = await this.serialService.connectSession(this.session!)
|
||||||
spinner.stop(true)
|
spinner.stop(true)
|
||||||
|
session.emitServiceMessage('Port opened')
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
spinner.stop(true)
|
spinner.stop(true)
|
||||||
this.write(colors.black.bgRed(' X ') + ' ' + colors.red(e.message) + '\r\n')
|
this.write(colors.black.bgRed(' X ') + ' ' + colors.red(e.message) + '\r\n')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
await this.session.start()
|
await this.session!.start()
|
||||||
this.session.resize(this.size.columns, this.size.rows)
|
this.session!.resize(this.size.columns, this.size.rows)
|
||||||
|
}
|
||||||
|
|
||||||
|
protected attachSessionHandlers () {
|
||||||
|
this.attachSessionHandler(this.session!.serviceMessage$.subscribe(msg => {
|
||||||
|
this.write(`\r\n${colors.black.bgWhite(' Serial ')} ${msg}\r\n`)
|
||||||
|
this.session?.resize(this.size.columns, this.size.rows)
|
||||||
|
}))
|
||||||
|
this.attachSessionHandler(this.session!.destroyed$.subscribe(() => {
|
||||||
|
this.write('Press any key to reconnect\r\n')
|
||||||
|
this.input$.pipe(first()).subscribe(() => {
|
||||||
|
if (!this.session?.open) {
|
||||||
|
this.reconnect()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}))
|
||||||
|
super.attachSessionHandlers()
|
||||||
}
|
}
|
||||||
|
|
||||||
async getRecoveryToken (): Promise<any> {
|
async getRecoveryToken (): Promise<any> {
|
||||||
@@ -99,8 +114,10 @@ export class SerialTabComponent extends BaseTerminalTabComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
reconnect () {
|
async reconnect (): Promise<void> {
|
||||||
this.initializeSession()
|
this.session?.destroy()
|
||||||
|
await this.initializeSession()
|
||||||
|
this.session?.releaseInitialDataBuffer()
|
||||||
}
|
}
|
||||||
|
|
||||||
async changeBaudRate () {
|
async changeBaudRate () {
|
||||||
|
@@ -30,10 +30,17 @@ export class SerialService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async connectSession (session: SerialSession): Promise<SerialPort> {
|
async connectSession (session: SerialSession): Promise<SerialPort> {
|
||||||
const serial = new SerialPort(session.connection.port, { autoOpen: false, baudRate: session.connection.baudrate,
|
const serial = new SerialPort(session.connection.port, {
|
||||||
dataBits: session.connection.databits, stopBits: session.connection.stopbits, parity: session.connection.parity,
|
autoOpen: false,
|
||||||
rtscts: session.connection.rtscts, xon: session.connection.xon, xoff: session.connection.xoff,
|
baudRate: session.connection.baudrate,
|
||||||
xany: session.connection.xany })
|
dataBits: session.connection.databits,
|
||||||
|
stopBits: session.connection.stopbits,
|
||||||
|
parity: session.connection.parity,
|
||||||
|
rtscts: session.connection.rtscts,
|
||||||
|
xon: session.connection.xon,
|
||||||
|
xoff: session.connection.xoff,
|
||||||
|
xany: session.connection.xany,
|
||||||
|
})
|
||||||
session.serial = serial
|
session.serial = serial
|
||||||
let connected = false
|
let connected = false
|
||||||
await new Promise(async (resolve, reject) => {
|
await new Promise(async (resolve, reject) => {
|
||||||
@@ -50,6 +57,10 @@ export class SerialService {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
serial.on('close', () => {
|
||||||
|
session.emitServiceMessage('Port closed')
|
||||||
|
session.destroy()
|
||||||
|
})
|
||||||
|
|
||||||
try {
|
try {
|
||||||
serial.open()
|
serial.open()
|
||||||
@@ -103,7 +114,7 @@ export class SerialService {
|
|||||||
options.push({
|
options.push({
|
||||||
name: 'Manage connections',
|
name: 'Manage connections',
|
||||||
icon: 'cog',
|
icon: 'cog',
|
||||||
callback: () => this.app.openNewTab(SettingsTabComponent, { activeTab: 'serial' }),
|
callback: () => this.app.openNewTabRaw(SettingsTabComponent, { activeTab: 'serial' }),
|
||||||
})
|
})
|
||||||
|
|
||||||
options.push({
|
options.push({
|
||||||
|
@@ -40,7 +40,7 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{ test: /\.pug$/, use: ['apply-loader', 'pug-loader'] },
|
{ test: /\.pug$/, use: ['apply-loader', 'pug-loader'] },
|
||||||
{ test: /\.scss$/, use: ['to-string-loader', 'css-loader', 'sass-loader'] },
|
{ test: /\.scss$/, use: ['@terminus-term/to-string-loader', 'css-loader', 'sass-loader'] },
|
||||||
{ test: /\.svg/, use: ['svg-inline-loader'] },
|
{ test: /\.svg/, use: ['svg-inline-loader'] },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@@ -50,6 +50,8 @@ module.exports = {
|
|||||||
'path',
|
'path',
|
||||||
'ngx-toastr',
|
'ngx-toastr',
|
||||||
'serialport',
|
'serialport',
|
||||||
|
'readline',
|
||||||
|
'stream',
|
||||||
'windows-process-tree/build/Release/windows_process_tree.node',
|
'windows-process-tree/build/Release/windows_process_tree.node',
|
||||||
/^rxjs/,
|
/^rxjs/,
|
||||||
/^@angular/,
|
/^@angular/,
|
||||||
|
@@ -32,6 +32,11 @@ ansi-colors@^4.1.1:
|
|||||||
resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348"
|
resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348"
|
||||||
integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==
|
integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==
|
||||||
|
|
||||||
|
buffer-replace@^1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/buffer-replace/-/buffer-replace-1.0.0.tgz#bc427c40af4c1f06d6933dede57110acba8ade54"
|
||||||
|
integrity sha1-vEJ8QK9MHwbWkz3t5XEQrLqK3lQ=
|
||||||
|
|
||||||
cli-spinner@^0.2.10:
|
cli-spinner@^0.2.10:
|
||||||
version "0.2.10"
|
version "0.2.10"
|
||||||
resolved "https://registry.yarnpkg.com/cli-spinner/-/cli-spinner-0.2.10.tgz#f7d617a36f5c47a7bc6353c697fc9338ff782a47"
|
resolved "https://registry.yarnpkg.com/cli-spinner/-/cli-spinner-0.2.10.tgz#f7d617a36f5c47a7bc6353c697fc9338ff782a47"
|
||||||
|
@@ -307,7 +307,7 @@ ngb-tabset.vertical(type='pills', [activeId]='activeTab')
|
|||||||
td {{hotkey.id}}
|
td {{hotkey.id}}
|
||||||
td.pr-5
|
td.pr-5
|
||||||
multi-hotkey-input(
|
multi-hotkey-input(
|
||||||
[model]='getHotkey(hotkey.id)',
|
[model]='getHotkey(hotkey.id) || []',
|
||||||
(modelChange)='setHotkey(hotkey.id, $event); config.save(); docking.dock()'
|
(modelChange)='setHotkey(hotkey.id, $event); config.save(); docking.dock()'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -60,7 +60,7 @@ export class SettingsTabComponent extends BaseTabComponent {
|
|||||||
this.settingsProviders = config.enabledServices(this.settingsProviders)
|
this.settingsProviders = config.enabledServices(this.settingsProviders)
|
||||||
this.themes = config.enabledServices(this.themes)
|
this.themes = config.enabledServices(this.themes)
|
||||||
|
|
||||||
this.configDefaults = yaml.safeDump(config.getDefaults())
|
this.configDefaults = yaml.dump(config.getDefaults())
|
||||||
|
|
||||||
const onConfigChange = () => {
|
const onConfigChange = () => {
|
||||||
this.configFile = config.readRaw()
|
this.configFile = config.readRaw()
|
||||||
@@ -116,7 +116,7 @@ export class SettingsTabComponent extends BaseTabComponent {
|
|||||||
|
|
||||||
isConfigFileValid () {
|
isConfigFileValid () {
|
||||||
try {
|
try {
|
||||||
yaml.safeLoad(this.configFile)
|
yaml.load(this.configFile)
|
||||||
return true
|
return true
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
return false
|
return false
|
||||||
|
@@ -40,8 +40,8 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{ test: /\.pug$/, use: ['apply-loader', 'pug-loader'] },
|
{ test: /\.pug$/, use: ['apply-loader', 'pug-loader'] },
|
||||||
{ test: /\.scss$/, use: ['to-string-loader', 'css-loader', 'sass-loader'] },
|
{ test: /\.scss$/, use: ['@terminus-term/to-string-loader', 'css-loader', 'sass-loader'] },
|
||||||
{ test: /\.css$/, use: ['to-string-loader', 'css-loader', 'sass-loader'] },
|
{ test: /\.css$/, use: ['@terminus-term/to-string-loader', 'css-loader', 'sass-loader'] },
|
||||||
{ test: /\.svg/, use: ['svg-inline-loader'] },
|
{ test: /\.svg/, use: ['svg-inline-loader'] },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@@ -140,6 +140,9 @@ export class SSHSession extends BaseSession {
|
|||||||
this.shell = await this.openShellChannel({ x11: this.connection.x11 })
|
this.shell = await this.openShellChannel({ x11: this.connection.x11 })
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this.emitServiceMessage(colors.bgRed.black(' X ') + ` Remote rejected opening a shell channel: ${err}`)
|
this.emitServiceMessage(colors.bgRed.black(' X ') + ` Remote rejected opening a shell channel: ${err}`)
|
||||||
|
if (err.toString().includes('Unable to request X11')) {
|
||||||
|
this.emitServiceMessage(' Make sure `xauth` is installed on the remote side')
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -245,7 +248,13 @@ export class SSHSession extends BaseSession {
|
|||||||
}
|
}
|
||||||
socket.on('error', e => {
|
socket.on('error', e => {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-base-to-string
|
// eslint-disable-next-line @typescript-eslint/no-base-to-string
|
||||||
this.emitServiceMessage(colors.bgRed.black(' X ') + ` Could not connect to the X server ${xHost}:${xPort}: ${e}`)
|
this.emitServiceMessage(colors.bgRed.black(' X ') + ` Could not connect to the X server: ${e}`)
|
||||||
|
this.emitServiceMessage(` Terminus tried to connect to ${xHost}:${xPort} based on the DISPLAY environment var (${displaySpec})`)
|
||||||
|
if (process.platform === 'win32') {
|
||||||
|
this.emitServiceMessage(' To use X forwarding, you need a local X server, e.g.:')
|
||||||
|
this.emitServiceMessage(' * VcXsrv: https://sourceforge.net/projects/vcxsrv/')
|
||||||
|
this.emitServiceMessage(' * Xming: https://sourceforge.net/projects/xming/')
|
||||||
|
}
|
||||||
reject()
|
reject()
|
||||||
})
|
})
|
||||||
socket.on('connect', () => {
|
socket.on('connect', () => {
|
||||||
@@ -363,6 +372,10 @@ export class SSHSession extends BaseSession {
|
|||||||
this.kill('TERM')
|
this.kill('TERM')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
supportsWorkingDirectory (): boolean {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
async getWorkingDirectory (): Promise<string|null> {
|
async getWorkingDirectory (): Promise<string|null> {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
@@ -398,3 +411,9 @@ export interface SSHConnectionGroup {
|
|||||||
name: string
|
name: string
|
||||||
connections: SSHConnection[]
|
connections: SSHConnection[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const ALGORITHM_BLACKLIST = [
|
||||||
|
// cause native crashes in node crypto, use EC instead
|
||||||
|
'diffie-hellman-group-exchange-sha256',
|
||||||
|
'diffie-hellman-group-exchange-sha1',
|
||||||
|
]
|
||||||
|
@@ -103,7 +103,7 @@
|
|||||||
.header
|
.header
|
||||||
.title Jump host
|
.title Jump host
|
||||||
select.form-control([(ngModel)]='connection.jumpHost')
|
select.form-control([(ngModel)]='connection.jumpHost')
|
||||||
option([ngValue]='null') None
|
option(value='') None
|
||||||
option([ngValue]='x.name', *ngFor='let x of config.store.ssh.connections') {{x.name}}
|
option([ngValue]='x.name', *ngFor='let x of config.store.ssh.connections') {{x.name}}
|
||||||
|
|
||||||
.form-line
|
.form-line
|
||||||
|
@@ -3,7 +3,7 @@ import { Component } from '@angular/core'
|
|||||||
import { NgbModal, NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
|
import { NgbModal, NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
|
||||||
import { ElectronService, HostAppService, ConfigService } from 'terminus-core'
|
import { ElectronService, HostAppService, ConfigService } from 'terminus-core'
|
||||||
import { PasswordStorageService } from '../services/passwordStorage.service'
|
import { PasswordStorageService } from '../services/passwordStorage.service'
|
||||||
import { SSHConnection, LoginScript, SSHAlgorithmType } from '../api'
|
import { SSHConnection, LoginScript, SSHAlgorithmType, ALGORITHM_BLACKLIST } from '../api'
|
||||||
import { PromptModalComponent } from './promptModal.component'
|
import { PromptModalComponent } from './promptModal.component'
|
||||||
import { ALGORITHMS } from 'ssh2-streams/lib/constants'
|
import { ALGORITHMS } from 'ssh2-streams/lib/constants'
|
||||||
|
|
||||||
@@ -40,8 +40,8 @@ export class EditConnectionModalComponent {
|
|||||||
[SSHAlgorithmType.CIPHER]: 'CIPHER',
|
[SSHAlgorithmType.CIPHER]: 'CIPHER',
|
||||||
[SSHAlgorithmType.HMAC]: 'HMAC',
|
[SSHAlgorithmType.HMAC]: 'HMAC',
|
||||||
}[k]
|
}[k]
|
||||||
this.supportedAlgorithms[k] = ALGORITHMS[supportedAlg]
|
this.supportedAlgorithms[k] = ALGORITHMS[supportedAlg].filter(x => !ALGORITHM_BLACKLIST.includes(x))
|
||||||
this.defaultAlgorithms[k] = ALGORITHMS[defaultAlg]
|
this.defaultAlgorithms[k] = ALGORITHMS[defaultAlg].filter(x => !ALGORITHM_BLACKLIST.includes(x))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -14,15 +14,17 @@ import { Subscription } from 'rxjs'
|
|||||||
/** @hidden */
|
/** @hidden */
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ssh-tab',
|
selector: 'ssh-tab',
|
||||||
template: BaseTerminalTabComponent.template + (require('./sshTab.component.pug') as string),
|
template: `${BaseTerminalTabComponent.template} ${require('./sshTab.component.pug')}`,
|
||||||
styles: [require('./sshTab.component.scss'), ...BaseTerminalTabComponent.styles],
|
styles: [require('./sshTab.component.scss'), ...BaseTerminalTabComponent.styles],
|
||||||
animations: BaseTerminalTabComponent.animations,
|
animations: BaseTerminalTabComponent.animations,
|
||||||
})
|
})
|
||||||
export class SSHTabComponent extends BaseTerminalTabComponent {
|
export class SSHTabComponent extends BaseTerminalTabComponent {
|
||||||
connection?: SSHConnection
|
connection?: SSHConnection
|
||||||
session?: SSHSession
|
session: SSHSession|null = null
|
||||||
private sessionStack: SSHSession[] = []
|
private sessionStack: SSHSession[] = []
|
||||||
private homeEndSubscription: Subscription
|
private homeEndSubscription: Subscription
|
||||||
|
private recentInputs = ''
|
||||||
|
private reconnectOffered = false
|
||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
injector: Injector,
|
injector: Injector,
|
||||||
@@ -57,6 +59,10 @@ export class SSHTabComponent extends BaseTerminalTabComponent {
|
|||||||
|
|
||||||
this.frontendReady$.pipe(first()).subscribe(() => {
|
this.frontendReady$.pipe(first()).subscribe(() => {
|
||||||
this.initializeSession()
|
this.initializeSession()
|
||||||
|
this.input$.subscribe(data => {
|
||||||
|
this.recentInputs += data
|
||||||
|
this.recentInputs = this.recentInputs.substring(this.recentInputs.length - 32)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
super.ngOnInit()
|
super.ngOnInit()
|
||||||
@@ -68,12 +74,23 @@ export class SSHTabComponent extends BaseTerminalTabComponent {
|
|||||||
|
|
||||||
async setupOneSession (session: SSHSession): Promise<void> {
|
async setupOneSession (session: SSHSession): Promise<void> {
|
||||||
if (session.connection.jumpHost) {
|
if (session.connection.jumpHost) {
|
||||||
const jumpConnection = this.config.store.ssh.connections.find(x => x.name === session.connection.jumpHost)
|
const jumpConnection: SSHConnection|null = this.config.store.ssh.connections.find(x => x.name === session.connection.jumpHost)
|
||||||
|
|
||||||
|
if (!jumpConnection) {
|
||||||
|
throw new Error(`${session.connection.host}: jump host "${session.connection.jumpHost}" not found in your config`)
|
||||||
|
}
|
||||||
|
|
||||||
const jumpSession = this.ssh.createSession(jumpConnection)
|
const jumpSession = this.ssh.createSession(jumpConnection)
|
||||||
|
|
||||||
await this.setupOneSession(jumpSession)
|
await this.setupOneSession(jumpSession)
|
||||||
|
|
||||||
jumpSession.destroyed$.subscribe(() => session.destroy())
|
this.attachSessionHandler(
|
||||||
|
jumpSession.destroyed$.subscribe(() => {
|
||||||
|
if (session.open) {
|
||||||
|
session.destroy()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
session.jumpStream = await new Promise((resolve, reject) => jumpSession.ssh.forwardOut(
|
session.jumpStream = await new Promise((resolve, reject) => jumpSession.ssh.forwardOut(
|
||||||
'127.0.0.1', 0, session.connection.host, session.connection.port ?? 22,
|
'127.0.0.1', 0, session.connection.host, session.connection.port ?? 22,
|
||||||
@@ -93,15 +110,11 @@ export class SSHTabComponent extends BaseTerminalTabComponent {
|
|||||||
this.sessionStack.push(session)
|
this.sessionStack.push(session)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.attachSessionHandler(session.serviceMessage$.subscribe(msg => {
|
||||||
session.serviceMessage$.subscribe(msg => {
|
|
||||||
this.write(`\r\n${colors.black.bgWhite(' SSH ')} ${msg}\r\n`)
|
this.write(`\r\n${colors.black.bgWhite(' SSH ')} ${msg}\r\n`)
|
||||||
session.resize(this.size.columns, this.size.rows)
|
session.resize(this.size.columns, this.size.rows)
|
||||||
})
|
}))
|
||||||
|
|
||||||
session.destroyed$.subscribe(() => {
|
|
||||||
this.write('\r\n' + colors.black.bgCyan(' SSH ') + ` ${session.connection.host}: session closed\r\n`)
|
|
||||||
})
|
|
||||||
|
|
||||||
this.write('\r\n' + colors.black.bgCyan(' SSH ') + ` Connecting to ${session.connection.host}\r\n`)
|
this.write('\r\n' + colors.black.bgCyan(' SSH ') + ` Connecting to ${session.connection.host}\r\n`)
|
||||||
|
|
||||||
@@ -128,20 +141,49 @@ export class SSHTabComponent extends BaseTerminalTabComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected attachSessionHandlers (): void {
|
||||||
|
const session = this.session!
|
||||||
|
super.attachSessionHandlers()
|
||||||
|
this.attachSessionHandler(session.destroyed$.subscribe(() => {
|
||||||
|
if (
|
||||||
|
// Ctrl-D
|
||||||
|
this.recentInputs.charCodeAt(this.recentInputs.length - 1) === 4 ||
|
||||||
|
this.recentInputs.endsWith('exit\r')
|
||||||
|
) {
|
||||||
|
// User closed the session
|
||||||
|
this.destroy()
|
||||||
|
} else {
|
||||||
|
// Session was closed abruptly
|
||||||
|
this.write('\r\n' + colors.black.bgCyan(' SSH ') + ` ${session.connection.host}: session closed\r\n`)
|
||||||
|
if (!this.reconnectOffered) {
|
||||||
|
this.reconnectOffered = true
|
||||||
|
this.write('Press any key to reconnect\r\n')
|
||||||
|
this.attachSessionHandler(this.input$.pipe(first()).subscribe(() => {
|
||||||
|
this.reconnect()
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
async initializeSession (): Promise<void> {
|
async initializeSession (): Promise<void> {
|
||||||
|
this.reconnectOffered = false
|
||||||
if (!this.connection) {
|
if (!this.connection) {
|
||||||
this.logger.error('No SSH connection info supplied')
|
this.logger.error('No SSH connection info supplied')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
this.session = this.ssh.createSession(this.connection)
|
const session = this.ssh.createSession(this.connection)
|
||||||
|
this.setSession(session)
|
||||||
|
|
||||||
await this.setupOneSession(this.session)
|
try {
|
||||||
|
await this.setupOneSession(session)
|
||||||
|
} catch (e) {
|
||||||
|
this.write(colors.black.bgRed(' X ') + ' ' + colors.red(e.message) + '\r\n')
|
||||||
|
}
|
||||||
|
|
||||||
this.attachSessionHandlers()
|
await this.session!.start()
|
||||||
|
this.session!.resize(this.size.columns, this.size.rows)
|
||||||
await this.session.start()
|
|
||||||
this.session.resize(this.size.columns, this.size.rows)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async getRecoveryToken (): Promise<RecoveryToken> {
|
async getRecoveryToken (): Promise<RecoveryToken> {
|
||||||
|
@@ -12,7 +12,7 @@ import * as sshpk from 'sshpk'
|
|||||||
import { ToastrService } from 'ngx-toastr'
|
import { ToastrService } from 'ngx-toastr'
|
||||||
import { HostAppService, Platform, Logger, LogService, ElectronService, AppService, SelectorOption, ConfigService } from 'terminus-core'
|
import { HostAppService, Platform, Logger, LogService, ElectronService, AppService, SelectorOption, ConfigService } from 'terminus-core'
|
||||||
import { SettingsTabComponent } from 'terminus-settings'
|
import { SettingsTabComponent } from 'terminus-settings'
|
||||||
import { SSHConnection, SSHSession } from '../api'
|
import { ALGORITHM_BLACKLIST, SSHConnection, SSHSession } from '../api'
|
||||||
import { PromptModalComponent } from '../components/promptModal.component'
|
import { PromptModalComponent } from '../components/promptModal.component'
|
||||||
import { PasswordStorageService } from './passwordStorage.service'
|
import { PasswordStorageService } from './passwordStorage.service'
|
||||||
import { SSHTabComponent } from '../components/sshTab.component'
|
import { SSHTabComponent } from '../components/sshTab.component'
|
||||||
@@ -147,6 +147,10 @@ export class SSHService {
|
|||||||
session.ssh = ssh
|
session.ssh = ssh
|
||||||
let connected = false
|
let connected = false
|
||||||
let savedPassword: string|null = null
|
let savedPassword: string|null = null
|
||||||
|
const algorithms = {}
|
||||||
|
for (const key of Object.keys(session.connection.algorithms ?? {})) {
|
||||||
|
algorithms[key] = session.connection.algorithms![key].filter(x => !ALGORITHM_BLACKLIST.includes(x))
|
||||||
|
}
|
||||||
await new Promise(async (resolve, reject) => {
|
await new Promise(async (resolve, reject) => {
|
||||||
ssh.on('ready', () => {
|
ssh.on('ready', () => {
|
||||||
connected = true
|
connected = true
|
||||||
@@ -258,7 +262,7 @@ export class SSHService {
|
|||||||
tryKeyboard: true,
|
tryKeyboard: true,
|
||||||
agent: agent ?? undefined,
|
agent: agent ?? undefined,
|
||||||
agentForward: session.connection.agentForward && !!agent,
|
agentForward: session.connection.agentForward && !!agent,
|
||||||
keepaliveInterval: session.connection.keepaliveInterval,
|
keepaliveInterval: session.connection.keepaliveInterval ?? 15000,
|
||||||
keepaliveCountMax: session.connection.keepaliveCountMax,
|
keepaliveCountMax: session.connection.keepaliveCountMax,
|
||||||
readyTimeout: session.connection.readyTimeout,
|
readyTimeout: session.connection.readyTimeout,
|
||||||
hostVerifier: (digest: string) => {
|
hostVerifier: (digest: string) => {
|
||||||
@@ -267,7 +271,7 @@ export class SSHService {
|
|||||||
return true
|
return true
|
||||||
},
|
},
|
||||||
hostHash: 'sha256' as any,
|
hostHash: 'sha256' as any,
|
||||||
algorithms: session.connection.algorithms,
|
algorithms,
|
||||||
sock: session.jumpStream,
|
sock: session.jumpStream,
|
||||||
authHandler: methodsLeft => {
|
authHandler: methodsLeft => {
|
||||||
while (true) {
|
while (true) {
|
||||||
@@ -379,7 +383,7 @@ export class SSHService {
|
|||||||
options.push({
|
options.push({
|
||||||
name: 'Manage connections',
|
name: 'Manage connections',
|
||||||
icon: 'cog',
|
icon: 'cog',
|
||||||
callback: () => this.app.openNewTab(SettingsTabComponent, { activeTab: 'ssh' }),
|
callback: () => this.app.openNewTabRaw(SettingsTabComponent, { activeTab: 'ssh' }),
|
||||||
})
|
})
|
||||||
|
|
||||||
options.push({
|
options.push({
|
||||||
|
@@ -40,7 +40,7 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{ test: /\.pug$/, use: ['apply-loader', 'pug-loader'] },
|
{ test: /\.pug$/, use: ['apply-loader', 'pug-loader'] },
|
||||||
{ test: /\.scss$/, use: ['to-string-loader', 'css-loader', 'sass-loader'] },
|
{ test: /\.scss$/, use: ['@terminus-term/to-string-loader', 'css-loader', 'sass-loader'] },
|
||||||
{ test: /\.svg/, use: ['svg-inline-loader'] },
|
{ test: /\.svg/, use: ['svg-inline-loader'] },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
@@ -27,12 +27,12 @@
|
|||||||
"runes": "^0.4.2",
|
"runes": "^0.4.2",
|
||||||
"slugify": "^1.4.0",
|
"slugify": "^1.4.0",
|
||||||
"xterm": "^4.9.0-beta.7",
|
"xterm": "^4.9.0-beta.7",
|
||||||
"xterm-addon-fit": "^0.4.0-beta.8",
|
"xterm-addon-fit": "^0.5.0",
|
||||||
"xterm-addon-ligatures": "^0.4.0-beta.5",
|
"xterm-addon-ligatures": "^0.4.0",
|
||||||
"xterm-addon-search": "^0.7.0-beta.2",
|
"xterm-addon-search": "^0.8.0",
|
||||||
"xterm-addon-serialize": "^0.3.0",
|
"xterm-addon-serialize": "^0.4.0",
|
||||||
"xterm-addon-unicode11": "^0.2.0",
|
"xterm-addon-unicode11": "^0.2.0",
|
||||||
"xterm-addon-webgl": "^0.8.0",
|
"xterm-addon-webgl": "^0.9.0",
|
||||||
"zmodem.js": "^0.1.9"
|
"zmodem.js": "^0.1.9"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
|
@@ -18,6 +18,7 @@ import { TerminalDecorator } from './decorator'
|
|||||||
/** @hidden */
|
/** @hidden */
|
||||||
export interface ToastrServiceProxy {
|
export interface ToastrServiceProxy {
|
||||||
info: (_: string) => void
|
info: (_: string) => void
|
||||||
|
error: (_: string) => void
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* A class to base your custom terminal tabs on
|
* A class to base your custom terminal tabs on
|
||||||
@@ -35,7 +36,7 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
|
|||||||
]),
|
]),
|
||||||
])]
|
])]
|
||||||
|
|
||||||
session?: BaseSession
|
session: BaseSession|null = null
|
||||||
savedState?: any
|
savedState?: any
|
||||||
|
|
||||||
@Input() zoom = 0
|
@Input() zoom = 0
|
||||||
@@ -94,6 +95,7 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
|
|||||||
private bellPlayer: HTMLAudioElement
|
private bellPlayer: HTMLAudioElement
|
||||||
private termContainerSubscriptions: Subscription[] = []
|
private termContainerSubscriptions: Subscription[] = []
|
||||||
private allFocusModeSubscription: Subscription|null = null
|
private allFocusModeSubscription: Subscription|null = null
|
||||||
|
private sessionHandlers: Subscription[] = []
|
||||||
|
|
||||||
get input$ (): Observable<Buffer> {
|
get input$ (): Observable<Buffer> {
|
||||||
if (!this.frontend) {
|
if (!this.frontend) {
|
||||||
@@ -140,7 +142,7 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
|
|||||||
this.logger = this.log.create('baseTerminalTab')
|
this.logger = this.log.create('baseTerminalTab')
|
||||||
this.setTitle('Terminal')
|
this.setTitle('Terminal')
|
||||||
|
|
||||||
this.hotkeysSubscription = this.hotkeys.matchedHotkey.subscribe(hotkey => {
|
this.hotkeysSubscription = this.hotkeys.matchedHotkey.subscribe(async hotkey => {
|
||||||
if (!this.hasFocus) {
|
if (!this.hasFocus) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -207,6 +209,9 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
|
|||||||
case 'pane-focus-all':
|
case 'pane-focus-all':
|
||||||
this.focusAllPanes()
|
this.focusAllPanes()
|
||||||
break
|
break
|
||||||
|
case 'copy-current-path':
|
||||||
|
this.copyCurrentPath()
|
||||||
|
break
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
this.bellPlayer = document.createElement('audio')
|
this.bellPlayer = document.createElement('audio')
|
||||||
@@ -217,10 +222,6 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
|
|||||||
|
|
||||||
/** @hidden */
|
/** @hidden */
|
||||||
ngOnInit (): void {
|
ngOnInit (): void {
|
||||||
if (!this.session) {
|
|
||||||
throw new Error('No session set on the tab object by the time ngOnInit is called')
|
|
||||||
}
|
|
||||||
|
|
||||||
this.focused$.subscribe(() => {
|
this.focused$.subscribe(() => {
|
||||||
this.configure()
|
this.configure()
|
||||||
this.frontend?.focus()
|
this.frontend?.focus()
|
||||||
@@ -347,7 +348,7 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
|
|||||||
async paste (): Promise<void> {
|
async paste (): Promise<void> {
|
||||||
let data = this.electron.clipboard.readText()
|
let data = this.electron.clipboard.readText()
|
||||||
if (this.config.store.terminal.bracketedPaste) {
|
if (this.config.store.terminal.bracketedPaste) {
|
||||||
data = '\x1b[200~' + data + '\x1b[201~'
|
data = `\x1b[200~${data}\x1b[201~`
|
||||||
}
|
}
|
||||||
if (this.hostApp.platform === Platform.Windows) {
|
if (this.hostApp.platform === Platform.Windows) {
|
||||||
data = data.replace(/\r\n/g, '\r')
|
data = data.replace(/\r\n/g, '\r')
|
||||||
@@ -418,10 +419,11 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (this.parent instanceof SplitTabComponent) {
|
if (this.parent instanceof SplitTabComponent) {
|
||||||
this.parent._allFocusMode = true
|
const parent = this.parent
|
||||||
this.parent.layout()
|
parent._allFocusMode = true
|
||||||
|
parent.layout()
|
||||||
this.allFocusModeSubscription = this.frontend?.input$.subscribe(data => {
|
this.allFocusModeSubscription = this.frontend?.input$.subscribe(data => {
|
||||||
for (const tab of (this.parent as SplitTabComponent).getAllTabs()) {
|
for (const tab of parent.getAllTabs()) {
|
||||||
if (tab !== this && tab instanceof BaseTerminalTabComponent) {
|
if (tab !== this && tab instanceof BaseTerminalTabComponent) {
|
||||||
tab.sendInput(data)
|
tab.sendInput(data)
|
||||||
}
|
}
|
||||||
@@ -442,6 +444,19 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async copyCurrentPath (): Promise<void> {
|
||||||
|
let cwd: string|null = null
|
||||||
|
if (this.session?.supportsWorkingDirectory()) {
|
||||||
|
cwd = await this.session.getWorkingDirectory()
|
||||||
|
}
|
||||||
|
if (cwd) {
|
||||||
|
this.electron.clipboard.writeText(cwd)
|
||||||
|
this.toastr.info('Copied')
|
||||||
|
} else {
|
||||||
|
this.toastr.error('Shell does not support current path detection')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** @hidden */
|
/** @hidden */
|
||||||
ngOnDestroy (): void {
|
ngOnDestroy (): void {
|
||||||
this.frontend?.detach(this.content.nativeElement)
|
this.frontend?.detach(this.content.nativeElement)
|
||||||
@@ -554,26 +569,55 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setSession (session: BaseSession|null, destroyOnSessionClose = false): void {
|
||||||
|
if (session) {
|
||||||
|
if (this.session) {
|
||||||
|
this.setSession(null)
|
||||||
|
}
|
||||||
|
this.detachSessionHandlers()
|
||||||
|
this.session = session
|
||||||
|
this.attachSessionHandlers(destroyOnSessionClose)
|
||||||
|
} else {
|
||||||
|
this.detachSessionHandlers()
|
||||||
|
this.session = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected attachSessionHandler (subscription: Subscription): void {
|
||||||
|
this.sessionHandlers.push(subscription)
|
||||||
|
}
|
||||||
|
|
||||||
protected attachSessionHandlers (destroyOnSessionClose = false): void {
|
protected attachSessionHandlers (destroyOnSessionClose = false): void {
|
||||||
if (!this.session) {
|
if (!this.session) {
|
||||||
throw new Error('Session not set')
|
throw new Error('Session not set')
|
||||||
}
|
}
|
||||||
|
|
||||||
// this.session.output$.bufferTime(10).subscribe((datas) => {
|
// this.session.output$.bufferTime(10).subscribe((datas) => {
|
||||||
this.session.output$.subscribe(data => {
|
this.attachSessionHandler(this.session.output$.subscribe(data => {
|
||||||
if (this.enablePassthrough) {
|
if (this.enablePassthrough) {
|
||||||
this.zone.run(() => {
|
this.zone.run(() => {
|
||||||
this.output.next(data)
|
this.output.next(data)
|
||||||
this.write(data)
|
this.write(data)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
}))
|
||||||
|
|
||||||
if (destroyOnSessionClose) {
|
if (destroyOnSessionClose) {
|
||||||
this.sessionCloseSubscription = this.session.closed$.subscribe(() => {
|
this.attachSessionHandler(this.sessionCloseSubscription = this.session.closed$.subscribe(() => {
|
||||||
this.frontend?.destroy()
|
this.frontend?.destroy()
|
||||||
this.destroy()
|
this.destroy()
|
||||||
})
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.attachSessionHandler(this.session.destroyed$.subscribe(() => {
|
||||||
|
this.setSession(null)
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
protected detachSessionHandlers (): void {
|
||||||
|
for (const s of this.sessionHandlers) {
|
||||||
|
s.unsubscribe()
|
||||||
|
}
|
||||||
|
this.sessionHandlers = []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -10,7 +10,7 @@ import { Subject } from 'rxjs'
|
|||||||
})
|
})
|
||||||
export class EnvironmentEditorComponent {
|
export class EnvironmentEditorComponent {
|
||||||
@Output() modelChange = new Subject<any>()
|
@Output() modelChange = new Subject<any>()
|
||||||
vars: {key: string, value: string}[] = []
|
vars: { key: string, value: string }[] = []
|
||||||
private cachedModel: any
|
private cachedModel: any
|
||||||
|
|
||||||
@Input() get model (): any {
|
@Input() get model (): any {
|
||||||
|
@@ -57,15 +57,14 @@ h3.mb-3 Shell
|
|||||||
|
|
||||||
.form-line
|
.form-line
|
||||||
.header
|
.header
|
||||||
.title Always Use Working Directory
|
.title Directory for new tabs
|
||||||
.description
|
|
||||||
div By default, new terminals will open where the previous terminal was working.
|
|
||||||
div Enabling this option will always launch new terminals in the working directory specified above.
|
|
||||||
|
|
||||||
toggle(
|
select.form-control(
|
||||||
[(ngModel)]='config.store.terminal.alwaysUseWorkingDirectory',
|
[(ngModel)]='config.store.terminal.alwaysUseWorkingDirectory',
|
||||||
(ngModelChange)='config.save()'
|
(ngModelChange)='config.save()',
|
||||||
)
|
)
|
||||||
|
option([ngValue]='false') Same as active tab's directory
|
||||||
|
option([ngValue]='true') The working directory from above
|
||||||
|
|
||||||
.form-line.align-items-start
|
.form-line.align-items-start
|
||||||
.header
|
.header
|
||||||
@@ -97,7 +96,7 @@ h3.mt-3 Saved Profiles
|
|||||||
button.btn.btn-outline-danger.ml-1((click)='$event.stopPropagation(); deleteProfile(profile)')
|
button.btn.btn-outline-danger.ml-1((click)='$event.stopPropagation(); deleteProfile(profile)')
|
||||||
i.fas.fa-trash
|
i.fas.fa-trash
|
||||||
|
|
||||||
div(ngbDropdown, placement='top-left')
|
.pb-4(ngbDropdown, placement='top-left')
|
||||||
button.btn.btn-primary(ngbDropdownToggle)
|
button.btn.btn-primary(ngbDropdownToggle)
|
||||||
i.fas.fa-fw.fa-plus
|
i.fas.fa-fw.fa-plus
|
||||||
| New profile
|
| New profile
|
||||||
|
@@ -4,6 +4,7 @@ import { ConfigProvider, Platform } from 'terminus-core'
|
|||||||
export class TerminalConfigProvider extends ConfigProvider {
|
export class TerminalConfigProvider extends ConfigProvider {
|
||||||
defaults = {
|
defaults = {
|
||||||
hotkeys: {
|
hotkeys: {
|
||||||
|
'copy-current-path': [],
|
||||||
shell: {
|
shell: {
|
||||||
__nonStructural: true,
|
__nonStructural: true,
|
||||||
},
|
},
|
||||||
|
@@ -62,6 +62,10 @@ export class TerminalHotkeyProvider extends HotkeyProvider {
|
|||||||
id: 'ctrl-c',
|
id: 'ctrl-c',
|
||||||
name: 'Intelligent Ctrl-C (copy/abort)',
|
name: 'Intelligent Ctrl-C (copy/abort)',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: 'copy-current-path',
|
||||||
|
name: 'Copy current path',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
id: 'search',
|
id: 'search',
|
||||||
name: 'Search',
|
name: 'Search',
|
||||||
|
@@ -194,6 +194,9 @@ export default class TerminalModule { // eslint-disable-line @typescript-eslint/
|
|||||||
})
|
})
|
||||||
|
|
||||||
hostApp.cliOpenDirectory$.subscribe(async directory => {
|
hostApp.cliOpenDirectory$.subscribe(async directory => {
|
||||||
|
if (directory.length > 1 && (directory.endsWith('/') || directory.endsWith('\\'))) {
|
||||||
|
directory = directory.substring(0, directory.length - 1)
|
||||||
|
}
|
||||||
if (await fs.exists(directory)) {
|
if (await fs.exists(directory)) {
|
||||||
if ((await fs.stat(directory)).isDirectory()) {
|
if ((await fs.stat(directory)).isDirectory()) {
|
||||||
terminal.openTab(undefined, directory)
|
terminal.openTab(undefined, directory)
|
||||||
|
@@ -2,12 +2,11 @@ import * as psNode from 'ps-node'
|
|||||||
import * as fs from 'mz/fs'
|
import * as fs from 'mz/fs'
|
||||||
import * as os from 'os'
|
import * as os from 'os'
|
||||||
import * as nodePTY from '@terminus-term/node-pty'
|
import * as nodePTY from '@terminus-term/node-pty'
|
||||||
|
import { getWorkingDirectoryFromPID } from 'native-process-working-directory'
|
||||||
import { Observable, Subject } from 'rxjs'
|
import { Observable, Subject } from 'rxjs'
|
||||||
import { first } from 'rxjs/operators'
|
import { first } from 'rxjs/operators'
|
||||||
import { Injectable } from '@angular/core'
|
import { Injectable } from '@angular/core'
|
||||||
import { Logger, LogService, ConfigService, WIN_BUILD_CONPTY_SUPPORTED, isWindowsBuild } from 'terminus-core'
|
import { Logger, LogService, ConfigService, WIN_BUILD_CONPTY_SUPPORTED, isWindowsBuild } from 'terminus-core'
|
||||||
import { exec } from 'mz/child_process'
|
|
||||||
import { SessionOptions } from '../api/interfaces'
|
import { SessionOptions } from '../api/interfaces'
|
||||||
|
|
||||||
/* eslint-disable block-scoped-var */
|
/* eslint-disable block-scoped-var */
|
||||||
@@ -20,7 +19,6 @@ try {
|
|||||||
var windowsProcessTree = require('windows-process-tree') // eslint-disable-line @typescript-eslint/no-var-requires, no-var
|
var windowsProcessTree = require('windows-process-tree') // eslint-disable-line @typescript-eslint/no-var-requires, no-var
|
||||||
} catch { }
|
} catch { }
|
||||||
|
|
||||||
|
|
||||||
export interface ChildProcess {
|
export interface ChildProcess {
|
||||||
pid: number
|
pid: number
|
||||||
ppid: number
|
ppid: number
|
||||||
@@ -28,7 +26,6 @@ export interface ChildProcess {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const windowsDirectoryRegex = /([a-zA-Z]:[^\:\[\]\?\"\<\>\|]+)/mi
|
const windowsDirectoryRegex = /([a-zA-Z]:[^\:\[\]\?\"\<\>\|]+)/mi
|
||||||
const catalinaDataVolumePrefix = '/System/Volumes/Data'
|
|
||||||
const OSC1337Prefix = Buffer.from('\x1b]1337;')
|
const OSC1337Prefix = Buffer.from('\x1b]1337;')
|
||||||
const OSC1337Suffix = Buffer.from('\x07')
|
const OSC1337Suffix = Buffer.from('\x07')
|
||||||
|
|
||||||
@@ -87,6 +84,7 @@ export abstract class BaseSession {
|
|||||||
abstract kill (signal?: string): void
|
abstract kill (signal?: string): void
|
||||||
abstract async getChildProcesses (): Promise<ChildProcess[]>
|
abstract async getChildProcesses (): Promise<ChildProcess[]>
|
||||||
abstract async gracefullyKillProcess (): Promise<void>
|
abstract async gracefullyKillProcess (): Promise<void>
|
||||||
|
abstract supportsWorkingDirectory (): boolean
|
||||||
abstract async getWorkingDirectory (): Promise<string|null>
|
abstract async getWorkingDirectory (): Promise<string|null>
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,6 +94,7 @@ export class Session extends BaseSession {
|
|||||||
private pauseAfterExit = false
|
private pauseAfterExit = false
|
||||||
private guessedCWD: string|null = null
|
private guessedCWD: string|null = null
|
||||||
private reportedCWD: string
|
private reportedCWD: string
|
||||||
|
private initialCWD: string|null = null
|
||||||
|
|
||||||
constructor (private config: ConfigService) {
|
constructor (private config: ConfigService) {
|
||||||
super()
|
super()
|
||||||
@@ -153,6 +152,7 @@ export class Session extends BaseSession {
|
|||||||
this.truePID = processes[0].pid
|
this.truePID = processes[0].pid
|
||||||
processes = await this.getChildProcesses()
|
processes = await this.getChildProcesses()
|
||||||
}
|
}
|
||||||
|
this.initialCWD = await this.getWorkingDirectory()
|
||||||
}, 2000)
|
}, 2000)
|
||||||
|
|
||||||
this.open = true
|
this.open = true
|
||||||
@@ -259,6 +259,10 @@ export class Session extends BaseSession {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
supportsWorkingDirectory (): boolean {
|
||||||
|
return !!(this.truePID || this.reportedCWD || this.guessedCWD)
|
||||||
|
}
|
||||||
|
|
||||||
async getWorkingDirectory (): Promise<string|null> {
|
async getWorkingDirectory (): Promise<string|null> {
|
||||||
if (this.reportedCWD) {
|
if (this.reportedCWD) {
|
||||||
return this.reportedCWD
|
return this.reportedCWD
|
||||||
@@ -266,40 +270,31 @@ export class Session extends BaseSession {
|
|||||||
if (!this.truePID) {
|
if (!this.truePID) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
if (process.platform === 'darwin') {
|
let cwd: string|null = null
|
||||||
let lines: string[] = []
|
|
||||||
try {
|
try {
|
||||||
lines = (await exec(`lsof -p ${this.truePID} -Fn`))[0].toString().split('\n')
|
cwd = getWorkingDirectoryFromPID(this.truePID)
|
||||||
} catch (e) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
let cwd = lines[lines[1] === 'fcwd' ? 2 : 1].substring(1)
|
|
||||||
if (cwd.startsWith(catalinaDataVolumePrefix)) {
|
|
||||||
cwd = cwd.substring(catalinaDataVolumePrefix.length)
|
|
||||||
}
|
|
||||||
return cwd
|
|
||||||
}
|
|
||||||
if (process.platform === 'linux') {
|
|
||||||
try {
|
|
||||||
const cwd = await fs.readlink(`/proc/${this.truePID}/cwd`)
|
|
||||||
return cwd
|
|
||||||
} catch (exc) {
|
} catch (exc) {
|
||||||
console.error(exc)
|
console.error(exc)
|
||||||
return null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (process.platform === 'win32') {
|
|
||||||
if (!this.guessedCWD) {
|
|
||||||
return null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await fs.access(this.guessedCWD)
|
cwd = await fs.realpath(cwd)
|
||||||
} catch (e) {
|
} catch {}
|
||||||
|
|
||||||
|
if (process.platform === 'win32' && (cwd === this.initialCWD || cwd === process.env.WINDIR)) {
|
||||||
|
// shell doesn't truly change its process' CWD
|
||||||
|
cwd = null
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
|
||||||
|
cwd = cwd || this.guessedCWD
|
||||||
|
|
||||||
|
try {
|
||||||
|
await fs.access(cwd)
|
||||||
|
} catch {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
return this.guessedCWD
|
return cwd
|
||||||
}
|
|
||||||
return null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private guessWindowsCWD (data: string) {
|
private guessWindowsCWD (data: string) {
|
||||||
|
@@ -16,7 +16,7 @@ export class TerminalFrontendService {
|
|||||||
private hotkeys: HotkeysService,
|
private hotkeys: HotkeysService,
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
getFrontend (session?: BaseSession): Frontend {
|
getFrontend (session?: BaseSession|null): Frontend {
|
||||||
if (!session) {
|
if (!session) {
|
||||||
const frontend: Frontend = new {
|
const frontend: Frontend = new {
|
||||||
xterm: XTermFrontend,
|
xterm: XTermFrontend,
|
||||||
|
@@ -8,6 +8,8 @@ import { Shell } from '../api/interfaces'
|
|||||||
/** @hidden */
|
/** @hidden */
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class MacOSDefaultShellProvider extends ShellProvider {
|
export class MacOSDefaultShellProvider extends ShellProvider {
|
||||||
|
private cachedShell?: string
|
||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
private hostApp: HostAppService,
|
private hostApp: HostAppService,
|
||||||
) {
|
) {
|
||||||
@@ -18,14 +20,29 @@ export class MacOSDefaultShellProvider extends ShellProvider {
|
|||||||
if (this.hostApp.platform !== Platform.macOS) {
|
if (this.hostApp.platform !== Platform.macOS) {
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
const shellEntry = (await exec(`/usr/bin/dscl . -read /Users/${process.env.LOGNAME} UserShell`))[0].toString()
|
|
||||||
return [{
|
return [{
|
||||||
id: 'default',
|
id: 'default',
|
||||||
name: 'User default',
|
name: 'User default',
|
||||||
command: shellEntry.split(' ')[1].trim(),
|
command: await this.getDefaultShellCached(),
|
||||||
args: ['--login'],
|
args: ['--login'],
|
||||||
hidden: true,
|
hidden: true,
|
||||||
env: {},
|
env: {},
|
||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async getDefaultShellCached () {
|
||||||
|
if (!this.cachedShell) {
|
||||||
|
this.cachedShell = await this.getDefaultShell()
|
||||||
|
} else {
|
||||||
|
this.getDefaultShell().then(shell => {
|
||||||
|
this.cachedShell = shell
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return this.cachedShell!
|
||||||
|
}
|
||||||
|
|
||||||
|
private async getDefaultShell () {
|
||||||
|
const shellEntry = (await exec(`/usr/bin/dscl . -read /Users/${process.env.LOGNAME} UserShell`))[0].toString()
|
||||||
|
return shellEntry.split(' ')[1].trim()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -123,6 +123,13 @@ export class NewTabContextMenu extends TabContextMenuItemProvider {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (tab instanceof TerminalTabComponent && tab.session?.supportsWorkingDirectory()) {
|
||||||
|
items.push({
|
||||||
|
label: 'Copy current path',
|
||||||
|
click: () => this.zone.run(() => tab.copyCurrentPath()),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
return items
|
return items
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -43,7 +43,7 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{ test: /\.pug$/, use: ['apply-loader', 'pug-loader'] },
|
{ test: /\.pug$/, use: ['apply-loader', 'pug-loader'] },
|
||||||
{ test: /\.scss$/, use: ['to-string-loader', 'css-loader', 'sass-loader'] },
|
{ test: /\.scss$/, use: ['@terminus-term/to-string-loader', 'css-loader', 'sass-loader'] },
|
||||||
{ test: /\.css$/, use: ['style-loader', 'css-loader'] },
|
{ test: /\.css$/, use: ['style-loader', 'css-loader'] },
|
||||||
{ test: /\.svg/, use: ['svg-inline-loader'] },
|
{ test: /\.svg/, use: ['svg-inline-loader'] },
|
||||||
{
|
{
|
||||||
@@ -67,6 +67,7 @@ module.exports = {
|
|||||||
'windows-native-registry',
|
'windows-native-registry',
|
||||||
'@terminus-term/node-pty',
|
'@terminus-term/node-pty',
|
||||||
'windows-process-tree',
|
'windows-process-tree',
|
||||||
|
'native-process-working-directory',
|
||||||
'os',
|
'os',
|
||||||
/^rxjs/,
|
/^rxjs/,
|
||||||
/^@angular/,
|
/^@angular/,
|
||||||
|
@@ -111,10 +111,10 @@ exit-on-epipe@~1.0.1:
|
|||||||
resolved "https://registry.yarnpkg.com/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz#0bdd92e87d5285d267daa8171d0eb06159689692"
|
resolved "https://registry.yarnpkg.com/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz#0bdd92e87d5285d267daa8171d0eb06159689692"
|
||||||
integrity sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw==
|
integrity sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw==
|
||||||
|
|
||||||
font-finder@^1.0.3, font-finder@^1.0.4:
|
font-finder@^1.0.3, font-finder@^1.1.0:
|
||||||
version "1.0.4"
|
version "1.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/font-finder/-/font-finder-1.0.4.tgz#2ca944954dd8d0e1b5bdc4c596cc08607761d89b"
|
resolved "https://registry.yarnpkg.com/font-finder/-/font-finder-1.1.0.tgz#2bff2b2762acba720239c8bec898a96daae90858"
|
||||||
integrity sha512-naF16RpjWUTFLqzhmdivYpBCrqySN6PI+a4GPtoEsCdvOpbKYTGeTjO7mxh3Wwjz4xKU+Oqx9kwOcteLDeMFQA==
|
integrity sha512-wpCL2uIbi6GurJbU7ZlQ3nGd61Ho+dSU6U83/xJT5UPFfN35EeCW/rOtS+5k+IuEZu2SYmHzDIPL9eA5tSYRAw==
|
||||||
dependencies:
|
dependencies:
|
||||||
get-system-fonts "^2.0.0"
|
get-system-fonts "^2.0.0"
|
||||||
promise-stream-reader "^1.0.1"
|
promise-stream-reader "^1.0.1"
|
||||||
@@ -337,43 +337,43 @@ tiny-inflate@^1.0.2:
|
|||||||
resolved "https://registry.yarnpkg.com/tiny-inflate/-/tiny-inflate-1.0.3.tgz#122715494913a1805166aaf7c93467933eea26c4"
|
resolved "https://registry.yarnpkg.com/tiny-inflate/-/tiny-inflate-1.0.3.tgz#122715494913a1805166aaf7c93467933eea26c4"
|
||||||
integrity sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==
|
integrity sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==
|
||||||
|
|
||||||
xterm-addon-fit@^0.4.0-beta.8:
|
xterm-addon-fit@^0.5.0:
|
||||||
version "0.4.0"
|
version "0.5.0"
|
||||||
resolved "https://registry.yarnpkg.com/xterm-addon-fit/-/xterm-addon-fit-0.4.0.tgz#06e0c5d0a6aaacfb009ef565efa1c81e93d90193"
|
resolved "https://registry.yarnpkg.com/xterm-addon-fit/-/xterm-addon-fit-0.5.0.tgz#2d51b983b786a97dcd6cde805e700c7f913bc596"
|
||||||
integrity sha512-p4BESuV/g2L6pZzFHpeNLLnep9mp/DkF3qrPglMiucSFtD8iJxtMufEoEJbN8LZwB4i+8PFpFvVuFrGOSpW05w==
|
integrity sha512-DsS9fqhXHacEmsPxBJZvfj2la30Iz9xk+UKjhQgnYNkrUIN5CYLbw7WEfz117c7+S86S/tpHPfvNxJsF5/G8wQ==
|
||||||
|
|
||||||
xterm-addon-ligatures@^0.4.0-beta.5:
|
xterm-addon-ligatures@^0.4.0:
|
||||||
version "0.4.0-beta.7"
|
version "0.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/xterm-addon-ligatures/-/xterm-addon-ligatures-0.4.0-beta.7.tgz#06dfafe0491a2e4744b1a6429958f261820baa00"
|
resolved "https://registry.yarnpkg.com/xterm-addon-ligatures/-/xterm-addon-ligatures-0.4.0.tgz#23235d831988c5780ca1e28002b750ec0b1a78ca"
|
||||||
integrity sha512-GVZKbm7GRgs0LFtdKKmpu0Cs2jfC+sdRtl2E4vWEmhi8WNeW9iINbrsYgdtFPvs1X9OaKxEWqEXJkTcy5rmLHQ==
|
integrity sha512-on+2TgzioEL5Mz60WchsTiuR2SvYzG3xVro39HIpYFM641lpMuPM83Pdm3W/ogkaGrpGm29Ysq2S2LCl/h7rhw==
|
||||||
dependencies:
|
dependencies:
|
||||||
font-finder "^1.0.4"
|
font-finder "^1.1.0"
|
||||||
font-ligatures "^1.3.3"
|
font-ligatures "^1.3.3"
|
||||||
|
|
||||||
xterm-addon-search@^0.7.0-beta.2:
|
xterm-addon-search@^0.8.0:
|
||||||
version "0.7.0"
|
version "0.8.0"
|
||||||
resolved "https://registry.yarnpkg.com/xterm-addon-search/-/xterm-addon-search-0.7.0.tgz#c929d3e5cbb335e82bff72f158ea82936d9cd4ef"
|
resolved "https://registry.yarnpkg.com/xterm-addon-search/-/xterm-addon-search-0.8.0.tgz#e33eab918df7eac7e7baf95dd2b3d14133754881"
|
||||||
integrity sha512-6060evmJJ+tZcjnx33FXaeEHLpuXEa7l9UzUsYfMlCKbu88AbE+5LJocTKCHYd71cwCwb9pjmv/G1o9Rf9Zbcg==
|
integrity sha512-MPJGPVPpHRUw9cLIuqQbrVepmENMOybVUSxIALz5h1ryyQBrVqVujq2hL5aroX5/dZJoHx9lGHQTVLQ07SKgKA==
|
||||||
|
|
||||||
xterm-addon-serialize@^0.3.0:
|
xterm-addon-serialize@^0.4.0:
|
||||||
version "0.3.0"
|
version "0.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/xterm-addon-serialize/-/xterm-addon-serialize-0.3.0.tgz#b4f24089285801bcc5f601791a4cac416d528a6a"
|
resolved "https://registry.yarnpkg.com/xterm-addon-serialize/-/xterm-addon-serialize-0.4.0.tgz#9854fd87afba6157b9016e9c93f0cf9e0efc2de5"
|
||||||
integrity sha512-g+eGqgvQiON4CCEku0iG53obZxi353wig2XRR75DOoHlPMLrO63kvt2V+OahnJlxCpsWQ1BFu4Q5HquQnS6uvQ==
|
integrity sha512-xEdzCNa6ZzFplDlscYTSSUogy1C6y3G3nS68Qbe5zntFAqHOBeyggExQi0E8yZg/no8ewYH0GSKZnOheo/ZoKg==
|
||||||
|
|
||||||
xterm-addon-unicode11@^0.2.0:
|
xterm-addon-unicode11@^0.2.0:
|
||||||
version "0.2.0"
|
version "0.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/xterm-addon-unicode11/-/xterm-addon-unicode11-0.2.0.tgz#9ed0c482b353908bba27778893ca80823382737c"
|
resolved "https://registry.yarnpkg.com/xterm-addon-unicode11/-/xterm-addon-unicode11-0.2.0.tgz#9ed0c482b353908bba27778893ca80823382737c"
|
||||||
integrity sha512-rjFDItPc/IDoSiEnoDFwKroNwLD/7t9vYKENjrcKVZg5tgJuuUj8D4rZtP6iVCjSB1LTLYmUs4L/EmCqIyLR/Q==
|
integrity sha512-rjFDItPc/IDoSiEnoDFwKroNwLD/7t9vYKENjrcKVZg5tgJuuUj8D4rZtP6iVCjSB1LTLYmUs4L/EmCqIyLR/Q==
|
||||||
|
|
||||||
xterm-addon-webgl@^0.8.0:
|
xterm-addon-webgl@^0.9.0:
|
||||||
version "0.8.0"
|
version "0.9.0"
|
||||||
resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.8.0.tgz#4bc6bb4dbfea5b0d2d7978d6c5cef922d584fb4f"
|
resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.9.0.tgz#947ca94f9fd72462155c300dfb82bc471402d60a"
|
||||||
integrity sha512-dlpYPsv0C9S6v6+T/h/d/otSbdUTizMJdxvSoS34tUpMOHev6iW7Zqt5KRFqYxl4vCqpDk9Wmhb3fKL3kwX5fQ==
|
integrity sha512-JSRoe/MgPEKCpr7LbiC+sQUq0c9l/ZhsBXYugKx5BJsJEPsY+5EFcqAexuhsJVe/qV+CP3hsbYDe/411rw3ASA==
|
||||||
|
|
||||||
xterm@^4.9.0-beta.7:
|
xterm@^4.9.0-beta.7:
|
||||||
version "4.9.0"
|
version "4.10.0"
|
||||||
resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.9.0.tgz#7a4c097a433d565339b5533b468bbc60c6c87969"
|
resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.10.0.tgz#fc4f554e3e718aff9b83622e858e64b0953067bb"
|
||||||
integrity sha512-wGfqufmioctKr8VkbRuZbVDfjlXWGZZ1PWHy1yqqpGT3Nm6yaJx8lxDbSEBANtgaiVPTcKSp97sxOy5IlpqYfw==
|
integrity sha512-Wn66I8YpSVkgP3R95GjABC6Eb21pFfnCSnyIqKIIoUI13ohvwd0KGVzUDfyEFfSAzKbPJfrT2+vt7SfUXBZQKQ==
|
||||||
|
|
||||||
yallist@^2.1.2:
|
yallist@^2.1.2:
|
||||||
version "2.1.2"
|
version "2.1.2"
|
||||||
|
@@ -24,6 +24,9 @@
|
|||||||
"es7",
|
"es7",
|
||||||
"es2015",
|
"es2015",
|
||||||
"es2017"
|
"es2017"
|
||||||
]
|
],
|
||||||
|
"paths": {
|
||||||
|
"terminus-*": ["../../terminus-*/src"]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user