mirror of
https://github.com/Eugeny/tabby.git
synced 2025-09-07 09:01:50 +00:00
Compare commits
23 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
329d0448d3 | ||
![]() |
100436f511 | ||
![]() |
22d3e35723 | ||
![]() |
9cdcc8d8e5 | ||
![]() |
168e6f17dc | ||
![]() |
a2c636fdbf | ||
![]() |
413ca70729 | ||
![]() |
6f99e6c14b | ||
![]() |
e65811786d | ||
![]() |
aecd381b25 | ||
![]() |
89465f57d5 | ||
![]() |
3bf0ac43ef | ||
![]() |
a66dd43e1e | ||
![]() |
dd4566cf02 | ||
![]() |
f2be34d137 | ||
![]() |
e28c619bdc | ||
![]() |
04bf5dbcfb | ||
![]() |
a2128ca1f2 | ||
![]() |
bf0d02d1fc | ||
![]() |
792de65696 | ||
![]() |
fab21f6859 | ||
![]() |
b0b01b98be | ||
![]() |
24dff4b5b7 |
@@ -6,7 +6,7 @@
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/Eugeny/terminus/releases/latest">Downloads</a> | <a href="https://t.me/joinchat/AAAAAEZuCv2WKKYcfyQ3QA">Community</a> | <a href="https://ci.appveyor.com/project/Eugeny/terminus/build/artifacts">Latest Windows nightly</a>
|
||||
<a href="https://github.com/Eugeny/terminus/releases/latest">Downloads</a> | <a href="https://t.me/joinchat/HgLqPhRg9Inhmm7WD3H1BQ">Community</a> | <a href="https://ci.appveyor.com/project/Eugeny/terminus/build/artifacts">Latest Windows nightly</a>
|
||||
</p>
|
||||
|
||||
----
|
||||
@@ -19,8 +19,9 @@
|
||||
* Full Unicode support including double-width characters
|
||||
* Doesn't choke on fast-flowing outputs
|
||||
* Proper shell-like experience on Windows including tab completion (via Clink)
|
||||
* PowerShell Core, WSL (Bash on Windows), PowerShell, Git-Bash, Cygwin, Cmder and CMD support
|
||||
* Tab persistence on macOS and Linux
|
||||
* PowerShell (+Core), WSL (Bash on Windows), Git-Bash, Cygwin, Cmder and CMD support
|
||||
* Remembers your tabs
|
||||
* Integrated SSH client and connection manager
|
||||
|
||||
|
||||
[](https://ko-fi.com/eugeny)
|
||||
@@ -38,6 +39,7 @@ Plugins can be installed directly from the Settings view inside Terminus.
|
||||
* [title-control](https://github.com/kbjr/terminus-title-control) - allows modifying the title of the terminal tabs by providing a prefix, suffix, and/or strings to be removed
|
||||
* [scrollbar](https://github.com/kbjr/terminus-scrollbar) - adds a scrollbar to terminal tabs
|
||||
* [quick-cmds](https://github.com/Domain/terminus-quick-cmds) - quickly send commands to one or all terminal tabs
|
||||
* [save-output](https://github.com/Eugeny/terminus-save-output) - record terminal output into a file
|
||||
|
||||
---
|
||||
|
||||
|
@@ -1,4 +1,5 @@
|
||||
import { app, ipcMain, Menu, Tray, shell } from 'electron'
|
||||
import * as electron from 'electron'
|
||||
import { loadConfig } from './config'
|
||||
import { Window, WindowOptions } from './window'
|
||||
|
||||
@@ -18,6 +19,11 @@ export class Application {
|
||||
}
|
||||
|
||||
app.commandLine.appendSwitch('disable-http-cache')
|
||||
app.commandLine.appendSwitch('lang', 'EN')
|
||||
}
|
||||
|
||||
init () {
|
||||
electron.screen.on('display-metrics-changed', () => this.broadcast('host:display-metrics-changed'))
|
||||
}
|
||||
|
||||
async newWindow (options?: WindowOptions): Promise<Window> {
|
||||
|
@@ -12,7 +12,6 @@ if (!process.env.TERMINUS_PLUGINS) {
|
||||
const application = new Application()
|
||||
|
||||
ipcMain.on('app:new-window', () => {
|
||||
console.log('new-window')
|
||||
application.newWindow()
|
||||
})
|
||||
|
||||
@@ -59,5 +58,6 @@ app.on('ready', () => {
|
||||
}
|
||||
]))
|
||||
}
|
||||
application.init()
|
||||
application.newWindow({ hidden: argv.hidden })
|
||||
})
|
||||
|
@@ -11,7 +11,7 @@ let AccentState: any
|
||||
let DwmEnableBlurBehindWindow: any
|
||||
if (process.platform === 'win32') {
|
||||
SetWindowCompositionAttribute = require('windows-swca').SetWindowCompositionAttribute
|
||||
AccentState = require('windows-swca').AccentState
|
||||
AccentState = require('windows-swca').ACCENT_STATE
|
||||
DwmEnableBlurBehindWindow = require('windows-blurbehind').DwmEnableBlurBehindWindow
|
||||
}
|
||||
|
||||
@@ -103,16 +103,14 @@ export class Window {
|
||||
if (process.platform === 'win32') {
|
||||
if (parseFloat(os.release()) >= 10) {
|
||||
let attribValue = AccentState.ACCENT_DISABLED
|
||||
let color = 0x00000000
|
||||
if (enabled) {
|
||||
if (parseInt(os.release().split('.')[2]) >= 17063 && type === 'fluent') {
|
||||
attribValue = AccentState.ACCENT_ENABLE_FLUENT
|
||||
color = 0x01000000 // using a small alpha because acrylic bugs out at full transparency.
|
||||
attribValue = AccentState.ACCENT_ENABLE_ACRYLICBLURBEHIND
|
||||
} else {
|
||||
attribValue = AccentState.ACCENT_ENABLE_BLURBEHIND
|
||||
}
|
||||
}
|
||||
SetWindowCompositionAttribute(this.window, attribValue, color)
|
||||
SetWindowCompositionAttribute(this.window.getNativeWindowHandle(), attribValue, 0x00000000)
|
||||
} else {
|
||||
DwmEnableBlurBehindWindow(this.window, enabled)
|
||||
}
|
||||
@@ -184,28 +182,28 @@ export class Window {
|
||||
})
|
||||
|
||||
ipcMain.on('window-focus', event => {
|
||||
if (event.sender !== this.window.webContents) {
|
||||
if (!this.window || event.sender !== this.window.webContents) {
|
||||
return
|
||||
}
|
||||
this.window.focus()
|
||||
})
|
||||
|
||||
ipcMain.on('window-maximize', event => {
|
||||
if (event.sender !== this.window.webContents) {
|
||||
if (!this.window || event.sender !== this.window.webContents) {
|
||||
return
|
||||
}
|
||||
this.window.maximize()
|
||||
})
|
||||
|
||||
ipcMain.on('window-unmaximize', event => {
|
||||
if (event.sender !== this.window.webContents) {
|
||||
if (!this.window || event.sender !== this.window.webContents) {
|
||||
return
|
||||
}
|
||||
this.window.unmaximize()
|
||||
})
|
||||
|
||||
ipcMain.on('window-toggle-maximize', event => {
|
||||
if (event.sender !== this.window.webContents) {
|
||||
if (!this.window || event.sender !== this.window.webContents) {
|
||||
return
|
||||
}
|
||||
if (this.window.isMaximized()) {
|
||||
@@ -216,42 +214,42 @@ export class Window {
|
||||
})
|
||||
|
||||
ipcMain.on('window-minimize', event => {
|
||||
if (event.sender !== this.window.webContents) {
|
||||
if (!this.window || event.sender !== this.window.webContents) {
|
||||
return
|
||||
}
|
||||
this.window.minimize()
|
||||
})
|
||||
|
||||
ipcMain.on('window-set-bounds', (event, bounds) => {
|
||||
if (event.sender !== this.window.webContents) {
|
||||
if (!this.window || event.sender !== this.window.webContents) {
|
||||
return
|
||||
}
|
||||
this.window.setBounds(bounds)
|
||||
})
|
||||
|
||||
ipcMain.on('window-set-always-on-top', (event, flag) => {
|
||||
if (event.sender !== this.window.webContents) {
|
||||
if (!this.window || event.sender !== this.window.webContents) {
|
||||
return
|
||||
}
|
||||
this.window.setAlwaysOnTop(flag)
|
||||
})
|
||||
|
||||
ipcMain.on('window-set-vibrancy', (event, enabled, type) => {
|
||||
if (event.sender !== this.window.webContents) {
|
||||
if (!this.window || event.sender !== this.window.webContents) {
|
||||
return
|
||||
}
|
||||
this.setVibrancy(enabled, type)
|
||||
})
|
||||
|
||||
ipcMain.on('window-set-title', (event, title) => {
|
||||
if (event.sender !== this.window.webContents) {
|
||||
if (!this.window || event.sender !== this.window.webContents) {
|
||||
return
|
||||
}
|
||||
this.window.setTitle(title)
|
||||
})
|
||||
|
||||
ipcMain.on('window-bring-to-front', event => {
|
||||
if (event.sender !== this.window.webContents) {
|
||||
if (!this.window || event.sender !== this.window.webContents) {
|
||||
return
|
||||
}
|
||||
if (this.window.isMinimized()) {
|
||||
@@ -262,7 +260,7 @@ export class Window {
|
||||
})
|
||||
|
||||
ipcMain.on('window-close', event => {
|
||||
if (event.sender !== this.window.webContents) {
|
||||
if (!this.window || event.sender !== this.window.webContents) {
|
||||
return
|
||||
}
|
||||
this.closing = true
|
||||
|
@@ -36,7 +36,7 @@
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"windows-blurbehind": "^1.0.0",
|
||||
"windows-swca": "^1.1.1"
|
||||
"windows-swca": "^2.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/mz": "0.0.31"
|
||||
|
@@ -16,11 +16,11 @@ function normalizePath (path: string): string {
|
||||
|
||||
nodeRequire.main.paths.map(x => nodeModule.globalPaths.push(normalizePath(x)))
|
||||
|
||||
if (process.env.DEV) {
|
||||
if (process.env.TERMINUS_DEV) {
|
||||
nodeModule.globalPaths.unshift(path.dirname(require('electron').remote.app.getAppPath()))
|
||||
}
|
||||
|
||||
const builtinPluginsPath = process.env.DEV ? path.dirname(require('electron').remote.app.getAppPath()) : path.join((process as any).resourcesPath, 'builtin-plugins')
|
||||
const builtinPluginsPath = process.env.TERMINUS_DEV ? path.dirname(require('electron').remote.app.getAppPath()) : path.join((process as any).resourcesPath, 'builtin-plugins')
|
||||
|
||||
const userPluginsPath = path.join(
|
||||
require('electron').remote.app.getPath('appData'),
|
||||
|
@@ -9,7 +9,6 @@
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"sourceMap": true,
|
||||
"noUnusedParameters": true,
|
||||
"noImplicitReturns": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noUnusedParameters": true,
|
||||
|
@@ -9,7 +9,7 @@ module.exports = {
|
||||
preload: path.resolve(__dirname, 'src/entry.preload.ts'),
|
||||
bundle: path.resolve(__dirname, 'src/entry.ts'),
|
||||
},
|
||||
mode: process.env.DEV ? 'development' : 'production',
|
||||
mode: process.env.TERMINUS_DEV ? 'development' : 'production',
|
||||
optimization:{
|
||||
minimize: false,
|
||||
},
|
||||
|
@@ -7,7 +7,7 @@ module.exports = {
|
||||
entry: {
|
||||
main: path.resolve(__dirname, 'lib/index.ts'),
|
||||
},
|
||||
mode: process.env.DEV ? 'development' : 'production',
|
||||
mode: process.env.TERMINUS_DEV ? 'development' : 'production',
|
||||
context: __dirname,
|
||||
devtool: 'source-map',
|
||||
output: {
|
||||
|
@@ -70,6 +70,11 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.13.tgz#530f0f9254209b0335bf5cc6387822594ef47093"
|
||||
integrity sha512-Y3EAG7VA7NVNbZek/fjJtILnmTk/ZfpJuWZGDBqDZ1dVIxgJJJ82fXPW7pKnqyV9CD/9bcPOCi7eErUqGMHOrA==
|
||||
|
||||
"@types/node@^10.12.18":
|
||||
version "10.12.18"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-10.12.18.tgz#1d3ca764718915584fcd9f6344621b7672665c67"
|
||||
integrity sha512-fh+pAqt4xRzPfqA6eh3Z2y6fyZavRIumvjhaCL753+TVkGKGhpPeyrJG2JftD0T9q4GF00KjefsQ+PQNDdWQaQ==
|
||||
|
||||
accessibility-developer-tools@^2.11.0:
|
||||
version "2.12.0"
|
||||
resolved "https://registry.yarnpkg.com/accessibility-developer-tools/-/accessibility-developer-tools-2.12.0.tgz#3da0cce9d6ec6373964b84f35db7cfc3df7ab514"
|
||||
@@ -620,10 +625,12 @@ windows-blurbehind@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/windows-blurbehind/-/windows-blurbehind-1.0.0.tgz#050efb988704c44335bdc3efefd757f6e463b8ac"
|
||||
integrity sha512-lO+A7fhTHO7oy9zJM3o1AdzfSQrmtPkdwvleeuww840ghijjEA1f1Zp8bKA3mJu2DFNtVT40fwmqtgsCGat4UA==
|
||||
|
||||
windows-swca@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/windows-swca/-/windows-swca-1.1.1.tgz#0b3530278c67d408baac71c3a6aeb16d55318bf8"
|
||||
integrity sha512-hKmHrNYJD72Kg0u35fjkiFIuMKuC+Tztmf3Obnf4aTkNjstEpbSEspEeSo3ZNixaVCETA1dLbDkVUQVF1QxtWA==
|
||||
windows-swca@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/windows-swca/-/windows-swca-2.0.1.tgz#25d78ce25251292061494a0ad07c02282b28b4e3"
|
||||
integrity sha512-flj+HD6RUemZUvKKguLLnMUOYkQSgDu9qrhUIO4cydvtb/x+sxU8XmpZUtugYuydcdikB9zsCOMgKnAqIQ+7nw==
|
||||
dependencies:
|
||||
"@types/node" "^10.12.18"
|
||||
|
||||
wrap-ansi@^2.0.0:
|
||||
version "2.1.0"
|
||||
|
@@ -127,9 +127,9 @@
|
||||
},
|
||||
"scripts": {
|
||||
"build": "webpack --color --config app/webpack.main.config.js && webpack --color --config app/webpack.config.js && webpack --color --config terminus-core/webpack.config.js && webpack --color --config terminus-settings/webpack.config.js && webpack --color --config terminus-terminal/webpack.config.js && webpack --color --config terminus-settings/webpack.config.js && webpack --color --config terminus-plugin-manager/webpack.config.js && webpack --color --config terminus-community-color-schemes/webpack.config.js && webpack --color --config terminus-ssh/webpack.config.js",
|
||||
"watch": "cross-env DEV=1 webpack --progress --color --watch",
|
||||
"start": "cross-env DEV=1 electron app --debug",
|
||||
"prod": "cross-env DEV=1 electron app",
|
||||
"watch": "cross-env TERMINUS_DEV=1 webpack --progress --color --watch",
|
||||
"start": "cross-env TERMINUS_DEV=1 electron app --debug",
|
||||
"prod": "cross-env TERMINUS_DEV=1 electron app",
|
||||
"lint": "tslint -c tslint.json -t stylish terminus-*/src/**/*.ts terminus-*/src/*.ts app/src/*.ts",
|
||||
"postinstall": "node ./scripts/install-deps.js"
|
||||
},
|
||||
|
@@ -13,7 +13,7 @@ module.exports = {
|
||||
libraryTarget: 'umd',
|
||||
devtoolModuleFilenameTemplate: 'webpack-terminus-community-color-schemes:///[resource-path]',
|
||||
},
|
||||
mode: process.env.DEV ? 'development' : 'production',
|
||||
mode: process.env.TERMINUS_DEV ? 'development' : 'production',
|
||||
optimization:{
|
||||
minimize: false,
|
||||
},
|
||||
|
@@ -9,7 +9,6 @@ import { HotkeysService } from '../services/hotkeys.service'
|
||||
import { Logger, LogService } from '../services/log.service'
|
||||
import { ConfigService } from '../services/config.service'
|
||||
import { DockingService } from '../services/docking.service'
|
||||
import { TabRecoveryService } from '../services/tabRecovery.service'
|
||||
import { ThemesService } from '../services/themes.service'
|
||||
import { UpdaterService } from '../services/updater.service'
|
||||
import { TouchbarService } from '../services/touchbar.service'
|
||||
@@ -69,7 +68,6 @@ export class AppRootComponent {
|
||||
constructor (
|
||||
private docking: DockingService,
|
||||
private electron: ElectronService,
|
||||
private tabRecovery: TabRecoveryService,
|
||||
private hotkeys: HotkeysService,
|
||||
private updater: UpdaterService,
|
||||
private touchbar: TouchbarService,
|
||||
@@ -199,9 +197,7 @@ export class AppRootComponent {
|
||||
}
|
||||
|
||||
async ngOnInit () {
|
||||
await this.tabRecovery.recoverTabs()
|
||||
this.ready = true
|
||||
this.tabRecovery.saveTabs(this.app.tabs)
|
||||
|
||||
this.app.emitReady()
|
||||
}
|
||||
|
@@ -20,6 +20,10 @@
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
|
||||
.off {
|
||||
color: rgba(0, 0, 0, .5);
|
||||
}
|
||||
|
||||
.icon {
|
||||
position: relative;
|
||||
flex: none;
|
||||
|
@@ -5,6 +5,7 @@ import { BaseTabComponent } from '../components/baseTab.component'
|
||||
import { Logger, LogService } from './log.service'
|
||||
import { ConfigService } from './config.service'
|
||||
import { HostAppService } from './hostApp.service'
|
||||
import { TabRecoveryService } from './tabRecovery.service'
|
||||
|
||||
export declare type TabComponentType = new (...args: any[]) => BaseTabComponent
|
||||
|
||||
@@ -61,11 +62,25 @@ export class AppService {
|
||||
private config: ConfigService,
|
||||
private hostApp: HostAppService,
|
||||
private injector: Injector,
|
||||
private tabRecovery: TabRecoveryService,
|
||||
log: LogService,
|
||||
) {
|
||||
this.logger = log.create('app')
|
||||
|
||||
this.hostApp.windowCloseRequest$.subscribe(() => this.closeWindow())
|
||||
|
||||
this.tabRecovery.recoverTabs().then(tabs => {
|
||||
for (let tab of tabs) {
|
||||
this.openNewTab(tab.type, tab.options)
|
||||
}
|
||||
|
||||
this.tabsChanged$.subscribe(() => {
|
||||
tabRecovery.saveTabs(this.tabs)
|
||||
})
|
||||
setInterval(() => {
|
||||
tabRecovery.saveTabs(this.tabs)
|
||||
}, 30000)
|
||||
})
|
||||
}
|
||||
|
||||
openNewTab (type: TabComponentType, inputs?: any): BaseTabComponent {
|
||||
@@ -105,7 +120,9 @@ export class AppService {
|
||||
this.activeTab = tab
|
||||
this.activeTabChange.next(tab)
|
||||
if (this.activeTab) {
|
||||
this.activeTab.emitFocused()
|
||||
setImmediate(() => {
|
||||
this.activeTab.emitFocused()
|
||||
})
|
||||
this.hostApp.setTitle(this.activeTab.title)
|
||||
}
|
||||
}
|
||||
@@ -160,6 +177,17 @@ export class AppService {
|
||||
this.tabClosed.next(tab)
|
||||
}
|
||||
|
||||
async duplicateTab (tab: BaseTabComponent) {
|
||||
let token = await tab.getRecoveryToken()
|
||||
if (!token) {
|
||||
return
|
||||
}
|
||||
let recoveredTab = await this.tabRecovery.recoverTab(token)
|
||||
if (recoveredTab) {
|
||||
this.openNewTab(recoveredTab.type, recoveredTab.options)
|
||||
}
|
||||
}
|
||||
|
||||
async closeWindow () {
|
||||
for (let tab of this.tabs) {
|
||||
if (!await tab.canClose()) {
|
||||
|
@@ -31,6 +31,7 @@ export class HostAppService {
|
||||
private configChangeBroadcast = new Subject<void>()
|
||||
private windowCloseRequest = new Subject<void>()
|
||||
private windowMoved = new Subject<void>()
|
||||
private displayMetricsChanged = new Subject<void>()
|
||||
private logger: Logger
|
||||
private windowId: number
|
||||
|
||||
@@ -43,6 +44,7 @@ export class HostAppService {
|
||||
get configChangeBroadcast$ (): Observable<void> { return this.configChangeBroadcast }
|
||||
get windowCloseRequest$ (): Observable<void> { return this.windowCloseRequest }
|
||||
get windowMoved$ (): Observable<void> { return this.windowMoved }
|
||||
get displayMetricsChanged$ (): Observable<void> { return this.displayMetricsChanged }
|
||||
|
||||
constructor (
|
||||
private zone: NgZone,
|
||||
@@ -86,6 +88,10 @@ export class HostAppService {
|
||||
this.zone.run(() => this.windowMoved.next())
|
||||
})
|
||||
|
||||
electron.ipcRenderer.on('host:display-metrics-changed', () => {
|
||||
this.zone.run(() => this.displayMetricsChanged.next())
|
||||
})
|
||||
|
||||
electron.ipcRenderer.on('host:second-instance', (_$event, argv: any, cwd: string) => this.zone.run(() => {
|
||||
this.logger.info('Second instance', argv)
|
||||
const op = argv._[0]
|
||||
|
@@ -23,7 +23,7 @@ const initializeWinston = (electron: ElectronService) => {
|
||||
colorize: false
|
||||
}),
|
||||
new winston.transports.Console({
|
||||
level: 'info',
|
||||
level: 'debug',
|
||||
handleExceptions: false,
|
||||
json: false,
|
||||
colorize: true
|
||||
|
@@ -2,7 +2,6 @@ import { Injectable, Inject } from '@angular/core'
|
||||
import { TabRecoveryProvider, RecoveredTab } from '../api/tabRecovery'
|
||||
import { BaseTabComponent } from '../components/baseTab.component'
|
||||
import { Logger, LogService } from '../services/log.service'
|
||||
import { AppService } from '../services/app.service'
|
||||
import { ConfigService } from '../services/config.service'
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
@@ -11,17 +10,10 @@ export class TabRecoveryService {
|
||||
|
||||
constructor (
|
||||
@Inject(TabRecoveryProvider) private tabRecoveryProviders: TabRecoveryProvider[],
|
||||
private app: AppService,
|
||||
private config: ConfigService,
|
||||
log: LogService
|
||||
) {
|
||||
this.logger = log.create('tabRecovery')
|
||||
app.tabsChanged$.subscribe(() => {
|
||||
this.saveTabs(app.tabs)
|
||||
})
|
||||
setInterval(() => {
|
||||
this.saveTabs(app.tabs)
|
||||
}, 30000)
|
||||
}
|
||||
|
||||
async saveTabs (tabs: BaseTabComponent[]) {
|
||||
@@ -34,25 +26,32 @@ export class TabRecoveryService {
|
||||
)
|
||||
}
|
||||
|
||||
async recoverTabs (): Promise<void> {
|
||||
async recoverTab (token: any): Promise<RecoveredTab> {
|
||||
for (let provider of this.config.enabledServices(this.tabRecoveryProviders)) {
|
||||
try {
|
||||
let tab = await provider.recover(token)
|
||||
if (tab) {
|
||||
return tab
|
||||
}
|
||||
} catch (error) {
|
||||
this.logger.warn('Tab recovery crashed:', token, provider, error)
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
async recoverTabs (): Promise<RecoveredTab[]> {
|
||||
if (window.localStorage.tabsRecovery) {
|
||||
let tabs: RecoveredTab[] = []
|
||||
for (let token of JSON.parse(window.localStorage.tabsRecovery)) {
|
||||
for (let provider of this.config.enabledServices(this.tabRecoveryProviders)) {
|
||||
try {
|
||||
let tab = await provider.recover(token)
|
||||
if (tab) {
|
||||
tabs.push(tab)
|
||||
}
|
||||
} catch (error) {
|
||||
this.logger.warn('Tab recovery crashed:', token, provider, error)
|
||||
}
|
||||
let tab = await this.recoverTab(token)
|
||||
if (tab) {
|
||||
tabs.push(tab)
|
||||
}
|
||||
}
|
||||
tabs.forEach(tab => {
|
||||
this.app.openNewTab(tab.type, tab.options)
|
||||
})
|
||||
return tabs
|
||||
}
|
||||
return []
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -67,6 +67,7 @@ export class CommonOptionsContextMenu extends TabContextMenuItemProvider {
|
||||
|
||||
constructor (
|
||||
private zone: NgZone,
|
||||
private app: AppService,
|
||||
) {
|
||||
super()
|
||||
}
|
||||
@@ -77,6 +78,10 @@ export class CommonOptionsContextMenu extends TabContextMenuItemProvider {
|
||||
label: 'Rename',
|
||||
click: () => this.zone.run(() => tabHeader.showRenameTabModal())
|
||||
},
|
||||
{
|
||||
label: 'Duplicate',
|
||||
click: () => this.zone.run(() => this.app.duplicateTab(tab))
|
||||
},
|
||||
{
|
||||
label: 'Color',
|
||||
sublabel: COLORS.find(x => x.value === tab.color).name,
|
||||
|
@@ -14,7 +14,7 @@ module.exports = {
|
||||
libraryTarget: 'umd',
|
||||
devtoolModuleFilenameTemplate: 'webpack-terminus-core:///[resource-path]',
|
||||
},
|
||||
mode: process.env.DEV ? 'development' : 'production',
|
||||
mode: process.env.TERMINUS_DEV ? 'development' : 'production',
|
||||
optimization:{
|
||||
minimize: false,
|
||||
},
|
||||
|
@@ -65,7 +65,7 @@ div(*ngIf='npmInstalled')
|
||||
.input-group.mb-3
|
||||
.input-group-prepend
|
||||
.input-group-text
|
||||
i.fas.fa-fw.fa-circle-o-notch.fa-spin(*ngIf='!availablePluginsReady')
|
||||
i.fas.fa-fw.fa-circle-notch.fa-spin(*ngIf='!availablePluginsReady')
|
||||
i.fas.fa-fw.fa-search(*ngIf='availablePluginsReady')
|
||||
input.form-control(
|
||||
type='text',
|
||||
|
@@ -13,7 +13,7 @@ module.exports = {
|
||||
libraryTarget: 'umd',
|
||||
devtoolModuleFilenameTemplate: 'webpack-terminus-plugin-manager:///[resource-path]',
|
||||
},
|
||||
mode: process.env.DEV ? 'development' : 'production',
|
||||
mode: process.env.TERMINUS_DEV ? 'development' : 'production',
|
||||
optimization:{
|
||||
minimize: false,
|
||||
},
|
||||
|
@@ -14,7 +14,7 @@ module.exports = {
|
||||
libraryTarget: 'umd',
|
||||
devtoolModuleFilenameTemplate: 'webpack-terminus-settings:///[resource-path]',
|
||||
},
|
||||
mode: process.env.DEV ? 'development' : 'production',
|
||||
mode: process.env.TERMINUS_DEV ? 'development' : 'production',
|
||||
optimization:{
|
||||
minimize: false,
|
||||
},
|
||||
|
@@ -36,10 +36,11 @@
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"wincredmgr": "^2.0.0",
|
||||
"xkeychain": "^0.0.6",
|
||||
"windows-process-tree": "^0.2.3"
|
||||
"windows-process-tree": "^0.2.3",
|
||||
"xkeychain": "^0.0.6"
|
||||
},
|
||||
"dependencies": {
|
||||
"ssh2": "^0.5.5"
|
||||
"ssh2": "^0.8.2",
|
||||
"ssh2-streams": "^0.4.2"
|
||||
}
|
||||
}
|
||||
|
@@ -7,6 +7,13 @@ export interface LoginScript {
|
||||
optional?: boolean
|
||||
}
|
||||
|
||||
export enum SSHAlgorithmType {
|
||||
HMAC = 'hmac',
|
||||
KEX = 'kex',
|
||||
CIPHER = 'cipher',
|
||||
HOSTKEY = 'serverHostKey'
|
||||
}
|
||||
|
||||
export interface SSHConnection {
|
||||
name?: string
|
||||
host: string
|
||||
@@ -19,6 +26,8 @@ export interface SSHConnection {
|
||||
keepaliveInterval?: number
|
||||
keepaliveCountMax?: number
|
||||
readyTimeout?: number
|
||||
|
||||
algorithms?: {[t: string]: string[]}
|
||||
}
|
||||
|
||||
export class SSHSession extends BaseSession {
|
||||
|
@@ -85,6 +85,27 @@
|
||||
placeholder='20000',
|
||||
[(ngModel)]='connection.readyTimeout',
|
||||
)
|
||||
|
||||
.form-group
|
||||
label Ciphers
|
||||
div(*ngFor='let alg of supportedAlgorithms.cipher')
|
||||
checkbox([text]='alg', [(ngModel)]='algorithms.cipher[alg]')
|
||||
|
||||
.form-group
|
||||
label Key exchange
|
||||
div(*ngFor='let alg of supportedAlgorithms.kex')
|
||||
checkbox([text]='alg', [(ngModel)]='algorithms.kex[alg]')
|
||||
|
||||
.form-group
|
||||
label HMAC
|
||||
div(*ngFor='let alg of supportedAlgorithms.hmac')
|
||||
checkbox([text]='alg', [(ngModel)]='algorithms.hmac[alg]')
|
||||
|
||||
.form-group
|
||||
label Host key
|
||||
div(*ngFor='let alg of supportedAlgorithms.serverHostKey')
|
||||
checkbox([text]='alg', [(ngModel)]='algorithms.serverHostKey[alg]')
|
||||
|
||||
|
||||
ngb-tab(id='scripts')
|
||||
ng-template(ngbTabTitle)
|
||||
|
@@ -2,7 +2,8 @@ import { Component } from '@angular/core'
|
||||
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
|
||||
import { ElectronService, HostAppService } from 'terminus-core'
|
||||
import { PasswordStorageService } from '../services/passwordStorage.service'
|
||||
import { SSHConnection, LoginScript } from '../api'
|
||||
import { SSHConnection, LoginScript, SSHAlgorithmType } from '../api'
|
||||
import { ALGORITHMS } from 'ssh2-streams/lib/constants'
|
||||
|
||||
@Component({
|
||||
template: require('./editConnectionModal.component.pug'),
|
||||
@@ -12,6 +13,10 @@ export class EditConnectionModalComponent {
|
||||
newScript: LoginScript
|
||||
hasSavedPassword: boolean
|
||||
|
||||
supportedAlgorithms: {[id: string]: string[]} = {}
|
||||
defaultAlgorithms: {[id: string]: string[]} = {}
|
||||
algorithms: {[id: string]: {[a: string]: boolean}} = {}
|
||||
|
||||
constructor (
|
||||
private modalInstance: NgbActiveModal,
|
||||
private electron: ElectronService,
|
||||
@@ -19,10 +24,41 @@ export class EditConnectionModalComponent {
|
||||
private passwordStorage: PasswordStorageService,
|
||||
) {
|
||||
this.newScript = { expect: '', send: '' }
|
||||
|
||||
for (let k of Object.values(SSHAlgorithmType)) {
|
||||
this.supportedAlgorithms[k] = ALGORITHMS[
|
||||
{
|
||||
[SSHAlgorithmType.KEX]: 'SUPPORTED_KEX',
|
||||
[SSHAlgorithmType.HOSTKEY]: 'SUPPORTED_SERVER_HOST_KEY',
|
||||
[SSHAlgorithmType.CIPHER]: 'SUPPORTED_CIPHER',
|
||||
[SSHAlgorithmType.HMAC]: 'SUPPORTED_HMAC',
|
||||
}[k]
|
||||
]
|
||||
this.defaultAlgorithms[k] = ALGORITHMS[
|
||||
{
|
||||
[SSHAlgorithmType.KEX]: 'KEX',
|
||||
[SSHAlgorithmType.HOSTKEY]: 'SERVER_HOST_KEY',
|
||||
[SSHAlgorithmType.CIPHER]: 'CIPHER',
|
||||
[SSHAlgorithmType.HMAC]: 'HMAC',
|
||||
}[k]
|
||||
]
|
||||
}
|
||||
console.log(this)
|
||||
}
|
||||
|
||||
async ngOnInit () {
|
||||
this.hasSavedPassword = !!(await this.passwordStorage.loadPassword(this.connection))
|
||||
this.connection.algorithms = this.connection.algorithms || {}
|
||||
for (let k of Object.values(SSHAlgorithmType)) {
|
||||
if (!this.connection.algorithms[k]) {
|
||||
this.connection.algorithms[k] = this.defaultAlgorithms[k]
|
||||
}
|
||||
|
||||
this.algorithms[k] = {}
|
||||
for (let alg of this.connection.algorithms[k]) {
|
||||
this.algorithms[k][alg] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
clearSavedPassword () {
|
||||
@@ -43,6 +79,11 @@ export class EditConnectionModalComponent {
|
||||
}
|
||||
|
||||
save () {
|
||||
for (let k of Object.values(SSHAlgorithmType)) {
|
||||
this.connection.algorithms[k] = Object.entries(this.algorithms[k])
|
||||
.filter(([k, v]) => !!v)
|
||||
.map(([k, v]) => k)
|
||||
}
|
||||
this.modalInstance.close(this.connection)
|
||||
}
|
||||
|
||||
|
@@ -26,6 +26,10 @@ export class SSHTabComponent extends BaseTerminalTabComponent {
|
||||
})
|
||||
|
||||
super.ngOnInit()
|
||||
|
||||
setImmediate(() => {
|
||||
this.setTitle(this.connection.name)
|
||||
})
|
||||
}
|
||||
|
||||
async initializeSession () {
|
||||
|
@@ -164,6 +164,7 @@ export class SSHService {
|
||||
return true
|
||||
},
|
||||
hostHash: 'sha256' as any,
|
||||
algorithms: session.connection.algorithms,
|
||||
})
|
||||
} catch (e) {
|
||||
this.toastr.error(e.message)
|
||||
|
@@ -12,7 +12,7 @@ module.exports = {
|
||||
libraryTarget: 'umd',
|
||||
devtoolModuleFilenameTemplate: 'webpack-terminus-ssh:///[resource-path]',
|
||||
},
|
||||
mode: process.env.DEV ? 'development' : 'production',
|
||||
mode: process.env.TERMINUS_DEV ? 'development' : 'production',
|
||||
optimization:{
|
||||
minimize: false,
|
||||
},
|
||||
@@ -44,6 +44,7 @@ module.exports = {
|
||||
externals: [
|
||||
'fs',
|
||||
'node-ssh',
|
||||
'ssh2-streams',
|
||||
'xkeychain',
|
||||
'wincredmgr',
|
||||
'path',
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -15,7 +15,7 @@ export class ButtonProvider extends ToolbarButtonProvider {
|
||||
hotkeys: HotkeysService,
|
||||
) {
|
||||
super()
|
||||
if (!electron.remote.process.env.DEV) {
|
||||
if (!electron.remote.process.env.TERMINUS_DEV) {
|
||||
setImmediate(async () => {
|
||||
let argv: string[] = electron.remote.process.argv
|
||||
for (let arg of argv.slice(1).concat([electron.remote.process.argv0])) {
|
||||
|
@@ -1,6 +1,6 @@
|
||||
h3.mb-3 Appearance
|
||||
.row
|
||||
.col-md-6
|
||||
.d-flex
|
||||
.mr-5
|
||||
.form-line
|
||||
.header
|
||||
.title Frontend
|
||||
@@ -26,6 +26,7 @@ h3.mb-3 Appearance
|
||||
)
|
||||
input.form-control.w-25(
|
||||
type='number',
|
||||
max='48',
|
||||
[(ngModel)]='config.store.terminal.fontSize',
|
||||
(ngModelChange)='config.save()',
|
||||
)
|
||||
@@ -91,7 +92,7 @@ h3.mb-3 Appearance
|
||||
[title]='idx',
|
||||
)
|
||||
|
||||
.col-md-6
|
||||
div
|
||||
.form-group
|
||||
.appearance-preview(
|
||||
[style.font-family]='config.store.terminal.font',
|
||||
|
@@ -3,6 +3,9 @@
|
||||
margin-left: 20px;
|
||||
padding: 10px;
|
||||
overflow: hidden;
|
||||
max-width: 400px;
|
||||
max-height: 400px;
|
||||
|
||||
span {
|
||||
white-space: pre;
|
||||
}
|
||||
|
@@ -24,6 +24,7 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
|
||||
@Input() zoom = 0
|
||||
@ViewChild('content') content
|
||||
@HostBinding('style.background-color') backgroundColor: string
|
||||
@HostBinding('class.top-padded') topPadded: boolean
|
||||
frontend: Frontend
|
||||
sessionCloseSubscription: Subscription
|
||||
hotkeysSubscription: Subscription
|
||||
@@ -145,7 +146,15 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
|
||||
})
|
||||
|
||||
this.frontend.configure()
|
||||
this.frontend.attach(this.content.nativeElement)
|
||||
|
||||
if (this.hasFocus) {
|
||||
this.frontend.attach(this.content.nativeElement)
|
||||
} else {
|
||||
this.focused$.pipe(first()).subscribe(() => {
|
||||
this.frontend.attach(this.content.nativeElement)
|
||||
})
|
||||
}
|
||||
|
||||
this.attachTermContainerHandlers()
|
||||
|
||||
this.configure()
|
||||
@@ -244,7 +253,7 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
|
||||
}),
|
||||
|
||||
this.frontend.resize$.subscribe(({ columns, rows }) => {
|
||||
this.logger.info(`Resizing to ${columns}x${rows}`)
|
||||
this.logger.debug(`Resizing to ${columns}x${rows}`)
|
||||
this.size = { columns, rows }
|
||||
this.zone.run(() => {
|
||||
if (this.session && this.session.open) {
|
||||
@@ -256,6 +265,10 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
|
||||
this.hostApp.windowMoved$.subscribe(() => setTimeout(() => {
|
||||
this.configure()
|
||||
}, 250)),
|
||||
|
||||
this.hostApp.displayMetricsChanged$.subscribe(() => setTimeout(() => {
|
||||
this.configure()
|
||||
}, 250)),
|
||||
]
|
||||
}
|
||||
|
||||
@@ -296,6 +309,10 @@ export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit
|
||||
configure (): void {
|
||||
this.frontend.configure()
|
||||
|
||||
this.topPadded = this.hostApp.platform === Platform.macOS
|
||||
&& this.config.store.appearance.frame === 'thin'
|
||||
&& this.config.store.appearance.tabsLocation === 'bottom'
|
||||
|
||||
if (this.config.store.terminal.background === 'colorScheme') {
|
||||
if (this.config.store.terminal.colorScheme.background) {
|
||||
this.backgroundColor = this.config.store.terminal.colorScheme.background
|
||||
|
@@ -25,6 +25,9 @@ h3.mb-3 Shell
|
||||
(ngModelChange)='config.save()'
|
||||
)
|
||||
|
||||
.alert.alert-info.d-flex.align-items-center(*ngIf='config.store.terminal.useConPTY && isConPTYAvailable && !isConPTYStable')
|
||||
.mr-auto Windows 10 build 18309 or above is recommended for ConPTY
|
||||
|
||||
.alert.alert-info.d-flex.align-items-center(*ngIf='config.store.terminal.shell.startsWith("wsl") && (config.store.terminal.frontend != "hterm" || !config.store.terminal.useConPTY)')
|
||||
.mr-auto WSL terminal only supports TrueColor with ConPTY and the hterm frontend
|
||||
|
||||
|
@@ -1,3 +1,4 @@
|
||||
import * as os from 'os'
|
||||
import { Component } from '@angular/core'
|
||||
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
|
||||
import { Subscription } from 'rxjs'
|
||||
@@ -15,6 +16,7 @@ export class ShellSettingsTabComponent {
|
||||
profiles: Profile[] = []
|
||||
Platform = Platform
|
||||
isConPTYAvailable: boolean
|
||||
isConPTYStable: boolean
|
||||
private configSubscription: Subscription
|
||||
|
||||
constructor (
|
||||
@@ -31,6 +33,9 @@ export class ShellSettingsTabComponent {
|
||||
})
|
||||
this.reload()
|
||||
this.isConPTYAvailable = uac.isAvailable
|
||||
this.isConPTYStable = hostApp.platform === Platform.Windows
|
||||
&& parseFloat(os.release()) >= 10
|
||||
&& parseInt(os.release().split('.')[2]) >= 18309
|
||||
}
|
||||
|
||||
async ngOnInit () {
|
||||
|
@@ -3,6 +3,10 @@
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
|
||||
&.top-padded {
|
||||
padding-top: 20px;
|
||||
}
|
||||
|
||||
&> .content {
|
||||
flex: auto;
|
||||
position: relative;
|
||||
|
@@ -8,7 +8,7 @@ export class TerminalConfigProvider extends ConfigProvider {
|
||||
},
|
||||
},
|
||||
terminal: {
|
||||
frontend: 'hterm',
|
||||
frontend: 'xterm',
|
||||
autoOpen: false,
|
||||
fontSize: 14,
|
||||
linePadding: 0,
|
||||
|
@@ -54,6 +54,14 @@ export class XTermFrontend extends Frontend {
|
||||
|
||||
this.xtermCore._scrollToBottom = this.xtermCore.scrollToBottom.bind(this.xtermCore)
|
||||
this.xtermCore.scrollToBottom = () => null
|
||||
|
||||
this.resizeHandler = () => {
|
||||
try {
|
||||
(this.xterm as any).fit()
|
||||
} catch {
|
||||
// tends to throw when element wasn't shown yet
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
attach (host: HTMLElement): void {
|
||||
@@ -61,7 +69,6 @@ export class XTermFrontend extends Frontend {
|
||||
this.ready.next(null)
|
||||
this.ready.complete()
|
||||
|
||||
this.resizeHandler = () => (this.xterm as any).fit()
|
||||
window.addEventListener('resize', this.resizeHandler)
|
||||
|
||||
this.resizeHandler()
|
||||
|
@@ -118,7 +118,7 @@ export class Session extends BaseSession {
|
||||
rows: options.height || 30,
|
||||
cwd,
|
||||
env: env,
|
||||
experimentalUseConpty: this.config.store.terminal.useConPTY,
|
||||
experimentalUseConpty: this.config.store.terminal.useConPTY && 1,
|
||||
})
|
||||
|
||||
this.guessedCWD = cwd
|
||||
|
@@ -25,7 +25,7 @@ export class UACService {
|
||||
'UAC.exe',
|
||||
)
|
||||
|
||||
if (process.env.DEV) {
|
||||
if (process.env.TERMINUS_DEV) {
|
||||
helperPath = path.join(
|
||||
path.dirname(this.electron.app.getPath('exe')),
|
||||
'..', '..', '..',
|
||||
|
@@ -13,7 +13,7 @@ module.exports = {
|
||||
libraryTarget: 'umd',
|
||||
devtoolModuleFilenameTemplate: 'webpack-terminus-terminal:///[resource-path]',
|
||||
},
|
||||
mode: process.env.DEV ? 'development' : 'production',
|
||||
mode: process.env.TERMINUS_DEV ? 'development' : 'production',
|
||||
optimization: {
|
||||
minimize: false,
|
||||
},
|
||||
|
@@ -15,9 +15,9 @@
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/node@*":
|
||||
version "10.12.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-10.12.0.tgz#ea6dcbddbc5b584c83f06c60e82736d8fbb0c235"
|
||||
integrity sha512-3TUHC3jsBAB7qVRGxT6lWyYo2v96BMmD2PTcl47H25Lu7UXtFH/2qqmKiVrnel6Ne//0TFYf6uvNX+HW2FRkLQ==
|
||||
version "10.12.19"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-10.12.19.tgz#ca1018c26be01f07e66ac7fefbeb6407e4490c61"
|
||||
integrity sha512-2NVovndCjJQj6fUUn9jCgpP4WSqr+u1SoUZMZyJkhGeBFsm6dE46l31S7lPUYt9uQ28XI+ibrJA1f5XyH5HNtA==
|
||||
|
||||
"@types/node@7.0.12":
|
||||
version "7.0.12"
|
||||
@@ -34,10 +34,10 @@ any-promise@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f"
|
||||
integrity sha1-q8av7tzqUugJzcA3au0845Y10X8=
|
||||
|
||||
big.js@^3.1.3:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/big.js/-/big.js-3.2.0.tgz#a5fc298b81b9e0dca2e458824784b65c52ba588e"
|
||||
integrity sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==
|
||||
big.js@^5.2.2:
|
||||
version "5.2.2"
|
||||
resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328"
|
||||
integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==
|
||||
|
||||
connected-domain@^1.0.0:
|
||||
version "1.0.0"
|
||||
@@ -100,24 +100,26 @@ hterm-umdjs@1.4.1:
|
||||
resolved "https://registry.yarnpkg.com/hterm-umdjs/-/hterm-umdjs-1.4.1.tgz#0cd5352eaf927c70b83c36146cf2c2a281dba957"
|
||||
integrity sha512-r5JOmdDK1bZCmp3cKcuGRLVeum33H+pzD119ZxmQou+QUVe6SAVSz03HvKWVhM2Ao1Biv+fkhFDmnsaRPq0tFg==
|
||||
|
||||
json5@^0.5.0:
|
||||
version "0.5.1"
|
||||
resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821"
|
||||
integrity sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=
|
||||
json5@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe"
|
||||
integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==
|
||||
dependencies:
|
||||
minimist "^1.2.0"
|
||||
|
||||
loader-utils@^1.0.2:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.1.0.tgz#c98aef488bcceda2ffb5e2de646d6a754429f5cd"
|
||||
integrity sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=
|
||||
version "1.2.3"
|
||||
resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.2.3.tgz#1ff5dc6911c9f0a062531a4c04b609406108c2c7"
|
||||
integrity sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA==
|
||||
dependencies:
|
||||
big.js "^3.1.3"
|
||||
big.js "^5.2.2"
|
||||
emojis-list "^2.0.0"
|
||||
json5 "^0.5.0"
|
||||
json5 "^1.0.1"
|
||||
|
||||
lru-cache@^4.1.3:
|
||||
version "4.1.3"
|
||||
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.3.tgz#a1175cf3496dfc8436c156c334b4955992bce69c"
|
||||
integrity sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA==
|
||||
version "4.1.5"
|
||||
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd"
|
||||
integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==
|
||||
dependencies:
|
||||
pseudomap "^1.0.2"
|
||||
yallist "^2.1.2"
|
||||
@@ -129,6 +131,11 @@ macos-native-processlist@^1.0.0:
|
||||
dependencies:
|
||||
nan "^2.10.0"
|
||||
|
||||
minimist@^1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
|
||||
integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=
|
||||
|
||||
mz@^2.6.0:
|
||||
version "2.7.0"
|
||||
resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32"
|
||||
@@ -138,22 +145,17 @@ mz@^2.6.0:
|
||||
object-assign "^4.0.1"
|
||||
thenify-all "^1.0.0"
|
||||
|
||||
nan@2.10.0:
|
||||
version "2.10.0"
|
||||
resolved "https://registry.yarnpkg.com/nan/-/nan-2.10.0.tgz#96d0cd610ebd58d4b4de9cc0c6828cda99c7548f"
|
||||
integrity sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==
|
||||
|
||||
nan@>=2.10.0, nan@^2.10.0:
|
||||
version "2.11.1"
|
||||
resolved "https://registry.yarnpkg.com/nan/-/nan-2.11.1.tgz#90e22bccb8ca57ea4cd37cc83d3819b52eea6766"
|
||||
integrity sha512-iji6k87OSXa0CcrLl9z+ZiYSuR2o+c0bGuNmXdrhTQTakxytAFsC56SArGYoiHlJlFoHSnvmhpceZJaXkVuOtA==
|
||||
nan@2.12.1, nan@>=2.10.0, nan@^2.10.0:
|
||||
version "2.12.1"
|
||||
resolved "https://registry.yarnpkg.com/nan/-/nan-2.12.1.tgz#7b1aa193e9aa86057e3c7bbd0ac448e770925552"
|
||||
integrity sha512-JY7V6lRkStKcKTvHO5NVSQRv+RV+FIL5pvDoLiAtSL9pKlC5x9PKQcZDsq7m4FO4d57mkhC6Z+QhAh3Jdk5JFw==
|
||||
|
||||
node-pty@^0.8.0:
|
||||
version "0.8.0"
|
||||
resolved "https://registry.yarnpkg.com/node-pty/-/node-pty-0.8.0.tgz#08bccb633f49e2e3f7245eb56ea6b40f37ccd64f"
|
||||
integrity sha512-g5ggk3gN4gLrDmAllee5ScFyX3YzpOC/U8VJafha4pE7do0TIE1voiIxEbHSRUOPD1xYqmY+uHhOKAd3avbxGQ==
|
||||
version "0.8.1"
|
||||
resolved "https://registry.yarnpkg.com/node-pty/-/node-pty-0.8.1.tgz#94b457bec013e7a09b8d9141f63b0787fa25c23f"
|
||||
integrity sha512-j+/g0Q5dR+vkELclpJpz32HcS3O/3EdPSGPvDXJZVJQLCvgG0toEbfmymxAEyQyZEpaoKHAcoL+PvKM+4N9nlw==
|
||||
dependencies:
|
||||
nan "2.10.0"
|
||||
nan "2.12.1"
|
||||
|
||||
object-assign@^4.0.1:
|
||||
version "4.1.1"
|
||||
|
Reference in New Issue
Block a user