diff --git a/.all-contributorsrc b/.all-contributorsrc
new file mode 100644
index 00000000..ea603f0e
--- /dev/null
+++ b/.all-contributorsrc
@@ -0,0 +1,173 @@
+{
+ "files": [
+ "README.md"
+ ],
+ "imageSize": 100,
+ "commit": false,
+ "contributors": [
+ {
+ "login": "mezner",
+ "name": "Russell Myers",
+ "avatar_url": "https://avatars2.githubusercontent.com/u/184085?v=4",
+ "profile": "http://www.russellmyers.com",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "ehwarren",
+ "name": "Austin Warren",
+ "avatar_url": "https://avatars1.githubusercontent.com/u/3991658?v=4",
+ "profile": "http://www.morwire.com",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "Drachenkaetzchen",
+ "name": "Felicia Hummel",
+ "avatar_url": "https://avatars1.githubusercontent.com/u/162974?v=4",
+ "profile": "https://github.com/Drachenkaetzchen",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "mikemaccana",
+ "name": "Mike MacCana",
+ "avatar_url": "https://avatars2.githubusercontent.com/u/172594?v=4",
+ "profile": "https://github.com/mikemaccana",
+ "contributions": [
+ "test",
+ "design"
+ ]
+ },
+ {
+ "login": "yxuko",
+ "name": "Yacine Kanzari",
+ "avatar_url": "https://avatars1.githubusercontent.com/u/1786317?v=4",
+ "profile": "https://github.com/yxuko",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "BBJip",
+ "name": "BBJip",
+ "avatar_url": "https://avatars2.githubusercontent.com/u/32908927?v=4",
+ "profile": "https://github.com/BBJip",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "Futagirl",
+ "name": "Futagirl",
+ "avatar_url": "https://avatars2.githubusercontent.com/u/33533958?v=4",
+ "profile": "https://github.com/Futagirl",
+ "contributions": [
+ "design"
+ ]
+ },
+ {
+ "login": "levrik",
+ "name": "Levin Rickert",
+ "avatar_url": "https://avatars3.githubusercontent.com/u/9491603?v=4",
+ "profile": "https://www.levrik.io",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "kwonoj",
+ "name": "OJ Kwon",
+ "avatar_url": "https://avatars2.githubusercontent.com/u/1210596?v=4",
+ "profile": "https://kwonoj.github.io",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "Domain",
+ "name": "domain",
+ "avatar_url": "https://avatars2.githubusercontent.com/u/903197?v=4",
+ "profile": "https://github.com/Domain",
+ "contributions": [
+ "plugin",
+ "code"
+ ]
+ },
+ {
+ "login": "kbjr",
+ "name": "James Brumond",
+ "avatar_url": "https://avatars1.githubusercontent.com/u/195127?v=4",
+ "profile": "http://www.jbrumond.me",
+ "contributions": [
+ "plugin"
+ ]
+ },
+ {
+ "login": "Tyriar",
+ "name": "Daniel Imms",
+ "avatar_url": "https://avatars0.githubusercontent.com/u/2193314?v=4",
+ "profile": "http://www.growingwiththeweb.com",
+ "contributions": [
+ "code",
+ "plugin",
+ "test"
+ ]
+ },
+ {
+ "login": "baflo",
+ "name": "Florian Bachmann",
+ "avatar_url": "https://avatars2.githubusercontent.com/u/834350?v=4",
+ "profile": "https://github.com/baflo",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "mischah",
+ "name": "Michael KΓΌhnel",
+ "avatar_url": "https://avatars2.githubusercontent.com/u/441011?v=4",
+ "profile": "http://michael-kuehnel.de",
+ "contributions": [
+ "code",
+ "design"
+ ]
+ },
+ {
+ "login": "NieLeben",
+ "name": "Tilmann Meyer",
+ "avatar_url": "https://avatars3.githubusercontent.com/u/47182955?v=4",
+ "profile": "https://github.com/NieLeben",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "PMExtra",
+ "name": "PM Extra",
+ "avatar_url": "https://avatars3.githubusercontent.com/u/11289158?v=4",
+ "profile": "http://www.jubeat.net",
+ "contributions": [
+ "bug"
+ ]
+ },
+ {
+ "login": "IgnusG",
+ "name": "Jonathan",
+ "avatar_url": "https://avatars1.githubusercontent.com/u/6438760?v=4",
+ "profile": "https://jjuhas.keybase.pub//",
+ "contributions": [
+ "code"
+ ]
+ }
+ ],
+ "contributorsPerLine": 7,
+ "projectName": "terminus",
+ "projectOwner": "Eugeny",
+ "repoType": "github",
+ "repoHost": "https://github.com",
+ "commitConvention": "none"
+}
diff --git a/.eslintrc.yml b/.eslintrc.yml
new file mode 100644
index 00000000..20da7bad
--- /dev/null
+++ b/.eslintrc.yml
@@ -0,0 +1,82 @@
+parser: '@typescript-eslint/parser'
+parserOptions:
+ project: tsconfig.json
+extends:
+ - 'plugin:@typescript-eslint/all'
+plugins:
+ - '@typescript-eslint'
+env:
+ browser: true
+ es6: true
+ node: true
+ commonjs: true
+rules:
+ '@typescript-eslint/semi':
+ - error
+ - never
+ '@typescript-eslint/indent':
+ - error
+ - 4
+ '@typescript-eslint/explicit-member-accessibility':
+ - error
+ - accessibility: no-public
+ overrides:
+ parameterProperties: explicit
+ '@typescript-eslint/no-require-imports': off
+ '@typescript-eslint/no-parameter-properties': off
+ '@typescript-eslint/explicit-function-return-type': off
+ '@typescript-eslint/no-explicit-any': off
+ '@typescript-eslint/no-magic-numbers': off
+ '@typescript-eslint/member-delimiter-style': off
+ '@typescript-eslint/promise-function-async': off
+ '@typescript-eslint/no-unnecessary-type-assertion': off
+ '@typescript-eslint/require-array-sort-compare': off
+ '@typescript-eslint/no-use-before-define':
+ - error
+ - classes: false
+ no-duplicate-imports: error
+ array-bracket-spacing:
+ - error
+ - never
+ block-scoped-var: error
+ brace-style:
+ - error
+ - 1tbs
+ - allowSingleLine: true
+ computed-property-spacing:
+ - error
+ - never
+ comma-dangle:
+ - error
+ - always-multiline
+ curly: error
+ eol-last: error
+ eqeqeq:
+ - error
+ - smart
+ linebreak-style:
+ - error
+ - unix
+ max-depth:
+ - 1
+ - 5
+ max-statements:
+ - 1
+ - 80
+ no-multiple-empty-lines: error
+ no-mixed-spaces-and-tabs: error
+ no-trailing-spaces: error
+ '@typescript-eslint/no-unused-vars':
+ - error
+ - vars: all
+ args: after-used
+ argsIgnorePattern: ^_
+ no-undef: error
+ object-curly-spacing:
+ - error
+ - always
+ quote-props:
+ - warn
+ - as-needed
+ - keywords: true
+ numbers: true
diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
new file mode 100644
index 00000000..9be12b64
--- /dev/null
+++ b/.github/FUNDING.yml
@@ -0,0 +1,3 @@
+github: eugeny
+open_collective: terminus
+ko_fi: eugeny
diff --git a/.github/stale.yml b/.github/stale.yml
index 333a804b..a3d40cc4 100644
--- a/.github/stale.yml
+++ b/.github/stale.yml
@@ -5,7 +5,7 @@ daysUntilClose: 14
# Issues with these labels will never be considered stale
exemptLabels:
- "T: Enhancement"
- - "S: Triaged"
+ - "S: Confirmed"
# Label to use when marking an issue as stale
staleLabel: "S: Stale"
# Comment to post when marking an issue as stale. Set to `false` to disable
diff --git a/.gitignore b/.gitignore
index e35c983b..188054a5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,6 +5,9 @@ node_modules
build/files.wxs
dist
+*/dist
+*/typings
+*.tsbuildinfo
*.xcworkspacedata
*.xcuserstate
@@ -17,3 +20,7 @@ npm-debug.log
builtin-plugins
package-lock.json
yarn-error.log
+
+docs/api
+.travis.ssh.key
+*.code-workspace
diff --git a/.travis.ssh.key.enc b/.travis.ssh.key.enc
new file mode 100644
index 00000000..5f07ddbf
Binary files /dev/null and b/.travis.ssh.key.enc differ
diff --git a/.travis.ssh.key.pub b/.travis.ssh.key.pub
new file mode 100644
index 00000000..e534803e
--- /dev/null
+++ b/.travis.ssh.key.pub
@@ -0,0 +1 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDDFM4nHSbET5V7EYNgjA8NeVfOxV0wVMdZ2YvsDzD+qPJ4+MYbvsL7ZPaSxQSn7n6ATkLHjKje5RpF/Rl9K3kucGs0P6cqJVeE0qryEteQ3Q+fYAk+bD2J9ZQ/hv/0NtLl8T+7lJUZ3WUxFH73sgph77Sw0z+kMpPaK7U2vqMBQD/7+6iJgya31wP0qW0XKDz1BjKeXgwTg10Pm4vcGsR4c2q7YIzSzBHffcyo0vJyFvOX/ZKHlZRcq/wnQMeOl/hPgf1xCENjQZmFVReQlYSw5cNNDT9HZPKekOAZFFez7/AbPiTIo/bnBYIv0mdUjr3nw8nXF505q8LiD3z/ksaaWDqe9CCLM4W0Bh7/dhP7IGPdfX0fVHLhOnYIOsG21D8rWJjMPkVRSLyEvWNAnVuObJNHoQu8VATnOxfPNnMun72IHyyFWVoADk5JcsMbzcP7gZB+5oJO7U1qpcdndtBOA3ZlF0Uz2jVZnqavoEBWT39tl3vs69hAA3aTPGclg7HMuAJOl4HsKmaUgDxqV2wCX/S4pDqmKMbmumDLX+MM0xl0gXj/zpVJp9BzdnrArkC40ivmC6TSA4wrdN0tNBlqApkH5/jxGWrcu2AXVn9PGF3+QrjW0iu+QMZCaKWDhLIQC835uFwzhnNGlx41B7uxMLuNFxKXdQ3f/cC9QMG8ew== TravisCIDeployKey
diff --git a/.travis.yml b/.travis.yml
index afc19994..bbb5a58d 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,29 +1,25 @@
-matrix:
- include:
- - os: linux
- env: BUILD_FOR=linux
- - os: osx
- env: BUILD_FOR=macos
-
language: node_js
-node_js: 8
+node_js: 11
-cache:
- directories:
- - node_modules
- - app/node_modules
+stages:
+ - Docs
-before_install:
- - yarn install
- - scripts/install-deps.js
+jobs:
+ include:
+ - stage: 'Docs'
+ os: linux
+ if: branch = master
+ script:
+ - set -e
+ - openssl aes-256-cbc -K $encrypted_4e2fb4889ef8_key -iv $encrypted_4e2fb4889ef8_iv -in .travis.ssh.key.enc -out .travis.ssh.key -d
+ - eval "$(ssh-agent -s)"
+ - chmod 600 .travis.ssh.key
+ - ssh-add .travis.ssh.key
+ - yarn
+ - yarn run docs
+ - rsync -e "ssh -o StrictHostKeyChecking=no" -arv docs/api/ root@ajenti.org:/srv/terminus-docs/
-script:
- - scripts/build-native.js
- - yarn run build
- - scripts/prepackage-plugins.js
- - scripts/build-$BUILD_FOR.js
-
-dist: trusty
+dist: xenial
sudo: false
addons:
@@ -31,6 +27,14 @@ addons:
packages:
- rpm
- yarn
+ - libsecret-1-dev
sources:
- sourceline: 'deb https://dl.yarnpkg.com/debian/ stable main'
key_url: 'https://dl.yarnpkg.com/debian/pubkey.gpg'
+
+cache:
+ directories:
+ - 'terminus-*/node_modules'
+ - $HOME/.cache/yarn
+ - $HOME/.cache/electron
+ - $HOME/.cache/electron-builder
diff --git a/HACKING.md b/HACKING.md
index 31e89587..c7525235 100644
--- a/HACKING.md
+++ b/HACKING.md
@@ -92,11 +92,11 @@ Plugins provide functionality by exporting singular or multi providers:
```javascript
import { NgModule, Injectable } from '@angular/core'
-import { ToolbarButtonProvider, IToolbarButton } from 'terminus-core'
+import { ToolbarButtonProvider, ToolbarButton } from 'terminus-core'
@Injectable()
export class MyButtonProvider extends ToolbarButtonProvider {
- provide (): IToolbarButton[] {
+ provide (): ToolbarButton[] {
return [{
icon: 'star',
title: 'Foobar',
diff --git a/README.md b/README.md
index f7a53694..8ad43baa 100644
--- a/README.md
+++ b/README.md
@@ -1,43 +1,58 @@

+
-
-
+
+
- Downloads | Community | Latest Windows nightly
+
----
-**Terminus** is a terminal heavily inspired by Hyper. It is, however, designed for people who need to get things done.
+**Terminus** is a highly configurable terminal emulator for Windows, macOS and Linux
- * Runs on Windows, macOS and Linux
* Theming and color schemes
* Fully configurable shortcuts
+ * Split panes
+ * Remembers your tabs
+ * PowerShell (and PS Core), WSL, Git-Bash, Cygwin, Cmder and CMD support
+ * Integrated SSH client and connection manager
* 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
+ * Proper shell experience on Windows including tab completion (via Clink)
[](https://ko-fi.com/eugeny)
+---
+
+* **Terminus is** an alternative to Windows' standard terminal (conhost), PowerShell ISE, PuTTY or iTerm
+
+* **Terminus is not** a new shell or a MinGW or Cygwin replacement. Neither is it lightweight - if RAM usage is of importance, consider [Conemu](https://conemu.github.io) or [Alacritty](https://github.com/jwilm/alacritty)
---
# Plugins
-Plugins can be installed directly from the Settings view inside Terminus.
+Plugins and themes can be installed directly from the Settings view inside Terminus.
* [clickable-links](https://github.com/Eugeny/terminus-clickable-links) - makes paths and URLs in the terminal clickable
- * [theme-hype](https://github.com/Eugeny/terminus-theme-hype) - a Hyper inspired theme
* [shell-selector](https://github.com/Eugeny/terminus-shell-selector) - a quick shell selector pane
* [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
+ * [scrollbar](https://github.com/kbjr/terminus-scrollbar) - adds a scrollbar to hterm tabs
+
+# Themes
+
+ * [hype](https://github.com/Eugeny/terminus-theme-hype) - a Hyper inspired theme
+ * [relaxed](https://github.com/Relaxed-Theme/relaxed-terminal-themes#terminus) - the Relaxed theme for Terminus
+ * [gruvbox](https://github.com/porkloin/terminus-theme-gruvbox)
+ * [windows10](https://www.npmjs.com/package/terminus-theme-windows10)
+ * [altair](https://github.com/yxuko/terminus-altair)
---
@@ -45,8 +60,16 @@ Plugins can be installed directly from the Settings view inside Terminus.
Pull requests and plugins are welcome!
-See [HACKING.md](https://github.com/Eugeny/terminus/blob/master/HACKING.md) for information of how the project is laid out, and a very brief plugin development tutorial.
+See [HACKING.md](https://github.com/Eugeny/terminus/blob/master/HACKING.md) and [API docs](http://ajenti.org/terminus-docs/) for information of how the project is laid out, and a very brief plugin development tutorial.
+---
-## License
-[](https://app.fossa.io/projects/git%2Bhttps%3A%2F%2Fgithub.com%2FEugeny%2Fterminus?ref=badge_large)
+Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
+
+
+
+
+
+
+
+This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
diff --git a/app/assets/activity.png b/app/assets/activity.png
new file mode 100644
index 00000000..adc9b6f8
Binary files /dev/null and b/app/assets/activity.png differ
diff --git a/app/dev-app-update.yml b/app/dev-app-update.yml
new file mode 100644
index 00000000..e95e81c4
--- /dev/null
+++ b/app/dev-app-update.yml
@@ -0,0 +1,4 @@
+owner: eugeny
+repo: terminus
+provider: github
+updaterCacheDirName: terminus-updater
diff --git a/app/lib/app.ts b/app/lib/app.ts
index 59d99175..b67cce41 100644
--- a/app/lib/app.ts
+++ b/app/lib/app.ts
@@ -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,16 @@ export class Application {
}
app.commandLine.appendSwitch('disable-http-cache')
+ app.commandLine.appendSwitch('lang', 'EN')
+
+ for (const flag of configData.flags || [['force_discrete_gpu', '0']]) {
+ console.log('Setting Electron flag:', flag.join('='))
+ app.commandLine.appendSwitch(flag[0], flag[1])
+ }
+ }
+
+ init () {
+ electron.screen.on('display-metrics-changed', () => this.broadcast('host:display-metrics-changed'))
}
async newWindow (options?: WindowOptions): Promise {
@@ -103,7 +114,7 @@ export class Application {
{
label: 'Preferences',
accelerator: 'Cmd+,',
- async click () {
+ click: async () => {
if (!this.hasWindows()) {
await this.newWindow()
}
diff --git a/app/lib/cli.ts b/app/lib/cli.ts
index 5d68ac64..d1cfcf75 100644
--- a/app/lib/cli.ts
+++ b/app/lib/cli.ts
@@ -13,6 +13,9 @@ export function parseArgs (argv, cwd) {
.command('run [command...]', 'run a command in the terminal', {
command: { type: 'string' },
})
+ .command('profile [profileName]', 'open a tab with specified profile', {
+ profileName: { type: 'string' },
+ })
.command('paste [text]', 'paste stdin into the active tab', yargs => {
return yargs.option('escape', {
alias: 'e',
@@ -38,6 +41,5 @@ export function parseArgs (argv, cwd) {
type: 'boolean'
})
.help('help')
- .strict()
.parse(argv.slice(1))
}
diff --git a/app/lib/index.ts b/app/lib/index.ts
index 28fe3c18..d479f630 100644
--- a/app/lib/index.ts
+++ b/app/lib/index.ts
@@ -1,9 +1,8 @@
import './lru'
import { app, ipcMain, Menu } from 'electron'
-import electronDebug = require('electron-debug')
import { parseArgs } from './cli'
import { Application } from './app'
-if (process.platform === 'win32' && require('electron-squirrel-startup')) process.exit(0)
+import electronDebug = require('electron-debug')
if (!process.env.TERMINUS_PLUGINS) {
process.env.TERMINUS_PLUGINS = ''
@@ -12,7 +11,6 @@ if (!process.env.TERMINUS_PLUGINS) {
const application = new Application()
ipcMain.on('app:new-window', () => {
- console.log('new-window')
application.newWindow()
})
@@ -45,7 +43,11 @@ if (!app.requestSingleInstanceLock()) {
}
if (argv.d) {
- electronDebug({ enabled: true, showDevTools: 'undocked' })
+ electronDebug({
+ isEnabled: true,
+ showDevTools: true,
+ devToolsMode: 'undocked'
+ })
}
app.on('ready', () => {
@@ -59,5 +61,6 @@ app.on('ready', () => {
}
]))
}
+ application.init()
application.newWindow({ hidden: argv.hidden })
})
diff --git a/app/lib/window.ts b/app/lib/window.ts
index 527f489f..94687af7 100644
--- a/app/lib/window.ts
+++ b/app/lib/window.ts
@@ -1,4 +1,5 @@
import { Subject, Observable } from 'rxjs'
+import { debounceTime } from 'rxjs/operators'
import { BrowserWindow, app, ipcMain, Rectangle } from 'electron'
import ElectronConfig = require('electron-config')
import * as os from 'os'
@@ -10,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
}
@@ -43,7 +44,9 @@ export class Window {
title: 'Terminus',
minWidth: 400,
minHeight: 300,
- webPreferences: { webSecurity: false },
+ webPreferences: {
+ nodeIntegration: true,
+ },
frame: false,
show: false,
backgroundColor: '#00000000'
@@ -102,16 +105,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)
}
@@ -143,6 +144,16 @@ export class Window {
this.visible.next(false)
})
+ let moveSubscription = new Observable(observer => {
+ this.window.on('move', () => observer.next())
+ }).pipe(debounceTime(250)).subscribe(() => {
+ this.window.webContents.send('host:window-moved')
+ })
+
+ this.window.on('closed', () => {
+ moveSubscription.unsubscribe()
+ })
+
this.window.on('enter-full-screen', () => this.window.webContents.send('host:window-enter-full-screen'))
this.window.on('leave-full-screen', () => this.window.webContents.send('host:window-leave-full-screen'))
@@ -173,28 +184,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()) {
@@ -205,42 +216,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()) {
@@ -250,7 +261,10 @@ export class Window {
this.window.moveTop()
})
- ipcMain.on('window-close', () => {
+ ipcMain.on('window-close', event => {
+ if (!this.window || event.sender !== this.window.webContents) {
+ return
+ }
this.closing = true
this.window.close()
})
diff --git a/app/package.json b/app/package.json
index e9bc507e..b1a9c0db 100644
--- a/app/package.json
+++ b/app/package.json
@@ -13,32 +13,34 @@
"watch": "webpack --progress --color --watch"
},
"dependencies": {
- "@angular/animations": "7.2.0-beta.1",
- "@angular/common": "7.2.0-beta.1",
- "@angular/compiler": "7.2.0-beta.1",
- "@angular/core": "7.2.0-beta.1",
- "@angular/forms": "7.2.0-beta.1",
- "@angular/platform-browser": "7.2.0-beta.1",
- "@angular/platform-browser-dynamic": "7.2.0-beta.1",
- "@ng-bootstrap/ng-bootstrap": "^3.3.1",
+ "@angular/animations": "7.2.8",
+ "@angular/common": "7.2.8",
+ "@angular/compiler": "7.2.8",
+ "@angular/core": "7.2.8",
+ "@angular/forms": "7.2.8",
+ "@angular/platform-browser": "7.2.8",
+ "@angular/platform-browser-dynamic": "7.2.8",
+ "@ng-bootstrap/ng-bootstrap": "^4.2.0",
"devtron": "1.4.0",
- "electron-config": "0.2.1",
- "electron-debug": "^2.0.0",
- "electron-is-dev": "0.1.2",
- "electron-squirrel-startup": "^1.0.0",
- "js-yaml": "3.8.2",
- "mz": "^2.6.0",
- "ngx-toastr": "^9.1.1",
+ "electron-config": "2.0.0",
+ "electron-debug": "^3.0.0",
+ "electron-is-dev": "1.1.0",
+ "electron-updater": "^4.0.6",
+ "js-yaml": "3.13.1",
+ "mz": "^2.7.0",
+ "ngx-toastr": "^10.0.4",
+ "npm": "~6.9.0",
"path": "0.12.7",
- "rxjs": "^6.3.3",
- "yargs": "^12.0.1",
- "zone.js": "^0.8.26"
+ "rxjs": "^6.5.2",
+ "rxjs-compat": "^6.5.2",
+ "yargs": "^13.2.4",
+ "zone.js": "^0.8.29"
},
"optionalDependencies": {
- "windows-blurbehind": "^1.0.0",
- "windows-swca": "^1.1.1"
+ "windows-blurbehind": "^1.0.1",
+ "windows-swca": "^2.0.2"
},
"devDependencies": {
- "@types/mz": "0.0.31"
+ "@types/mz": "0.0.32"
}
}
diff --git a/app/src/app.module.ts b/app/src/app.module.ts
index 08866dec..f792c8e0 100644
--- a/app/src/app.module.ts
+++ b/app/src/app.module.ts
@@ -4,18 +4,19 @@ import { NgbModule } from '@ng-bootstrap/ng-bootstrap'
import { ToastrModule } from 'ngx-toastr'
export function getRootModule (plugins: any[]) {
- let imports = [
+ const imports = [
BrowserModule,
...plugins,
NgbModule.forRoot(),
ToastrModule.forRoot({
positionClass: 'toast-bottom-center',
+ toastClass: 'toast',
preventDuplicates: true,
extendedTimeOut: 5000,
}),
]
- let bootstrap = [
- ...(plugins.filter(x => x.bootstrap).map(x => x.bootstrap)),
+ const bootstrap = [
+ ...plugins.filter(x => x.bootstrap).map(x => x.bootstrap),
]
if (bootstrap.length === 0) {
@@ -25,7 +26,7 @@ export function getRootModule (plugins: any[]) {
@NgModule({
imports,
bootstrap,
- }) class RootModule { }
+ }) class RootModule { } // eslint-disable-line @typescript-eslint/no-extraneous-class
return RootModule
}
diff --git a/app/src/entry.preload.ts b/app/src/entry.preload.ts
index ecbd5838..a425d4a8 100644
--- a/app/src/entry.preload.ts
+++ b/app/src/entry.preload.ts
@@ -1,7 +1,9 @@
import '../lib/lru'
-import 'source-sans-pro'
+import 'source-sans-pro/source-sans-pro.css'
import 'source-code-pro/source-code-pro.css'
-import 'font-awesome/css/font-awesome.css'
+import '@fortawesome/fontawesome-free/css/solid.css'
+import '@fortawesome/fontawesome-free/css/brands.css'
+import '@fortawesome/fontawesome-free/css/fontawesome.css'
import 'ngx-toastr/toastr.css'
import './preload.scss'
@@ -14,20 +16,20 @@ Raven.config(
{
release: require('electron').remote.app.getVersion(),
dataCallback: (data: any) => {
- const normalize = (filename) => {
- let splitArray = filename.split('/')
+ const normalize = (filename: string) => {
+ const splitArray = filename.split('/')
return splitArray[splitArray.length - 1]
}
- data.exception.values[0].stacktrace.frames.forEach(frame => {
+ data.exception.values[0].stacktrace.frames.forEach((frame: any) => {
frame.filename = normalize(frame.filename)
})
data.culprit = data.exception.values[0].stacktrace.frames[0].filename
return data
- }
- }
+ },
+ },
)
process.on('uncaughtException' as any, (err) => {
diff --git a/app/src/entry.ts b/app/src/entry.ts
index 2a8c639e..801f385b 100644
--- a/app/src/entry.ts
+++ b/app/src/entry.ts
@@ -1,40 +1,43 @@
import 'zone.js'
-import 'core-js/es7/reflect'
-import 'core-js/core/delay'
+import 'core-js/proposals/reflect-metadata'
import 'rxjs'
+import * as isDev from 'electron-is-dev'
+
import './global.scss'
import './toastr.scss'
-// Always land on the start view
-location.hash = ''
-
import { enableProdMode, NgModuleRef } from '@angular/core'
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'
import { getRootModule } from './app.module'
-import { findPlugins, loadPlugins, IPluginInfo } from './plugins'
+import { findPlugins, loadPlugins, PluginInfo } from './plugins'
+
+// Always land on the start view
+location.hash = ''
+
+;(process as any).enablePromiseAPI = true
if (process.platform === 'win32') {
process.env.HOME = process.env.HOMEDRIVE + process.env.HOMEPATH
}
-if (require('electron-is-dev')) {
+if (isDev) {
console.warn('Running in debug mode')
} else {
enableProdMode()
}
-async function bootstrap (plugins: IPluginInfo[], safeMode = false): Promise> {
+async function bootstrap (plugins: PluginInfo[], safeMode = false): Promise> {
if (safeMode) {
plugins = plugins.filter(x => x.isBuiltin)
}
- let pluginsModules = await loadPlugins(plugins, (current, total) => {
- (document.querySelector('.progress .bar') as HTMLElement).style.width = 100 * current / total + '%'
+ const pluginsModules = await loadPlugins(plugins, (current, total) => {
+ (document.querySelector('.progress .bar') as HTMLElement).style.width = `${100 * current / total}%` // eslint-disable-line
})
- let module = getRootModule(pluginsModules)
+ const module = getRootModule(pluginsModules)
window['rootModule'] = module
- return await platformBrowserDynamic().bootstrapModule(module)
+ return platformBrowserDynamic().bootstrapModule(module)
}
findPlugins().then(async plugins => {
diff --git a/app/src/plugins.ts b/app/src/plugins.ts
index cc3ebddb..029d9f41 100644
--- a/app/src/plugins.ts
+++ b/app/src/plugins.ts
@@ -1,10 +1,8 @@
import * as fs from 'mz/fs'
import * as path from 'path'
-const nodeModule = require('module')
+const nodeModule = require('module') // eslint-disable-line @typescript-eslint/no-var-requires
const nodeRequire = (global as any).require
-declare function delay (ms: number): Promise
-
function normalizePath (path: string): string {
const cygwinPrefix = '/cygdrive/'
if (path.startsWith(cygwinPrefix)) {
@@ -14,13 +12,13 @@ function normalizePath (path: string): string {
return path
}
-nodeRequire.main.paths.map(x => nodeModule.globalPaths.push(normalizePath(x)))
+nodeRequire.main.paths.map((x: string) => 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'),
@@ -28,6 +26,10 @@ const userPluginsPath = path.join(
'plugins',
)
+if (!fs.existsSync(userPluginsPath)) {
+ fs.mkdir(userPluginsPath)
+}
+
Object.assign(window, { builtinPluginsPath, userPluginsPath })
nodeModule.globalPaths.unshift(builtinPluginsPath)
nodeModule.globalPaths.unshift(path.join(userPluginsPath, 'node_modules'))
@@ -36,9 +38,9 @@ if (process.env.TERMINUS_PLUGINS) {
process.env.TERMINUS_PLUGINS.split(':').map(x => nodeModule.globalPaths.push(normalizePath(x)))
}
-export declare type ProgressCallback = (current, total) => void
+export type ProgressCallback = (current: number, total: number) => void // eslint-disable-line @typescript-eslint/no-type-alias
-export interface IPluginInfo {
+export interface PluginInfo {
name: string
description: string
packageName: string
@@ -62,6 +64,7 @@ const builtinModules = [
'ngx-toastr',
'rxjs',
'rxjs/operators',
+ 'rxjs-compat/Subject',
'terminus-core',
'terminus-settings',
'terminus-terminal',
@@ -70,47 +73,53 @@ const builtinModules = [
const cachedBuiltinModules = {}
builtinModules.forEach(m => {
+ const label = 'Caching ' + m
+ console.time(label)
cachedBuiltinModules[m] = nodeRequire(m)
+ console.timeEnd(label)
})
-const originalRequire = nodeRequire('module').prototype.require
-nodeRequire('module').prototype.require = function (query) {
+const originalRequire = (global as any).require
+;(global as any).require = function (query: string) {
if (cachedBuiltinModules[query]) {
return cachedBuiltinModules[query]
}
return originalRequire.apply(this, arguments)
}
-export async function findPlugins (): Promise {
- let paths = nodeModule.globalPaths
- let foundPlugins: IPluginInfo[] = []
- let candidateLocations: { pluginDir: string, packageName: string }[] = []
+export async function findPlugins (): Promise {
+ const paths = nodeModule.globalPaths
+ let foundPlugins: PluginInfo[] = []
+ const candidateLocations: { pluginDir: string, packageName: string }[] = []
+ const PREFIX = 'terminus-'
for (let pluginDir of paths) {
pluginDir = normalizePath(pluginDir)
if (!await fs.exists(pluginDir)) {
continue
}
- let pluginNames = await fs.readdir(pluginDir)
+ const pluginNames = await fs.readdir(pluginDir)
if (await fs.exists(path.join(pluginDir, 'package.json'))) {
candidateLocations.push({
pluginDir: path.dirname(pluginDir),
- packageName: path.basename(pluginDir)
+ packageName: path.basename(pluginDir),
})
}
- for (let packageName of pluginNames) {
- candidateLocations.push({ pluginDir, packageName })
+ for (const packageName of pluginNames) {
+ if (packageName.startsWith(PREFIX)) {
+ candidateLocations.push({ pluginDir, packageName })
+ }
}
}
- for (let { pluginDir, packageName } of candidateLocations) {
- let pluginPath = path.join(pluginDir, packageName)
- let infoPath = path.join(pluginPath, 'package.json')
+ for (const { pluginDir, packageName } of candidateLocations) {
+ const pluginPath = path.join(pluginDir, packageName)
+ const infoPath = path.join(pluginPath, 'package.json')
if (!await fs.exists(infoPath)) {
continue
}
- let name = packageName.substring('terminus-'.length)
+ const name = packageName.substring(PREFIX.length)
if (foundPlugins.some(x => x.name === name)) {
console.info(`Plugin ${packageName} already exists, overriding`)
@@ -118,7 +127,7 @@ export async function findPlugins (): Promise {
}
try {
- let info = JSON.parse(await fs.readFile(infoPath, {encoding: 'utf-8'}))
+ const info = JSON.parse(await fs.readFile(infoPath, { encoding: 'utf-8' }))
if (!info.keywords || !(info.keywords.includes('terminus-plugin') || info.keywords.includes('terminus-builtin-plugin'))) {
continue
}
@@ -143,23 +152,25 @@ export async function findPlugins (): Promise {
return foundPlugins
}
-export async function loadPlugins (foundPlugins: IPluginInfo[], progress: ProgressCallback): Promise {
- let plugins: any[] = []
+export async function loadPlugins (foundPlugins: PluginInfo[], progress: ProgressCallback): Promise {
+ const plugins: any[] = []
progress(0, 1)
let index = 0
- for (let foundPlugin of foundPlugins) {
+ for (const foundPlugin of foundPlugins) {
console.info(`Loading ${foundPlugin.name}: ${nodeRequire.resolve(foundPlugin.path)}`)
progress(index, foundPlugins.length)
try {
- let packageModule = nodeRequire(foundPlugin.path)
- let pluginModule = packageModule.default.forRoot ? packageModule.default.forRoot() : packageModule.default
+ const label = 'Loading ' + foundPlugin.name
+ console.time(label)
+ const packageModule = nodeRequire(foundPlugin.path)
+ const pluginModule = packageModule.default.forRoot ? packageModule.default.forRoot() : packageModule.default
pluginModule['pluginName'] = foundPlugin.name
pluginModule['bootstrap'] = packageModule.bootstrap
plugins.push(pluginModule)
+ console.timeEnd(label)
} catch (error) {
console.error(`Could not load ${foundPlugin.name}:`, error)
}
- await delay(1)
index++
}
progress(1, 1)
diff --git a/app/src/root.component.ts b/app/src/root.component.ts
index dee7aff9..8d2bd18c 100644
--- a/app/src/root.component.ts
+++ b/app/src/root.component.ts
@@ -1,6 +1,6 @@
import { Component } from '@angular/core'
@Component({
- template: ' '
+ template: ' ',
})
-export class RootComponent { }
+export class RootComponent { } // eslint-disable-line @typescript-eslint/no-extraneous-class
diff --git a/app/src/toastr.scss b/app/src/toastr.scss
index ce64cd03..63fd7dee 100644
--- a/app/src/toastr.scss
+++ b/app/src/toastr.scss
@@ -2,6 +2,7 @@
display: flex;
flex-direction: column;
align-items: center;
+ padding: 20px;
.toast {
box-shadow: 0 1px 0 rgba(0,0,0,.25);
diff --git a/app/tsconfig.json b/app/tsconfig.json
index 2b1acbeb..cf51608a 100644
--- a/app/tsconfig.json
+++ b/app/tsconfig.json
@@ -9,7 +9,6 @@
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"sourceMap": true,
- "noUnusedParameters": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"noUnusedParameters": true,
diff --git a/app/webpack.config.js b/app/webpack.config.js
index 0db27868..e3fa00e2 100644
--- a/app/webpack.config.js
+++ b/app/webpack.config.js
@@ -5,11 +5,11 @@ module.exports = {
name: 'terminus',
target: 'node',
entry: {
- 'index.ignore': 'file-loader?name=index.html!val-loader!pug-html-loader!' + path.resolve(__dirname, './index.pug'),
+ 'index.ignore': 'file-loader?name=index.html!pug-html-loader!' + path.resolve(__dirname, './index.pug'),
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,
},
diff --git a/app/webpack.main.config.js b/app/webpack.main.config.js
index 353906c0..fab72b87 100644
--- a/app/webpack.main.config.js
+++ b/app/webpack.main.config.js
@@ -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: {
@@ -36,7 +36,6 @@ module.exports = {
electron: 'commonjs electron',
'electron-config': 'commonjs electron-config',
'electron-vibrancy': 'commonjs electron-vibrancy',
- 'electron-squirrel-startup': 'commonjs electron-squirrel-startup',
fs: 'commonjs fs',
mz: 'commonjs mz',
path: 'commonjs path',
diff --git a/app/yarn.lock b/app/yarn.lock
index e4dec840..f38e8878 100644
--- a/app/yarn.lock
+++ b/app/yarn.lock
@@ -2,79 +2,130 @@
# yarn lockfile v1
-"@angular/animations@7.2.0-beta.1":
- version "7.2.0-beta.1"
- resolved "https://registry.yarnpkg.com/@angular/animations/-/animations-7.2.0-beta.1.tgz#c288de4a89b0197ba53a8411173ec4085fbbd9c9"
- integrity sha512-82u9L2poaREjkTJlYEKdOO1B1LaVBwqJBZvIXU04+21WQBJoi050sxUl6lmjVVs5rRc0e/y2gifyrb42pUEntA==
+"@angular/animations@7.2.8":
+ version "7.2.8"
+ resolved "https://registry.yarnpkg.com/@angular/animations/-/animations-7.2.8.tgz#0285364c839c660a934ab0f753ec21424bfb292e"
+ integrity sha512-dJn9koYukyz15TouBc+z5z9fdThDk+bKgdlij25eYSu5Mpmtk04gB4eIMQA97K0UDh1d4YukgSJ5w3ZIk0m8DQ==
dependencies:
tslib "^1.9.0"
-"@angular/common@7.2.0-beta.1":
- version "7.2.0-beta.1"
- resolved "https://registry.yarnpkg.com/@angular/common/-/common-7.2.0-beta.1.tgz#be9d14f239b7a390fc056e3bb540da181631fb1a"
- integrity sha512-+aYfO20nrqurOLxM0w/UJkOHjGzNFOc2j52ggyj1vr62nTk+W63j4P8tcUsW6iHFCsOF5auSkclKUbNIliMf0A==
+"@angular/common@7.2.8":
+ version "7.2.8"
+ resolved "https://registry.yarnpkg.com/@angular/common/-/common-7.2.8.tgz#660c816b6f08cd2919a6efb7465397e4ff14d265"
+ integrity sha512-LgOhf68+LPndGZhtnUlGFd2goReXYmHzaFZW8gCEi9aC+H+Io8bjYh0gkH3xDreevEOe3f0z6coXNFLIxSmTuA==
dependencies:
tslib "^1.9.0"
-"@angular/compiler@7.2.0-beta.1":
- version "7.2.0-beta.1"
- resolved "https://registry.yarnpkg.com/@angular/compiler/-/compiler-7.2.0-beta.1.tgz#355a10a80615afdd1d6a5ed682222e9e57e65fd7"
- integrity sha512-KxI93dLm1SPNbazfG41QcmxVS7T9VmQ8wzhMHOVJo4DP77g2E5xUB5nOInMCMI43lbZEIckBxo/ci4jwiiq8uA==
+"@angular/compiler@7.2.8":
+ version "7.2.8"
+ resolved "https://registry.yarnpkg.com/@angular/compiler/-/compiler-7.2.8.tgz#9d9c1515e99914399e6915c1c90484b1d255560b"
+ integrity sha512-PrU97cTsOdofpaDkxK0rWUA/CGd0u6ESOI6XvFVm5xH9zJInsdY8ShSHklnr1JJnss70e1dGKZbZq32OChxWMw==
dependencies:
tslib "^1.9.0"
-"@angular/core@7.2.0-beta.1":
- version "7.2.0-beta.1"
- resolved "https://registry.yarnpkg.com/@angular/core/-/core-7.2.0-beta.1.tgz#32bef8f3d424333791d0e0bd4a3f3afee9b1349d"
- integrity sha512-gJzQAauezAMU8vEEMh1PrXv52fA9ceUXac/tJ8KIi08zEjyIRXLvKggWr7YXAbt5LwgKsn27JwecqeS5h4K/BQ==
+"@angular/core@7.2.8":
+ version "7.2.8"
+ resolved "https://registry.yarnpkg.com/@angular/core/-/core-7.2.8.tgz#6586d9b6c6321c80119b3f3e2bd0edbb32d0b649"
+ integrity sha512-QKwug2kWJC00zm2rvmD9mCJzsOkMVhSu8vqPWf83poWTh8+F9aIVWcy29W0VoGpBkSchOnK8hf9DnKVv28j9nw==
dependencies:
tslib "^1.9.0"
-"@angular/forms@7.2.0-beta.1":
- version "7.2.0-beta.1"
- resolved "https://registry.yarnpkg.com/@angular/forms/-/forms-7.2.0-beta.1.tgz#399ea4585502027d53396eac935f8f20bd5ad2bf"
- integrity sha512-1NQ2hw8Y4hjgr5qXoOvQJRjmQno/fhQUuIRx0SC7hYySur1E9vcI8rZDVDB+LwiGexALh8H70zwJ64lNxzwpvA==
+"@angular/forms@7.2.8":
+ version "7.2.8"
+ resolved "https://registry.yarnpkg.com/@angular/forms/-/forms-7.2.8.tgz#adf194088495822d55dcf3e5bf69196dcf19465d"
+ integrity sha512-lbSX4IHFHz/c4e2RHiPpL8MJlzDkCuQEHnqsujDaV2X9o9fApS6+C1X4x7Z2XDKqonmeX+aHQwv9+SLejX6OyQ==
dependencies:
tslib "^1.9.0"
-"@angular/platform-browser-dynamic@7.2.0-beta.1":
- version "7.2.0-beta.1"
- resolved "https://registry.yarnpkg.com/@angular/platform-browser-dynamic/-/platform-browser-dynamic-7.2.0-beta.1.tgz#4a95ee6d53fb02e529f1f1842ee8839a25ec4790"
- integrity sha512-wnf6WSfh9AsBzI8I//eNolmQ2rwMIk/KIuGmTEOAuAxRMLgqzZUA3PjX2XAE6oUUowqy1MET1UFiqjDf/NZcNQ==
+"@angular/platform-browser-dynamic@7.2.8":
+ version "7.2.8"
+ resolved "https://registry.yarnpkg.com/@angular/platform-browser-dynamic/-/platform-browser-dynamic-7.2.8.tgz#e82768900cedfa75bf453263f931a9f90f7aaab2"
+ integrity sha512-nOJt28A5pRn4mdL8y98V7bA6OOdMRjsQAcWCr/isGYF0l1yDC0ijUGWkHuRtj3z1/9tmERN0BLXx+xs1h4JhCQ==
dependencies:
tslib "^1.9.0"
-"@angular/platform-browser@7.2.0-beta.1":
- version "7.2.0-beta.1"
- resolved "https://registry.yarnpkg.com/@angular/platform-browser/-/platform-browser-7.2.0-beta.1.tgz#20c272ebfcccb3151baed7ceddbafdb359f54cd8"
- integrity sha512-sCMzCFCdE4Dq9foXf2PpWPegtVfirHhg+DQzoiwFDYj5i+QB9nWY7BOLlrCPAWpd8opUxCsaLrzXbfgM40FAGA==
+"@angular/platform-browser@7.2.8":
+ version "7.2.8"
+ resolved "https://registry.yarnpkg.com/@angular/platform-browser/-/platform-browser-7.2.8.tgz#11096727b99bf3d7fd82a00a3a468b933c9713bd"
+ integrity sha512-SizCRMc7Or27g2CugcqWnaAikRPfgLgRvb9GFFGpcgoq8CRfOVwkyR5dFZuqN39H+uwtwuTMP5OUYhZcrFNKug==
dependencies:
tslib "^1.9.0"
-"@ng-bootstrap/ng-bootstrap@^3.3.1":
- version "3.3.1"
- resolved "https://registry.yarnpkg.com/@ng-bootstrap/ng-bootstrap/-/ng-bootstrap-3.3.1.tgz#435eebc57dd4a371d02f342f1e919d1c4bb522a2"
- integrity sha512-awty+5Kil0i/xIV7SSmKa5YozU83EdIx2EenF2AUDTczSKhHNhRByo82rjtwIhshN25/ZEss4aSDhgILLI88fw==
+"@ng-bootstrap/ng-bootstrap@^4.2.0":
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/@ng-bootstrap/ng-bootstrap/-/ng-bootstrap-4.2.0.tgz#17152252834f3b5dc50742f3aafeaa9eb27a05f8"
+ integrity sha512-41Sg9RKgFGfnkWJhzPJIumYbib+GCTZ8N17q3PGfLORqtIN25KUFHGuO8EYOYd+zrDVYe8g4JYZoxQZvxaxm6w==
dependencies:
tslib "^1.9.0"
-"@types/mz@0.0.31":
- version "0.0.31"
- resolved "https://registry.yarnpkg.com/@types/mz/-/mz-0.0.31.tgz#a4d80c082fefe71e40a7c0f07d1e6555bbbc7b52"
- integrity sha1-pNgMCC/v5x5Ap8DwfR5lVbu8e1I=
+"@types/mz@0.0.32":
+ version "0.0.32"
+ resolved "https://registry.yarnpkg.com/@types/mz/-/mz-0.0.32.tgz#e8248b4e41424c052edc1725dd33650c313a3659"
+ integrity sha512-cy3yebKhrHuOcrJGkfwNHhpTXQLgmXSv1BX+4p32j+VUQ6aP2eJ5cL7OvGcAQx75fCTFaAIIAKewvqL+iwSd4g==
dependencies:
"@types/node" "*"
-"@types/node@*":
- version "8.0.13"
- resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.13.tgz#530f0f9254209b0335bf5cc6387822594ef47093"
- integrity sha512-Y3EAG7VA7NVNbZek/fjJtILnmTk/ZfpJuWZGDBqDZ1dVIxgJJJ82fXPW7pKnqyV9CD/9bcPOCi7eErUqGMHOrA==
+"@types/node@*", "@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==
+
+JSONStream@^1.3.4, JSONStream@^1.3.5:
+ version "1.3.5"
+ resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.5.tgz#3208c1f08d3a4d99261ab64f92302bc15e111ca0"
+ integrity sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==
+ dependencies:
+ jsonparse "^1.2.0"
+ through ">=2.2.7 <3"
+
+abbrev@1, abbrev@~1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8"
+ integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==
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"
integrity sha1-PaDM6dbsY3OWS4TzXbfPw996tRQ=
+agent-base@4, agent-base@^4.1.0:
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.3.0.tgz#8165f01c436009bccad0b1d122f05ed770efc6ee"
+ integrity sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==
+ dependencies:
+ es6-promisify "^5.0.0"
+
+agent-base@~4.2.1:
+ version "4.2.1"
+ resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.2.1.tgz#d89e5999f797875674c07d87f260fc41e83e8ca9"
+ integrity sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==
+ dependencies:
+ es6-promisify "^5.0.0"
+
+agentkeepalive@^3.4.1:
+ version "3.5.2"
+ resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-3.5.2.tgz#a113924dd3fa24a0bc3b78108c450c2abee00f67"
+ integrity sha512-e0L/HNe6qkQ7H19kTlRRqUibEAwDK5AFk6y3PtMsuut2VAH6+Q4xZml1tNDJD7kSAyqmbG/K08K5WEJYtUrSlQ==
+ dependencies:
+ humanize-ms "^1.2.1"
+
+ajv@^6.5.5:
+ version "6.10.0"
+ resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.0.tgz#90d0d54439da587cd7e843bfb7045f50bd22bdf1"
+ integrity sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg==
+ dependencies:
+ fast-deep-equal "^2.0.1"
+ fast-json-stable-stringify "^2.0.0"
+ json-schema-traverse "^0.4.1"
+ uri-js "^4.2.2"
+
+ansi-align@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-2.0.0.tgz#c36aeccba563b89ceb556f3690f0b1d9e3547f7f"
+ integrity sha1-w2rsy6VjuJzrVW82kPCx2eNUf38=
+ dependencies:
+ string-width "^2.0.0"
+
ansi-regex@^2.0.0:
version "2.1.1"
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
@@ -85,11 +136,56 @@ ansi-regex@^3.0.0:
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998"
integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=
+ansi-regex@^4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997"
+ integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==
+
+ansi-styles@^3.2.0, ansi-styles@^3.2.1:
+ version "3.2.1"
+ resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
+ integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==
+ dependencies:
+ color-convert "^1.9.0"
+
+ansicolors@~0.3.2:
+ version "0.3.2"
+ resolved "https://registry.yarnpkg.com/ansicolors/-/ansicolors-0.3.2.tgz#665597de86a9ffe3aa9bfbe6cae5c6ea426b4979"
+ integrity sha1-ZlWX3oap/+Oqm/vmyuXG6kJrSXk=
+
+ansistyles@~0.1.3:
+ version "0.1.3"
+ resolved "https://registry.yarnpkg.com/ansistyles/-/ansistyles-0.1.3.tgz#5de60415bda071bb37127854c864f41b23254539"
+ integrity sha1-XeYEFb2gcbs3EnhUyGT0GyMlRTk=
+
any-promise@^1.0.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f"
integrity sha1-q8av7tzqUugJzcA3au0845Y10X8=
+aproba@^1.0.3, aproba@^1.1.1, aproba@^1.1.2:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a"
+ integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==
+
+"aproba@^1.1.2 || 2", aproba@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/aproba/-/aproba-2.0.0.tgz#52520b8ae5b569215b354efc0caa3fe1e45a8adc"
+ integrity sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==
+
+archy@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40"
+ integrity sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=
+
+are-we-there-yet@~1.1.2:
+ version "1.1.5"
+ resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21"
+ integrity sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==
+ dependencies:
+ delegates "^1.0.0"
+ readable-stream "^2.0.6"
+
argparse@^1.0.7:
version "1.0.9"
resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.9.tgz#73d83bc263f86e97f8cc4f6bae1b0e90a7d22c86"
@@ -97,11 +193,235 @@ argparse@^1.0.7:
dependencies:
sprintf-js "~1.0.2"
-camelcase@^4.1.0:
+asap@^2.0.0:
+ version "2.0.6"
+ resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46"
+ integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=
+
+asn1@~0.2.3:
+ version "0.2.4"
+ resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136"
+ integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==
+ dependencies:
+ safer-buffer "~2.1.0"
+
+assert-plus@1.0.0, assert-plus@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525"
+ integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=
+
+asynckit@^0.4.0:
+ version "0.4.0"
+ resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
+ integrity sha1-x57Zf380y48robyXkLzDZkdLS3k=
+
+aws-sign2@~0.7.0:
+ version "0.7.0"
+ resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8"
+ integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=
+
+aws4@^1.8.0:
+ version "1.8.0"
+ resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f"
+ integrity sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==
+
+balanced-match@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
+ integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c=
+
+bcrypt-pbkdf@^1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e"
+ integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=
+ dependencies:
+ tweetnacl "^0.14.3"
+
+bin-links@^1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/bin-links/-/bin-links-1.1.2.tgz#fb74bd54bae6b7befc6c6221f25322ac830d9757"
+ integrity sha512-8eEHVgYP03nILphilltWjeIjMbKyJo3wvp9K816pHbhP301ismzw15mxAAEVQ/USUwcP++1uNrbERbp8lOA6Fg==
+ dependencies:
+ bluebird "^3.5.0"
+ cmd-shim "^2.0.2"
+ gentle-fs "^2.0.0"
+ graceful-fs "^4.1.11"
+ write-file-atomic "^2.3.0"
+
+block-stream@*:
+ version "0.0.9"
+ resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a"
+ integrity sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=
+ dependencies:
+ inherits "~2.0.0"
+
+bluebird-lst@^1.0.6, bluebird-lst@^1.0.7:
+ version "1.0.8"
+ resolved "https://registry.yarnpkg.com/bluebird-lst/-/bluebird-lst-1.0.8.tgz#61b572e8b3eb57e0fff676a0e54566d93597e6a4"
+ integrity sha512-InUDOaBaIjIobOa3O4YRAbFgff907uTJZXW0m0rhk3zhVZ4GvsmdCLEAKC1CTWTtUWCM8iWTTfFX9N/xQR/etw==
+ dependencies:
+ bluebird "^3.5.4"
+
+bluebird@^3.5.0, bluebird@^3.5.1, bluebird@^3.5.3:
+ version "3.5.5"
+ resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.5.tgz#a8d0afd73251effbbd5fe384a77d73003c17a71f"
+ integrity sha512-5am6HnnfN+urzt4yfg7IgTbotDjIT/u8AJpEt0sIU9FtXfVeezXAPKswrG+xKUCOYAINpSdgZVDU6QFh+cuH3w==
+
+bluebird@^3.5.4:
+ version "3.5.4"
+ resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.4.tgz#d6cc661595de30d5b3af5fcedd3c0b3ef6ec5714"
+ integrity sha512-FG+nFEZChJrbQ9tIccIfZJBz3J7mLrAhxakAbnrJWn8d7aKOC+LWifa0G+p4ZqKp4y13T7juYvdhq9NzKdsrjw==
+
+boxen@^1.2.1:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/boxen/-/boxen-1.3.0.tgz#55c6c39a8ba58d9c61ad22cd877532deb665a20b"
+ integrity sha512-TNPjfTr432qx7yOjQyaXm3dSR0MH9vXp7eT1BFSl/C51g+EFnOR9hTg1IreahGBmDNCehscshe45f+C1TBZbLw==
+ dependencies:
+ ansi-align "^2.0.0"
+ camelcase "^4.0.0"
+ chalk "^2.0.1"
+ cli-boxes "^1.0.0"
+ string-width "^2.0.0"
+ term-size "^1.2.0"
+ widest-line "^2.0.0"
+
+brace-expansion@^1.1.7:
+ version "1.1.11"
+ resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
+ integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
+ dependencies:
+ balanced-match "^1.0.0"
+ concat-map "0.0.1"
+
+buffer-from@^1.0.0:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
+ integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==
+
+builder-util-runtime@~8.1.0:
+ version "8.1.1"
+ resolved "https://registry.yarnpkg.com/builder-util-runtime/-/builder-util-runtime-8.1.1.tgz#f2f6fc43e33d26892bd491667fc746ad69bccc50"
+ integrity sha512-+ieS4PMB33vVE2S3ZNWBEQJ1zKmAs/agrBdh7XadE1lKLjrH4aXYuOh9OOGdxqIRldhlhNBaF+yKMMEFOdNVig==
+ dependencies:
+ bluebird-lst "^1.0.6"
+ debug "^4.1.1"
+ fs-extra-p "^7.0.0"
+ sax "^1.2.4"
+
+builtins@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/builtins/-/builtins-1.0.3.tgz#cb94faeb61c8696451db36534e1422f94f0aee88"
+ integrity sha1-y5T662HIaWRR2zZTThQi+U8K7og=
+
+byline@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/byline/-/byline-5.0.0.tgz#741c5216468eadc457b03410118ad77de8c1ddb1"
+ integrity sha1-dBxSFkaOrcRXsDQQEYrXfejB3bE=
+
+byte-size@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/byte-size/-/byte-size-5.0.1.tgz#4b651039a5ecd96767e71a3d7ed380e48bed4191"
+ integrity sha512-/XuKeqWocKsYa/cBY1YbSJSWWqTi4cFgr9S6OyM7PBaPbr9zvNGwWP33vt0uqGhwDdN+y3yhbXVILEUpnwEWGw==
+
+cacache@^11.0.1, cacache@^11.3.2:
+ version "11.3.2"
+ resolved "https://registry.yarnpkg.com/cacache/-/cacache-11.3.2.tgz#2d81e308e3d258ca38125b676b98b2ac9ce69bfa"
+ integrity sha512-E0zP4EPGDOaT2chM08Als91eYnf8Z+eH1awwwVsngUmgppfM5jjJ8l3z5vO5p5w/I3LsiXawb1sW0VY65pQABg==
+ dependencies:
+ bluebird "^3.5.3"
+ chownr "^1.1.1"
+ figgy-pudding "^3.5.1"
+ glob "^7.1.3"
+ graceful-fs "^4.1.15"
+ lru-cache "^5.1.1"
+ mississippi "^3.0.0"
+ mkdirp "^0.5.1"
+ move-concurrently "^1.0.1"
+ promise-inflight "^1.0.1"
+ rimraf "^2.6.2"
+ ssri "^6.0.1"
+ unique-filename "^1.1.1"
+ y18n "^4.0.0"
+
+call-limit@~1.1.0:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/call-limit/-/call-limit-1.1.1.tgz#ef15f2670db3f1992557e2d965abc459e6e358d4"
+ integrity sha512-5twvci5b9eRBw2wCfPtN0GmlR2/gadZqyFpPhOK6CvMFoFgA+USnZ6Jpu1lhG9h85pQ3Ouil3PfXWRD4EUaRiQ==
+
+camelcase@^4.0.0, camelcase@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd"
integrity sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=
+camelcase@^5.0.0:
+ version "5.3.1"
+ resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
+ integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
+
+capture-stack-trace@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/capture-stack-trace/-/capture-stack-trace-1.0.1.tgz#a6c0bbe1f38f3aa0b92238ecb6ff42c344d4135d"
+ integrity sha512-mYQLZnx5Qt1JgB1WEiMCf2647plpGeQ2NMR/5L0HNZzGQo4fuSPnK+wjfPnKZV0aiJDgzmWqqkV/g7JD+DW0qw==
+
+caseless@~0.12.0:
+ version "0.12.0"
+ resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
+ integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=
+
+chalk@^2.0.1:
+ version "2.4.2"
+ resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
+ integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
+ dependencies:
+ ansi-styles "^3.2.1"
+ escape-string-regexp "^1.0.5"
+ supports-color "^5.3.0"
+
+chownr@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.1.tgz#54726b8b8fff4df053c42187e801fb4412df1494"
+ integrity sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==
+
+ci-info@^1.5.0:
+ version "1.6.0"
+ resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.6.0.tgz#2ca20dbb9ceb32d4524a683303313f0304b1e497"
+ integrity sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==
+
+ci-info@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46"
+ integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==
+
+cidr-regex@^2.0.10:
+ version "2.0.10"
+ resolved "https://registry.yarnpkg.com/cidr-regex/-/cidr-regex-2.0.10.tgz#af13878bd4ad704de77d6dc800799358b3afa70d"
+ integrity sha512-sB3ogMQXWvreNPbJUZMRApxuRYd+KoIo4RGQ81VatjmMW6WJPo+IJZ2846FGItr9VzKo5w7DXzijPLGtSd0N3Q==
+ dependencies:
+ ip-regex "^2.1.0"
+
+cli-boxes@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-1.0.0.tgz#4fa917c3e59c94a004cd61f8ee509da651687143"
+ integrity sha1-T6kXw+WclKAEzWH47lCdplFocUM=
+
+cli-columns@^3.1.2:
+ version "3.1.2"
+ resolved "https://registry.yarnpkg.com/cli-columns/-/cli-columns-3.1.2.tgz#6732d972979efc2ae444a1f08e08fa139c96a18e"
+ integrity sha1-ZzLZcpee/CrkRKHwjgj6E5yWoY4=
+ dependencies:
+ string-width "^2.0.0"
+ strip-ansi "^3.0.1"
+
+cli-table3@^0.5.0, cli-table3@^0.5.1:
+ version "0.5.1"
+ resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.5.1.tgz#0252372d94dfc40dbd8df06005f48f31f656f202"
+ integrity sha512-7Qg2Jrep1S/+Q3EceiZtQcDPWxhAvBw+ERf1162v4sikJrvojMHFqXt8QIVha8UlH9rgU0BeWPytZ9/TzYqlUw==
+ dependencies:
+ object-assign "^4.1.0"
+ string-width "^2.1.1"
+ optionalDependencies:
+ colors "^1.1.2"
+
cliui@^4.0.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/cliui/-/cliui-4.1.0.tgz#348422dbe82d800b3022eef4f6ac10bf2e4d1b49"
@@ -111,20 +431,139 @@ cliui@^4.0.0:
strip-ansi "^4.0.0"
wrap-ansi "^2.0.0"
+cliui@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5"
+ integrity sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==
+ dependencies:
+ string-width "^3.1.0"
+ strip-ansi "^5.2.0"
+ wrap-ansi "^5.1.0"
+
+clone@^1.0.2:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e"
+ integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4=
+
+cmd-shim@^2.0.2, cmd-shim@~2.0.2:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/cmd-shim/-/cmd-shim-2.0.2.tgz#6fcbda99483a8fd15d7d30a196ca69d688a2efdb"
+ integrity sha1-b8vamUg6j9FdfTChlspp1oii79s=
+ dependencies:
+ graceful-fs "^4.1.2"
+ mkdirp "~0.5.0"
+
code-point-at@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=
-conf@^0.11.1:
- version "0.11.2"
- resolved "https://registry.yarnpkg.com/conf/-/conf-0.11.2.tgz#879f479267600483e502583462ca4063fc9779b2"
- integrity sha1-h59HkmdgBIPlAlg0YspAY/yXebI=
+color-convert@^1.9.0:
+ version "1.9.3"
+ resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
+ integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==
dependencies:
- dot-prop "^3.0.0"
- env-paths "^0.3.0"
+ color-name "1.1.3"
+
+color-name@1.1.3:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
+ integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=
+
+colors@^1.1.2:
+ version "1.3.3"
+ resolved "https://registry.yarnpkg.com/colors/-/colors-1.3.3.tgz#39e005d546afe01e01f9c4ca8fa50f686a01205d"
+ integrity sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg==
+
+columnify@~1.5.4:
+ version "1.5.4"
+ resolved "https://registry.yarnpkg.com/columnify/-/columnify-1.5.4.tgz#4737ddf1c7b69a8a7c340570782e947eec8e78bb"
+ integrity sha1-Rzfd8ce2mop8NAVweC6UfuyOeLs=
+ dependencies:
+ strip-ansi "^3.0.0"
+ wcwidth "^1.0.0"
+
+combined-stream@^1.0.6, combined-stream@~1.0.6:
+ version "1.0.8"
+ resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
+ integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
+ dependencies:
+ delayed-stream "~1.0.0"
+
+concat-map@0.0.1:
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
+ integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
+
+concat-stream@^1.5.0:
+ version "1.6.2"
+ resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34"
+ integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==
+ dependencies:
+ buffer-from "^1.0.0"
+ inherits "^2.0.3"
+ readable-stream "^2.2.2"
+ typedarray "^0.0.6"
+
+conf@^1.0.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/conf/-/conf-1.4.0.tgz#1ea66c9d7a9b601674a5bb9d2b8dc3c726625e67"
+ integrity sha512-bzlVWS2THbMetHqXKB8ypsXN4DQ/1qopGwNJi1eYbpwesJcd86FBjFciCQX/YwAhp9bM7NVnPFqZ5LpV7gP0Dg==
+ dependencies:
+ dot-prop "^4.1.0"
+ env-paths "^1.0.0"
+ make-dir "^1.0.0"
+ pkg-up "^2.0.0"
+ write-file-atomic "^2.3.0"
+
+config-chain@^1.1.12:
+ version "1.1.12"
+ resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.12.tgz#0fde8d091200eb5e808caf25fe618c02f48e4efa"
+ integrity sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA==
+ dependencies:
+ ini "^1.3.4"
+ proto-list "~1.2.1"
+
+configstore@^3.0.0:
+ version "3.1.2"
+ resolved "https://registry.yarnpkg.com/configstore/-/configstore-3.1.2.tgz#c6f25defaeef26df12dd33414b001fe81a543f8f"
+ integrity sha512-vtv5HtGjcYUgFrXc6Kx747B83MRRVS5R1VTEQoXvuP+kMI+if6uywV0nDGoiydJRy4yk7h9od5Og0kxx4zUXmw==
+ dependencies:
+ dot-prop "^4.1.0"
+ graceful-fs "^4.1.2"
+ make-dir "^1.0.0"
+ unique-string "^1.0.0"
+ write-file-atomic "^2.0.0"
+ xdg-basedir "^3.0.0"
+
+console-control-strings@^1.0.0, console-control-strings@^1.1.0, console-control-strings@~1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e"
+ integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=
+
+copy-concurrently@^1.0.0:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/copy-concurrently/-/copy-concurrently-1.0.5.tgz#92297398cae34937fcafd6ec8139c18051f0b5e0"
+ integrity sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==
+ dependencies:
+ aproba "^1.1.1"
+ fs-write-stream-atomic "^1.0.8"
+ iferr "^0.1.5"
mkdirp "^0.5.1"
- pkg-up "^1.0.0"
+ rimraf "^2.5.4"
+ run-queue "^1.0.0"
+
+core-util-is@1.0.2, core-util-is@~1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
+ integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
+
+create-error-class@^3.0.0:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/create-error-class/-/create-error-class-3.0.2.tgz#06be7abef947a3f14a30fd610671d401bca8b7b6"
+ integrity sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=
+ dependencies:
+ capture-stack-trace "^1.0.0"
cross-spawn@^5.0.1:
version "5.1.0"
@@ -135,19 +574,108 @@ cross-spawn@^5.0.1:
shebang-command "^1.2.0"
which "^1.2.9"
-debug@^2.2.0, debug@^2.6.8:
- version "2.6.8"
- resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc"
- integrity sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=
+cross-spawn@^6.0.0:
+ version "6.0.5"
+ resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"
+ integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==
+ dependencies:
+ nice-try "^1.0.4"
+ path-key "^2.0.1"
+ semver "^5.5.0"
+ shebang-command "^1.2.0"
+ which "^1.2.9"
+
+crypto-random-string@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-1.0.0.tgz#a230f64f568310e1498009940790ec99545bca7e"
+ integrity sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=
+
+cyclist@~0.2.2:
+ version "0.2.2"
+ resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-0.2.2.tgz#1b33792e11e914a2fd6d6ed6447464444e5fa640"
+ integrity sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA=
+
+dashdash@^1.12.0:
+ version "1.14.1"
+ resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0"
+ integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=
+ dependencies:
+ assert-plus "^1.0.0"
+
+debug@3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
+ integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==
dependencies:
ms "2.0.0"
-decamelize@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-2.0.0.tgz#656d7bbc8094c4c788ea53c5840908c9c7d063c7"
- integrity sha512-Ikpp5scV3MSYxY39ymh45ZLEecsTdv/Xj2CaQfI8RLMuwi7XvjX9H/fhraiSuU+C5w5NTDu4ZU72xNiZnurBPg==
+debug@^2.6.8:
+ version "2.6.9"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
+ integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
dependencies:
- xregexp "4.0.0"
+ ms "2.0.0"
+
+debug@^3.1.0:
+ version "3.2.6"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b"
+ integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==
+ dependencies:
+ ms "^2.1.1"
+
+debug@^4.1.1:
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791"
+ integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==
+ dependencies:
+ ms "^2.1.1"
+
+debuglog@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492"
+ integrity sha1-qiT/uaw9+aI1GDfPstJ5NgzXhJI=
+
+decamelize@^1.1.1, decamelize@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
+ integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=
+
+decode-uri-component@^0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545"
+ integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=
+
+deep-extend@^0.6.0:
+ version "0.6.0"
+ resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac"
+ integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==
+
+defaults@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d"
+ integrity sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=
+ dependencies:
+ clone "^1.0.2"
+
+delayed-stream@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
+ integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk=
+
+delegates@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a"
+ integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=
+
+detect-indent@~5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-5.0.0.tgz#3871cc0a6a002e8c3e5b3cf7f336264675f06b9d"
+ integrity sha1-OHHMCmoALow+Wzz38zYmRnXwa50=
+
+detect-newline@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-2.1.0.tgz#f41f1c10be4b00e87b5f13da680759f2c5bfd3e2"
+ integrity sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=
devtron@1.4.0:
version "1.4.0"
@@ -158,44 +686,80 @@ devtron@1.4.0:
highlight.js "^9.3.0"
humanize-plus "^1.8.1"
-dot-prop@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-3.0.0.tgz#1b708af094a49c9a0e7dbcad790aba539dac1177"
- integrity sha1-G3CK8JSknJoOfbyteQq6U52sEXc=
+dezalgo@^1.0.0, dezalgo@~1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/dezalgo/-/dezalgo-1.0.3.tgz#7f742de066fc748bc8db820569dddce49bf0d456"
+ integrity sha1-f3Qt4Gb8dIvI24IFad3c5Jvw1FY=
+ dependencies:
+ asap "^2.0.0"
+ wrappy "1"
+
+dot-prop@^4.1.0:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.2.0.tgz#1f19e0c2e1aa0e32797c49799f2837ac6af69c57"
+ integrity sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==
dependencies:
is-obj "^1.0.0"
-electron-config@0.2.1:
- version "0.2.1"
- resolved "https://registry.yarnpkg.com/electron-config/-/electron-config-0.2.1.tgz#7e12c26412d06bf3ed3896d0479df162986b95ba"
- integrity sha1-fhLCZBLQa/PtOJbQR53xYphrlbo=
- dependencies:
- conf "^0.11.1"
+dotenv@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-5.0.1.tgz#a5317459bd3d79ab88cff6e44057a6a3fbb1fcef"
+ integrity sha512-4As8uPrjfwb7VXC+WnLCbXK7y+Ueb2B3zgNCePYfhxS1PYeaO1YTeplffTEcbfLhvFNGLAz90VvJs9yomG7bow==
-electron-debug@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/electron-debug/-/electron-debug-2.0.0.tgz#3059a6557acbfb091f138d83875f57bac80cea6d"
- integrity sha512-orGlw9uErUztdD7cgdKz78txq3czpOnKG/zvvsINkUsugqL+dn77UFrbwRGVgPwuLJ7Ejbjjk9EcxIcgTivMbA==
+duplexer3@^0.1.4:
+ version "0.1.4"
+ resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2"
+ integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=
+
+duplexify@^3.4.2, duplexify@^3.6.0:
+ version "3.7.1"
+ resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309"
+ integrity sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==
dependencies:
- electron-is-dev "^0.3.0"
- electron-localshortcut "^3.0.0"
+ end-of-stream "^1.0.0"
+ inherits "^2.0.1"
+ readable-stream "^2.0.0"
+ stream-shift "^1.0.0"
+
+ecc-jsbn@~0.1.1:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9"
+ integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=
+ dependencies:
+ jsbn "~0.1.0"
+ safer-buffer "^2.1.0"
+
+editor@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/editor/-/editor-1.0.0.tgz#60c7f87bd62bcc6a894fa8ccd6afb7823a24f742"
+ integrity sha1-YMf4e9YrzGqJT6jM1q+3gjok90I=
+
+electron-config@2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/electron-config/-/electron-config-2.0.0.tgz#b00a7d55556d9c1aa59f5eec3bdf446c773425ff"
+ integrity sha512-5mGwRK4lsAo6tiy4KNF/zUInYpUGr7JJzLA8FHOoqBWV3kkKJWSrDXo4Uk2Ffm5aeQ1o73XuorfkYhaWFV2O4g==
+ dependencies:
+ conf "^1.0.0"
+
+electron-debug@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/electron-debug/-/electron-debug-3.0.0.tgz#55b7895df7f371558d0595d14dc2f8a738a41c81"
+ integrity sha512-rLrnn7L2soeIqwB6FIzn4+pj6RwT66XhUxadcrS3okjB3ezAv8LsolqrFrO2UrTrvchZgTCcEapV4J0UxlYWIw==
+ dependencies:
+ electron-is-dev "^1.1.0"
+ electron-localshortcut "^3.1.0"
electron-is-accelerator@^0.1.0:
version "0.1.2"
resolved "https://registry.yarnpkg.com/electron-is-accelerator/-/electron-is-accelerator-0.1.2.tgz#509e510c26a56b55e17f863a4b04e111846ab27b"
integrity sha1-UJ5RDCala1Xhf4Y6SwThEYRqsns=
-electron-is-dev@0.1.2:
- version "0.1.2"
- resolved "https://registry.yarnpkg.com/electron-is-dev/-/electron-is-dev-0.1.2.tgz#8a1043e32b3a1da1c3f553dce28ce764246167e3"
- integrity sha1-ihBD4ys6HaHD9VPc4oznZCRhZ+M=
+electron-is-dev@1.1.0, electron-is-dev@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/electron-is-dev/-/electron-is-dev-1.1.0.tgz#b15a2a600bdc48a51a857d460e05f15b19a2522c"
+ integrity sha512-Z1qA/1oHNowGtSBIcWk0pcLEqYT/j+13xUw/MYOrBUOL4X7VN0i0KCTf5SqyvMPmW5pSPKbo28wkxMxzZ20YnQ==
-electron-is-dev@^0.3.0:
- version "0.3.0"
- resolved "https://registry.yarnpkg.com/electron-is-dev/-/electron-is-dev-0.3.0.tgz#14e6fda5c68e9e4ecbeff9ccf037cbd7c05c5afe"
- integrity sha1-FOb9pcaOnk7L7/nM8DfL18BcWv4=
-
-electron-localshortcut@^3.0.0:
+electron-localshortcut@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/electron-localshortcut/-/electron-localshortcut-3.1.0.tgz#10c1ffd537b8d39170aaf6e1551341f7780dd2ce"
integrity sha512-MgL/j5jdjW7iA0R6cI7S045B0GlKXWM1FjjujVPjlrmyXRa6yH0bGSaIAfxXAF9tpJm3pLEiQzerYHkRh9JG/A==
@@ -205,22 +769,78 @@ electron-localshortcut@^3.0.0:
keyboardevent-from-electron-accelerator "^1.1.0"
keyboardevents-areequal "^0.2.1"
-electron-squirrel-startup@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/electron-squirrel-startup/-/electron-squirrel-startup-1.0.0.tgz#19b4e55933fa0ef8f556784b9c660f772546a0b8"
- integrity sha1-GbTlWTP6Dvj1VnhLnGYPdyVGoLg=
+electron-updater@^4.0.6:
+ version "4.0.6"
+ resolved "https://registry.yarnpkg.com/electron-updater/-/electron-updater-4.0.6.tgz#9c4f495ae0e80bf4425e3e1b801c5ed2ab933c2d"
+ integrity sha512-JPGLME6fxJcHG8hX7HWFl6Aew6iVm0DkcrENreKa5SUJCHG+uUaAhxDGDt+YGcNkyx1uJ6eBGMvFxDTLUv67pg==
dependencies:
- debug "^2.2.0"
+ bluebird-lst "^1.0.6"
+ builder-util-runtime "~8.1.0"
+ fs-extra-p "^7.0.0"
+ js-yaml "^3.12.0"
+ lazy-val "^1.0.3"
+ lodash.isequal "^4.5.0"
+ pako "^1.0.7"
+ semver "^5.6.0"
+ source-map-support "^0.5.9"
-env-paths@^0.3.0:
- version "0.3.1"
- resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-0.3.1.tgz#c30ccfcbc30c890943dc08a85582517ef00da463"
- integrity sha1-wwzPy8MMiQlD3AioVYJRfvANpGM=
+emoji-regex@^7.0.1:
+ version "7.0.3"
+ resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156"
+ integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==
-esprima@^3.1.1:
- version "3.1.3"
- resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633"
- integrity sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=
+encoding@^0.1.11:
+ version "0.1.12"
+ resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb"
+ integrity sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=
+ dependencies:
+ iconv-lite "~0.4.13"
+
+end-of-stream@^1.0.0, end-of-stream@^1.1.0:
+ version "1.4.1"
+ resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43"
+ integrity sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==
+ dependencies:
+ once "^1.4.0"
+
+env-paths@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-1.0.0.tgz#4168133b42bb05c38a35b1ae4397c8298ab369e0"
+ integrity sha1-QWgTO0K7BcOKNbGuQ5fIKYqzaeA=
+
+err-code@^1.0.0:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/err-code/-/err-code-1.1.2.tgz#06e0116d3028f6aef4806849eb0ea6a748ae6960"
+ integrity sha1-BuARbTAo9q70gGhJ6w6mp0iuaWA=
+
+errno@~0.1.7:
+ version "0.1.7"
+ resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.7.tgz#4684d71779ad39af177e3f007996f7c67c852618"
+ integrity sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==
+ dependencies:
+ prr "~1.0.1"
+
+es6-promise@^4.0.3:
+ version "4.2.8"
+ resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a"
+ integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==
+
+es6-promisify@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203"
+ integrity sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=
+ dependencies:
+ es6-promise "^4.0.3"
+
+escape-string-regexp@^1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
+ integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
+
+esprima@^4.0.0:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71"
+ integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==
execa@^0.7.0:
version "0.7.0"
@@ -235,13 +855,60 @@ execa@^0.7.0:
signal-exit "^3.0.0"
strip-eof "^1.0.0"
-find-up@^1.0.0:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f"
- integrity sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=
+execa@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8"
+ integrity sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==
dependencies:
- path-exists "^2.0.0"
- pinkie-promise "^2.0.0"
+ cross-spawn "^6.0.0"
+ get-stream "^4.0.0"
+ is-stream "^1.1.0"
+ npm-run-path "^2.0.0"
+ p-finally "^1.0.0"
+ signal-exit "^3.0.0"
+ strip-eof "^1.0.0"
+
+extend@~3.0.2:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
+ integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==
+
+extsprintf@1.3.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05"
+ integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=
+
+extsprintf@^1.2.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f"
+ integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8=
+
+fast-deep-equal@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49"
+ integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=
+
+fast-json-stable-stringify@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2"
+ integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I=
+
+figgy-pudding@^3.4.1, figgy-pudding@^3.5.1:
+ version "3.5.1"
+ resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.1.tgz#862470112901c727a0e495a80744bd5baa1d6790"
+ integrity sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w==
+
+find-npm-prefix@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/find-npm-prefix/-/find-npm-prefix-1.0.2.tgz#8d8ce2c78b3b4b9e66c8acc6a37c231eb841cfdf"
+ integrity sha512-KEftzJ+H90x6pcKtdXZEPsQse8/y/UnvzRKrOSQFprnrGaFuJ62fVkP34Iu2IYuMvyauCyoLTNkJZgrrGA2wkA==
+
+find-up@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7"
+ integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c=
+ dependencies:
+ locate-path "^2.0.0"
find-up@^3.0.0:
version "3.0.0"
@@ -250,36 +917,385 @@ find-up@^3.0.0:
dependencies:
locate-path "^3.0.0"
+flush-write-stream@^1.0.0:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.1.1.tgz#8dd7d873a1babc207d94ead0c2e0e44276ebf2e8"
+ integrity sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==
+ dependencies:
+ inherits "^2.0.3"
+ readable-stream "^2.3.6"
+
+forever-agent@~0.6.1:
+ version "0.6.1"
+ resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
+ integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=
+
+form-data@~2.3.2:
+ version "2.3.3"
+ resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6"
+ integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==
+ dependencies:
+ asynckit "^0.4.0"
+ combined-stream "^1.0.6"
+ mime-types "^2.1.12"
+
+from2@^1.3.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/from2/-/from2-1.3.0.tgz#88413baaa5f9a597cfde9221d86986cd3c061dfd"
+ integrity sha1-iEE7qqX5pZfP3pIh2GmGzTwGHf0=
+ dependencies:
+ inherits "~2.0.1"
+ readable-stream "~1.1.10"
+
+from2@^2.1.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/from2/-/from2-2.3.0.tgz#8bfb5502bde4a4d36cfdeea007fcca21d7e382af"
+ integrity sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=
+ dependencies:
+ inherits "^2.0.1"
+ readable-stream "^2.0.0"
+
+fs-extra-p@^7.0.0:
+ version "7.0.1"
+ resolved "https://registry.yarnpkg.com/fs-extra-p/-/fs-extra-p-7.0.1.tgz#4eec0b6dfa150fa90f6ddd773b4fb1d55cad54e3"
+ integrity sha512-yhd2OV0HnHt2oitlp+X9hl2ReX4X/7kQeL7/72qzPHTZj5eUPGzAKOvEglU02Fa1OeG2rSy/aKB4WGVaLiF8tw==
+ dependencies:
+ bluebird-lst "^1.0.7"
+ fs-extra "^7.0.1"
+
+fs-extra@^7.0.1:
+ version "7.0.1"
+ resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9"
+ integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==
+ dependencies:
+ graceful-fs "^4.1.2"
+ jsonfile "^4.0.0"
+ universalify "^0.1.0"
+
+fs-minipass@^1.2.5:
+ version "1.2.6"
+ resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.6.tgz#2c5cc30ded81282bfe8a0d7c7c1853ddeb102c07"
+ integrity sha512-crhvyXcMejjv3Z5d2Fa9sf5xLYVCF5O1c71QxbVnbLsmYMBEvDAftewesN/HhY03YRoA7zOMxjNGrF5svGaaeQ==
+ dependencies:
+ minipass "^2.2.1"
+
+fs-vacuum@^1.2.10, fs-vacuum@~1.2.10:
+ version "1.2.10"
+ resolved "https://registry.yarnpkg.com/fs-vacuum/-/fs-vacuum-1.2.10.tgz#b7629bec07a4031a2548fdf99f5ecf1cc8b31e36"
+ integrity sha1-t2Kb7AekAxolSP35n17PHMizHjY=
+ dependencies:
+ graceful-fs "^4.1.2"
+ path-is-inside "^1.0.1"
+ rimraf "^2.5.2"
+
+fs-write-stream-atomic@^1.0.8, fs-write-stream-atomic@~1.0.10:
+ version "1.0.10"
+ resolved "https://registry.yarnpkg.com/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz#b47df53493ef911df75731e70a9ded0189db40c9"
+ integrity sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=
+ dependencies:
+ graceful-fs "^4.1.2"
+ iferr "^0.1.5"
+ imurmurhash "^0.1.4"
+ readable-stream "1 || 2"
+
+fs.realpath@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
+ integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8=
+
+fstream@^1.0.0, fstream@^1.0.12:
+ version "1.0.12"
+ resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.12.tgz#4e8ba8ee2d48be4f7d0de505455548eae5932045"
+ integrity sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==
+ dependencies:
+ graceful-fs "^4.1.2"
+ inherits "~2.0.0"
+ mkdirp ">=0.5 0"
+ rimraf "2"
+
+gauge@~2.7.3:
+ version "2.7.4"
+ resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7"
+ integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=
+ dependencies:
+ aproba "^1.0.3"
+ console-control-strings "^1.0.0"
+ has-unicode "^2.0.0"
+ object-assign "^4.1.0"
+ signal-exit "^3.0.0"
+ string-width "^1.0.1"
+ strip-ansi "^3.0.1"
+ wide-align "^1.1.0"
+
+genfun@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/genfun/-/genfun-5.0.0.tgz#9dd9710a06900a5c4a5bf57aca5da4e52fe76537"
+ integrity sha512-KGDOARWVga7+rnB3z9Sd2Letx515owfk0hSxHGuqjANb1M+x2bGZGqHLiozPsYMdM2OubeMni/Hpwmjq6qIUhA==
+
+gentle-fs@^2.0.0, gentle-fs@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/gentle-fs/-/gentle-fs-2.0.1.tgz#585cfd612bfc5cd52471fdb42537f016a5ce3687"
+ integrity sha512-cEng5+3fuARewXktTEGbwsktcldA+YsnUEaXZwcK/3pjSE1X9ObnTs+/8rYf8s+RnIcQm2D5x3rwpN7Zom8Bew==
+ dependencies:
+ aproba "^1.1.2"
+ fs-vacuum "^1.2.10"
+ graceful-fs "^4.1.11"
+ iferr "^0.1.5"
+ mkdirp "^0.5.1"
+ path-is-inside "^1.0.2"
+ read-cmd-shim "^1.0.1"
+ slide "^1.1.6"
+
get-caller-file@^1.0.1:
version "1.0.3"
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a"
integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==
+get-caller-file@^2.0.1:
+ version "2.0.5"
+ resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
+ integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
+
get-stream@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14"
integrity sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=
+get-stream@^4.0.0, get-stream@^4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5"
+ integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==
+ dependencies:
+ pump "^3.0.0"
+
+getpass@^0.1.1:
+ version "0.1.7"
+ resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa"
+ integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=
+ dependencies:
+ assert-plus "^1.0.0"
+
+glob@^7.0.3, glob@^7.1.1, glob@^7.1.3:
+ version "7.1.4"
+ resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.4.tgz#aa608a2f6c577ad357e1ae5a5c26d9a8d1969255"
+ integrity sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==
+ dependencies:
+ fs.realpath "^1.0.0"
+ inflight "^1.0.4"
+ inherits "2"
+ minimatch "^3.0.4"
+ once "^1.3.0"
+ path-is-absolute "^1.0.0"
+
+global-dirs@^0.1.0:
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-0.1.1.tgz#b319c0dd4607f353f3be9cca4c72fc148c49f445"
+ integrity sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU=
+ dependencies:
+ ini "^1.3.4"
+
+got@^6.7.1:
+ version "6.7.1"
+ resolved "https://registry.yarnpkg.com/got/-/got-6.7.1.tgz#240cd05785a9a18e561dc1b44b41c763ef1e8db0"
+ integrity sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=
+ dependencies:
+ create-error-class "^3.0.0"
+ duplexer3 "^0.1.4"
+ get-stream "^3.0.0"
+ is-redirect "^1.0.0"
+ is-retry-allowed "^1.0.0"
+ is-stream "^1.0.0"
+ lowercase-keys "^1.0.0"
+ safe-buffer "^5.0.1"
+ timed-out "^4.0.0"
+ unzip-response "^2.0.1"
+ url-parse-lax "^1.0.0"
+
+graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6:
+ version "4.1.15"
+ resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00"
+ integrity sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==
+
+har-schema@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92"
+ integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=
+
+har-validator@~5.1.0:
+ version "5.1.3"
+ resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.3.tgz#1ef89ebd3e4996557675eed9893110dc350fa080"
+ integrity sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==
+ dependencies:
+ ajv "^6.5.5"
+ har-schema "^2.0.0"
+
+has-flag@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
+ integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0=
+
+has-unicode@^2.0.0, has-unicode@~2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9"
+ integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=
+
highlight.js@^9.3.0:
version "9.12.0"
resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.12.0.tgz#e6d9dbe57cbefe60751f02af336195870c90c01e"
integrity sha1-5tnb5Xy+/mB1HwKvM2GVhwyQwB4=
+hosted-git-info@^2.1.4, hosted-git-info@^2.6.0, hosted-git-info@^2.7.1:
+ version "2.7.1"
+ resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.7.1.tgz#97f236977bd6e125408930ff6de3eec6281ec047"
+ integrity sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==
+
+http-cache-semantics@^3.8.1:
+ version "3.8.1"
+ resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz#39b0e16add9b605bf0a9ef3d9daaf4843b4cacd2"
+ integrity sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==
+
+http-proxy-agent@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz#e4821beef5b2142a2026bd73926fe537631c5405"
+ integrity sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==
+ dependencies:
+ agent-base "4"
+ debug "3.1.0"
+
+http-signature@~1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1"
+ integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=
+ dependencies:
+ assert-plus "^1.0.0"
+ jsprim "^1.2.2"
+ sshpk "^1.7.0"
+
+https-proxy-agent@^2.2.1:
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz#51552970fa04d723e04c56d04178c3f92592bbc0"
+ integrity sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ==
+ dependencies:
+ agent-base "^4.1.0"
+ debug "^3.1.0"
+
+humanize-ms@^1.2.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/humanize-ms/-/humanize-ms-1.2.1.tgz#c46e3159a293f6b896da29316d8b6fe8bb79bbed"
+ integrity sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0=
+ dependencies:
+ ms "^2.0.0"
+
humanize-plus@^1.8.1:
version "1.8.2"
resolved "https://registry.yarnpkg.com/humanize-plus/-/humanize-plus-1.8.2.tgz#a65b34459ad6367adbb3707a82a3c9f916167030"
integrity sha1-pls0RZrWNnrbs3B6gqPJ+RYWcDA=
+iconv-lite@~0.4.13:
+ version "0.4.24"
+ resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
+ integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
+ dependencies:
+ safer-buffer ">= 2.1.2 < 3"
+
+iferr@^0.1.5:
+ version "0.1.5"
+ resolved "https://registry.yarnpkg.com/iferr/-/iferr-0.1.5.tgz#c60eed69e6d8fdb6b3104a1fcbca1c192dc5b501"
+ integrity sha1-xg7taebY/bazEEofy8ocGS3FtQE=
+
+iferr@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/iferr/-/iferr-1.0.2.tgz#e9fde49a9da06dc4a4194c6c9ed6d08305037a6d"
+ integrity sha512-9AfeLfji44r5TKInjhz3W9DyZI1zR1JAf2hVBMGhddAKPqBsupb89jGfbCTHIGZd6fGZl9WlHdn4AObygyMKwg==
+
+ignore-walk@^3.0.1:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.1.tgz#a83e62e7d272ac0e3b551aaa82831a19b69f82f8"
+ integrity sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ==
+ dependencies:
+ minimatch "^3.0.4"
+
+import-lazy@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43"
+ integrity sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=
+
+imurmurhash@^0.1.4:
+ version "0.1.4"
+ resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
+ integrity sha1-khi5srkoojixPcT7a21XbyMUU+o=
+
+inflight@^1.0.4, inflight@~1.0.6:
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
+ integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=
+ dependencies:
+ once "^1.3.0"
+ wrappy "1"
+
+inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
+ integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
+
inherits@2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1"
integrity sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=
+ini@^1.3.4, ini@^1.3.5, ini@~1.3.0:
+ version "1.3.5"
+ resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927"
+ integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==
+
+init-package-json@^1.10.3:
+ version "1.10.3"
+ resolved "https://registry.yarnpkg.com/init-package-json/-/init-package-json-1.10.3.tgz#45ffe2f610a8ca134f2bd1db5637b235070f6cbe"
+ integrity sha512-zKSiXKhQveNteyhcj1CoOP8tqp1QuxPIPBl8Bid99DGLFqA1p87M6lNgfjJHSBoWJJlidGOv5rWjyYKEB3g2Jw==
+ dependencies:
+ glob "^7.1.1"
+ npm-package-arg "^4.0.0 || ^5.0.0 || ^6.0.0"
+ promzard "^0.3.0"
+ read "~1.0.1"
+ read-package-json "1 || 2"
+ semver "2.x || 3.x || 4 || 5"
+ validate-npm-package-license "^3.0.1"
+ validate-npm-package-name "^3.0.0"
+
invert-kv@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6"
integrity sha1-EEqOSqym09jNFXqO+L+rLXo//bY=
+invert-kv@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-2.0.0.tgz#7393f5afa59ec9ff5f67a27620d11c226e3eec02"
+ integrity sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==
+
+ip-regex@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9"
+ integrity sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=
+
+ip@^1.1.5:
+ version "1.1.5"
+ resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a"
+ integrity sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=
+
+is-ci@^1.0.10:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-1.2.1.tgz#e3779c8ee17fccf428488f6e281187f2e632841c"
+ integrity sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==
+ dependencies:
+ ci-info "^1.5.0"
+
+is-cidr@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/is-cidr/-/is-cidr-3.0.0.tgz#1acf35c9e881063cd5f696d48959b30fed3eed56"
+ integrity sha512-8Xnnbjsb0x462VoYiGlhEi+drY8SFwrHiSYuzc/CEwco55vkehTaxAyIjEdpi3EMvLPPJAJi9FlzP+h+03gp0Q==
+ dependencies:
+ cidr-regex "^2.0.10"
+
is-fullwidth-code-point@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb"
@@ -292,28 +1308,125 @@ is-fullwidth-code-point@^2.0.0:
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f"
integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=
+is-installed-globally@^0.1.0:
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.1.0.tgz#0dfd98f5a9111716dd535dda6492f67bf3d25a80"
+ integrity sha1-Df2Y9akRFxbdU13aZJL2e/PSWoA=
+ dependencies:
+ global-dirs "^0.1.0"
+ is-path-inside "^1.0.0"
+
+is-npm@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-1.0.0.tgz#f2fb63a65e4905b406c86072765a1a4dc793b9f4"
+ integrity sha1-8vtjpl5JBbQGyGBydloaTceTufQ=
+
is-obj@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f"
integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8=
-is-stream@^1.1.0:
+is-path-inside@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.1.tgz#8ef5b7de50437a3fdca6b4e865ef7aa55cb48036"
+ integrity sha1-jvW33lBDej/cprToZe96pVy0gDY=
+ dependencies:
+ path-is-inside "^1.0.1"
+
+is-redirect@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/is-redirect/-/is-redirect-1.0.0.tgz#1d03dded53bd8db0f30c26e4f95d36fc7c87dc24"
+ integrity sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=
+
+is-retry-allowed@^1.0.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz#11a060568b67339444033d0125a61a20d564fb34"
+ integrity sha1-EaBgVotnM5REAz0BJaYaINVk+zQ=
+
+is-stream@^1.0.0, is-stream@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ=
+is-typedarray@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
+ integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=
+
+isarray@0.0.1:
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf"
+ integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=
+
+isarray@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
+ integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=
+
isexe@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=
-js-yaml@3.8.2:
- version "3.8.2"
- resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.8.2.tgz#02d3e2c0f6beab20248d412c352203827d786721"
- integrity sha1-AtPiwPa+qyAkjUEsNSIDgn14ZyE=
+isstream@~0.1.2:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
+ integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=
+
+js-yaml@3.13.1, js-yaml@^3.12.0:
+ version "3.13.1"
+ resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847"
+ integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==
dependencies:
argparse "^1.0.7"
- esprima "^3.1.1"
+ esprima "^4.0.0"
+
+jsbn@~0.1.0:
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
+ integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM=
+
+json-parse-better-errors@^1.0.0, json-parse-better-errors@^1.0.1, json-parse-better-errors@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9"
+ integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==
+
+json-schema-traverse@^0.4.1:
+ version "0.4.1"
+ resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
+ integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==
+
+json-schema@0.2.3:
+ version "0.2.3"
+ resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13"
+ integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=
+
+json-stringify-safe@~5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
+ integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=
+
+jsonfile@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb"
+ integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=
+ optionalDependencies:
+ graceful-fs "^4.1.6"
+
+jsonparse@^1.2.0:
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280"
+ integrity sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=
+
+jsprim@^1.2.2:
+ version "1.4.1"
+ resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2"
+ integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=
+ dependencies:
+ assert-plus "1.0.0"
+ extsprintf "1.3.0"
+ json-schema "0.2.3"
+ verror "1.10.0"
keyboardevent-from-electron-accelerator@^1.1.0:
version "1.1.0"
@@ -325,6 +1438,23 @@ keyboardevents-areequal@^0.2.1:
resolved "https://registry.yarnpkg.com/keyboardevents-areequal/-/keyboardevents-areequal-0.2.2.tgz#88191ec738ce9f7591c25e9056de928b40277194"
integrity sha512-Nv+Kr33T0mEjxR500q+I6IWisOQ0lK1GGOncV0kWE6n4KFmpcu7RUX5/2B0EUtX51Cb0HjZ9VJsSY3u4cBa0kw==
+latest-version@^3.0.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-3.1.0.tgz#a205383fea322b33b5ae3b18abee0dc2f356ee15"
+ integrity sha1-ogU4P+oyKzO1rjsYq+4NwvNW7hU=
+ dependencies:
+ package-json "^4.0.0"
+
+lazy-property@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/lazy-property/-/lazy-property-1.0.0.tgz#84ddc4b370679ba8bd4cdcfa4c06b43d57111147"
+ integrity sha1-hN3Es3Bnm6i9TNz6TAa0PVcREUc=
+
+lazy-val@^1.0.3:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/lazy-val/-/lazy-val-1.0.4.tgz#882636a7245c2cfe6e0a4e3ba6c5d68a137e5c65"
+ integrity sha512-u93kb2fPbIrfzBuLjZE+w+fJbUUMhNDXxNmMfaqNgpfQf1CO5ZSe2LfsnBqVAk7i/2NF48OSoRj+Xe2VT+lE8Q==
+
lcid@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835"
@@ -332,6 +1462,155 @@ lcid@^1.0.0:
dependencies:
invert-kv "^1.0.0"
+lcid@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/lcid/-/lcid-2.0.0.tgz#6ef5d2df60e52f82eb228a4c373e8d1f397253cf"
+ integrity sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==
+ dependencies:
+ invert-kv "^2.0.0"
+
+libcipm@^3.0.3:
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/libcipm/-/libcipm-3.0.3.tgz#2e764effe0b90d458790dab3165794c804075ed3"
+ integrity sha512-71V5CpTI+zFydTc5IjJ/tx8JHbXEJvmYF2zaSVW1V3X1rRnRjXqh44iuiyry1xgi3ProUQ1vX1uwFiWs00+2og==
+ dependencies:
+ bin-links "^1.1.2"
+ bluebird "^3.5.1"
+ figgy-pudding "^3.5.1"
+ find-npm-prefix "^1.0.2"
+ graceful-fs "^4.1.11"
+ ini "^1.3.5"
+ lock-verify "^2.0.2"
+ mkdirp "^0.5.1"
+ npm-lifecycle "^2.0.3"
+ npm-logical-tree "^1.2.1"
+ npm-package-arg "^6.1.0"
+ pacote "^9.1.0"
+ read-package-json "^2.0.13"
+ rimraf "^2.6.2"
+ worker-farm "^1.6.0"
+
+libnpm@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/libnpm/-/libnpm-2.0.1.tgz#a48fcdee3c25e13c77eb7c60a0efe561d7fb0d8f"
+ integrity sha512-qTKoxyJvpBxHZQB6k0AhSLajyXq9ZE/lUsZzuHAplr2Bpv9G+k4YuYlExYdUCeVRRGqcJt8hvkPh4tBwKoV98w==
+ dependencies:
+ bin-links "^1.1.2"
+ bluebird "^3.5.3"
+ find-npm-prefix "^1.0.2"
+ libnpmaccess "^3.0.1"
+ libnpmconfig "^1.2.1"
+ libnpmhook "^5.0.2"
+ libnpmorg "^1.0.0"
+ libnpmpublish "^1.1.0"
+ libnpmsearch "^2.0.0"
+ libnpmteam "^1.0.1"
+ lock-verify "^2.0.2"
+ npm-lifecycle "^2.1.0"
+ npm-logical-tree "^1.2.1"
+ npm-package-arg "^6.1.0"
+ npm-profile "^4.0.1"
+ npm-registry-fetch "^3.8.0"
+ npmlog "^4.1.2"
+ pacote "^9.2.3"
+ read-package-json "^2.0.13"
+ stringify-package "^1.0.0"
+
+libnpmaccess@^3.0.1:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/libnpmaccess/-/libnpmaccess-3.0.1.tgz#5b3a9de621f293d425191aa2e779102f84167fa8"
+ integrity sha512-RlZ7PNarCBt+XbnP7R6PoVgOq9t+kou5rvhaInoNibhPO7eMlRfS0B8yjatgn2yaHIwWNyoJDolC/6Lc5L/IQA==
+ dependencies:
+ aproba "^2.0.0"
+ get-stream "^4.0.0"
+ npm-package-arg "^6.1.0"
+ npm-registry-fetch "^3.8.0"
+
+libnpmconfig@^1.2.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/libnpmconfig/-/libnpmconfig-1.2.1.tgz#c0c2f793a74e67d4825e5039e7a02a0044dfcbc0"
+ integrity sha512-9esX8rTQAHqarx6qeZqmGQKBNZR5OIbl/Ayr0qQDy3oXja2iFVQQI81R6GZ2a02bSNZ9p3YOGX1O6HHCb1X7kA==
+ dependencies:
+ figgy-pudding "^3.5.1"
+ find-up "^3.0.0"
+ ini "^1.3.5"
+
+libnpmhook@^5.0.2:
+ version "5.0.2"
+ resolved "https://registry.yarnpkg.com/libnpmhook/-/libnpmhook-5.0.2.tgz#d12817b0fb893f36f1d5be20017f2aea25825d94"
+ integrity sha512-vLenmdFWhRfnnZiNFPNMog6CK7Ujofy2TWiM2CrpZUjBRIhHkJeDaAbJdYCT6W4lcHtyrJR8yXW8KFyq6UAp1g==
+ dependencies:
+ aproba "^2.0.0"
+ figgy-pudding "^3.4.1"
+ get-stream "^4.0.0"
+ npm-registry-fetch "^3.8.0"
+
+libnpmorg@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/libnpmorg/-/libnpmorg-1.0.0.tgz#979b868c48ba28c5820e3bb9d9e73c883c16a232"
+ integrity sha512-o+4eVJBoDGMgRwh2lJY0a8pRV2c/tQM/SxlqXezjcAg26Qe9jigYVs+Xk0vvlYDWCDhP0g74J8UwWeAgsB7gGw==
+ dependencies:
+ aproba "^2.0.0"
+ figgy-pudding "^3.4.1"
+ get-stream "^4.0.0"
+ npm-registry-fetch "^3.8.0"
+
+libnpmpublish@^1.1.0:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/libnpmpublish/-/libnpmpublish-1.1.1.tgz#ff0c6bb0b4ad2bda2ad1f5fba6760a4af37125f0"
+ integrity sha512-nefbvJd/wY38zdt+b9SHL6171vqBrMtZ56Gsgfd0duEKb/pB8rDT4/ObUQLrHz1tOfht1flt2zM+UGaemzAG5g==
+ dependencies:
+ aproba "^2.0.0"
+ figgy-pudding "^3.5.1"
+ get-stream "^4.0.0"
+ lodash.clonedeep "^4.5.0"
+ normalize-package-data "^2.4.0"
+ npm-package-arg "^6.1.0"
+ npm-registry-fetch "^3.8.0"
+ semver "^5.5.1"
+ ssri "^6.0.1"
+
+libnpmsearch@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/libnpmsearch/-/libnpmsearch-2.0.0.tgz#de05af47ada81554a5f64276a69599070d4a5685"
+ integrity sha512-vd+JWbTGzOSfiOc+72MU6y7WqmBXn49egCCrIXp27iE/88bX8EpG64ST1blWQI1bSMUr9l1AKPMVsqa2tS5KWA==
+ dependencies:
+ figgy-pudding "^3.5.1"
+ get-stream "^4.0.0"
+ npm-registry-fetch "^3.8.0"
+
+libnpmteam@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/libnpmteam/-/libnpmteam-1.0.1.tgz#ff704b1b6c06ea674b3b1101ac3e305f5114f213"
+ integrity sha512-gDdrflKFCX7TNwOMX1snWojCoDE5LoRWcfOC0C/fqF7mBq8Uz9zWAX4B2RllYETNO7pBupBaSyBDkTAC15cAMg==
+ dependencies:
+ aproba "^2.0.0"
+ figgy-pudding "^3.4.1"
+ get-stream "^4.0.0"
+ npm-registry-fetch "^3.8.0"
+
+libnpx@^10.2.0:
+ version "10.2.0"
+ resolved "https://registry.yarnpkg.com/libnpx/-/libnpx-10.2.0.tgz#1bf4a1c9f36081f64935eb014041da10855e3102"
+ integrity sha512-X28coei8/XRCt15cYStbLBph+KGhFra4VQhRBPuH/HHMkC5dxM8v24RVgUsvODKCrUZ0eTgiTqJp6zbl0sskQQ==
+ dependencies:
+ dotenv "^5.0.1"
+ npm-package-arg "^6.0.0"
+ rimraf "^2.6.2"
+ safe-buffer "^5.1.0"
+ update-notifier "^2.3.0"
+ which "^1.3.0"
+ y18n "^4.0.0"
+ yargs "^11.0.0"
+
+locate-path@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e"
+ integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=
+ dependencies:
+ p-locate "^2.0.0"
+ path-exists "^3.0.0"
+
locate-path@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e"
@@ -340,14 +1619,120 @@ locate-path@^3.0.0:
p-locate "^3.0.0"
path-exists "^3.0.0"
-lru-cache@^4.0.1:
- version "4.1.3"
- resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.3.tgz#a1175cf3496dfc8436c156c334b4955992bce69c"
- integrity sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA==
+lock-verify@^2.0.2, lock-verify@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/lock-verify/-/lock-verify-2.1.0.tgz#fff4c918b8db9497af0c5fa7f6d71555de3ceb47"
+ integrity sha512-vcLpxnGvrqisKvLQ2C2v0/u7LVly17ak2YSgoK4PrdsYBXQIax19vhKiLfvKNFx7FRrpTnitrpzF/uuCMuorIg==
+ dependencies:
+ npm-package-arg "^6.1.0"
+ semver "^5.4.1"
+
+lockfile@^1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/lockfile/-/lockfile-1.0.4.tgz#07f819d25ae48f87e538e6578b6964a4981a5609"
+ integrity sha512-cvbTwETRfsFh4nHsL1eGWapU1XFi5Ot9E85sWAwia7Y7EgB7vfqcZhTKZ+l7hCGxSPoushMv5GKhT5PdLv03WA==
+ dependencies:
+ signal-exit "^3.0.2"
+
+lodash._baseuniq@~4.6.0:
+ version "4.6.0"
+ resolved "https://registry.yarnpkg.com/lodash._baseuniq/-/lodash._baseuniq-4.6.0.tgz#0ebb44e456814af7905c6212fa2c9b2d51b841e8"
+ integrity sha1-DrtE5FaBSveQXGIS+iybLVG4Qeg=
+ dependencies:
+ lodash._createset "~4.0.0"
+ lodash._root "~3.0.0"
+
+lodash._createset@~4.0.0:
+ version "4.0.3"
+ resolved "https://registry.yarnpkg.com/lodash._createset/-/lodash._createset-4.0.3.tgz#0f4659fbb09d75194fa9e2b88a6644d363c9fe26"
+ integrity sha1-D0ZZ+7CddRlPqeK4imZE02PJ/iY=
+
+lodash._root@~3.0.0:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/lodash._root/-/lodash._root-3.0.1.tgz#fba1c4524c19ee9a5f8136b4609f017cf4ded692"
+ integrity sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=
+
+lodash.clonedeep@^4.5.0, lodash.clonedeep@~4.5.0:
+ version "4.5.0"
+ resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef"
+ integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=
+
+lodash.isequal@^4.5.0:
+ version "4.5.0"
+ resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0"
+ integrity sha1-QVxEePK8wwEgwizhDtMib30+GOA=
+
+lodash.union@~4.6.0:
+ version "4.6.0"
+ resolved "https://registry.yarnpkg.com/lodash.union/-/lodash.union-4.6.0.tgz#48bb5088409f16f1821666641c44dd1aaae3cd88"
+ integrity sha1-SLtQiECfFvGCFmZkHETdGqrjzYg=
+
+lodash.uniq@~4.5.0:
+ version "4.5.0"
+ resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
+ integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=
+
+lodash.without@~4.4.0:
+ version "4.4.0"
+ resolved "https://registry.yarnpkg.com/lodash.without/-/lodash.without-4.4.0.tgz#3cd4574a00b67bae373a94b748772640507b7aac"
+ integrity sha1-PNRXSgC2e643OpS3SHcmQFB7eqw=
+
+lowercase-keys@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f"
+ integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==
+
+lru-cache@^4.0.1, lru-cache@^4.1.2, lru-cache@^4.1.3, lru-cache@^4.1.5:
+ 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"
+lru-cache@^5.1.1:
+ version "5.1.1"
+ resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920"
+ integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==
+ dependencies:
+ yallist "^3.0.2"
+
+make-dir@^1.0.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c"
+ integrity sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==
+ dependencies:
+ pify "^3.0.0"
+
+make-fetch-happen@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-4.0.1.tgz#141497cb878f243ba93136c83d8aba12c216c083"
+ integrity sha512-7R5ivfy9ilRJ1EMKIOziwrns9fGeAD4bAha8EB7BIiBBLHm2KeTUGCrICFt2rbHfzheTLynv50GnNTK1zDTrcQ==
+ dependencies:
+ agentkeepalive "^3.4.1"
+ cacache "^11.0.1"
+ http-cache-semantics "^3.8.1"
+ http-proxy-agent "^2.1.0"
+ https-proxy-agent "^2.2.1"
+ lru-cache "^4.1.2"
+ mississippi "^3.0.0"
+ node-fetch-npm "^2.0.2"
+ promise-retry "^1.1.1"
+ socks-proxy-agent "^4.0.0"
+ ssri "^6.0.0"
+
+map-age-cleaner@^0.1.1:
+ version "0.1.3"
+ resolved "https://registry.yarnpkg.com/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz#7d583a7306434c055fe474b0f45078e6e1b4b92a"
+ integrity sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==
+ dependencies:
+ p-defer "^1.0.0"
+
+meant@~1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/meant/-/meant-1.0.1.tgz#66044fea2f23230ec806fb515efea29c44d2115d"
+ integrity sha512-UakVLFjKkbbUwNWJ2frVLnnAtbb7D7DsloxRd3s/gDpI8rdv8W5Hp3NaDb+POBI1fQdeussER6NB8vpcRURvlg==
+
mem@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/mem/-/mem-1.1.0.tgz#5edd52b485ca1d900fe64895505399a0dfa45f76"
@@ -355,44 +1740,306 @@ mem@^1.1.0:
dependencies:
mimic-fn "^1.0.0"
+mem@^4.0.0:
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/mem/-/mem-4.3.0.tgz#461af497bc4ae09608cdb2e60eefb69bff744178"
+ integrity sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==
+ dependencies:
+ map-age-cleaner "^0.1.1"
+ mimic-fn "^2.0.0"
+ p-is-promise "^2.0.0"
+
+mime-db@1.40.0:
+ version "1.40.0"
+ resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.40.0.tgz#a65057e998db090f732a68f6c276d387d4126c32"
+ integrity sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==
+
+mime-types@^2.1.12, mime-types@~2.1.19:
+ version "2.1.24"
+ resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.24.tgz#b6f8d0b3e951efb77dedeca194cff6d16f676f81"
+ integrity sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==
+ dependencies:
+ mime-db "1.40.0"
+
mimic-fn@^1.0.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022"
integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==
+mimic-fn@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
+ integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
+
+minimatch@^3.0.4:
+ version "3.0.4"
+ resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
+ integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
+ dependencies:
+ brace-expansion "^1.1.7"
+
minimist@0.0.8:
version "0.0.8"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=
-mkdirp@^0.5.1:
+minimist@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
+ integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=
+
+minipass@^2.2.1, minipass@^2.3.5:
+ version "2.3.5"
+ resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.3.5.tgz#cacebe492022497f656b0f0f51e2682a9ed2d848"
+ integrity sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA==
+ dependencies:
+ safe-buffer "^5.1.2"
+ yallist "^3.0.0"
+
+minizlib@^1.2.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.2.1.tgz#dd27ea6136243c7c880684e8672bb3a45fd9b614"
+ integrity sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA==
+ dependencies:
+ minipass "^2.2.1"
+
+mississippi@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-3.0.0.tgz#ea0a3291f97e0b5e8776b363d5f0a12d94c67022"
+ integrity sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==
+ dependencies:
+ concat-stream "^1.5.0"
+ duplexify "^3.4.2"
+ end-of-stream "^1.1.0"
+ flush-write-stream "^1.0.0"
+ from2 "^2.1.0"
+ parallel-transform "^1.1.0"
+ pump "^3.0.0"
+ pumpify "^1.3.3"
+ stream-each "^1.1.0"
+ through2 "^2.0.0"
+
+"mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@~0.5.1:
version "0.5.1"
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=
dependencies:
minimist "0.0.8"
+move-concurrently@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92"
+ integrity sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=
+ dependencies:
+ aproba "^1.1.1"
+ copy-concurrently "^1.0.0"
+ fs-write-stream-atomic "^1.0.8"
+ mkdirp "^0.5.1"
+ rimraf "^2.5.4"
+ run-queue "^1.0.3"
+
ms@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=
-mz@^2.6.0:
- version "2.6.0"
- resolved "https://registry.yarnpkg.com/mz/-/mz-2.6.0.tgz#c8b8521d958df0a4f2768025db69c719ee4ef1ce"
- integrity sha1-yLhSHZWN8KTydoAl22nHGe5O8c4=
+ms@^2.0.0:
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
+ integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
+
+ms@^2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a"
+ integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==
+
+mute-stream@~0.0.4:
+ version "0.0.8"
+ resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d"
+ integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==
+
+mz@^2.7.0:
+ version "2.7.0"
+ resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32"
+ integrity sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==
dependencies:
any-promise "^1.0.0"
object-assign "^4.0.1"
thenify-all "^1.0.0"
-ngx-toastr@^9.1.1:
- version "9.1.1"
- resolved "https://registry.yarnpkg.com/ngx-toastr/-/ngx-toastr-9.1.1.tgz#c7ec0284d13951422ccf47439a387372ddccc768"
- integrity sha512-v43BmIXPmwMRx9Uv0ru2UaPQLA14gTsqWgXrO1DKC8RXnBGGoQEE48cVCaDX1GhaGM5GSzVO2s0o+nb688zsFw==
+ngx-toastr@^10.0.4:
+ version "10.0.4"
+ resolved "https://registry.yarnpkg.com/ngx-toastr/-/ngx-toastr-10.0.4.tgz#cbc61b8d67d748194ea7a28542b01e39bf1fc6c2"
+ integrity sha512-iN+zr2Msae5wV334c1dytRhSYNdUz467jwv1NE91lMmllsMkpUzZlu8VdFCeTFt+/R4TWzz19xBRqhpp+OAuVA==
dependencies:
tslib "^1.9.0"
+nice-try@^1.0.4:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
+ integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==
+
+node-fetch-npm@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/node-fetch-npm/-/node-fetch-npm-2.0.2.tgz#7258c9046182dca345b4208eda918daf33697ff7"
+ integrity sha512-nJIxm1QmAj4v3nfCvEeCrYSoVwXyxLnaPBK5W1W5DGEJwjlKuC2VEUycGw5oxk+4zZahRrB84PUJJgEmhFTDFw==
+ dependencies:
+ encoding "^0.1.11"
+ json-parse-better-errors "^1.0.0"
+ safe-buffer "^5.1.1"
+
+node-gyp@^3.8.0:
+ version "3.8.0"
+ resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-3.8.0.tgz#540304261c330e80d0d5edce253a68cb3964218c"
+ integrity sha512-3g8lYefrRRzvGeSowdJKAKyks8oUpLEd/DyPV4eMhVlhJ0aNaZqIrNUIPuEWWTAoPqyFkfGrM67MC69baqn6vA==
+ dependencies:
+ fstream "^1.0.0"
+ glob "^7.0.3"
+ graceful-fs "^4.1.2"
+ mkdirp "^0.5.0"
+ nopt "2 || 3"
+ npmlog "0 || 1 || 2 || 3 || 4"
+ osenv "0"
+ request "^2.87.0"
+ rimraf "2"
+ semver "~5.3.0"
+ tar "^2.0.0"
+ which "1"
+
+node-gyp@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-4.0.0.tgz#972654af4e5dd0cd2a19081b4b46fe0442ba6f45"
+ integrity sha512-2XiryJ8sICNo6ej8d0idXDEMKfVfFK7kekGCtJAuelGsYHQxhj13KTf95swTCN2dZ/4lTfZ84Fu31jqJEEgjWA==
+ dependencies:
+ glob "^7.0.3"
+ graceful-fs "^4.1.2"
+ mkdirp "^0.5.0"
+ nopt "2 || 3"
+ npmlog "0 || 1 || 2 || 3 || 4"
+ osenv "0"
+ request "^2.87.0"
+ rimraf "2"
+ semver "~5.3.0"
+ tar "^4.4.8"
+ which "1"
+
+"nopt@2 || 3":
+ version "3.0.6"
+ resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9"
+ integrity sha1-xkZdvwirzU2zWTF/eaxopkayj/k=
+ dependencies:
+ abbrev "1"
+
+nopt@~4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d"
+ integrity sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=
+ dependencies:
+ abbrev "1"
+ osenv "^0.1.4"
+
+normalize-package-data@^2.0.0, normalize-package-data@^2.4.0, normalize-package-data@^2.5.0:
+ version "2.5.0"
+ resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8"
+ integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==
+ dependencies:
+ hosted-git-info "^2.1.4"
+ resolve "^1.10.0"
+ semver "2 || 3 || 4 || 5"
+ validate-npm-package-license "^3.0.1"
+
+npm-audit-report@^1.3.2:
+ version "1.3.2"
+ resolved "https://registry.yarnpkg.com/npm-audit-report/-/npm-audit-report-1.3.2.tgz#303bc78cd9e4c226415076a4f7e528c89fc77018"
+ integrity sha512-abeqS5ONyXNaZJPGAf6TOUMNdSe1Y6cpc9MLBRn+CuUoYbfdca6AxOyXVlfIv9OgKX+cacblbG5w7A6ccwoTPw==
+ dependencies:
+ cli-table3 "^0.5.0"
+ console-control-strings "^1.1.0"
+
+npm-bundled@^1.0.1:
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.6.tgz#e7ba9aadcef962bb61248f91721cd932b3fe6bdd"
+ integrity sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g==
+
+npm-cache-filename@~1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/npm-cache-filename/-/npm-cache-filename-1.0.2.tgz#ded306c5b0bfc870a9e9faf823bc5f283e05ae11"
+ integrity sha1-3tMGxbC/yHCp6fr4I7xfKD4FrhE=
+
+npm-install-checks@~3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/npm-install-checks/-/npm-install-checks-3.0.0.tgz#d4aecdfd51a53e3723b7b2f93b2ee28e307bc0d7"
+ integrity sha1-1K7N/VGlPjcjt7L5Oy7ijjB7wNc=
+ dependencies:
+ semver "^2.3.0 || 3.x || 4 || 5"
+
+npm-lifecycle@^2.0.3, npm-lifecycle@^2.1.0:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/npm-lifecycle/-/npm-lifecycle-2.1.1.tgz#0027c09646f0fd346c5c93377bdaba59c6748fdf"
+ integrity sha512-+Vg6I60Z75V/09pdcH5iUo/99Q/vop35PaI99elvxk56azSVVsdsSsS/sXqKDNwbRRNN1qSxkcO45ZOu0yOWew==
+ dependencies:
+ byline "^5.0.0"
+ graceful-fs "^4.1.15"
+ node-gyp "^4.0.0"
+ resolve-from "^4.0.0"
+ slide "^1.1.6"
+ uid-number "0.0.6"
+ umask "^1.1.0"
+ which "^1.3.1"
+
+npm-logical-tree@^1.2.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/npm-logical-tree/-/npm-logical-tree-1.2.1.tgz#44610141ca24664cad35d1e607176193fd8f5b88"
+ integrity sha512-AJI/qxDB2PWI4LG1CYN579AY1vCiNyWfkiquCsJWqntRu/WwimVrC8yXeILBFHDwxfOejxewlmnvW9XXjMlYIg==
+
+"npm-package-arg@^4.0.0 || ^5.0.0 || ^6.0.0", npm-package-arg@^6.0.0, npm-package-arg@^6.1.0:
+ version "6.1.0"
+ resolved "https://registry.yarnpkg.com/npm-package-arg/-/npm-package-arg-6.1.0.tgz#15ae1e2758a5027efb4c250554b85a737db7fcc1"
+ integrity sha512-zYbhP2k9DbJhA0Z3HKUePUgdB1x7MfIfKssC+WLPFMKTBZKpZh5m13PgexJjCq6KW7j17r0jHWcCpxEqnnncSA==
+ dependencies:
+ hosted-git-info "^2.6.0"
+ osenv "^0.1.5"
+ semver "^5.5.0"
+ validate-npm-package-name "^3.0.0"
+
+npm-packlist@^1.1.12, npm-packlist@^1.4.1:
+ version "1.4.1"
+ resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.1.tgz#19064cdf988da80ea3cee45533879d90192bbfbc"
+ integrity sha512-+TcdO7HJJ8peiiYhvPxsEDhF3PJFGUGRcFsGve3vxvxdcpO2Z4Z7rkosRM0kWj6LfbK/P0gu3dzk5RU1ffvFcw==
+ dependencies:
+ ignore-walk "^3.0.1"
+ npm-bundled "^1.0.1"
+
+npm-pick-manifest@^2.2.3:
+ version "2.2.3"
+ resolved "https://registry.yarnpkg.com/npm-pick-manifest/-/npm-pick-manifest-2.2.3.tgz#32111d2a9562638bb2c8f2bf27f7f3092c8fae40"
+ integrity sha512-+IluBC5K201+gRU85vFlUwX3PFShZAbAgDNp2ewJdWMVSppdo/Zih0ul2Ecky/X7b51J7LrrUAP+XOmOCvYZqA==
+ dependencies:
+ figgy-pudding "^3.5.1"
+ npm-package-arg "^6.0.0"
+ semver "^5.4.1"
+
+npm-profile@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/npm-profile/-/npm-profile-4.0.1.tgz#d350f7a5e6b60691c7168fbb8392c3603583f5aa"
+ integrity sha512-NQ1I/1Q7YRtHZXkcuU1/IyHeLy6pd+ScKg4+DQHdfsm769TGq6HPrkbuNJVJS4zwE+0mvvmeULzQdWn2L2EsVA==
+ dependencies:
+ aproba "^1.1.2 || 2"
+ figgy-pudding "^3.4.1"
+ npm-registry-fetch "^3.8.0"
+
+npm-registry-fetch@^3.8.0, npm-registry-fetch@^3.9.0:
+ version "3.9.0"
+ resolved "https://registry.yarnpkg.com/npm-registry-fetch/-/npm-registry-fetch-3.9.0.tgz#44d841780e2833f06accb34488f8c7450d1a6856"
+ integrity sha512-srwmt8YhNajAoSAaDWndmZgx89lJwIZ1GWxOuckH4Coek4uHv5S+o/l9FLQe/awA+JwTnj4FJHldxhlXdZEBmw==
+ dependencies:
+ JSONStream "^1.3.4"
+ bluebird "^3.5.1"
+ figgy-pudding "^3.4.1"
+ lru-cache "^4.1.3"
+ make-fetch-happen "^4.0.1"
+ npm-package-arg "^6.1.0"
+
npm-run-path@^2.0.0:
version "2.0.2"
resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f"
@@ -400,16 +2047,167 @@ npm-run-path@^2.0.0:
dependencies:
path-key "^2.0.0"
+npm-user-validate@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/npm-user-validate/-/npm-user-validate-1.0.0.tgz#8ceca0f5cea04d4e93519ef72d0557a75122e951"
+ integrity sha1-jOyg9c6gTU6TUZ73LQVXp1Ei6VE=
+
+npm@~6.9.0:
+ version "6.9.0"
+ resolved "https://registry.yarnpkg.com/npm/-/npm-6.9.0.tgz#5296720486814a64a7fb082de00c4b5cfd11211f"
+ integrity sha512-91V+zB5hDxO+Jyp2sUKS7juHlIM95dGQxTeQtmZI1nAI/7kjWXFipPrtwwKjhyKmV4GsS2LzJhrxRjGWsU9z/w==
+ dependencies:
+ JSONStream "^1.3.5"
+ abbrev "~1.1.1"
+ ansicolors "~0.3.2"
+ ansistyles "~0.1.3"
+ aproba "^2.0.0"
+ archy "~1.0.0"
+ bin-links "^1.1.2"
+ bluebird "^3.5.3"
+ byte-size "^5.0.1"
+ cacache "^11.3.2"
+ call-limit "~1.1.0"
+ chownr "^1.1.1"
+ ci-info "^2.0.0"
+ cli-columns "^3.1.2"
+ cli-table3 "^0.5.1"
+ cmd-shim "~2.0.2"
+ columnify "~1.5.4"
+ config-chain "^1.1.12"
+ detect-indent "~5.0.0"
+ detect-newline "^2.1.0"
+ dezalgo "~1.0.3"
+ editor "~1.0.0"
+ figgy-pudding "^3.5.1"
+ find-npm-prefix "^1.0.2"
+ fs-vacuum "~1.2.10"
+ fs-write-stream-atomic "~1.0.10"
+ gentle-fs "^2.0.1"
+ glob "^7.1.3"
+ graceful-fs "^4.1.15"
+ has-unicode "~2.0.1"
+ hosted-git-info "^2.7.1"
+ iferr "^1.0.2"
+ inflight "~1.0.6"
+ inherits "~2.0.3"
+ ini "^1.3.5"
+ init-package-json "^1.10.3"
+ is-cidr "^3.0.0"
+ json-parse-better-errors "^1.0.2"
+ lazy-property "~1.0.0"
+ libcipm "^3.0.3"
+ libnpm "^2.0.1"
+ libnpmhook "^5.0.2"
+ libnpx "^10.2.0"
+ lock-verify "^2.1.0"
+ lockfile "^1.0.4"
+ lodash._baseuniq "~4.6.0"
+ lodash.clonedeep "~4.5.0"
+ lodash.union "~4.6.0"
+ lodash.uniq "~4.5.0"
+ lodash.without "~4.4.0"
+ lru-cache "^4.1.5"
+ meant "~1.0.1"
+ mississippi "^3.0.0"
+ mkdirp "~0.5.1"
+ move-concurrently "^1.0.1"
+ node-gyp "^3.8.0"
+ nopt "~4.0.1"
+ normalize-package-data "^2.5.0"
+ npm-audit-report "^1.3.2"
+ npm-cache-filename "~1.0.2"
+ npm-install-checks "~3.0.0"
+ npm-lifecycle "^2.1.0"
+ npm-package-arg "^6.1.0"
+ npm-packlist "^1.4.1"
+ npm-pick-manifest "^2.2.3"
+ npm-registry-fetch "^3.9.0"
+ npm-user-validate "~1.0.0"
+ npmlog "~4.1.2"
+ once "~1.4.0"
+ opener "^1.5.1"
+ osenv "^0.1.5"
+ pacote "^9.5.0"
+ path-is-inside "~1.0.2"
+ promise-inflight "~1.0.1"
+ qrcode-terminal "^0.12.0"
+ query-string "^6.2.0"
+ qw "~1.0.1"
+ read "~1.0.7"
+ read-cmd-shim "~1.0.1"
+ read-installed "~4.0.3"
+ read-package-json "^2.0.13"
+ read-package-tree "^5.2.2"
+ readable-stream "^3.1.1"
+ request "^2.88.0"
+ retry "^0.12.0"
+ rimraf "^2.6.3"
+ safe-buffer "^5.1.2"
+ semver "^5.6.0"
+ sha "~2.0.1"
+ slide "~1.1.6"
+ sorted-object "~2.0.1"
+ sorted-union-stream "~2.1.3"
+ ssri "^6.0.1"
+ stringify-package "^1.0.0"
+ tar "^4.4.8"
+ text-table "~0.2.0"
+ tiny-relative-date "^1.3.0"
+ uid-number "0.0.6"
+ umask "~1.1.0"
+ unique-filename "^1.1.1"
+ unpipe "~1.0.0"
+ update-notifier "^2.5.0"
+ uuid "^3.3.2"
+ validate-npm-package-license "^3.0.4"
+ validate-npm-package-name "~3.0.0"
+ which "^1.3.1"
+ worker-farm "^1.6.0"
+ write-file-atomic "^2.4.2"
+
+"npmlog@0 || 1 || 2 || 3 || 4", npmlog@^4.1.2, npmlog@~4.1.2:
+ version "4.1.2"
+ resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b"
+ integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==
+ dependencies:
+ are-we-there-yet "~1.1.2"
+ console-control-strings "~1.1.0"
+ gauge "~2.7.3"
+ set-blocking "~2.0.0"
+
number-is-nan@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=
-object-assign@^4.0.1:
+oauth-sign@~0.9.0:
+ version "0.9.0"
+ resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455"
+ integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==
+
+object-assign@^4.0.1, object-assign@^4.1.0:
version "4.1.1"
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
+once@^1.3.0, once@^1.3.1, once@^1.4.0, once@~1.4.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
+ integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E=
+ dependencies:
+ wrappy "1"
+
+opener@^1.5.1:
+ version "1.5.1"
+ resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.1.tgz#6d2f0e77f1a0af0032aca716c2c1fbb8e7e8abed"
+ integrity sha512-goYSy5c2UXE4Ra1xixabeVh1guIX/ZV/YokJksb6q2lubWu6UbvPQ20p542/sFIll1nl8JnCyK9oBaOcCWXwvA==
+
+os-homedir@^1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3"
+ integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M=
+
os-locale@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-2.1.0.tgz#42bc2900a6b5b8bd17376c8e882b65afccf24bf2"
@@ -419,11 +2217,50 @@ os-locale@^2.0.0:
lcid "^1.0.0"
mem "^1.1.0"
+os-locale@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-3.1.0.tgz#a802a6ee17f24c10483ab9935719cef4ed16bf1a"
+ integrity sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==
+ dependencies:
+ execa "^1.0.0"
+ lcid "^2.0.0"
+ mem "^4.0.0"
+
+os-tmpdir@^1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
+ integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=
+
+osenv@0, osenv@^0.1.4, osenv@^0.1.5:
+ version "0.1.5"
+ resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410"
+ integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==
+ dependencies:
+ os-homedir "^1.0.0"
+ os-tmpdir "^1.0.0"
+
+p-defer@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c"
+ integrity sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=
+
p-finally@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae"
integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=
+p-is-promise@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-2.1.0.tgz#918cebaea248a62cf7ffab8e3bca8c5f882fc42e"
+ integrity sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==
+
+p-limit@^1.1.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8"
+ integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==
+ dependencies:
+ p-try "^1.0.0"
+
p-limit@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.0.0.tgz#e624ed54ee8c460a778b3c9f3670496ff8a57aec"
@@ -431,6 +2268,13 @@ p-limit@^2.0.0:
dependencies:
p-try "^2.0.0"
+p-locate@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43"
+ integrity sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=
+ dependencies:
+ p-limit "^1.1.0"
+
p-locate@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4"
@@ -438,28 +2282,98 @@ p-locate@^3.0.0:
dependencies:
p-limit "^2.0.0"
+p-try@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3"
+ integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=
+
p-try@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.0.0.tgz#85080bb87c64688fa47996fe8f7dfbe8211760b1"
integrity sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ==
-path-exists@^2.0.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b"
- integrity sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=
+package-json@^4.0.0:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/package-json/-/package-json-4.0.1.tgz#8869a0401253661c4c4ca3da6c2121ed555f5eed"
+ integrity sha1-iGmgQBJTZhxMTKPabCEh7VVfXu0=
dependencies:
- pinkie-promise "^2.0.0"
+ got "^6.7.1"
+ registry-auth-token "^3.0.1"
+ registry-url "^3.0.3"
+ semver "^5.1.0"
+
+pacote@^9.1.0, pacote@^9.2.3, pacote@^9.5.0:
+ version "9.5.0"
+ resolved "https://registry.yarnpkg.com/pacote/-/pacote-9.5.0.tgz#85f3013a3f6dd51c108b0ccabd3de8102ddfaeda"
+ integrity sha512-aUplXozRbzhaJO48FaaeClmN+2Mwt741MC6M3bevIGZwdCaP7frXzbUOfOWa91FPHoLITzG0hYaKY363lxO3bg==
+ dependencies:
+ bluebird "^3.5.3"
+ cacache "^11.3.2"
+ figgy-pudding "^3.5.1"
+ get-stream "^4.1.0"
+ glob "^7.1.3"
+ lru-cache "^5.1.1"
+ make-fetch-happen "^4.0.1"
+ minimatch "^3.0.4"
+ minipass "^2.3.5"
+ mississippi "^3.0.0"
+ mkdirp "^0.5.1"
+ normalize-package-data "^2.4.0"
+ npm-package-arg "^6.1.0"
+ npm-packlist "^1.1.12"
+ npm-pick-manifest "^2.2.3"
+ npm-registry-fetch "^3.8.0"
+ osenv "^0.1.5"
+ promise-inflight "^1.0.1"
+ promise-retry "^1.1.1"
+ protoduck "^5.0.1"
+ rimraf "^2.6.2"
+ safe-buffer "^5.1.2"
+ semver "^5.6.0"
+ ssri "^6.0.1"
+ tar "^4.4.8"
+ unique-filename "^1.1.1"
+ which "^1.3.1"
+
+pako@^1.0.7:
+ version "1.0.10"
+ resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.10.tgz#4328badb5086a426aa90f541977d4955da5c9732"
+ integrity sha512-0DTvPVU3ed8+HNXOu5Bs+o//Mbdj9VNQMUOe9oKCwh8l0GNwpTDMKCWbRjgtD291AWnkAgkqA/LOnQS8AmS1tw==
+
+parallel-transform@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/parallel-transform/-/parallel-transform-1.1.0.tgz#d410f065b05da23081fcd10f28854c29bda33b06"
+ integrity sha1-1BDwZbBdojCB/NEPKIVMKb2jOwY=
+ dependencies:
+ cyclist "~0.2.2"
+ inherits "^2.0.3"
+ readable-stream "^2.1.5"
path-exists@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515"
integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=
-path-key@^2.0.0:
+path-is-absolute@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
+ integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18=
+
+path-is-inside@^1.0.1, path-is-inside@^1.0.2, path-is-inside@~1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53"
+ integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=
+
+path-key@^2.0.0, path-key@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40"
integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=
+path-parse@^1.0.6:
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c"
+ integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==
+
path@0.12.7:
version "0.12.7"
resolved "https://registry.yarnpkg.com/path/-/path-0.12.7.tgz#d4dc2a506c4ce2197eb481ebfcd5b36c0140b10f"
@@ -468,35 +2382,288 @@ path@0.12.7:
process "^0.11.1"
util "^0.10.3"
-pinkie-promise@^2.0.0:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa"
- integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o=
- dependencies:
- pinkie "^2.0.0"
+performance-now@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
+ integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=
-pinkie@^2.0.0:
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870"
- integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA=
+pify@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176"
+ integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=
-pkg-up@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-1.0.0.tgz#3e08fb461525c4421624a33b9f7e6d0af5b05a26"
- integrity sha1-Pgj7RhUlxEIWJKM7n35tCvWwWiY=
+pkg-up@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-2.0.0.tgz#c819ac728059a461cab1c3889a2be3c49a004d7f"
+ integrity sha1-yBmscoBZpGHKscOImivjxJoATX8=
dependencies:
- find-up "^1.0.0"
+ find-up "^2.1.0"
+
+prepend-http@^1.0.1:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc"
+ integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=
+
+process-nextick-args@~2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa"
+ integrity sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==
process@^0.11.1:
version "0.11.10"
resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182"
integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI=
+promise-inflight@^1.0.1, promise-inflight@~1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3"
+ integrity sha1-mEcocL8igTL8vdhoEputEsPAKeM=
+
+promise-retry@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/promise-retry/-/promise-retry-1.1.1.tgz#6739e968e3051da20ce6497fb2b50f6911df3d6d"
+ integrity sha1-ZznpaOMFHaIM5kl/srUPaRHfPW0=
+ dependencies:
+ err-code "^1.0.0"
+ retry "^0.10.0"
+
+promzard@^0.3.0:
+ version "0.3.0"
+ resolved "https://registry.yarnpkg.com/promzard/-/promzard-0.3.0.tgz#26a5d6ee8c7dee4cb12208305acfb93ba382a9ee"
+ integrity sha1-JqXW7ox97kyxIggwWs+5O6OCqe4=
+ dependencies:
+ read "1"
+
+proto-list@~1.2.1:
+ version "1.2.4"
+ resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849"
+ integrity sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=
+
+protoduck@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/protoduck/-/protoduck-5.0.1.tgz#03c3659ca18007b69a50fd82a7ebcc516261151f"
+ integrity sha512-WxoCeDCoCBY55BMvj4cAEjdVUFGRWed9ZxPlqTKYyw1nDDTQ4pqmnIMAGfJlg7Dx35uB/M+PHJPTmGOvaCaPTg==
+ dependencies:
+ genfun "^5.0.0"
+
+prr@~1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476"
+ integrity sha1-0/wRS6BplaRexok/SEzrHXj19HY=
+
pseudomap@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3"
integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM=
+psl@^1.1.24:
+ version "1.1.32"
+ resolved "https://registry.yarnpkg.com/psl/-/psl-1.1.32.tgz#3f132717cf2f9c169724b2b6caf373cf694198db"
+ integrity sha512-MHACAkHpihU/REGGPLj4sEfc/XKW2bheigvHO1dUqjaKigMp1C8+WLQYRGgeKFMsw5PMfegZcaN8IDXK/cD0+g==
+
+pump@^2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/pump/-/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909"
+ integrity sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==
+ dependencies:
+ end-of-stream "^1.1.0"
+ once "^1.3.1"
+
+pump@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64"
+ integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==
+ dependencies:
+ end-of-stream "^1.1.0"
+ once "^1.3.1"
+
+pumpify@^1.3.3:
+ version "1.5.1"
+ resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-1.5.1.tgz#36513be246ab27570b1a374a5ce278bfd74370ce"
+ integrity sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==
+ dependencies:
+ duplexify "^3.6.0"
+ inherits "^2.0.3"
+ pump "^2.0.0"
+
+punycode@^1.4.1:
+ version "1.4.1"
+ resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e"
+ integrity sha1-wNWmOycYgArY4esPpSachN1BhF4=
+
+punycode@^2.1.0:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
+ integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
+
+qrcode-terminal@^0.12.0:
+ version "0.12.0"
+ resolved "https://registry.yarnpkg.com/qrcode-terminal/-/qrcode-terminal-0.12.0.tgz#bb5b699ef7f9f0505092a3748be4464fe71b5819"
+ integrity sha512-EXtzRZmC+YGmGlDFbXKxQiMZNwCLEO6BANKXG4iCtSIM0yqc/pappSx3RIKr4r0uh5JsBckOXeKrB3Iz7mdQpQ==
+
+qs@~6.5.2:
+ version "6.5.2"
+ resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36"
+ integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==
+
+query-string@^6.2.0:
+ version "6.6.0"
+ resolved "https://registry.yarnpkg.com/query-string/-/query-string-6.6.0.tgz#a6b7dfd57ad67e346b143d033df2b1e4cfb6b53a"
+ integrity sha512-Xhvaa80rZzfvI7gYXF6ism5otKTyea90XROstBTBKiWE/tDfnIDbQwkGLguJaQBNweVCW4T9DoTe5eyox0CbZQ==
+ dependencies:
+ decode-uri-component "^0.2.0"
+ split-on-first "^1.0.0"
+ strict-uri-encode "^2.0.0"
+
+qw@~1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/qw/-/qw-1.0.1.tgz#efbfdc740f9ad054304426acb183412cc8b996d4"
+ integrity sha1-77/cdA+a0FQwRCassYNBLMi5ltQ=
+
+rc@^1.0.1, rc@^1.1.6:
+ version "1.2.8"
+ resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed"
+ integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==
+ dependencies:
+ deep-extend "^0.6.0"
+ ini "~1.3.0"
+ minimist "^1.2.0"
+ strip-json-comments "~2.0.1"
+
+read-cmd-shim@^1.0.1, read-cmd-shim@~1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/read-cmd-shim/-/read-cmd-shim-1.0.1.tgz#2d5d157786a37c055d22077c32c53f8329e91c7b"
+ integrity sha1-LV0Vd4ajfAVdIgd8MsU/gynpHHs=
+ dependencies:
+ graceful-fs "^4.1.2"
+
+read-installed@~4.0.3:
+ version "4.0.3"
+ resolved "https://registry.yarnpkg.com/read-installed/-/read-installed-4.0.3.tgz#ff9b8b67f187d1e4c29b9feb31f6b223acd19067"
+ integrity sha1-/5uLZ/GH0eTCm5/rMfayI6zRkGc=
+ dependencies:
+ debuglog "^1.0.1"
+ read-package-json "^2.0.0"
+ readdir-scoped-modules "^1.0.0"
+ semver "2 || 3 || 4 || 5"
+ slide "~1.1.3"
+ util-extend "^1.0.1"
+ optionalDependencies:
+ graceful-fs "^4.1.2"
+
+"read-package-json@1 || 2", read-package-json@^2.0.0, read-package-json@^2.0.13:
+ version "2.0.13"
+ resolved "https://registry.yarnpkg.com/read-package-json/-/read-package-json-2.0.13.tgz#2e82ebd9f613baa6d2ebe3aa72cefe3f68e41f4a"
+ integrity sha512-/1dZ7TRZvGrYqE0UAfN6qQb5GYBsNcqS1C0tNK601CFOJmtHI7NIGXwetEPU/OtoFHZL3hDxm4rolFFVE9Bnmg==
+ dependencies:
+ glob "^7.1.1"
+ json-parse-better-errors "^1.0.1"
+ normalize-package-data "^2.0.0"
+ slash "^1.0.0"
+ optionalDependencies:
+ graceful-fs "^4.1.2"
+
+read-package-tree@^5.2.2:
+ version "5.2.2"
+ resolved "https://registry.yarnpkg.com/read-package-tree/-/read-package-tree-5.2.2.tgz#4b6a0ef2d943c1ea36a578214c9a7f6b7424f7a8"
+ integrity sha512-rW3XWUUkhdKmN2JKB4FL563YAgtINifso5KShykufR03nJ5loGFlkUMe1g/yxmqX073SoYYTsgXu7XdDinKZuA==
+ dependencies:
+ debuglog "^1.0.1"
+ dezalgo "^1.0.0"
+ once "^1.3.0"
+ read-package-json "^2.0.0"
+ readdir-scoped-modules "^1.0.0"
+
+read@1, read@~1.0.1, read@~1.0.7:
+ version "1.0.7"
+ resolved "https://registry.yarnpkg.com/read/-/read-1.0.7.tgz#b3da19bd052431a97671d44a42634adf710b40c4"
+ integrity sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ=
+ dependencies:
+ mute-stream "~0.0.4"
+
+"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.6, readable-stream@~2.3.6:
+ version "2.3.6"
+ resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf"
+ integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==
+ dependencies:
+ core-util-is "~1.0.0"
+ inherits "~2.0.3"
+ isarray "~1.0.0"
+ process-nextick-args "~2.0.0"
+ safe-buffer "~5.1.1"
+ string_decoder "~1.1.1"
+ util-deprecate "~1.0.1"
+
+readable-stream@^3.1.1:
+ version "3.4.0"
+ resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.4.0.tgz#a51c26754658e0a3c21dbf59163bd45ba6f447fc"
+ integrity sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ==
+ dependencies:
+ inherits "^2.0.3"
+ string_decoder "^1.1.1"
+ util-deprecate "^1.0.1"
+
+readable-stream@~1.1.10:
+ version "1.1.14"
+ resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9"
+ integrity sha1-fPTFTvZI44EwhMY23SB54WbAgdk=
+ dependencies:
+ core-util-is "~1.0.0"
+ inherits "~2.0.1"
+ isarray "0.0.1"
+ string_decoder "~0.10.x"
+
+readdir-scoped-modules@^1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/readdir-scoped-modules/-/readdir-scoped-modules-1.0.2.tgz#9fafa37d286be5d92cbaebdee030dc9b5f406747"
+ integrity sha1-n6+jfShr5dksuuve4DDcm19AZ0c=
+ dependencies:
+ debuglog "^1.0.1"
+ dezalgo "^1.0.0"
+ graceful-fs "^4.1.2"
+ once "^1.3.0"
+
+registry-auth-token@^3.0.1:
+ version "3.4.0"
+ resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-3.4.0.tgz#d7446815433f5d5ed6431cd5dca21048f66b397e"
+ integrity sha512-4LM6Fw8eBQdwMYcES4yTnn2TqIasbXuwDx3um+QRs7S55aMKCBKBxvPXl2RiUjHwuJLTyYfxSpmfSAjQpcuP+A==
+ dependencies:
+ rc "^1.1.6"
+ safe-buffer "^5.0.1"
+
+registry-url@^3.0.3:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-3.1.0.tgz#3d4ef870f73dde1d77f0cf9a381432444e174942"
+ integrity sha1-PU74cPc93h138M+aOBQyRE4XSUI=
+ dependencies:
+ rc "^1.0.1"
+
+request@^2.87.0, request@^2.88.0:
+ version "2.88.0"
+ resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef"
+ integrity sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==
+ dependencies:
+ aws-sign2 "~0.7.0"
+ aws4 "^1.8.0"
+ caseless "~0.12.0"
+ combined-stream "~1.0.6"
+ extend "~3.0.2"
+ forever-agent "~0.6.1"
+ form-data "~2.3.2"
+ har-validator "~5.1.0"
+ http-signature "~1.2.0"
+ is-typedarray "~1.0.0"
+ isstream "~0.1.2"
+ json-stringify-safe "~5.0.1"
+ mime-types "~2.1.19"
+ oauth-sign "~0.9.0"
+ performance-now "^2.1.0"
+ qs "~6.5.2"
+ safe-buffer "^5.1.2"
+ tough-cookie "~2.4.3"
+ tunnel-agent "^0.6.0"
+ uuid "^3.3.2"
+
require-directory@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
@@ -507,18 +2674,104 @@ require-main-filename@^1.0.1:
resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1"
integrity sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=
-rxjs@^6.3.3:
- version "6.3.3"
- resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.3.3.tgz#3c6a7fa420e844a81390fb1158a9ec614f4bad55"
- integrity sha512-JTWmoY9tWCs7zvIk/CvRjhjGaOd+OVBM987mxFo+OW66cGpdKjZcpmc74ES1sB//7Kl/PAe8+wEakuhG4pcgOw==
+require-main-filename@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b"
+ integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==
+
+resolve-from@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6"
+ integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==
+
+resolve@^1.10.0:
+ version "1.11.1"
+ resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.11.1.tgz#ea10d8110376982fef578df8fc30b9ac30a07a3e"
+ integrity sha512-vIpgF6wfuJOZI7KKKSP+HmiKggadPQAdsp5HiC1mvqnfp0gF1vdwgBWZIdrVft9pgqoMFQN+R7BSWZiBxx+BBw==
+ dependencies:
+ path-parse "^1.0.6"
+
+retry@^0.10.0:
+ version "0.10.1"
+ resolved "https://registry.yarnpkg.com/retry/-/retry-0.10.1.tgz#e76388d217992c252750241d3d3956fed98d8ff4"
+ integrity sha1-52OI0heZLCUnUCQdPTlW/tmNj/Q=
+
+retry@^0.12.0:
+ version "0.12.0"
+ resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b"
+ integrity sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=
+
+rimraf@2, rimraf@^2.5.2, rimraf@^2.5.4, rimraf@^2.6.2, rimraf@^2.6.3:
+ version "2.6.3"
+ resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab"
+ integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==
+ dependencies:
+ glob "^7.1.3"
+
+run-queue@^1.0.0, run-queue@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/run-queue/-/run-queue-1.0.3.tgz#e848396f057d223f24386924618e25694161ec47"
+ integrity sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=
+ dependencies:
+ aproba "^1.1.1"
+
+rxjs-compat@^6.5.2:
+ version "6.5.2"
+ resolved "https://registry.yarnpkg.com/rxjs-compat/-/rxjs-compat-6.5.2.tgz#e469070adf6260bdad195e9d4a39f444ae28b458"
+ integrity sha512-TRMkTp4FgSxE2HtGvxmgRukh3JqdFM7ejAj1Ti/VdodbPGfWvZR5+KdLKRV9jVDFyu2SknM8RD+PR54KGnoLjg==
+
+rxjs@^6.5.2:
+ version "6.5.2"
+ resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.2.tgz#2e35ce815cd46d84d02a209fb4e5921e051dbec7"
+ integrity sha512-HUb7j3kvb7p7eCUHE3FqjoDsC1xfZQ4AHFWfTKSpZ+sAhhz5X1WX0ZuUqWbzB2QhSLp3DoLUG+hMdEDKqWo2Zg==
dependencies:
tslib "^1.9.0"
-set-blocking@^2.0.0:
+safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, 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#991ec69d296e0313747d59bdfd2b745c35f8828d"
+ integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
+
+"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0:
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
+ integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
+
+sax@^1.2.4:
+ version "1.2.4"
+ resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
+ integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==
+
+semver-diff@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-2.1.0.tgz#4bbb8437c8d37e4b0cf1a68fd726ec6d645d6d36"
+ integrity sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY=
+ dependencies:
+ semver "^5.0.3"
+
+"semver@2 || 3 || 4 || 5", "semver@2.x || 3.x || 4 || 5", "semver@^2.3.0 || 3.x || 4 || 5", semver@^5.0.3, semver@^5.1.0, semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0:
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.0.tgz#790a7cf6fea5459bac96110b29b60412dc8ff96b"
+ integrity sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==
+
+semver@~5.3.0:
+ version "5.3.0"
+ resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f"
+ integrity sha1-myzl094C0XxgEq0yaqa00M9U+U8=
+
+set-blocking@^2.0.0, set-blocking@~2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc=
+sha@~2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/sha/-/sha-2.0.1.tgz#6030822fbd2c9823949f8f72ed6411ee5cf25aae"
+ integrity sha1-YDCCL70smCOUn49y7WQR7lzyWq4=
+ dependencies:
+ graceful-fs "^4.1.2"
+ readable-stream "^2.0.2"
+
shebang-command@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"
@@ -531,16 +2784,152 @@ shebang-regex@^1.0.0:
resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3"
integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=
-signal-exit@^3.0.0:
+signal-exit@^3.0.0, signal-exit@^3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d"
integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=
+slash@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55"
+ integrity sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=
+
+slide@^1.1.6, slide@~1.1.3, slide@~1.1.6:
+ version "1.1.6"
+ resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707"
+ integrity sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=
+
+smart-buffer@4.0.2:
+ version "4.0.2"
+ resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.0.2.tgz#5207858c3815cc69110703c6b94e46c15634395d"
+ integrity sha512-JDhEpTKzXusOqXZ0BUIdH+CjFdO/CR3tLlf5CN34IypI+xMmXW1uB16OOY8z3cICbJlDAVJzNbwBhNO0wt9OAw==
+
+socks-proxy-agent@^4.0.0:
+ version "4.0.2"
+ resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-4.0.2.tgz#3c8991f3145b2799e70e11bd5fbc8b1963116386"
+ integrity sha512-NT6syHhI9LmuEMSK6Kd2V7gNv5KFZoLE7V5udWmn0de+3Mkj3UMA/AJPLyeNUVmElCurSHtUdM3ETpR3z770Wg==
+ dependencies:
+ agent-base "~4.2.1"
+ socks "~2.3.2"
+
+socks@~2.3.2:
+ version "2.3.2"
+ resolved "https://registry.yarnpkg.com/socks/-/socks-2.3.2.tgz#ade388e9e6d87fdb11649c15746c578922a5883e"
+ integrity sha512-pCpjxQgOByDHLlNqlnh/mNSAxIUkyBBuwwhTcV+enZGbDaClPvHdvm6uvOwZfFJkam7cGhBNbb4JxiP8UZkRvQ==
+ dependencies:
+ ip "^1.1.5"
+ smart-buffer "4.0.2"
+
+sorted-object@~2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/sorted-object/-/sorted-object-2.0.1.tgz#7d631f4bd3a798a24af1dffcfbfe83337a5df5fc"
+ integrity sha1-fWMfS9OnmKJK8d/8+/6DM3pd9fw=
+
+sorted-union-stream@~2.1.3:
+ version "2.1.3"
+ resolved "https://registry.yarnpkg.com/sorted-union-stream/-/sorted-union-stream-2.1.3.tgz#c7794c7e077880052ff71a8d4a2dbb4a9a638ac7"
+ integrity sha1-x3lMfgd4gAUv9xqNSi27Sppjisc=
+ dependencies:
+ from2 "^1.3.0"
+ stream-iterate "^1.1.0"
+
+source-map-support@^0.5.9:
+ version "0.5.12"
+ resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.12.tgz#b4f3b10d51857a5af0138d3ce8003b201613d599"
+ integrity sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ==
+ dependencies:
+ buffer-from "^1.0.0"
+ source-map "^0.6.0"
+
+source-map@^0.6.0:
+ version "0.6.1"
+ resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
+ integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
+
+spdx-correct@^3.0.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.0.tgz#fb83e504445268f154b074e218c87c003cd31df4"
+ integrity sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==
+ dependencies:
+ spdx-expression-parse "^3.0.0"
+ spdx-license-ids "^3.0.0"
+
+spdx-exceptions@^2.1.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz#2ea450aee74f2a89bfb94519c07fcd6f41322977"
+ integrity sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==
+
+spdx-expression-parse@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0"
+ integrity sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==
+ dependencies:
+ spdx-exceptions "^2.1.0"
+ spdx-license-ids "^3.0.0"
+
+spdx-license-ids@^3.0.0:
+ version "3.0.4"
+ resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.4.tgz#75ecd1a88de8c184ef015eafb51b5b48bfd11bb1"
+ integrity sha512-7j8LYJLeY/Yb6ACbQ7F76qy5jHkp0U6jgBfJsk97bwWlVUnUWsAgpyaCvo17h0/RQGnQ036tVDomiwoI4pDkQA==
+
+split-on-first@^1.0.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/split-on-first/-/split-on-first-1.1.0.tgz#f610afeee3b12bce1d0c30425e76398b78249a5f"
+ integrity sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==
+
sprintf-js@~1.0.2:
version "1.0.3"
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=
+sshpk@^1.7.0:
+ version "1.16.1"
+ resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877"
+ integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==
+ dependencies:
+ asn1 "~0.2.3"
+ assert-plus "^1.0.0"
+ bcrypt-pbkdf "^1.0.0"
+ dashdash "^1.12.0"
+ ecc-jsbn "~0.1.1"
+ getpass "^0.1.1"
+ jsbn "~0.1.0"
+ safer-buffer "^2.0.2"
+ tweetnacl "~0.14.0"
+
+ssri@^6.0.0, ssri@^6.0.1:
+ version "6.0.1"
+ resolved "https://registry.yarnpkg.com/ssri/-/ssri-6.0.1.tgz#2a3c41b28dd45b62b63676ecb74001265ae9edd8"
+ integrity sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==
+ dependencies:
+ figgy-pudding "^3.5.1"
+
+stream-each@^1.1.0:
+ version "1.2.3"
+ resolved "https://registry.yarnpkg.com/stream-each/-/stream-each-1.2.3.tgz#ebe27a0c389b04fbcc233642952e10731afa9bae"
+ integrity sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==
+ dependencies:
+ end-of-stream "^1.1.0"
+ stream-shift "^1.0.0"
+
+stream-iterate@^1.1.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/stream-iterate/-/stream-iterate-1.2.0.tgz#2bd7c77296c1702a46488b8ad41f79865eecd4e1"
+ integrity sha1-K9fHcpbBcCpGSIuK1B95hl7s1OE=
+ dependencies:
+ readable-stream "^2.1.5"
+ stream-shift "^1.0.0"
+
+stream-shift@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.0.tgz#d5c752825e5367e786f78e18e445ea223a155952"
+ integrity sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=
+
+strict-uri-encode@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546"
+ integrity sha1-ucczDHBChi9rFC3CdLvMWGbONUY=
+
string-width@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3"
@@ -550,7 +2939,7 @@ string-width@^1.0.1:
is-fullwidth-code-point "^1.0.0"
strip-ansi "^3.0.0"
-string-width@^2.0.0, string-width@^2.1.1:
+"string-width@^1.0.2 || 2", string-width@^2.0.0, string-width@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e"
integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==
@@ -558,6 +2947,39 @@ string-width@^2.0.0, string-width@^2.1.1:
is-fullwidth-code-point "^2.0.0"
strip-ansi "^4.0.0"
+string-width@^3.0.0, string-width@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961"
+ integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==
+ dependencies:
+ emoji-regex "^7.0.1"
+ is-fullwidth-code-point "^2.0.0"
+ strip-ansi "^5.1.0"
+
+string_decoder@^1.1.1:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.2.0.tgz#fe86e738b19544afe70469243b2a1ee9240eae8d"
+ integrity sha512-6YqyX6ZWEYguAxgZzHGL7SsCeGx3V2TtOTqZz1xSTSWnqsbWwbptafNyvf/ACquZUXV3DANr5BDIwNYe1mN42w==
+ dependencies:
+ safe-buffer "~5.1.0"
+
+string_decoder@~0.10.x:
+ version "0.10.31"
+ resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94"
+ integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=
+
+string_decoder@~1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8"
+ integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==
+ dependencies:
+ safe-buffer "~5.1.0"
+
+stringify-package@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/stringify-package/-/stringify-package-1.0.0.tgz#e02828089333d7d45cd8c287c30aa9a13375081b"
+ integrity sha512-JIQqiWmLiEozOC0b0BtxZ/AOUtdUZHCBPgqIZ2kSJJqGwgb9neo44XdTHUC4HZSGqi03hOeB7W/E8rAlKnGe9g==
+
strip-ansi@^3.0.0, strip-ansi@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf"
@@ -572,11 +2994,64 @@ strip-ansi@^4.0.0:
dependencies:
ansi-regex "^3.0.0"
+strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0:
+ version "5.2.0"
+ resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae"
+ integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==
+ dependencies:
+ ansi-regex "^4.1.0"
+
strip-eof@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf"
integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=
+strip-json-comments@~2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
+ integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo=
+
+supports-color@^5.3.0:
+ version "5.5.0"
+ resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
+ integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==
+ dependencies:
+ has-flag "^3.0.0"
+
+tar@^2.0.0:
+ version "2.2.2"
+ resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.2.tgz#0ca8848562c7299b8b446ff6a4d60cdbb23edc40"
+ integrity sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA==
+ dependencies:
+ block-stream "*"
+ fstream "^1.0.12"
+ inherits "2"
+
+tar@^4.4.8:
+ version "4.4.10"
+ resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.10.tgz#946b2810b9a5e0b26140cf78bea6b0b0d689eba1"
+ integrity sha512-g2SVs5QIxvo6OLp0GudTqEf05maawKUxXru104iaayWA09551tFCTI8f1Asb4lPfkBr91k07iL4c11XO3/b0tA==
+ dependencies:
+ chownr "^1.1.1"
+ fs-minipass "^1.2.5"
+ minipass "^2.3.5"
+ minizlib "^1.2.1"
+ mkdirp "^0.5.0"
+ safe-buffer "^5.1.2"
+ yallist "^3.0.3"
+
+term-size@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/term-size/-/term-size-1.2.0.tgz#458b83887f288fc56d6fffbfad262e26638efa69"
+ integrity sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk=
+ dependencies:
+ execa "^0.7.0"
+
+text-table@~0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
+ integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=
+
thenify-all@^1.0.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/thenify-all/-/thenify-all-1.6.0.tgz#1a1918d402d8fc3f98fbf234db0bcc8cc10e9726"
@@ -591,11 +3066,145 @@ thenify-all@^1.0.0:
dependencies:
any-promise "^1.0.0"
+through2@^2.0.0:
+ version "2.0.5"
+ resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd"
+ integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==
+ dependencies:
+ readable-stream "~2.3.6"
+ xtend "~4.0.1"
+
+"through@>=2.2.7 <3":
+ version "2.3.8"
+ resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
+ integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=
+
+timed-out@^4.0.0:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f"
+ integrity sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=
+
+tiny-relative-date@^1.3.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/tiny-relative-date/-/tiny-relative-date-1.3.0.tgz#fa08aad501ed730f31cc043181d995c39a935e07"
+ integrity sha512-MOQHpzllWxDCHHaDno30hhLfbouoYlOI8YlMNtvKe1zXbjEVhbcEovQxvZrPvtiYW630GQDoMMarCnjfyfHA+A==
+
+tough-cookie@~2.4.3:
+ version "2.4.3"
+ resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781"
+ integrity sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==
+ dependencies:
+ psl "^1.1.24"
+ punycode "^1.4.1"
+
tslib@^1.9.0:
version "1.9.1"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.1.tgz#a5d1f0532a49221c87755cfcc89ca37197242ba7"
integrity sha512-avfPS28HmGLLc2o4elcc2EIq2FcH++Yo5YxpBZi9Yw93BCTGFthI4HPE4Rpep6vSYQaK8e69PelM44tPj+RaQg==
+tunnel-agent@^0.6.0:
+ version "0.6.0"
+ resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd"
+ integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=
+ dependencies:
+ safe-buffer "^5.0.1"
+
+tweetnacl@^0.14.3, tweetnacl@~0.14.0:
+ version "0.14.5"
+ resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
+ integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=
+
+typedarray@^0.0.6:
+ version "0.0.6"
+ resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
+ integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
+
+uid-number@0.0.6:
+ version "0.0.6"
+ resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81"
+ integrity sha1-DqEOgDXo61uOREnwbaHHMGY7qoE=
+
+umask@^1.1.0, umask@~1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/umask/-/umask-1.1.0.tgz#f29cebf01df517912bb58ff9c4e50fde8e33320d"
+ integrity sha1-8pzr8B31F5ErtY/5xOUP3o4zMg0=
+
+unique-filename@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-1.1.1.tgz#1d69769369ada0583103a1e6ae87681b56573230"
+ integrity sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==
+ dependencies:
+ unique-slug "^2.0.0"
+
+unique-slug@^2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-2.0.1.tgz#5e9edc6d1ce8fb264db18a507ef9bd8544451ca6"
+ integrity sha512-n9cU6+gITaVu7VGj1Z8feKMmfAjEAQGhwD9fE3zvpRRa0wEIx8ODYkVGfSc94M2OX00tUFV8wH3zYbm1I8mxFg==
+ dependencies:
+ imurmurhash "^0.1.4"
+
+unique-string@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-1.0.0.tgz#9e1057cca851abb93398f8b33ae187b99caec11a"
+ integrity sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo=
+ dependencies:
+ crypto-random-string "^1.0.0"
+
+universalify@^0.1.0:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66"
+ integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==
+
+unpipe@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
+ integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=
+
+unzip-response@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/unzip-response/-/unzip-response-2.0.1.tgz#d2f0f737d16b0615e72a6935ed04214572d56f97"
+ integrity sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c=
+
+update-notifier@^2.3.0, update-notifier@^2.5.0:
+ version "2.5.0"
+ resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-2.5.0.tgz#d0744593e13f161e406acb1d9408b72cad08aff6"
+ integrity sha512-gwMdhgJHGuj/+wHJJs9e6PcCszpxR1b236igrOkUofGhqJuG+amlIKwApH1IW1WWl7ovZxsX49lMBWLxSdm5Dw==
+ dependencies:
+ boxen "^1.2.1"
+ chalk "^2.0.1"
+ configstore "^3.0.0"
+ import-lazy "^2.1.0"
+ is-ci "^1.0.10"
+ is-installed-globally "^0.1.0"
+ is-npm "^1.0.0"
+ latest-version "^3.0.0"
+ semver-diff "^2.0.0"
+ xdg-basedir "^3.0.0"
+
+uri-js@^4.2.2:
+ version "4.2.2"
+ resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0"
+ integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==
+ dependencies:
+ punycode "^2.1.0"
+
+url-parse-lax@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-1.0.0.tgz#7af8f303645e9bd79a272e7a14ac68bc0609da73"
+ integrity sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=
+ dependencies:
+ prepend-http "^1.0.1"
+
+util-deprecate@^1.0.1, util-deprecate@~1.0.1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
+ integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
+
+util-extend@^1.0.1:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/util-extend/-/util-extend-1.0.3.tgz#a7c216d267545169637b3b6edc6ca9119e2ff93f"
+ integrity sha1-p8IW0mdUUWljeztu3GypEZ4v+T8=
+
util@^0.10.3:
version "0.10.3"
resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9"
@@ -603,27 +3212,86 @@ util@^0.10.3:
dependencies:
inherits "2.0.1"
+uuid@^3.3.2:
+ version "3.3.2"
+ resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131"
+ integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==
+
+validate-npm-package-license@^3.0.1, validate-npm-package-license@^3.0.4:
+ version "3.0.4"
+ resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a"
+ integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==
+ dependencies:
+ spdx-correct "^3.0.0"
+ spdx-expression-parse "^3.0.0"
+
+validate-npm-package-name@^3.0.0, validate-npm-package-name@~3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz#5fa912d81eb7d0c74afc140de7317f0ca7df437e"
+ integrity sha1-X6kS2B630MdK/BQN5zF/DKffQ34=
+ dependencies:
+ builtins "^1.0.3"
+
+verror@1.10.0:
+ version "1.10.0"
+ resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400"
+ integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=
+ dependencies:
+ assert-plus "^1.0.0"
+ core-util-is "1.0.2"
+ extsprintf "^1.2.0"
+
+wcwidth@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8"
+ integrity sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=
+ dependencies:
+ defaults "^1.0.3"
+
which-module@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a"
integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=
-which@^1.2.9:
+which@1, which@^1.2.9, which@^1.3.0, which@^1.3.1:
version "1.3.1"
resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==
dependencies:
isexe "^2.0.0"
-windows-blurbehind@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/windows-blurbehind/-/windows-blurbehind-1.0.0.tgz#050efb988704c44335bdc3efefd757f6e463b8ac"
- integrity sha512-lO+A7fhTHO7oy9zJM3o1AdzfSQrmtPkdwvleeuww840ghijjEA1f1Zp8bKA3mJu2DFNtVT40fwmqtgsCGat4UA==
+wide-align@^1.1.0:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457"
+ integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==
+ dependencies:
+ string-width "^1.0.2 || 2"
-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==
+widest-line@^2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-2.0.1.tgz#7438764730ec7ef4381ce4df82fb98a53142a3fc"
+ integrity sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA==
+ dependencies:
+ string-width "^2.1.1"
+
+windows-blurbehind@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/windows-blurbehind/-/windows-blurbehind-1.0.1.tgz#ff098713873304e38330b2c54cc41bb369b587b9"
+ integrity sha512-1HzHfCiM1ayrbACJu5qE9zELV24uX/tINT6kxaZwLY3rtQAoeav6x9z7LFHWoLaGDN/sYbnK+9Vk0cz7fsk5HQ==
+
+windows-swca@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/windows-swca/-/windows-swca-2.0.2.tgz#66807012f73f5d3c0f0cb49bfa61be297aaabb50"
+ integrity sha512-9935KGV1gH3EBy7re9UEfDrxY3fbXBcwrUgEZk1exxe6swcGKFhO82ECh4QXVBjIhq+ROIVW3SBF/OUnZFSNGw==
+ dependencies:
+ "@types/node" "^10.12.18"
+
+worker-farm@^1.6.0:
+ version "1.7.0"
+ resolved "https://registry.yarnpkg.com/worker-farm/-/worker-farm-1.7.0.tgz#26a94c5391bbca926152002f69b84a4bf772e5a8"
+ integrity sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==
+ dependencies:
+ errno "~0.1.7"
wrap-ansi@^2.0.0:
version "2.1.0"
@@ -633,12 +3301,45 @@ wrap-ansi@^2.0.0:
string-width "^1.0.1"
strip-ansi "^3.0.1"
-xregexp@4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-4.0.0.tgz#e698189de49dd2a18cc5687b05e17c8e43943020"
- integrity sha512-PHyM+sQouu7xspQQwELlGwwd05mXUFqwFYfqPO0cC7x4fxyHnnuetmQr6CjJiafIDoH4MogHb9dOoJzR/Y4rFg==
+wrap-ansi@^5.1.0:
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09"
+ integrity sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==
+ dependencies:
+ ansi-styles "^3.2.0"
+ string-width "^3.0.0"
+ strip-ansi "^5.0.0"
-"y18n@^3.2.1 || ^4.0.0":
+wrappy@1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
+ integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
+
+write-file-atomic@^2.0.0, write-file-atomic@^2.3.0, write-file-atomic@^2.4.2:
+ version "2.4.3"
+ resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.4.3.tgz#1fd2e9ae1df3e75b8d8c367443c692d4ca81f481"
+ integrity sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==
+ dependencies:
+ graceful-fs "^4.1.11"
+ imurmurhash "^0.1.4"
+ signal-exit "^3.0.2"
+
+xdg-basedir@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-3.0.0.tgz#496b2cc109eca8dbacfe2dc72b603c17c5870ad4"
+ integrity sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ=
+
+xtend@~4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af"
+ integrity sha1-pcbVMr5lbiPbgg77lDofBJmNY68=
+
+y18n@^3.2.1:
+ version "3.2.1"
+ resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41"
+ integrity sha1-bRX7qITAhnnA136I53WegR4H+kE=
+
+y18n@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b"
integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==
@@ -648,21 +3349,34 @@ yallist@^2.1.2:
resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52"
integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=
-yargs-parser@^10.1.0:
- version "10.1.0"
- resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-10.1.0.tgz#7202265b89f7e9e9f2e5765e0fe735a905edbaa8"
- integrity sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ==
+yallist@^3.0.0, yallist@^3.0.2, yallist@^3.0.3:
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.3.tgz#b4b049e314be545e3ce802236d6cd22cd91c3de9"
+ integrity sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==
+
+yargs-parser@^13.1.0:
+ version "13.1.0"
+ resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.0.tgz#7016b6dd03e28e1418a510e258be4bff5a31138f"
+ integrity sha512-Yq+32PrijHRri0vVKQEm+ys8mbqWjLiwQkMFNXEENutzLPP0bE4Lcd4iA3OQY5HF+GD3xXxf0MEHb8E4/SA3AA==
+ dependencies:
+ camelcase "^5.0.0"
+ decamelize "^1.2.0"
+
+yargs-parser@^9.0.2:
+ version "9.0.2"
+ resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-9.0.2.tgz#9ccf6a43460fe4ed40a9bb68f48d43b8a68cc077"
+ integrity sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc=
dependencies:
camelcase "^4.1.0"
-yargs@^12.0.1:
- version "12.0.1"
- resolved "https://registry.yarnpkg.com/yargs/-/yargs-12.0.1.tgz#6432e56123bb4e7c3562115401e98374060261c2"
- integrity sha512-B0vRAp1hRX4jgIOWFtjfNjd9OA9RWYZ6tqGA9/I/IrTMsxmKvtWy+ersM+jzpQqbC3YfLzeABPdeTgcJ9eu1qQ==
+yargs@^11.0.0:
+ version "11.1.0"
+ resolved "https://registry.yarnpkg.com/yargs/-/yargs-11.1.0.tgz#90b869934ed6e871115ea2ff58b03f4724ed2d77"
+ integrity sha512-NwW69J42EsCSanF8kyn5upxvjp5ds+t3+udGBeTbFnERA+lF541DDpMawzo4z6W/QrzNM18D+BPMiOBibnFV5A==
dependencies:
cliui "^4.0.0"
- decamelize "^2.0.0"
- find-up "^3.0.0"
+ decamelize "^1.1.1"
+ find-up "^2.1.0"
get-caller-file "^1.0.1"
os-locale "^2.0.0"
require-directory "^2.1.1"
@@ -670,10 +3384,27 @@ yargs@^12.0.1:
set-blocking "^2.0.0"
string-width "^2.0.0"
which-module "^2.0.0"
- y18n "^3.2.1 || ^4.0.0"
- yargs-parser "^10.1.0"
+ y18n "^3.2.1"
+ yargs-parser "^9.0.2"
-zone.js@^0.8.26:
- version "0.8.26"
- resolved "https://registry.yarnpkg.com/zone.js/-/zone.js-0.8.26.tgz#7bdd72f7668c5a7ad6b118148b4ea39c59d08d2d"
- integrity sha512-W9Nj+UmBJG251wkCacIkETgra4QgBo/vgoEkb4a2uoLzpQG7qF9nzwoLXWU5xj3Fg2mxGvEDh47mg24vXccYjA==
+yargs@^13.2.4:
+ version "13.2.4"
+ resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.2.4.tgz#0b562b794016eb9651b98bd37acf364aa5d6dc83"
+ integrity sha512-HG/DWAJa1PAnHT9JAhNa8AbAv3FPaiLzioSjCcmuXXhP8MlpHO5vwls4g4j6n30Z74GVQj8Xa62dWVx1QCGklg==
+ dependencies:
+ cliui "^5.0.0"
+ find-up "^3.0.0"
+ get-caller-file "^2.0.1"
+ os-locale "^3.1.0"
+ require-directory "^2.1.1"
+ require-main-filename "^2.0.0"
+ set-blocking "^2.0.0"
+ string-width "^3.0.0"
+ which-module "^2.0.0"
+ y18n "^4.0.0"
+ yargs-parser "^13.1.0"
+
+zone.js@^0.8.29:
+ version "0.8.29"
+ resolved "https://registry.yarnpkg.com/zone.js/-/zone.js-0.8.29.tgz#8dce92aa0dd553b50bc5bfbb90af9986ad845a12"
+ integrity sha512-mla2acNCMkWXBD+c+yeUrBUrzOxYMNFdQ6FGfigGGtEVBPJx07BQeJekjt9DmH1FtZek4E9rE1eRR9qQpxACOQ==
diff --git a/appveyor.yml b/appveyor.yml
index d1e13a32..84c2bdfb 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -6,23 +6,24 @@ platform:
environment:
nodejs_version: "10"
-cache:
- - '%USERPROFILE%\.electron'
-
version: "{build}"
install:
- ps: Install-Product node $env:nodejs_version $env:platform
- - npm install
- - node scripts/install-deps.js
+ - yarn
- node scripts/build-native.js
build_script:
- - npm run build
+ - yarn run build:typings
+ - yarn run build
- node scripts/prepackage-plugins.js
- node scripts/build-windows.js
artifacts:
- - path: 'dist\win\*.exe'
- - path: 'dist\squirrel-windows\*.exe'
- path: 'dist\*.exe'
+
+cache:
+ - node_modules
+ - "*\\node_modules"
+ - "%USERPROFILE%\\.electron"
+ - "%LOCALAPPDATA%\\Yarn"
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
new file mode 100644
index 00000000..b2edded0
--- /dev/null
+++ b/azure-pipelines.yml
@@ -0,0 +1,209 @@
+trigger:
+- master
+
+variables:
+- group: Vars
+
+jobs:
+- job: Windows
+ pool:
+ vmImage: 'vs2017-win2016'
+
+ steps:
+ - task: NodeTool@0
+ inputs:
+ versionSpec: '10.x'
+ displayName: 'Install Node.js'
+
+ - script: yarn
+ displayName: 'Install dependencies'
+
+ - script: node scripts/build-native.js
+ displayName: 'Rebuild native dependencies'
+
+ - script: yarn run build:typings
+ displayName: 'Build typings'
+
+ - script: yarn run build
+ displayName: 'Build'
+
+ - script: node scripts/prepackage-plugins.js
+ displayName: 'Prepackage plugins'
+
+ - script: node scripts/build-windows.js
+ displayName: 'Package'
+ env:
+ WIN_CSC_LINK: $(WIN_CSC_LINK)
+ WIN_CSC_KEY_PASSWORD: $(WIN_CSC_KEY_PASSWORD)
+ BT_TOKEN: $(BT_TOKEN)
+ GH_TOKEN: $(GH_TOKEN)
+
+ - task: CopyFiles@2
+ inputs:
+ contents: 'dist\\*-setup.exe'
+ targetFolder: $(Build.ArtifactStagingDirectory)
+ flattenFolders: true
+ cleanTargetFolder: true
+
+ - task: PublishBuildArtifacts@1
+ inputs:
+ pathtoPublish: $(Build.ArtifactStagingDirectory)
+ artifactName: Windows - Installer
+ condition: eq(variables['Build.SourceBranch'], 'refs/heads/master')
+
+ - task: CopyFiles@2
+ inputs:
+ contents: 'dist\\*-portable.exe'
+ targetFolder: $(Build.ArtifactStagingDirectory)
+ flattenFolders: true
+ cleanTargetFolder: true
+
+ - task: PublishBuildArtifacts@1
+ inputs:
+ pathtoPublish: $(Build.ArtifactStagingDirectory)
+ artifactName: Windows - Portable build
+ condition: eq(variables['Build.SourceBranch'], 'refs/heads/master')
+
+- job: Linux
+ pool:
+ vmImage: 'ubuntu-16.04'
+
+ steps:
+ - task: NodeTool@0
+ inputs:
+ versionSpec: '10.x'
+ displayName: 'Install Node.js'
+
+ - script: yarn
+ displayName: 'Install dependencies'
+
+ - script: node scripts/build-native.js
+ displayName: 'Rebuild native dependencies'
+
+ - script: yarn run build:typings
+ displayName: 'Build typings'
+
+ - script: yarn run build
+ displayName: 'Build'
+
+ - script: node scripts/prepackage-plugins.js
+ displayName: 'Prepackage plugins'
+
+ - script: node scripts/build-linux.js
+ displayName: 'Package'
+ env:
+ BT_TOKEN: $(BT_TOKEN)
+ GH_TOKEN: $(GH_TOKEN)
+
+ - task: CopyFiles@2
+ inputs:
+ contents: 'dist/*.deb'
+ targetFolder: $(Build.ArtifactStagingDirectory)
+ flattenFolders: true
+ cleanTargetFolder: true
+
+ - task: PublishBuildArtifacts@1
+ inputs:
+ pathtoPublish: $(Build.ArtifactStagingDirectory)
+ artifactName: Linux - DEB
+ condition: eq(variables['Build.SourceBranch'], 'refs/heads/master')
+
+ - task: CopyFiles@2
+ inputs:
+ contents: 'dist/*.rpm'
+ targetFolder: $(Build.ArtifactStagingDirectory)
+ flattenFolders: true
+ cleanTargetFolder: true
+
+ - task: PublishBuildArtifacts@1
+ inputs:
+ pathtoPublish: $(Build.ArtifactStagingDirectory)
+ artifactName: Linux - RPM
+ condition: eq(variables['Build.SourceBranch'], 'refs/heads/master')
+
+ - task: CopyFiles@2
+ inputs:
+ contents: 'dist/*.snap'
+ targetFolder: $(Build.ArtifactStagingDirectory)
+ flattenFolders: true
+ cleanTargetFolder: true
+
+ - task: PublishBuildArtifacts@1
+ inputs:
+ pathtoPublish: $(Build.ArtifactStagingDirectory)
+ artifactName: Linux - Snap
+ condition: eq(variables['Build.SourceBranch'], 'refs/heads/master')
+
+ - task: CopyFiles@2
+ inputs:
+ contents: 'dist/*.tar.gz'
+ targetFolder: $(Build.ArtifactStagingDirectory)
+ flattenFolders: true
+ cleanTargetFolder: true
+
+ - task: PublishBuildArtifacts@1
+ inputs:
+ pathtoPublish: $(Build.ArtifactStagingDirectory)
+ artifactName: Linux - tar.gz
+ condition: eq(variables['Build.SourceBranch'], 'refs/heads/master')
+
+- job: macOS
+ pool:
+ vmImage: 'macOS-10.14'
+
+ steps:
+ - task: NodeTool@0
+ inputs:
+ versionSpec: '10.x'
+ displayName: 'Install Node.js'
+
+ - script: yarn
+ displayName: 'Install dependencies'
+
+ - script: node scripts/build-native.js
+ displayName: 'Rebuild native dependencies'
+
+ - script: yarn run build:typings
+ displayName: 'Build typings'
+
+ - script: yarn run build
+ displayName: 'Build'
+
+ - script: node scripts/prepackage-plugins.js
+ displayName: 'Prepackage plugins'
+
+ - script: node scripts/build-macos.js
+ displayName: 'Package'
+ env:
+ CSC_LINK: $(CSC_LINK)
+ CSC_KEY_PASSWORD: $(CSC_KEY_PASSWORD)
+ BT_TOKEN: $(BT_TOKEN)
+ GH_TOKEN: $(GH_TOKEN)
+ APPSTORE_USERNAME: $(APPSTORE_USERNAME)
+ APPSTORE_PASSWORD: $(APPSTORE_PASSWORD)
+
+ - task: CopyFiles@2
+ inputs:
+ contents: 'dist/*.dmg'
+ targetFolder: $(Build.ArtifactStagingDirectory)
+ flattenFolders: true
+ cleanTargetFolder: true
+
+ - task: PublishBuildArtifacts@1
+ inputs:
+ pathtoPublish: $(Build.ArtifactStagingDirectory)
+ artifactName: macOS - DMG
+ condition: eq(variables['Build.SourceBranch'], 'refs/heads/master')
+
+ - task: CopyFiles@2
+ inputs:
+ contents: 'dist/*.zip'
+ targetFolder: $(Build.ArtifactStagingDirectory)
+ flattenFolders: true
+ cleanTargetFolder: true
+
+ - task: PublishBuildArtifacts@1
+ inputs:
+ pathtoPublish: $(Build.ArtifactStagingDirectory)
+ artifactName: macOS - app.zip
+ condition: eq(variables['Build.SourceBranch'], 'refs/heads/master')
diff --git a/build/icons/128x128.png b/build/icons/128x128.png
index df98af73..5cb9846a 100644
Binary files a/build/icons/128x128.png and b/build/icons/128x128.png differ
diff --git a/build/icons/16x16.png b/build/icons/16x16.png
index 18042c31..eabb241f 100644
Binary files a/build/icons/16x16.png and b/build/icons/16x16.png differ
diff --git a/build/icons/256x256.png b/build/icons/256x256.png
index d0d4acd1..8a4a7d01 100644
Binary files a/build/icons/256x256.png and b/build/icons/256x256.png differ
diff --git a/build/icons/32x32.png b/build/icons/32x32.png
index e99dcebe..ca9ad6f9 100644
Binary files a/build/icons/32x32.png and b/build/icons/32x32.png differ
diff --git a/build/icons/64x64.png b/build/icons/64x64.png
index fb741708..c8693163 100644
Binary files a/build/icons/64x64.png and b/build/icons/64x64.png differ
diff --git a/build/installer.nsh b/build/installer.nsh
new file mode 100644
index 00000000..45fcaf8a
--- /dev/null
+++ b/build/installer.nsh
@@ -0,0 +1,3 @@
+!macro customInit
+ nsExec::Exec '"$LOCALAPPDATA\terminus\Update.exe" --uninstall -s'
+!macroend
diff --git a/build/mac/afterSignHook.js b/build/mac/afterSignHook.js
new file mode 100644
index 00000000..85189ff6
--- /dev/null
+++ b/build/mac/afterSignHook.js
@@ -0,0 +1,36 @@
+// See: https://medium.com/@TwitterArchiveEraser/notarize-electron-apps-7a5f988406db
+
+const fs = require('fs')
+const path = require('path')
+const notarizer = require('electron-notarize')
+
+module.exports = async function (params) {
+ console.log('env: ', process.env)
+ // notarize the app on Mac OS only.
+ if (process.platform !== 'darwin' || process.env.BUILD_SOURCEBRANCH !== 'refs/heads/master') {
+ return
+ }
+ console.log('afterSign hook triggered', params)
+
+ let appId = 'org.terminus'
+
+ let appPath = path.join(params.appOutDir, `${params.packager.appInfo.productFilename}.app`)
+ if (!fs.existsSync(appPath)) {
+ throw new Error(`Cannot find application at: ${appPath}`)
+ }
+
+ console.log(`Notarizing ${appId} found at ${appPath}`)
+
+ try {
+ await notarizer.notarize({
+ appBundleId: appId,
+ appPath: appPath,
+ appleId: process.env.APPSTORE_USERNAME,
+ appleIdPassword: process.env.APPSTORE_PASSWORD,
+ })
+ } catch (error) {
+ console.error(error)
+ }
+
+ console.log(`Done notarizing ${appId}`)
+}
diff --git a/build/mac/entitlements.plist b/build/mac/entitlements.plist
new file mode 100644
index 00000000..38c887b2
--- /dev/null
+++ b/build/mac/entitlements.plist
@@ -0,0 +1,12 @@
+
+
+
+
+ com.apple.security.cs.allow-jit
+
+ com.apple.security.cs.allow-unsigned-executable-memory
+
+ com.apple.security.cs.allow-dyld-environment-variables
+
+
+
diff --git a/build/windows/squirrel.gif b/build/windows/squirrel.gif
new file mode 100644
index 00000000..3b2b25e9
Binary files /dev/null and b/build/windows/squirrel.gif differ
diff --git a/docs/background.jpeg b/docs/background.jpeg
deleted file mode 100644
index 0e0c7ee1..00000000
Binary files a/docs/background.jpeg and /dev/null differ
diff --git a/docs/dist/assets/background.jpeg b/docs/dist/assets/background.jpeg
deleted file mode 100644
index 0e0c7ee1..00000000
Binary files a/docs/dist/assets/background.jpeg and /dev/null differ
diff --git a/docs/dist/assets/terminal.png b/docs/dist/assets/terminal.png
deleted file mode 100644
index 7a7097c1..00000000
Binary files a/docs/dist/assets/terminal.png and /dev/null differ
diff --git a/docs/dist/bundle.js b/docs/dist/bundle.js
deleted file mode 100644
index 6f8e1b2c..00000000
--- a/docs/dist/bundle.js
+++ /dev/null
@@ -1 +0,0 @@
-!function(n){var t={};function o(r){if(t[r])return t[r].exports;var e=t[r]={i:r,l:!1,exports:{}};return n[r].call(e.exports,e,e.exports,o),e.l=!0,e.exports}o.m=n,o.c=t,o.d=function(n,t,r){o.o(n,t)||Object.defineProperty(n,t,{enumerable:!0,get:r})},o.r=function(n){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(n,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(n,"__esModule",{value:!0})},o.t=function(n,t){if(1&t&&(n=o(n)),8&t)return n;if(4&t&&"object"==typeof n&&n&&n.__esModule)return n;var r=Object.create(null);if(o.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:n}),2&t&&"string"!=typeof n)for(var e in n)o.d(r,e,function(t){return n[t]}.bind(null,e));return r},o.n=function(n){var t=n&&n.__esModule?function(){return n.default}:function(){return n};return o.d(t,"a",t),t},o.o=function(n,t){return Object.prototype.hasOwnProperty.call(n,t)},o.p="",o(o.s=2)}([function(n,t,o){n.exports=o.p+"assets/background.jpeg"},,function(n,t,o){"use strict";o.r(t);o(3)},function(n,t,o){var r=o(4);"string"==typeof r&&(r=[[n.i,r,""]]);var e={hmr:!0,transform:void 0,insertInto:void 0};o(8)(r,e);r.locals&&(n.exports=r.locals)},function(n,t,o){var r=o(5);(n.exports=o(6)(!1)).push([n.i,'/*!\n * Bootstrap v4.1.3 (https://getbootstrap.com/)\n * Copyright 2011-2018 The Bootstrap Authors\n * Copyright 2011-2018 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n:root {\n --blue: #007bff;\n --indigo: #6610f2;\n --purple: #6f42c1;\n --pink: #e83e8c;\n --red: #dc3545;\n --orange: #fd7e14;\n --yellow: #ffc107;\n --green: #28a745;\n --teal: #20c997;\n --cyan: #17a2b8;\n --white: #fff;\n --gray: #6c757d;\n --gray-dark: #343a40;\n --primary: #007bff;\n --secondary: #6c757d;\n --success: #28a745;\n --info: #17a2b8;\n --warning: #ffc107;\n --danger: #dc3545;\n --light: #f8f9fa;\n --dark: #343a40;\n --breakpoint-xs: 0;\n --breakpoint-sm: 576px;\n --breakpoint-md: 768px;\n --breakpoint-lg: 992px;\n --breakpoint-xl: 1200px;\n --font-family-sans-serif: Source Sans Pro;\n --font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; }\n\n*,\n*::before,\n*::after {\n box-sizing: border-box; }\n\nhtml {\n font-family: sans-serif;\n line-height: 1.15;\n -webkit-text-size-adjust: 100%;\n -ms-text-size-adjust: 100%;\n -ms-overflow-style: scrollbar;\n -webkit-tap-highlight-color: rgba(0, 0, 0, 0); }\n\n@-ms-viewport {\n width: device-width; }\n\narticle, aside, figcaption, figure, footer, header, hgroup, main, nav, section {\n display: block; }\n\nbody {\n margin: 0;\n font-family: "Source Sans Pro";\n font-size: 1rem;\n font-weight: 400;\n line-height: 1.5;\n color: #212529;\n text-align: left;\n background-color: #fff; }\n\n[tabindex="-1"]:focus {\n outline: 0 !important; }\n\nhr {\n box-sizing: content-box;\n height: 0;\n overflow: visible; }\n\nh1, h2, h3, h4, h5, h6 {\n margin-top: 0;\n margin-bottom: 0.5rem; }\n\np {\n margin-top: 0;\n margin-bottom: 1rem; }\n\nabbr[title],\nabbr[data-original-title] {\n text-decoration: underline;\n text-decoration: underline dotted;\n cursor: help;\n border-bottom: 0; }\n\naddress {\n margin-bottom: 1rem;\n font-style: normal;\n line-height: inherit; }\n\nol,\nul,\ndl {\n margin-top: 0;\n margin-bottom: 1rem; }\n\nol ol,\nul ul,\nol ul,\nul ol {\n margin-bottom: 0; }\n\ndt {\n font-weight: 700; }\n\ndd {\n margin-bottom: .5rem;\n margin-left: 0; }\n\nblockquote {\n margin: 0 0 1rem; }\n\ndfn {\n font-style: italic; }\n\nb,\nstrong {\n font-weight: bolder; }\n\nsmall {\n font-size: 80%; }\n\nsub,\nsup {\n position: relative;\n font-size: 75%;\n line-height: 0;\n vertical-align: baseline; }\n\nsub {\n bottom: -.25em; }\n\nsup {\n top: -.5em; }\n\na {\n color: #007bff;\n text-decoration: none;\n background-color: transparent;\n -webkit-text-decoration-skip: objects; }\n a:hover {\n color: #0056b3;\n text-decoration: underline; }\n\na:not([href]):not([tabindex]) {\n color: inherit;\n text-decoration: none; }\n a:not([href]):not([tabindex]):hover, a:not([href]):not([tabindex]):focus {\n color: inherit;\n text-decoration: none; }\n a:not([href]):not([tabindex]):focus {\n outline: 0; }\n\npre,\ncode,\nkbd,\nsamp {\n font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;\n font-size: 1em; }\n\npre {\n margin-top: 0;\n margin-bottom: 1rem;\n overflow: auto;\n -ms-overflow-style: scrollbar; }\n\nfigure {\n margin: 0 0 1rem; }\n\nimg {\n vertical-align: middle;\n border-style: none; }\n\nsvg {\n overflow: hidden;\n vertical-align: middle; }\n\ntable {\n border-collapse: collapse; }\n\ncaption {\n padding-top: 0.75rem;\n padding-bottom: 0.75rem;\n color: #6c757d;\n text-align: left;\n caption-side: bottom; }\n\nth {\n text-align: inherit; }\n\nlabel {\n display: inline-block;\n margin-bottom: 0.5rem; }\n\nbutton {\n border-radius: 0; }\n\nbutton:focus {\n outline: 1px dotted;\n outline: 5px auto -webkit-focus-ring-color; }\n\ninput,\nbutton,\nselect,\noptgroup,\ntextarea {\n margin: 0;\n font-family: inherit;\n font-size: inherit;\n line-height: inherit; }\n\nbutton,\ninput {\n overflow: visible; }\n\nbutton,\nselect {\n text-transform: none; }\n\nbutton,\nhtml [type="button"],\n[type="reset"],\n[type="submit"] {\n -webkit-appearance: button; }\n\nbutton::-moz-focus-inner,\n[type="button"]::-moz-focus-inner,\n[type="reset"]::-moz-focus-inner,\n[type="submit"]::-moz-focus-inner {\n padding: 0;\n border-style: none; }\n\ninput[type="radio"],\ninput[type="checkbox"] {\n box-sizing: border-box;\n padding: 0; }\n\ninput[type="date"],\ninput[type="time"],\ninput[type="datetime-local"],\ninput[type="month"] {\n -webkit-appearance: listbox; }\n\ntextarea {\n overflow: auto;\n resize: vertical; }\n\nfieldset {\n min-width: 0;\n padding: 0;\n margin: 0;\n border: 0; }\n\nlegend {\n display: block;\n width: 100%;\n max-width: 100%;\n padding: 0;\n margin-bottom: .5rem;\n font-size: 1.5rem;\n line-height: inherit;\n color: inherit;\n white-space: normal; }\n\nprogress {\n vertical-align: baseline; }\n\n[type="number"]::-webkit-inner-spin-button,\n[type="number"]::-webkit-outer-spin-button {\n height: auto; }\n\n[type="search"] {\n outline-offset: -2px;\n -webkit-appearance: none; }\n\n[type="search"]::-webkit-search-cancel-button,\n[type="search"]::-webkit-search-decoration {\n -webkit-appearance: none; }\n\n::-webkit-file-upload-button {\n font: inherit;\n -webkit-appearance: button; }\n\noutput {\n display: inline-block; }\n\nsummary {\n display: list-item;\n cursor: pointer; }\n\ntemplate {\n display: none; }\n\n[hidden] {\n display: none !important; }\n\nh1, h2, h3, h4, h5, h6,\n.h1, .h2, .h3, .h4, .h5, .h6 {\n margin-bottom: 0.5rem;\n font-family: inherit;\n font-weight: 500;\n line-height: 1.2;\n color: inherit; }\n\nh1, .h1 {\n font-size: 2.5rem; }\n\nh2, .h2 {\n font-size: 2rem; }\n\nh3, .h3 {\n font-size: 1.75rem; }\n\nh4, .h4 {\n font-size: 1.5rem; }\n\nh5, .h5 {\n font-size: 1.25rem; }\n\nh6, .h6 {\n font-size: 1rem; }\n\n.lead {\n font-size: 1.25rem;\n font-weight: 300; }\n\n.display-1 {\n font-size: 6rem;\n font-weight: 300;\n line-height: 1.2; }\n\n.display-2 {\n font-size: 5.5rem;\n font-weight: 300;\n line-height: 1.2; }\n\n.display-3 {\n font-size: 4.5rem;\n font-weight: 300;\n line-height: 1.2; }\n\n.display-4 {\n font-size: 3.5rem;\n font-weight: 300;\n line-height: 1.2; }\n\nhr {\n margin-top: 1rem;\n margin-bottom: 1rem;\n border: 0;\n border-top: 1px solid rgba(0, 0, 0, 0.1); }\n\nsmall,\n.small {\n font-size: 80%;\n font-weight: 400; }\n\nmark,\n.mark {\n padding: 0.2em;\n background-color: #fcf8e3; }\n\n.list-unstyled {\n padding-left: 0;\n list-style: none; }\n\n.list-inline {\n padding-left: 0;\n list-style: none; }\n\n.list-inline-item {\n display: inline-block; }\n .list-inline-item:not(:last-child) {\n margin-right: 0.5rem; }\n\n.initialism {\n font-size: 90%;\n text-transform: uppercase; }\n\n.blockquote {\n margin-bottom: 1rem;\n font-size: 1.25rem; }\n\n.blockquote-footer {\n display: block;\n font-size: 80%;\n color: #6c757d; }\n .blockquote-footer::before {\n content: "\\2014 \\A0"; }\n\n.img-fluid {\n max-width: 100%;\n height: auto; }\n\n.img-thumbnail {\n padding: 0.25rem;\n background-color: #fff;\n border: 1px solid #dee2e6;\n border-radius: 0.25rem;\n max-width: 100%;\n height: auto; }\n\n.figure {\n display: inline-block; }\n\n.figure-img {\n margin-bottom: 0.5rem;\n line-height: 1; }\n\n.figure-caption {\n font-size: 90%;\n color: #6c757d; }\n\ncode {\n font-size: 87.5%;\n color: #e83e8c;\n word-break: break-word; }\n a > code {\n color: inherit; }\n\nkbd {\n padding: 0.2rem 0.4rem;\n font-size: 87.5%;\n color: #fff;\n background-color: #212529;\n border-radius: 0.2rem; }\n kbd kbd {\n padding: 0;\n font-size: 100%;\n font-weight: 700; }\n\npre {\n display: block;\n font-size: 87.5%;\n color: #212529; }\n pre code {\n font-size: inherit;\n color: inherit;\n word-break: normal; }\n\n.pre-scrollable {\n max-height: 340px;\n overflow-y: scroll; }\n\n.container {\n width: 100%;\n padding-right: 15px;\n padding-left: 15px;\n margin-right: auto;\n margin-left: auto; }\n @media (min-width: 576px) {\n .container {\n max-width: 540px; } }\n @media (min-width: 768px) {\n .container {\n max-width: 720px; } }\n @media (min-width: 992px) {\n .container {\n max-width: 960px; } }\n @media (min-width: 1200px) {\n .container {\n max-width: 1140px; } }\n\n.container-fluid {\n width: 100%;\n padding-right: 15px;\n padding-left: 15px;\n margin-right: auto;\n margin-left: auto; }\n\n.row {\n display: flex;\n flex-wrap: wrap;\n margin-right: -15px;\n margin-left: -15px; }\n\n.no-gutters {\n margin-right: 0;\n margin-left: 0; }\n .no-gutters > .col,\n .no-gutters > [class*="col-"] {\n padding-right: 0;\n padding-left: 0; }\n\n.col-1, .col-2, .col-3, .col-4, .col-5, .col-6, .col-7, .col-8, .col-9, .col-10, .col-11, .col-12, .col,\n.col-auto, .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12, .col-sm,\n.col-sm-auto, .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12, .col-md,\n.col-md-auto, .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12, .col-lg,\n.col-lg-auto, .col-xl-1, .col-xl-2, .col-xl-3, .col-xl-4, .col-xl-5, .col-xl-6, .col-xl-7, .col-xl-8, .col-xl-9, .col-xl-10, .col-xl-11, .col-xl-12, .col-xl,\n.col-xl-auto {\n position: relative;\n width: 100%;\n min-height: 1px;\n padding-right: 15px;\n padding-left: 15px; }\n\n.col {\n flex-basis: 0;\n flex-grow: 1;\n max-width: 100%; }\n\n.col-auto {\n flex: 0 0 auto;\n width: auto;\n max-width: none; }\n\n.col-1 {\n flex: 0 0 8.33333%;\n max-width: 8.33333%; }\n\n.col-2 {\n flex: 0 0 16.66667%;\n max-width: 16.66667%; }\n\n.col-3 {\n flex: 0 0 25%;\n max-width: 25%; }\n\n.col-4 {\n flex: 0 0 33.33333%;\n max-width: 33.33333%; }\n\n.col-5 {\n flex: 0 0 41.66667%;\n max-width: 41.66667%; }\n\n.col-6 {\n flex: 0 0 50%;\n max-width: 50%; }\n\n.col-7 {\n flex: 0 0 58.33333%;\n max-width: 58.33333%; }\n\n.col-8 {\n flex: 0 0 66.66667%;\n max-width: 66.66667%; }\n\n.col-9 {\n flex: 0 0 75%;\n max-width: 75%; }\n\n.col-10 {\n flex: 0 0 83.33333%;\n max-width: 83.33333%; }\n\n.col-11 {\n flex: 0 0 91.66667%;\n max-width: 91.66667%; }\n\n.col-12 {\n flex: 0 0 100%;\n max-width: 100%; }\n\n.order-first {\n order: -1; }\n\n.order-last {\n order: 13; }\n\n.order-0 {\n order: 0; }\n\n.order-1 {\n order: 1; }\n\n.order-2 {\n order: 2; }\n\n.order-3 {\n order: 3; }\n\n.order-4 {\n order: 4; }\n\n.order-5 {\n order: 5; }\n\n.order-6 {\n order: 6; }\n\n.order-7 {\n order: 7; }\n\n.order-8 {\n order: 8; }\n\n.order-9 {\n order: 9; }\n\n.order-10 {\n order: 10; }\n\n.order-11 {\n order: 11; }\n\n.order-12 {\n order: 12; }\n\n.offset-1 {\n margin-left: 8.33333%; }\n\n.offset-2 {\n margin-left: 16.66667%; }\n\n.offset-3 {\n margin-left: 25%; }\n\n.offset-4 {\n margin-left: 33.33333%; }\n\n.offset-5 {\n margin-left: 41.66667%; }\n\n.offset-6 {\n margin-left: 50%; }\n\n.offset-7 {\n margin-left: 58.33333%; }\n\n.offset-8 {\n margin-left: 66.66667%; }\n\n.offset-9 {\n margin-left: 75%; }\n\n.offset-10 {\n margin-left: 83.33333%; }\n\n.offset-11 {\n margin-left: 91.66667%; }\n\n@media (min-width: 576px) {\n .col-sm {\n flex-basis: 0;\n flex-grow: 1;\n max-width: 100%; }\n .col-sm-auto {\n flex: 0 0 auto;\n width: auto;\n max-width: none; }\n .col-sm-1 {\n flex: 0 0 8.33333%;\n max-width: 8.33333%; }\n .col-sm-2 {\n flex: 0 0 16.66667%;\n max-width: 16.66667%; }\n .col-sm-3 {\n flex: 0 0 25%;\n max-width: 25%; }\n .col-sm-4 {\n flex: 0 0 33.33333%;\n max-width: 33.33333%; }\n .col-sm-5 {\n flex: 0 0 41.66667%;\n max-width: 41.66667%; }\n .col-sm-6 {\n flex: 0 0 50%;\n max-width: 50%; }\n .col-sm-7 {\n flex: 0 0 58.33333%;\n max-width: 58.33333%; }\n .col-sm-8 {\n flex: 0 0 66.66667%;\n max-width: 66.66667%; }\n .col-sm-9 {\n flex: 0 0 75%;\n max-width: 75%; }\n .col-sm-10 {\n flex: 0 0 83.33333%;\n max-width: 83.33333%; }\n .col-sm-11 {\n flex: 0 0 91.66667%;\n max-width: 91.66667%; }\n .col-sm-12 {\n flex: 0 0 100%;\n max-width: 100%; }\n .order-sm-first {\n order: -1; }\n .order-sm-last {\n order: 13; }\n .order-sm-0 {\n order: 0; }\n .order-sm-1 {\n order: 1; }\n .order-sm-2 {\n order: 2; }\n .order-sm-3 {\n order: 3; }\n .order-sm-4 {\n order: 4; }\n .order-sm-5 {\n order: 5; }\n .order-sm-6 {\n order: 6; }\n .order-sm-7 {\n order: 7; }\n .order-sm-8 {\n order: 8; }\n .order-sm-9 {\n order: 9; }\n .order-sm-10 {\n order: 10; }\n .order-sm-11 {\n order: 11; }\n .order-sm-12 {\n order: 12; }\n .offset-sm-0 {\n margin-left: 0; }\n .offset-sm-1 {\n margin-left: 8.33333%; }\n .offset-sm-2 {\n margin-left: 16.66667%; }\n .offset-sm-3 {\n margin-left: 25%; }\n .offset-sm-4 {\n margin-left: 33.33333%; }\n .offset-sm-5 {\n margin-left: 41.66667%; }\n .offset-sm-6 {\n margin-left: 50%; }\n .offset-sm-7 {\n margin-left: 58.33333%; }\n .offset-sm-8 {\n margin-left: 66.66667%; }\n .offset-sm-9 {\n margin-left: 75%; }\n .offset-sm-10 {\n margin-left: 83.33333%; }\n .offset-sm-11 {\n margin-left: 91.66667%; } }\n\n@media (min-width: 768px) {\n .col-md {\n flex-basis: 0;\n flex-grow: 1;\n max-width: 100%; }\n .col-md-auto {\n flex: 0 0 auto;\n width: auto;\n max-width: none; }\n .col-md-1 {\n flex: 0 0 8.33333%;\n max-width: 8.33333%; }\n .col-md-2 {\n flex: 0 0 16.66667%;\n max-width: 16.66667%; }\n .col-md-3 {\n flex: 0 0 25%;\n max-width: 25%; }\n .col-md-4 {\n flex: 0 0 33.33333%;\n max-width: 33.33333%; }\n .col-md-5 {\n flex: 0 0 41.66667%;\n max-width: 41.66667%; }\n .col-md-6 {\n flex: 0 0 50%;\n max-width: 50%; }\n .col-md-7 {\n flex: 0 0 58.33333%;\n max-width: 58.33333%; }\n .col-md-8 {\n flex: 0 0 66.66667%;\n max-width: 66.66667%; }\n .col-md-9 {\n flex: 0 0 75%;\n max-width: 75%; }\n .col-md-10 {\n flex: 0 0 83.33333%;\n max-width: 83.33333%; }\n .col-md-11 {\n flex: 0 0 91.66667%;\n max-width: 91.66667%; }\n .col-md-12 {\n flex: 0 0 100%;\n max-width: 100%; }\n .order-md-first {\n order: -1; }\n .order-md-last {\n order: 13; }\n .order-md-0 {\n order: 0; }\n .order-md-1 {\n order: 1; }\n .order-md-2 {\n order: 2; }\n .order-md-3 {\n order: 3; }\n .order-md-4 {\n order: 4; }\n .order-md-5 {\n order: 5; }\n .order-md-6 {\n order: 6; }\n .order-md-7 {\n order: 7; }\n .order-md-8 {\n order: 8; }\n .order-md-9 {\n order: 9; }\n .order-md-10 {\n order: 10; }\n .order-md-11 {\n order: 11; }\n .order-md-12 {\n order: 12; }\n .offset-md-0 {\n margin-left: 0; }\n .offset-md-1 {\n margin-left: 8.33333%; }\n .offset-md-2 {\n margin-left: 16.66667%; }\n .offset-md-3 {\n margin-left: 25%; }\n .offset-md-4 {\n margin-left: 33.33333%; }\n .offset-md-5 {\n margin-left: 41.66667%; }\n .offset-md-6 {\n margin-left: 50%; }\n .offset-md-7 {\n margin-left: 58.33333%; }\n .offset-md-8 {\n margin-left: 66.66667%; }\n .offset-md-9 {\n margin-left: 75%; }\n .offset-md-10 {\n margin-left: 83.33333%; }\n .offset-md-11 {\n margin-left: 91.66667%; } }\n\n@media (min-width: 992px) {\n .col-lg {\n flex-basis: 0;\n flex-grow: 1;\n max-width: 100%; }\n .col-lg-auto {\n flex: 0 0 auto;\n width: auto;\n max-width: none; }\n .col-lg-1 {\n flex: 0 0 8.33333%;\n max-width: 8.33333%; }\n .col-lg-2 {\n flex: 0 0 16.66667%;\n max-width: 16.66667%; }\n .col-lg-3 {\n flex: 0 0 25%;\n max-width: 25%; }\n .col-lg-4 {\n flex: 0 0 33.33333%;\n max-width: 33.33333%; }\n .col-lg-5 {\n flex: 0 0 41.66667%;\n max-width: 41.66667%; }\n .col-lg-6 {\n flex: 0 0 50%;\n max-width: 50%; }\n .col-lg-7 {\n flex: 0 0 58.33333%;\n max-width: 58.33333%; }\n .col-lg-8 {\n flex: 0 0 66.66667%;\n max-width: 66.66667%; }\n .col-lg-9 {\n flex: 0 0 75%;\n max-width: 75%; }\n .col-lg-10 {\n flex: 0 0 83.33333%;\n max-width: 83.33333%; }\n .col-lg-11 {\n flex: 0 0 91.66667%;\n max-width: 91.66667%; }\n .col-lg-12 {\n flex: 0 0 100%;\n max-width: 100%; }\n .order-lg-first {\n order: -1; }\n .order-lg-last {\n order: 13; }\n .order-lg-0 {\n order: 0; }\n .order-lg-1 {\n order: 1; }\n .order-lg-2 {\n order: 2; }\n .order-lg-3 {\n order: 3; }\n .order-lg-4 {\n order: 4; }\n .order-lg-5 {\n order: 5; }\n .order-lg-6 {\n order: 6; }\n .order-lg-7 {\n order: 7; }\n .order-lg-8 {\n order: 8; }\n .order-lg-9 {\n order: 9; }\n .order-lg-10 {\n order: 10; }\n .order-lg-11 {\n order: 11; }\n .order-lg-12 {\n order: 12; }\n .offset-lg-0 {\n margin-left: 0; }\n .offset-lg-1 {\n margin-left: 8.33333%; }\n .offset-lg-2 {\n margin-left: 16.66667%; }\n .offset-lg-3 {\n margin-left: 25%; }\n .offset-lg-4 {\n margin-left: 33.33333%; }\n .offset-lg-5 {\n margin-left: 41.66667%; }\n .offset-lg-6 {\n margin-left: 50%; }\n .offset-lg-7 {\n margin-left: 58.33333%; }\n .offset-lg-8 {\n margin-left: 66.66667%; }\n .offset-lg-9 {\n margin-left: 75%; }\n .offset-lg-10 {\n margin-left: 83.33333%; }\n .offset-lg-11 {\n margin-left: 91.66667%; } }\n\n@media (min-width: 1200px) {\n .col-xl {\n flex-basis: 0;\n flex-grow: 1;\n max-width: 100%; }\n .col-xl-auto {\n flex: 0 0 auto;\n width: auto;\n max-width: none; }\n .col-xl-1 {\n flex: 0 0 8.33333%;\n max-width: 8.33333%; }\n .col-xl-2 {\n flex: 0 0 16.66667%;\n max-width: 16.66667%; }\n .col-xl-3 {\n flex: 0 0 25%;\n max-width: 25%; }\n .col-xl-4 {\n flex: 0 0 33.33333%;\n max-width: 33.33333%; }\n .col-xl-5 {\n flex: 0 0 41.66667%;\n max-width: 41.66667%; }\n .col-xl-6 {\n flex: 0 0 50%;\n max-width: 50%; }\n .col-xl-7 {\n flex: 0 0 58.33333%;\n max-width: 58.33333%; }\n .col-xl-8 {\n flex: 0 0 66.66667%;\n max-width: 66.66667%; }\n .col-xl-9 {\n flex: 0 0 75%;\n max-width: 75%; }\n .col-xl-10 {\n flex: 0 0 83.33333%;\n max-width: 83.33333%; }\n .col-xl-11 {\n flex: 0 0 91.66667%;\n max-width: 91.66667%; }\n .col-xl-12 {\n flex: 0 0 100%;\n max-width: 100%; }\n .order-xl-first {\n order: -1; }\n .order-xl-last {\n order: 13; }\n .order-xl-0 {\n order: 0; }\n .order-xl-1 {\n order: 1; }\n .order-xl-2 {\n order: 2; }\n .order-xl-3 {\n order: 3; }\n .order-xl-4 {\n order: 4; }\n .order-xl-5 {\n order: 5; }\n .order-xl-6 {\n order: 6; }\n .order-xl-7 {\n order: 7; }\n .order-xl-8 {\n order: 8; }\n .order-xl-9 {\n order: 9; }\n .order-xl-10 {\n order: 10; }\n .order-xl-11 {\n order: 11; }\n .order-xl-12 {\n order: 12; }\n .offset-xl-0 {\n margin-left: 0; }\n .offset-xl-1 {\n margin-left: 8.33333%; }\n .offset-xl-2 {\n margin-left: 16.66667%; }\n .offset-xl-3 {\n margin-left: 25%; }\n .offset-xl-4 {\n margin-left: 33.33333%; }\n .offset-xl-5 {\n margin-left: 41.66667%; }\n .offset-xl-6 {\n margin-left: 50%; }\n .offset-xl-7 {\n margin-left: 58.33333%; }\n .offset-xl-8 {\n margin-left: 66.66667%; }\n .offset-xl-9 {\n margin-left: 75%; }\n .offset-xl-10 {\n margin-left: 83.33333%; }\n .offset-xl-11 {\n margin-left: 91.66667%; } }\n\n.table {\n width: 100%;\n margin-bottom: 1rem;\n background-color: transparent; }\n .table th,\n .table td {\n padding: 0.75rem;\n vertical-align: top;\n border-top: 1px solid #dee2e6; }\n .table thead th {\n vertical-align: bottom;\n border-bottom: 2px solid #dee2e6; }\n .table tbody + tbody {\n border-top: 2px solid #dee2e6; }\n .table .table {\n background-color: #fff; }\n\n.table-sm th,\n.table-sm td {\n padding: 0.3rem; }\n\n.table-bordered {\n border: 1px solid #dee2e6; }\n .table-bordered th,\n .table-bordered td {\n border: 1px solid #dee2e6; }\n .table-bordered thead th,\n .table-bordered thead td {\n border-bottom-width: 2px; }\n\n.table-borderless th,\n.table-borderless td,\n.table-borderless thead th,\n.table-borderless tbody + tbody {\n border: 0; }\n\n.table-striped tbody tr:nth-of-type(odd) {\n background-color: rgba(0, 0, 0, 0.05); }\n\n.table-hover tbody tr:hover {\n background-color: rgba(0, 0, 0, 0.075); }\n\n.table-primary,\n.table-primary > th,\n.table-primary > td {\n background-color: #b8daff; }\n\n.table-hover .table-primary:hover {\n background-color: #9fcdff; }\n .table-hover .table-primary:hover > td,\n .table-hover .table-primary:hover > th {\n background-color: #9fcdff; }\n\n.table-secondary,\n.table-secondary > th,\n.table-secondary > td {\n background-color: #d6d8db; }\n\n.table-hover .table-secondary:hover {\n background-color: #c8cbcf; }\n .table-hover .table-secondary:hover > td,\n .table-hover .table-secondary:hover > th {\n background-color: #c8cbcf; }\n\n.table-success,\n.table-success > th,\n.table-success > td {\n background-color: #c3e6cb; }\n\n.table-hover .table-success:hover {\n background-color: #b1dfbb; }\n .table-hover .table-success:hover > td,\n .table-hover .table-success:hover > th {\n background-color: #b1dfbb; }\n\n.table-info,\n.table-info > th,\n.table-info > td {\n background-color: #bee5eb; }\n\n.table-hover .table-info:hover {\n background-color: #abdde5; }\n .table-hover .table-info:hover > td,\n .table-hover .table-info:hover > th {\n background-color: #abdde5; }\n\n.table-warning,\n.table-warning > th,\n.table-warning > td {\n background-color: #ffeeba; }\n\n.table-hover .table-warning:hover {\n background-color: #ffe8a1; }\n .table-hover .table-warning:hover > td,\n .table-hover .table-warning:hover > th {\n background-color: #ffe8a1; }\n\n.table-danger,\n.table-danger > th,\n.table-danger > td {\n background-color: #f5c6cb; }\n\n.table-hover .table-danger:hover {\n background-color: #f1b0b7; }\n .table-hover .table-danger:hover > td,\n .table-hover .table-danger:hover > th {\n background-color: #f1b0b7; }\n\n.table-light,\n.table-light > th,\n.table-light > td {\n background-color: #fdfdfe; }\n\n.table-hover .table-light:hover {\n background-color: #ececf6; }\n .table-hover .table-light:hover > td,\n .table-hover .table-light:hover > th {\n background-color: #ececf6; }\n\n.table-dark,\n.table-dark > th,\n.table-dark > td {\n background-color: #c6c8ca; }\n\n.table-hover .table-dark:hover {\n background-color: #b9bbbe; }\n .table-hover .table-dark:hover > td,\n .table-hover .table-dark:hover > th {\n background-color: #b9bbbe; }\n\n.table-active,\n.table-active > th,\n.table-active > td {\n background-color: rgba(0, 0, 0, 0.075); }\n\n.table-hover .table-active:hover {\n background-color: rgba(0, 0, 0, 0.075); }\n .table-hover .table-active:hover > td,\n .table-hover .table-active:hover > th {\n background-color: rgba(0, 0, 0, 0.075); }\n\n.table .thead-dark th {\n color: #fff;\n background-color: #212529;\n border-color: #32383e; }\n\n.table .thead-light th {\n color: #495057;\n background-color: #e9ecef;\n border-color: #dee2e6; }\n\n.table-dark {\n color: #fff;\n background-color: #212529; }\n .table-dark th,\n .table-dark td,\n .table-dark thead th {\n border-color: #32383e; }\n .table-dark.table-bordered {\n border: 0; }\n .table-dark.table-striped tbody tr:nth-of-type(odd) {\n background-color: rgba(255, 255, 255, 0.05); }\n .table-dark.table-hover tbody tr:hover {\n background-color: rgba(255, 255, 255, 0.075); }\n\n@media (max-width: 575.98px) {\n .table-responsive-sm {\n display: block;\n width: 100%;\n overflow-x: auto;\n -webkit-overflow-scrolling: touch;\n -ms-overflow-style: -ms-autohiding-scrollbar; }\n .table-responsive-sm > .table-bordered {\n border: 0; } }\n\n@media (max-width: 767.98px) {\n .table-responsive-md {\n display: block;\n width: 100%;\n overflow-x: auto;\n -webkit-overflow-scrolling: touch;\n -ms-overflow-style: -ms-autohiding-scrollbar; }\n .table-responsive-md > .table-bordered {\n border: 0; } }\n\n@media (max-width: 991.98px) {\n .table-responsive-lg {\n display: block;\n width: 100%;\n overflow-x: auto;\n -webkit-overflow-scrolling: touch;\n -ms-overflow-style: -ms-autohiding-scrollbar; }\n .table-responsive-lg > .table-bordered {\n border: 0; } }\n\n@media (max-width: 1199.98px) {\n .table-responsive-xl {\n display: block;\n width: 100%;\n overflow-x: auto;\n -webkit-overflow-scrolling: touch;\n -ms-overflow-style: -ms-autohiding-scrollbar; }\n .table-responsive-xl > .table-bordered {\n border: 0; } }\n\n.table-responsive {\n display: block;\n width: 100%;\n overflow-x: auto;\n -webkit-overflow-scrolling: touch;\n -ms-overflow-style: -ms-autohiding-scrollbar; }\n .table-responsive > .table-bordered {\n border: 0; }\n\n.form-control {\n display: block;\n width: 100%;\n height: calc(2.25rem + 2px);\n padding: 0.375rem 0.75rem;\n font-size: 1rem;\n line-height: 1.5;\n color: #495057;\n background-color: #fff;\n background-clip: padding-box;\n border: 1px solid #ced4da;\n border-radius: 0.25rem;\n transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; }\n @media screen and (prefers-reduced-motion: reduce) {\n .form-control {\n transition: none; } }\n .form-control::-ms-expand {\n background-color: transparent;\n border: 0; }\n .form-control:focus {\n color: #495057;\n background-color: #fff;\n border-color: #80bdff;\n outline: 0;\n box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25); }\n .form-control::placeholder {\n color: #6c757d;\n opacity: 1; }\n .form-control:disabled, .form-control[readonly] {\n background-color: #e9ecef;\n opacity: 1; }\n\nselect.form-control:focus::-ms-value {\n color: #495057;\n background-color: #fff; }\n\n.form-control-file,\n.form-control-range {\n display: block;\n width: 100%; }\n\n.col-form-label {\n padding-top: calc(0.375rem + 1px);\n padding-bottom: calc(0.375rem + 1px);\n margin-bottom: 0;\n font-size: inherit;\n line-height: 1.5; }\n\n.col-form-label-lg {\n padding-top: calc(0.5rem + 1px);\n padding-bottom: calc(0.5rem + 1px);\n font-size: 1.25rem;\n line-height: 1.5; }\n\n.col-form-label-sm {\n padding-top: calc(0.25rem + 1px);\n padding-bottom: calc(0.25rem + 1px);\n font-size: 0.875rem;\n line-height: 1.5; }\n\n.form-control-plaintext {\n display: block;\n width: 100%;\n padding-top: 0.375rem;\n padding-bottom: 0.375rem;\n margin-bottom: 0;\n line-height: 1.5;\n color: #212529;\n background-color: transparent;\n border: solid transparent;\n border-width: 1px 0; }\n .form-control-plaintext.form-control-sm, .form-control-plaintext.form-control-lg {\n padding-right: 0;\n padding-left: 0; }\n\n.form-control-sm {\n height: calc(1.8125rem + 2px);\n padding: 0.25rem 0.5rem;\n font-size: 0.875rem;\n line-height: 1.5;\n border-radius: 0.2rem; }\n\n.form-control-lg {\n height: calc(2.875rem + 2px);\n padding: 0.5rem 1rem;\n font-size: 1.25rem;\n line-height: 1.5;\n border-radius: 0; }\n\nselect.form-control[size], select.form-control[multiple] {\n height: auto; }\n\ntextarea.form-control {\n height: auto; }\n\n.form-group {\n margin-bottom: 1rem; }\n\n.form-text {\n display: block;\n margin-top: 0.25rem; }\n\n.form-row {\n display: flex;\n flex-wrap: wrap;\n margin-right: -5px;\n margin-left: -5px; }\n .form-row > .col,\n .form-row > [class*="col-"] {\n padding-right: 5px;\n padding-left: 5px; }\n\n.form-check {\n position: relative;\n display: block;\n padding-left: 1.25rem; }\n\n.form-check-input {\n position: absolute;\n margin-top: 0.3rem;\n margin-left: -1.25rem; }\n .form-check-input:disabled ~ .form-check-label {\n color: #6c757d; }\n\n.form-check-label {\n margin-bottom: 0; }\n\n.form-check-inline {\n display: inline-flex;\n align-items: center;\n padding-left: 0;\n margin-right: 0.75rem; }\n .form-check-inline .form-check-input {\n position: static;\n margin-top: 0;\n margin-right: 0.3125rem;\n margin-left: 0; }\n\n.valid-feedback {\n display: none;\n width: 100%;\n margin-top: 0.25rem;\n font-size: 80%;\n color: #28a745; }\n\n.valid-tooltip {\n position: absolute;\n top: 100%;\n z-index: 5;\n display: none;\n max-width: 100%;\n padding: 0.25rem 0.5rem;\n margin-top: .1rem;\n font-size: 0.875rem;\n line-height: 1.5;\n color: #fff;\n background-color: rgba(40, 167, 69, 0.9);\n border-radius: 0.25rem; }\n\n.was-validated .form-control:valid, .form-control.is-valid, .was-validated\n.custom-select:valid,\n.custom-select.is-valid {\n border-color: #28a745; }\n .was-validated .form-control:valid:focus, .form-control.is-valid:focus, .was-validated\n .custom-select:valid:focus,\n .custom-select.is-valid:focus {\n border-color: #28a745;\n box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.25); }\n .was-validated .form-control:valid ~ .valid-feedback,\n .was-validated .form-control:valid ~ .valid-tooltip, .form-control.is-valid ~ .valid-feedback,\n .form-control.is-valid ~ .valid-tooltip, .was-validated\n .custom-select:valid ~ .valid-feedback,\n .was-validated\n .custom-select:valid ~ .valid-tooltip,\n .custom-select.is-valid ~ .valid-feedback,\n .custom-select.is-valid ~ .valid-tooltip {\n display: block; }\n\n.was-validated .form-control-file:valid ~ .valid-feedback,\n.was-validated .form-control-file:valid ~ .valid-tooltip, .form-control-file.is-valid ~ .valid-feedback,\n.form-control-file.is-valid ~ .valid-tooltip {\n display: block; }\n\n.was-validated .form-check-input:valid ~ .form-check-label, .form-check-input.is-valid ~ .form-check-label {\n color: #28a745; }\n\n.was-validated .form-check-input:valid ~ .valid-feedback,\n.was-validated .form-check-input:valid ~ .valid-tooltip, .form-check-input.is-valid ~ .valid-feedback,\n.form-check-input.is-valid ~ .valid-tooltip {\n display: block; }\n\n.was-validated .custom-control-input:valid ~ .custom-control-label, .custom-control-input.is-valid ~ .custom-control-label {\n color: #28a745; }\n .was-validated .custom-control-input:valid ~ .custom-control-label::before, .custom-control-input.is-valid ~ .custom-control-label::before {\n background-color: #71dd8a; }\n\n.was-validated .custom-control-input:valid ~ .valid-feedback,\n.was-validated .custom-control-input:valid ~ .valid-tooltip, .custom-control-input.is-valid ~ .valid-feedback,\n.custom-control-input.is-valid ~ .valid-tooltip {\n display: block; }\n\n.was-validated .custom-control-input:valid:checked ~ .custom-control-label::before, .custom-control-input.is-valid:checked ~ .custom-control-label::before {\n background-color: #34ce57; }\n\n.was-validated .custom-control-input:valid:focus ~ .custom-control-label::before, .custom-control-input.is-valid:focus ~ .custom-control-label::before {\n box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(40, 167, 69, 0.25); }\n\n.was-validated .custom-file-input:valid ~ .custom-file-label, .custom-file-input.is-valid ~ .custom-file-label {\n border-color: #28a745; }\n .was-validated .custom-file-input:valid ~ .custom-file-label::after, .custom-file-input.is-valid ~ .custom-file-label::after {\n border-color: inherit; }\n\n.was-validated .custom-file-input:valid ~ .valid-feedback,\n.was-validated .custom-file-input:valid ~ .valid-tooltip, .custom-file-input.is-valid ~ .valid-feedback,\n.custom-file-input.is-valid ~ .valid-tooltip {\n display: block; }\n\n.was-validated .custom-file-input:valid:focus ~ .custom-file-label, .custom-file-input.is-valid:focus ~ .custom-file-label {\n box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.25); }\n\n.invalid-feedback {\n display: none;\n width: 100%;\n margin-top: 0.25rem;\n font-size: 80%;\n color: #dc3545; }\n\n.invalid-tooltip {\n position: absolute;\n top: 100%;\n z-index: 5;\n display: none;\n max-width: 100%;\n padding: 0.25rem 0.5rem;\n margin-top: .1rem;\n font-size: 0.875rem;\n line-height: 1.5;\n color: #fff;\n background-color: rgba(220, 53, 69, 0.9);\n border-radius: 0.25rem; }\n\n.was-validated .form-control:invalid, .form-control.is-invalid, .was-validated\n.custom-select:invalid,\n.custom-select.is-invalid {\n border-color: #dc3545; }\n .was-validated .form-control:invalid:focus, .form-control.is-invalid:focus, .was-validated\n .custom-select:invalid:focus,\n .custom-select.is-invalid:focus {\n border-color: #dc3545;\n box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25); }\n .was-validated .form-control:invalid ~ .invalid-feedback,\n .was-validated .form-control:invalid ~ .invalid-tooltip, .form-control.is-invalid ~ .invalid-feedback,\n .form-control.is-invalid ~ .invalid-tooltip, .was-validated\n .custom-select:invalid ~ .invalid-feedback,\n .was-validated\n .custom-select:invalid ~ .invalid-tooltip,\n .custom-select.is-invalid ~ .invalid-feedback,\n .custom-select.is-invalid ~ .invalid-tooltip {\n display: block; }\n\n.was-validated .form-control-file:invalid ~ .invalid-feedback,\n.was-validated .form-control-file:invalid ~ .invalid-tooltip, .form-control-file.is-invalid ~ .invalid-feedback,\n.form-control-file.is-invalid ~ .invalid-tooltip {\n display: block; }\n\n.was-validated .form-check-input:invalid ~ .form-check-label, .form-check-input.is-invalid ~ .form-check-label {\n color: #dc3545; }\n\n.was-validated .form-check-input:invalid ~ .invalid-feedback,\n.was-validated .form-check-input:invalid ~ .invalid-tooltip, .form-check-input.is-invalid ~ .invalid-feedback,\n.form-check-input.is-invalid ~ .invalid-tooltip {\n display: block; }\n\n.was-validated .custom-control-input:invalid ~ .custom-control-label, .custom-control-input.is-invalid ~ .custom-control-label {\n color: #dc3545; }\n .was-validated .custom-control-input:invalid ~ .custom-control-label::before, .custom-control-input.is-invalid ~ .custom-control-label::before {\n background-color: #efa2a9; }\n\n.was-validated .custom-control-input:invalid ~ .invalid-feedback,\n.was-validated .custom-control-input:invalid ~ .invalid-tooltip, .custom-control-input.is-invalid ~ .invalid-feedback,\n.custom-control-input.is-invalid ~ .invalid-tooltip {\n display: block; }\n\n.was-validated .custom-control-input:invalid:checked ~ .custom-control-label::before, .custom-control-input.is-invalid:checked ~ .custom-control-label::before {\n background-color: #e4606d; }\n\n.was-validated .custom-control-input:invalid:focus ~ .custom-control-label::before, .custom-control-input.is-invalid:focus ~ .custom-control-label::before {\n box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(220, 53, 69, 0.25); }\n\n.was-validated .custom-file-input:invalid ~ .custom-file-label, .custom-file-input.is-invalid ~ .custom-file-label {\n border-color: #dc3545; }\n .was-validated .custom-file-input:invalid ~ .custom-file-label::after, .custom-file-input.is-invalid ~ .custom-file-label::after {\n border-color: inherit; }\n\n.was-validated .custom-file-input:invalid ~ .invalid-feedback,\n.was-validated .custom-file-input:invalid ~ .invalid-tooltip, .custom-file-input.is-invalid ~ .invalid-feedback,\n.custom-file-input.is-invalid ~ .invalid-tooltip {\n display: block; }\n\n.was-validated .custom-file-input:invalid:focus ~ .custom-file-label, .custom-file-input.is-invalid:focus ~ .custom-file-label {\n box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25); }\n\n.form-inline {\n display: flex;\n flex-flow: row wrap;\n align-items: center; }\n .form-inline .form-check {\n width: 100%; }\n @media (min-width: 576px) {\n .form-inline label {\n display: flex;\n align-items: center;\n justify-content: center;\n margin-bottom: 0; }\n .form-inline .form-group {\n display: flex;\n flex: 0 0 auto;\n flex-flow: row wrap;\n align-items: center;\n margin-bottom: 0; }\n .form-inline .form-control {\n display: inline-block;\n width: auto;\n vertical-align: middle; }\n .form-inline .form-control-plaintext {\n display: inline-block; }\n .form-inline .input-group,\n .form-inline .custom-select {\n width: auto; }\n .form-inline .form-check {\n display: flex;\n align-items: center;\n justify-content: center;\n width: auto;\n padding-left: 0; }\n .form-inline .form-check-input {\n position: relative;\n margin-top: 0;\n margin-right: 0.25rem;\n margin-left: 0; }\n .form-inline .custom-control {\n align-items: center;\n justify-content: center; }\n .form-inline .custom-control-label {\n margin-bottom: 0; } }\n\n.btn {\n display: inline-block;\n font-weight: 400;\n text-align: center;\n white-space: nowrap;\n vertical-align: middle;\n user-select: none;\n border: 3px solid transparent;\n padding: 0.375rem 0.75rem;\n font-size: 1rem;\n line-height: 1.5;\n border-radius: 0.25rem;\n transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; }\n @media screen and (prefers-reduced-motion: reduce) {\n .btn {\n transition: none; } }\n .btn:hover, .btn:focus {\n text-decoration: none; }\n .btn:focus, .btn.focus {\n outline: 0;\n box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25); }\n .btn.disabled, .btn:disabled {\n opacity: 0.65; }\n .btn:not(:disabled):not(.disabled) {\n cursor: pointer; }\n\na.btn.disabled,\nfieldset:disabled a.btn {\n pointer-events: none; }\n\n.btn-primary {\n color: #fff;\n background-color: #007bff;\n border-color: #007bff; }\n .btn-primary:hover {\n color: #fff;\n background-color: #0069d9;\n border-color: #0062cc; }\n .btn-primary:focus, .btn-primary.focus {\n box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.5); }\n .btn-primary.disabled, .btn-primary:disabled {\n color: #fff;\n background-color: #007bff;\n border-color: #007bff; }\n .btn-primary:not(:disabled):not(.disabled):active, .btn-primary:not(:disabled):not(.disabled).active,\n .show > .btn-primary.dropdown-toggle {\n color: #fff;\n background-color: #0062cc;\n border-color: #005cbf; }\n .btn-primary:not(:disabled):not(.disabled):active:focus, .btn-primary:not(:disabled):not(.disabled).active:focus,\n .show > .btn-primary.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.5); }\n\n.btn-secondary {\n color: #fff;\n background-color: #6c757d;\n border-color: #6c757d; }\n .btn-secondary:hover {\n color: #fff;\n background-color: #5a6268;\n border-color: #545b62; }\n .btn-secondary:focus, .btn-secondary.focus {\n box-shadow: 0 0 0 0.2rem rgba(108, 117, 125, 0.5); }\n .btn-secondary.disabled, .btn-secondary:disabled {\n color: #fff;\n background-color: #6c757d;\n border-color: #6c757d; }\n .btn-secondary:not(:disabled):not(.disabled):active, .btn-secondary:not(:disabled):not(.disabled).active,\n .show > .btn-secondary.dropdown-toggle {\n color: #fff;\n background-color: #545b62;\n border-color: #4e555b; }\n .btn-secondary:not(:disabled):not(.disabled):active:focus, .btn-secondary:not(:disabled):not(.disabled).active:focus,\n .show > .btn-secondary.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(108, 117, 125, 0.5); }\n\n.btn-success {\n color: #fff;\n background-color: #28a745;\n border-color: #28a745; }\n .btn-success:hover {\n color: #fff;\n background-color: #218838;\n border-color: #1e7e34; }\n .btn-success:focus, .btn-success.focus {\n box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5); }\n .btn-success.disabled, .btn-success:disabled {\n color: #fff;\n background-color: #28a745;\n border-color: #28a745; }\n .btn-success:not(:disabled):not(.disabled):active, .btn-success:not(:disabled):not(.disabled).active,\n .show > .btn-success.dropdown-toggle {\n color: #fff;\n background-color: #1e7e34;\n border-color: #1c7430; }\n .btn-success:not(:disabled):not(.disabled):active:focus, .btn-success:not(:disabled):not(.disabled).active:focus,\n .show > .btn-success.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5); }\n\n.btn-info {\n color: #fff;\n background-color: #17a2b8;\n border-color: #17a2b8; }\n .btn-info:hover {\n color: #fff;\n background-color: #138496;\n border-color: #117a8b; }\n .btn-info:focus, .btn-info.focus {\n box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5); }\n .btn-info.disabled, .btn-info:disabled {\n color: #fff;\n background-color: #17a2b8;\n border-color: #17a2b8; }\n .btn-info:not(:disabled):not(.disabled):active, .btn-info:not(:disabled):not(.disabled).active,\n .show > .btn-info.dropdown-toggle {\n color: #fff;\n background-color: #117a8b;\n border-color: #10707f; }\n .btn-info:not(:disabled):not(.disabled):active:focus, .btn-info:not(:disabled):not(.disabled).active:focus,\n .show > .btn-info.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5); }\n\n.btn-warning {\n color: #212529;\n background-color: #ffc107;\n border-color: #ffc107; }\n .btn-warning:hover {\n color: #212529;\n background-color: #e0a800;\n border-color: #d39e00; }\n .btn-warning:focus, .btn-warning.focus {\n box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5); }\n .btn-warning.disabled, .btn-warning:disabled {\n color: #212529;\n background-color: #ffc107;\n border-color: #ffc107; }\n .btn-warning:not(:disabled):not(.disabled):active, .btn-warning:not(:disabled):not(.disabled).active,\n .show > .btn-warning.dropdown-toggle {\n color: #212529;\n background-color: #d39e00;\n border-color: #c69500; }\n .btn-warning:not(:disabled):not(.disabled):active:focus, .btn-warning:not(:disabled):not(.disabled).active:focus,\n .show > .btn-warning.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5); }\n\n.btn-danger {\n color: #fff;\n background-color: #dc3545;\n border-color: #dc3545; }\n .btn-danger:hover {\n color: #fff;\n background-color: #c82333;\n border-color: #bd2130; }\n .btn-danger:focus, .btn-danger.focus {\n box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5); }\n .btn-danger.disabled, .btn-danger:disabled {\n color: #fff;\n background-color: #dc3545;\n border-color: #dc3545; }\n .btn-danger:not(:disabled):not(.disabled):active, .btn-danger:not(:disabled):not(.disabled).active,\n .show > .btn-danger.dropdown-toggle {\n color: #fff;\n background-color: #bd2130;\n border-color: #b21f2d; }\n .btn-danger:not(:disabled):not(.disabled):active:focus, .btn-danger:not(:disabled):not(.disabled).active:focus,\n .show > .btn-danger.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5); }\n\n.btn-light {\n color: #212529;\n background-color: #f8f9fa;\n border-color: #f8f9fa; }\n .btn-light:hover {\n color: #212529;\n background-color: #e2e6ea;\n border-color: #dae0e5; }\n .btn-light:focus, .btn-light.focus {\n box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5); }\n .btn-light.disabled, .btn-light:disabled {\n color: #212529;\n background-color: #f8f9fa;\n border-color: #f8f9fa; }\n .btn-light:not(:disabled):not(.disabled):active, .btn-light:not(:disabled):not(.disabled).active,\n .show > .btn-light.dropdown-toggle {\n color: #212529;\n background-color: #dae0e5;\n border-color: #d3d9df; }\n .btn-light:not(:disabled):not(.disabled):active:focus, .btn-light:not(:disabled):not(.disabled).active:focus,\n .show > .btn-light.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5); }\n\n.btn-dark {\n color: #fff;\n background-color: #343a40;\n border-color: #343a40; }\n .btn-dark:hover {\n color: #fff;\n background-color: #23272b;\n border-color: #1d2124; }\n .btn-dark:focus, .btn-dark.focus {\n box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5); }\n .btn-dark.disabled, .btn-dark:disabled {\n color: #fff;\n background-color: #343a40;\n border-color: #343a40; }\n .btn-dark:not(:disabled):not(.disabled):active, .btn-dark:not(:disabled):not(.disabled).active,\n .show > .btn-dark.dropdown-toggle {\n color: #fff;\n background-color: #1d2124;\n border-color: #171a1d; }\n .btn-dark:not(:disabled):not(.disabled):active:focus, .btn-dark:not(:disabled):not(.disabled).active:focus,\n .show > .btn-dark.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5); }\n\n.btn-outline-primary {\n color: #007bff;\n background-color: transparent;\n background-image: none;\n border-color: #007bff; }\n .btn-outline-primary:hover {\n color: #fff;\n background-color: #007bff;\n border-color: #007bff; }\n .btn-outline-primary:focus, .btn-outline-primary.focus {\n box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.5); }\n .btn-outline-primary.disabled, .btn-outline-primary:disabled {\n color: #007bff;\n background-color: transparent; }\n .btn-outline-primary:not(:disabled):not(.disabled):active, .btn-outline-primary:not(:disabled):not(.disabled).active,\n .show > .btn-outline-primary.dropdown-toggle {\n color: #fff;\n background-color: #007bff;\n border-color: #007bff; }\n .btn-outline-primary:not(:disabled):not(.disabled):active:focus, .btn-outline-primary:not(:disabled):not(.disabled).active:focus,\n .show > .btn-outline-primary.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.5); }\n\n.btn-outline-secondary {\n color: #6c757d;\n background-color: transparent;\n background-image: none;\n border-color: #6c757d; }\n .btn-outline-secondary:hover {\n color: #fff;\n background-color: #6c757d;\n border-color: #6c757d; }\n .btn-outline-secondary:focus, .btn-outline-secondary.focus {\n box-shadow: 0 0 0 0.2rem rgba(108, 117, 125, 0.5); }\n .btn-outline-secondary.disabled, .btn-outline-secondary:disabled {\n color: #6c757d;\n background-color: transparent; }\n .btn-outline-secondary:not(:disabled):not(.disabled):active, .btn-outline-secondary:not(:disabled):not(.disabled).active,\n .show > .btn-outline-secondary.dropdown-toggle {\n color: #fff;\n background-color: #6c757d;\n border-color: #6c757d; }\n .btn-outline-secondary:not(:disabled):not(.disabled):active:focus, .btn-outline-secondary:not(:disabled):not(.disabled).active:focus,\n .show > .btn-outline-secondary.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(108, 117, 125, 0.5); }\n\n.btn-outline-success {\n color: #28a745;\n background-color: transparent;\n background-image: none;\n border-color: #28a745; }\n .btn-outline-success:hover {\n color: #fff;\n background-color: #28a745;\n border-color: #28a745; }\n .btn-outline-success:focus, .btn-outline-success.focus {\n box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5); }\n .btn-outline-success.disabled, .btn-outline-success:disabled {\n color: #28a745;\n background-color: transparent; }\n .btn-outline-success:not(:disabled):not(.disabled):active, .btn-outline-success:not(:disabled):not(.disabled).active,\n .show > .btn-outline-success.dropdown-toggle {\n color: #fff;\n background-color: #28a745;\n border-color: #28a745; }\n .btn-outline-success:not(:disabled):not(.disabled):active:focus, .btn-outline-success:not(:disabled):not(.disabled).active:focus,\n .show > .btn-outline-success.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5); }\n\n.btn-outline-info {\n color: #17a2b8;\n background-color: transparent;\n background-image: none;\n border-color: #17a2b8; }\n .btn-outline-info:hover {\n color: #fff;\n background-color: #17a2b8;\n border-color: #17a2b8; }\n .btn-outline-info:focus, .btn-outline-info.focus {\n box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5); }\n .btn-outline-info.disabled, .btn-outline-info:disabled {\n color: #17a2b8;\n background-color: transparent; }\n .btn-outline-info:not(:disabled):not(.disabled):active, .btn-outline-info:not(:disabled):not(.disabled).active,\n .show > .btn-outline-info.dropdown-toggle {\n color: #fff;\n background-color: #17a2b8;\n border-color: #17a2b8; }\n .btn-outline-info:not(:disabled):not(.disabled):active:focus, .btn-outline-info:not(:disabled):not(.disabled).active:focus,\n .show > .btn-outline-info.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5); }\n\n.btn-outline-warning {\n color: #ffc107;\n background-color: transparent;\n background-image: none;\n border-color: #ffc107; }\n .btn-outline-warning:hover {\n color: #212529;\n background-color: #ffc107;\n border-color: #ffc107; }\n .btn-outline-warning:focus, .btn-outline-warning.focus {\n box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5); }\n .btn-outline-warning.disabled, .btn-outline-warning:disabled {\n color: #ffc107;\n background-color: transparent; }\n .btn-outline-warning:not(:disabled):not(.disabled):active, .btn-outline-warning:not(:disabled):not(.disabled).active,\n .show > .btn-outline-warning.dropdown-toggle {\n color: #212529;\n background-color: #ffc107;\n border-color: #ffc107; }\n .btn-outline-warning:not(:disabled):not(.disabled):active:focus, .btn-outline-warning:not(:disabled):not(.disabled).active:focus,\n .show > .btn-outline-warning.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5); }\n\n.btn-outline-danger {\n color: #dc3545;\n background-color: transparent;\n background-image: none;\n border-color: #dc3545; }\n .btn-outline-danger:hover {\n color: #fff;\n background-color: #dc3545;\n border-color: #dc3545; }\n .btn-outline-danger:focus, .btn-outline-danger.focus {\n box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5); }\n .btn-outline-danger.disabled, .btn-outline-danger:disabled {\n color: #dc3545;\n background-color: transparent; }\n .btn-outline-danger:not(:disabled):not(.disabled):active, .btn-outline-danger:not(:disabled):not(.disabled).active,\n .show > .btn-outline-danger.dropdown-toggle {\n color: #fff;\n background-color: #dc3545;\n border-color: #dc3545; }\n .btn-outline-danger:not(:disabled):not(.disabled):active:focus, .btn-outline-danger:not(:disabled):not(.disabled).active:focus,\n .show > .btn-outline-danger.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5); }\n\n.btn-outline-light {\n color: #f8f9fa;\n background-color: transparent;\n background-image: none;\n border-color: #f8f9fa; }\n .btn-outline-light:hover {\n color: #212529;\n background-color: #f8f9fa;\n border-color: #f8f9fa; }\n .btn-outline-light:focus, .btn-outline-light.focus {\n box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5); }\n .btn-outline-light.disabled, .btn-outline-light:disabled {\n color: #f8f9fa;\n background-color: transparent; }\n .btn-outline-light:not(:disabled):not(.disabled):active, .btn-outline-light:not(:disabled):not(.disabled).active,\n .show > .btn-outline-light.dropdown-toggle {\n color: #212529;\n background-color: #f8f9fa;\n border-color: #f8f9fa; }\n .btn-outline-light:not(:disabled):not(.disabled):active:focus, .btn-outline-light:not(:disabled):not(.disabled).active:focus,\n .show > .btn-outline-light.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5); }\n\n.btn-outline-dark {\n color: #343a40;\n background-color: transparent;\n background-image: none;\n border-color: #343a40; }\n .btn-outline-dark:hover {\n color: #fff;\n background-color: #343a40;\n border-color: #343a40; }\n .btn-outline-dark:focus, .btn-outline-dark.focus {\n box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5); }\n .btn-outline-dark.disabled, .btn-outline-dark:disabled {\n color: #343a40;\n background-color: transparent; }\n .btn-outline-dark:not(:disabled):not(.disabled):active, .btn-outline-dark:not(:disabled):not(.disabled).active,\n .show > .btn-outline-dark.dropdown-toggle {\n color: #fff;\n background-color: #343a40;\n border-color: #343a40; }\n .btn-outline-dark:not(:disabled):not(.disabled):active:focus, .btn-outline-dark:not(:disabled):not(.disabled).active:focus,\n .show > .btn-outline-dark.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5); }\n\n.btn-link {\n font-weight: 400;\n color: #007bff;\n background-color: transparent; }\n .btn-link:hover {\n color: #0056b3;\n text-decoration: underline;\n background-color: transparent;\n border-color: transparent; }\n .btn-link:focus, .btn-link.focus {\n text-decoration: underline;\n border-color: transparent;\n box-shadow: none; }\n .btn-link:disabled, .btn-link.disabled {\n color: #6c757d;\n pointer-events: none; }\n\n.btn-lg, .btn-group-lg > .btn {\n padding: 0.5rem 1rem;\n font-size: 1.25rem;\n line-height: 1.5;\n border-radius: 0; }\n\n.btn-sm, .btn-group-sm > .btn {\n padding: 0.25rem 0.5rem;\n font-size: 0.875rem;\n line-height: 1.5;\n border-radius: 0.2rem; }\n\n.btn-block {\n display: block;\n width: 100%; }\n .btn-block + .btn-block {\n margin-top: 0.5rem; }\n\ninput[type="submit"].btn-block,\ninput[type="reset"].btn-block,\ninput[type="button"].btn-block {\n width: 100%; }\n\n.fade {\n transition: opacity 0.15s linear; }\n @media screen and (prefers-reduced-motion: reduce) {\n .fade {\n transition: none; } }\n .fade:not(.show) {\n opacity: 0; }\n\n.collapse:not(.show) {\n display: none; }\n\n.collapsing {\n position: relative;\n height: 0;\n overflow: hidden;\n transition: height 0.35s ease; }\n @media screen and (prefers-reduced-motion: reduce) {\n .collapsing {\n transition: none; } }\n\n.dropup,\n.dropright,\n.dropdown,\n.dropleft {\n position: relative; }\n\n.dropdown-toggle::after {\n display: inline-block;\n width: 0;\n height: 0;\n margin-left: 0.255em;\n vertical-align: 0.255em;\n content: "";\n border-top: 0.3em solid;\n border-right: 0.3em solid transparent;\n border-bottom: 0;\n border-left: 0.3em solid transparent; }\n\n.dropdown-toggle:empty::after {\n margin-left: 0; }\n\n.dropdown-menu {\n position: absolute;\n top: 100%;\n left: 0;\n z-index: 1000;\n display: none;\n float: left;\n min-width: 10rem;\n padding: 0.5rem 0;\n margin: 0.125rem 0 0;\n font-size: 1rem;\n color: #212529;\n text-align: left;\n list-style: none;\n background-color: #fff;\n background-clip: padding-box;\n border: 1px solid rgba(0, 0, 0, 0.15);\n border-radius: 0.25rem; }\n\n.dropdown-menu-right {\n right: 0;\n left: auto; }\n\n.dropup .dropdown-menu {\n top: auto;\n bottom: 100%;\n margin-top: 0;\n margin-bottom: 0.125rem; }\n\n.dropup .dropdown-toggle::after {\n display: inline-block;\n width: 0;\n height: 0;\n margin-left: 0.255em;\n vertical-align: 0.255em;\n content: "";\n border-top: 0;\n border-right: 0.3em solid transparent;\n border-bottom: 0.3em solid;\n border-left: 0.3em solid transparent; }\n\n.dropup .dropdown-toggle:empty::after {\n margin-left: 0; }\n\n.dropright .dropdown-menu {\n top: 0;\n right: auto;\n left: 100%;\n margin-top: 0;\n margin-left: 0.125rem; }\n\n.dropright .dropdown-toggle::after {\n display: inline-block;\n width: 0;\n height: 0;\n margin-left: 0.255em;\n vertical-align: 0.255em;\n content: "";\n border-top: 0.3em solid transparent;\n border-right: 0;\n border-bottom: 0.3em solid transparent;\n border-left: 0.3em solid; }\n\n.dropright .dropdown-toggle:empty::after {\n margin-left: 0; }\n\n.dropright .dropdown-toggle::after {\n vertical-align: 0; }\n\n.dropleft .dropdown-menu {\n top: 0;\n right: 100%;\n left: auto;\n margin-top: 0;\n margin-right: 0.125rem; }\n\n.dropleft .dropdown-toggle::after {\n display: inline-block;\n width: 0;\n height: 0;\n margin-left: 0.255em;\n vertical-align: 0.255em;\n content: ""; }\n\n.dropleft .dropdown-toggle::after {\n display: none; }\n\n.dropleft .dropdown-toggle::before {\n display: inline-block;\n width: 0;\n height: 0;\n margin-right: 0.255em;\n vertical-align: 0.255em;\n content: "";\n border-top: 0.3em solid transparent;\n border-right: 0.3em solid;\n border-bottom: 0.3em solid transparent; }\n\n.dropleft .dropdown-toggle:empty::after {\n margin-left: 0; }\n\n.dropleft .dropdown-toggle::before {\n vertical-align: 0; }\n\n.dropdown-menu[x-placement^="top"], .dropdown-menu[x-placement^="right"], .dropdown-menu[x-placement^="bottom"], .dropdown-menu[x-placement^="left"] {\n right: auto;\n bottom: auto; }\n\n.dropdown-divider {\n height: 0;\n margin: 0.5rem 0;\n overflow: hidden;\n border-top: 1px solid #e9ecef; }\n\n.dropdown-item {\n display: block;\n width: 100%;\n padding: 0.25rem 1.5rem;\n clear: both;\n font-weight: 400;\n color: #212529;\n text-align: inherit;\n white-space: nowrap;\n background-color: transparent;\n border: 0; }\n .dropdown-item:hover, .dropdown-item:focus {\n color: #16181b;\n text-decoration: none;\n background-color: #f8f9fa; }\n .dropdown-item.active, .dropdown-item:active {\n color: #fff;\n text-decoration: none;\n background-color: #007bff; }\n .dropdown-item.disabled, .dropdown-item:disabled {\n color: #6c757d;\n background-color: transparent; }\n\n.dropdown-menu.show {\n display: block; }\n\n.dropdown-header {\n display: block;\n padding: 0.5rem 1.5rem;\n margin-bottom: 0;\n font-size: 0.875rem;\n color: #6c757d;\n white-space: nowrap; }\n\n.dropdown-item-text {\n display: block;\n padding: 0.25rem 1.5rem;\n color: #212529; }\n\n.btn-group,\n.btn-group-vertical {\n position: relative;\n display: inline-flex;\n vertical-align: middle; }\n .btn-group > .btn,\n .btn-group-vertical > .btn {\n position: relative;\n flex: 0 1 auto; }\n .btn-group > .btn:hover,\n .btn-group-vertical > .btn:hover {\n z-index: 1; }\n .btn-group > .btn:focus, .btn-group > .btn:active, .btn-group > .btn.active,\n .btn-group-vertical > .btn:focus,\n .btn-group-vertical > .btn:active,\n .btn-group-vertical > .btn.active {\n z-index: 1; }\n .btn-group .btn + .btn,\n .btn-group .btn + .btn-group,\n .btn-group .btn-group + .btn,\n .btn-group .btn-group + .btn-group,\n .btn-group-vertical .btn + .btn,\n .btn-group-vertical .btn + .btn-group,\n .btn-group-vertical .btn-group + .btn,\n .btn-group-vertical .btn-group + .btn-group {\n margin-left: -3px; }\n\n.btn-toolbar {\n display: flex;\n flex-wrap: wrap;\n justify-content: flex-start; }\n .btn-toolbar .input-group {\n width: auto; }\n\n.btn-group > .btn:first-child {\n margin-left: 0; }\n\n.btn-group > .btn:not(:last-child):not(.dropdown-toggle),\n.btn-group > .btn-group:not(:last-child) > .btn {\n border-top-right-radius: 0;\n border-bottom-right-radius: 0; }\n\n.btn-group > .btn:not(:first-child),\n.btn-group > .btn-group:not(:first-child) > .btn {\n border-top-left-radius: 0;\n border-bottom-left-radius: 0; }\n\n.dropdown-toggle-split {\n padding-right: 0.5625rem;\n padding-left: 0.5625rem; }\n .dropdown-toggle-split::after,\n .dropup .dropdown-toggle-split::after,\n .dropright .dropdown-toggle-split::after {\n margin-left: 0; }\n .dropleft .dropdown-toggle-split::before {\n margin-right: 0; }\n\n.btn-sm + .dropdown-toggle-split, .btn-group-sm > .btn + .dropdown-toggle-split {\n padding-right: 0.375rem;\n padding-left: 0.375rem; }\n\n.btn-lg + .dropdown-toggle-split, .btn-group-lg > .btn + .dropdown-toggle-split {\n padding-right: 0.75rem;\n padding-left: 0.75rem; }\n\n.btn-group-vertical {\n flex-direction: column;\n align-items: flex-start;\n justify-content: center; }\n .btn-group-vertical .btn,\n .btn-group-vertical .btn-group {\n width: 100%; }\n .btn-group-vertical > .btn + .btn,\n .btn-group-vertical > .btn + .btn-group,\n .btn-group-vertical > .btn-group + .btn,\n .btn-group-vertical > .btn-group + .btn-group {\n margin-top: -3px;\n margin-left: 0; }\n .btn-group-vertical > .btn:not(:last-child):not(.dropdown-toggle),\n .btn-group-vertical > .btn-group:not(:last-child) > .btn {\n border-bottom-right-radius: 0;\n border-bottom-left-radius: 0; }\n .btn-group-vertical > .btn:not(:first-child),\n .btn-group-vertical > .btn-group:not(:first-child) > .btn {\n border-top-left-radius: 0;\n border-top-right-radius: 0; }\n\n.btn-group-toggle > .btn,\n.btn-group-toggle > .btn-group > .btn {\n margin-bottom: 0; }\n .btn-group-toggle > .btn input[type="radio"],\n .btn-group-toggle > .btn input[type="checkbox"],\n .btn-group-toggle > .btn-group > .btn input[type="radio"],\n .btn-group-toggle > .btn-group > .btn input[type="checkbox"] {\n position: absolute;\n clip: rect(0, 0, 0, 0);\n pointer-events: none; }\n\n.input-group {\n position: relative;\n display: flex;\n flex-wrap: wrap;\n align-items: stretch;\n width: 100%; }\n .input-group > .form-control,\n .input-group > .custom-select,\n .input-group > .custom-file {\n position: relative;\n flex: 1 1 auto;\n width: 1%;\n margin-bottom: 0; }\n .input-group > .form-control + .form-control,\n .input-group > .form-control + .custom-select,\n .input-group > .form-control + .custom-file,\n .input-group > .custom-select + .form-control,\n .input-group > .custom-select + .custom-select,\n .input-group > .custom-select + .custom-file,\n .input-group > .custom-file + .form-control,\n .input-group > .custom-file + .custom-select,\n .input-group > .custom-file + .custom-file {\n margin-left: -1px; }\n .input-group > .form-control:focus,\n .input-group > .custom-select:focus,\n .input-group > .custom-file .custom-file-input:focus ~ .custom-file-label {\n z-index: 3; }\n .input-group > .custom-file .custom-file-input:focus {\n z-index: 4; }\n .input-group > .form-control:not(:last-child),\n .input-group > .custom-select:not(:last-child) {\n border-top-right-radius: 0;\n border-bottom-right-radius: 0; }\n .input-group > .form-control:not(:first-child),\n .input-group > .custom-select:not(:first-child) {\n border-top-left-radius: 0;\n border-bottom-left-radius: 0; }\n .input-group > .custom-file {\n display: flex;\n align-items: center; }\n .input-group > .custom-file:not(:last-child) .custom-file-label,\n .input-group > .custom-file:not(:last-child) .custom-file-label::after {\n border-top-right-radius: 0;\n border-bottom-right-radius: 0; }\n .input-group > .custom-file:not(:first-child) .custom-file-label {\n border-top-left-radius: 0;\n border-bottom-left-radius: 0; }\n\n.input-group-prepend,\n.input-group-append {\n display: flex; }\n .input-group-prepend .btn,\n .input-group-append .btn {\n position: relative;\n z-index: 2; }\n .input-group-prepend .btn + .btn,\n .input-group-prepend .btn + .input-group-text,\n .input-group-prepend .input-group-text + .input-group-text,\n .input-group-prepend .input-group-text + .btn,\n .input-group-append .btn + .btn,\n .input-group-append .btn + .input-group-text,\n .input-group-append .input-group-text + .input-group-text,\n .input-group-append .input-group-text + .btn {\n margin-left: -1px; }\n\n.input-group-prepend {\n margin-right: -1px; }\n\n.input-group-append {\n margin-left: -1px; }\n\n.input-group-text {\n display: flex;\n align-items: center;\n padding: 0.375rem 0.75rem;\n margin-bottom: 0;\n font-size: 1rem;\n font-weight: 400;\n line-height: 1.5;\n color: #495057;\n text-align: center;\n white-space: nowrap;\n background-color: #e9ecef;\n border: 1px solid #ced4da;\n border-radius: 0.25rem; }\n .input-group-text input[type="radio"],\n .input-group-text input[type="checkbox"] {\n margin-top: 0; }\n\n.input-group-lg > .form-control,\n.input-group-lg > .input-group-prepend > .input-group-text,\n.input-group-lg > .input-group-append > .input-group-text,\n.input-group-lg > .input-group-prepend > .btn,\n.input-group-lg > .input-group-append > .btn {\n height: calc(2.875rem + 2px);\n padding: 0.5rem 1rem;\n font-size: 1.25rem;\n line-height: 1.5;\n border-radius: 0; }\n\n.input-group-sm > .form-control,\n.input-group-sm > .input-group-prepend > .input-group-text,\n.input-group-sm > .input-group-append > .input-group-text,\n.input-group-sm > .input-group-prepend > .btn,\n.input-group-sm > .input-group-append > .btn {\n height: calc(1.8125rem + 2px);\n padding: 0.25rem 0.5rem;\n font-size: 0.875rem;\n line-height: 1.5;\n border-radius: 0.2rem; }\n\n.input-group > .input-group-prepend > .btn,\n.input-group > .input-group-prepend > .input-group-text,\n.input-group > .input-group-append:not(:last-child) > .btn,\n.input-group > .input-group-append:not(:last-child) > .input-group-text,\n.input-group > .input-group-append:last-child > .btn:not(:last-child):not(.dropdown-toggle),\n.input-group > .input-group-append:last-child > .input-group-text:not(:last-child) {\n border-top-right-radius: 0;\n border-bottom-right-radius: 0; }\n\n.input-group > .input-group-append > .btn,\n.input-group > .input-group-append > .input-group-text,\n.input-group > .input-group-prepend:not(:first-child) > .btn,\n.input-group > .input-group-prepend:not(:first-child) > .input-group-text,\n.input-group > .input-group-prepend:first-child > .btn:not(:first-child),\n.input-group > .input-group-prepend:first-child > .input-group-text:not(:first-child) {\n border-top-left-radius: 0;\n border-bottom-left-radius: 0; }\n\n.custom-control {\n position: relative;\n display: block;\n min-height: 1.5rem;\n padding-left: 1.5rem; }\n\n.custom-control-inline {\n display: inline-flex;\n margin-right: 1rem; }\n\n.custom-control-input {\n position: absolute;\n z-index: -1;\n opacity: 0; }\n .custom-control-input:checked ~ .custom-control-label::before {\n color: #fff;\n background-color: #007bff; }\n .custom-control-input:focus ~ .custom-control-label::before {\n box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(0, 123, 255, 0.25); }\n .custom-control-input:active ~ .custom-control-label::before {\n color: #fff;\n background-color: #b3d7ff; }\n .custom-control-input:disabled ~ .custom-control-label {\n color: #6c757d; }\n .custom-control-input:disabled ~ .custom-control-label::before {\n background-color: #e9ecef; }\n\n.custom-control-label {\n position: relative;\n margin-bottom: 0; }\n .custom-control-label::before {\n position: absolute;\n top: 0.25rem;\n left: -1.5rem;\n display: block;\n width: 1rem;\n height: 1rem;\n pointer-events: none;\n content: "";\n user-select: none;\n background-color: #dee2e6; }\n .custom-control-label::after {\n position: absolute;\n top: 0.25rem;\n left: -1.5rem;\n display: block;\n width: 1rem;\n height: 1rem;\n content: "";\n background-repeat: no-repeat;\n background-position: center center;\n background-size: 50% 50%; }\n\n.custom-checkbox .custom-control-label::before {\n border-radius: 0.25rem; }\n\n.custom-checkbox .custom-control-input:checked ~ .custom-control-label::before {\n background-color: #007bff; }\n\n.custom-checkbox .custom-control-input:checked ~ .custom-control-label::after {\n background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns=\'http://www.w3.org/2000/svg\' viewBox=\'0 0 8 8\'%3E%3Cpath fill=\'%23fff\' d=\'M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z\'/%3E%3C/svg%3E"); }\n\n.custom-checkbox .custom-control-input:indeterminate ~ .custom-control-label::before {\n background-color: #007bff; }\n\n.custom-checkbox .custom-control-input:indeterminate ~ .custom-control-label::after {\n background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns=\'http://www.w3.org/2000/svg\' viewBox=\'0 0 4 4\'%3E%3Cpath stroke=\'%23fff\' d=\'M0 2h4\'/%3E%3C/svg%3E"); }\n\n.custom-checkbox .custom-control-input:disabled:checked ~ .custom-control-label::before {\n background-color: rgba(0, 123, 255, 0.5); }\n\n.custom-checkbox .custom-control-input:disabled:indeterminate ~ .custom-control-label::before {\n background-color: rgba(0, 123, 255, 0.5); }\n\n.custom-radio .custom-control-label::before {\n border-radius: 50%; }\n\n.custom-radio .custom-control-input:checked ~ .custom-control-label::before {\n background-color: #007bff; }\n\n.custom-radio .custom-control-input:checked ~ .custom-control-label::after {\n background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns=\'http://www.w3.org/2000/svg\' viewBox=\'-4 -4 8 8\'%3E%3Ccircle r=\'3\' fill=\'%23fff\'/%3E%3C/svg%3E"); }\n\n.custom-radio .custom-control-input:disabled:checked ~ .custom-control-label::before {\n background-color: rgba(0, 123, 255, 0.5); }\n\n.custom-select {\n display: inline-block;\n width: 100%;\n height: calc(2.25rem + 2px);\n padding: 0.375rem 1.75rem 0.375rem 0.75rem;\n line-height: 1.5;\n color: #495057;\n vertical-align: middle;\n background: #fff url("data:image/svg+xml;charset=utf8,%3Csvg xmlns=\'http://www.w3.org/2000/svg\' viewBox=\'0 0 4 5\'%3E%3Cpath fill=\'%23343a40\' d=\'M2 0L0 2h4zm0 5L0 3h4z\'/%3E%3C/svg%3E") no-repeat right 0.75rem center;\n background-size: 8px 10px;\n border: 1px solid #ced4da;\n border-radius: 0.25rem;\n appearance: none; }\n .custom-select:focus {\n border-color: #80bdff;\n outline: 0;\n box-shadow: 0 0 0 0.2rem rgba(128, 189, 255, 0.5); }\n .custom-select:focus::-ms-value {\n color: #495057;\n background-color: #fff; }\n .custom-select[multiple], .custom-select[size]:not([size="1"]) {\n height: auto;\n padding-right: 0.75rem;\n background-image: none; }\n .custom-select:disabled {\n color: #6c757d;\n background-color: #e9ecef; }\n .custom-select::-ms-expand {\n opacity: 0; }\n\n.custom-select-sm {\n height: calc(1.8125rem + 2px);\n padding-top: 0.375rem;\n padding-bottom: 0.375rem;\n font-size: 75%; }\n\n.custom-select-lg {\n height: calc(2.875rem + 2px);\n padding-top: 0.375rem;\n padding-bottom: 0.375rem;\n font-size: 125%; }\n\n.custom-file {\n position: relative;\n display: inline-block;\n width: 100%;\n height: calc(2.25rem + 2px);\n margin-bottom: 0; }\n\n.custom-file-input {\n position: relative;\n z-index: 2;\n width: 100%;\n height: calc(2.25rem + 2px);\n margin: 0;\n opacity: 0; }\n .custom-file-input:focus ~ .custom-file-label {\n border-color: #80bdff;\n box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25); }\n .custom-file-input:focus ~ .custom-file-label::after {\n border-color: #80bdff; }\n .custom-file-input:disabled ~ .custom-file-label {\n background-color: #e9ecef; }\n .custom-file-input:lang(en) ~ .custom-file-label::after {\n content: "Browse"; }\n\n.custom-file-label {\n position: absolute;\n top: 0;\n right: 0;\n left: 0;\n z-index: 1;\n height: calc(2.25rem + 2px);\n padding: 0.375rem 0.75rem;\n line-height: 1.5;\n color: #495057;\n background-color: #fff;\n border: 1px solid #ced4da;\n border-radius: 0.25rem; }\n .custom-file-label::after {\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n z-index: 3;\n display: block;\n height: 2.25rem;\n padding: 0.375rem 0.75rem;\n line-height: 1.5;\n color: #495057;\n content: "Browse";\n background-color: #e9ecef;\n border-left: 1px solid #ced4da;\n border-radius: 0 0.25rem 0.25rem 0; }\n\n.custom-range {\n width: 100%;\n padding-left: 0;\n background-color: transparent;\n appearance: none; }\n .custom-range:focus {\n outline: none; }\n .custom-range:focus::-webkit-slider-thumb {\n box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(0, 123, 255, 0.25); }\n .custom-range:focus::-moz-range-thumb {\n box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(0, 123, 255, 0.25); }\n .custom-range:focus::-ms-thumb {\n box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(0, 123, 255, 0.25); }\n .custom-range::-moz-focus-outer {\n border: 0; }\n .custom-range::-webkit-slider-thumb {\n width: 1rem;\n height: 1rem;\n margin-top: -0.25rem;\n background-color: #007bff;\n border: 0;\n border-radius: 1rem;\n transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n appearance: none; }\n @media screen and (prefers-reduced-motion: reduce) {\n .custom-range::-webkit-slider-thumb {\n transition: none; } }\n .custom-range::-webkit-slider-thumb:active {\n background-color: #b3d7ff; }\n .custom-range::-webkit-slider-runnable-track {\n width: 100%;\n height: 0.5rem;\n color: transparent;\n cursor: pointer;\n background-color: #dee2e6;\n border-color: transparent;\n border-radius: 1rem; }\n .custom-range::-moz-range-thumb {\n width: 1rem;\n height: 1rem;\n background-color: #007bff;\n border: 0;\n border-radius: 1rem;\n transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n appearance: none; }\n @media screen and (prefers-reduced-motion: reduce) {\n .custom-range::-moz-range-thumb {\n transition: none; } }\n .custom-range::-moz-range-thumb:active {\n background-color: #b3d7ff; }\n .custom-range::-moz-range-track {\n width: 100%;\n height: 0.5rem;\n color: transparent;\n cursor: pointer;\n background-color: #dee2e6;\n border-color: transparent;\n border-radius: 1rem; }\n .custom-range::-ms-thumb {\n width: 1rem;\n height: 1rem;\n margin-top: 0;\n margin-right: 0.2rem;\n margin-left: 0.2rem;\n background-color: #007bff;\n border: 0;\n border-radius: 1rem;\n transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n appearance: none; }\n @media screen and (prefers-reduced-motion: reduce) {\n .custom-range::-ms-thumb {\n transition: none; } }\n .custom-range::-ms-thumb:active {\n background-color: #b3d7ff; }\n .custom-range::-ms-track {\n width: 100%;\n height: 0.5rem;\n color: transparent;\n cursor: pointer;\n background-color: transparent;\n border-color: transparent;\n border-width: 0.5rem; }\n .custom-range::-ms-fill-lower {\n background-color: #dee2e6;\n border-radius: 1rem; }\n .custom-range::-ms-fill-upper {\n margin-right: 15px;\n background-color: #dee2e6;\n border-radius: 1rem; }\n\n.custom-control-label::before,\n.custom-file-label,\n.custom-select {\n transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; }\n @media screen and (prefers-reduced-motion: reduce) {\n .custom-control-label::before,\n .custom-file-label,\n .custom-select {\n transition: none; } }\n\n.nav {\n display: flex;\n flex-wrap: wrap;\n padding-left: 0;\n margin-bottom: 0;\n list-style: none; }\n\n.nav-link {\n display: block;\n padding: 0.5rem 1rem; }\n .nav-link:hover, .nav-link:focus {\n text-decoration: none; }\n .nav-link.disabled {\n color: #6c757d; }\n\n.nav-tabs {\n border-bottom: 1px solid #dee2e6; }\n .nav-tabs .nav-item {\n margin-bottom: -1px; }\n .nav-tabs .nav-link {\n border: 1px solid transparent;\n border-top-left-radius: 0.25rem;\n border-top-right-radius: 0.25rem; }\n .nav-tabs .nav-link:hover, .nav-tabs .nav-link:focus {\n border-color: #e9ecef #e9ecef #dee2e6; }\n .nav-tabs .nav-link.disabled {\n color: #6c757d;\n background-color: transparent;\n border-color: transparent; }\n .nav-tabs .nav-link.active,\n .nav-tabs .nav-item.show .nav-link {\n color: #495057;\n background-color: #fff;\n border-color: #dee2e6 #dee2e6 #fff; }\n .nav-tabs .dropdown-menu {\n margin-top: -1px;\n border-top-left-radius: 0;\n border-top-right-radius: 0; }\n\n.nav-pills .nav-link {\n border-radius: 0.25rem; }\n\n.nav-pills .nav-link.active,\n.nav-pills .show > .nav-link {\n color: #fff;\n background-color: #007bff; }\n\n.nav-fill .nav-item {\n flex: 1 1 auto;\n text-align: center; }\n\n.nav-justified .nav-item {\n flex-basis: 0;\n flex-grow: 1;\n text-align: center; }\n\n.tab-content > .tab-pane {\n display: none; }\n\n.tab-content > .active {\n display: block; }\n\n.navbar {\n position: relative;\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n justify-content: space-between;\n padding: 0.5rem 1rem; }\n .navbar > .container,\n .navbar > .container-fluid {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n justify-content: space-between; }\n\n.navbar-brand {\n display: inline-block;\n padding-top: 0.3125rem;\n padding-bottom: 0.3125rem;\n margin-right: 1rem;\n font-size: 1.25rem;\n line-height: inherit;\n white-space: nowrap; }\n .navbar-brand:hover, .navbar-brand:focus {\n text-decoration: none; }\n\n.navbar-nav {\n display: flex;\n flex-direction: column;\n padding-left: 0;\n margin-bottom: 0;\n list-style: none; }\n .navbar-nav .nav-link {\n padding-right: 0;\n padding-left: 0; }\n .navbar-nav .dropdown-menu {\n position: static;\n float: none; }\n\n.navbar-text {\n display: inline-block;\n padding-top: 0.5rem;\n padding-bottom: 0.5rem; }\n\n.navbar-collapse {\n flex-basis: 100%;\n flex-grow: 1;\n align-items: center; }\n\n.navbar-toggler {\n padding: 0.25rem 0.75rem;\n font-size: 1.25rem;\n line-height: 1;\n background-color: transparent;\n border: 1px solid transparent;\n border-radius: 0.25rem; }\n .navbar-toggler:hover, .navbar-toggler:focus {\n text-decoration: none; }\n .navbar-toggler:not(:disabled):not(.disabled) {\n cursor: pointer; }\n\n.navbar-toggler-icon {\n display: inline-block;\n width: 1.5em;\n height: 1.5em;\n vertical-align: middle;\n content: "";\n background: no-repeat center center;\n background-size: 100% 100%; }\n\n@media (max-width: 575.98px) {\n .navbar-expand-sm > .container,\n .navbar-expand-sm > .container-fluid {\n padding-right: 0;\n padding-left: 0; } }\n\n@media (min-width: 576px) {\n .navbar-expand-sm {\n flex-flow: row nowrap;\n justify-content: flex-start; }\n .navbar-expand-sm .navbar-nav {\n flex-direction: row; }\n .navbar-expand-sm .navbar-nav .dropdown-menu {\n position: absolute; }\n .navbar-expand-sm .navbar-nav .nav-link {\n padding-right: 0.5rem;\n padding-left: 0.5rem; }\n .navbar-expand-sm > .container,\n .navbar-expand-sm > .container-fluid {\n flex-wrap: nowrap; }\n .navbar-expand-sm .navbar-collapse {\n display: flex !important;\n flex-basis: auto; }\n .navbar-expand-sm .navbar-toggler {\n display: none; } }\n\n@media (max-width: 767.98px) {\n .navbar-expand-md > .container,\n .navbar-expand-md > .container-fluid {\n padding-right: 0;\n padding-left: 0; } }\n\n@media (min-width: 768px) {\n .navbar-expand-md {\n flex-flow: row nowrap;\n justify-content: flex-start; }\n .navbar-expand-md .navbar-nav {\n flex-direction: row; }\n .navbar-expand-md .navbar-nav .dropdown-menu {\n position: absolute; }\n .navbar-expand-md .navbar-nav .nav-link {\n padding-right: 0.5rem;\n padding-left: 0.5rem; }\n .navbar-expand-md > .container,\n .navbar-expand-md > .container-fluid {\n flex-wrap: nowrap; }\n .navbar-expand-md .navbar-collapse {\n display: flex !important;\n flex-basis: auto; }\n .navbar-expand-md .navbar-toggler {\n display: none; } }\n\n@media (max-width: 991.98px) {\n .navbar-expand-lg > .container,\n .navbar-expand-lg > .container-fluid {\n padding-right: 0;\n padding-left: 0; } }\n\n@media (min-width: 992px) {\n .navbar-expand-lg {\n flex-flow: row nowrap;\n justify-content: flex-start; }\n .navbar-expand-lg .navbar-nav {\n flex-direction: row; }\n .navbar-expand-lg .navbar-nav .dropdown-menu {\n position: absolute; }\n .navbar-expand-lg .navbar-nav .nav-link {\n padding-right: 0.5rem;\n padding-left: 0.5rem; }\n .navbar-expand-lg > .container,\n .navbar-expand-lg > .container-fluid {\n flex-wrap: nowrap; }\n .navbar-expand-lg .navbar-collapse {\n display: flex !important;\n flex-basis: auto; }\n .navbar-expand-lg .navbar-toggler {\n display: none; } }\n\n@media (max-width: 1199.98px) {\n .navbar-expand-xl > .container,\n .navbar-expand-xl > .container-fluid {\n padding-right: 0;\n padding-left: 0; } }\n\n@media (min-width: 1200px) {\n .navbar-expand-xl {\n flex-flow: row nowrap;\n justify-content: flex-start; }\n .navbar-expand-xl .navbar-nav {\n flex-direction: row; }\n .navbar-expand-xl .navbar-nav .dropdown-menu {\n position: absolute; }\n .navbar-expand-xl .navbar-nav .nav-link {\n padding-right: 0.5rem;\n padding-left: 0.5rem; }\n .navbar-expand-xl > .container,\n .navbar-expand-xl > .container-fluid {\n flex-wrap: nowrap; }\n .navbar-expand-xl .navbar-collapse {\n display: flex !important;\n flex-basis: auto; }\n .navbar-expand-xl .navbar-toggler {\n display: none; } }\n\n.navbar-expand {\n flex-flow: row nowrap;\n justify-content: flex-start; }\n .navbar-expand > .container,\n .navbar-expand > .container-fluid {\n padding-right: 0;\n padding-left: 0; }\n .navbar-expand .navbar-nav {\n flex-direction: row; }\n .navbar-expand .navbar-nav .dropdown-menu {\n position: absolute; }\n .navbar-expand .navbar-nav .nav-link {\n padding-right: 0.5rem;\n padding-left: 0.5rem; }\n .navbar-expand > .container,\n .navbar-expand > .container-fluid {\n flex-wrap: nowrap; }\n .navbar-expand .navbar-collapse {\n display: flex !important;\n flex-basis: auto; }\n .navbar-expand .navbar-toggler {\n display: none; }\n\n.navbar-light .navbar-brand {\n color: rgba(0, 0, 0, 0.9); }\n .navbar-light .navbar-brand:hover, .navbar-light .navbar-brand:focus {\n color: rgba(0, 0, 0, 0.9); }\n\n.navbar-light .navbar-nav .nav-link {\n color: rgba(0, 0, 0, 0.5); }\n .navbar-light .navbar-nav .nav-link:hover, .navbar-light .navbar-nav .nav-link:focus {\n color: rgba(0, 0, 0, 0.7); }\n .navbar-light .navbar-nav .nav-link.disabled {\n color: rgba(0, 0, 0, 0.3); }\n\n.navbar-light .navbar-nav .show > .nav-link,\n.navbar-light .navbar-nav .active > .nav-link,\n.navbar-light .navbar-nav .nav-link.show,\n.navbar-light .navbar-nav .nav-link.active {\n color: rgba(0, 0, 0, 0.9); }\n\n.navbar-light .navbar-toggler {\n color: rgba(0, 0, 0, 0.5);\n border-color: rgba(0, 0, 0, 0.1); }\n\n.navbar-light .navbar-toggler-icon {\n background-image: url("data:image/svg+xml;charset=utf8,%3Csvg viewBox=\'0 0 30 30\' xmlns=\'http://www.w3.org/2000/svg\'%3E%3Cpath stroke=\'rgba(0, 0, 0, 0.5)\' stroke-width=\'2\' stroke-linecap=\'round\' stroke-miterlimit=\'10\' d=\'M4 7h22M4 15h22M4 23h22\'/%3E%3C/svg%3E"); }\n\n.navbar-light .navbar-text {\n color: rgba(0, 0, 0, 0.5); }\n .navbar-light .navbar-text a {\n color: rgba(0, 0, 0, 0.9); }\n .navbar-light .navbar-text a:hover, .navbar-light .navbar-text a:focus {\n color: rgba(0, 0, 0, 0.9); }\n\n.navbar-dark .navbar-brand {\n color: #fff; }\n .navbar-dark .navbar-brand:hover, .navbar-dark .navbar-brand:focus {\n color: #fff; }\n\n.navbar-dark .navbar-nav .nav-link {\n color: rgba(255, 255, 255, 0.5); }\n .navbar-dark .navbar-nav .nav-link:hover, .navbar-dark .navbar-nav .nav-link:focus {\n color: rgba(255, 255, 255, 0.75); }\n .navbar-dark .navbar-nav .nav-link.disabled {\n color: rgba(255, 255, 255, 0.25); }\n\n.navbar-dark .navbar-nav .show > .nav-link,\n.navbar-dark .navbar-nav .active > .nav-link,\n.navbar-dark .navbar-nav .nav-link.show,\n.navbar-dark .navbar-nav .nav-link.active {\n color: #fff; }\n\n.navbar-dark .navbar-toggler {\n color: rgba(255, 255, 255, 0.5);\n border-color: rgba(255, 255, 255, 0.1); }\n\n.navbar-dark .navbar-toggler-icon {\n background-image: url("data:image/svg+xml;charset=utf8,%3Csvg viewBox=\'0 0 30 30\' xmlns=\'http://www.w3.org/2000/svg\'%3E%3Cpath stroke=\'rgba(255, 255, 255, 0.5)\' stroke-width=\'2\' stroke-linecap=\'round\' stroke-miterlimit=\'10\' d=\'M4 7h22M4 15h22M4 23h22\'/%3E%3C/svg%3E"); }\n\n.navbar-dark .navbar-text {\n color: rgba(255, 255, 255, 0.5); }\n .navbar-dark .navbar-text a {\n color: #fff; }\n .navbar-dark .navbar-text a:hover, .navbar-dark .navbar-text a:focus {\n color: #fff; }\n\n.card {\n position: relative;\n display: flex;\n flex-direction: column;\n min-width: 0;\n word-wrap: break-word;\n background-color: #fff;\n background-clip: border-box;\n border: 1px solid rgba(0, 0, 0, 0.125);\n border-radius: 0.25rem; }\n .card > hr {\n margin-right: 0;\n margin-left: 0; }\n .card > .list-group:first-child .list-group-item:first-child {\n border-top-left-radius: 0.25rem;\n border-top-right-radius: 0.25rem; }\n .card > .list-group:last-child .list-group-item:last-child {\n border-bottom-right-radius: 0.25rem;\n border-bottom-left-radius: 0.25rem; }\n\n.card-body {\n flex: 1 1 auto;\n padding: 1.25rem; }\n\n.card-title {\n margin-bottom: 0.75rem; }\n\n.card-subtitle {\n margin-top: -0.375rem;\n margin-bottom: 0; }\n\n.card-text:last-child {\n margin-bottom: 0; }\n\n.card-link:hover {\n text-decoration: none; }\n\n.card-link + .card-link {\n margin-left: 1.25rem; }\n\n.card-header {\n padding: 0.75rem 1.25rem;\n margin-bottom: 0;\n background-color: rgba(0, 0, 0, 0.03);\n border-bottom: 1px solid rgba(0, 0, 0, 0.125); }\n .card-header:first-child {\n border-radius: calc(0.25rem - 1px) calc(0.25rem - 1px) 0 0; }\n .card-header + .list-group .list-group-item:first-child {\n border-top: 0; }\n\n.card-footer {\n padding: 0.75rem 1.25rem;\n background-color: rgba(0, 0, 0, 0.03);\n border-top: 1px solid rgba(0, 0, 0, 0.125); }\n .card-footer:last-child {\n border-radius: 0 0 calc(0.25rem - 1px) calc(0.25rem - 1px); }\n\n.card-header-tabs {\n margin-right: -0.625rem;\n margin-bottom: -0.75rem;\n margin-left: -0.625rem;\n border-bottom: 0; }\n\n.card-header-pills {\n margin-right: -0.625rem;\n margin-left: -0.625rem; }\n\n.card-img-overlay {\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n padding: 1.25rem; }\n\n.card-img {\n width: 100%;\n border-radius: calc(0.25rem - 1px); }\n\n.card-img-top {\n width: 100%;\n border-top-left-radius: calc(0.25rem - 1px);\n border-top-right-radius: calc(0.25rem - 1px); }\n\n.card-img-bottom {\n width: 100%;\n border-bottom-right-radius: calc(0.25rem - 1px);\n border-bottom-left-radius: calc(0.25rem - 1px); }\n\n.card-deck {\n display: flex;\n flex-direction: column; }\n .card-deck .card {\n margin-bottom: 15px; }\n @media (min-width: 576px) {\n .card-deck {\n flex-flow: row wrap;\n margin-right: -15px;\n margin-left: -15px; }\n .card-deck .card {\n display: flex;\n flex: 1 0 0%;\n flex-direction: column;\n margin-right: 15px;\n margin-bottom: 0;\n margin-left: 15px; } }\n\n.card-group {\n display: flex;\n flex-direction: column; }\n .card-group > .card {\n margin-bottom: 15px; }\n @media (min-width: 576px) {\n .card-group {\n flex-flow: row wrap; }\n .card-group > .card {\n flex: 1 0 0%;\n margin-bottom: 0; }\n .card-group > .card + .card {\n margin-left: 0;\n border-left: 0; }\n .card-group > .card:first-child {\n border-top-right-radius: 0;\n border-bottom-right-radius: 0; }\n .card-group > .card:first-child .card-img-top,\n .card-group > .card:first-child .card-header {\n border-top-right-radius: 0; }\n .card-group > .card:first-child .card-img-bottom,\n .card-group > .card:first-child .card-footer {\n border-bottom-right-radius: 0; }\n .card-group > .card:last-child {\n border-top-left-radius: 0;\n border-bottom-left-radius: 0; }\n .card-group > .card:last-child .card-img-top,\n .card-group > .card:last-child .card-header {\n border-top-left-radius: 0; }\n .card-group > .card:last-child .card-img-bottom,\n .card-group > .card:last-child .card-footer {\n border-bottom-left-radius: 0; }\n .card-group > .card:only-child {\n border-radius: 0.25rem; }\n .card-group > .card:only-child .card-img-top,\n .card-group > .card:only-child .card-header {\n border-top-left-radius: 0.25rem;\n border-top-right-radius: 0.25rem; }\n .card-group > .card:only-child .card-img-bottom,\n .card-group > .card:only-child .card-footer {\n border-bottom-right-radius: 0.25rem;\n border-bottom-left-radius: 0.25rem; }\n .card-group > .card:not(:first-child):not(:last-child):not(:only-child) {\n border-radius: 0; }\n .card-group > .card:not(:first-child):not(:last-child):not(:only-child) .card-img-top,\n .card-group > .card:not(:first-child):not(:last-child):not(:only-child) .card-img-bottom,\n .card-group > .card:not(:first-child):not(:last-child):not(:only-child) .card-header,\n .card-group > .card:not(:first-child):not(:last-child):not(:only-child) .card-footer {\n border-radius: 0; } }\n\n.card-columns .card {\n margin-bottom: 0.75rem; }\n\n@media (min-width: 576px) {\n .card-columns {\n column-count: 3;\n column-gap: 1.25rem;\n orphans: 1;\n widows: 1; }\n .card-columns .card {\n display: inline-block;\n width: 100%; } }\n\n.accordion .card:not(:first-of-type):not(:last-of-type) {\n border-bottom: 0;\n border-radius: 0; }\n\n.accordion .card:not(:first-of-type) .card-header:first-child {\n border-radius: 0; }\n\n.accordion .card:first-of-type {\n border-bottom: 0;\n border-bottom-right-radius: 0;\n border-bottom-left-radius: 0; }\n\n.accordion .card:last-of-type {\n border-top-left-radius: 0;\n border-top-right-radius: 0; }\n\n.breadcrumb {\n display: flex;\n flex-wrap: wrap;\n padding: 0.75rem 1rem;\n margin-bottom: 1rem;\n list-style: none;\n background-color: #e9ecef;\n border-radius: 0.25rem; }\n\n.breadcrumb-item + .breadcrumb-item {\n padding-left: 0.5rem; }\n .breadcrumb-item + .breadcrumb-item::before {\n display: inline-block;\n padding-right: 0.5rem;\n color: #6c757d;\n content: "/"; }\n\n.breadcrumb-item + .breadcrumb-item:hover::before {\n text-decoration: underline; }\n\n.breadcrumb-item + .breadcrumb-item:hover::before {\n text-decoration: none; }\n\n.breadcrumb-item.active {\n color: #6c757d; }\n\n.pagination {\n display: flex;\n padding-left: 0;\n list-style: none;\n border-radius: 0.25rem; }\n\n.page-link {\n position: relative;\n display: block;\n padding: 0.5rem 0.75rem;\n margin-left: -1px;\n line-height: 1.25;\n color: #007bff;\n background-color: #fff;\n border: 1px solid #dee2e6; }\n .page-link:hover {\n z-index: 2;\n color: #0056b3;\n text-decoration: none;\n background-color: #e9ecef;\n border-color: #dee2e6; }\n .page-link:focus {\n z-index: 2;\n outline: 0;\n box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25); }\n .page-link:not(:disabled):not(.disabled) {\n cursor: pointer; }\n\n.page-item:first-child .page-link {\n margin-left: 0;\n border-top-left-radius: 0.25rem;\n border-bottom-left-radius: 0.25rem; }\n\n.page-item:last-child .page-link {\n border-top-right-radius: 0.25rem;\n border-bottom-right-radius: 0.25rem; }\n\n.page-item.active .page-link {\n z-index: 1;\n color: #fff;\n background-color: #007bff;\n border-color: #007bff; }\n\n.page-item.disabled .page-link {\n color: #6c757d;\n pointer-events: none;\n cursor: auto;\n background-color: #fff;\n border-color: #dee2e6; }\n\n.pagination-lg .page-link {\n padding: 0.75rem 1.5rem;\n font-size: 1.25rem;\n line-height: 1.5; }\n\n.pagination-lg .page-item:first-child .page-link {\n border-top-left-radius: 0;\n border-bottom-left-radius: 0; }\n\n.pagination-lg .page-item:last-child .page-link {\n border-top-right-radius: 0;\n border-bottom-right-radius: 0; }\n\n.pagination-sm .page-link {\n padding: 0.25rem 0.5rem;\n font-size: 0.875rem;\n line-height: 1.5; }\n\n.pagination-sm .page-item:first-child .page-link {\n border-top-left-radius: 0.2rem;\n border-bottom-left-radius: 0.2rem; }\n\n.pagination-sm .page-item:last-child .page-link {\n border-top-right-radius: 0.2rem;\n border-bottom-right-radius: 0.2rem; }\n\n.badge {\n display: inline-block;\n padding: 0.25em 0.4em;\n font-size: 75%;\n font-weight: 700;\n line-height: 1;\n text-align: center;\n white-space: nowrap;\n vertical-align: baseline;\n border-radius: 0.25rem; }\n .badge:empty {\n display: none; }\n\n.btn .badge {\n position: relative;\n top: -1px; }\n\n.badge-pill {\n padding-right: 0.6em;\n padding-left: 0.6em;\n border-radius: 10rem; }\n\n.badge-primary {\n color: #fff;\n background-color: #007bff; }\n .badge-primary[href]:hover, .badge-primary[href]:focus {\n color: #fff;\n text-decoration: none;\n background-color: #0062cc; }\n\n.badge-secondary {\n color: #fff;\n background-color: #6c757d; }\n .badge-secondary[href]:hover, .badge-secondary[href]:focus {\n color: #fff;\n text-decoration: none;\n background-color: #545b62; }\n\n.badge-success {\n color: #fff;\n background-color: #28a745; }\n .badge-success[href]:hover, .badge-success[href]:focus {\n color: #fff;\n text-decoration: none;\n background-color: #1e7e34; }\n\n.badge-info {\n color: #fff;\n background-color: #17a2b8; }\n .badge-info[href]:hover, .badge-info[href]:focus {\n color: #fff;\n text-decoration: none;\n background-color: #117a8b; }\n\n.badge-warning {\n color: #212529;\n background-color: #ffc107; }\n .badge-warning[href]:hover, .badge-warning[href]:focus {\n color: #212529;\n text-decoration: none;\n background-color: #d39e00; }\n\n.badge-danger {\n color: #fff;\n background-color: #dc3545; }\n .badge-danger[href]:hover, .badge-danger[href]:focus {\n color: #fff;\n text-decoration: none;\n background-color: #bd2130; }\n\n.badge-light {\n color: #212529;\n background-color: #f8f9fa; }\n .badge-light[href]:hover, .badge-light[href]:focus {\n color: #212529;\n text-decoration: none;\n background-color: #dae0e5; }\n\n.badge-dark {\n color: #fff;\n background-color: #343a40; }\n .badge-dark[href]:hover, .badge-dark[href]:focus {\n color: #fff;\n text-decoration: none;\n background-color: #1d2124; }\n\n.jumbotron {\n padding: 2rem 1rem;\n margin-bottom: 2rem;\n background-color: #e9ecef;\n border-radius: 0; }\n @media (min-width: 576px) {\n .jumbotron {\n padding: 4rem 2rem; } }\n\n.jumbotron-fluid {\n padding-right: 0;\n padding-left: 0;\n border-radius: 0; }\n\n.alert {\n position: relative;\n padding: 0.75rem 1.25rem;\n margin-bottom: 1rem;\n border: 1px solid transparent;\n border-radius: 0.25rem; }\n\n.alert-heading {\n color: inherit; }\n\n.alert-link {\n font-weight: 700; }\n\n.alert-dismissible {\n padding-right: 4rem; }\n .alert-dismissible .close {\n position: absolute;\n top: 0;\n right: 0;\n padding: 0.75rem 1.25rem;\n color: inherit; }\n\n.alert-primary {\n color: #004085;\n background-color: #cce5ff;\n border-color: #b8daff; }\n .alert-primary hr {\n border-top-color: #9fcdff; }\n .alert-primary .alert-link {\n color: #002752; }\n\n.alert-secondary {\n color: #383d41;\n background-color: #e2e3e5;\n border-color: #d6d8db; }\n .alert-secondary hr {\n border-top-color: #c8cbcf; }\n .alert-secondary .alert-link {\n color: #202326; }\n\n.alert-success {\n color: #155724;\n background-color: #d4edda;\n border-color: #c3e6cb; }\n .alert-success hr {\n border-top-color: #b1dfbb; }\n .alert-success .alert-link {\n color: #0b2e13; }\n\n.alert-info {\n color: #0c5460;\n background-color: #d1ecf1;\n border-color: #bee5eb; }\n .alert-info hr {\n border-top-color: #abdde5; }\n .alert-info .alert-link {\n color: #062c33; }\n\n.alert-warning {\n color: #856404;\n background-color: #fff3cd;\n border-color: #ffeeba; }\n .alert-warning hr {\n border-top-color: #ffe8a1; }\n .alert-warning .alert-link {\n color: #533f03; }\n\n.alert-danger {\n color: #721c24;\n background-color: #f8d7da;\n border-color: #f5c6cb; }\n .alert-danger hr {\n border-top-color: #f1b0b7; }\n .alert-danger .alert-link {\n color: #491217; }\n\n.alert-light {\n color: #818182;\n background-color: #fefefe;\n border-color: #fdfdfe; }\n .alert-light hr {\n border-top-color: #ececf6; }\n .alert-light .alert-link {\n color: #686868; }\n\n.alert-dark {\n color: #1b1e21;\n background-color: #d6d8d9;\n border-color: #c6c8ca; }\n .alert-dark hr {\n border-top-color: #b9bbbe; }\n .alert-dark .alert-link {\n color: #040505; }\n\n@keyframes progress-bar-stripes {\n from {\n background-position: 1rem 0; }\n to {\n background-position: 0 0; } }\n\n.progress {\n display: flex;\n height: 1rem;\n overflow: hidden;\n font-size: 0.75rem;\n background-color: #e9ecef;\n border-radius: 0.25rem; }\n\n.progress-bar {\n display: flex;\n flex-direction: column;\n justify-content: center;\n color: #fff;\n text-align: center;\n white-space: nowrap;\n background-color: #007bff;\n transition: width 0.6s ease; }\n @media screen and (prefers-reduced-motion: reduce) {\n .progress-bar {\n transition: none; } }\n\n.progress-bar-striped {\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-size: 1rem 1rem; }\n\n.progress-bar-animated {\n animation: progress-bar-stripes 1s linear infinite; }\n\n.media {\n display: flex;\n align-items: flex-start; }\n\n.media-body {\n flex: 1; }\n\n.list-group {\n display: flex;\n flex-direction: column;\n padding-left: 0;\n margin-bottom: 0; }\n\n.list-group-item-action {\n width: 100%;\n color: #495057;\n text-align: inherit; }\n .list-group-item-action:hover, .list-group-item-action:focus {\n color: #495057;\n text-decoration: none;\n background-color: #f8f9fa; }\n .list-group-item-action:active {\n color: #212529;\n background-color: #e9ecef; }\n\n.list-group-item {\n position: relative;\n display: block;\n padding: 0.75rem 1.25rem;\n margin-bottom: -1px;\n background-color: #fff;\n border: 1px solid rgba(0, 0, 0, 0.125); }\n .list-group-item:first-child {\n border-top-left-radius: 0.25rem;\n border-top-right-radius: 0.25rem; }\n .list-group-item:last-child {\n margin-bottom: 0;\n border-bottom-right-radius: 0.25rem;\n border-bottom-left-radius: 0.25rem; }\n .list-group-item:hover, .list-group-item:focus {\n z-index: 1;\n text-decoration: none; }\n .list-group-item.disabled, .list-group-item:disabled {\n color: #6c757d;\n background-color: #fff; }\n .list-group-item.active {\n z-index: 2;\n color: #fff;\n background-color: #007bff;\n border-color: #007bff; }\n\n.list-group-flush .list-group-item {\n border-right: 0;\n border-left: 0;\n border-radius: 0; }\n\n.list-group-flush:first-child .list-group-item:first-child {\n border-top: 0; }\n\n.list-group-flush:last-child .list-group-item:last-child {\n border-bottom: 0; }\n\n.list-group-item-primary {\n color: #004085;\n background-color: #b8daff; }\n .list-group-item-primary.list-group-item-action:hover, .list-group-item-primary.list-group-item-action:focus {\n color: #004085;\n background-color: #9fcdff; }\n .list-group-item-primary.list-group-item-action.active {\n color: #fff;\n background-color: #004085;\n border-color: #004085; }\n\n.list-group-item-secondary {\n color: #383d41;\n background-color: #d6d8db; }\n .list-group-item-secondary.list-group-item-action:hover, .list-group-item-secondary.list-group-item-action:focus {\n color: #383d41;\n background-color: #c8cbcf; }\n .list-group-item-secondary.list-group-item-action.active {\n color: #fff;\n background-color: #383d41;\n border-color: #383d41; }\n\n.list-group-item-success {\n color: #155724;\n background-color: #c3e6cb; }\n .list-group-item-success.list-group-item-action:hover, .list-group-item-success.list-group-item-action:focus {\n color: #155724;\n background-color: #b1dfbb; }\n .list-group-item-success.list-group-item-action.active {\n color: #fff;\n background-color: #155724;\n border-color: #155724; }\n\n.list-group-item-info {\n color: #0c5460;\n background-color: #bee5eb; }\n .list-group-item-info.list-group-item-action:hover, .list-group-item-info.list-group-item-action:focus {\n color: #0c5460;\n background-color: #abdde5; }\n .list-group-item-info.list-group-item-action.active {\n color: #fff;\n background-color: #0c5460;\n border-color: #0c5460; }\n\n.list-group-item-warning {\n color: #856404;\n background-color: #ffeeba; }\n .list-group-item-warning.list-group-item-action:hover, .list-group-item-warning.list-group-item-action:focus {\n color: #856404;\n background-color: #ffe8a1; }\n .list-group-item-warning.list-group-item-action.active {\n color: #fff;\n background-color: #856404;\n border-color: #856404; }\n\n.list-group-item-danger {\n color: #721c24;\n background-color: #f5c6cb; }\n .list-group-item-danger.list-group-item-action:hover, .list-group-item-danger.list-group-item-action:focus {\n color: #721c24;\n background-color: #f1b0b7; }\n .list-group-item-danger.list-group-item-action.active {\n color: #fff;\n background-color: #721c24;\n border-color: #721c24; }\n\n.list-group-item-light {\n color: #818182;\n background-color: #fdfdfe; }\n .list-group-item-light.list-group-item-action:hover, .list-group-item-light.list-group-item-action:focus {\n color: #818182;\n background-color: #ececf6; }\n .list-group-item-light.list-group-item-action.active {\n color: #fff;\n background-color: #818182;\n border-color: #818182; }\n\n.list-group-item-dark {\n color: #1b1e21;\n background-color: #c6c8ca; }\n .list-group-item-dark.list-group-item-action:hover, .list-group-item-dark.list-group-item-action:focus {\n color: #1b1e21;\n background-color: #b9bbbe; }\n .list-group-item-dark.list-group-item-action.active {\n color: #fff;\n background-color: #1b1e21;\n border-color: #1b1e21; }\n\n.close {\n float: right;\n font-size: 1.5rem;\n font-weight: 700;\n line-height: 1;\n color: #000;\n text-shadow: 0 1px 0 #fff;\n opacity: .5; }\n .close:not(:disabled):not(.disabled) {\n cursor: pointer; }\n .close:not(:disabled):not(.disabled):hover, .close:not(:disabled):not(.disabled):focus {\n color: #000;\n text-decoration: none;\n opacity: .75; }\n\nbutton.close {\n padding: 0;\n background-color: transparent;\n border: 0;\n -webkit-appearance: none; }\n\n.modal-open {\n overflow: hidden; }\n .modal-open .modal {\n overflow-x: hidden;\n overflow-y: auto; }\n\n.modal {\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: 1050;\n display: none;\n overflow: hidden;\n outline: 0; }\n\n.modal-dialog {\n position: relative;\n width: auto;\n margin: 0.5rem;\n pointer-events: none; }\n .modal.fade .modal-dialog {\n transition: transform 0.3s ease-out;\n transform: translate(0, -25%); }\n @media screen and (prefers-reduced-motion: reduce) {\n .modal.fade .modal-dialog {\n transition: none; } }\n .modal.show .modal-dialog {\n transform: translate(0, 0); }\n\n.modal-dialog-centered {\n display: flex;\n align-items: center;\n min-height: calc(100% - (0.5rem * 2)); }\n .modal-dialog-centered::before {\n display: block;\n height: calc(100vh - (0.5rem * 2));\n content: ""; }\n\n.modal-content {\n position: relative;\n display: flex;\n flex-direction: column;\n width: 100%;\n pointer-events: auto;\n background-color: #fff;\n background-clip: padding-box;\n border: 1px solid rgba(0, 0, 0, 0.2);\n border-radius: 0;\n outline: 0; }\n\n.modal-backdrop {\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: 1040;\n background-color: #000; }\n .modal-backdrop.fade {\n opacity: 0; }\n .modal-backdrop.show {\n opacity: 0.5; }\n\n.modal-header {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n padding: 1rem;\n border-bottom: 1px solid #e9ecef;\n border-top-left-radius: 0;\n border-top-right-radius: 0; }\n .modal-header .close {\n padding: 1rem;\n margin: -1rem -1rem -1rem auto; }\n\n.modal-title {\n margin-bottom: 0;\n line-height: 1.5; }\n\n.modal-body {\n position: relative;\n flex: 1 1 auto;\n padding: 1rem; }\n\n.modal-footer {\n display: flex;\n align-items: center;\n justify-content: flex-end;\n padding: 1rem;\n border-top: 1px solid #e9ecef; }\n .modal-footer > :not(:first-child) {\n margin-left: .25rem; }\n .modal-footer > :not(:last-child) {\n margin-right: .25rem; }\n\n.modal-scrollbar-measure {\n position: absolute;\n top: -9999px;\n width: 50px;\n height: 50px;\n overflow: scroll; }\n\n@media (min-width: 576px) {\n .modal-dialog {\n max-width: 500px;\n margin: 1.75rem auto; }\n .modal-dialog-centered {\n min-height: calc(100% - (1.75rem * 2)); }\n .modal-dialog-centered::before {\n height: calc(100vh - (1.75rem * 2)); }\n .modal-sm {\n max-width: 300px; } }\n\n@media (min-width: 992px) {\n .modal-lg {\n max-width: 800px; } }\n\n.tooltip {\n position: absolute;\n z-index: 1070;\n display: block;\n margin: 0;\n font-family: "Source Sans Pro";\n font-style: normal;\n font-weight: 400;\n line-height: 1.5;\n text-align: left;\n text-align: start;\n text-decoration: none;\n text-shadow: none;\n text-transform: none;\n letter-spacing: normal;\n word-break: normal;\n word-spacing: normal;\n white-space: normal;\n line-break: auto;\n font-size: 0.875rem;\n word-wrap: break-word;\n opacity: 0; }\n .tooltip.show {\n opacity: 0.9; }\n .tooltip .arrow {\n position: absolute;\n display: block;\n width: 0.8rem;\n height: 0.4rem; }\n .tooltip .arrow::before {\n position: absolute;\n content: "";\n border-color: transparent;\n border-style: solid; }\n\n.bs-tooltip-top, .bs-tooltip-auto[x-placement^="top"] {\n padding: 0.4rem 0; }\n .bs-tooltip-top .arrow, .bs-tooltip-auto[x-placement^="top"] .arrow {\n bottom: 0; }\n .bs-tooltip-top .arrow::before, .bs-tooltip-auto[x-placement^="top"] .arrow::before {\n top: 0;\n border-width: 0.4rem 0.4rem 0;\n border-top-color: #000; }\n\n.bs-tooltip-right, .bs-tooltip-auto[x-placement^="right"] {\n padding: 0 0.4rem; }\n .bs-tooltip-right .arrow, .bs-tooltip-auto[x-placement^="right"] .arrow {\n left: 0;\n width: 0.4rem;\n height: 0.8rem; }\n .bs-tooltip-right .arrow::before, .bs-tooltip-auto[x-placement^="right"] .arrow::before {\n right: 0;\n border-width: 0.4rem 0.4rem 0.4rem 0;\n border-right-color: #000; }\n\n.bs-tooltip-bottom, .bs-tooltip-auto[x-placement^="bottom"] {\n padding: 0.4rem 0; }\n .bs-tooltip-bottom .arrow, .bs-tooltip-auto[x-placement^="bottom"] .arrow {\n top: 0; }\n .bs-tooltip-bottom .arrow::before, .bs-tooltip-auto[x-placement^="bottom"] .arrow::before {\n bottom: 0;\n border-width: 0 0.4rem 0.4rem;\n border-bottom-color: #000; }\n\n.bs-tooltip-left, .bs-tooltip-auto[x-placement^="left"] {\n padding: 0 0.4rem; }\n .bs-tooltip-left .arrow, .bs-tooltip-auto[x-placement^="left"] .arrow {\n right: 0;\n width: 0.4rem;\n height: 0.8rem; }\n .bs-tooltip-left .arrow::before, .bs-tooltip-auto[x-placement^="left"] .arrow::before {\n left: 0;\n border-width: 0.4rem 0 0.4rem 0.4rem;\n border-left-color: #000; }\n\n.tooltip-inner {\n max-width: 200px;\n padding: 0.25rem 0.5rem;\n color: #fff;\n text-align: center;\n background-color: #000;\n border-radius: 0.25rem; }\n\n.popover {\n position: absolute;\n top: 0;\n left: 0;\n z-index: 1060;\n display: block;\n max-width: 276px;\n font-family: "Source Sans Pro";\n font-style: normal;\n font-weight: 400;\n line-height: 1.5;\n text-align: left;\n text-align: start;\n text-decoration: none;\n text-shadow: none;\n text-transform: none;\n letter-spacing: normal;\n word-break: normal;\n word-spacing: normal;\n white-space: normal;\n line-break: auto;\n font-size: 0.875rem;\n word-wrap: break-word;\n background-color: #fff;\n background-clip: padding-box;\n border: 1px solid rgba(0, 0, 0, 0.2);\n border-radius: 0; }\n .popover .arrow {\n position: absolute;\n display: block;\n width: 1rem;\n height: 0.5rem;\n margin: 0 0; }\n .popover .arrow::before, .popover .arrow::after {\n position: absolute;\n display: block;\n content: "";\n border-color: transparent;\n border-style: solid; }\n\n.bs-popover-top, .bs-popover-auto[x-placement^="top"] {\n margin-bottom: 0.5rem; }\n .bs-popover-top .arrow, .bs-popover-auto[x-placement^="top"] .arrow {\n bottom: calc((0.5rem + 1px) * -1); }\n .bs-popover-top .arrow::before, .bs-popover-auto[x-placement^="top"] .arrow::before,\n .bs-popover-top .arrow::after,\n .bs-popover-auto[x-placement^="top"] .arrow::after {\n border-width: 0.5rem 0.5rem 0; }\n .bs-popover-top .arrow::before, .bs-popover-auto[x-placement^="top"] .arrow::before {\n bottom: 0;\n border-top-color: rgba(0, 0, 0, 0.25); }\n \n .bs-popover-top .arrow::after,\n .bs-popover-auto[x-placement^="top"] .arrow::after {\n bottom: 1px;\n border-top-color: #fff; }\n\n.bs-popover-right, .bs-popover-auto[x-placement^="right"] {\n margin-left: 0.5rem; }\n .bs-popover-right .arrow, .bs-popover-auto[x-placement^="right"] .arrow {\n left: calc((0.5rem + 1px) * -1);\n width: 0.5rem;\n height: 1rem;\n margin: 0 0; }\n .bs-popover-right .arrow::before, .bs-popover-auto[x-placement^="right"] .arrow::before,\n .bs-popover-right .arrow::after,\n .bs-popover-auto[x-placement^="right"] .arrow::after {\n border-width: 0.5rem 0.5rem 0.5rem 0; }\n .bs-popover-right .arrow::before, .bs-popover-auto[x-placement^="right"] .arrow::before {\n left: 0;\n border-right-color: rgba(0, 0, 0, 0.25); }\n \n .bs-popover-right .arrow::after,\n .bs-popover-auto[x-placement^="right"] .arrow::after {\n left: 1px;\n border-right-color: #fff; }\n\n.bs-popover-bottom, .bs-popover-auto[x-placement^="bottom"] {\n margin-top: 0.5rem; }\n .bs-popover-bottom .arrow, .bs-popover-auto[x-placement^="bottom"] .arrow {\n top: calc((0.5rem + 1px) * -1); }\n .bs-popover-bottom .arrow::before, .bs-popover-auto[x-placement^="bottom"] .arrow::before,\n .bs-popover-bottom .arrow::after,\n .bs-popover-auto[x-placement^="bottom"] .arrow::after {\n border-width: 0 0.5rem 0.5rem 0.5rem; }\n .bs-popover-bottom .arrow::before, .bs-popover-auto[x-placement^="bottom"] .arrow::before {\n top: 0;\n border-bottom-color: rgba(0, 0, 0, 0.25); }\n \n .bs-popover-bottom .arrow::after,\n .bs-popover-auto[x-placement^="bottom"] .arrow::after {\n top: 1px;\n border-bottom-color: #fff; }\n .bs-popover-bottom .popover-header::before, .bs-popover-auto[x-placement^="bottom"] .popover-header::before {\n position: absolute;\n top: 0;\n left: 50%;\n display: block;\n width: 1rem;\n margin-left: -0.5rem;\n content: "";\n border-bottom: 1px solid #f7f7f7; }\n\n.bs-popover-left, .bs-popover-auto[x-placement^="left"] {\n margin-right: 0.5rem; }\n .bs-popover-left .arrow, .bs-popover-auto[x-placement^="left"] .arrow {\n right: calc((0.5rem + 1px) * -1);\n width: 0.5rem;\n height: 1rem;\n margin: 0 0; }\n .bs-popover-left .arrow::before, .bs-popover-auto[x-placement^="left"] .arrow::before,\n .bs-popover-left .arrow::after,\n .bs-popover-auto[x-placement^="left"] .arrow::after {\n border-width: 0.5rem 0 0.5rem 0.5rem; }\n .bs-popover-left .arrow::before, .bs-popover-auto[x-placement^="left"] .arrow::before {\n right: 0;\n border-left-color: rgba(0, 0, 0, 0.25); }\n \n .bs-popover-left .arrow::after,\n .bs-popover-auto[x-placement^="left"] .arrow::after {\n right: 1px;\n border-left-color: #fff; }\n\n.popover-header {\n padding: 0.5rem 0.75rem;\n margin-bottom: 0;\n font-size: 1rem;\n color: inherit;\n background-color: #f7f7f7;\n border-bottom: 1px solid #ebebeb;\n border-top-left-radius: calc(0 - 1px);\n border-top-right-radius: calc(0 - 1px); }\n .popover-header:empty {\n display: none; }\n\n.popover-body {\n padding: 0.5rem 0.75rem;\n color: #212529; }\n\n.carousel {\n position: relative; }\n\n.carousel-inner {\n position: relative;\n width: 100%;\n overflow: hidden; }\n\n.carousel-item {\n position: relative;\n display: none;\n align-items: center;\n width: 100%;\n backface-visibility: hidden;\n perspective: 1000px; }\n\n.carousel-item.active,\n.carousel-item-next,\n.carousel-item-prev {\n display: block;\n transition: transform 0.6s ease; }\n @media screen and (prefers-reduced-motion: reduce) {\n .carousel-item.active,\n .carousel-item-next,\n .carousel-item-prev {\n transition: none; } }\n\n.carousel-item-next,\n.carousel-item-prev {\n position: absolute;\n top: 0; }\n\n.carousel-item-next.carousel-item-left,\n.carousel-item-prev.carousel-item-right {\n transform: translateX(0); }\n @supports (transform-style: preserve-3d) {\n .carousel-item-next.carousel-item-left,\n .carousel-item-prev.carousel-item-right {\n transform: translate3d(0, 0, 0); } }\n\n.carousel-item-next,\n.active.carousel-item-right {\n transform: translateX(100%); }\n @supports (transform-style: preserve-3d) {\n .carousel-item-next,\n .active.carousel-item-right {\n transform: translate3d(100%, 0, 0); } }\n\n.carousel-item-prev,\n.active.carousel-item-left {\n transform: translateX(-100%); }\n @supports (transform-style: preserve-3d) {\n .carousel-item-prev,\n .active.carousel-item-left {\n transform: translate3d(-100%, 0, 0); } }\n\n.carousel-fade .carousel-item {\n opacity: 0;\n transition-duration: .6s;\n transition-property: opacity; }\n\n.carousel-fade .carousel-item.active,\n.carousel-fade .carousel-item-next.carousel-item-left,\n.carousel-fade .carousel-item-prev.carousel-item-right {\n opacity: 1; }\n\n.carousel-fade .active.carousel-item-left,\n.carousel-fade .active.carousel-item-right {\n opacity: 0; }\n\n.carousel-fade .carousel-item-next,\n.carousel-fade .carousel-item-prev,\n.carousel-fade .carousel-item.active,\n.carousel-fade .active.carousel-item-left,\n.carousel-fade .active.carousel-item-prev {\n transform: translateX(0); }\n @supports (transform-style: preserve-3d) {\n .carousel-fade .carousel-item-next,\n .carousel-fade .carousel-item-prev,\n .carousel-fade .carousel-item.active,\n .carousel-fade .active.carousel-item-left,\n .carousel-fade .active.carousel-item-prev {\n transform: translate3d(0, 0, 0); } }\n\n.carousel-control-prev,\n.carousel-control-next {\n position: absolute;\n top: 0;\n bottom: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 15%;\n color: #fff;\n text-align: center;\n opacity: 0.5; }\n .carousel-control-prev:hover, .carousel-control-prev:focus,\n .carousel-control-next:hover,\n .carousel-control-next:focus {\n color: #fff;\n text-decoration: none;\n outline: 0;\n opacity: .9; }\n\n.carousel-control-prev {\n left: 0; }\n\n.carousel-control-next {\n right: 0; }\n\n.carousel-control-prev-icon,\n.carousel-control-next-icon {\n display: inline-block;\n width: 20px;\n height: 20px;\n background: transparent no-repeat center center;\n background-size: 100% 100%; }\n\n.carousel-control-prev-icon {\n background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns=\'http://www.w3.org/2000/svg\' fill=\'%23fff\' viewBox=\'0 0 8 8\'%3E%3Cpath d=\'M5.25 0l-4 4 4 4 1.5-1.5-2.5-2.5 2.5-2.5-1.5-1.5z\'/%3E%3C/svg%3E"); }\n\n.carousel-control-next-icon {\n background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns=\'http://www.w3.org/2000/svg\' fill=\'%23fff\' viewBox=\'0 0 8 8\'%3E%3Cpath d=\'M2.75 0l-1.5 1.5 2.5 2.5-2.5 2.5 1.5 1.5 4-4-4-4z\'/%3E%3C/svg%3E"); }\n\n.carousel-indicators {\n position: absolute;\n right: 0;\n bottom: 10px;\n left: 0;\n z-index: 15;\n display: flex;\n justify-content: center;\n padding-left: 0;\n margin-right: 15%;\n margin-left: 15%;\n list-style: none; }\n .carousel-indicators li {\n position: relative;\n flex: 0 1 auto;\n width: 30px;\n height: 3px;\n margin-right: 3px;\n margin-left: 3px;\n text-indent: -999px;\n cursor: pointer;\n background-color: rgba(255, 255, 255, 0.5); }\n .carousel-indicators li::before {\n position: absolute;\n top: -10px;\n left: 0;\n display: inline-block;\n width: 100%;\n height: 10px;\n content: ""; }\n .carousel-indicators li::after {\n position: absolute;\n bottom: -10px;\n left: 0;\n display: inline-block;\n width: 100%;\n height: 10px;\n content: ""; }\n .carousel-indicators .active {\n background-color: #fff; }\n\n.carousel-caption {\n position: absolute;\n right: 15%;\n bottom: 20px;\n left: 15%;\n z-index: 10;\n padding-top: 20px;\n padding-bottom: 20px;\n color: #fff;\n text-align: center; }\n\n.align-baseline {\n vertical-align: baseline !important; }\n\n.align-top {\n vertical-align: top !important; }\n\n.align-middle {\n vertical-align: middle !important; }\n\n.align-bottom {\n vertical-align: bottom !important; }\n\n.align-text-bottom {\n vertical-align: text-bottom !important; }\n\n.align-text-top {\n vertical-align: text-top !important; }\n\n.bg-primary {\n background-color: #007bff !important; }\n\na.bg-primary:hover, a.bg-primary:focus,\nbutton.bg-primary:hover,\nbutton.bg-primary:focus {\n background-color: #0062cc !important; }\n\n.bg-secondary {\n background-color: #6c757d !important; }\n\na.bg-secondary:hover, a.bg-secondary:focus,\nbutton.bg-secondary:hover,\nbutton.bg-secondary:focus {\n background-color: #545b62 !important; }\n\n.bg-success {\n background-color: #28a745 !important; }\n\na.bg-success:hover, a.bg-success:focus,\nbutton.bg-success:hover,\nbutton.bg-success:focus {\n background-color: #1e7e34 !important; }\n\n.bg-info {\n background-color: #17a2b8 !important; }\n\na.bg-info:hover, a.bg-info:focus,\nbutton.bg-info:hover,\nbutton.bg-info:focus {\n background-color: #117a8b !important; }\n\n.bg-warning {\n background-color: #ffc107 !important; }\n\na.bg-warning:hover, a.bg-warning:focus,\nbutton.bg-warning:hover,\nbutton.bg-warning:focus {\n background-color: #d39e00 !important; }\n\n.bg-danger {\n background-color: #dc3545 !important; }\n\na.bg-danger:hover, a.bg-danger:focus,\nbutton.bg-danger:hover,\nbutton.bg-danger:focus {\n background-color: #bd2130 !important; }\n\n.bg-light {\n background-color: #f8f9fa !important; }\n\na.bg-light:hover, a.bg-light:focus,\nbutton.bg-light:hover,\nbutton.bg-light:focus {\n background-color: #dae0e5 !important; }\n\n.bg-dark {\n background-color: #343a40 !important; }\n\na.bg-dark:hover, a.bg-dark:focus,\nbutton.bg-dark:hover,\nbutton.bg-dark:focus {\n background-color: #1d2124 !important; }\n\n.bg-white {\n background-color: #fff !important; }\n\n.bg-transparent {\n background-color: transparent !important; }\n\n.border {\n border: 1px solid #dee2e6 !important; }\n\n.border-top {\n border-top: 1px solid #dee2e6 !important; }\n\n.border-right {\n border-right: 1px solid #dee2e6 !important; }\n\n.border-bottom {\n border-bottom: 1px solid #dee2e6 !important; }\n\n.border-left {\n border-left: 1px solid #dee2e6 !important; }\n\n.border-0 {\n border: 0 !important; }\n\n.border-top-0 {\n border-top: 0 !important; }\n\n.border-right-0 {\n border-right: 0 !important; }\n\n.border-bottom-0 {\n border-bottom: 0 !important; }\n\n.border-left-0 {\n border-left: 0 !important; }\n\n.border-primary {\n border-color: #007bff !important; }\n\n.border-secondary {\n border-color: #6c757d !important; }\n\n.border-success {\n border-color: #28a745 !important; }\n\n.border-info {\n border-color: #17a2b8 !important; }\n\n.border-warning {\n border-color: #ffc107 !important; }\n\n.border-danger {\n border-color: #dc3545 !important; }\n\n.border-light {\n border-color: #f8f9fa !important; }\n\n.border-dark {\n border-color: #343a40 !important; }\n\n.border-white {\n border-color: #fff !important; }\n\n.rounded {\n border-radius: 0.25rem !important; }\n\n.rounded-top {\n border-top-left-radius: 0.25rem !important;\n border-top-right-radius: 0.25rem !important; }\n\n.rounded-right {\n border-top-right-radius: 0.25rem !important;\n border-bottom-right-radius: 0.25rem !important; }\n\n.rounded-bottom {\n border-bottom-right-radius: 0.25rem !important;\n border-bottom-left-radius: 0.25rem !important; }\n\n.rounded-left {\n border-top-left-radius: 0.25rem !important;\n border-bottom-left-radius: 0.25rem !important; }\n\n.rounded-circle {\n border-radius: 50% !important; }\n\n.rounded-0 {\n border-radius: 0 !important; }\n\n.clearfix::after {\n display: block;\n clear: both;\n content: ""; }\n\n.d-none {\n display: none !important; }\n\n.d-inline {\n display: inline !important; }\n\n.d-inline-block {\n display: inline-block !important; }\n\n.d-block {\n display: block !important; }\n\n.d-table {\n display: table !important; }\n\n.d-table-row {\n display: table-row !important; }\n\n.d-table-cell {\n display: table-cell !important; }\n\n.d-flex {\n display: flex !important; }\n\n.d-inline-flex {\n display: inline-flex !important; }\n\n@media (min-width: 576px) {\n .d-sm-none {\n display: none !important; }\n .d-sm-inline {\n display: inline !important; }\n .d-sm-inline-block {\n display: inline-block !important; }\n .d-sm-block {\n display: block !important; }\n .d-sm-table {\n display: table !important; }\n .d-sm-table-row {\n display: table-row !important; }\n .d-sm-table-cell {\n display: table-cell !important; }\n .d-sm-flex {\n display: flex !important; }\n .d-sm-inline-flex {\n display: inline-flex !important; } }\n\n@media (min-width: 768px) {\n .d-md-none {\n display: none !important; }\n .d-md-inline {\n display: inline !important; }\n .d-md-inline-block {\n display: inline-block !important; }\n .d-md-block {\n display: block !important; }\n .d-md-table {\n display: table !important; }\n .d-md-table-row {\n display: table-row !important; }\n .d-md-table-cell {\n display: table-cell !important; }\n .d-md-flex {\n display: flex !important; }\n .d-md-inline-flex {\n display: inline-flex !important; } }\n\n@media (min-width: 992px) {\n .d-lg-none {\n display: none !important; }\n .d-lg-inline {\n display: inline !important; }\n .d-lg-inline-block {\n display: inline-block !important; }\n .d-lg-block {\n display: block !important; }\n .d-lg-table {\n display: table !important; }\n .d-lg-table-row {\n display: table-row !important; }\n .d-lg-table-cell {\n display: table-cell !important; }\n .d-lg-flex {\n display: flex !important; }\n .d-lg-inline-flex {\n display: inline-flex !important; } }\n\n@media (min-width: 1200px) {\n .d-xl-none {\n display: none !important; }\n .d-xl-inline {\n display: inline !important; }\n .d-xl-inline-block {\n display: inline-block !important; }\n .d-xl-block {\n display: block !important; }\n .d-xl-table {\n display: table !important; }\n .d-xl-table-row {\n display: table-row !important; }\n .d-xl-table-cell {\n display: table-cell !important; }\n .d-xl-flex {\n display: flex !important; }\n .d-xl-inline-flex {\n display: inline-flex !important; } }\n\n@media print {\n .d-print-none {\n display: none !important; }\n .d-print-inline {\n display: inline !important; }\n .d-print-inline-block {\n display: inline-block !important; }\n .d-print-block {\n display: block !important; }\n .d-print-table {\n display: table !important; }\n .d-print-table-row {\n display: table-row !important; }\n .d-print-table-cell {\n display: table-cell !important; }\n .d-print-flex {\n display: flex !important; }\n .d-print-inline-flex {\n display: inline-flex !important; } }\n\n.embed-responsive {\n position: relative;\n display: block;\n width: 100%;\n padding: 0;\n overflow: hidden; }\n .embed-responsive::before {\n display: block;\n content: ""; }\n .embed-responsive .embed-responsive-item,\n .embed-responsive iframe,\n .embed-responsive embed,\n .embed-responsive object,\n .embed-responsive video {\n position: absolute;\n top: 0;\n bottom: 0;\n left: 0;\n width: 100%;\n height: 100%;\n border: 0; }\n\n.embed-responsive-21by9::before {\n padding-top: 42.85714%; }\n\n.embed-responsive-16by9::before {\n padding-top: 56.25%; }\n\n.embed-responsive-4by3::before {\n padding-top: 75%; }\n\n.embed-responsive-1by1::before {\n padding-top: 100%; }\n\n.flex-row {\n flex-direction: row !important; }\n\n.flex-column {\n flex-direction: column !important; }\n\n.flex-row-reverse {\n flex-direction: row-reverse !important; }\n\n.flex-column-reverse {\n flex-direction: column-reverse !important; }\n\n.flex-wrap {\n flex-wrap: wrap !important; }\n\n.flex-nowrap {\n flex-wrap: nowrap !important; }\n\n.flex-wrap-reverse {\n flex-wrap: wrap-reverse !important; }\n\n.flex-fill {\n flex: 1 1 auto !important; }\n\n.flex-grow-0 {\n flex-grow: 0 !important; }\n\n.flex-grow-1 {\n flex-grow: 1 !important; }\n\n.flex-shrink-0 {\n flex-shrink: 0 !important; }\n\n.flex-shrink-1 {\n flex-shrink: 1 !important; }\n\n.justify-content-start {\n justify-content: flex-start !important; }\n\n.justify-content-end {\n justify-content: flex-end !important; }\n\n.justify-content-center {\n justify-content: center !important; }\n\n.justify-content-between {\n justify-content: space-between !important; }\n\n.justify-content-around {\n justify-content: space-around !important; }\n\n.align-items-start {\n align-items: flex-start !important; }\n\n.align-items-end {\n align-items: flex-end !important; }\n\n.align-items-center {\n align-items: center !important; }\n\n.align-items-baseline {\n align-items: baseline !important; }\n\n.align-items-stretch {\n align-items: stretch !important; }\n\n.align-content-start {\n align-content: flex-start !important; }\n\n.align-content-end {\n align-content: flex-end !important; }\n\n.align-content-center {\n align-content: center !important; }\n\n.align-content-between {\n align-content: space-between !important; }\n\n.align-content-around {\n align-content: space-around !important; }\n\n.align-content-stretch {\n align-content: stretch !important; }\n\n.align-self-auto {\n align-self: auto !important; }\n\n.align-self-start {\n align-self: flex-start !important; }\n\n.align-self-end {\n align-self: flex-end !important; }\n\n.align-self-center {\n align-self: center !important; }\n\n.align-self-baseline {\n align-self: baseline !important; }\n\n.align-self-stretch {\n align-self: stretch !important; }\n\n@media (min-width: 576px) {\n .flex-sm-row {\n flex-direction: row !important; }\n .flex-sm-column {\n flex-direction: column !important; }\n .flex-sm-row-reverse {\n flex-direction: row-reverse !important; }\n .flex-sm-column-reverse {\n flex-direction: column-reverse !important; }\n .flex-sm-wrap {\n flex-wrap: wrap !important; }\n .flex-sm-nowrap {\n flex-wrap: nowrap !important; }\n .flex-sm-wrap-reverse {\n flex-wrap: wrap-reverse !important; }\n .flex-sm-fill {\n flex: 1 1 auto !important; }\n .flex-sm-grow-0 {\n flex-grow: 0 !important; }\n .flex-sm-grow-1 {\n flex-grow: 1 !important; }\n .flex-sm-shrink-0 {\n flex-shrink: 0 !important; }\n .flex-sm-shrink-1 {\n flex-shrink: 1 !important; }\n .justify-content-sm-start {\n justify-content: flex-start !important; }\n .justify-content-sm-end {\n justify-content: flex-end !important; }\n .justify-content-sm-center {\n justify-content: center !important; }\n .justify-content-sm-between {\n justify-content: space-between !important; }\n .justify-content-sm-around {\n justify-content: space-around !important; }\n .align-items-sm-start {\n align-items: flex-start !important; }\n .align-items-sm-end {\n align-items: flex-end !important; }\n .align-items-sm-center {\n align-items: center !important; }\n .align-items-sm-baseline {\n align-items: baseline !important; }\n .align-items-sm-stretch {\n align-items: stretch !important; }\n .align-content-sm-start {\n align-content: flex-start !important; }\n .align-content-sm-end {\n align-content: flex-end !important; }\n .align-content-sm-center {\n align-content: center !important; }\n .align-content-sm-between {\n align-content: space-between !important; }\n .align-content-sm-around {\n align-content: space-around !important; }\n .align-content-sm-stretch {\n align-content: stretch !important; }\n .align-self-sm-auto {\n align-self: auto !important; }\n .align-self-sm-start {\n align-self: flex-start !important; }\n .align-self-sm-end {\n align-self: flex-end !important; }\n .align-self-sm-center {\n align-self: center !important; }\n .align-self-sm-baseline {\n align-self: baseline !important; }\n .align-self-sm-stretch {\n align-self: stretch !important; } }\n\n@media (min-width: 768px) {\n .flex-md-row {\n flex-direction: row !important; }\n .flex-md-column {\n flex-direction: column !important; }\n .flex-md-row-reverse {\n flex-direction: row-reverse !important; }\n .flex-md-column-reverse {\n flex-direction: column-reverse !important; }\n .flex-md-wrap {\n flex-wrap: wrap !important; }\n .flex-md-nowrap {\n flex-wrap: nowrap !important; }\n .flex-md-wrap-reverse {\n flex-wrap: wrap-reverse !important; }\n .flex-md-fill {\n flex: 1 1 auto !important; }\n .flex-md-grow-0 {\n flex-grow: 0 !important; }\n .flex-md-grow-1 {\n flex-grow: 1 !important; }\n .flex-md-shrink-0 {\n flex-shrink: 0 !important; }\n .flex-md-shrink-1 {\n flex-shrink: 1 !important; }\n .justify-content-md-start {\n justify-content: flex-start !important; }\n .justify-content-md-end {\n justify-content: flex-end !important; }\n .justify-content-md-center {\n justify-content: center !important; }\n .justify-content-md-between {\n justify-content: space-between !important; }\n .justify-content-md-around {\n justify-content: space-around !important; }\n .align-items-md-start {\n align-items: flex-start !important; }\n .align-items-md-end {\n align-items: flex-end !important; }\n .align-items-md-center {\n align-items: center !important; }\n .align-items-md-baseline {\n align-items: baseline !important; }\n .align-items-md-stretch {\n align-items: stretch !important; }\n .align-content-md-start {\n align-content: flex-start !important; }\n .align-content-md-end {\n align-content: flex-end !important; }\n .align-content-md-center {\n align-content: center !important; }\n .align-content-md-between {\n align-content: space-between !important; }\n .align-content-md-around {\n align-content: space-around !important; }\n .align-content-md-stretch {\n align-content: stretch !important; }\n .align-self-md-auto {\n align-self: auto !important; }\n .align-self-md-start {\n align-self: flex-start !important; }\n .align-self-md-end {\n align-self: flex-end !important; }\n .align-self-md-center {\n align-self: center !important; }\n .align-self-md-baseline {\n align-self: baseline !important; }\n .align-self-md-stretch {\n align-self: stretch !important; } }\n\n@media (min-width: 992px) {\n .flex-lg-row {\n flex-direction: row !important; }\n .flex-lg-column {\n flex-direction: column !important; }\n .flex-lg-row-reverse {\n flex-direction: row-reverse !important; }\n .flex-lg-column-reverse {\n flex-direction: column-reverse !important; }\n .flex-lg-wrap {\n flex-wrap: wrap !important; }\n .flex-lg-nowrap {\n flex-wrap: nowrap !important; }\n .flex-lg-wrap-reverse {\n flex-wrap: wrap-reverse !important; }\n .flex-lg-fill {\n flex: 1 1 auto !important; }\n .flex-lg-grow-0 {\n flex-grow: 0 !important; }\n .flex-lg-grow-1 {\n flex-grow: 1 !important; }\n .flex-lg-shrink-0 {\n flex-shrink: 0 !important; }\n .flex-lg-shrink-1 {\n flex-shrink: 1 !important; }\n .justify-content-lg-start {\n justify-content: flex-start !important; }\n .justify-content-lg-end {\n justify-content: flex-end !important; }\n .justify-content-lg-center {\n justify-content: center !important; }\n .justify-content-lg-between {\n justify-content: space-between !important; }\n .justify-content-lg-around {\n justify-content: space-around !important; }\n .align-items-lg-start {\n align-items: flex-start !important; }\n .align-items-lg-end {\n align-items: flex-end !important; }\n .align-items-lg-center {\n align-items: center !important; }\n .align-items-lg-baseline {\n align-items: baseline !important; }\n .align-items-lg-stretch {\n align-items: stretch !important; }\n .align-content-lg-start {\n align-content: flex-start !important; }\n .align-content-lg-end {\n align-content: flex-end !important; }\n .align-content-lg-center {\n align-content: center !important; }\n .align-content-lg-between {\n align-content: space-between !important; }\n .align-content-lg-around {\n align-content: space-around !important; }\n .align-content-lg-stretch {\n align-content: stretch !important; }\n .align-self-lg-auto {\n align-self: auto !important; }\n .align-self-lg-start {\n align-self: flex-start !important; }\n .align-self-lg-end {\n align-self: flex-end !important; }\n .align-self-lg-center {\n align-self: center !important; }\n .align-self-lg-baseline {\n align-self: baseline !important; }\n .align-self-lg-stretch {\n align-self: stretch !important; } }\n\n@media (min-width: 1200px) {\n .flex-xl-row {\n flex-direction: row !important; }\n .flex-xl-column {\n flex-direction: column !important; }\n .flex-xl-row-reverse {\n flex-direction: row-reverse !important; }\n .flex-xl-column-reverse {\n flex-direction: column-reverse !important; }\n .flex-xl-wrap {\n flex-wrap: wrap !important; }\n .flex-xl-nowrap {\n flex-wrap: nowrap !important; }\n .flex-xl-wrap-reverse {\n flex-wrap: wrap-reverse !important; }\n .flex-xl-fill {\n flex: 1 1 auto !important; }\n .flex-xl-grow-0 {\n flex-grow: 0 !important; }\n .flex-xl-grow-1 {\n flex-grow: 1 !important; }\n .flex-xl-shrink-0 {\n flex-shrink: 0 !important; }\n .flex-xl-shrink-1 {\n flex-shrink: 1 !important; }\n .justify-content-xl-start {\n justify-content: flex-start !important; }\n .justify-content-xl-end {\n justify-content: flex-end !important; }\n .justify-content-xl-center {\n justify-content: center !important; }\n .justify-content-xl-between {\n justify-content: space-between !important; }\n .justify-content-xl-around {\n justify-content: space-around !important; }\n .align-items-xl-start {\n align-items: flex-start !important; }\n .align-items-xl-end {\n align-items: flex-end !important; }\n .align-items-xl-center {\n align-items: center !important; }\n .align-items-xl-baseline {\n align-items: baseline !important; }\n .align-items-xl-stretch {\n align-items: stretch !important; }\n .align-content-xl-start {\n align-content: flex-start !important; }\n .align-content-xl-end {\n align-content: flex-end !important; }\n .align-content-xl-center {\n align-content: center !important; }\n .align-content-xl-between {\n align-content: space-between !important; }\n .align-content-xl-around {\n align-content: space-around !important; }\n .align-content-xl-stretch {\n align-content: stretch !important; }\n .align-self-xl-auto {\n align-self: auto !important; }\n .align-self-xl-start {\n align-self: flex-start !important; }\n .align-self-xl-end {\n align-self: flex-end !important; }\n .align-self-xl-center {\n align-self: center !important; }\n .align-self-xl-baseline {\n align-self: baseline !important; }\n .align-self-xl-stretch {\n align-self: stretch !important; } }\n\n.float-left {\n float: left !important; }\n\n.float-right {\n float: right !important; }\n\n.float-none {\n float: none !important; }\n\n@media (min-width: 576px) {\n .float-sm-left {\n float: left !important; }\n .float-sm-right {\n float: right !important; }\n .float-sm-none {\n float: none !important; } }\n\n@media (min-width: 768px) {\n .float-md-left {\n float: left !important; }\n .float-md-right {\n float: right !important; }\n .float-md-none {\n float: none !important; } }\n\n@media (min-width: 992px) {\n .float-lg-left {\n float: left !important; }\n .float-lg-right {\n float: right !important; }\n .float-lg-none {\n float: none !important; } }\n\n@media (min-width: 1200px) {\n .float-xl-left {\n float: left !important; }\n .float-xl-right {\n float: right !important; }\n .float-xl-none {\n float: none !important; } }\n\n.position-static {\n position: static !important; }\n\n.position-relative {\n position: relative !important; }\n\n.position-absolute {\n position: absolute !important; }\n\n.position-fixed {\n position: fixed !important; }\n\n.position-sticky {\n position: sticky !important; }\n\n.fixed-top {\n position: fixed;\n top: 0;\n right: 0;\n left: 0;\n z-index: 1030; }\n\n.fixed-bottom {\n position: fixed;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: 1030; }\n\n@supports (position: sticky) {\n .sticky-top {\n position: sticky;\n top: 0;\n z-index: 1020; } }\n\n.sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0; }\n\n.sr-only-focusable:active, .sr-only-focusable:focus {\n position: static;\n width: auto;\n height: auto;\n overflow: visible;\n clip: auto;\n white-space: normal; }\n\n.shadow-sm {\n box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075) !important; }\n\n.shadow {\n box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15) !important; }\n\n.shadow-lg {\n box-shadow: 0 1rem 3rem rgba(0, 0, 0, 0.175) !important; }\n\n.shadow-none {\n box-shadow: none !important; }\n\n.w-25 {\n width: 25% !important; }\n\n.w-50 {\n width: 50% !important; }\n\n.w-75 {\n width: 75% !important; }\n\n.w-100 {\n width: 100% !important; }\n\n.w-auto {\n width: auto !important; }\n\n.h-25 {\n height: 25% !important; }\n\n.h-50 {\n height: 50% !important; }\n\n.h-75 {\n height: 75% !important; }\n\n.h-100 {\n height: 100% !important; }\n\n.h-auto {\n height: auto !important; }\n\n.mw-100 {\n max-width: 100% !important; }\n\n.mh-100 {\n max-height: 100% !important; }\n\n.m-0 {\n margin: 0 !important; }\n\n.mt-0,\n.my-0 {\n margin-top: 0 !important; }\n\n.mr-0,\n.mx-0 {\n margin-right: 0 !important; }\n\n.mb-0,\n.my-0 {\n margin-bottom: 0 !important; }\n\n.ml-0,\n.mx-0 {\n margin-left: 0 !important; }\n\n.m-1 {\n margin: 0.25rem !important; }\n\n.mt-1,\n.my-1 {\n margin-top: 0.25rem !important; }\n\n.mr-1,\n.mx-1 {\n margin-right: 0.25rem !important; }\n\n.mb-1,\n.my-1 {\n margin-bottom: 0.25rem !important; }\n\n.ml-1,\n.mx-1 {\n margin-left: 0.25rem !important; }\n\n.m-2 {\n margin: 0.5rem !important; }\n\n.mt-2,\n.my-2 {\n margin-top: 0.5rem !important; }\n\n.mr-2,\n.mx-2 {\n margin-right: 0.5rem !important; }\n\n.mb-2,\n.my-2 {\n margin-bottom: 0.5rem !important; }\n\n.ml-2,\n.mx-2 {\n margin-left: 0.5rem !important; }\n\n.m-3 {\n margin: 1rem !important; }\n\n.mt-3,\n.my-3 {\n margin-top: 1rem !important; }\n\n.mr-3,\n.mx-3 {\n margin-right: 1rem !important; }\n\n.mb-3,\n.my-3 {\n margin-bottom: 1rem !important; }\n\n.ml-3,\n.mx-3 {\n margin-left: 1rem !important; }\n\n.m-4 {\n margin: 1.5rem !important; }\n\n.mt-4,\n.my-4 {\n margin-top: 1.5rem !important; }\n\n.mr-4,\n.mx-4 {\n margin-right: 1.5rem !important; }\n\n.mb-4,\n.my-4 {\n margin-bottom: 1.5rem !important; }\n\n.ml-4,\n.mx-4 {\n margin-left: 1.5rem !important; }\n\n.m-5 {\n margin: 3rem !important; }\n\n.mt-5,\n.my-5 {\n margin-top: 3rem !important; }\n\n.mr-5,\n.mx-5 {\n margin-right: 3rem !important; }\n\n.mb-5,\n.my-5 {\n margin-bottom: 3rem !important; }\n\n.ml-5,\n.mx-5 {\n margin-left: 3rem !important; }\n\n.p-0 {\n padding: 0 !important; }\n\n.pt-0,\n.py-0 {\n padding-top: 0 !important; }\n\n.pr-0,\n.px-0 {\n padding-right: 0 !important; }\n\n.pb-0,\n.py-0 {\n padding-bottom: 0 !important; }\n\n.pl-0,\n.px-0 {\n padding-left: 0 !important; }\n\n.p-1 {\n padding: 0.25rem !important; }\n\n.pt-1,\n.py-1 {\n padding-top: 0.25rem !important; }\n\n.pr-1,\n.px-1 {\n padding-right: 0.25rem !important; }\n\n.pb-1,\n.py-1 {\n padding-bottom: 0.25rem !important; }\n\n.pl-1,\n.px-1 {\n padding-left: 0.25rem !important; }\n\n.p-2 {\n padding: 0.5rem !important; }\n\n.pt-2,\n.py-2 {\n padding-top: 0.5rem !important; }\n\n.pr-2,\n.px-2 {\n padding-right: 0.5rem !important; }\n\n.pb-2,\n.py-2 {\n padding-bottom: 0.5rem !important; }\n\n.pl-2,\n.px-2 {\n padding-left: 0.5rem !important; }\n\n.p-3 {\n padding: 1rem !important; }\n\n.pt-3,\n.py-3 {\n padding-top: 1rem !important; }\n\n.pr-3,\n.px-3 {\n padding-right: 1rem !important; }\n\n.pb-3,\n.py-3 {\n padding-bottom: 1rem !important; }\n\n.pl-3,\n.px-3 {\n padding-left: 1rem !important; }\n\n.p-4 {\n padding: 1.5rem !important; }\n\n.pt-4,\n.py-4 {\n padding-top: 1.5rem !important; }\n\n.pr-4,\n.px-4 {\n padding-right: 1.5rem !important; }\n\n.pb-4,\n.py-4 {\n padding-bottom: 1.5rem !important; }\n\n.pl-4,\n.px-4 {\n padding-left: 1.5rem !important; }\n\n.p-5 {\n padding: 3rem !important; }\n\n.pt-5,\n.py-5 {\n padding-top: 3rem !important; }\n\n.pr-5,\n.px-5 {\n padding-right: 3rem !important; }\n\n.pb-5,\n.py-5 {\n padding-bottom: 3rem !important; }\n\n.pl-5,\n.px-5 {\n padding-left: 3rem !important; }\n\n.m-auto {\n margin: auto !important; }\n\n.mt-auto,\n.my-auto {\n margin-top: auto !important; }\n\n.mr-auto,\n.mx-auto {\n margin-right: auto !important; }\n\n.mb-auto,\n.my-auto {\n margin-bottom: auto !important; }\n\n.ml-auto,\n.mx-auto {\n margin-left: auto !important; }\n\n@media (min-width: 576px) {\n .m-sm-0 {\n margin: 0 !important; }\n .mt-sm-0,\n .my-sm-0 {\n margin-top: 0 !important; }\n .mr-sm-0,\n .mx-sm-0 {\n margin-right: 0 !important; }\n .mb-sm-0,\n .my-sm-0 {\n margin-bottom: 0 !important; }\n .ml-sm-0,\n .mx-sm-0 {\n margin-left: 0 !important; }\n .m-sm-1 {\n margin: 0.25rem !important; }\n .mt-sm-1,\n .my-sm-1 {\n margin-top: 0.25rem !important; }\n .mr-sm-1,\n .mx-sm-1 {\n margin-right: 0.25rem !important; }\n .mb-sm-1,\n .my-sm-1 {\n margin-bottom: 0.25rem !important; }\n .ml-sm-1,\n .mx-sm-1 {\n margin-left: 0.25rem !important; }\n .m-sm-2 {\n margin: 0.5rem !important; }\n .mt-sm-2,\n .my-sm-2 {\n margin-top: 0.5rem !important; }\n .mr-sm-2,\n .mx-sm-2 {\n margin-right: 0.5rem !important; }\n .mb-sm-2,\n .my-sm-2 {\n margin-bottom: 0.5rem !important; }\n .ml-sm-2,\n .mx-sm-2 {\n margin-left: 0.5rem !important; }\n .m-sm-3 {\n margin: 1rem !important; }\n .mt-sm-3,\n .my-sm-3 {\n margin-top: 1rem !important; }\n .mr-sm-3,\n .mx-sm-3 {\n margin-right: 1rem !important; }\n .mb-sm-3,\n .my-sm-3 {\n margin-bottom: 1rem !important; }\n .ml-sm-3,\n .mx-sm-3 {\n margin-left: 1rem !important; }\n .m-sm-4 {\n margin: 1.5rem !important; }\n .mt-sm-4,\n .my-sm-4 {\n margin-top: 1.5rem !important; }\n .mr-sm-4,\n .mx-sm-4 {\n margin-right: 1.5rem !important; }\n .mb-sm-4,\n .my-sm-4 {\n margin-bottom: 1.5rem !important; }\n .ml-sm-4,\n .mx-sm-4 {\n margin-left: 1.5rem !important; }\n .m-sm-5 {\n margin: 3rem !important; }\n .mt-sm-5,\n .my-sm-5 {\n margin-top: 3rem !important; }\n .mr-sm-5,\n .mx-sm-5 {\n margin-right: 3rem !important; }\n .mb-sm-5,\n .my-sm-5 {\n margin-bottom: 3rem !important; }\n .ml-sm-5,\n .mx-sm-5 {\n margin-left: 3rem !important; }\n .p-sm-0 {\n padding: 0 !important; }\n .pt-sm-0,\n .py-sm-0 {\n padding-top: 0 !important; }\n .pr-sm-0,\n .px-sm-0 {\n padding-right: 0 !important; }\n .pb-sm-0,\n .py-sm-0 {\n padding-bottom: 0 !important; }\n .pl-sm-0,\n .px-sm-0 {\n padding-left: 0 !important; }\n .p-sm-1 {\n padding: 0.25rem !important; }\n .pt-sm-1,\n .py-sm-1 {\n padding-top: 0.25rem !important; }\n .pr-sm-1,\n .px-sm-1 {\n padding-right: 0.25rem !important; }\n .pb-sm-1,\n .py-sm-1 {\n padding-bottom: 0.25rem !important; }\n .pl-sm-1,\n .px-sm-1 {\n padding-left: 0.25rem !important; }\n .p-sm-2 {\n padding: 0.5rem !important; }\n .pt-sm-2,\n .py-sm-2 {\n padding-top: 0.5rem !important; }\n .pr-sm-2,\n .px-sm-2 {\n padding-right: 0.5rem !important; }\n .pb-sm-2,\n .py-sm-2 {\n padding-bottom: 0.5rem !important; }\n .pl-sm-2,\n .px-sm-2 {\n padding-left: 0.5rem !important; }\n .p-sm-3 {\n padding: 1rem !important; }\n .pt-sm-3,\n .py-sm-3 {\n padding-top: 1rem !important; }\n .pr-sm-3,\n .px-sm-3 {\n padding-right: 1rem !important; }\n .pb-sm-3,\n .py-sm-3 {\n padding-bottom: 1rem !important; }\n .pl-sm-3,\n .px-sm-3 {\n padding-left: 1rem !important; }\n .p-sm-4 {\n padding: 1.5rem !important; }\n .pt-sm-4,\n .py-sm-4 {\n padding-top: 1.5rem !important; }\n .pr-sm-4,\n .px-sm-4 {\n padding-right: 1.5rem !important; }\n .pb-sm-4,\n .py-sm-4 {\n padding-bottom: 1.5rem !important; }\n .pl-sm-4,\n .px-sm-4 {\n padding-left: 1.5rem !important; }\n .p-sm-5 {\n padding: 3rem !important; }\n .pt-sm-5,\n .py-sm-5 {\n padding-top: 3rem !important; }\n .pr-sm-5,\n .px-sm-5 {\n padding-right: 3rem !important; }\n .pb-sm-5,\n .py-sm-5 {\n padding-bottom: 3rem !important; }\n .pl-sm-5,\n .px-sm-5 {\n padding-left: 3rem !important; }\n .m-sm-auto {\n margin: auto !important; }\n .mt-sm-auto,\n .my-sm-auto {\n margin-top: auto !important; }\n .mr-sm-auto,\n .mx-sm-auto {\n margin-right: auto !important; }\n .mb-sm-auto,\n .my-sm-auto {\n margin-bottom: auto !important; }\n .ml-sm-auto,\n .mx-sm-auto {\n margin-left: auto !important; } }\n\n@media (min-width: 768px) {\n .m-md-0 {\n margin: 0 !important; }\n .mt-md-0,\n .my-md-0 {\n margin-top: 0 !important; }\n .mr-md-0,\n .mx-md-0 {\n margin-right: 0 !important; }\n .mb-md-0,\n .my-md-0 {\n margin-bottom: 0 !important; }\n .ml-md-0,\n .mx-md-0 {\n margin-left: 0 !important; }\n .m-md-1 {\n margin: 0.25rem !important; }\n .mt-md-1,\n .my-md-1 {\n margin-top: 0.25rem !important; }\n .mr-md-1,\n .mx-md-1 {\n margin-right: 0.25rem !important; }\n .mb-md-1,\n .my-md-1 {\n margin-bottom: 0.25rem !important; }\n .ml-md-1,\n .mx-md-1 {\n margin-left: 0.25rem !important; }\n .m-md-2 {\n margin: 0.5rem !important; }\n .mt-md-2,\n .my-md-2 {\n margin-top: 0.5rem !important; }\n .mr-md-2,\n .mx-md-2 {\n margin-right: 0.5rem !important; }\n .mb-md-2,\n .my-md-2 {\n margin-bottom: 0.5rem !important; }\n .ml-md-2,\n .mx-md-2 {\n margin-left: 0.5rem !important; }\n .m-md-3 {\n margin: 1rem !important; }\n .mt-md-3,\n .my-md-3 {\n margin-top: 1rem !important; }\n .mr-md-3,\n .mx-md-3 {\n margin-right: 1rem !important; }\n .mb-md-3,\n .my-md-3 {\n margin-bottom: 1rem !important; }\n .ml-md-3,\n .mx-md-3 {\n margin-left: 1rem !important; }\n .m-md-4 {\n margin: 1.5rem !important; }\n .mt-md-4,\n .my-md-4 {\n margin-top: 1.5rem !important; }\n .mr-md-4,\n .mx-md-4 {\n margin-right: 1.5rem !important; }\n .mb-md-4,\n .my-md-4 {\n margin-bottom: 1.5rem !important; }\n .ml-md-4,\n .mx-md-4 {\n margin-left: 1.5rem !important; }\n .m-md-5 {\n margin: 3rem !important; }\n .mt-md-5,\n .my-md-5 {\n margin-top: 3rem !important; }\n .mr-md-5,\n .mx-md-5 {\n margin-right: 3rem !important; }\n .mb-md-5,\n .my-md-5 {\n margin-bottom: 3rem !important; }\n .ml-md-5,\n .mx-md-5 {\n margin-left: 3rem !important; }\n .p-md-0 {\n padding: 0 !important; }\n .pt-md-0,\n .py-md-0 {\n padding-top: 0 !important; }\n .pr-md-0,\n .px-md-0 {\n padding-right: 0 !important; }\n .pb-md-0,\n .py-md-0 {\n padding-bottom: 0 !important; }\n .pl-md-0,\n .px-md-0 {\n padding-left: 0 !important; }\n .p-md-1 {\n padding: 0.25rem !important; }\n .pt-md-1,\n .py-md-1 {\n padding-top: 0.25rem !important; }\n .pr-md-1,\n .px-md-1 {\n padding-right: 0.25rem !important; }\n .pb-md-1,\n .py-md-1 {\n padding-bottom: 0.25rem !important; }\n .pl-md-1,\n .px-md-1 {\n padding-left: 0.25rem !important; }\n .p-md-2 {\n padding: 0.5rem !important; }\n .pt-md-2,\n .py-md-2 {\n padding-top: 0.5rem !important; }\n .pr-md-2,\n .px-md-2 {\n padding-right: 0.5rem !important; }\n .pb-md-2,\n .py-md-2 {\n padding-bottom: 0.5rem !important; }\n .pl-md-2,\n .px-md-2 {\n padding-left: 0.5rem !important; }\n .p-md-3 {\n padding: 1rem !important; }\n .pt-md-3,\n .py-md-3 {\n padding-top: 1rem !important; }\n .pr-md-3,\n .px-md-3 {\n padding-right: 1rem !important; }\n .pb-md-3,\n .py-md-3 {\n padding-bottom: 1rem !important; }\n .pl-md-3,\n .px-md-3 {\n padding-left: 1rem !important; }\n .p-md-4 {\n padding: 1.5rem !important; }\n .pt-md-4,\n .py-md-4 {\n padding-top: 1.5rem !important; }\n .pr-md-4,\n .px-md-4 {\n padding-right: 1.5rem !important; }\n .pb-md-4,\n .py-md-4 {\n padding-bottom: 1.5rem !important; }\n .pl-md-4,\n .px-md-4 {\n padding-left: 1.5rem !important; }\n .p-md-5 {\n padding: 3rem !important; }\n .pt-md-5,\n .py-md-5 {\n padding-top: 3rem !important; }\n .pr-md-5,\n .px-md-5 {\n padding-right: 3rem !important; }\n .pb-md-5,\n .py-md-5 {\n padding-bottom: 3rem !important; }\n .pl-md-5,\n .px-md-5 {\n padding-left: 3rem !important; }\n .m-md-auto {\n margin: auto !important; }\n .mt-md-auto,\n .my-md-auto {\n margin-top: auto !important; }\n .mr-md-auto,\n .mx-md-auto {\n margin-right: auto !important; }\n .mb-md-auto,\n .my-md-auto {\n margin-bottom: auto !important; }\n .ml-md-auto,\n .mx-md-auto {\n margin-left: auto !important; } }\n\n@media (min-width: 992px) {\n .m-lg-0 {\n margin: 0 !important; }\n .mt-lg-0,\n .my-lg-0 {\n margin-top: 0 !important; }\n .mr-lg-0,\n .mx-lg-0 {\n margin-right: 0 !important; }\n .mb-lg-0,\n .my-lg-0 {\n margin-bottom: 0 !important; }\n .ml-lg-0,\n .mx-lg-0 {\n margin-left: 0 !important; }\n .m-lg-1 {\n margin: 0.25rem !important; }\n .mt-lg-1,\n .my-lg-1 {\n margin-top: 0.25rem !important; }\n .mr-lg-1,\n .mx-lg-1 {\n margin-right: 0.25rem !important; }\n .mb-lg-1,\n .my-lg-1 {\n margin-bottom: 0.25rem !important; }\n .ml-lg-1,\n .mx-lg-1 {\n margin-left: 0.25rem !important; }\n .m-lg-2 {\n margin: 0.5rem !important; }\n .mt-lg-2,\n .my-lg-2 {\n margin-top: 0.5rem !important; }\n .mr-lg-2,\n .mx-lg-2 {\n margin-right: 0.5rem !important; }\n .mb-lg-2,\n .my-lg-2 {\n margin-bottom: 0.5rem !important; }\n .ml-lg-2,\n .mx-lg-2 {\n margin-left: 0.5rem !important; }\n .m-lg-3 {\n margin: 1rem !important; }\n .mt-lg-3,\n .my-lg-3 {\n margin-top: 1rem !important; }\n .mr-lg-3,\n .mx-lg-3 {\n margin-right: 1rem !important; }\n .mb-lg-3,\n .my-lg-3 {\n margin-bottom: 1rem !important; }\n .ml-lg-3,\n .mx-lg-3 {\n margin-left: 1rem !important; }\n .m-lg-4 {\n margin: 1.5rem !important; }\n .mt-lg-4,\n .my-lg-4 {\n margin-top: 1.5rem !important; }\n .mr-lg-4,\n .mx-lg-4 {\n margin-right: 1.5rem !important; }\n .mb-lg-4,\n .my-lg-4 {\n margin-bottom: 1.5rem !important; }\n .ml-lg-4,\n .mx-lg-4 {\n margin-left: 1.5rem !important; }\n .m-lg-5 {\n margin: 3rem !important; }\n .mt-lg-5,\n .my-lg-5 {\n margin-top: 3rem !important; }\n .mr-lg-5,\n .mx-lg-5 {\n margin-right: 3rem !important; }\n .mb-lg-5,\n .my-lg-5 {\n margin-bottom: 3rem !important; }\n .ml-lg-5,\n .mx-lg-5 {\n margin-left: 3rem !important; }\n .p-lg-0 {\n padding: 0 !important; }\n .pt-lg-0,\n .py-lg-0 {\n padding-top: 0 !important; }\n .pr-lg-0,\n .px-lg-0 {\n padding-right: 0 !important; }\n .pb-lg-0,\n .py-lg-0 {\n padding-bottom: 0 !important; }\n .pl-lg-0,\n .px-lg-0 {\n padding-left: 0 !important; }\n .p-lg-1 {\n padding: 0.25rem !important; }\n .pt-lg-1,\n .py-lg-1 {\n padding-top: 0.25rem !important; }\n .pr-lg-1,\n .px-lg-1 {\n padding-right: 0.25rem !important; }\n .pb-lg-1,\n .py-lg-1 {\n padding-bottom: 0.25rem !important; }\n .pl-lg-1,\n .px-lg-1 {\n padding-left: 0.25rem !important; }\n .p-lg-2 {\n padding: 0.5rem !important; }\n .pt-lg-2,\n .py-lg-2 {\n padding-top: 0.5rem !important; }\n .pr-lg-2,\n .px-lg-2 {\n padding-right: 0.5rem !important; }\n .pb-lg-2,\n .py-lg-2 {\n padding-bottom: 0.5rem !important; }\n .pl-lg-2,\n .px-lg-2 {\n padding-left: 0.5rem !important; }\n .p-lg-3 {\n padding: 1rem !important; }\n .pt-lg-3,\n .py-lg-3 {\n padding-top: 1rem !important; }\n .pr-lg-3,\n .px-lg-3 {\n padding-right: 1rem !important; }\n .pb-lg-3,\n .py-lg-3 {\n padding-bottom: 1rem !important; }\n .pl-lg-3,\n .px-lg-3 {\n padding-left: 1rem !important; }\n .p-lg-4 {\n padding: 1.5rem !important; }\n .pt-lg-4,\n .py-lg-4 {\n padding-top: 1.5rem !important; }\n .pr-lg-4,\n .px-lg-4 {\n padding-right: 1.5rem !important; }\n .pb-lg-4,\n .py-lg-4 {\n padding-bottom: 1.5rem !important; }\n .pl-lg-4,\n .px-lg-4 {\n padding-left: 1.5rem !important; }\n .p-lg-5 {\n padding: 3rem !important; }\n .pt-lg-5,\n .py-lg-5 {\n padding-top: 3rem !important; }\n .pr-lg-5,\n .px-lg-5 {\n padding-right: 3rem !important; }\n .pb-lg-5,\n .py-lg-5 {\n padding-bottom: 3rem !important; }\n .pl-lg-5,\n .px-lg-5 {\n padding-left: 3rem !important; }\n .m-lg-auto {\n margin: auto !important; }\n .mt-lg-auto,\n .my-lg-auto {\n margin-top: auto !important; }\n .mr-lg-auto,\n .mx-lg-auto {\n margin-right: auto !important; }\n .mb-lg-auto,\n .my-lg-auto {\n margin-bottom: auto !important; }\n .ml-lg-auto,\n .mx-lg-auto {\n margin-left: auto !important; } }\n\n@media (min-width: 1200px) {\n .m-xl-0 {\n margin: 0 !important; }\n .mt-xl-0,\n .my-xl-0 {\n margin-top: 0 !important; }\n .mr-xl-0,\n .mx-xl-0 {\n margin-right: 0 !important; }\n .mb-xl-0,\n .my-xl-0 {\n margin-bottom: 0 !important; }\n .ml-xl-0,\n .mx-xl-0 {\n margin-left: 0 !important; }\n .m-xl-1 {\n margin: 0.25rem !important; }\n .mt-xl-1,\n .my-xl-1 {\n margin-top: 0.25rem !important; }\n .mr-xl-1,\n .mx-xl-1 {\n margin-right: 0.25rem !important; }\n .mb-xl-1,\n .my-xl-1 {\n margin-bottom: 0.25rem !important; }\n .ml-xl-1,\n .mx-xl-1 {\n margin-left: 0.25rem !important; }\n .m-xl-2 {\n margin: 0.5rem !important; }\n .mt-xl-2,\n .my-xl-2 {\n margin-top: 0.5rem !important; }\n .mr-xl-2,\n .mx-xl-2 {\n margin-right: 0.5rem !important; }\n .mb-xl-2,\n .my-xl-2 {\n margin-bottom: 0.5rem !important; }\n .ml-xl-2,\n .mx-xl-2 {\n margin-left: 0.5rem !important; }\n .m-xl-3 {\n margin: 1rem !important; }\n .mt-xl-3,\n .my-xl-3 {\n margin-top: 1rem !important; }\n .mr-xl-3,\n .mx-xl-3 {\n margin-right: 1rem !important; }\n .mb-xl-3,\n .my-xl-3 {\n margin-bottom: 1rem !important; }\n .ml-xl-3,\n .mx-xl-3 {\n margin-left: 1rem !important; }\n .m-xl-4 {\n margin: 1.5rem !important; }\n .mt-xl-4,\n .my-xl-4 {\n margin-top: 1.5rem !important; }\n .mr-xl-4,\n .mx-xl-4 {\n margin-right: 1.5rem !important; }\n .mb-xl-4,\n .my-xl-4 {\n margin-bottom: 1.5rem !important; }\n .ml-xl-4,\n .mx-xl-4 {\n margin-left: 1.5rem !important; }\n .m-xl-5 {\n margin: 3rem !important; }\n .mt-xl-5,\n .my-xl-5 {\n margin-top: 3rem !important; }\n .mr-xl-5,\n .mx-xl-5 {\n margin-right: 3rem !important; }\n .mb-xl-5,\n .my-xl-5 {\n margin-bottom: 3rem !important; }\n .ml-xl-5,\n .mx-xl-5 {\n margin-left: 3rem !important; }\n .p-xl-0 {\n padding: 0 !important; }\n .pt-xl-0,\n .py-xl-0 {\n padding-top: 0 !important; }\n .pr-xl-0,\n .px-xl-0 {\n padding-right: 0 !important; }\n .pb-xl-0,\n .py-xl-0 {\n padding-bottom: 0 !important; }\n .pl-xl-0,\n .px-xl-0 {\n padding-left: 0 !important; }\n .p-xl-1 {\n padding: 0.25rem !important; }\n .pt-xl-1,\n .py-xl-1 {\n padding-top: 0.25rem !important; }\n .pr-xl-1,\n .px-xl-1 {\n padding-right: 0.25rem !important; }\n .pb-xl-1,\n .py-xl-1 {\n padding-bottom: 0.25rem !important; }\n .pl-xl-1,\n .px-xl-1 {\n padding-left: 0.25rem !important; }\n .p-xl-2 {\n padding: 0.5rem !important; }\n .pt-xl-2,\n .py-xl-2 {\n padding-top: 0.5rem !important; }\n .pr-xl-2,\n .px-xl-2 {\n padding-right: 0.5rem !important; }\n .pb-xl-2,\n .py-xl-2 {\n padding-bottom: 0.5rem !important; }\n .pl-xl-2,\n .px-xl-2 {\n padding-left: 0.5rem !important; }\n .p-xl-3 {\n padding: 1rem !important; }\n .pt-xl-3,\n .py-xl-3 {\n padding-top: 1rem !important; }\n .pr-xl-3,\n .px-xl-3 {\n padding-right: 1rem !important; }\n .pb-xl-3,\n .py-xl-3 {\n padding-bottom: 1rem !important; }\n .pl-xl-3,\n .px-xl-3 {\n padding-left: 1rem !important; }\n .p-xl-4 {\n padding: 1.5rem !important; }\n .pt-xl-4,\n .py-xl-4 {\n padding-top: 1.5rem !important; }\n .pr-xl-4,\n .px-xl-4 {\n padding-right: 1.5rem !important; }\n .pb-xl-4,\n .py-xl-4 {\n padding-bottom: 1.5rem !important; }\n .pl-xl-4,\n .px-xl-4 {\n padding-left: 1.5rem !important; }\n .p-xl-5 {\n padding: 3rem !important; }\n .pt-xl-5,\n .py-xl-5 {\n padding-top: 3rem !important; }\n .pr-xl-5,\n .px-xl-5 {\n padding-right: 3rem !important; }\n .pb-xl-5,\n .py-xl-5 {\n padding-bottom: 3rem !important; }\n .pl-xl-5,\n .px-xl-5 {\n padding-left: 3rem !important; }\n .m-xl-auto {\n margin: auto !important; }\n .mt-xl-auto,\n .my-xl-auto {\n margin-top: auto !important; }\n .mr-xl-auto,\n .mx-xl-auto {\n margin-right: auto !important; }\n .mb-xl-auto,\n .my-xl-auto {\n margin-bottom: auto !important; }\n .ml-xl-auto,\n .mx-xl-auto {\n margin-left: auto !important; } }\n\n.text-monospace {\n font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; }\n\n.text-justify {\n text-align: justify !important; }\n\n.text-nowrap {\n white-space: nowrap !important; }\n\n.text-truncate {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap; }\n\n.text-left {\n text-align: left !important; }\n\n.text-right {\n text-align: right !important; }\n\n.text-center {\n text-align: center !important; }\n\n@media (min-width: 576px) {\n .text-sm-left {\n text-align: left !important; }\n .text-sm-right {\n text-align: right !important; }\n .text-sm-center {\n text-align: center !important; } }\n\n@media (min-width: 768px) {\n .text-md-left {\n text-align: left !important; }\n .text-md-right {\n text-align: right !important; }\n .text-md-center {\n text-align: center !important; } }\n\n@media (min-width: 992px) {\n .text-lg-left {\n text-align: left !important; }\n .text-lg-right {\n text-align: right !important; }\n .text-lg-center {\n text-align: center !important; } }\n\n@media (min-width: 1200px) {\n .text-xl-left {\n text-align: left !important; }\n .text-xl-right {\n text-align: right !important; }\n .text-xl-center {\n text-align: center !important; } }\n\n.text-lowercase {\n text-transform: lowercase !important; }\n\n.text-uppercase {\n text-transform: uppercase !important; }\n\n.text-capitalize {\n text-transform: capitalize !important; }\n\n.font-weight-light {\n font-weight: 300 !important; }\n\n.font-weight-normal {\n font-weight: 400 !important; }\n\n.font-weight-bold {\n font-weight: 700 !important; }\n\n.font-italic {\n font-style: italic !important; }\n\n.text-white {\n color: #fff !important; }\n\n.text-primary {\n color: #007bff !important; }\n\na.text-primary:hover, a.text-primary:focus {\n color: #0062cc !important; }\n\n.text-secondary {\n color: #6c757d !important; }\n\na.text-secondary:hover, a.text-secondary:focus {\n color: #545b62 !important; }\n\n.text-success {\n color: #28a745 !important; }\n\na.text-success:hover, a.text-success:focus {\n color: #1e7e34 !important; }\n\n.text-info {\n color: #17a2b8 !important; }\n\na.text-info:hover, a.text-info:focus {\n color: #117a8b !important; }\n\n.text-warning {\n color: #ffc107 !important; }\n\na.text-warning:hover, a.text-warning:focus {\n color: #d39e00 !important; }\n\n.text-danger {\n color: #dc3545 !important; }\n\na.text-danger:hover, a.text-danger:focus {\n color: #bd2130 !important; }\n\n.text-light {\n color: #f8f9fa !important; }\n\na.text-light:hover, a.text-light:focus {\n color: #dae0e5 !important; }\n\n.text-dark {\n color: #343a40 !important; }\n\na.text-dark:hover, a.text-dark:focus {\n color: #1d2124 !important; }\n\n.text-body {\n color: #212529 !important; }\n\n.text-muted {\n color: #6c757d !important; }\n\n.text-black-50 {\n color: rgba(0, 0, 0, 0.5) !important; }\n\n.text-white-50 {\n color: rgba(255, 255, 255, 0.5) !important; }\n\n.text-hide {\n font: 0/0 a;\n color: transparent;\n text-shadow: none;\n background-color: transparent;\n border: 0; }\n\n.visible {\n visibility: visible !important; }\n\n.invisible {\n visibility: hidden !important; }\n\n@media print {\n *,\n *::before,\n *::after {\n text-shadow: none !important;\n box-shadow: none !important; }\n a:not(.btn) {\n text-decoration: underline; }\n abbr[title]::after {\n content: " (" attr(title) ")"; }\n pre {\n white-space: pre-wrap !important; }\n pre,\n blockquote {\n border: 1px solid #adb5bd;\n page-break-inside: avoid; }\n thead {\n display: table-header-group; }\n tr,\n img {\n page-break-inside: avoid; }\n p,\n h2,\n h3 {\n orphans: 3;\n widows: 3; }\n h2,\n h3 {\n page-break-after: avoid; }\n @page {\n size: a3; }\n body {\n min-width: 992px !important; }\n .container {\n min-width: 992px !important; }\n .navbar {\n display: none; }\n .badge {\n border: 1px solid #000; }\n .table {\n border-collapse: collapse !important; }\n .table td,\n .table th {\n background-color: #fff !important; }\n .table-bordered th,\n .table-bordered td {\n border: 1px solid #dee2e6 !important; }\n .table-dark {\n color: inherit; }\n .table-dark th,\n .table-dark td,\n .table-dark thead th,\n .table-dark tbody + tbody {\n border-color: #dee2e6; }\n .table .thead-dark th {\n color: inherit;\n border-color: #dee2e6; } }\n\nh1 {\n font-size: 10vw;\n font-weight: 200;\n margin: 0; }\n\nbody {\n overflow-x: hidden; }\n\n.subtitle {\n font-style: italic;\n color: #999;\n font-size: 5vw;\n font-weight: 300; }\n\n.background-stripe {\n width: 100vw;\n background-image: url('+r(o(0))+");\n background-size: cover;\n height: 30vw;\n margin: 200px 0 150px;\n min-height: 1000px;\n position: relative; }\n .background-stripe .overlay {\n position: absolute;\n width: 100vw;\n width: 1px;\n height: 1px; }\n .background-stripe .overlay.overlay1 {\n top: -1px;\n left: 0;\n border-top: 10vw solid white;\n border-right: 100vw solid transparent; }\n .background-stripe .overlay.overlay2 {\n bottom: -1px;\n right: 0;\n border-bottom: 10vw solid white;\n border-left: 100vw solid transparent; }\n .background-stripe .terminal {\n position: absolute;\n left: 50%;\n top: 5vw;\n width: 1304px;\n margin-left: -652px;\n height: 972px;\n border-radius: 9px;\n box-shadow: 0 0 100px black;\n background: url("+r(o(7))+");\n background-size: cover;\n animation: slideIn ease-out 1s;\n opacity: .95; }\n @media (max-width: 1500px) {\n .background-stripe {\n min-height: 500px;\n margin: 200px 0 100px; }\n .background-stripe .terminal {\n width: 652px;\n top: -100px;\n margin-left: -326px;\n height: 486px;\n border-radius: 5px; } }\n @media (max-width: 750px) {\n .background-stripe {\n min-height: 250px;\n margin: 100px 0 50px; }\n .background-stripe .terminal {\n width: 326px;\n top: -50px;\n margin-left: -163px;\n height: 243px;\n border-radius: 3px; } }\n\n.feature {\n font-size: 45px;\n line-height: 40px;\n opacity: .5;\n font-style: italic; }\n\n@keyframes slideIn {\n from {\n opacity: 0;\n margin-top: 200px; }\n to {\n opacity: .95;\n margin-top: 0px; } }\n\n.background-stripe2 {\n width: 100vw;\n background-image: url("+r(o(0))+");\n background-size: cover;\n height: 30vw;\n margin: 100px 0 0;\n position: relative; }\n .background-stripe2 .overlay {\n position: absolute;\n width: 100vw;\n width: 1px;\n height: 1px; }\n .background-stripe2 .overlay.overlay1 {\n top: -1px;\n right: 0;\n border-top: 10vw solid white;\n border-left: 100vw solid transparent; }\n",""])},function(n,t){n.exports=function(n){return"string"!=typeof n?n:(/^['"].*['"]$/.test(n)&&(n=n.slice(1,-1)),/["'() \t\n]/.test(n)?'"'+n.replace(/"/g,'\\"').replace(/\n/g,"\\n")+'"':n)}},function(n,t){n.exports=function(n){var t=[];return t.toString=function(){return this.map(function(t){var o=function(n,t){var o=n[1]||"",r=n[3];if(!r)return o;if(t&&"function"==typeof btoa){var e=function(n){return"/*# sourceMappingURL=data:application/json;charset=utf-8;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(n))))+" */"}(r),a=r.sources.map(function(n){return"/*# sourceURL="+r.sourceRoot+n+" */"});return[o].concat(a).concat([e]).join("\n")}return[o].join("\n")}(t,n);return t[2]?"@media "+t[2]+"{"+o+"}":o}).join("")},t.i=function(n,o){"string"==typeof n&&(n=[[null,n,""]]);for(var r={},e=0;e=0&&d.splice(t,1)}function g(n){var t=document.createElement("style");if(void 0===n.attrs.type&&(n.attrs.type="text/css"),void 0===n.attrs.nonce){var r=function(){0;return o.nc}();r&&(n.attrs.nonce=r)}return f(t,n.attrs),s(n,t),t}function f(n,t){Object.keys(t).forEach(function(o){n.setAttribute(o,t[o])})}function u(n,t){var o,r,e,a;if(t.transform&&n.css){if(!(a=t.transform(n.css)))return function(){};n.css=a}if(t.singleton){var d=l++;o=i||(i=g(t)),r=x.bind(null,o,d,!1),e=x.bind(null,o,d,!0)}else n.sourceMap&&"function"==typeof URL&&"function"==typeof URL.createObjectURL&&"function"==typeof URL.revokeObjectURL&&"function"==typeof Blob&&"function"==typeof btoa?(o=function(n){var t=document.createElement("link");return void 0===n.attrs.type&&(n.attrs.type="text/css"),n.attrs.rel="stylesheet",f(t,n.attrs),s(n,t),t}(t),r=function(n,t,o){var r=o.css,e=o.sourceMap,a=void 0===t.convertToAbsoluteUrls&&e;(t.convertToAbsoluteUrls||a)&&(r=m(r));e&&(r+="\n/*# sourceMappingURL=data:application/json;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(e))))+" */");var i=new Blob([r],{type:"text/css"}),l=n.href;n.href=URL.createObjectURL(i),l&&URL.revokeObjectURL(l)}.bind(null,o,t),e=function(){b(o),o.href&&URL.revokeObjectURL(o.href)}):(o=g(t),r=function(n,t){var o=t.css,r=t.media;r&&n.setAttribute("media",r);if(n.styleSheet)n.styleSheet.cssText=o;else{for(;n.firstChild;)n.removeChild(n.firstChild);n.appendChild(document.createTextNode(o))}}.bind(null,o),e=function(){b(o)});return r(n),function(t){if(t){if(t.css===n.css&&t.media===n.media&&t.sourceMap===n.sourceMap)return;r(n=t)}else e()}}n.exports=function(n,t){if("undefined"!=typeof DEBUG&&DEBUG&&"object"!=typeof document)throw new Error("The style-loader cannot be used in a non-browser environment");(t=t||{}).attrs="object"==typeof t.attrs?t.attrs:{},t.singleton||"boolean"==typeof t.singleton||(t.singleton=e()),t.insertInto||(t.insertInto="head"),t.insertAt||(t.insertAt="bottom");var o=p(n,t);return c(o,t),function(n){for(var e=[],a=0;aTerminus windows
linux
macos
powershell
wsl
cygwin
git-bash
cmder
clink
full unicode
global hotkey
plugins
tab recovery
custom css
themes
font ligatures
clickable paths
tabs on top/bottom
vibrancy
bracketed paste
\ No newline at end of file
diff --git a/docs/index.js b/docs/index.js
deleted file mode 100644
index 0779cb30..00000000
--- a/docs/index.js
+++ /dev/null
@@ -1 +0,0 @@
-import './styles.scss'
diff --git a/docs/index.pug b/docs/index.pug
deleted file mode 100644
index abc5cbae..00000000
--- a/docs/index.pug
+++ /dev/null
@@ -1,75 +0,0 @@
-doctype html
-html
- head
- base(href='dist/')
- meta(name='viewport', content='initial-scale=1, minimal-ui, shrink-to-fit=no')
- link(href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400", rel="stylesheet")
- script(src='bundle.js')
- title Terminus
- body
- .mt-5.mb-5#header
- .text-center
- h1 Terminus
- .subtitle.mb-3 A terminal for a more modern age
-
- a.btn.btn-lg.btn-outline-dark.mt-4(href='https://github.com/Eugeny/terminus/releases/latest', target='_blank')
- strong DOWNLOAD
-
- a.btn.btn-lg.btn-outline-secondary.mt-4.ml-3(href='https://github.com/Eugeny/terminus', target='_blank')
- strong GITHUB
-
-
- .background-stripe
- .overlay.overlay1
- .overlay.overlay2
- .terminal
-
- .container.mt-5.mb-5
- .d-flex.flex-wrap.flex-md-nowrap
- .w-100
- .feature windows
- .feature linux
- .feature macos
- br
- .feature powershell
- .feature wsl
- .feature cygwin
- .feature git-bash
- .feature cmder
- .feature clink
-
- .w-100
- .feature full unicode
- .feature global hotkey
- .feature plugins
- .feature tab recovery
- .feature custom css
- .feature themes
- .feature font ligatures
- .feature clickable paths
- .feature tabs on top/bottom
- .feature vibrancy
- .feature bracketed paste
-
- .container.mt-5.mb-5
- .text-center.mt-5
- .mb-4.mt-5
- script(type='text/javascript', src='https://ko-fi.com/widgets/widget_2.js')
- script(type='text/javascript').
- kofiwidget2.init('Buy me a coffee', '#46b798', 'J3J8KWTF')
- kofiwidget2.draw()
-
- a.btn.btn-lg.btn-outline-secondary.mt-3(href='/terminus/#header')
- strong BEAM ME UP
-
- .background-stripe2
- .overlay.overlay1
-
- script.
- (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
- (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
- m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
- })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
-
- ga('create', 'UA-3278102-18', 'auto');
- ga('send', 'pageview');
diff --git a/docs/package.json b/docs/package.json
deleted file mode 100644
index 34a8ebc5..00000000
--- a/docs/package.json
+++ /dev/null
@@ -1,24 +0,0 @@
-{
- "name": "docs",
- "version": "1.0.0",
- "main": "index.js",
- "scripts": {
- "build": "webpack --progress",
- "watch": "webpack --progress --watch"
- },
- "private": true,
- "devDependencies": {
- "bootstrap": "^4.1.3",
- "css-loader": "^1.0.0",
- "file-loader": "^1.1.11",
- "node-sass": "^4.9.3",
- "pug": "^2.0.3",
- "pug-cli": "^1.0.0-alpha6",
- "pug-html-loader": "^1.1.5",
- "sass-loader": "^7.1.0",
- "style-loader": "^0.22.1",
- "val-loader": "^1.1.1",
- "webpack": "^4.16.5",
- "webpack-cli": "^3.1.0"
- }
-}
diff --git a/docs/readme.png b/docs/readme.png
index bf283062..a07fa82d 100644
Binary files a/docs/readme.png and b/docs/readme.png differ
diff --git a/docs/styles.scss b/docs/styles.scss
deleted file mode 100644
index dd0549e9..00000000
--- a/docs/styles.scss
+++ /dev/null
@@ -1,141 +0,0 @@
-$font-family-sans-serif: "Source Sans Pro";
-$border-radius-lg: 0;
-$btn-border-width: 3px;
-
-@import "node_modules/bootstrap/scss/bootstrap";
-
-
-h1 {
- font-size: 10vw;
- font-weight: 200;
- margin: 0;
-}
-
-body {
- overflow-x: hidden;
-}
-
-.subtitle {
- font-style: italic;
- color: #999;
- font-size: 5vw;
- font-weight: 300;
-}
-
-.background-stripe {
- width: 100vw;
- background-image: url('./background.jpeg');
- background-size: cover;
- height: 30vw;
- margin: 200px 0 150px;
- min-height: 1000px;
- position: relative;
-
- .overlay {
- position: absolute;
- width: 100vw;
- width: 1px;
- height: 1px;
-
- &.overlay1 {
- top: -1px;
- left: 0;
- border-top: 10vw solid white;
- border-right: 100vw solid transparent;
- }
-
- &.overlay2 {
- bottom: -1px;
- right: 0;
- border-bottom: 10vw solid white;
- border-left: 100vw solid transparent;
- }
- }
-
- .terminal {
- position: absolute;
- left: 50%;
- top: 5vw;
-
- width: 1304px;
- margin-left: -652px;
- height: 972px;
- border-radius: 9px;
-
- box-shadow: 0 0 100px black;
- background: url('./terminal.png');
- background-size: cover;
-
- animation: slideIn ease-out 1s;
- opacity: .95;
- }
-
- @media(max-width: 1500px) {
- min-height: 500px;
- margin: 200px 0 100px;
-
- .terminal {
- width: 652px;
- top: -100px;
- margin-left: -326px;
- height: 486px;
- border-radius: 5px;
- }
- }
-
- @media(max-width: 750px) {
- min-height: 250px;
- margin: 100px 0 50px;
-
- .terminal {
- width: 326px;
- top: -50px;
- margin-left: -163px;
- height: 243px;
- border-radius: 3px;
- }
- }
-
-}
-
-.feature {
- font-size: 45px;
- line-height: 40px;
- opacity: .5;
- font-style: italic;
-}
-
-@keyframes slideIn {
- from {
- opacity: 0;
- margin-top: 200px;
- }
- to {
- opacity: .95;
- margin-top: 0px;
- }
-}
-
-
-.background-stripe2 {
- width: 100vw;
- background-image: url('./background.jpeg');
- background-size: cover;
- height: 30vw;
- margin: 100px 0 0;
- position: relative;
-
- .overlay {
- position: absolute;
- width: 100vw;
- width: 1px;
- height: 1px;
-
- &.overlay1 {
- top: -1px;
- right: 0;
- border-top: 10vw solid white;
- border-left: 100vw solid transparent;
- }
- }
-}
diff --git a/docs/terminal.png b/docs/terminal.png
deleted file mode 100644
index 7a7097c1..00000000
Binary files a/docs/terminal.png and /dev/null differ
diff --git a/docs/webpack.config.js b/docs/webpack.config.js
deleted file mode 100644
index 92de3e9c..00000000
--- a/docs/webpack.config.js
+++ /dev/null
@@ -1,27 +0,0 @@
-const path = require('path')
-
-module.exports = {
- entry: {
- 'index.ignore': 'file-loader?name=../index.html!pug-html-loader!' + path.resolve(__dirname, './index.pug'),
- 'bundle': path.resolve(__dirname, 'index.js'),
- },
- context: __dirname,
- output: {
- path: path.join(__dirname, 'dist'),
- filename: '[name].js'
- },
- module: {
- rules: [
- { test: /\.scss$/, use: ['style-loader', 'css-loader', 'sass-loader'] },
- {
- test: /\.(jpeg|png)?$/,
- use: {
- loader: 'file-loader',
- options: {
- name: 'assets/[name].[ext]'
- }
- }
- }
- ]
- },
-}
diff --git a/extras/UAC.exe b/extras/UAC.exe
new file mode 100644
index 00000000..6be50ba1
Binary files /dev/null and b/extras/UAC.exe differ
diff --git a/package.json b/package.json
index 7f8035fa..c53ff818 100644
--- a/package.json
+++ b/package.json
@@ -1,64 +1,65 @@
{
- "name": "term",
"devDependencies": {
- "@types/electron-config": "^0.2.1",
- "@types/electron-debug": "^1.1.0",
- "@types/fs-promise": "1.0.1",
- "@types/js-yaml": "^3.11.2",
- "@types/node": "^10.11.5",
- "@types/webpack-env": "1.13.0",
- "app-builder-lib": "^20.28.4",
- "apply-loader": "0.1.0",
+ "@fortawesome/fontawesome-free": "^5.9.0",
+ "@types/electron-config": "^3.2.2",
+ "@types/electron-debug": "^2.1.0",
+ "@types/fs-promise": "1.0.3",
+ "@types/js-yaml": "^3.12.1",
+ "@types/node": "^12.0.10",
+ "@types/webpack-env": "1.13.9",
+ "@typescript-eslint/eslint-plugin": "^1.11.0",
+ "@typescript-eslint/parser": "^1.11.0",
+ "app-builder-lib": "^21.0.3",
+ "apply-loader": "2.0.0",
"awesome-typescript-loader": "^5.0.0",
- "core-js": "2.4.1",
- "cross-env": "4.0.0",
- "css-loader": "0.28.0",
- "electron": "4.0.0-beta.8",
- "electron-builder": "^20.38.2",
- "electron-builder-squirrel-windows": "^20.28.3",
- "electron-installer-snap": "^3.0.0",
- "electron-rebuild": "^1.8.2",
- "file-loader": "^1.1.11",
- "font-awesome": "4.7.0",
- "graceful-fs": "^4.1.11",
- "html-loader": "0.4.4",
- "json-loader": "0.5.4",
- "less": "2.7.1",
- "less-loader": "2.2.3",
- "node-abi": "^2.4.4",
- "node-gyp": "^3.6.2",
- "node-sass": "^4.5.3",
- "npmlog": "4.1.0",
+ "core-js": "^3.1.4",
+ "cross-env": "5.2.0",
+ "css-loader": "3.0.0",
+ "electron": "^5.0.5",
+ "electron-builder": "^20.44.4",
+ "electron-installer-snap": "^4.0.0",
+ "electron-notarize": "^0.1.1",
+ "electron-rebuild": "^1.8.5",
+ "eslint": "^5.16.0",
+ "file-loader": "^4.0.0",
+ "graceful-fs": "^4.1.15",
+ "html-loader": "0.5.5",
+ "json-loader": "0.5.7",
+ "node-abi": "^2.9.0",
+ "node-gyp": "^5.0.0",
+ "node-sass": "^4.12.0",
+ "npmlog": "4.1.2",
"npx": "^10.2.0",
- "pug": "^2.0.3",
- "pug-html-loader": "1.0.9",
- "pug-lint": "^2.5.0",
+ "pug": "^2.0.4",
+ "pug-html-loader": "1.1.5",
+ "pug-lint": "^2.6.0",
"pug-loader": "^2.4.0",
- "pug-static-loader": "0.0.1",
- "raven-js": "3.16.0",
- "raw-loader": "0.5.1",
+ "pug-static-loader": "2.0.0",
+ "raven-js": "3.27.2",
+ "raw-loader": "3.0.0",
"sass-loader": "^7.0.1",
- "shelljs": "0.7.7",
+ "shelljs": "0.8.3",
"source-code-pro": "^2.30.1",
- "source-sans-pro": "2.0.10",
- "style-loader": "0.13.1",
+ "source-sans-pro": "2.45.0",
+ "style-loader": "^0.23.1",
"svg-inline-loader": "^0.8.0",
"to-string-loader": "1.1.5",
- "tslint": "5.1.0",
- "tslint-config-standard": "5.0.2",
- "tslint-eslint-rules": "4.0.0",
- "typescript": "^3.1.3",
- "url-loader": "^1.1.1",
- "val-loader": "0.5.0",
- "webpack": "^4.22.0",
- "webpack-cli": "^3.1.2",
- "yaml-loader": "0.4.0",
- "yarn": "^1.10.1"
+ "typedoc": "^0.14.2",
+ "typescript": "^3.5.2",
+ "url-loader": "^2.0.0",
+ "val-loader": "1.1.1",
+ "webpack": "^4.35.0",
+ "webpack-cli": "^3.3.5",
+ "yaml-loader": "0.5.0"
+ },
+ "resolutions": {
+ "*/node-abi": "^2.8.0"
},
"build": {
"appId": "org.terminus",
"productName": "Terminus",
"compression": "normal",
+ "afterSign": "./build/mac/afterSignHook.js",
"files": [
"**/*",
"dist"
@@ -69,24 +70,33 @@
],
"win": {
"icon": "./build/windows/icon.ico",
- "publish": [
- "github"
- ],
- "artifactName": "terminus-${version}-setup.exe"
+ "artifactName": "terminus-${version}-setup.exe",
+ "rfc3161TimeStampServer": "http://sha256timestamp.ws.symantec.com/sha256/timestamp"
},
- "squirrelWindows": {
- "iconUrl": "https://github.com/Eugeny/terminus/raw/master/build/windows/icon.ico",
- "artifactName": "terminus-${version}-setup.exe"
+ "nsis": {
+ "oneClick": false,
+ "artifactName": "terminus-${version}-setup.${ext}",
+ "installerIcon": "./build/windows/icon.ico"
},
+ "publish": [
+ {
+ "provider": "bintray",
+ "token": "d993c4faa708a4cba84fa3a8e822457e7298d75c",
+ "component": "main"
+ },
+ {
+ "provider": "github"
+ }
+ ],
"portable": {
"artifactName": "terminus-${version}-portable.exe"
},
"mac": {
"category": "public.app-category.video",
"icon": "./build/mac/icon.icns",
- "publish": [
- "github"
- ],
+ "artifactName": "terminus-${version}-macos.${ext}",
+ "hardenedRuntime": true,
+ "entitlements": "./build/mac/entitlements.plist",
"extendInfo": {
"NSRequiresAquaSystemAppearance": false
}
@@ -97,21 +107,17 @@
"linux": {
"category": "Utilities",
"icon": "./build/icons",
- "artifactName": "terminus-${version}-linux.${ext}",
- "publish": [
- "github"
- ]
+ "artifactName": "terminus-${version}-linux.${ext}"
},
"deb": {
"depends": [
- "screen",
"gconf2",
"gconf-service",
"libnotify4",
+ "libsecret-1-0",
"libappindicator1",
"libxtst6",
- "libnss3",
- "tmux"
+ "libnss3"
],
"afterInstall": "build/linux/after-install.tpl"
},
@@ -123,12 +129,17 @@
}
},
"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",
- "lint": "tslint -c tslint.json -t stylish terminus-*/src/**/*.ts terminus-*/src/*.ts app/src/*.ts",
- "postinstall": "install-app-deps"
+ "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-plugin-manager/webpack.config.js && webpack --color --config terminus-community-color-schemes/webpack.config.js && webpack --color --config terminus-ssh/webpack.config.js",
+ "build:typings": "tsc --project terminus-core/tsconfig.typings.json && tsc --project terminus-settings/tsconfig.typings.json && tsc --project terminus-terminal/tsconfig.typings.json && tsc --project terminus-plugin-manager/tsconfig.typings.json && tsc --project terminus-ssh/tsconfig.typings.json",
+ "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",
+ "docs": "typedoc --out docs/api terminus-core/src && typedoc --out docs/api/terminal --tsconfig terminus-terminal/tsconfig.typings.json terminus-terminal/src && typedoc --out docs/api/settings --tsconfig terminus-settings/tsconfig.typings.json terminus-settings/src",
+ "lint": "eslint --ext ts */src",
+ "postinstall": "node ./scripts/install-deps.js"
},
- "repository": "eugeny/terminus"
+ "repository": "eugeny/terminus",
+ "dependencies": {
+ "eslint-plugin-import": "^2.18.0"
+ }
}
diff --git a/scripts/build-linux.js b/scripts/build-linux.js
index fd159a1a..4ad7ff20 100755
--- a/scripts/build-linux.js
+++ b/scripts/build-linux.js
@@ -11,4 +11,4 @@ builder({
},
},
publish: 'onTag',
-})
+}).catch(() => process.exit(1))
diff --git a/scripts/build-macos.js b/scripts/build-macos.js
index a116f852..7e3aea09 100755
--- a/scripts/build-macos.js
+++ b/scripts/build-macos.js
@@ -11,4 +11,4 @@ builder({
},
},
publish: 'onTag',
-})
+}).catch(() => process.exit(1))
diff --git a/scripts/build-native.js b/scripts/build-native.js
index 42735e86..025029ae 100755
--- a/scripts/build-native.js
+++ b/scripts/build-native.js
@@ -4,24 +4,20 @@ const path = require('path')
const vars = require('./vars')
lifecycles = []
-lifecycles.push(rebuild({
- buildPath: path.resolve(__dirname, '../app'),
- electronVersion: vars.electronVersion,
- force: true,
-}).lifecycle)
-lifecycles.push(rebuild({
- buildPath: path.resolve(__dirname, '../terminus-ssh'),
- electronVersion: vars.electronVersion,
- force: true,
-}).lifecycle)
-lifecycles.push(rebuild({
- buildPath: path.resolve(__dirname, '../terminus-terminal'),
- electronVersion: vars.electronVersion,
- force: true,
-}).lifecycle)
+for (let dir of ['app', 'terminus-core', 'terminus-ssh', 'terminus-terminal']) {
+ build = rebuild({
+ buildPath: path.resolve(__dirname, '../' + dir),
+ electronVersion: vars.electronVersion,
+ force: true,
+ })
+ build.catch(() => process.exit(1))
+ lifecycles.push([build.lifecycle, dir])
+}
-for (let lc of lifecycles) {
+console.info('Building against Electron', vars.electronVersion)
+
+for (let [lc, dir] of lifecycles) {
lc.on('module-found', name => {
- console.info('Rebuilding', name)
+ console.info('Rebuilding', dir + '/' + name)
})
}
diff --git a/scripts/build-windows.js b/scripts/build-windows.js
index 5e741626..4b0e6bc3 100755
--- a/scripts/build-windows.js
+++ b/scripts/build-windows.js
@@ -4,11 +4,11 @@ const vars = require('./vars')
builder({
dir: true,
- win: ['squirrel', 'portable'],
+ win: ['nsis', 'portable'],
config: {
extraMetadata: {
version: vars.version,
},
},
publish: 'onTag',
-})
+}).catch(() => process.exit(1))
diff --git a/scripts/install-deps.js b/scripts/install-deps.js
index 39b5591a..be7a2795 100755
--- a/scripts/install-deps.js
+++ b/scripts/install-deps.js
@@ -8,7 +8,6 @@ const localBinPath = path.resolve(__dirname, '../node_modules/.bin');
const npx = `${localBinPath}/npx`;
log.info('deps', 'app')
-sh.exec(`${npx} yarn install`)
sh.cd('app')
sh.exec(`${npx} yarn install`)
diff --git a/scripts/vars.js b/scripts/vars.js
index 93cfdca9..d482c199 100755
--- a/scripts/vars.js
+++ b/scripts/vars.js
@@ -1,12 +1,18 @@
const path = require('path')
const fs = require('fs')
+const semver = require('semver')
const childProcess = require('child_process')
const appInfo = JSON.parse(fs.readFileSync(path.resolve(__dirname, '../app/package.json')))
-const pkgInfo = JSON.parse(fs.readFileSync(path.resolve(__dirname, '../package.json')))
+const electronInfo = JSON.parse(fs.readFileSync(path.resolve(__dirname, '../node_modules/electron/package.json')))
exports.version = childProcess.execSync('git describe --tags', {encoding:'utf-8'})
-exports.version = exports.version.substring(1, exports.version.length - 1)
+exports.version = exports.version.substring(1).trim()
+exports.version = exports.version.replace('-', '-c')
+
+if (exports.version.includes('-c')) {
+ exports.version = semver.inc(exports.version, 'prepatch').replace('-0', '-nightly.0')
+}
exports.builtinPlugins = [
'terminus-core',
@@ -20,4 +26,4 @@ exports.bundledModules = [
'@angular',
'@ng-bootstrap',
]
-exports.electronVersion = pkgInfo.devDependencies.electron
+exports.electronVersion = electronInfo.version
diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml
new file mode 100644
index 00000000..98eb91bf
--- /dev/null
+++ b/snap/snapcraft.yaml
@@ -0,0 +1,26 @@
+name: terminus
+version: '1.0.0'
+summary: A terminal for a modern age
+description: |
+ Terminus is a terminal heavily inspired by Hyper. It is, however, designed for people who need to get things done.
+
+grade: devel
+confinement: devmode
+
+apps:
+ terminus:
+ command: opt/terminus/terminus
+
+parts:
+ app:
+ plugin: nodejs
+ source: .
+ build-packages:
+ - libfontconfig-dev
+ override-build: |
+ yarn
+ ./scripts/build-native.js
+ yarn run build
+ ./scripts/build-linux.js
+ mkdir -p $SNAPCRAFT_PART_INSTALL/opt/terminus || true
+ cp -ar dist/linux-unpacked/* $SNAPCRAFT_PART_INSTALL/opt/terminus/
diff --git a/terminus-community-color-schemes/package.json b/terminus-community-color-schemes/package.json
index aa214125..ca31c987 100644
--- a/terminus-community-color-schemes/package.json
+++ b/terminus-community-color-schemes/package.json
@@ -1,12 +1,12 @@
{
"name": "terminus-community-color-schemes",
- "version": "1.0.0-alpha.55",
+ "version": "1.0.73-c4-ga7d62b0",
"description": "Community color schemes for Terminus",
"keywords": [
"terminus-builtin-plugin"
],
"main": "dist/index.js",
- "typings": "dist/index.d.ts",
+ "typings": "typings/index.d.ts",
"scripts": {
"build": "webpack --progress --color",
"watch": "webpack --progress --color --watch"
@@ -22,8 +22,7 @@
"terminus-terminal": "*"
},
"devDependencies": {
- "@types/node": "7.0.12",
+ "@types/node": "12.0.10",
"@types/webpack-env": "^1.13.0"
- },
- "false": {}
+ }
}
diff --git a/terminus-community-color-schemes/schemes/Relaxed b/terminus-community-color-schemes/schemes/Relaxed
new file mode 100644
index 00000000..08496e7f
--- /dev/null
+++ b/terminus-community-color-schemes/schemes/Relaxed
@@ -0,0 +1,36 @@
+! special
+*.foreground: #d8d8d8
+*.background: #343a43
+*.cursorColor: #d8d8d8
+
+! black
+*.color0: #2c3037
+*.color8: #626262
+
+! red
+*.color1: #bb5653
+*.color9: #c35956
+
+! green
+*.color2: #909d62
+*.color10: #9fab76
+
+! yellow
+*.color3: #eac179
+*.color11: #ecc179
+
+! blue
+*.color4: #698698
+*.color12: #7da9c7
+
+! magenta
+*.color5: #b06597
+*.color13: #ba6ca0
+
+! cyan
+*.color6: #c9dfff
+*.color14: #abbacf
+
+! white
+*.color7: #d8d8d8
+*.color15: #f7f7f7
diff --git a/terminus-community-color-schemes/src/colorSchemes.ts b/terminus-community-color-schemes/src/colorSchemes.ts
index 05fd83a3..97452db5 100644
--- a/terminus-community-color-schemes/src/colorSchemes.ts
+++ b/terminus-community-color-schemes/src/colorSchemes.ts
@@ -1,26 +1,26 @@
import { Injectable } from '@angular/core'
-import { TerminalColorSchemeProvider, ITerminalColorScheme } from 'terminus-terminal'
+import { TerminalColorSchemeProvider, TerminalColorScheme } from 'terminus-terminal'
const schemeContents = require.context('../schemes/', true, /.*/)
@Injectable()
export class ColorSchemes extends TerminalColorSchemeProvider {
- async getSchemes (): Promise {
- let schemes: ITerminalColorScheme[] = []
+ async getSchemes (): Promise {
+ const schemes: TerminalColorScheme[] = []
schemeContents.keys().forEach(schemeFile => {
- let lines = (schemeContents(schemeFile) as string).split('\n')
+ const lines = (schemeContents(schemeFile).default as string).split('\n')
// process #define variables
- let variables: any = {}
+ const variables: any = {}
lines
.filter(x => x.startsWith('#define'))
.map(x => x.split(' ').map(v => v.trim()))
- .forEach(([ignore, variableName, variableValue]) => {
+ .forEach(([_, variableName, variableValue]) => {
variables[variableName] = variableValue
})
- let values: any = {}
+ const values: any = {}
lines
.filter(x => x.startsWith('*.'))
.map(x => x.substring(2))
@@ -29,7 +29,7 @@ export class ColorSchemes extends TerminalColorSchemeProvider {
values[key] = variables[value] ? variables[value] : value
})
- let colors: string[] = []
+ const colors: string[] = []
let colorIndex = 0
while (values[`color${colorIndex}`]) {
colors.push(values[`color${colorIndex}`])
diff --git a/terminus-community-color-schemes/src/index.ts b/terminus-community-color-schemes/src/index.ts
index 7c4ddb90..757dc81d 100644
--- a/terminus-community-color-schemes/src/index.ts
+++ b/terminus-community-color-schemes/src/index.ts
@@ -8,4 +8,4 @@ import { ColorSchemes } from './colorSchemes'
{ provide: TerminalColorSchemeProvider, useClass: ColorSchemes, multi: true },
],
})
-export default class PopularThemesModule { }
+export default class PopularThemesModule { } // eslint-disable-line @typescript-eslint/no-extraneous-class
diff --git a/terminus-community-color-schemes/tsconfig.json b/terminus-community-color-schemes/tsconfig.json
index 1d6cfcbf..286cc9cd 100644
--- a/terminus-community-color-schemes/tsconfig.json
+++ b/terminus-community-color-schemes/tsconfig.json
@@ -2,7 +2,6 @@
"extends": "../tsconfig.json",
"exclude": ["node_modules", "dist"],
"compilerOptions": {
- "baseUrl": "src",
- "declarationDir": "dist"
+ "baseUrl": "src"
}
}
diff --git a/terminus-community-color-schemes/webpack.config.js b/terminus-community-color-schemes/webpack.config.js
index bbecf921..b407a9fb 100644
--- a/terminus-community-color-schemes/webpack.config.js
+++ b/terminus-community-color-schemes/webpack.config.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,
},
diff --git a/terminus-community-color-schemes/yarn.lock b/terminus-community-color-schemes/yarn.lock
index 68fb398f..e3c01f71 100644
--- a/terminus-community-color-schemes/yarn.lock
+++ b/terminus-community-color-schemes/yarn.lock
@@ -2,12 +2,12 @@
# yarn lockfile v1
-"@types/node@7.0.12":
- version "7.0.12"
- resolved "https://registry.yarnpkg.com/@types/node/-/node-7.0.12.tgz#ae5f67a19c15f752148004db07cbbb372e69efc9"
- integrity sha1-rl9noZwV91IUgATbB8u7Ny5p78k=
+"@types/node@12.0.10":
+ version "12.0.10"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-12.0.10.tgz#51babf9c7deadd5343620055fc8aff7995c8b031"
+ integrity sha512-LcsGbPomWsad6wmMNv7nBLw7YYYyfdYcz6xryKYQhx89c3XXan+8Q6AJ43G5XDIaklaVkK3mE4fCb0SBvMiPSQ==
"@types/webpack-env@^1.13.0":
- version "1.13.1"
- resolved "https://registry.yarnpkg.com/@types/webpack-env/-/webpack-env-1.13.1.tgz#b45c222e24301bd006e3edfc762cc6b51bda236a"
- integrity sha512-oHyg0NssP2RCpCvE35hhbSqMJRsc5lSW+GFe+Vc65JL+kHII1VMYM+0KeV/z4utFuUqPoQRmq8KMMp7ba0dj6Q==
+ version "1.13.9"
+ resolved "https://registry.yarnpkg.com/@types/webpack-env/-/webpack-env-1.13.9.tgz#a67287861c928ebf4159a908d1fb1a2a34d4097a"
+ integrity sha512-p8zp5xqkly3g4cCmo2mKOHI9+Z/kObmDj0BmjbDDJQlgDTiEGTbm17MEwTAusV6XceCy+bNw9q/ZHXHyKo3zkg==
diff --git a/terminus-core/README.md b/terminus-core/README.md
new file mode 100644
index 00000000..0bf5ef39
--- /dev/null
+++ b/terminus-core/README.md
@@ -0,0 +1,31 @@
+Terminus Core Plugin
+--------------------
+
+See also: [Settings plugin API](./settings/), [Terminal plugin API](./settings/)
+
+* tabbed interface services
+* toolbar UI
+* config file management
+* hotkeys
+* tab recovery
+* logging
+* theming
+
+Using the API:
+
+```ts
+import { AppService, TabContextMenuItemProvider } from 'terminus-core'
+```
+
+Exporting your subclasses:
+
+```ts
+@NgModule({
+ ...
+ providers: [
+ ...
+ { provide: TabContextMenuItemProvider, useClass: MyContextMenu, multi: true },
+ ...
+ ]
+})
+```
diff --git a/terminus-core/package.json b/terminus-core/package.json
index af89fe1a..47aa624a 100644
--- a/terminus-core/package.json
+++ b/terminus-core/package.json
@@ -1,12 +1,12 @@
{
"name": "terminus-core",
- "version": "1.0.0-alpha.55",
+ "version": "1.0.73-c4-ga7d62b0",
"description": "Terminus core",
"keywords": [
"terminus-builtin-plugin"
],
"main": "dist/index.js",
- "typings": "dist/index.d.ts",
+ "typings": "typings/index.d.ts",
"scripts": {
"build": "webpack --progress --color --display-modules",
"watch": "webpack --progress --color --watch"
@@ -18,18 +18,25 @@
"license": "MIT",
"devDependencies": {
"@types/js-yaml": "^3.9.0",
- "@types/node": "^7.0.37",
+ "@types/node": "^12.0.2",
+ "@types/shell-escape": "^0.2.0",
"@types/webpack-env": "^1.13.0",
"@types/winston": "^2.3.6",
- "axios": "^0.18.0",
+ "axios": "^0.19.0",
"bootstrap": "^4.1.3",
- "core-js": "^2.4.1",
- "electron-updater": "^2.8.9",
+ "core-js": "^3.1.2",
+ "deepmerge": "^3.2.0",
+ "electron-updater": "^4.0.6",
+ "js-yaml": "^3.9.0",
+ "mixpanel": "^0.10.2",
"ng2-dnd": "^5.0.2",
"ngx-perfect-scrollbar": "^6.0.0",
- "rage-edit-tmp": "^1.1.0",
"shell-escape": "^0.2.0",
- "universal-analytics": "^0.4.17"
+ "uuid": "^3.3.2",
+ "winston": "^3.2.1"
+ },
+ "optionalDependencies": {
+ "windows-native-registry": "^1.0.14"
},
"peerDependencies": {
"@angular/animations": "4.0.1",
@@ -40,10 +47,5 @@
"@angular/platform-browser-dynamic": "4.0.1",
"rxjs": "5.3.0",
"zone.js": "0.8.4"
- },
- "dependencies": {
- "deepmerge": "^1.5.0",
- "js-yaml": "^3.9.0",
- "winston": "^2.4.0"
}
}
diff --git a/terminus-core/src/api/configProvider.ts b/terminus-core/src/api/configProvider.ts
index 9bafc874..7ed3b868 100644
--- a/terminus-core/src/api/configProvider.ts
+++ b/terminus-core/src/api/configProvider.ts
@@ -1,4 +1,37 @@
+/**
+ * Extend to add your own config options
+ */
export abstract class ConfigProvider {
+ /**
+ * Default values, e.g.
+ *
+ * ```ts
+ * defaults = {
+ * myPlugin: {
+ * foo: 1
+ * }
+ * }
+ * ```
+ */
defaults: any = {}
- platformDefaults: any = {}
+
+ /**
+ * [[Platform]] specific defaults, e.g.
+ *
+ * ```ts
+ * platformDefaults = {
+ * [Platform.Windows]: {
+ * myPlugin: {
+ * bar: true
+ * }
+ * },
+ * [Platform.macOS]: {
+ * myPlugin: {
+ * bar: false
+ * }
+ * },
+ * }
+ * ```
+ */
+ platformDefaults: {[platform: string]: any} = {}
}
diff --git a/terminus-core/src/api/hotkeyProvider.ts b/terminus-core/src/api/hotkeyProvider.ts
index d1bb95b0..8e153a73 100644
--- a/terminus-core/src/api/hotkeyProvider.ts
+++ b/terminus-core/src/api/hotkeyProvider.ts
@@ -1,10 +1,14 @@
-export interface IHotkeyDescription {
- id: string,
- name: string,
+export interface HotkeyDescription {
+ id: string
+ name: string
}
+/**
+ * Extend to provide your own hotkeys. A corresponding [[ConfigProvider]]
+ * must also provide the `hotkeys.foo` config options with the default values
+ */
export abstract class HotkeyProvider {
- hotkeys: IHotkeyDescription[] = []
+ hotkeys: HotkeyDescription[] = []
- abstract provide (): Promise
+ abstract provide (): Promise
}
diff --git a/terminus-core/src/api/index.ts b/terminus-core/src/api/index.ts
index 8c533ba8..7112d09e 100644
--- a/terminus-core/src/api/index.ts
+++ b/terminus-core/src/api/index.ts
@@ -1,9 +1,11 @@
export { BaseTabComponent, BaseTabProcess } from '../components/baseTab.component'
+export { SplitTabComponent, SplitContainer } from '../components/splitTab.component'
export { TabRecoveryProvider, RecoveredTab } from './tabRecovery'
-export { ToolbarButtonProvider, IToolbarButton } from './toolbarButtonProvider'
+export { ToolbarButtonProvider, ToolbarButton } from './toolbarButtonProvider'
export { ConfigProvider } from './configProvider'
-export { HotkeyProvider, IHotkeyDescription } from './hotkeyProvider'
+export { HotkeyProvider, HotkeyDescription } from './hotkeyProvider'
export { Theme } from './theme'
+export { TabContextMenuItemProvider } from './tabContextMenuProvider'
export { AppService } from '../services/app.service'
export { ConfigService } from '../services/config.service'
@@ -15,3 +17,4 @@ export { HotkeysService } from '../services/hotkeys.service'
export { HostAppService, Platform } from '../services/hostApp.service'
export { ShellIntegrationService } from '../services/shellIntegration.service'
export { ThemesService } from '../services/themes.service'
+export { TabsService } from '../services/tabs.service'
diff --git a/terminus-core/src/api/tabContextMenuProvider.ts b/terminus-core/src/api/tabContextMenuProvider.ts
new file mode 100644
index 00000000..e3581abf
--- /dev/null
+++ b/terminus-core/src/api/tabContextMenuProvider.ts
@@ -0,0 +1,11 @@
+import { BaseTabComponent } from '../components/baseTab.component'
+import { TabHeaderComponent } from '../components/tabHeader.component'
+
+/**
+ * Extend to add items to the tab header's context menu
+ */
+export abstract class TabContextMenuItemProvider {
+ weight = 0
+
+ abstract async getItems (tab: BaseTabComponent, tabHeader?: TabHeaderComponent): Promise
+}
diff --git a/terminus-core/src/api/tabRecovery.ts b/terminus-core/src/api/tabRecovery.ts
index f3473e77..63e7ec82 100644
--- a/terminus-core/src/api/tabRecovery.ts
+++ b/terminus-core/src/api/tabRecovery.ts
@@ -1,10 +1,38 @@
-import { TabComponentType } from '../services/app.service'
+import { TabComponentType } from '../services/tabs.service'
export interface RecoveredTab {
- type: TabComponentType,
- options?: any,
+ /**
+ * Component type to be instantiated
+ */
+ type: TabComponentType
+
+ /**
+ * Component instance inputs
+ */
+ options?: any
}
+/**
+ * Extend to enable recovery for your custom tab.
+ * This works in conjunction with [[getRecoveryToken()]]
+ *
+ * Terminus will try to find any [[TabRecoveryProvider]] that is able to process
+ * the recovery token previously returned by [[getRecoveryToken]].
+ *
+ * Recommended token format:
+ *
+ * ```json
+ * {
+ * type: 'my-tab-type',
+ * foo: 'bar',
+ * }
+ * ```
+ */
export abstract class TabRecoveryProvider {
- abstract async recover (recoveryToken: any): Promise
+ /**
+ * @param recoveryToken a recovery token found in the saved tabs list
+ * @returns [[RecoveredTab]] descriptor containing tab type and component inputs
+ * or `null` if this token is from a different tab type or is not supported
+ */
+ abstract async recover (recoveryToken: any): Promise
}
diff --git a/terminus-core/src/api/theme.ts b/terminus-core/src/api/theme.ts
index 9f9792ed..d86577be 100644
--- a/terminus-core/src/api/theme.ts
+++ b/terminus-core/src/api/theme.ts
@@ -1,5 +1,13 @@
+/**
+ * Extend to add a custom CSS theme
+ */
export abstract class Theme {
name: string
+
+ /**
+ * Complete CSS stylesheet
+ */
css: string
+
terminalBackground: string
}
diff --git a/terminus-core/src/api/toolbarButtonProvider.ts b/terminus-core/src/api/toolbarButtonProvider.ts
index 16189c90..c801ec1f 100644
--- a/terminus-core/src/api/toolbarButtonProvider.ts
+++ b/terminus-core/src/api/toolbarButtonProvider.ts
@@ -1,14 +1,39 @@
import { SafeHtml } from '@angular/platform-browser'
-export interface IToolbarButton {
+/**
+ * See [[ToolbarButtonProvider]]
+ */
+export interface ToolbarButton {
+ /**
+ * Raw SVG icon code
+ */
icon: SafeHtml
- touchBarNSImage?: string
+
title: string
+
+ /**
+ * Optional Touch Bar icon ID
+ */
+ touchBarNSImage?: string
+
+ /**
+ * Optional Touch Bar button label
+ */
touchBarTitle?: string
+
weight?: number
- click: () => void
+
+ click?: () => void
+
+ submenu?: () => Promise
+
+ /** @hidden */
+ submenuItems?: ToolbarButton[]
}
+/**
+ * Extend to add buttons to the toolbar
+ */
export abstract class ToolbarButtonProvider {
- abstract provide (): IToolbarButton[]
+ abstract provide (): ToolbarButton[]
}
diff --git a/terminus-core/src/components/appRoot.component.pug b/terminus-core/src/components/appRoot.component.pug
index 474e01bb..e9ac6404 100644
--- a/terminus-core/src/components/appRoot.component.pug
+++ b/terminus-core/src/components/appRoot.component.pug
@@ -32,22 +32,48 @@ title-bar(
)
.btn-group.background
- button.btn.btn-secondary.btn-tab-bar(
- *ngFor='let button of leftToolbarButtons',
- [title]='button.title',
- (click)='button.click()',
- [innerHTML]='button.icon',
+ .d-flex(
+ *ngFor='let button of leftToolbarButtons',
+ ngbDropdown,
+ (openChange)='generateButtonSubmenu(button)',
)
+ button.btn.btn-secondary.btn-tab-bar(
+ [title]='button.title',
+ (click)='button.click && button.click()',
+ [innerHTML]='button.icon',
+ ngbDropdownToggle,
+ )
+ div(*ngIf='button.submenu', ngbDropdownMenu)
+ button.dropdown-item.d-flex.align-items-center(
+ *ngFor='let item of button.submenuItems',
+ (click)='item.click()',
+ ngbDropdownItem,
+ )
+ .icon-wrapper([innerHTML]='item.icon')
+ .ml-3 {{item.title}}
.drag-space.background([class.persistent]='config.store.appearance.frame == "thin" && hostApp.platform != Platform.macOS')
.btn-group.background
- button.btn.btn-secondary.btn-tab-bar(
- *ngFor='let button of rightToolbarButtons',
- [title]='button.title',
- (click)='button.click()',
- [innerHTML]='button.icon',
+ .d-flex(
+ *ngFor='let button of rightToolbarButtons',
+ ngbDropdown,
+ (openChange)='generateButtonSubmenu(button)',
)
+ button.btn.btn-secondary.btn-tab-bar(
+ [title]='button.title',
+ (click)='button.click && button.click()',
+ [innerHTML]='button.icon',
+ ngbDropdownToggle,
+ )
+ div(*ngIf='button.submenu', ngbDropdownMenu)
+ button.dropdown-item.d-flex.align-items-center(
+ *ngFor='let item of button.submenuItems',
+ (click)='item.click()',
+ ngbDropdownItem,
+ )
+ .icon-wrapper([innerHTML]='item.icon')
+ .ml-3 {{item.title}}
button.btn.btn-secondary.btn-tab-bar.btn-update(
*ngIf='updatesAvailable',
diff --git a/terminus-core/src/components/appRoot.component.scss b/terminus-core/src/components/appRoot.component.scss
index fa10e61a..7b2f42d7 100644
--- a/terminus-core/src/components/appRoot.component.scss
+++ b/terminus-core/src/components/appRoot.component.scss
@@ -48,6 +48,10 @@ $tab-border-radius: 4px;
color: #aaa;
border: none;
border-radius: 0;
+
+ &.dropdown-toggle::after {
+ display: none;
+ }
}
&>.tabs {
@@ -88,12 +92,20 @@ hotkey-hint {
max-width: 300px;
}
-::ng-deep .btn-tab-bar svg {
+::ng-deep .btn-tab-bar svg,
+::ng-deep .btn-tab-bar + .dropdown-menu svg {
+ width: 16px;
height: 16px;
fill: white;
fill-opacity: 0.75;
}
+.icon-wrapper {
+ display: flex;
+ width: 16px;
+ height: 17px;
+}
+
::ng-deep .btn-update svg {
fill: cyan;
}
diff --git a/terminus-core/src/components/appRoot.component.ts b/terminus-core/src/components/appRoot.component.ts
index 505b0cc5..47601368 100644
--- a/terminus-core/src/components/appRoot.component.ts
+++ b/terminus-core/src/components/appRoot.component.ts
@@ -9,15 +9,15 @@ 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'
import { BaseTabComponent } from './baseTab.component'
import { SafeModeModalComponent } from './safeModeModal.component'
-import { AppService, IToolbarButton, ToolbarButtonProvider } from '../api'
+import { AppService, ToolbarButton, ToolbarButtonProvider } from '../api'
+/** @hidden */
@Component({
selector: 'app-root',
template: require('./appRoot.component.pug'),
@@ -26,36 +26,36 @@ import { AppService, IToolbarButton, ToolbarButtonProvider } from '../api'
trigger('animateTab', [
state('in', style({
'flex-basis': '200px',
- 'width': '200px',
+ width: '200px',
})),
transition(':enter', [
style({
'flex-basis': '1px',
- 'width': '1px',
+ width: '1px',
}),
animate('250ms ease-in-out', style({
'flex-basis': '200px',
- 'width': '200px',
- }))
+ width: '200px',
+ })),
]),
transition(':leave', [
style({
'flex-basis': '200px',
- 'width': '200px',
+ width: '200px',
}),
animate('250ms ease-in-out', style({
'flex-basis': '1px',
- 'width': '1px',
- }))
- ])
- ])
- ]
+ width: '1px',
+ })),
+ ]),
+ ]),
+ ],
})
export class AppRootComponent {
Platform = Platform
@Input() ready = false
- @Input() leftToolbarButtons: IToolbarButton[]
- @Input() rightToolbarButtons: IToolbarButton[]
+ @Input() leftToolbarButtons: ToolbarButton[]
+ @Input() rightToolbarButtons: ToolbarButton[]
@HostBinding('class.platform-win32') platformClassWindows = process.platform === 'win32'
@HostBinding('class.platform-darwin') platformClassMacOS = process.platform === 'darwin'
@HostBinding('class.platform-linux') platformClassLinux = process.platform === 'linux'
@@ -69,7 +69,6 @@ export class AppRootComponent {
constructor (
private docking: DockingService,
private electron: ElectronService,
- private tabRecovery: TabRecoveryService,
private hotkeys: HotkeysService,
private updater: UpdaterService,
private touchbar: TouchbarService,
@@ -90,9 +89,9 @@ export class AppRootComponent {
this.updateIcon = domSanitizer.bypassSecurityTrustHtml(require('../icons/gift.svg')),
- this.hotkeys.matchedHotkey.subscribe((hotkey) => {
+ this.hotkeys.matchedHotkey.subscribe((hotkey: string) => {
if (hotkey.startsWith('tab-')) {
- let index = parseInt(hotkey.split('-')[1])
+ const index = parseInt(hotkey.split('-')[1])
if (index <= this.app.tabs.length) {
this.app.selectTab(this.app.tabs[index - 1])
}
@@ -128,6 +127,11 @@ export class AppRootComponent {
this.onGlobalHotkey()
})
+ this.hostApp.windowCloseRequest$.subscribe(async () => {
+ await this.app.closeAllTabs()
+ this.hostApp.closeWindow()
+ })
+
if (window['safeModeReason']) {
ngbModal.open(SafeModeModalComponent)
}
@@ -199,9 +203,7 @@ export class AppRootComponent {
}
async ngOnInit () {
- await this.tabRecovery.recoverTabs()
this.ready = true
- this.tabRecovery.saveTabs(this.app.tabs)
this.app.emitReady()
}
@@ -231,14 +233,20 @@ export class AppRootComponent {
})
}
- private getToolbarButtons (aboveZero: boolean): IToolbarButton[] {
- let buttons: IToolbarButton[] = []
+ async generateButtonSubmenu (button: ToolbarButton) {
+ if (button.submenu) {
+ button.submenuItems = await button.submenu()
+ }
+ }
+
+ private getToolbarButtons (aboveZero: boolean): ToolbarButton[] {
+ let buttons: ToolbarButton[] = []
this.config.enabledServices(this.toolbarButtonProviders).forEach(provider => {
buttons = buttons.concat(provider.provide())
})
return buttons
- .filter((button) => (button.weight > 0) === aboveZero)
- .sort((a: IToolbarButton, b: IToolbarButton) => (a.weight || 0) - (b.weight || 0))
+ .filter(button => button.weight > 0 === aboveZero)
+ .sort((a: ToolbarButton, b: ToolbarButton) => (a.weight || 0) - (b.weight || 0))
}
private updateVibrancy () {
diff --git a/terminus-core/src/components/baseTab.component.ts b/terminus-core/src/components/baseTab.component.ts
index 9cc8aec2..982e88a1 100644
--- a/terminus-core/src/components/baseTab.component.ts
+++ b/terminus-core/src/components/baseTab.component.ts
@@ -1,27 +1,58 @@
import { Observable, Subject } from 'rxjs'
import { ViewRef } from '@angular/core'
+/**
+ * Represents an active "process" inside a tab,
+ * for example, a user process running inside a terminal tab
+ */
export interface BaseTabProcess {
name: string
}
+/**
+ * Abstract base class for custom tab components
+ */
export abstract class BaseTabComponent {
- private static lastTabID = 0
- id: number
+ /**
+ * Current tab title
+ */
title: string
+
+ /**
+ * User-defined title override
+ */
customTitle: string
- hasFocus = false
+
+ /**
+ * Last tab activity state
+ */
hasActivity = false
+
+ /**
+ * ViewRef to the tab DOM element
+ */
hostView: ViewRef
+
+ /**
+ * CSS color override for the tab's header
+ */
color: string = null
- protected titleChange = new Subject()
- protected focused = new Subject()
- protected blurred = new Subject()
- protected progress = new Subject()
- protected activity = new Subject()
- protected destroyed = new Subject()
+
+ protected hasFocus = false
+
+ /**
+ * Ping this if your recovery state has been changed and you want
+ * your tab state to be saved sooner
+ */
+ protected recoveryStateChangedHint = new Subject()
private progressClearTimeout: number
+ private titleChange = new Subject()
+ private focused = new Subject()
+ private blurred = new Subject()
+ private progress = new Subject()
+ private activity = new Subject()
+ private destroyed = new Subject()
get focused$ (): Observable { return this.focused }
get blurred$ (): Observable { return this.blurred }
@@ -29,9 +60,9 @@ export abstract class BaseTabComponent {
get progress$ (): Observable { return this.progress }
get activity$ (): Observable { return this.activity }
get destroyed$ (): Observable { return this.destroyed }
+ get recoveryStateChangedHint$ (): Observable { return this.recoveryStateChangedHint }
constructor () {
- this.id = BaseTabComponent.lastTabID++
this.focused$.subscribe(() => {
this.hasFocus = true
})
@@ -47,6 +78,11 @@ export abstract class BaseTabComponent {
}
}
+ /**
+ * Sets visual progressbar on the tab
+ *
+ * @param {type} progress: value between 0 and 1, or `null` to remove
+ */
setProgress (progress: number) {
this.progress.next(progress)
if (progress) {
@@ -55,28 +91,47 @@ export abstract class BaseTabComponent {
}
this.progressClearTimeout = setTimeout(() => {
this.setProgress(null)
- }, 5000)
+ }, 5000) as any
}
}
+ /**
+ * Shows the acticity marker on the tab header
+ */
displayActivity (): void {
this.hasActivity = true
this.activity.next(true)
}
+ /**
+ * Removes the acticity marker from the tab header
+ */
clearActivity (): void {
this.hasActivity = false
this.activity.next(false)
}
- getRecoveryToken (): any {
+ /**
+ * Override this and implement a [[TabRecoveryProvider]] to enable recovery
+ * for your custom tab
+ *
+ * @return JSON serializable tab state representation
+ * for your [[TabRecoveryProvider]] to parse
+ */
+ async getRecoveryToken (): Promise {
return null
}
+ /**
+ * Override this to enable task completion notifications for the tab
+ */
async getCurrentProcess (): Promise {
return null
}
+ /**
+ * Return false to prevent the tab from being closed
+ */
async canClose (): Promise {
return true
}
@@ -89,11 +144,15 @@ export abstract class BaseTabComponent {
this.blurred.next()
}
+ /**
+ * Called before the tab is closed
+ */
destroy (): void {
this.focused.complete()
this.blurred.complete()
this.titleChange.complete()
this.progress.complete()
+ this.recoveryStateChangedHint.complete()
this.destroyed.next()
this.destroyed.complete()
}
diff --git a/terminus-core/src/components/checkbox.component.pug b/terminus-core/src/components/checkbox.component.pug
index 2a5115a6..fc25f2ae 100644
--- a/terminus-core/src/components/checkbox.component.pug
+++ b/terminus-core/src/components/checkbox.component.pug
@@ -1,4 +1,4 @@
.icon(tabindex='0', [class.active]='model', (keyup.space)='click()')
- i.fa.fa-square-o.off
- i.fa.fa-check-square.on
+ i.fas.fa-square.off
+ i.fas.fa-check-square.on
.text {{text}}
diff --git a/terminus-core/src/components/checkbox.component.scss b/terminus-core/src/components/checkbox.component.scss
index a1a10352..647912f6 100644
--- a/terminus-core/src/components/checkbox.component.scss
+++ b/terminus-core/src/components/checkbox.component.scss
@@ -20,6 +20,10 @@
flex-direction: row;
align-items: center;
+ .off {
+ color: rgba(0, 0, 0, .5);
+ }
+
.icon {
position: relative;
flex: none;
diff --git a/terminus-core/src/components/checkbox.component.ts b/terminus-core/src/components/checkbox.component.ts
index 060f0e95..5cb5ebd5 100644
--- a/terminus-core/src/components/checkbox.component.ts
+++ b/terminus-core/src/components/checkbox.component.ts
@@ -1,13 +1,14 @@
import { NgZone, Component, Input, HostBinding, HostListener } from '@angular/core'
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'
+/** @hidden */
@Component({
selector: 'checkbox',
template: require('./checkbox.component.pug'),
styles: [require('./checkbox.component.scss')],
providers: [
{ provide: NG_VALUE_ACCESSOR, useExisting: CheckboxComponent, multi: true },
- ]
+ ],
})
export class CheckboxComponent implements ControlValueAccessor {
@HostBinding('class.active') @Input() model: boolean
@@ -22,7 +23,7 @@ export class CheckboxComponent implements ControlValueAccessor {
}
this.model = !this.model
- for (let fx of this.changed) {
+ for (const fx of this.changed) {
fx(this.model)
}
}
diff --git a/terminus-core/src/components/renameTabModal.component.ts b/terminus-core/src/components/renameTabModal.component.ts
index 1410568f..e8e105b3 100644
--- a/terminus-core/src/components/renameTabModal.component.ts
+++ b/terminus-core/src/components/renameTabModal.component.ts
@@ -1,6 +1,7 @@
import { Component, Input, ElementRef, ViewChild } from '@angular/core'
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
+/** @hidden */
@Component({
selector: 'rename-tab-modal',
template: require('./renameTabModal.component.pug'),
@@ -16,6 +17,7 @@ export class RenameTabModalComponent {
ngOnInit () {
setTimeout(() => {
this.input.nativeElement.focus()
+ this.input.nativeElement.select()
}, 250)
}
diff --git a/terminus-core/src/components/safeModeModal.component.ts b/terminus-core/src/components/safeModeModal.component.ts
index 33a5b605..a2dd39c0 100644
--- a/terminus-core/src/components/safeModeModal.component.ts
+++ b/terminus-core/src/components/safeModeModal.component.ts
@@ -1,6 +1,7 @@
import { Component, Input } from '@angular/core'
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
+/** @hidden */
@Component({
template: require('./safeModeModal.component.pug'),
})
diff --git a/terminus-core/src/components/splitTab.component.scss b/terminus-core/src/components/splitTab.component.scss
new file mode 100644
index 00000000..15c6d27e
--- /dev/null
+++ b/terminus-core/src/components/splitTab.component.scss
@@ -0,0 +1,5 @@
+:host {
+ display: block;
+ position: relative;
+ flex: auto;
+}
diff --git a/terminus-core/src/components/splitTab.component.ts b/terminus-core/src/components/splitTab.component.ts
new file mode 100644
index 00000000..a13aaa3b
--- /dev/null
+++ b/terminus-core/src/components/splitTab.component.ts
@@ -0,0 +1,524 @@
+import { Observable, Subject, Subscription } from 'rxjs'
+import { Component, Injectable, ViewChild, ViewContainerRef, EmbeddedViewRef, OnInit, OnDestroy } from '@angular/core'
+import { BaseTabComponent, BaseTabProcess } from './baseTab.component'
+import { TabRecoveryProvider, RecoveredTab } from '../api/tabRecovery'
+import { TabsService } from '../services/tabs.service'
+import { HotkeysService } from '../services/hotkeys.service'
+import { TabRecoveryService } from '../services/tabRecovery.service'
+
+export type SplitOrientation = 'v' | 'h' // eslint-disable-line @typescript-eslint/no-type-alias
+export type SplitDirection = 'r' | 't' | 'b' | 'l' // eslint-disable-line @typescript-eslint/no-type-alias
+
+/**
+ * Describes a horizontal or vertical split row or column
+ */
+export class SplitContainer {
+ orientation: SplitOrientation = 'h'
+
+ /**
+ * Children could be tabs or other containers
+ */
+ children: (BaseTabComponent | SplitContainer)[] = []
+
+ /**
+ * Relative sizes of children, between 0 and 1. Total sum is 1
+ */
+ ratios: number[] = []
+
+ x: number
+ y: number
+ w: number
+ h: number
+
+ /**
+ * @return Flat list of all tabs inside this container
+ */
+ getAllTabs () {
+ let r = []
+ for (const child of this.children) {
+ if (child instanceof SplitContainer) {
+ r = r.concat(child.getAllTabs())
+ } else {
+ r.push(child)
+ }
+ }
+ return r
+ }
+
+ /**
+ * Remove unnecessarily nested child containers and renormalizes [[ratios]]
+ */
+ normalize () {
+ for (let i = 0; i < this.children.length; i++) {
+ const child = this.children[i]
+
+ if (child instanceof SplitContainer) {
+ child.normalize()
+
+ if (child.children.length === 0) {
+ this.children.splice(i, 1)
+ this.ratios.splice(i, 1)
+ i--
+ continue
+ } else if (child.children.length === 1) {
+ this.children[i] = child.children[0]
+ } else if (child.orientation === this.orientation) {
+ const ratio = this.ratios[i]
+ this.children.splice(i, 1)
+ this.ratios.splice(i, 1)
+ for (let j = 0; j < child.children.length; j++) {
+ this.children.splice(i, 0, child.children[j])
+ this.ratios.splice(i, 0, child.ratios[j] * ratio)
+ i++
+ }
+ }
+ }
+ }
+
+ let s = 0
+ for (const x of this.ratios) {
+ s += x
+ }
+ this.ratios = this.ratios.map(x => x / s)
+ }
+
+ /**
+ * Gets the left/top side offset for the given element index (between 0 and 1)
+ */
+ getOffsetRatio (index: number): number {
+ let s = 0
+ for (let i = 0; i < index; i++) {
+ s += this.ratios[i]
+ }
+ return s
+ }
+
+ async serialize () {
+ const children = []
+ for (const child of this.children) {
+ if (child instanceof SplitContainer) {
+ children.push(await child.serialize())
+ } else {
+ children.push(await child.getRecoveryToken())
+ }
+ }
+ return {
+ type: 'app:split-tab',
+ ratios: this.ratios,
+ orientation: this.orientation,
+ children,
+ }
+ }
+}
+
+/**
+ * Represents a spanner (draggable border between two split areas)
+ */
+export interface SplitSpannerInfo {
+ container: SplitContainer
+
+ /**
+ * Number of the right/bottom split in the container
+ */
+ index: number
+}
+
+/**
+ * Split tab is a tab that contains other tabs and allows further splitting them
+ * You'll mainly encounter it inside [[AppService]].tabs
+ */
+@Component({
+ selector: 'split-tab',
+ template: `
+
+
+ `,
+ styles: [require('./splitTab.component.scss')],
+})
+export class SplitTabComponent extends BaseTabComponent implements OnInit, OnDestroy {
+ /** @hidden */
+ @ViewChild('vc', { read: ViewContainerRef }) viewContainer: ViewContainerRef
+
+ /**
+ * Top-level split container
+ */
+ root: SplitContainer
+
+ /** @hidden */
+ _recoveredState: any
+
+ /** @hidden */
+ _spanners: SplitSpannerInfo[] = []
+
+ private focusedTab: BaseTabComponent
+ private hotkeysSubscription: Subscription
+ private viewRefs: Map> = new Map()
+
+ private tabAdded = new Subject()
+ private tabRemoved = new Subject()
+ private splitAdjusted = new Subject()
+ private focusChanged = new Subject()
+
+ get tabAdded$ (): Observable { return this.tabAdded }
+ get tabRemoved$ (): Observable { return this.tabRemoved }
+
+ /**
+ * Fired when split ratio is changed for a given spanner
+ */
+ get splitAdjusted$ (): Observable { return this.splitAdjusted }
+
+ /**
+ * Fired when a different sub-tab gains focus
+ */
+ get focusChanged$ (): Observable { return this.focusChanged }
+
+ /** @hidden */
+ constructor (
+ private hotkeys: HotkeysService,
+ private tabsService: TabsService,
+ private tabRecovery: TabRecoveryService,
+ ) {
+ super()
+ this.root = new SplitContainer()
+ this.setTitle('')
+
+ this.focused$.subscribe(() => {
+ this.getAllTabs().forEach(x => x.emitFocused())
+ this.focus(this.focusedTab)
+ })
+ this.blurred$.subscribe(() => this.getAllTabs().forEach(x => x.emitBlurred()))
+
+ this.hotkeysSubscription = this.hotkeys.matchedHotkey.subscribe(hotkey => {
+ if (!this.hasFocus) {
+ return
+ }
+ switch (hotkey) {
+ case 'split-right':
+ this.splitTab(this.focusedTab, 'r')
+ break
+ case 'split-bottom':
+ this.splitTab(this.focusedTab, 'b')
+ break
+ case 'split-top':
+ this.splitTab(this.focusedTab, 't')
+ break
+ case 'split-left':
+ this.splitTab(this.focusedTab, 'l')
+ break
+ case 'pane-nav-left':
+ this.navigate('l')
+ break
+ case 'pane-nav-right':
+ this.navigate('r')
+ break
+ case 'pane-nav-up':
+ this.navigate('t')
+ break
+ case 'pane-nav-down':
+ this.navigate('b')
+ break
+ case 'close-pane':
+ this.removeTab(this.focusedTab)
+ break
+ }
+ })
+ }
+
+ /** @hidden */
+ async ngOnInit () {
+ if (this._recoveredState) {
+ await this.recoverContainer(this.root, this._recoveredState)
+ this.layout()
+ setImmediate(() => {
+ this.getAllTabs().forEach(x => x.emitFocused())
+ this.focusAnyIn(this.root)
+ })
+ }
+ }
+
+ /** @hidden */
+ ngOnDestroy () {
+ this.hotkeysSubscription.unsubscribe()
+ }
+
+ /** @returns Flat list of all sub-tabs */
+ getAllTabs () {
+ return this.root.getAllTabs()
+ }
+
+ getFocusedTab (): BaseTabComponent {
+ return this.focusedTab
+ }
+
+ focus (tab: BaseTabComponent) {
+ this.focusedTab = tab
+ for (const x of this.getAllTabs()) {
+ if (x !== tab) {
+ x.emitBlurred()
+ }
+ }
+ if (tab) {
+ tab.emitFocused()
+ this.focusChanged.next(tab)
+ }
+ this.layout()
+ }
+
+ /**
+ * Focuses the first available tab inside the given [[SplitContainer]]
+ */
+ focusAnyIn (parent: BaseTabComponent | SplitContainer) {
+ if (!parent) {
+ return
+ }
+ if (parent instanceof SplitContainer) {
+ this.focusAnyIn(parent.children[0])
+ } else {
+ this.focus(parent)
+ }
+ }
+
+ /**
+ * Inserts a new `tab` to the `side` of the `relative` tab
+ */
+ addTab (tab: BaseTabComponent, relative: BaseTabComponent, side: SplitDirection) {
+ let target = this.getParentOf(relative) || this.root
+ let insertIndex = target.children.indexOf(relative)
+
+ if (
+ target.orientation === 'v' && ['l', 'r'].includes(side) ||
+ target.orientation === 'h' && ['t', 'b'].includes(side)
+ ) {
+ const newContainer = new SplitContainer()
+ newContainer.orientation = target.orientation === 'v' ? 'h' : 'v'
+ newContainer.children = [relative]
+ newContainer.ratios = [1]
+ target.children[insertIndex] = newContainer
+ target = newContainer
+ insertIndex = 0
+ }
+
+ if (insertIndex === -1) {
+ insertIndex = 0
+ } else {
+ insertIndex += side === 'l' || side === 't' ? 0 : 1
+ }
+
+ for (let i = 0; i < target.children.length; i++) {
+ target.ratios[i] *= target.children.length / (target.children.length + 1)
+ }
+ target.ratios.splice(insertIndex, 0, 1 / (target.children.length + 1))
+ target.children.splice(insertIndex, 0, tab)
+
+ this.recoveryStateChangedHint.next()
+ this.attachTabView(tab)
+
+ setImmediate(() => {
+ this.layout()
+ this.tabAdded.next(tab)
+ this.focus(tab)
+ })
+ }
+
+ removeTab (tab: BaseTabComponent) {
+ const parent = this.getParentOf(tab)
+ const index = parent.children.indexOf(tab)
+ parent.ratios.splice(index, 1)
+ parent.children.splice(index, 1)
+
+ this.detachTabView(tab)
+
+ this.layout()
+
+ this.tabRemoved.next(tab)
+
+ if (this.root.children.length === 0) {
+ this.destroy()
+ } else {
+ this.focusAnyIn(parent)
+ }
+ }
+
+ /**
+ * Moves focus in the given direction
+ */
+ navigate (dir: SplitDirection) {
+ let rel: BaseTabComponent | SplitContainer = this.focusedTab
+ let parent = this.getParentOf(rel)
+ const orientation = ['l', 'r'].includes(dir) ? 'h' : 'v'
+
+ while (parent !== this.root && parent.orientation !== orientation) {
+ rel = parent
+ parent = this.getParentOf(rel)
+ }
+
+ if (parent.orientation !== orientation) {
+ return
+ }
+
+ const index = parent.children.indexOf(rel)
+ if (['l', 't'].includes(dir)) {
+ if (index > 0) {
+ this.focusAnyIn(parent.children[index - 1])
+ }
+ } else {
+ if (index < parent.children.length - 1) {
+ this.focusAnyIn(parent.children[index + 1])
+ }
+ }
+ }
+
+ async splitTab (tab: BaseTabComponent, dir: SplitDirection) {
+ const newTab = await this.tabsService.duplicate(tab)
+ this.addTab(newTab, tab, dir)
+ }
+
+ /**
+ * @returns the immediate parent of `tab`
+ */
+ getParentOf (tab: BaseTabComponent | SplitContainer, root?: SplitContainer): SplitContainer {
+ root = root || this.root
+ for (const child of root.children) {
+ if (child instanceof SplitContainer) {
+ const r = this.getParentOf(tab, child)
+ if (r) {
+ return r
+ }
+ }
+ if (child === tab) {
+ return root
+ }
+ }
+ return null
+ }
+
+ /** @hidden */
+ async canClose (): Promise {
+ return !(await Promise.all(this.getAllTabs().map(x => x.canClose()))).some(x => !x)
+ }
+
+ /** @hidden */
+ async getRecoveryToken (): Promise {
+ return this.root.serialize()
+ }
+
+ /** @hidden */
+ async getCurrentProcess (): Promise {
+ return (await Promise.all(this.getAllTabs().map(x => x.getCurrentProcess()))).find(x => !!x)
+ }
+
+ /** @hidden */
+ onSpannerAdjusted (spanner: SplitSpannerInfo) {
+ this.layout()
+ this.splitAdjusted.next(spanner)
+ }
+
+ private attachTabView (tab: BaseTabComponent) {
+ const ref = this.viewContainer.insert(tab.hostView) as EmbeddedViewRef // eslint-disable-line @typescript-eslint/no-unnecessary-type-assertion
+ this.viewRefs.set(tab, ref)
+
+ ref.rootNodes[0].addEventListener('click', () => this.focus(tab))
+
+ tab.titleChange$.subscribe(t => this.setTitle(t))
+ tab.activity$.subscribe(a => a ? this.displayActivity() : this.clearActivity())
+ tab.progress$.subscribe(p => this.setProgress(p))
+ if (tab.title) {
+ this.setTitle(tab.title)
+ }
+ tab.destroyed$.subscribe(() => {
+ this.removeTab(tab)
+ })
+ }
+
+ private detachTabView (tab: BaseTabComponent) {
+ const ref = this.viewRefs.get(tab)
+ this.viewRefs.delete(tab)
+ this.viewContainer.remove(this.viewContainer.indexOf(ref))
+ }
+
+ private layout () {
+ this.root.normalize()
+ this._spanners = []
+ this.layoutInternal(this.root, 0, 0, 100, 100)
+ }
+
+ private layoutInternal (root: SplitContainer, x: number, y: number, w: number, h: number) {
+ const size = root.orientation === 'v' ? h : w
+ const sizes = root.ratios.map(x => x * size)
+
+ root.x = x
+ root.y = y
+ root.w = w
+ root.h = h
+
+ let offset = 0
+ root.children.forEach((child, i) => {
+ const childX = root.orientation === 'v' ? x : x + offset
+ const childY = root.orientation === 'v' ? y + offset : y
+ const childW = root.orientation === 'v' ? w : sizes[i]
+ const childH = root.orientation === 'v' ? sizes[i] : h
+ if (child instanceof SplitContainer) {
+ this.layoutInternal(child, childX, childY, childW, childH)
+ } else {
+ const element = this.viewRefs.get(child).rootNodes[0]
+ element.style.position = 'absolute'
+ element.style.left = `${childX}%`
+ element.style.top = `${childY}%`
+ element.style.width = `${childW}%`
+ element.style.height = `${childH}%`
+
+ element.style.opacity = child === this.focusedTab ? 1 : 0.75
+ }
+ offset += sizes[i]
+
+ if (i !== 0) {
+ this._spanners.push({
+ container: root,
+ index: i,
+ })
+ }
+ })
+ }
+
+ private async recoverContainer (root: SplitContainer, state: any) {
+ const children: (SplitContainer | BaseTabComponent)[] = []
+ root.orientation = state.orientation
+ root.ratios = state.ratios
+ root.children = children
+ for (const childState of state.children) {
+ if (childState.type === 'app:split-tab') {
+ const child = new SplitContainer()
+ await this.recoverContainer(child, childState)
+ children.push(child)
+ } else {
+ const recovered = await this.tabRecovery.recoverTab(childState)
+ if (recovered) {
+ const tab = this.tabsService.create(recovered.type, recovered.options)
+ children.push(tab)
+ this.attachTabView(tab)
+ } else {
+ state.ratios.splice(state.children.indexOf(childState), 0)
+ }
+ }
+ }
+ }
+}
+
+/** @hidden */
+@Injectable()
+export class SplitTabRecoveryProvider extends TabRecoveryProvider {
+ async recover (recoveryToken: any): Promise {
+ if (recoveryToken && recoveryToken.type === 'app:split-tab') {
+ return {
+ type: SplitTabComponent,
+ options: { _recoveredState: recoveryToken },
+ }
+ }
+ return null
+ }
+}
diff --git a/terminus-core/src/components/splitTabSpanner.component.scss b/terminus-core/src/components/splitTabSpanner.component.scss
new file mode 100644
index 00000000..08b7a6a3
--- /dev/null
+++ b/terminus-core/src/components/splitTabSpanner.component.scss
@@ -0,0 +1,22 @@
+:host {
+ display: block;
+ position: absolute;
+ z-index: 5;
+ transition: 0.125s background;
+
+ &.v {
+ cursor: ns-resize;
+ height: 10px;
+ margin-top: -5px;
+ }
+
+ &.h {
+ cursor: ew-resize;
+ width: 10px;
+ margin-left: -5px;
+ }
+
+ &:hover, &.active {
+ background: rgba(255, 255, 255, .125);
+ }
+}
diff --git a/terminus-core/src/components/splitTabSpanner.component.ts b/terminus-core/src/components/splitTabSpanner.component.ts
new file mode 100644
index 00000000..af53be27
--- /dev/null
+++ b/terminus-core/src/components/splitTabSpanner.component.ts
@@ -0,0 +1,88 @@
+import { Component, Input, HostBinding, ElementRef, Output, EventEmitter } from '@angular/core'
+import { SplitContainer } from './splitTab.component'
+
+/** @hidden */
+@Component({
+ selector: 'split-tab-spanner',
+ template: '',
+ styles: [require('./splitTabSpanner.component.scss')],
+})
+export class SplitTabSpannerComponent {
+ @Input() container: SplitContainer
+ @Input() index: number
+ @Output() change = new EventEmitter()
+ @HostBinding('class.active') isActive = false
+ @HostBinding('class.h') isHorizontal = false
+ @HostBinding('class.v') isVertical = true
+ @HostBinding('style.left') cssLeft: string
+ @HostBinding('style.top') cssTop: string
+ @HostBinding('style.width') cssWidth: string
+ @HostBinding('style.height') cssHeight: string
+ private marginOffset = -5
+
+ constructor (private element: ElementRef) { }
+
+ ngAfterViewInit () {
+ this.element.nativeElement.addEventListener('mousedown', (e: MouseEvent) => {
+ this.isActive = true
+ const start = this.isVertical ? e.pageY : e.pageX
+ let current = start
+ const oldPosition: number = this.isVertical ? this.element.nativeElement.offsetTop : this.element.nativeElement.offsetLeft
+
+ const dragHandler = (e: MouseEvent) => {
+ current = this.isVertical ? e.pageY : e.pageX
+ const newPosition = oldPosition + (current - start)
+ if (this.isVertical) {
+ this.element.nativeElement.style.top = `${newPosition - this.marginOffset}px`
+ } else {
+ this.element.nativeElement.style.left = `${newPosition - this.marginOffset}px`
+ }
+ }
+
+ const offHandler = () => {
+ this.isActive = false
+ document.removeEventListener('mouseup', offHandler)
+ this.element.nativeElement.parentElement.removeEventListener('mousemove', dragHandler)
+
+ let diff = (current - start) / (this.isVertical ? this.element.nativeElement.parentElement.clientHeight : this.element.nativeElement.parentElement.clientWidth)
+
+ diff = Math.max(diff, -this.container.ratios[this.index - 1] + 0.1)
+ diff = Math.min(diff, this.container.ratios[this.index] - 0.1)
+
+ this.container.ratios[this.index - 1] += diff
+ this.container.ratios[this.index] -= diff
+ this.change.emit()
+ }
+
+ document.addEventListener('mouseup', offHandler)
+ this.element.nativeElement.parentElement.addEventListener('mousemove', dragHandler)
+ })
+ }
+
+ ngOnChanges () {
+ this.isHorizontal = this.container.orientation === 'h'
+ this.isVertical = this.container.orientation === 'v'
+ if (this.isVertical) {
+ this.setDimensions(
+ this.container.x,
+ this.container.y + this.container.h * this.container.getOffsetRatio(this.index),
+ this.container.w,
+ null
+ )
+ } else {
+ this.setDimensions(
+ this.container.x + this.container.w * this.container.getOffsetRatio(this.index),
+ this.container.y,
+ null,
+ this.container.h
+ )
+ }
+ }
+
+ private setDimensions (x: number, y: number, w: number, h: number) {
+ this.cssLeft = `${x}%`
+ this.cssTop = `${y}%`
+ this.cssWidth = w ? `${w}%` : null
+ this.cssHeight = h ? `${h}%` : null
+ }
+}
diff --git a/terminus-core/src/components/startPage.component.pug b/terminus-core/src/components/startPage.component.pug
index 9ea99aa1..256b9096 100644
--- a/terminus-core/src/components/startPage.component.pug
+++ b/terminus-core/src/components/startPage.component.pug
@@ -14,10 +14,10 @@ div
footer.d-flex.align-items-center
.btn-group.mr-auto
button.btn.btn-secondary((click)='homeBase.openGitHub()')
- i.fa.fa-github
+ i.fab.fa-github
span GitHub
button.btn.btn-secondary((click)='homeBase.reportBug()')
- i.fa.fa-bug
+ i.fas.fa-bug
span Report a problem
.form-control-static.selectable.no-drag Version: {{homeBase.appVersion}}
diff --git a/terminus-core/src/components/startPage.component.scss b/terminus-core/src/components/startPage.component.scss
index 02f36dea..72e84555 100644
--- a/terminus-core/src/components/startPage.component.scss
+++ b/terminus-core/src/components/startPage.component.scss
@@ -2,7 +2,6 @@
display: flex;
flex-direction: column;
flex: auto;
- -webkit-app-region: drag;
overflow-y: auto;
}
@@ -25,10 +24,6 @@ footer {
background: rgba(0,0,0,.5);
}
-a, button {
- -webkit-app-region: no-drag;
-}
-
.list-group-item ::ng-deep svg {
width: 16px;
height: 16px;
diff --git a/terminus-core/src/components/startPage.component.ts b/terminus-core/src/components/startPage.component.ts
index dde12e9e..51e90dab 100644
--- a/terminus-core/src/components/startPage.component.ts
+++ b/terminus-core/src/components/startPage.component.ts
@@ -1,8 +1,9 @@
import { Component, Inject } from '@angular/core'
import { ConfigService } from '../services/config.service'
import { HomeBaseService } from '../services/homeBase.service'
-import { IToolbarButton, ToolbarButtonProvider } from '../api'
+import { ToolbarButton, ToolbarButtonProvider } from '../api'
+/** @hidden */
@Component({
selector: 'start-page',
template: require('./startPage.component.pug'),
@@ -18,10 +19,11 @@ export class StartPageComponent {
) {
}
- getButtons (): IToolbarButton[] {
+ getButtons (): ToolbarButton[] {
return this.config.enabledServices(this.toolbarButtonProviders)
.map(provider => provider.provide())
.reduce((a, b) => a.concat(b))
- .sort((a: IToolbarButton, b: IToolbarButton) => (a.weight || 0) - (b.weight || 0))
+ .filter(x => !!x.click)
+ .sort((a: ToolbarButton, b: ToolbarButton) => (a.weight || 0) - (b.weight || 0))
}
}
diff --git a/terminus-core/src/components/tabBody.component.ts b/terminus-core/src/components/tabBody.component.ts
index 016bb5a5..0735ec4d 100644
--- a/terminus-core/src/components/tabBody.component.ts
+++ b/terminus-core/src/components/tabBody.component.ts
@@ -1,6 +1,7 @@
import { Component, Input, ViewChild, HostBinding, ViewContainerRef, OnChanges } from '@angular/core'
import { BaseTabComponent } from '../components/baseTab.component'
+/** @hidden */
@Component({
selector: 'tab-body',
template: `
@@ -17,7 +18,7 @@ import { BaseTabComponent } from '../components/baseTab.component'
export class TabBodyComponent implements OnChanges {
@Input() @HostBinding('class.active') active: boolean
@Input() tab: BaseTabComponent
- @ViewChild('placeholder', {read: ViewContainerRef}) placeholder: ViewContainerRef
+ @ViewChild('placeholder', { read: ViewContainerRef }) placeholder: ViewContainerRef
ngOnChanges (changes) {
if (changes.tab) {
diff --git a/terminus-core/src/components/tabHeader.component.ts b/terminus-core/src/components/tabHeader.component.ts
index 92e0ca59..0aabb01b 100644
--- a/terminus-core/src/components/tabHeader.component.ts
+++ b/terminus-core/src/components/tabHeader.component.ts
@@ -1,22 +1,15 @@
-import { Component, Input, HostBinding, HostListener, NgZone, ViewChild, ElementRef } from '@angular/core'
+import { Component, Input, Optional, Inject, HostBinding, HostListener, ViewChild, ElementRef } from '@angular/core'
import { SortableComponent } from 'ng2-dnd'
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
+import { TabContextMenuItemProvider } from '../api/tabContextMenuProvider'
import { BaseTabComponent } from './baseTab.component'
import { RenameTabModalComponent } from './renameTabModal.component'
+import { HotkeysService } from '../services/hotkeys.service'
import { ElectronService } from '../services/electron.service'
import { AppService } from '../services/app.service'
import { HostAppService, Platform } from '../services/hostApp.service'
-const COLORS = [
- { name: 'No color', value: null },
- { name: 'Blue', value: '#0275d8' },
- { name: 'Green', value: '#5cb85c' },
- { name: 'Orange', value: '#f0ad4e' },
- { name: 'Purple', value: '#613d7c' },
- { name: 'Red', value: '#d9534f' },
- { name: 'Yellow', value: '#ffd500' },
-]
-
+/** @hidden */
@Component({
selector: 'tab-header',
template: require('./tabHeader.component.pug'),
@@ -30,16 +23,24 @@ export class TabHeaderComponent {
@Input() progress: number
@ViewChild('handle') handle: ElementRef
- private completionNotificationEnabled = false
-
constructor (
public app: AppService,
private electron: ElectronService,
- private zone: NgZone,
private hostApp: HostAppService,
private ngbModal: NgbModal,
+ private hotkeys: HotkeysService,
private parentDraggable: SortableComponent,
- ) { }
+ @Optional() @Inject(TabContextMenuItemProvider) protected contextMenuProviders: TabContextMenuItemProvider[],
+ ) {
+ this.hotkeys.matchedHotkey.subscribe((hotkey) => {
+ if (this.app.activeTab === this.tab) {
+ if (hotkey === 'rename-tab') {
+ this.showRenameTabModal()
+ }
+ }
+ })
+ this.contextMenuProviders.sort((a, b) => a.weight - b.weight)
+ }
ngOnInit () {
if (this.hostApp.platform === Platform.macOS) {
@@ -50,8 +51,8 @@ export class TabHeaderComponent {
})
}
- @HostListener('dblclick') onDoubleClick (): void {
- let modal = this.ngbModal.open(RenameTabModalComponent)
+ showRenameTabModal (): void {
+ const modal = this.ngbModal.open(RenameTabModalComponent)
modal.componentInstance.value = this.tab.customTitle || this.tab.title
modal.result.then(result => {
this.tab.setTitle(result)
@@ -59,6 +60,19 @@ export class TabHeaderComponent {
}).catch(() => null)
}
+ async buildContextMenu (): Promise {
+ let items: Electron.MenuItemConstructorOptions[] = []
+ for (const section of await Promise.all(this.contextMenuProviders.map(x => x.getItems(this.tab, this)))) {
+ items.push({ type: 'separator' })
+ items = items.concat(section)
+ }
+ return items.slice(1)
+ }
+
+ @HostListener('dblclick') onDoubleClick (): void {
+ this.showRenameTabModal()
+ }
+
@HostListener('auxclick', ['$event']) async onAuxClick ($event: MouseEvent) {
if ($event.which === 2) {
this.app.closeTab(this.tab, true)
@@ -66,90 +80,11 @@ export class TabHeaderComponent {
if ($event.which === 3) {
event.preventDefault()
- let contextMenu = this.electron.remote.Menu.buildFromTemplate([
- {
- label: 'Close',
- click: () => this.zone.run(() => {
- this.app.closeTab(this.tab, true)
- })
- },
- {
- label: 'Close other tabs',
- click: () => this.zone.run(() => {
- for (let tab of this.app.tabs.filter(x => x !== this.tab)) {
- this.app.closeTab(tab, true)
- }
- })
- },
- {
- label: 'Close tabs to the right',
- click: () => this.zone.run(() => {
- for (let tab of this.app.tabs.slice(this.app.tabs.indexOf(this.tab) + 1)) {
- this.app.closeTab(tab, true)
- }
- })
- },
- {
- label: 'Close tabs to the left',
- click: () => this.zone.run(() => {
- for (let tab of this.app.tabs.slice(0, this.app.tabs.indexOf(this.tab))) {
- this.app.closeTab(tab, true)
- }
- })
- },
- {
- label: 'Color',
- sublabel: COLORS.find(x => x.value === this.tab.color).name,
- submenu: COLORS.map(color => ({
- label: color.name,
- type: 'radio',
- checked: this.tab.color === color.value,
- click: () => this.zone.run(() => {
- this.tab.color = color.value
- }),
- })),
- }
- ])
-
- let process = await this.tab.getCurrentProcess()
- if (process) {
- contextMenu.append(new this.electron.MenuItem({
- id: 'sep',
- type: 'separator',
- }))
- contextMenu.append(new this.electron.MenuItem({
- id: 'process-name',
- enabled: false,
- label: 'Current process: ' + process.name,
- }))
- contextMenu.append(new this.electron.MenuItem({
- id: 'completion',
- label: 'Notify when done',
- type: 'checkbox',
- checked: this.completionNotificationEnabled,
- click: () => this.zone.run(() => {
- this.completionNotificationEnabled = !this.completionNotificationEnabled
-
- if (this.completionNotificationEnabled) {
- this.app.observeTabCompletion(this.tab).subscribe(() => {
- new Notification('Process completed', {
- body: process.name,
- }).addEventListener('click', () => {
- this.app.selectTab(this.tab)
- })
- this.completionNotificationEnabled = false
- })
- } else {
- this.app.stopObservingTabCompletion(this.tab)
- }
- })
- }))
- }
+ const contextMenu = this.electron.remote.Menu.buildFromTemplate(await this.buildContextMenu())
contextMenu.popup({
x: $event.pageX,
y: $event.pageY,
- async: true,
})
}
}
diff --git a/terminus-core/src/components/titleBar.component.ts b/terminus-core/src/components/titleBar.component.ts
index b53bc60e..9e8b088b 100644
--- a/terminus-core/src/components/titleBar.component.ts
+++ b/terminus-core/src/components/titleBar.component.ts
@@ -1,8 +1,9 @@
import { Component } from '@angular/core'
+/** @hidden */
@Component({
selector: 'title-bar',
template: require('./titleBar.component.pug'),
styles: [require('./titleBar.component.scss')],
})
-export class TitleBarComponent { }
+export class TitleBarComponent { } // eslint-disable-line @typescript-eslint/no-extraneous-class
diff --git a/terminus-core/src/components/toggle.component.ts b/terminus-core/src/components/toggle.component.ts
index 91fd5878..a417b1b6 100644
--- a/terminus-core/src/components/toggle.component.ts
+++ b/terminus-core/src/components/toggle.component.ts
@@ -2,6 +2,7 @@ import { Component } from '@angular/core'
import { NG_VALUE_ACCESSOR } from '@angular/forms'
import { CheckboxComponent } from './checkbox.component'
+/** @hidden */
@Component({
selector: 'toggle',
template: `
@@ -16,7 +17,7 @@ import { CheckboxComponent } from './checkbox.component'
styles: [require('./toggle.component.scss')],
providers: [
{ provide: NG_VALUE_ACCESSOR, useExisting: ToggleComponent, multi: true },
- ]
+ ],
})
export class ToggleComponent extends CheckboxComponent {
}
diff --git a/terminus-core/src/components/welcomeTab.component.pug b/terminus-core/src/components/welcomeTab.component.pug
new file mode 100644
index 00000000..45186247
--- /dev/null
+++ b/terminus-core/src/components/welcomeTab.component.pug
@@ -0,0 +1,19 @@
+.mb-4
+ .terminus-logo
+ h1.terminus-title Terminus
+ sup Ξ±
+
+.container
+ .text-center.mb-5 Thank you for downloading Terminus!
+
+ .form-line
+ .header
+ .title Enable analytics
+ .description Help us track the number of Terminus installs across the world!
+ toggle(
+ [(ngModel)]='config.store.enableAnalytics',
+ (ngModelChange)='config.save(); config.requestRestart()',
+ )
+
+ .text-center.mt-5
+ button.btn.btn-primary((click)='closeAndDisable()') Close and never show again
diff --git a/terminus-core/src/components/welcomeTab.component.scss b/terminus-core/src/components/welcomeTab.component.scss
new file mode 100644
index 00000000..6a6860fd
--- /dev/null
+++ b/terminus-core/src/components/welcomeTab.component.scss
@@ -0,0 +1,6 @@
+:host {
+ display: flex;
+ flex-direction: column;
+ margin: auto;
+ flex: 0 1 500px;
+}
diff --git a/terminus-core/src/components/welcomeTab.component.ts b/terminus-core/src/components/welcomeTab.component.ts
new file mode 100644
index 00000000..f2b8a9f4
--- /dev/null
+++ b/terminus-core/src/components/welcomeTab.component.ts
@@ -0,0 +1,26 @@
+import { Component } from '@angular/core'
+import { BaseTabComponent } from './baseTab.component'
+import { ConfigService } from '../services/config.service'
+import { AppService } from '../services/app.service'
+
+/** @hidden */
+@Component({
+ selector: 'welcome-page',
+ template: require('./welcomeTab.component.pug'),
+ styles: [require('./welcomeTab.component.scss')],
+})
+export class WelcomeTabComponent extends BaseTabComponent {
+ constructor (
+ private app: AppService,
+ public config: ConfigService,
+ ) {
+ super()
+ this.setTitle('Welcome')
+ }
+
+ closeAndDisable () {
+ this.config.store.enableWelcomeTab = false
+ this.config.save()
+ this.app.closeTab(this)
+ }
+}
diff --git a/terminus-core/src/components/windowControls.component.pug b/terminus-core/src/components/windowControls.component.pug
index ad14083f..84716e91 100644
--- a/terminus-core/src/components/windowControls.component.pug
+++ b/terminus-core/src/components/windowControls.component.pug
@@ -9,7 +9,7 @@ button.btn.btn-secondary.btn-maximize(
svg(version='1.1', width='10', height='10')
path(d='M 0,0 0,10 10,10 10,0 Z M 1,1 9,1 9,9 1,9 Z')
button.btn.btn-secondary.btn-close(
- (click)='app.closeWindow()'
+ (click)='closeWindow()'
)
svg(version='1.1', width='10', height='10')
path(d='M 0,0 0,0.7 4.3,5 0,9.3 0,10 0.7,10 5,5.7 9.3,10 10,10 10,9.3 5.7,5 10,0.7 10,0 9.3,0 5,4.3 0.7,0 Z')
diff --git a/terminus-core/src/components/windowControls.component.ts b/terminus-core/src/components/windowControls.component.ts
index 2b5188e7..152382da 100644
--- a/terminus-core/src/components/windowControls.component.ts
+++ b/terminus-core/src/components/windowControls.component.ts
@@ -2,6 +2,7 @@ import { Component } from '@angular/core'
import { HostAppService } from '../services/hostApp.service'
import { AppService } from '../services/app.service'
+/** @hidden */
@Component({
selector: 'window-controls',
template: require('./windowControls.component.pug'),
@@ -9,4 +10,9 @@ import { AppService } from '../services/app.service'
})
export class WindowControlsComponent {
constructor (public hostApp: HostAppService, public app: AppService) { }
+
+ async closeWindow () {
+ await this.app.closeAllTabs()
+ this.hostApp.closeWindow()
+ }
}
diff --git a/terminus-core/src/config.ts b/terminus-core/src/config.ts
index 086ca350..a81ff957 100644
--- a/terminus-core/src/config.ts
+++ b/terminus-core/src/config.ts
@@ -1,6 +1,7 @@
import { ConfigProvider } from './api/configProvider'
import { Platform } from './services/hostApp.service'
+/** @hidden */
export class CoreConfigProvider extends ConfigProvider {
platformDefaults = {
[Platform.macOS]: require('./configDefaults.macos.yaml'),
diff --git a/terminus-core/src/configDefaults.linux.yaml b/terminus-core/src/configDefaults.linux.yaml
index 75671c35..164a790e 100644
--- a/terminus-core/src/configDefaults.linux.yaml
+++ b/terminus-core/src/configDefaults.linux.yaml
@@ -7,46 +7,48 @@ hotkeys:
- 'F11'
close-tab:
- 'Ctrl-Shift-W'
- - ['Ctrl-A', 'K']
- toggle-last-tab:
- - ['Ctrl-A', 'A']
- - ['Ctrl-A', 'Ctrl-A']
+ toggle-last-tab: []
+ rename-tab:
+ - 'Ctrl-Shift-R'
next-tab:
- - 'Ctrl-Shift-ArrowRight'
- - ['Ctrl-A', 'N']
+ - 'Ctrl-Shift-Right'
- 'Ctrl-Tab'
previous-tab:
- - 'Ctrl-Shift-ArrowLeft'
- - ['Ctrl-A', 'P']
+ - 'Ctrl-Shift-Left'
- 'Ctrl-Shift-Tab'
tab-1:
- 'Alt-1'
- - ['Ctrl-A', '1']
tab-2:
- 'Alt-2'
- - ['Ctrl-A', '2']
tab-3:
- 'Alt-3'
- - ['Ctrl-A', '3']
tab-4:
- 'Alt-4'
- - ['Ctrl-A', '4']
tab-5:
- 'Alt-5'
- - ['Ctrl-A', '5']
tab-6:
- 'Alt-6'
- - ['Ctrl-A', '6']
tab-7:
- 'Alt-7'
- - ['Ctrl-A', '7']
tab-8:
- 'Alt-8'
- - ['Ctrl-A', '8']
tab-9:
- 'Alt-9'
- - ['Ctrl-A', '9']
tab-10:
- 'Alt-0'
- - ['Ctrl-A', '0']
+ split-right:
+ - 'Ctrl-Shift-E'
+ split-bottom:
+ - 'Ctrl-Shift-D'
+ split-left: []
+ split-top: []
+ pane-nav-right:
+ - 'Ctrl-Alt-Right'
+ pane-nav-down:
+ - 'Ctrl-Alt-Down'
+ pane-nav-up:
+ - 'Ctrl-Alt-Up'
+ pane-nav-left:
+ - 'Ctrl-Alt-Left'
+ close-pane: []
pluginBlacklist: ['ssh']
diff --git a/terminus-core/src/configDefaults.macos.yaml b/terminus-core/src/configDefaults.macos.yaml
index 239f30fc..acce9713 100644
--- a/terminus-core/src/configDefaults.macos.yaml
+++ b/terminus-core/src/configDefaults.macos.yaml
@@ -8,6 +8,8 @@ hotkeys:
close-tab:
- 'β-W'
toggle-last-tab: []
+ rename-tab:
+ - 'β-R'
next-tab:
- 'Ctrl-Tab'
previous-tab:
@@ -32,4 +34,20 @@ hotkeys:
- 'β-9'
tab-10:
- 'β-0'
+ split-right:
+ - 'β-Shift-D'
+ split-bottom:
+ - 'β-D'
+ split-left: []
+ split-top: []
+ pane-nav-right:
+ - 'β-β₯-Right'
+ pane-nav-down:
+ - 'β-β₯-Down'
+ pane-nav-up:
+ - 'β-β₯-Up'
+ pane-nav-left:
+ - 'β-β₯-Left'
+ close-pane:
+ - 'β-Shift-W'
pluginBlacklist: ['ssh']
diff --git a/terminus-core/src/configDefaults.windows.yaml b/terminus-core/src/configDefaults.windows.yaml
index b5222d65..467a2cf9 100644
--- a/terminus-core/src/configDefaults.windows.yaml
+++ b/terminus-core/src/configDefaults.windows.yaml
@@ -7,46 +7,48 @@ hotkeys:
- 'F11'
close-tab:
- 'Ctrl-Shift-W'
- - ['Ctrl-A', 'K']
- toggle-last-tab:
- - ['Ctrl-A', 'A']
- - ['Ctrl-A', 'Ctrl-A']
+ toggle-last-tab: []
+ rename-tab:
+ - 'Ctrl-Shift-R'
next-tab:
- - 'Ctrl-Shift-ArrowRight'
- - ['Ctrl-A', 'N']
+ - 'Ctrl-Shift-Right'
- 'Ctrl-Tab'
previous-tab:
- - 'Ctrl-Shift-ArrowLeft'
- - ['Ctrl-A', 'P']
+ - 'Ctrl-Shift-Left'
- 'Ctrl-Shift-Tab'
tab-1:
- 'Alt-1'
- - ['Ctrl-A', '1']
tab-2:
- 'Alt-2'
- - ['Ctrl-A', '2']
tab-3:
- 'Alt-3'
- - ['Ctrl-A', '3']
tab-4:
- 'Alt-4'
- - ['Ctrl-A', '4']
tab-5:
- 'Alt-5'
- - ['Ctrl-A', '5']
tab-6:
- 'Alt-6'
- - ['Ctrl-A', '6']
tab-7:
- 'Alt-7'
- - ['Ctrl-A', '7']
tab-8:
- 'Alt-8'
- - ['Ctrl-A', '8']
tab-9:
- 'Alt-9'
- - ['Ctrl-A', '9']
tab-10:
- 'Alt-0'
- - ['Ctrl-A', '0']
+ split-right:
+ - 'Ctrl-Shift-E'
+ split-bottom:
+ - 'Ctrl-Shift-D'
+ split-left: []
+ split-top: []
+ pane-nav-right:
+ - 'Ctrl-Alt-Right'
+ pane-nav-down:
+ - 'Ctrl-Alt-Down'
+ pane-nav-up:
+ - 'Ctrl-Alt-Up'
+ pane-nav-left:
+ - 'Ctrl-Alt-Left'
+ close-pane: []
pluginBlacklist: []
diff --git a/terminus-core/src/configDefaults.yaml b/terminus-core/src/configDefaults.yaml
index 01251dd6..332eee95 100644
--- a/terminus-core/src/configDefaults.yaml
+++ b/terminus-core/src/configDefaults.yaml
@@ -11,3 +11,6 @@ appearance:
vibrancy: false
vibrancyType: 'blur'
enableAnalytics: true
+enableWelcomeTab: true
+electronFlags:
+ - ['force_discrete_gpu', '0']
diff --git a/terminus-core/src/directives/autofocus.directive.ts b/terminus-core/src/directives/autofocus.directive.ts
index 34b3625e..26849b8c 100644
--- a/terminus-core/src/directives/autofocus.directive.ts
+++ b/terminus-core/src/directives/autofocus.directive.ts
@@ -1,7 +1,8 @@
import { Directive, AfterViewInit, ElementRef } from '@angular/core'
+/** @hidden */
@Directive({
- selector: '[autofocus]'
+ selector: '[autofocus]',
})
export class AutofocusDirective implements AfterViewInit {
constructor (private el: ElementRef) { }
diff --git a/terminus-core/src/hotkeys.ts b/terminus-core/src/hotkeys.ts
new file mode 100644
index 00000000..1ee22240
--- /dev/null
+++ b/terminus-core/src/hotkeys.ts
@@ -0,0 +1,121 @@
+import { Injectable } from '@angular/core'
+import { HotkeyDescription, HotkeyProvider } from './api/hotkeyProvider'
+
+/** @hidden */
+@Injectable()
+export class AppHotkeyProvider extends HotkeyProvider {
+ hotkeys: HotkeyDescription[] = [
+ {
+ id: 'new-window',
+ name: 'New window',
+ },
+ {
+ id: 'toggle-window',
+ name: 'Toggle terminal window',
+ },
+ {
+ id: 'toggle-fullscreen',
+ name: 'Toggle fullscreen mode',
+ },
+ {
+ id: 'rename-tab',
+ name: 'Rename Tab',
+ },
+ {
+ id: 'close-tab',
+ name: 'Close tab',
+ },
+ {
+ id: 'toggle-last-tab',
+ name: 'Toggle last tab',
+ },
+ {
+ id: 'next-tab',
+ name: 'Next tab',
+ },
+ {
+ id: 'previous-tab',
+ name: 'Previous tab',
+ },
+ {
+ id: 'tab-1',
+ name: 'Tab 1',
+ },
+ {
+ id: 'tab-2',
+ name: 'Tab 2',
+ },
+ {
+ id: 'tab-3',
+ name: 'Tab 3',
+ },
+ {
+ id: 'tab-4',
+ name: 'Tab 4',
+ },
+ {
+ id: 'tab-5',
+ name: 'Tab 5',
+ },
+ {
+ id: 'tab-6',
+ name: 'Tab 6',
+ },
+ {
+ id: 'tab-7',
+ name: 'Tab 7',
+ },
+ {
+ id: 'tab-8',
+ name: 'Tab 8',
+ },
+ {
+ id: 'tab-9',
+ name: 'Tab 9',
+ },
+ {
+ id: 'tab-10',
+ name: 'Tab 10',
+ },
+ {
+ id: 'split-right',
+ name: 'Split to the right',
+ },
+ {
+ id: 'split-bottom',
+ name: 'Split to the bottom',
+ },
+ {
+ id: 'split-left',
+ name: 'Split to the left',
+ },
+ {
+ id: 'split-top',
+ name: 'Split to the top',
+ },
+ {
+ id: 'pane-nav-up',
+ name: 'Focus the pane above',
+ },
+ {
+ id: 'pane-nav-down',
+ name: 'Focus the pane below',
+ },
+ {
+ id: 'pane-nav-left',
+ name: 'Focus the pane on the left',
+ },
+ {
+ id: 'pane-nav-right',
+ name: 'Focus the pane on the right',
+ },
+ {
+ id: 'close-pane',
+ name: 'Close focused pane',
+ },
+ ]
+
+ async provide (): Promise {
+ return this.hotkeys
+ }
+}
diff --git a/terminus-core/src/index.ts b/terminus-core/src/index.ts
index 3c6d6ba2..4fb42fd0 100644
--- a/terminus-core/src/index.ts
+++ b/terminus-core/src/index.ts
@@ -6,20 +6,6 @@ import { NgbModule } from '@ng-bootstrap/ng-bootstrap'
import { PerfectScrollbarModule, PERFECT_SCROLLBAR_CONFIG } from 'ngx-perfect-scrollbar'
import { DndModule } from 'ng2-dnd'
-import { AppService } from './services/app.service'
-import { ConfigService } from './services/config.service'
-import { ElectronService } from './services/electron.service'
-import { HostAppService } from './services/hostApp.service'
-import { LogService } from './services/log.service'
-import { HomeBaseService } from './services/homeBase.service'
-import { HotkeysService, AppHotkeyProvider } from './services/hotkeys.service'
-import { DockingService } from './services/docking.service'
-import { ShellIntegrationService } from './services/shellIntegration.service'
-import { TabRecoveryService } from './services/tabRecovery.service'
-import { ThemesService } from './services/themes.service'
-import { TouchbarService } from './services/touchbar.service'
-import { UpdaterService } from './services/updater.service'
-
import { AppRootComponent } from './components/appRoot.component'
import { CheckboxComponent } from './components/checkbox.component'
import { TabBodyComponent } from './components/tabBody.component'
@@ -30,41 +16,49 @@ import { TitleBarComponent } from './components/titleBar.component'
import { ToggleComponent } from './components/toggle.component'
import { WindowControlsComponent } from './components/windowControls.component'
import { RenameTabModalComponent } from './components/renameTabModal.component'
+import { SplitTabComponent, SplitTabRecoveryProvider } from './components/splitTab.component'
+import { SplitTabSpannerComponent } from './components/splitTabSpanner.component'
+import { WelcomeTabComponent } from './components/welcomeTab.component'
import { AutofocusDirective } from './directives/autofocus.directive'
import { HotkeyProvider } from './api/hotkeyProvider'
import { ConfigProvider } from './api/configProvider'
import { Theme } from './api/theme'
+import { TabContextMenuItemProvider } from './api/tabContextMenuProvider'
+import { TabRecoveryProvider } from './api/tabRecovery'
+
+import { AppService } from './services/app.service'
+import { ConfigService } from './services/config.service'
import { StandardTheme, StandardCompactTheme, PaperTheme } from './theme'
import { CoreConfigProvider } from './config'
+import { AppHotkeyProvider } from './hotkeys'
+import { TaskCompletionContextMenu, CommonOptionsContextMenu, CloseContextMenu } from './tabContextMenu'
import 'perfect-scrollbar/css/perfect-scrollbar.css'
import 'ng2-dnd/bundles/style.css'
+// PerfectScrollbar fix
+import { fromEvent } from 'rxjs/internal/observable/fromEvent'
+import { merge } from 'rxjs/internal/observable/merge'
+require('rxjs').fromEvent = fromEvent
+require('rxjs').merge = merge
+
const PROVIDERS = [
- AppService,
- ConfigService,
- DockingService,
- ElectronService,
- HomeBaseService,
- HostAppService,
- HotkeysService,
- LogService,
- ShellIntegrationService,
- TabRecoveryService,
- ThemesService,
- TouchbarService,
- UpdaterService,
{ provide: HotkeyProvider, useClass: AppHotkeyProvider, multi: true },
{ provide: Theme, useClass: StandardTheme, multi: true },
{ provide: Theme, useClass: StandardCompactTheme, multi: true },
{ provide: Theme, useClass: PaperTheme, multi: true },
{ provide: ConfigProvider, useClass: CoreConfigProvider, multi: true },
- { provide: PERFECT_SCROLLBAR_CONFIG, useValue: { suppressScrollX: true }}
+ { provide: TabContextMenuItemProvider, useClass: CommonOptionsContextMenu, multi: true },
+ { provide: TabContextMenuItemProvider, useClass: CloseContextMenu, multi: true },
+ { provide: TabContextMenuItemProvider, useClass: TaskCompletionContextMenu, multi: true },
+ { provide: TabRecoveryProvider, useClass: SplitTabRecoveryProvider, multi: true },
+ { provide: PERFECT_SCROLLBAR_CONFIG, useValue: { suppressScrollX: true } },
]
+/** @hidden */
@NgModule({
imports: [
BrowserModule,
@@ -86,18 +80,31 @@ const PROVIDERS = [
RenameTabModalComponent,
SafeModeModalComponent,
AutofocusDirective,
+ SplitTabComponent,
+ SplitTabSpannerComponent,
+ WelcomeTabComponent,
],
entryComponents: [
RenameTabModalComponent,
SafeModeModalComponent,
+ SplitTabComponent,
+ WelcomeTabComponent,
],
exports: [
CheckboxComponent,
ToggleComponent,
AutofocusDirective,
- ]
+ ],
})
-export default class AppModule {
+export default class AppModule { // eslint-disable-line @typescript-eslint/no-extraneous-class
+ constructor (app: AppService, config: ConfigService) {
+ app.ready$.subscribe(() => {
+ if (config.store.enableWelcomeTab) {
+ app.openNewTabRaw(WelcomeTabComponent)
+ }
+ })
+ }
+
static forRoot (): ModuleWithProviders {
return {
ngModule: AppModule,
@@ -106,11 +113,9 @@ export default class AppModule {
}
}
-// PerfectScrollbar fix
-import { fromEvent } from 'rxjs/internal/observable/fromEvent'
-import { merge } from 'rxjs/internal/observable/merge'
-require('rxjs').fromEvent = fromEvent
-require('rxjs').merge = merge
-
export { AppRootComponent as bootstrap }
export * from './api'
+
+// Deprecations
+export { ToolbarButton as IToolbarButton } from './api'
+export { HotkeyDescription as IHotkeyDescription } from './api'
diff --git a/terminus-core/src/services/app.service.ts b/terminus-core/src/services/app.service.ts
index fef30982..69d18325 100644
--- a/terminus-core/src/services/app.service.ts
+++ b/terminus-core/src/services/app.service.ts
@@ -1,12 +1,12 @@
import { Observable, Subject, AsyncSubject } from 'rxjs'
import { takeUntil } from 'rxjs/operators'
-import { Injectable, ComponentFactoryResolver, Injector } from '@angular/core'
+import { Injectable } from '@angular/core'
import { BaseTabComponent } from '../components/baseTab.component'
-import { Logger, LogService } from './log.service'
+import { SplitTabComponent } from '../components/splitTab.component'
import { ConfigService } from './config.service'
import { HostAppService } from './hostApp.service'
-
-export declare type TabComponentType = new (...args: any[]) => BaseTabComponent
+import { TabRecoveryService } from './tabRecovery.service'
+import { TabsService, TabComponentType } from './tabs.service'
class CompletionObserver {
get done$ (): Observable { return this.done }
@@ -16,12 +16,12 @@ class CompletionObserver {
private interval: number
constructor (private tab: BaseTabComponent) {
- this.interval = setInterval(() => this.tick(), 1000)
+ this.interval = setInterval(() => this.tick(), 1000) as any
this.tab.destroyed$.pipe(takeUntil(this.destroyed$)).subscribe(() => this.stop())
}
async tick () {
- if (!(await this.tab.getCurrentProcess())) {
+ if (!await this.tab.getCurrentProcess()) {
this.done.next(null)
this.stop()
}
@@ -35,12 +35,14 @@ class CompletionObserver {
}
}
-@Injectable()
+@Injectable({ providedIn: 'root' })
export class AppService {
tabs: BaseTabComponent[] = []
- activeTab: BaseTabComponent
- lastTabIndex = 0
- logger: Logger
+
+ get activeTab (): BaseTabComponent { return this._activeTab }
+
+ private lastTabIndex = 0
+ private _activeTab: BaseTabComponent
private activeTabChange = new Subject()
private tabsChanged = new Subject()
@@ -54,62 +56,105 @@ export class AppService {
get tabOpened$ (): Observable { return this.tabOpened }
get tabsChanged$ (): Observable { return this.tabsChanged }
get tabClosed$ (): Observable { return this.tabClosed }
+
+ /** Fires once when the app is ready */
get ready$ (): Observable { return this.ready }
+ /** @hidden */
constructor (
- private componentFactoryResolver: ComponentFactoryResolver,
private config: ConfigService,
private hostApp: HostAppService,
- private injector: Injector,
- log: LogService,
+ private tabRecovery: TabRecoveryService,
+ private tabsService: TabsService,
) {
- this.logger = log.create('app')
+ this.tabRecovery.recoverTabs().then(tabs => {
+ for (const tab of tabs) {
+ this.openNewTabRaw(tab.type, tab.options)
+ }
- this.hostApp.windowCloseRequest$.subscribe(() => this.closeWindow())
+ this.tabsChanged$.subscribe(() => {
+ tabRecovery.saveTabs(this.tabs)
+ })
+ setInterval(() => {
+ tabRecovery.saveTabs(this.tabs)
+ }, 30000)
+ })
}
- openNewTab (type: TabComponentType, inputs?: any): BaseTabComponent {
- let componentFactory = this.componentFactoryResolver.resolveComponentFactory(type)
- let componentRef = componentFactory.create(this.injector)
- let tab = componentRef.instance
- tab.hostView = componentRef.hostView
- Object.assign(tab, inputs || {})
-
+ addTabRaw (tab: BaseTabComponent) {
this.tabs.push(tab)
this.selectTab(tab)
this.tabsChanged.next()
this.tabOpened.next(tab)
+ tab.recoveryStateChangedHint$.subscribe(() => {
+ this.tabRecovery.saveTabs(this.tabs)
+ })
+
tab.titleChange$.subscribe(title => {
- if (tab === this.activeTab) {
+ if (tab === this._activeTab) {
this.hostApp.setTitle(title)
}
})
+
+ tab.destroyed$.subscribe(() => {
+ const newIndex = Math.max(0, this.tabs.indexOf(tab) - 1)
+ this.tabs = this.tabs.filter((x) => x !== tab)
+ if (tab === this._activeTab) {
+ this.selectTab(this.tabs[newIndex])
+ }
+ this.tabsChanged.next()
+ this.tabClosed.next(tab)
+ })
+ }
+
+ /**
+ * Adds a new tab **without** wrapping it in a SplitTabComponent
+ * @param inputs Properties to be assigned on the new tab component instance
+ */
+ openNewTabRaw (type: TabComponentType, inputs?: any): BaseTabComponent {
+ const tab = this.tabsService.create(type, inputs)
+ this.addTabRaw(tab)
+ return tab
+ }
+
+ /**
+ * Adds a new tab while wrapping it in a SplitTabComponent
+ * @param inputs Properties to be assigned on the new tab component instance
+ */
+ openNewTab (type: TabComponentType, inputs?: any): BaseTabComponent {
+ const splitTab = this.tabsService.create(SplitTabComponent) as SplitTabComponent
+ const tab = this.tabsService.create(type, inputs)
+ splitTab.addTab(tab, null, 'r')
+ this.addTabRaw(splitTab)
return tab
}
selectTab (tab: BaseTabComponent) {
- if (this.activeTab === tab) {
- this.activeTab.emitFocused()
+ if (this._activeTab === tab) {
+ this._activeTab.emitFocused()
return
}
- if (this.tabs.includes(this.activeTab)) {
- this.lastTabIndex = this.tabs.indexOf(this.activeTab)
+ if (this.tabs.includes(this._activeTab)) {
+ this.lastTabIndex = this.tabs.indexOf(this._activeTab)
} else {
this.lastTabIndex = null
}
- if (this.activeTab) {
- this.activeTab.clearActivity()
- this.activeTab.emitBlurred()
+ if (this._activeTab) {
+ this._activeTab.clearActivity()
+ this._activeTab.emitBlurred()
}
- this.activeTab = tab
+ this._activeTab = tab
this.activeTabChange.next(tab)
- if (this.activeTab) {
- this.activeTab.emitFocused()
- this.hostApp.setTitle(this.activeTab.title)
+ if (this._activeTab) {
+ setImmediate(() => {
+ this._activeTab.emitFocused()
+ })
+ this.hostApp.setTitle(this._activeTab.title)
}
}
+ /** Switches between the current tab and the previously active one */
toggleLastTab () {
if (!this.lastTabIndex || this.lastTabIndex >= this.tabs.length) {
this.lastTabIndex = 0
@@ -119,7 +164,7 @@ export class AppService {
nextTab () {
if (this.tabs.length > 1) {
- let tabIndex = this.tabs.indexOf(this.activeTab)
+ const tabIndex = this.tabs.indexOf(this._activeTab)
if (tabIndex < this.tabs.length - 1) {
this.selectTab(this.tabs[tabIndex + 1])
} else if (this.config.store.appearance.cycleTabs) {
@@ -130,7 +175,7 @@ export class AppService {
previousTab () {
if (this.tabs.length > 1) {
- let tabIndex = this.tabs.indexOf(this.activeTab)
+ const tabIndex = this.tabs.indexOf(this._activeTab)
if (tabIndex > 0) {
this.selectTab(this.tabs[tabIndex - 1])
} else if (this.config.store.appearance.cycleTabs) {
@@ -139,6 +184,7 @@ export class AppService {
}
}
+ /** @hidden */
emitTabsChanged () {
this.tabsChanged.next()
}
@@ -150,37 +196,41 @@ export class AppService {
if (checkCanClose && !await tab.canClose()) {
return
}
- let newIndex = Math.max(0, this.tabs.indexOf(tab) - 1)
- this.tabs = this.tabs.filter((x) => x !== tab)
tab.destroy()
- if (tab === this.activeTab) {
- this.selectTab(this.tabs[newIndex])
- }
- this.tabsChanged.next()
- this.tabClosed.next(tab)
}
- async closeWindow () {
- for (let tab of this.tabs) {
+ async duplicateTab (tab: BaseTabComponent) {
+ const dup = await this.tabsService.duplicate(tab)
+ if (dup) {
+ this.addTabRaw(dup)
+ }
+ }
+
+ async closeAllTabs () {
+ for (const tab of this.tabs) {
if (!await tab.canClose()) {
return
}
}
- for (let tab of this.tabs) {
+ for (const tab of this.tabs) {
tab.destroy()
}
- this.hostApp.closeWindow()
}
+ /** @hidden */
emitReady () {
this.ready.next(null)
this.ready.complete()
this.hostApp.emitReady()
}
+ /**
+ * Returns an observable that fires once
+ * the tab's internal "process" (see [[BaseTabProcess]]) completes
+ */
observeTabCompletion (tab: BaseTabComponent): Observable {
if (!this.completionObservers.has(tab)) {
- let observer = new CompletionObserver(tab)
+ const observer = new CompletionObserver(tab)
observer.destroyed$.subscribe(() => {
this.stopObservingTabCompletion(tab)
})
diff --git a/terminus-core/src/services/config.service.ts b/terminus-core/src/services/config.service.ts
index a57500ab..157521c4 100644
--- a/terminus-core/src/services/config.service.ts
+++ b/terminus-core/src/services/config.service.ts
@@ -14,18 +14,19 @@ function isStructuralMember (v) {
Object.keys(v).length > 0 && !v.__nonStructural
}
-function isNonStructuralObjectMember (v) {
+function isNonStructuralObjectMember (v): boolean {
return v instanceof Object && !(v instanceof Array) && v.__nonStructural
}
+/** @hidden */
export class ConfigProxy {
constructor (real: any, defaults: any) {
- for (let key in defaults) {
+ for (const key in defaults) {
if (isStructuralMember(defaults[key])) {
if (!real[key]) {
real[key] = {}
}
- let proxy = new ConfigProxy(real[key], defaults[key])
+ const proxy = new ConfigProxy(real[key], defaults[key])
Object.defineProperty(
this,
key,
@@ -45,18 +46,18 @@ export class ConfigProxy {
get: () => this.getValue(key),
set: (value) => {
this.setValue(key, value)
- }
+ },
}
)
}
}
- this.getValue = (key: string) => {
+ this.getValue = (key: string) => { // eslint-disable-line @typescript-eslint/unbound-method
if (real[key] !== undefined) {
return real[key]
} else {
if (isNonStructuralObjectMember(defaults[key])) {
- real[key] = {...defaults[key]}
+ real[key] = { ...defaults[key] }
delete real[key].__nonStructural
return real[key]
} else {
@@ -65,27 +66,40 @@ export class ConfigProxy {
}
}
- this.setValue = (key: string, value: any) => {
+ this.setValue = (key: string, value: any) => { // eslint-disable-line @typescript-eslint/unbound-method
real[key] = value
}
}
- getValue (key: string): any { } // tslint:disable-line
- setValue (key: string, value: any) { } // tslint:disable-line
+ getValue (_key: string): any { }
+ setValue (_key: string, _value: any) { }
}
-@Injectable()
+@Injectable({ providedIn: 'root' })
export class ConfigService {
+ /**
+ * Contains the actual config values
+ */
store: any
+
+ /**
+ * Whether an app restart is required due to recent changes
+ */
restartRequested: boolean
+
+ /**
+ * Full config file path
+ */
+ path: string
+
private changed = new Subject()
private _store: any
- private path: string
private defaults: any
private servicesCache: { [id: string]: Function[] } = null
get changed$ (): Observable { return this.changed }
+ /** @hidden */
constructor (
electron: ElectronService,
private hostApp: HostAppService,
@@ -129,10 +143,16 @@ export class ConfigService {
this.hostApp.broadcastConfigChange()
}
+ /**
+ * Reads config YAML as string
+ */
readRaw (): string {
return yaml.safeDump(this._store)
}
+ /**
+ * Writes config YAML as string
+ */
writeRaw (data: string): void {
this._store = yaml.safeLoad(data)
this.save()
@@ -140,20 +160,22 @@ export class ConfigService {
this.emitChange()
}
- emitChange (): void {
- this.changed.next()
- }
-
requestRestart (): void {
this.restartRequested = true
}
+ /**
+ * Filters a list of Angular services to only include those provided
+ * by plugins that are enabled
+ *
+ * @typeparam T Base provider type
+ */
enabledServices (services: T[]): T[] {
if (!this.servicesCache) {
this.servicesCache = {}
- let ngModule = window['rootModule'].ngInjectorDef
- for (let imp of ngModule.imports) {
- let module = (imp['ngModule'] || imp)
+ const ngModule = window['rootModule'].ngInjectorDef
+ for (const imp of ngModule.imports) {
+ const module = imp['ngModule'] || imp
if (module.ngInjectorDef && module.ngInjectorDef.providers) {
this.servicesCache[module['pluginName']] = module.ngInjectorDef.providers.map(provider => {
return provider['useClass'] || provider
@@ -162,7 +184,7 @@ export class ConfigService {
}
}
return services.filter(service => {
- for (let pluginName in this.servicesCache) {
+ for (const pluginName in this.servicesCache) {
if (this.servicesCache[pluginName].includes(service.constructor)) {
return !this.store.pluginBlacklist.includes(pluginName)
}
@@ -170,4 +192,8 @@ export class ConfigService {
return true
})
}
+
+ private emitChange (): void {
+ this.changed.next()
+ }
}
diff --git a/terminus-core/src/services/docking.service.ts b/terminus-core/src/services/docking.service.ts
index 018522f7..20f368db 100644
--- a/terminus-core/src/services/docking.service.ts
+++ b/terminus-core/src/services/docking.service.ts
@@ -3,13 +3,9 @@ import { ConfigService } from '../services/config.service'
import { ElectronService } from '../services/electron.service'
import { HostAppService, Bounds } from '../services/hostApp.service'
-export interface IScreen {
- id: string
- name: string
-}
-
-@Injectable()
+@Injectable({ providedIn: 'root' })
export class DockingService {
+ /** @hidden */
constructor (
private electron: ElectronService,
private config: ConfigService,
@@ -20,21 +16,23 @@ export class DockingService {
}
dock () {
- let display = this.electron.screen.getAllDisplays()
- .filter((x) => x.id === this.config.store.appearance.dockScreen)[0]
- if (!display) {
- display = this.getCurrentScreen()
- }
-
- let dockSide = this.config.store.appearance.dock
- let newBounds: Bounds = { x: 0, y: 0, width: 0, height: 0 }
- let fill = this.config.store.appearance.dockFill
- let [minWidth, minHeight] = this.hostApp.getWindow().getMinimumSize()
+ const dockSide = this.config.store.appearance.dock
if (dockSide === 'off') {
this.hostApp.setAlwaysOnTop(false)
return
}
+
+ let display = this.electron.screen.getAllDisplays()
+ .filter(x => x.id === this.config.store.appearance.dockScreen)[0]
+ if (!display) {
+ display = this.getCurrentScreen()
+ }
+
+ const newBounds: Bounds = { x: 0, y: 0, width: 0, height: 0 }
+ const fill = this.config.store.appearance.dockFill
+ const [minWidth, minHeight] = this.hostApp.getWindow().getMinimumSize()
+
if (dockSide === 'left' || dockSide === 'right') {
newBounds.width = Math.max(minWidth, Math.round(fill * display.bounds.width))
newBounds.height = display.bounds.height
@@ -68,23 +66,23 @@ export class DockingService {
return this.electron.screen.getAllDisplays().map((display, index) => {
return {
id: display.id,
- name: {
- 0: 'Primary display',
- 1: 'Secondary display',
- }[index] || `Display ${index + 1}`
+ name: [
+ 'Primary display',
+ 'Secondary display',
+ ][index] || `Display ${index + 1}`,
}
})
}
- repositionWindow () {
- let [x, y] = this.hostApp.getWindow().getPosition()
- for (let screen of this.electron.screen.getAllDisplays()) {
- let bounds = screen.bounds
+ private repositionWindow () {
+ const [x, y] = this.hostApp.getWindow().getPosition()
+ for (const screen of this.electron.screen.getAllDisplays()) {
+ const bounds = screen.bounds
if (x >= bounds.x && x <= bounds.x + bounds.width && y >= bounds.y && y <= bounds.y + bounds.height) {
return
}
}
- let screen = this.electron.screen.getPrimaryDisplay()
+ const screen = this.electron.screen.getPrimaryDisplay()
this.hostApp.getWindow().setPosition(screen.bounds.x, screen.bounds.y)
}
}
diff --git a/terminus-core/src/services/electron.service.ts b/terminus-core/src/services/electron.service.ts
index 4a53c5c4..c570f598 100644
--- a/terminus-core/src/services/electron.service.ts
+++ b/terminus-core/src/services/electron.service.ts
@@ -1,24 +1,30 @@
import { Injectable } from '@angular/core'
-import { TouchBar, BrowserWindow, Menu, MenuItem } from 'electron'
+import { TouchBar, BrowserWindow, Menu, MenuItem, NativeImage } from 'electron'
-@Injectable()
+export interface MessageBoxResponse {
+ response: number
+ checkboxChecked?: boolean
+}
+
+@Injectable({ providedIn: 'root' })
export class ElectronService {
- app: any
- ipcRenderer: any
- shell: any
- dialog: any
- clipboard: any
- globalShortcut: any
- nativeImage: any
- screen: any
- remote: any
- autoUpdater: any
+ app: Electron.App
+ ipcRenderer: Electron.IpcRenderer
+ shell: Electron.Shell
+ dialog: Electron.Dialog
+ clipboard: Electron.Clipboard
+ globalShortcut: Electron.GlobalShortcut
+ nativeImage: typeof NativeImage
+ screen: Electron.Screen
+ remote: Electron.Remote
+ autoUpdater: Electron.AutoUpdater
TouchBar: typeof TouchBar
BrowserWindow: typeof BrowserWindow
Menu: typeof Menu
MenuItem: typeof MenuItem
private electron: any
+ /** @hidden */
constructor () {
this.electron = require('electron')
this.remote = this.electron.remote
@@ -37,21 +43,23 @@ export class ElectronService {
this.MenuItem = this.remote.MenuItem
}
- remoteRequire (name: string): any {
- return this.remote.require(name)
- }
-
- remoteRequirePluginModule (plugin: string, module: string, globals: any): any {
- return this.remoteRequire(this.remoteResolvePluginModule(plugin, module, globals))
- }
-
- remoteResolvePluginModule (plugin: string, module: string, globals: any): any {
- return globals.require.resolve(`${plugin}/node_modules/${module}`)
- }
-
+ /**
+ * Removes OS focus from Terminus' window
+ */
loseFocus () {
if (process.platform === 'darwin') {
this.remote.Menu.sendActionToFirstResponder('hide:')
}
}
+
+ async showMessageBox (
+ browserWindow: Electron.BrowserWindow,
+ options: Electron.MessageBoxOptions
+ ): Promise {
+ return new Promise(resolve => {
+ this.dialog.showMessageBox(browserWindow, options, (response, checkboxChecked) => {
+ resolve({ response, checkboxChecked })
+ })
+ })
+ }
}
diff --git a/terminus-core/src/services/homeBase.service.ts b/terminus-core/src/services/homeBase.service.ts
index 24334c67..934a2484 100644
--- a/terminus-core/src/services/homeBase.service.ts
+++ b/terminus-core/src/services/homeBase.service.ts
@@ -2,20 +2,22 @@ import * as os from 'os'
import { Injectable } from '@angular/core'
import { ElectronService } from './electron.service'
import { ConfigService } from './config.service'
-import ua = require('universal-analytics')
-import uuidv4 = require('uuid/v4')
+import * as mixpanel from 'mixpanel'
+import * as uuidv4 from 'uuid/v4'
-@Injectable()
+@Injectable({ providedIn: 'root' })
export class HomeBaseService {
appVersion: string
+ mixpanel: any
+ /** @hidden */
constructor (
private electron: ElectronService,
private config: ConfigService,
) {
this.appVersion = electron.app.getVersion()
- if (this.config.store.enableAnalytics) {
+ if (this.config.store.enableAnalytics && !this.config.store.enableWelcomeTab) {
this.enableAnalytics()
}
}
@@ -27,12 +29,12 @@ export class HomeBaseService {
reportBug () {
let body = `Version: ${this.appVersion}\n`
body += `Platform: ${os.platform()} ${os.release()}\n`
- let label = {
+ const label = {
darwin: 'OS: macOS',
windows: 'OS: Windows',
linux: 'OS: Linux',
}[os.platform()]
- let plugins = (window as any).installedPlugins.filter(x => !x.isBuiltin).map(x => x.name)
+ const plugins = (window as any).installedPlugins.filter(x => !x.isBuiltin).map(x => x.name)
body += `Plugins: ${plugins.join(', ') || 'none'}\n\n`
this.electron.shell.openExternal(`https://github.com/eugeny/terminus/issues/new?body=${encodeURIComponent(body)}&labels=${label}`)
}
@@ -41,9 +43,20 @@ export class HomeBaseService {
if (!window.localStorage.analyticsUserID) {
window.localStorage.analyticsUserID = uuidv4()
}
- const session = ua('UA-3278102-20', window.localStorage.analyticsUserID)
- session.set('cd1', this.appVersion)
- session.set('cd2', process.platform)
- session.pageview('/').send()
+ this.mixpanel = mixpanel.init('bb4638b0860eef14c04d4fbc5eb365fa')
+ if (!window.localStorage.installEventSent) {
+ this.mixpanel.track('freshInstall', this.getAnalyticsProperties())
+ window.localStorage.installEventSent = true
+ }
+ this.mixpanel.track('launch', this.getAnalyticsProperties())
+ }
+
+ getAnalyticsProperties () {
+ return {
+ distinct_id: window.localStorage.analyticsUserID, // eslint-disable-line @typescript-eslint/camelcase
+ platform: process.platform,
+ os: os.release(),
+ version: this.appVersion,
+ }
}
}
diff --git a/terminus-core/src/services/hostApp.service.ts b/terminus-core/src/services/hostApp.service.ts
index cf863e51..b50da1e9 100644
--- a/terminus-core/src/services/hostApp.service.ts
+++ b/terminus-core/src/services/hostApp.service.ts
@@ -1,5 +1,5 @@
import * as path from 'path'
-import shellEscape = require('shell-escape')
+import shellEscape from 'shell-escape'
import { Observable, Subject } from 'rxjs'
import { Injectable, NgZone, EventEmitter } from '@angular/core'
import { ElectronService } from './electron.service'
@@ -16,42 +16,89 @@ export interface Bounds {
height: number
}
-@Injectable()
+/**
+ * Provides interaction with the main process
+ */
+@Injectable({ providedIn: 'root' })
export class HostAppService {
platform: Platform
- nodePlatform: string
+
+ /**
+ * Fired once the window is visible
+ */
shown = new EventEmitter()
isFullScreen = false
+ isPortable = !!process.env.PORTABLE_EXECUTABLE_FILE
+
private preferencesMenu = new Subject()
private secondInstance = new Subject()
private cliOpenDirectory = new Subject()
private cliRunCommand = new Subject()
private cliPaste = new Subject()
+ private cliOpenProfile = new Subject()
private configChangeBroadcast = new Subject()
private windowCloseRequest = new Subject()
+ private windowMoved = new Subject()
+ private displayMetricsChanged = new Subject()
private logger: Logger
private windowId: number
+ /**
+ * Fired when Preferences is selected in the macOS menu
+ */
get preferencesMenu$ (): Observable { return this.preferencesMenu }
+
+ /**
+ * Fired when a second instance of Terminus is launched
+ */
get secondInstance$ (): Observable { return this.secondInstance }
+
+ /**
+ * Fired for the `terminus open` CLI command
+ */
get cliOpenDirectory$ (): Observable { return this.cliOpenDirectory }
+
+ /**
+ * Fired for the `terminus run` CLI command
+ */
get cliRunCommand$ (): Observable { return this.cliRunCommand }
+
+ /**
+ * Fired for the `terminus paste` CLI command
+ */
get cliPaste$ (): Observable { return this.cliPaste }
+
+ /**
+ * Fired for the `terminus profile` CLI command
+ */
+ get cliOpenProfile$ (): Observable { return this.cliOpenProfile }
+
+ /**
+ * Fired when another window modified the config file
+ */
get configChangeBroadcast$ (): Observable { return this.configChangeBroadcast }
+
+ /**
+ * Fired when the window close button is pressed
+ */
get windowCloseRequest$ (): Observable { return this.windowCloseRequest }
+ get windowMoved$ (): Observable { return this.windowMoved }
+
+ get displayMetricsChanged$ (): Observable { return this.displayMetricsChanged }
+
+ /** @hidden */
constructor (
private zone: NgZone,
private electron: ElectronService,
log: LogService,
) {
this.logger = log.create('hostApp')
- this.nodePlatform = require('os').platform()
this.platform = {
win32: Platform.Windows,
darwin: Platform.macOS,
- linux: Platform.Linux
- }[this.nodePlatform]
+ linux: Platform.Linux,
+ }[process.platform]
this.windowId = parseInt(location.search.substring(1))
this.logger.info('Window ID:', this.windowId)
@@ -78,6 +125,14 @@ export class HostAppService {
this.zone.run(() => this.windowCloseRequest.next())
})
+ electron.ipcRenderer.on('host:window-moved', () => {
+ 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]
@@ -91,6 +146,8 @@ export class HostAppService {
text = shellEscape([text])
}
this.cliPaste.next(text)
+ } else if (op === 'profile') {
+ this.cliOpenProfile.next(argv.profileName)
} else {
this.secondInstance.next()
}
@@ -101,6 +158,9 @@ export class HostAppService {
}))
}
+ /**
+ * Returns the current remote [[BrowserWindow]]
+ */
getWindow () {
return this.electron.BrowserWindow.fromId(this.windowId)
}
@@ -109,20 +169,8 @@ export class HostAppService {
this.electron.ipcRenderer.send('app:new-window')
}
- getShell () {
- return this.electron.shell
- }
-
- getAppPath () {
- return this.electron.app.getAppPath()
- }
-
- getPath (type: string) {
- return this.electron.app.getPath(type)
- }
-
toggleFullscreen () {
- let window = this.getWindow()
+ const window = this.getWindow()
window.setFullScreen(!this.isFullScreen)
}
@@ -158,6 +206,11 @@ export class HostAppService {
this.electron.ipcRenderer.send('window-set-always-on-top', flag)
}
+ /**
+ * Sets window vibrancy mode (Windows, macOS)
+ *
+ * @param type `null`, or `fluent` when supported (Windowd only)
+ */
setVibrancy (enable: boolean, type: string) {
document.body.classList.toggle('vibrant', enable)
if (this.platform === Platform.macOS) {
@@ -180,6 +233,9 @@ export class HostAppService {
this.electron.Menu.buildFromTemplate(menuDefinition).popup({})
}
+ /**
+ * Notifies other windows of config file changes
+ */
broadcastConfigChange () {
this.electron.ipcRenderer.send('app:config-change')
}
@@ -196,6 +252,15 @@ export class HostAppService {
this.electron.ipcRenderer.send('window-close')
}
+ relaunch () {
+ if (this.isPortable) {
+ this.electron.app.relaunch({ execPath: process.env.PORTABLE_EXECUTABLE_FILE })
+ } else {
+ this.electron.app.relaunch()
+ }
+ this.electron.app.exit()
+ }
+
quit () {
this.logger.info('Quitting')
this.electron.app.quit()
diff --git a/terminus-core/src/services/hotkeys.service.ts b/terminus-core/src/services/hotkeys.service.ts
index 4bd453e9..16b01417 100644
--- a/terminus-core/src/services/hotkeys.service.ts
+++ b/terminus-core/src/services/hotkeys.service.ts
@@ -1,40 +1,41 @@
import { Injectable, Inject, NgZone, EventEmitter } from '@angular/core'
-import { IHotkeyDescription, HotkeyProvider } from '../api/hotkeyProvider'
-import { NativeKeyEvent, stringifyKeySequence } from './hotkeys.util'
+import { HotkeyDescription, HotkeyProvider } from '../api/hotkeyProvider'
+import { stringifyKeySequence } from './hotkeys.util'
import { ConfigService } from '../services/config.service'
import { ElectronService } from '../services/electron.service'
export interface PartialHotkeyMatch {
- id: string,
- strokes: string[],
- matchedLength: number,
+ id: string
+ strokes: string[]
+ matchedLength: number
}
const KEY_TIMEOUT = 2000
interface EventBufferEntry {
- event: NativeKeyEvent,
- time: number,
+ event: KeyboardEvent
+ time: number
}
-@Injectable()
+@Injectable({ providedIn: 'root' })
export class HotkeysService {
- key = new EventEmitter()
+ key = new EventEmitter()
matchedHotkey = new EventEmitter()
globalHotkey = new EventEmitter()
private currentKeystrokes: EventBufferEntry[] = []
private disabledLevel = 0
- private hotkeyDescriptions: IHotkeyDescription[] = []
+ private hotkeyDescriptions: HotkeyDescription[] = []
+ /** @hidden */
constructor (
private zone: NgZone,
private electron: ElectronService,
private config: ConfigService,
@Inject(HotkeyProvider) private hotkeyProviders: HotkeyProvider[],
) {
- let events = ['keydown', 'keyup']
- events.forEach((event) => {
- document.addEventListener(event, (nativeEvent) => {
+ const events = ['keydown', 'keyup']
+ events.forEach(event => {
+ document.addEventListener(event, (nativeEvent: KeyboardEvent) => {
if (document.querySelectorAll('input:focus').length === 0) {
this.pushKeystroke(event, nativeEvent)
this.processKeystrokes()
@@ -51,15 +52,24 @@ export class HotkeysService {
})
}
- pushKeystroke (name, nativeEvent) {
- nativeEvent.event = name
+ /**
+ * Adds a new key event to the buffer
+ *
+ * @param name DOM event name
+ * @param nativeEvent event object
+ */
+ pushKeystroke (name: string, nativeEvent: KeyboardEvent) {
+ (nativeEvent as any).event = name
this.currentKeystrokes.push({ event: nativeEvent, time: performance.now() })
}
+ /**
+ * Check the buffer for new complete keystrokes
+ */
processKeystrokes () {
if (this.isEnabled()) {
this.zone.run(() => {
- let matched = this.getCurrentFullyMatchedHotkey()
+ const matched = this.getCurrentFullyMatchedHotkey()
if (matched) {
console.log('Matched hotkey', matched)
this.matchedHotkey.emit(matched)
@@ -69,7 +79,7 @@ export class HotkeysService {
}
}
- emitKeyEvent (nativeEvent) {
+ emitKeyEvent (nativeEvent: KeyboardEvent) {
this.zone.run(() => {
this.key.emit(nativeEvent)
})
@@ -80,65 +90,20 @@ export class HotkeysService {
}
getCurrentKeystrokes (): string[] {
- this.currentKeystrokes = this.currentKeystrokes.filter((x) => performance.now() - x.time < KEY_TIMEOUT )
- return stringifyKeySequence(this.currentKeystrokes.map((x) => x.event))
- }
-
- registerGlobalHotkey () {
- this.electron.globalShortcut.unregisterAll()
- let value = this.config.store.hotkeys['toggle-window'] || []
- if (typeof value === 'string') {
- value = [value]
- }
- value.forEach(item => {
- item = (typeof item === 'string') ? [item] : item
-
- try {
- this.electron.globalShortcut.register(item[0].replace(/-/g, '+'), () => {
- this.globalHotkey.emit()
- })
- } catch (err) {
- console.error('Could not register the global hotkey:', err)
- }
- })
- }
-
- getHotkeysConfig () {
- return this.getHotkeysConfigRecursive(this.config.store.hotkeys)
- }
-
- getHotkeysConfigRecursive (branch) {
- let keys = {}
- for (let key in branch) {
- let value = branch[key]
- if (value instanceof Object && !(value instanceof Array)) {
- let subkeys = this.getHotkeysConfigRecursive(value)
- for (let subkey in subkeys) {
- keys[key + '.' + subkey] = subkeys[subkey]
- }
- } else {
- if (typeof value === 'string') {
- value = [value]
- }
- if (value) {
- value = value.map((item) => (typeof item === 'string') ? [item] : item)
- keys[key] = value
- }
- }
- }
- return keys
+ this.currentKeystrokes = this.currentKeystrokes.filter(x => performance.now() - x.time < KEY_TIMEOUT)
+ return stringifyKeySequence(this.currentKeystrokes.map(x => x.event))
}
getCurrentFullyMatchedHotkey (): string {
- let currentStrokes = this.getCurrentKeystrokes()
- let config = this.getHotkeysConfig()
- for (let id in config) {
- for (let sequence of config[id]) {
+ const currentStrokes = this.getCurrentKeystrokes()
+ const config = this.getHotkeysConfig()
+ for (const id in config) {
+ for (const sequence of config[id]) {
if (currentStrokes.length < sequence.length) {
continue
}
if (sequence.every(
- (x, index) =>
+ (x: string, index: number) =>
x.toLowerCase() ===
currentStrokes[currentStrokes.length - sequence.length + index].toLowerCase()
)) {
@@ -150,21 +115,21 @@ export class HotkeysService {
}
getCurrentPartiallyMatchedHotkeys (): PartialHotkeyMatch[] {
- let currentStrokes = this.getCurrentKeystrokes()
- let config = this.getHotkeysConfig()
- let result = []
- for (let id in config) {
- for (let sequence of config[id]) {
+ const currentStrokes = this.getCurrentKeystrokes()
+ const config = this.getHotkeysConfig()
+ const result = []
+ for (const id in config) {
+ for (const sequence of config[id]) {
for (let matchLength = Math.min(currentStrokes.length, sequence.length); matchLength > 0; matchLength--) {
if (sequence.slice(0, matchLength).every(
- (x, index) =>
+ (x: string, index: number) =>
x.toLowerCase() ===
currentStrokes[currentStrokes.length - matchLength + index].toLowerCase()
)) {
result.push({
matchedLength: matchLength,
id,
- strokes: sequence
+ strokes: sequence,
})
break
}
@@ -174,7 +139,7 @@ export class HotkeysService {
return result
}
- getHotkeyDescription (id: string): IHotkeyDescription {
+ getHotkeyDescription (id: string): HotkeyDescription {
return this.hotkeyDescriptions.filter((x) => x.id === id)[0]
}
@@ -190,7 +155,7 @@ export class HotkeysService {
return this.disabledLevel === 0
}
- async getHotkeyDescriptions (): Promise {
+ async getHotkeyDescriptions (): Promise {
return (
await Promise.all(
this.config.enabledServices(this.hotkeyProviders)
@@ -198,82 +163,53 @@ export class HotkeysService {
)
).reduce((a, b) => a.concat(b))
}
-}
-@Injectable()
-export class AppHotkeyProvider extends HotkeyProvider {
- hotkeys: IHotkeyDescription[] = [
- {
- id: 'new-window',
- name: 'New window',
- },
- {
- id: 'toggle-window',
- name: 'Toggle terminal window',
- },
- {
- id: 'toggle-fullscreen',
- name: 'Toggle fullscreen mode',
- },
- {
- id: 'close-tab',
- name: 'Close tab',
- },
- {
- id: 'toggle-last-tab',
- name: 'Toggle last tab',
- },
- {
- id: 'next-tab',
- name: 'Next tab',
- },
- {
- id: 'previous-tab',
- name: 'Previous tab',
- },
- {
- id: 'tab-1',
- name: 'Tab 1',
- },
- {
- id: 'tab-2',
- name: 'Tab 2',
- },
- {
- id: 'tab-3',
- name: 'Tab 3',
- },
- {
- id: 'tab-4',
- name: 'Tab 4',
- },
- {
- id: 'tab-5',
- name: 'Tab 5',
- },
- {
- id: 'tab-6',
- name: 'Tab 6',
- },
- {
- id: 'tab-7',
- name: 'Tab 7',
- },
- {
- id: 'tab-8',
- name: 'Tab 8',
- },
- {
- id: 'tab-9',
- name: 'Tab 9',
- },
- {
- id: 'tab-10',
- name: 'Tab 10',
- },
- ]
+ private registerGlobalHotkey () {
+ this.electron.globalShortcut.unregisterAll()
+ let value = this.config.store.hotkeys['toggle-window'] || []
+ if (typeof value === 'string') {
+ value = [value]
+ }
+ value.forEach((item: string | string[]) => {
+ item = typeof item === 'string' ? [item] : item
- async provide (): Promise {
- return this.hotkeys
+ try {
+ let electronKeySpec = item[0]
+ electronKeySpec = electronKeySpec.replace('β', 'Command')
+ electronKeySpec = electronKeySpec.replace('β₯', 'Alt')
+ electronKeySpec = electronKeySpec.replace(/-/g, '+')
+ this.electron.globalShortcut.register(electronKeySpec, () => {
+ this.globalHotkey.emit()
+ })
+ } catch (err) {
+ console.error('Could not register the global hotkey:', err)
+ }
+ })
+ }
+
+ private getHotkeysConfig () {
+ return this.getHotkeysConfigRecursive(this.config.store.hotkeys)
+ }
+
+ private getHotkeysConfigRecursive (branch: any) {
+ const keys = {}
+ for (const key in branch) {
+ let value = branch[key]
+ if (value instanceof Object && !(value instanceof Array)) {
+ const subkeys = this.getHotkeysConfigRecursive(value)
+ for (const subkey in subkeys) {
+ keys[key + '.' + subkey] = subkeys[subkey]
+ }
+ } else {
+ if (typeof value === 'string') {
+ value = [value]
+ }
+ if (value) {
+ value = value.map((item: string | string[]) => typeof item === 'string' ? [item] : item)
+ keys[key] = value
+ }
+ }
+ }
+ return keys
}
}
diff --git a/terminus-core/src/services/hotkeys.util.ts b/terminus-core/src/services/hotkeys.util.ts
index 01759c3f..ca121244 100644
--- a/terminus-core/src/services/hotkeys.util.ts
+++ b/terminus-core/src/services/hotkeys.util.ts
@@ -10,24 +10,14 @@ export const altKeyName = {
linux: 'Alt',
}[process.platform]
-export interface NativeKeyEvent {
- event?: string,
- altKey: boolean,
- ctrlKey: boolean,
- metaKey: boolean,
- shiftKey: boolean,
- key: string,
- keyCode: string,
-}
-
-export function stringifyKeySequence (events: NativeKeyEvent[]): string[] {
- let items: string[] = []
+export function stringifyKeySequence (events: KeyboardEvent[]): string[] {
+ const items: string[] = []
events = events.slice()
while (events.length > 0) {
- let event = events.shift()
- if (event.event === 'keydown') {
- let itemKeys: string[] = []
+ const event = events.shift()
+ if ((event as any).event === 'keydown') {
+ const itemKeys: string[] = []
if (event.ctrlKey) {
itemKeys.push('Ctrl')
}
@@ -45,13 +35,26 @@ export function stringifyKeySequence (events: NativeKeyEvent[]): string[] {
// TODO make this optional?
continue
}
- if (event.key === ' ') {
- itemKeys.push('Space')
- } else if (event.key.length === 1) {
- itemKeys.push(event.key.toUpperCase())
- } else {
- itemKeys.push(event.key)
- }
+
+ let key = event.code
+ key = key.replace('Key', '')
+ key = key.replace('Arrow', '')
+ key = key.replace('Digit', '')
+ key = {
+ Comma: ',',
+ Period: '.',
+ Slash: '/',
+ Backslash: '\\',
+ IntlBackslash: '\\',
+ Backquote: '`',
+ Minus: '-',
+ Equal: '=',
+ Semicolon: ';',
+ Quote: '\'',
+ BracketLeft: '[',
+ BracketRight: ']',
+ }[key] || key
+ itemKeys.push(key)
items.push(itemKeys.join('-'))
}
}
diff --git a/terminus-core/src/services/log.service.ts b/terminus-core/src/services/log.service.ts
index 20023510..5879935d 100644
--- a/terminus-core/src/services/log.service.ts
+++ b/terminus-core/src/services/log.service.ts
@@ -11,25 +11,18 @@ const initializeWinston = (electron: ElectronService) => {
fs.mkdirSync(logDirectory)
}
- return new winston.Logger({
+ return winston.createLogger({
transports: [
new winston.transports.File({
level: 'debug',
filename: path.join(logDirectory, 'log.txt'),
+ format: winston.format.simple(),
handleExceptions: false,
- json: false,
maxsize: 5242880,
maxFiles: 5,
- colorize: false
}),
- new winston.transports.Console({
- level: 'info',
- handleExceptions: false,
- json: false,
- colorize: true
- })
],
- exitOnError: false
+ exitOnError: false,
})
}
@@ -39,24 +32,39 @@ export class Logger {
private name: string,
) {}
- doLog (level: string, ...args: any[]) {
+ debug (...args: any[]) {
+ this.doLog('debug', ...args)
+ }
+
+ info (...args: any[]) {
+ this.doLog('info', ...args)
+ }
+
+ warn (...args: any[]) {
+ this.doLog('warn', ...args)
+ }
+
+ error (...args: any[]) {
+ this.doLog('error', ...args)
+ }
+
+ log (...args: any[]) {
+ this.doLog('log', ...args)
+ }
+
+ private doLog (level: string, ...args: any[]) {
console[level](`%c[${this.name}]`, 'color: #aaa', ...args)
if (this.winstonLogger) {
this.winstonLogger[level](...args)
}
}
-
- debug (...args: any[]) { this.doLog('debug', ...args) }
- info (...args: any[]) { this.doLog('info', ...args) }
- warn (...args: any[]) { this.doLog('warn', ...args) }
- error (...args: any[]) { this.doLog('error', ...args) }
- log (...args: any[]) { this.doLog('log', ...args) }
}
-@Injectable()
+@Injectable({ providedIn: 'root' })
export class LogService {
private log: any
+ /** @hidden */
constructor (electron: ElectronService) {
this.log = initializeWinston(electron)
}
diff --git a/terminus-core/src/services/shellIntegration.service.ts b/terminus-core/src/services/shellIntegration.service.ts
index 6bbd8464..2078c626 100644
--- a/terminus-core/src/services/shellIntegration.service.ts
+++ b/terminus-core/src/services/shellIntegration.service.ts
@@ -1,24 +1,29 @@
import * as path from 'path'
import * as fs from 'mz/fs'
-import { Registry } from 'rage-edit-tmp'
import { exec } from 'mz/child_process'
import { Injectable } from '@angular/core'
import { ElectronService } from './electron.service'
import { HostAppService, Platform } from './hostApp.service'
-@Injectable()
+/* eslint-disable block-scoped-var */
+
+try {
+ var wnr = require('windows-native-registry') // eslint-disable-line @typescript-eslint/no-var-requires
+} catch (_) { }
+
+@Injectable({ providedIn: 'root' })
export class ShellIntegrationService {
private automatorWorkflows = ['Open Terminus here.workflow', 'Paste path into Terminus.workflow']
private automatorWorkflowsLocation: string
private automatorWorkflowsDestination: string
private registryKeys = [
{
- path: 'HKCU\\Software\\Classes\\Directory\\Background\\shell\\Open Terminus here',
- command: 'open "%V"'
+ path: 'Software\\Classes\\Directory\\Background\\shell\\Open Terminus here',
+ command: 'open "%V"',
},
{
- path: 'HKCU\\Software\\Classes\\*\\shell\\Paste path into Terminus',
- command: 'paste "%V"'
+ path: 'Software\\Classes\\*\\shell\\Paste path into Terminus',
+ command: 'paste "%V"',
},
]
constructor (
@@ -37,7 +42,44 @@ export class ShellIntegrationService {
this.updatePaths()
}
- async updatePaths (): Promise {
+ async isInstalled (): Promise {
+ if (this.hostApp.platform === Platform.macOS) {
+ return fs.exists(path.join(this.automatorWorkflowsDestination, this.automatorWorkflows[0]))
+ } else if (this.hostApp.platform === Platform.Windows) {
+ return !!wnr.getRegistryKey(wnr.HK.CU, this.registryKeys[0].path)
+ }
+ return true
+ }
+
+ async install () {
+ const exe: string = process.env.PORTABLE_EXECUTABLE_FILE || this.electron.app.getPath('exe')
+ if (this.hostApp.platform === Platform.macOS) {
+ for (const wf of this.automatorWorkflows) {
+ await exec(`cp -r "${this.automatorWorkflowsLocation}/${wf}" "${this.automatorWorkflowsDestination}"`)
+ }
+ } else if (this.hostApp.platform === Platform.Windows) {
+ for (const registryKey of this.registryKeys) {
+ wnr.createRegistryKey(wnr.HK.CU, registryKey.path)
+ wnr.createRegistryKey(wnr.HK.CU, registryKey.path + '\\command')
+ wnr.setRegistryValue(wnr.HK.CU, registryKey.path, 'Icon', wnr.REG.SZ, exe)
+ wnr.setRegistryValue(wnr.HK.CU, registryKey.path + '\\command', '', wnr.REG.SZ, exe + ' ' + registryKey.command)
+ }
+ }
+ }
+
+ async remove () {
+ if (this.hostApp.platform === Platform.macOS) {
+ for (const wf of this.automatorWorkflows) {
+ await exec(`rm -rf "${this.automatorWorkflowsDestination}/${wf}"`)
+ }
+ } else if (this.hostApp.platform === Platform.Windows) {
+ for (const registryKey of this.registryKeys) {
+ wnr.deleteRegistryKey(wnr.HK.CU, registryKey.path)
+ }
+ }
+ }
+
+ private async updatePaths (): Promise {
// Update paths in case of an update
if (this.hostApp.platform === Platform.Windows) {
if (await this.isInstalled()) {
@@ -45,26 +87,4 @@ export class ShellIntegrationService {
}
}
}
-
- async isInstalled (): Promise {
- if (this.hostApp.platform === Platform.macOS) {
- return await fs.exists(path.join(this.automatorWorkflowsDestination, this.automatorWorkflows[0]))
- } else if (this.hostApp.platform === Platform.Windows) {
- return await Registry.has(this.registryKeys[0].path)
- }
- return true
- }
-
- async install () {
- if (this.hostApp.platform === Platform.macOS) {
- for (let wf of this.automatorWorkflows) {
- await exec(`cp -r "${this.automatorWorkflowsLocation}/${wf}" "${this.automatorWorkflowsDestination}"`)
- }
- } else if (this.hostApp.platform === Platform.Windows) {
- for (let registryKey of this.registryKeys) {
- await Registry.set(registryKey.path, 'Icon', this.electron.app.getPath('exe'))
- await Registry.set(registryKey.path + '\\command', '', this.electron.app.getPath('exe') + ' ' + registryKey.command)
- }
- }
- }
}
diff --git a/terminus-core/src/services/tabRecovery.service.ts b/terminus-core/src/services/tabRecovery.service.ts
index 0bc3f0fe..47fdcf7e 100644
--- a/terminus-core/src/services/tabRecovery.service.ts
+++ b/terminus-core/src/services/tabRecovery.service.ts
@@ -2,52 +2,56 @@ 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()
+/** @hidden */
+@Injectable({ providedIn: 'root' })
export class TabRecoveryService {
logger: Logger
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)
- })
}
- saveTabs (tabs: BaseTabComponent[]) {
+ async saveTabs (tabs: BaseTabComponent[]) {
window.localStorage.tabsRecovery = JSON.stringify(
- tabs
- .map((tab) => tab.getRecoveryToken())
- .filter((token) => !!token)
+ await Promise.all(
+ tabs
+ .map(tab => tab.getRecoveryToken())
+ .filter(token => !!token)
+ )
)
}
- async recoverTabs (): Promise {
- 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)
- }
+ async recoverTab (token: any): Promise {
+ for (const provider of this.config.enabledServices(this.tabRecoveryProviders)) {
+ try {
+ const tab = await provider.recover(token)
+ if (tab) {
+ return tab
}
+ } catch (error) {
+ this.logger.warn('Tab recovery crashed:', token, provider, error)
}
- tabs.forEach(tab => {
- this.app.openNewTab(tab.type, tab.options)
- })
}
+ return null
}
+ async recoverTabs (): Promise {
+ if (window.localStorage.tabsRecovery) {
+ const tabs: RecoveredTab[] = []
+ for (const token of JSON.parse(window.localStorage.tabsRecovery)) {
+ const tab = await this.recoverTab(token)
+ if (tab) {
+ tabs.push(tab)
+ }
+ }
+ return tabs
+ }
+ return []
+ }
}
diff --git a/terminus-core/src/services/tabs.service.ts b/terminus-core/src/services/tabs.service.ts
new file mode 100644
index 00000000..90e752e6
--- /dev/null
+++ b/terminus-core/src/services/tabs.service.ts
@@ -0,0 +1,43 @@
+import { Injectable, ComponentFactoryResolver, Injector } from '@angular/core'
+import { BaseTabComponent } from '../components/baseTab.component'
+import { TabRecoveryService } from './tabRecovery.service'
+
+// eslint-disable-next-line @typescript-eslint/no-type-alias
+export type TabComponentType = new (...args: any[]) => BaseTabComponent
+
+@Injectable({ providedIn: 'root' })
+export class TabsService {
+ /** @hidden */
+ constructor (
+ private componentFactoryResolver: ComponentFactoryResolver,
+ private injector: Injector,
+ private tabRecovery: TabRecoveryService,
+ ) { }
+
+ /**
+ * Instantiates a tab component and assigns given inputs
+ */
+ create (type: TabComponentType, inputs?: any): BaseTabComponent {
+ const componentFactory = this.componentFactoryResolver.resolveComponentFactory(type)
+ const componentRef = componentFactory.create(this.injector)
+ const tab = componentRef.instance
+ tab.hostView = componentRef.hostView
+ Object.assign(tab, inputs || {})
+ return tab
+ }
+
+ /**
+ * Duplicates an existing tab instance (using the tab recovery system)
+ */
+ async duplicate (tab: BaseTabComponent): Promise {
+ const token = await tab.getRecoveryToken()
+ if (!token) {
+ return null
+ }
+ const dup = await this.tabRecovery.recoverTab(token)
+ if (dup) {
+ return this.create(dup.type, dup.options)
+ }
+ return null
+ }
+}
diff --git a/terminus-core/src/services/themes.service.ts b/terminus-core/src/services/themes.service.ts
index ce5c65db..24edea10 100644
--- a/terminus-core/src/services/themes.service.ts
+++ b/terminus-core/src/services/themes.service.ts
@@ -2,10 +2,11 @@ import { Inject, Injectable } from '@angular/core'
import { ConfigService } from '../services/config.service'
import { Theme } from '../api/theme'
-@Injectable()
+@Injectable({ providedIn: 'root' })
export class ThemesService {
private styleElement: HTMLElement = null
+ /** @hidden */
constructor (
private config: ConfigService,
@Inject(Theme) private themes: Theme[],
@@ -34,7 +35,7 @@ export class ThemesService {
document.querySelector('style#custom-css').innerHTML = this.config.store.appearance.css
}
- applyCurrentTheme (): void {
+ private applyCurrentTheme (): void {
this.applyTheme(this.findCurrentTheme())
}
}
diff --git a/terminus-core/src/services/touchbar.service.ts b/terminus-core/src/services/touchbar.service.ts
index b7bde349..10261200 100644
--- a/terminus-core/src/services/touchbar.service.ts
+++ b/terminus-core/src/services/touchbar.service.ts
@@ -3,12 +3,14 @@ import { TouchBarSegmentedControl, SegmentedControlSegment } from 'electron'
import { AppService } from './app.service'
import { ConfigService } from './config.service'
import { ElectronService } from './electron.service'
-import { HostAppService } from './hostApp.service'
-import { IToolbarButton, ToolbarButtonProvider } from '../api'
+import { HostAppService, Platform } from './hostApp.service'
+import { ToolbarButton, ToolbarButtonProvider } from '../api'
-@Injectable()
+/** @hidden */
+@Injectable({ providedIn: 'root' })
export class TouchbarService {
private tabsSegmentedControl: TouchBarSegmentedControl
+ private buttonsSegmentedControl: TouchBarSegmentedControl
private tabSegments: SegmentedControlSegment[] = []
private nsImageCache: {[id: string]: Electron.NativeImage} = {}
@@ -20,49 +22,88 @@ export class TouchbarService {
private electron: ElectronService,
private zone: NgZone,
) {
- app.tabsChanged$.subscribe(() => this.update())
- app.activeTabChange$.subscribe(() => this.update())
+ if (this.hostApp.platform !== Platform.macOS) {
+ return
+ }
+ app.tabsChanged$.subscribe(() => this.updateTabs())
+ app.activeTabChange$.subscribe(() => this.updateTabs())
+
+ const activityIconPath = `${electron.app.getAppPath()}/assets/activity.png`
+ const activityIcon = this.electron.nativeImage.createFromPath(activityIconPath)
app.tabOpened$.subscribe(tab => {
tab.titleChange$.subscribe(title => {
- this.tabSegments[app.tabs.indexOf(tab)].label = this.shortenTitle(title)
- this.tabsSegmentedControl.segments = this.tabSegments
+ const segment = this.tabSegments[app.tabs.indexOf(tab)]
+ if (segment) {
+ segment.label = this.shortenTitle(title)
+ this.tabsSegmentedControl.segments = this.tabSegments
+ }
+ })
+ tab.activity$.subscribe(hasActivity => {
+ const showIcon = this.app.activeTab !== tab && hasActivity
+ const segment = this.tabSegments[app.tabs.indexOf(tab)]
+ if (segment) {
+ segment.icon = showIcon ? activityIcon : null
+ }
})
})
}
+ updateTabs () {
+ this.tabSegments = this.app.tabs.map(tab => ({
+ label: this.shortenTitle(tab.title),
+ }))
+ this.tabsSegmentedControl.segments = this.tabSegments
+ this.tabsSegmentedControl.selectedIndex = this.app.tabs.indexOf(this.app.activeTab)
+ }
+
update () {
- let buttons: IToolbarButton[] = []
+ if (this.hostApp.platform !== Platform.macOS) {
+ return
+ }
+
+ let buttons: ToolbarButton[] = []
this.config.enabledServices(this.toolbarButtonProviders).forEach(provider => {
buttons = buttons.concat(provider.provide())
})
+ buttons = buttons.filter(x => !!x.touchBarNSImage)
buttons.sort((a, b) => (a.weight || 0) - (b.weight || 0))
this.tabSegments = this.app.tabs.map(tab => ({
label: this.shortenTitle(tab.title),
}))
+
this.tabsSegmentedControl = new this.electron.TouchBar.TouchBarSegmentedControl({
segments: this.tabSegments,
selectedIndex: this.app.tabs.indexOf(this.app.activeTab),
change: (selectedIndex) => this.zone.run(() => {
this.app.selectTab(this.app.tabs[selectedIndex])
- })
+ }),
})
- let touchBar = new this.electron.TouchBar({
+
+ this.buttonsSegmentedControl = new this.electron.TouchBar.TouchBarSegmentedControl({
+ segments: buttons.map(button => this.getButton(button)),
+ mode: 'buttons',
+ change: (selectedIndex) => this.zone.run(() => {
+ buttons[selectedIndex].click()
+ }),
+ })
+
+ const touchBar = new this.electron.TouchBar({
items: [
this.tabsSegmentedControl,
- new this.electron.TouchBar.TouchBarSpacer({size: 'flexible'}),
- new this.electron.TouchBar.TouchBarSpacer({size: 'small'}),
- ...buttons.map(button => this.getButton(button))
- ]
+ new this.electron.TouchBar.TouchBarSpacer({ size: 'flexible' }),
+ new this.electron.TouchBar.TouchBarSpacer({ size: 'small' }),
+ this.buttonsSegmentedControl,
+ ],
})
this.hostApp.setTouchBar(touchBar)
}
- private getButton (button: IToolbarButton): Electron.TouchBarButton {
- return new this.electron.TouchBar.TouchBarButton({
+ private getButton (button: ToolbarButton): Electron.SegmentedControlSegment {
+ return {
label: button.touchBarNSImage ? null : this.shortenTitle(button.touchBarTitle || button.title),
icon: button.touchBarNSImage ? this.getCachedNSImage(button.touchBarNSImage) : null,
- click: () => this.zone.run(() => button.click()),
- })
+ // click: () => this.zone.run(() => button.click()),
+ }
}
private getCachedNSImage (name: string) {
diff --git a/terminus-core/src/services/updater.service.ts b/terminus-core/src/services/updater.service.ts
index 8fa8ac46..1266ebfa 100644
--- a/terminus-core/src/services/updater.service.ts
+++ b/terminus-core/src/services/updater.service.ts
@@ -1,17 +1,19 @@
import axios from 'axios'
-import * as os from 'os'
+
import { Injectable } from '@angular/core'
import { Logger, LogService } from './log.service'
import { ElectronService } from './electron.service'
const UPDATES_URL = 'https://api.github.com/repos/eugeny/terminus/releases/latest'
-@Injectable()
+/** @hidden */
+@Injectable({ providedIn: 'root' })
export class UpdaterService {
private logger: Logger
private downloaded: Promise
- private isSquirrel = true
+ private electronUpdaterAvailable = true
private updateURL: string
+ private autoUpdater
constructor (
log: LogService,
@@ -19,42 +21,37 @@ export class UpdaterService {
) {
this.logger = log.create('updater')
- try {
- electron.autoUpdater.setFeedURL(`https://terminus-updates.herokuapp.com/update/${os.platform()}/${electron.app.getVersion()}`)
- } catch (e) {
- this.isSquirrel = false
- this.logger.info('Squirrel updater unavailable, falling back')
- }
+ this.autoUpdater = electron.remote.require('electron-updater').autoUpdater
- this.electron.autoUpdater.on('update-available', () => {
+ this.autoUpdater.on('update-available', () => {
this.logger.info('Update available')
})
- this.electron.autoUpdater.once('update-not-available', () => {
+ this.autoUpdater.once('update-not-available', () => {
this.logger.info('No updates')
})
this.downloaded = new Promise(resolve => {
- this.electron.autoUpdater.once('update-downloaded', () => resolve(true))
+ this.autoUpdater.once('update-downloaded', () => resolve(true))
})
this.logger.debug('Checking for updates')
- if (this.isSquirrel) {
+ if (this.electronUpdaterAvailable && !process.env.TERMINUS_DEV) {
try {
- this.electron.autoUpdater.checkForUpdates()
+ this.autoUpdater.checkForUpdates()
} catch (e) {
- this.isSquirrel = false
- this.logger.info('Squirrel updater unavailable, falling back')
+ this.electronUpdaterAvailable = false
+ this.logger.info('Electron updater unavailable, falling back', e)
}
}
}
async check (): Promise {
- if (!this.isSquirrel) {
+ if (!this.electronUpdaterAvailable) {
this.logger.debug('Checking for updates')
- let response = await axios.get(UPDATES_URL)
- let data = response.data
- let version = data.tag_name.substring(1)
+ const response = await axios.get(UPDATES_URL)
+ const data = response.data
+ const version = data.tag_name.substring(1)
if (this.electron.app.getVersion() !== version) {
this.logger.info('Update available')
this.updateURL = data.html_url
@@ -67,11 +64,11 @@ export class UpdaterService {
}
async update () {
- if (!this.isSquirrel) {
+ if (!this.electronUpdaterAvailable) {
this.electron.shell.openExternal(this.updateURL)
} else {
await this.downloaded
- this.electron.autoUpdater.quitAndInstall()
+ this.autoUpdater.quitAndInstall()
}
}
}
diff --git a/terminus-core/src/tabContextMenu.ts b/terminus-core/src/tabContextMenu.ts
new file mode 100644
index 00000000..f8894ee7
--- /dev/null
+++ b/terminus-core/src/tabContextMenu.ts
@@ -0,0 +1,147 @@
+import { Injectable, NgZone } from '@angular/core'
+import { AppService } from './services/app.service'
+import { BaseTabComponent } from './components/baseTab.component'
+import { TabHeaderComponent } from './components/tabHeader.component'
+import { TabContextMenuItemProvider } from './api/tabContextMenuProvider'
+
+/** @hidden */
+@Injectable()
+export class CloseContextMenu extends TabContextMenuItemProvider {
+ weight = -5
+
+ constructor (
+ private app: AppService,
+ private zone: NgZone,
+ ) {
+ super()
+ }
+
+ async getItems (tab: BaseTabComponent): Promise {
+ return [
+ {
+ label: 'Close',
+ click: () => this.zone.run(() => {
+ this.app.closeTab(tab, true)
+ }),
+ },
+ {
+ label: 'Close other tabs',
+ click: () => this.zone.run(() => {
+ for (const t of this.app.tabs.filter(x => x !== tab)) {
+ this.app.closeTab(t, true)
+ }
+ }),
+ },
+ {
+ label: 'Close tabs to the right',
+ click: () => this.zone.run(() => {
+ for (const t of this.app.tabs.slice(this.app.tabs.indexOf(tab) + 1)) {
+ this.app.closeTab(t, true)
+ }
+ }),
+ },
+ {
+ label: 'Close tabs to the left',
+ click: () => this.zone.run(() => {
+ for (const t of this.app.tabs.slice(0, this.app.tabs.indexOf(tab))) {
+ this.app.closeTab(t, true)
+ }
+ }),
+ },
+ ]
+ }
+}
+
+const COLORS = [
+ { name: 'No color', value: null },
+ { name: 'Blue', value: '#0275d8' },
+ { name: 'Green', value: '#5cb85c' },
+ { name: 'Orange', value: '#f0ad4e' },
+ { name: 'Purple', value: '#613d7c' },
+ { name: 'Red', value: '#d9534f' },
+ { name: 'Yellow', value: '#ffd500' },
+]
+
+/** @hidden */
+@Injectable()
+export class CommonOptionsContextMenu extends TabContextMenuItemProvider {
+ weight = -1
+
+ constructor (
+ private zone: NgZone,
+ private app: AppService,
+ ) {
+ super()
+ }
+
+ async getItems (tab: BaseTabComponent, tabHeader?: TabHeaderComponent): Promise {
+ return [
+ {
+ 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,
+ submenu: COLORS.map(color => ({
+ label: color.name,
+ type: 'radio',
+ checked: tab.color === color.value,
+ click: () => this.zone.run(() => {
+ tab.color = color.value
+ }),
+ })) as Electron.MenuItemConstructorOptions[],
+ },
+ ]
+ }
+}
+
+/** @hidden */
+@Injectable()
+export class TaskCompletionContextMenu extends TabContextMenuItemProvider {
+ constructor (
+ private app: AppService,
+ private zone: NgZone,
+ ) {
+ super()
+ }
+
+ async getItems (tab: BaseTabComponent): Promise {
+ const process = await tab.getCurrentProcess()
+ if (process) {
+ return [
+ {
+ id: 'process-name',
+ enabled: false,
+ label: 'Current process: ' + process.name,
+ },
+ {
+ label: 'Notify when done',
+ type: 'checkbox',
+ checked: (tab as any).__completionNotificationEnabled,
+ click: () => this.zone.run(() => {
+ (tab as any).__completionNotificationEnabled = !(tab as any).__completionNotificationEnabled
+
+ if ((tab as any).__completionNotificationEnabled) {
+ this.app.observeTabCompletion(tab).subscribe(() => {
+ new Notification('Process completed', {
+ body: process.name,
+ }).addEventListener('click', () => {
+ this.app.selectTab(tab)
+ })
+ ;(tab as any).__completionNotificationEnabled = false
+ })
+ } else {
+ this.app.stopObservingTabCompletion(tab)
+ }
+ }),
+ },
+ ]
+ }
+ return []
+ }
+}
diff --git a/terminus-core/src/theme.compact.scss b/terminus-core/src/theme.compact.scss
index 4d9297ba..db058e4f 100644
--- a/terminus-core/src/theme.compact.scss
+++ b/terminus-core/src/theme.compact.scss
@@ -6,6 +6,10 @@ app-root {
.btn-tab-bar {
line-height: 29px !important;
+
+ svg {
+ height: 14px;
+ }
}
}
diff --git a/terminus-core/src/theme.scss b/terminus-core/src/theme.scss
index f95f4907..3ea37c9f 100644
--- a/terminus-core/src/theme.scss
+++ b/terminus-core/src/theme.scss
@@ -51,12 +51,13 @@ $input-disabled-bg: #333;
$input-color: $body-color;
$input-color-placeholder: #333;
$input-border-color: #344;
+$input-border-width: 1px;
//$input-box-shadow: inset 0 1px 1px rgba($black,.075);
$input-border-radius: 0;
$custom-select-border-radius: 0;
$input-bg-focus: $input-bg;
-//$input-border-focus: lighten($brand-primary, 25%);
-//$input-box-shadow-focus: $input-box-shadow, rgba($input-border-focus, .6);
+$input-border-focus: lighten($blue, 25%);
+$input-focus-box-shadow: none;
$input-color-focus: $input-color;
$input-group-addon-bg: $body-bg;
$input-group-addon-border-color: $input-border-color;
@@ -70,7 +71,7 @@ $popover-bg: $body-bg;
$dropdown-bg: $body-bg;
$dropdown-link-color: $body-color;
-$dropdown-link-hover-color: #333;
+$dropdown-link-hover-color: white;
$dropdown-link-hover-bg: $body-bg2;
//$dropdown-link-active-color: $component-active-color;
//$dropdown-link-active-bg: $component-active-bg;
@@ -135,6 +136,10 @@ app-root {
background: transparent;
&:hover { background: rgba(0, 0, 0, .25) !important; }
&:active { background: rgba(0, 0, 0, .5) !important; }
+
+ &::after {
+ display: none;
+ }
}
&>.tabs {
@@ -346,6 +351,15 @@ ngb-tabset .tab-content {
}
}
+.list-group.list-group-flush .list-group-item:not(.list-group-item-action) {
+ background: transparent;
+ border-color: rgba(0, 0, 0, 0.2);
+
+ &:not(:last-child) {
+ border-bottom: none;
+ }
+}
+
select.form-control {
-webkit-appearance: none;
background-image: url("data:image/svg+xml;utf8, ");
@@ -362,6 +376,15 @@ toggle.active .body .toggle {
background: $blue;
}
+.modal .modal-footer {
+ background: rgba(0, 0, 0, .25);
+
+ .btn {
+ font-weight: bold;
+ padding: 0.375rem 1.5rem;
+ }
+}
+
.list-group-item svg {
fill: white;
fill-opacity: 0.75;
diff --git a/terminus-core/src/theme.ts b/terminus-core/src/theme.ts
index 327051d6..eeba75a4 100644
--- a/terminus-core/src/theme.ts
+++ b/terminus-core/src/theme.ts
@@ -1,23 +1,26 @@
import { Injectable } from '@angular/core'
import { Theme } from './api'
+/** @hidden */
@Injectable()
export class StandardTheme extends Theme {
name = 'Standard'
css = require('./theme.scss')
- terminalBackground = '#1D272D'
+ terminalBackground = '#222a33'
}
+/** @hidden */
@Injectable()
export class StandardCompactTheme extends Theme {
name = 'Compact'
css = require('./theme.compact.scss')
- terminalBackground = '#1D272D'
+ terminalBackground = '#222a33'
}
+/** @hidden */
@Injectable()
export class PaperTheme extends Theme {
name = 'Paper'
css = require('./theme.paper.scss')
- terminalBackground = '#1D272D'
+ terminalBackground = '#f7f1e0'
}
diff --git a/terminus-core/tsconfig.json b/terminus-core/tsconfig.json
index 1d6cfcbf..286cc9cd 100644
--- a/terminus-core/tsconfig.json
+++ b/terminus-core/tsconfig.json
@@ -2,7 +2,6 @@
"extends": "../tsconfig.json",
"exclude": ["node_modules", "dist"],
"compilerOptions": {
- "baseUrl": "src",
- "declarationDir": "dist"
+ "baseUrl": "src"
}
}
diff --git a/terminus-core/tsconfig.typings.json b/terminus-core/tsconfig.typings.json
new file mode 100644
index 00000000..c0d2273c
--- /dev/null
+++ b/terminus-core/tsconfig.typings.json
@@ -0,0 +1,14 @@
+{
+ "extends": "../tsconfig.json",
+ "exclude": ["node_modules", "dist", "typings"],
+ "compilerOptions": {
+ "baseUrl": "src",
+ "emitDeclarationOnly": true,
+ "declaration": true,
+ "declarationDir": "./typings",
+ "paths": {
+ "terminus-*": ["../../terminus-*"],
+ "*": ["../../app/node_modules/*"]
+ }
+ }
+}
diff --git a/terminus-core/webpack.config.js b/terminus-core/webpack.config.js
index 05e01711..294ac4e1 100644
--- a/terminus-core/webpack.config.js
+++ b/terminus-core/webpack.config.js
@@ -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,
},
@@ -51,10 +51,7 @@ module.exports = {
'fs',
'os',
'path',
- 'deepmerge',
- 'untildify',
- 'winston',
- 'js-yaml',
+ 'windows-native-registry',
/^rxjs/,
/^@angular/,
/^@ng-bootstrap/,
diff --git a/terminus-core/yarn.lock b/terminus-core/yarn.lock
index bdf27b89..04b1567c 100644
--- a/terminus-core/yarn.lock
+++ b/terminus-core/yarn.lock
@@ -3,36 +3,38 @@
"@types/js-yaml@^3.9.0":
- version "3.9.1"
- resolved "https://registry.yarnpkg.com/@types/js-yaml/-/js-yaml-3.9.1.tgz#2f3c142771bb345829ce690c5838760b6b9ba553"
- integrity sha512-6ejot8/A47YhEGg8K/Gi+/Nu4vohMgxEG383aBaHKjrGjJUQE7umk+vg5I7TaPe4C99nUZrCDw+weK3M7gg/oA==
+ version "3.12.1"
+ resolved "https://registry.yarnpkg.com/@types/js-yaml/-/js-yaml-3.12.1.tgz#5c6f4a1eabca84792fbd916f0cb40847f123c656"
+ integrity sha512-SGGAhXLHDx+PK4YLNcNGa6goPf9XRWQNAUUbffkwVGGXIxmDKWyGGL4inzq2sPmExu431Ekb9aEMn9BkPqEYFA==
-"@types/node@*", "@types/node@^7.0.37":
- version "7.0.43"
- resolved "https://registry.yarnpkg.com/@types/node/-/node-7.0.43.tgz#a187e08495a075f200ca946079c914e1a5fe962c"
- integrity sha512-7scYwwfHNppXvH/9JzakbVxk0o0QUILVk1Lv64GRaxwPuGpnF1QBiwdvhDpLcymb8BpomQL3KYoWKq3wUdDMhQ==
+"@types/node@^12.0.2":
+ version "12.0.10"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-12.0.10.tgz#51babf9c7deadd5343620055fc8aff7995c8b031"
+ integrity sha512-LcsGbPomWsad6wmMNv7nBLw7YYYyfdYcz6xryKYQhx89c3XXan+8Q6AJ43G5XDIaklaVkK3mE4fCb0SBvMiPSQ==
+
+"@types/shell-escape@^0.2.0":
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/@types/shell-escape/-/shell-escape-0.2.0.tgz#cd2f0df814388599dd07196dcc510de2669d1ed2"
+ integrity sha512-7kUdtJtUylvyISJbe9FMcvMTjRdP0EvNDO1WbT0lT22k/IPBiPRTpmWaKu5HTWLCGLQRWVHrzVHZktTDvvR23g==
"@types/webpack-env@^1.13.0":
- version "1.13.1"
- resolved "https://registry.yarnpkg.com/@types/webpack-env/-/webpack-env-1.13.1.tgz#b45c222e24301bd006e3edfc762cc6b51bda236a"
- integrity sha512-oHyg0NssP2RCpCvE35hhbSqMJRsc5lSW+GFe+Vc65JL+kHII1VMYM+0KeV/z4utFuUqPoQRmq8KMMp7ba0dj6Q==
+ version "1.13.9"
+ resolved "https://registry.yarnpkg.com/@types/webpack-env/-/webpack-env-1.13.9.tgz#a67287861c928ebf4159a908d1fb1a2a34d4097a"
+ integrity sha512-p8zp5xqkly3g4cCmo2mKOHI9+Z/kObmDj0BmjbDDJQlgDTiEGTbm17MEwTAusV6XceCy+bNw9q/ZHXHyKo3zkg==
"@types/winston@^2.3.6":
- version "2.3.6"
- resolved "https://registry.yarnpkg.com/@types/winston/-/winston-2.3.6.tgz#0f0954b9e16abd40598dc6e9cc2ea43044237997"
- integrity sha512-gZsUc53u4JHqt5nvfgTnjNP1SkzDmDtY7eZz/8WUFL43Pp8KMR+g8LiHjslwLLheIS/hfGH55QW4tJVjNwYh/Q==
+ version "2.4.4"
+ resolved "https://registry.yarnpkg.com/@types/winston/-/winston-2.4.4.tgz#48cc744b7b42fad74b9a2e8490e0112bd9a3d08d"
+ integrity sha512-BVGCztsypW8EYwJ+Hq+QNYiT/MUyCif0ouBH+flrY66O5W+KIXAMML6E/0fJpm7VjIzgangahl5S03bJJQGrZw==
dependencies:
- "@types/node" "*"
+ winston "*"
-ajv@^5.1.0:
- version "5.5.2"
- resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965"
- integrity sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=
+agent-base@^4.1.0:
+ version "4.2.1"
+ resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.2.1.tgz#d89e5999f797875674c07d87f260fc41e83e8ca9"
+ integrity sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==
dependencies:
- co "^4.6.0"
- fast-deep-equal "^1.0.0"
- fast-json-stable-stringify "^2.0.0"
- json-schema-traverse "^0.3.0"
+ es6-promisify "^5.0.0"
argparse@^1.0.7:
version "1.0.9"
@@ -41,413 +43,335 @@ argparse@^1.0.7:
dependencies:
sprintf-js "~1.0.2"
-asn1@~0.2.3:
- version "0.2.4"
- resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136"
- integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==
+async@^2.6.1:
+ version "2.6.2"
+ resolved "https://registry.yarnpkg.com/async/-/async-2.6.2.tgz#18330ea7e6e313887f5d2f2a904bac6fe4dd5381"
+ integrity sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==
dependencies:
- safer-buffer "~2.1.0"
+ lodash "^4.17.11"
-assert-plus@1.0.0, assert-plus@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525"
- integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=
-
-async@~1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/async/-/async-1.0.0.tgz#f8fc04ca3a13784ade9e1641af98578cfbd647a9"
- integrity sha1-+PwEyjoTeErenhZBr5hXjPvWR6k=
-
-asynckit@^0.4.0:
- version "0.4.0"
- resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
- integrity sha1-x57Zf380y48robyXkLzDZkdLS3k=
-
-aws-sign2@~0.7.0:
- version "0.7.0"
- resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8"
- integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=
-
-aws4@^1.6.0:
- version "1.8.0"
- resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f"
- integrity sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==
-
-axios@^0.18.0:
- version "0.18.0"
- resolved "https://registry.yarnpkg.com/axios/-/axios-0.18.0.tgz#32d53e4851efdc0a11993b6cd000789d70c05102"
- integrity sha1-MtU+SFHv3AoRmTts0AB4nXDAUQI=
+axios@^0.19.0:
+ version "0.19.0"
+ resolved "https://registry.yarnpkg.com/axios/-/axios-0.19.0.tgz#8e09bff3d9122e133f7b8101c8fbdd00ed3d2ab8"
+ integrity sha512-1uvKqKQta3KBxIz14F2v06AEHZ/dIoeKfbTRkK1E5oqjDnuEerLmYTgJB5AiQZHJcljpg1TuRzdjDR06qNk0DQ==
dependencies:
- follow-redirects "^1.3.0"
- is-buffer "^1.1.5"
+ follow-redirects "1.5.10"
+ is-buffer "^2.0.2"
-bcrypt-pbkdf@^1.0.0:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e"
- integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=
+bluebird-lst@^1.0.6, bluebird-lst@^1.0.7:
+ version "1.0.8"
+ resolved "https://registry.yarnpkg.com/bluebird-lst/-/bluebird-lst-1.0.8.tgz#61b572e8b3eb57e0fff676a0e54566d93597e6a4"
+ integrity sha512-InUDOaBaIjIobOa3O4YRAbFgff907uTJZXW0m0rhk3zhVZ4GvsmdCLEAKC1CTWTtUWCM8iWTTfFX9N/xQR/etw==
dependencies:
- tweetnacl "^0.14.3"
+ bluebird "^3.5.4"
-bluebird-lst@^1.0.2, bluebird-lst@^1.0.3:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/bluebird-lst/-/bluebird-lst-1.0.3.tgz#cc56c18660eff0a0b86e2c33d1659618f7005158"
- integrity sha512-NKk/GQk5fXcLKt4USI1htGuMwXHhKLa2a32FCNBFAOcpL0k8U5yFpusr3+NKc6RjytL8umW5pSQmtJCWWhiLrQ==
- dependencies:
- bluebird "^3.5.0"
-
-bluebird@^3.5.0:
- version "3.5.0"
- resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.0.tgz#791420d7f551eea2897453a8a77653f96606d67c"
- integrity sha1-eRQg1/VR7qKJdFOop3ZT+WYG1nw=
-
-boom@4.x.x:
- version "4.3.1"
- resolved "https://registry.yarnpkg.com/boom/-/boom-4.3.1.tgz#4f8a3005cb4a7e3889f749030fd25b96e01d2e31"
- integrity sha1-T4owBctKfjiJ90kDD9JbluAdLjE=
- dependencies:
- hoek "4.x.x"
-
-boom@5.x.x:
- version "5.2.0"
- resolved "https://registry.yarnpkg.com/boom/-/boom-5.2.0.tgz#5dd9da6ee3a5f302077436290cb717d3f4a54e02"
- integrity sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==
- dependencies:
- hoek "4.x.x"
+bluebird@^3.5.4:
+ version "3.5.5"
+ resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.5.tgz#a8d0afd73251effbbd5fe384a77d73003c17a71f"
+ integrity sha512-5am6HnnfN+urzt4yfg7IgTbotDjIT/u8AJpEt0sIU9FtXfVeezXAPKswrG+xKUCOYAINpSdgZVDU6QFh+cuH3w==
bootstrap@^4.1.3:
- version "4.1.3"
- resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-4.1.3.tgz#0eb371af2c8448e8c210411d0cb824a6409a12be"
- integrity sha512-rDFIzgXcof0jDyjNosjv4Sno77X4KuPeFxG2XZZv1/Kc8DRVGVADdoQyyOVDwPqL36DDmtCQbrpMCqvpPLJQ0w==
+ version "4.3.1"
+ resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-4.3.1.tgz#280ca8f610504d99d7b6b4bfc4b68cec601704ac"
+ integrity sha512-rXqOmH1VilAt2DyPzluTi2blhk17bO7ef+zLLPlWvG494pDxcM234pJ8wTc/6R40UWizAIIMgxjvxZg5kmsbag==
-caseless@~0.12.0:
- version "0.12.0"
- resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
- integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=
+buffer-from@^1.0.0:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
+ integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==
-co@^4.6.0:
- version "4.6.0"
- resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184"
- integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=
-
-colors@1.0.x:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b"
- integrity sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=
-
-combined-stream@1.0.6, combined-stream@~1.0.5:
- version "1.0.6"
- resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.6.tgz#723e7df6e801ac5613113a7e445a9b69cb632818"
- integrity sha1-cj599ugBrFYTETp+RFqbactjKBg=
+builder-util-runtime@~8.1.0:
+ version "8.1.1"
+ resolved "https://registry.yarnpkg.com/builder-util-runtime/-/builder-util-runtime-8.1.1.tgz#f2f6fc43e33d26892bd491667fc746ad69bccc50"
+ integrity sha512-+ieS4PMB33vVE2S3ZNWBEQJ1zKmAs/agrBdh7XadE1lKLjrH4aXYuOh9OOGdxqIRldhlhNBaF+yKMMEFOdNVig==
dependencies:
- delayed-stream "~1.0.0"
+ bluebird-lst "^1.0.6"
+ debug "^4.1.1"
+ fs-extra-p "^7.0.0"
+ sax "^1.2.4"
-core-js@^2.4.1:
- version "2.5.1"
- resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.1.tgz#ae6874dc66937789b80754ff5428df66819ca50b"
- integrity sha1-rmh03GaTd4m4B1T/VCjfZoGcpQs=
+color-convert@^1.9.1:
+ version "1.9.3"
+ resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
+ integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==
+ dependencies:
+ color-name "1.1.3"
-core-util-is@1.0.2:
+color-name@1.1.3:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
+ integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=
+
+color-name@^1.0.0:
+ version "1.1.4"
+ resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
+ integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
+
+color-string@^1.5.2:
+ version "1.5.3"
+ resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.5.3.tgz#c9bbc5f01b58b5492f3d6857459cb6590ce204cc"
+ integrity sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw==
+ dependencies:
+ color-name "^1.0.0"
+ simple-swizzle "^0.2.2"
+
+color@3.0.x:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/color/-/color-3.0.0.tgz#d920b4328d534a3ac8295d68f7bd4ba6c427be9a"
+ integrity sha512-jCpd5+s0s0t7p3pHQKpnJ0TpQKKdleP71LWcA0aqiljpiuAkOSUFN/dyH8ZwF0hRmFlrIuRhufds1QyEP9EB+w==
+ dependencies:
+ color-convert "^1.9.1"
+ color-string "^1.5.2"
+
+colornames@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/colornames/-/colornames-1.1.1.tgz#f8889030685c7c4ff9e2a559f5077eb76a816f96"
+ integrity sha1-+IiQMGhcfE/54qVZ9Qd+t2qBb5Y=
+
+colors@^1.2.1:
+ version "1.3.3"
+ resolved "https://registry.yarnpkg.com/colors/-/colors-1.3.3.tgz#39e005d546afe01e01f9c4ca8fa50f686a01205d"
+ integrity sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg==
+
+colorspace@1.1.x:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/colorspace/-/colorspace-1.1.2.tgz#e0128950d082b86a2168580796a0aa5d6c68d8c5"
+ integrity sha512-vt+OoIP2d76xLhjwbBaucYlNSpPsrJWPlBTtwCpQKIu6/CSMutyzX93O/Do0qzpH3YoHEes8YEFXyZ797rEhzQ==
+ dependencies:
+ color "3.0.x"
+ text-hex "1.0.x"
+
+core-js@^3.1.2:
+ version "3.1.4"
+ resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.1.4.tgz#3a2837fc48e582e1ae25907afcd6cf03b0cc7a07"
+ integrity sha512-YNZN8lt82XIMLnLirj9MhKDFZHalwzzrL9YLt6eb0T5D0EDl4IQ90IGkua8mHbnxNrkj1d8hbdizMc0Qmg1WnQ==
+
+core-util-is@~1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
-cryptiles@3.x.x:
- version "3.1.2"
- resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-3.1.2.tgz#a89fbb220f5ce25ec56e8c4aa8a4fd7b5b0d29fe"
- integrity sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4=
- dependencies:
- boom "5.x.x"
-
-cycle@1.0.x:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/cycle/-/cycle-1.0.3.tgz#21e80b2be8580f98b468f379430662b046c34ad2"
- integrity sha1-IegLK+hYD5i0aPN5QwZisEbDStI=
-
-dashdash@^1.12.0:
- version "1.14.1"
- resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0"
- integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=
- dependencies:
- assert-plus "^1.0.0"
-
-debug@=3.1.0, debug@^3.0.0:
+debug@=3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==
dependencies:
ms "2.0.0"
-debug@^3.0.1:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/debug/-/debug-3.0.1.tgz#0564c612b521dc92d9f2988f0549e34f9c98db64"
- integrity sha512-6nVc6S36qbt/mutyt+UGMnawAMrPDZUPQjRZI3FS9tCtDRhvxJbK79unYBLPi+z5SLXQ3ftoVBFCblQtNSls8w==
+debug@^3.1.0:
+ version "3.2.6"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b"
+ integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==
dependencies:
- ms "2.0.0"
+ ms "^2.1.1"
-deepmerge@^1.5.0:
- version "1.5.1"
- resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-1.5.1.tgz#c053bf06fd7276f1994f70c09a0760cb61a56237"
- integrity sha512-Ndl8eeOHB9dQkmT1HWCgY3t0odl4bmWKFzjQZBYAxVTNs2B3nn5b6orimRYHKZ4FI8psvZkA1INRCW6l7vc9lQ==
-
-delayed-stream@~1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
- integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk=
-
-ecc-jsbn@~0.1.1:
- version "0.1.2"
- resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9"
- integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=
+debug@^4.1.1:
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791"
+ integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==
dependencies:
- jsbn "~0.1.0"
- safer-buffer "^2.1.0"
+ ms "^2.1.1"
-electron-builder-http@~19.27.5:
- version "19.27.5"
- resolved "https://registry.yarnpkg.com/electron-builder-http/-/electron-builder-http-19.27.5.tgz#800865df2e618ffab9e5b3b895c15b4ce7fd7f17"
- integrity sha512-irxaEueAp+5GP8n2dLCh6scR4aE9+7IzEwAQ/R++U1rg1ADgsmhTOAx+Glt/u3tMzz7X8cM60P+tMtXyz1VfiQ==
+deepmerge@^3.2.0:
+ version "3.2.1"
+ resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-3.2.1.tgz#76a1f47854bcfcd66ee9a948d110540a8e12b261"
+ integrity sha512-+hbDSzTqEW0fWgnlKksg7XAOtT+ddZS5lHZJ6f6MdixRs9wQy+50fm1uUCVb1IkvjLUYX/SfFO021ZNwriURTw==
+
+diagnostics@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/diagnostics/-/diagnostics-1.1.1.tgz#cab6ac33df70c9d9a727490ae43ac995a769b22a"
+ integrity sha512-8wn1PmdunLJ9Tqbx+Fx/ZEuHfJf4NKSN2ZBj7SJC/OWRWha843+WsTjqMe1B5E3p28jqBlp+mJ2fPVxPyNgYKQ==
dependencies:
- bluebird-lst "^1.0.3"
- debug "^3.0.1"
- fs-extra-p "^4.4.0"
+ colorspace "1.1.x"
+ enabled "1.0.x"
+ kuler "1.0.x"
-electron-is-dev@^0.3.0:
- version "0.3.0"
- resolved "https://registry.yarnpkg.com/electron-is-dev/-/electron-is-dev-0.3.0.tgz#14e6fda5c68e9e4ecbeff9ccf037cbd7c05c5afe"
- integrity sha1-FOb9pcaOnk7L7/nM8DfL18BcWv4=
-
-electron-updater@^2.8.9:
- version "2.8.9"
- resolved "https://registry.yarnpkg.com/electron-updater/-/electron-updater-2.8.9.tgz#e2525dcbd7c27ff173bdfd2e87056d67310e2555"
- integrity sha512-ZlNBaznkhGO/fxPPEK3r+rzCch6ULrgecTRJsYu2cFkX4oS5AFfL5dndw1EpZzKIOHYYIEUSjZ5FpI3FCHit2Q==
+electron-updater@^4.0.6:
+ version "4.0.6"
+ resolved "https://registry.yarnpkg.com/electron-updater/-/electron-updater-4.0.6.tgz#9c4f495ae0e80bf4425e3e1b801c5ed2ab933c2d"
+ integrity sha512-JPGLME6fxJcHG8hX7HWFl6Aew6iVm0DkcrENreKa5SUJCHG+uUaAhxDGDt+YGcNkyx1uJ6eBGMvFxDTLUv67pg==
dependencies:
- bluebird-lst "^1.0.3"
- debug "^3.0.1"
- electron-builder-http "~19.27.5"
- electron-is-dev "^0.3.0"
- fs-extra-p "^4.4.0"
- js-yaml "^3.9.1"
- lazy-val "^1.0.2"
+ bluebird-lst "^1.0.6"
+ builder-util-runtime "~8.1.0"
+ fs-extra-p "^7.0.0"
+ js-yaml "^3.12.0"
+ lazy-val "^1.0.3"
lodash.isequal "^4.5.0"
- semver "^5.4.1"
- source-map-support "^0.4.16"
- uuid-1345 "^0.99.6"
- xelement "^1.0.16"
+ pako "^1.0.7"
+ semver "^5.6.0"
+ source-map-support "^0.5.9"
+
+enabled@1.0.x:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/enabled/-/enabled-1.0.2.tgz#965f6513d2c2d1c5f4652b64a2e3396467fc2f93"
+ integrity sha1-ll9lE9LC0cX0ZStkouM5ZGf8L5M=
+ dependencies:
+ env-variable "0.0.x"
+
+env-variable@0.0.x:
+ version "0.0.5"
+ resolved "https://registry.yarnpkg.com/env-variable/-/env-variable-0.0.5.tgz#913dd830bef11e96a039c038d4130604eba37f88"
+ integrity sha512-zoB603vQReOFvTg5xMl9I1P2PnHsHQQKTEowsKKD7nseUfJq6UWzK+4YtlWUO1nhiQUxe6XMkk+JleSZD1NZFA==
+
+es6-promise@^4.0.3:
+ version "4.2.6"
+ resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.6.tgz#b685edd8258886365ea62b57d30de28fadcd974f"
+ integrity sha512-aRVgGdnmW2OiySVPUC9e6m+plolMAJKjZnQlCwNSuK5yQ0JN61DZSO1X1Ufd1foqWRAlig0rhduTCHe7sVtK5Q==
+
+es6-promisify@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203"
+ integrity sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=
+ dependencies:
+ es6-promise "^4.0.3"
esprima@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.0.tgz#4499eddcd1110e0b218bacf2fa7f7f59f55ca804"
integrity sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==
-extend@~3.0.1:
- version "3.0.2"
- resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
- integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==
+fast-safe-stringify@^2.0.4:
+ version "2.0.6"
+ resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.0.6.tgz#04b26106cc56681f51a044cfc0d76cf0008ac2c2"
+ integrity sha512-q8BZ89jjc+mz08rSxROs8VsrBBcn1SIw1kq9NjolL509tkABRk9io01RAjSaEv1Xb2uFLt8VtRiZbGp5H8iDtg==
-extsprintf@1.3.0:
- version "1.3.0"
- resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05"
- integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=
+fecha@^2.3.3:
+ version "2.3.3"
+ resolved "https://registry.yarnpkg.com/fecha/-/fecha-2.3.3.tgz#948e74157df1a32fd1b12c3a3c3cdcb6ec9d96cd"
+ integrity sha512-lUGBnIamTAwk4znq5BcqsDaxSmZ9nDVJaij6NvRt/Tg4R69gERA+otPKbS86ROw9nxVMw2/mp1fnaiWqbs6Sdg==
-extsprintf@^1.2.0:
- version "1.4.0"
- resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f"
- integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8=
-
-eyes@0.1.x:
- version "0.1.8"
- resolved "https://registry.yarnpkg.com/eyes/-/eyes-0.1.8.tgz#62cf120234c683785d902348a800ef3e0cc20bc0"
- integrity sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A=
-
-fast-deep-equal@^1.0.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz#c053477817c86b51daa853c81e059b733d023614"
- integrity sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=
-
-fast-json-stable-stringify@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2"
- integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I=
-
-follow-redirects@^1.3.0:
+follow-redirects@1.5.10:
version "1.5.10"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.5.10.tgz#7b7a9f9aea2fdff36786a94ff643ed07f4ff5e2a"
integrity sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==
dependencies:
debug "=3.1.0"
-forever-agent@~0.6.1:
- version "0.6.1"
- resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
- integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=
-
-form-data@~2.3.1:
- version "2.3.2"
- resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.2.tgz#4970498be604c20c005d4f5c23aecd21d6b49099"
- integrity sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=
+fs-extra-p@^7.0.0:
+ version "7.0.1"
+ resolved "https://registry.yarnpkg.com/fs-extra-p/-/fs-extra-p-7.0.1.tgz#4eec0b6dfa150fa90f6ddd773b4fb1d55cad54e3"
+ integrity sha512-yhd2OV0HnHt2oitlp+X9hl2ReX4X/7kQeL7/72qzPHTZj5eUPGzAKOvEglU02Fa1OeG2rSy/aKB4WGVaLiF8tw==
dependencies:
- asynckit "^0.4.0"
- combined-stream "1.0.6"
- mime-types "^2.1.12"
+ bluebird-lst "^1.0.7"
+ fs-extra "^7.0.1"
-fs-extra-p@^4.4.0:
- version "4.4.0"
- resolved "https://registry.yarnpkg.com/fs-extra-p/-/fs-extra-p-4.4.0.tgz#729c601c4f4c701328921adc7cfe9b236f100660"
- integrity sha512-SDAF7Ma08/ERKmbNHBvoaxxox33/xiomZGhJlxoSaGYGn7jHCwLTFRnJ82wxrylZa+h0TtkBrrtXzRO79p3AHQ==
- dependencies:
- bluebird-lst "^1.0.2"
- fs-extra "^4.0.0"
-
-fs-extra@^4.0.0:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.1.tgz#7fc0c6c8957f983f57f306a24e5b9ddd8d0dd880"
- integrity sha1-f8DGyJV/mD9X8waiTlud3Y0N2IA=
+fs-extra@^7.0.1:
+ version "7.0.1"
+ resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9"
+ integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==
dependencies:
graceful-fs "^4.1.2"
- jsonfile "^3.0.0"
+ jsonfile "^4.0.0"
universalify "^0.1.0"
-getpass@^0.1.1:
- version "0.1.7"
- resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa"
- integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=
- dependencies:
- assert-plus "^1.0.0"
-
graceful-fs@^4.1.2, graceful-fs@^4.1.6:
version "4.1.11"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658"
integrity sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=
-har-schema@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92"
- integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=
-
-har-validator@~5.0.3:
- version "5.0.3"
- resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.0.3.tgz#ba402c266194f15956ef15e0fcf242993f6a7dfd"
- integrity sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=
+https-proxy-agent@2.2.1:
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz#51552970fa04d723e04c56d04178c3f92592bbc0"
+ integrity sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ==
dependencies:
- ajv "^5.1.0"
- har-schema "^2.0.0"
+ agent-base "^4.1.0"
+ debug "^3.1.0"
-hawk@~6.0.2:
- version "6.0.2"
- resolved "https://registry.yarnpkg.com/hawk/-/hawk-6.0.2.tgz#af4d914eb065f9b5ce4d9d11c1cb2126eecc3038"
- integrity sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ==
- dependencies:
- boom "4.x.x"
- cryptiles "3.x.x"
- hoek "4.x.x"
- sntp "2.x.x"
+inherits@^2.0.3, inherits@~2.0.3:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
+ integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
-hoek@4.x.x:
- version "4.2.1"
- resolved "https://registry.yarnpkg.com/hoek/-/hoek-4.2.1.tgz#9634502aa12c445dd5a7c5734b572bb8738aacbb"
- integrity sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA==
+is-arrayish@^0.3.1:
+ version "0.3.2"
+ resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03"
+ integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==
-http-signature@~1.2.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1"
- integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=
- dependencies:
- assert-plus "^1.0.0"
- jsprim "^1.2.2"
- sshpk "^1.7.0"
+is-buffer@^2.0.2:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.3.tgz#4ecf3fcf749cbd1e472689e109ac66261a25e725"
+ integrity sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw==
-is-buffer@^1.1.5:
- version "1.1.6"
- resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
- integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==
+is-stream@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
+ integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ=
-is-typedarray@~1.0.0:
+isarray@~1.0.0:
version "1.0.0"
- resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
- integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=
+ resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
+ integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=
-isstream@0.1.x, isstream@~0.1.2:
- version "0.1.2"
- resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
- integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=
-
-js-yaml@^3.9.0, js-yaml@^3.9.1:
- version "3.9.1"
- resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.9.1.tgz#08775cebdfdd359209f0d2acd383c8f86a6904a0"
- integrity sha512-CbcG379L1e+mWBnLvHWWeLs8GyV/EMw862uLI3c+GxVyDHWZcjZinwuBd3iW2pgxgIlksW/1vNJa4to+RvDOww==
+js-yaml@^3.12.0, js-yaml@^3.9.0:
+ version "3.13.1"
+ resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847"
+ integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==
dependencies:
argparse "^1.0.7"
esprima "^4.0.0"
-jsbn@~0.1.0:
- version "0.1.1"
- resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
- integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM=
-
-json-schema-traverse@^0.3.0:
- version "0.3.1"
- resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340"
- integrity sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=
-
-json-schema@0.2.3:
- version "0.2.3"
- resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13"
- integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=
-
-json-stringify-safe@~5.0.1:
- version "5.0.1"
- resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
- integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=
-
-jsonfile@^3.0.0:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-3.0.1.tgz#a5ecc6f65f53f662c4415c7675a0331d0992ec66"
- integrity sha1-pezG9l9T9mLEQVx2daAzHQmS7GY=
+jsonfile@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb"
+ integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=
optionalDependencies:
graceful-fs "^4.1.6"
-jsprim@^1.2.2:
- version "1.4.1"
- resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2"
- integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=
+kuler@1.0.x:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/kuler/-/kuler-1.0.1.tgz#ef7c784f36c9fb6e16dd3150d152677b2b0228a6"
+ integrity sha512-J9nVUucG1p/skKul6DU3PUZrhs0LPulNaeUOox0IyXDi8S4CztTHs1gQphhuZmzXG7VOQSf6NJfKuzteQLv9gQ==
dependencies:
- assert-plus "1.0.0"
- extsprintf "1.3.0"
- json-schema "0.2.3"
- verror "1.10.0"
+ colornames "^1.1.1"
-lazy-val@^1.0.2:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/lazy-val/-/lazy-val-1.0.2.tgz#d9b07fb1fce54cbc99b3c611de431b83249369b6"
- integrity sha512-2BaSu6qVnicKdWQPysrffZVFAKcPcZQ/q2YyeSjAxWaJlvCvKSrkcvsSHlleeIfA//fW2goTcYDTy2cBLN7+PQ==
+lazy-val@^1.0.3:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/lazy-val/-/lazy-val-1.0.4.tgz#882636a7245c2cfe6e0a4e3ba6c5d68a137e5c65"
+ integrity sha512-u93kb2fPbIrfzBuLjZE+w+fJbUUMhNDXxNmMfaqNgpfQf1CO5ZSe2LfsnBqVAk7i/2NF48OSoRj+Xe2VT+lE8Q==
lodash.isequal@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0"
integrity sha1-QVxEePK8wwEgwizhDtMib30+GOA=
-macaddress@^0.2.7:
- version "0.2.8"
- resolved "https://registry.yarnpkg.com/macaddress/-/macaddress-0.2.8.tgz#5904dc537c39ec6dbefeae902327135fa8511f12"
- integrity sha1-WQTcU3w57G2+/q6QIycTX6hRHxI=
+lodash@^4.17.11:
+ version "4.17.11"
+ resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d"
+ integrity sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==
-mime-db@~1.35.0:
- version "1.35.0"
- resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.35.0.tgz#0569d657466491283709663ad379a99b90d9ab47"
- integrity sha512-JWT/IcCTsB0Io3AhWUMjRqucrHSPsSf2xKLaRldJVULioggvkJvggZ3VXNNSRkCddE6D+BUI4HEIZIA2OjwIvg==
-
-mime-types@^2.1.12, mime-types@~2.1.17:
- version "2.1.19"
- resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.19.tgz#71e464537a7ef81c15f2db9d97e913fc0ff606f0"
- integrity sha512-P1tKYHVSZ6uFo26mtnve4HQFE3koh1UWVkp8YUC+ESBHe945xWSoXuHHiGarDqcEZ+whpCDnlNw5LON0kLo+sw==
+logform@^2.1.1:
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/logform/-/logform-2.1.2.tgz#957155ebeb67a13164069825ce67ddb5bb2dd360"
+ integrity sha512-+lZh4OpERDBLqjiwDLpAWNQu6KMjnlXH2ByZwCuSqVPJletw0kTWJf5CgSNAUKn1KUkv3m2cUz/LK8zyEy7wzQ==
dependencies:
- mime-db "~1.35.0"
+ colors "^1.2.1"
+ fast-safe-stringify "^2.0.4"
+ fecha "^2.3.3"
+ ms "^2.1.1"
+ triple-beam "^1.3.0"
+
+mixpanel@^0.10.2:
+ version "0.10.2"
+ resolved "https://registry.yarnpkg.com/mixpanel/-/mixpanel-0.10.2.tgz#10ff6cd76034b262d469094ad3d8c99039345376"
+ integrity sha512-+zbBQGd/Q5LLRooqJ2iyEDzKz2/ly4TipH5tE9te0BDMJpROxUMGffPulyHbh4FtMcbJuPmIUSIfy//JhhnlnA==
+ dependencies:
+ https-proxy-agent "2.2.1"
ms@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=
+ms@^2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a"
+ integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==
+
+nan@^2.13.2:
+ version "2.14.0"
+ resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c"
+ integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==
+
ng2-dnd@^5.0.2:
version "5.0.2"
resolved "https://registry.yarnpkg.com/ng2-dnd/-/ng2-dnd-5.0.2.tgz#862278ac7dedfa14f5783bbf34014d5d73dfefb4"
@@ -461,207 +385,168 @@ ngx-perfect-scrollbar@^6.0.0:
perfect-scrollbar "^1.3.0"
resize-observer-polyfill "^1.4.0"
-oauth-sign@~0.8.2:
- version "0.8.2"
- resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43"
- integrity sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=
+one-time@0.0.4:
+ version "0.0.4"
+ resolved "https://registry.yarnpkg.com/one-time/-/one-time-0.0.4.tgz#f8cdf77884826fe4dff93e3a9cc37b1e4480742e"
+ integrity sha1-+M33eISCb+Tf+T46nMN7HkSAdC4=
+
+pako@^1.0.7:
+ version "1.0.10"
+ resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.10.tgz#4328badb5086a426aa90f541977d4955da5c9732"
+ integrity sha512-0DTvPVU3ed8+HNXOu5Bs+o//Mbdj9VNQMUOe9oKCwh8l0GNwpTDMKCWbRjgtD291AWnkAgkqA/LOnQS8AmS1tw==
perfect-scrollbar@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/perfect-scrollbar/-/perfect-scrollbar-1.3.0.tgz#61da56f94b58870d8e0a617bce649cee17d1e3b2"
integrity sha512-7Ub8YOvZB5k+pTy0K3LYUDnH9Xl3qvHcclJyIX+AV5UxHxll146iVGq4rtc+848nTDBQq89J7QxKKMA++cTXzQ==
-performance-now@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
- integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=
+process-nextick-args@~2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa"
+ integrity sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==
-punycode@^1.4.1:
- version "1.4.1"
- resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e"
- integrity sha1-wNWmOycYgArY4esPpSachN1BhF4=
-
-qs@~6.5.1:
- version "6.5.2"
- resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36"
- integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==
-
-rage-edit-tmp@^1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/rage-edit-tmp/-/rage-edit-tmp-1.1.0.tgz#fc5d76716d2fe2cf97dcafbf3e26753e3a08e3b2"
- integrity sha512-lR97QHY5WSf9orInMJhPqUbenkdiy7QbXUoRMI+wBZGyAPkxNwgo7h6ojq634QrBf/kQo3mVXYjuD3ZYraNaZQ==
-
-request@2.86.0:
- version "2.86.0"
- resolved "https://registry.yarnpkg.com/request/-/request-2.86.0.tgz#2b9497f449b0a32654c081a5cf426bbfb5bf5b69"
- integrity sha512-BQZih67o9r+Ys94tcIW4S7Uu8pthjrQVxhsZ/weOwHbDfACxvIyvnAbzFQxjy1jMtvFSzv5zf4my6cZsJBbVzw==
+readable-stream@^2.3.6:
+ version "2.3.6"
+ resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf"
+ integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==
dependencies:
- aws-sign2 "~0.7.0"
- aws4 "^1.6.0"
- caseless "~0.12.0"
- combined-stream "~1.0.5"
- extend "~3.0.1"
- forever-agent "~0.6.1"
- form-data "~2.3.1"
- har-validator "~5.0.3"
- hawk "~6.0.2"
- http-signature "~1.2.0"
- is-typedarray "~1.0.0"
- isstream "~0.1.2"
- json-stringify-safe "~5.0.1"
- mime-types "~2.1.17"
- oauth-sign "~0.8.2"
- performance-now "^2.1.0"
- qs "~6.5.1"
- safe-buffer "^5.1.1"
- tough-cookie "~2.3.3"
- tunnel-agent "^0.6.0"
- uuid "^3.1.0"
+ core-util-is "~1.0.0"
+ inherits "~2.0.3"
+ isarray "~1.0.0"
+ process-nextick-args "~2.0.0"
+ safe-buffer "~5.1.1"
+ string_decoder "~1.1.1"
+ util-deprecate "~1.0.1"
+
+readable-stream@^3.1.1:
+ version "3.3.0"
+ resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.3.0.tgz#cb8011aad002eb717bf040291feba8569c986fb9"
+ integrity sha512-EsI+s3k3XsW+fU8fQACLN59ky34AZ14LoeVZpYwmZvldCFo0r0gnelwF2TcMjLor/BTL5aDJVBMkss0dthToPw==
+ dependencies:
+ inherits "^2.0.3"
+ string_decoder "^1.1.1"
+ util-deprecate "^1.0.1"
resize-observer-polyfill@^1.4.0:
version "1.5.0"
resolved "https://registry.yarnpkg.com/resize-observer-polyfill/-/resize-observer-polyfill-1.5.0.tgz#660ff1d9712a2382baa2cad450a4716209f9ca69"
integrity sha512-M2AelyJDVR/oLnToJLtuDJRBBWUGUvvGigj1411hXhAdyFWqMaqHp7TixW3FpiLuVaikIcR1QL+zqoJoZlOgpg==
-safe-buffer@^5.0.1, safe-buffer@^5.1.1:
+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#991ec69d296e0313747d59bdfd2b745c35f8828d"
integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
-safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0:
- version "2.1.2"
- resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
- integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
-
-sax@^1.2.1:
+sax@^1.2.4:
version "1.2.4"
resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==
-semver@^5.4.1:
- version "5.4.1"
- resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e"
- integrity sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==
+semver@^5.6.0:
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.0.tgz#790a7cf6fea5459bac96110b29b60412dc8ff96b"
+ integrity sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==
shell-escape@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/shell-escape/-/shell-escape-0.2.0.tgz#68fd025eb0490b4f567a027f0bf22480b5f84133"
integrity sha1-aP0CXrBJC09WegJ/C/IkgLX4QTM=
-sntp@2.x.x:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/sntp/-/sntp-2.1.0.tgz#2c6cec14fedc2222739caf9b5c3d85d1cc5a2cc8"
- integrity sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg==
+simple-swizzle@^0.2.2:
+ version "0.2.2"
+ resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a"
+ integrity sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=
dependencies:
- hoek "4.x.x"
+ is-arrayish "^0.3.1"
-source-map-support@^0.4.16:
- version "0.4.17"
- resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.17.tgz#6f2150553e6375375d0ccb3180502b78c18ba430"
- integrity sha512-30c1Ch8FSjV0FwC253iftbbj0dU/OXoSg1LAEGZJUlGgjTNj6cu+DVqJWWIZJY5RXLWV4eFtR+4ouo0VIOYOTg==
+source-map-support@^0.5.9:
+ version "0.5.12"
+ resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.12.tgz#b4f3b10d51857a5af0138d3ce8003b201613d599"
+ integrity sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ==
dependencies:
- source-map "^0.5.6"
+ buffer-from "^1.0.0"
+ source-map "^0.6.0"
-source-map@^0.5.6:
- version "0.5.7"
- resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
- integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=
+source-map@^0.6.0:
+ version "0.6.1"
+ resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
+ integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
sprintf-js@~1.0.2:
version "1.0.3"
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=
-sshpk@^1.7.0:
- version "1.14.2"
- resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.14.2.tgz#c6fc61648a3d9c4e764fd3fcdf4ea105e492ba98"
- integrity sha1-xvxhZIo9nE52T9P8306hBeSSupg=
- dependencies:
- asn1 "~0.2.3"
- assert-plus "^1.0.0"
- dashdash "^1.12.0"
- getpass "^0.1.1"
- safer-buffer "^2.0.2"
- optionalDependencies:
- bcrypt-pbkdf "^1.0.0"
- ecc-jsbn "~0.1.1"
- jsbn "~0.1.0"
- tweetnacl "~0.14.0"
-
stack-trace@0.0.x:
version "0.0.10"
resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0"
integrity sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=
-tough-cookie@~2.3.3:
- version "2.3.4"
- resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.4.tgz#ec60cee38ac675063ffc97a5c18970578ee83655"
- integrity sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==
+string_decoder@^1.1.1:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.2.0.tgz#fe86e738b19544afe70469243b2a1ee9240eae8d"
+ integrity sha512-6YqyX6ZWEYguAxgZzHGL7SsCeGx3V2TtOTqZz1xSTSWnqsbWwbptafNyvf/ACquZUXV3DANr5BDIwNYe1mN42w==
dependencies:
- punycode "^1.4.1"
+ safe-buffer "~5.1.0"
-tunnel-agent@^0.6.0:
- version "0.6.0"
- resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd"
- integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=
+string_decoder@~1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8"
+ integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==
dependencies:
- safe-buffer "^5.0.1"
+ safe-buffer "~5.1.0"
-tweetnacl@^0.14.3, tweetnacl@~0.14.0:
- version "0.14.5"
- resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
- integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=
+text-hex@1.0.x:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/text-hex/-/text-hex-1.0.0.tgz#69dc9c1b17446ee79a92bf5b884bb4b9127506f5"
+ integrity sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==
-universal-analytics@^0.4.17:
- version "0.4.17"
- resolved "https://registry.yarnpkg.com/universal-analytics/-/universal-analytics-0.4.17.tgz#b57a07e37446ebe4f32872b2152a44cbc5cc4b73"
- integrity sha512-N2JFymxv4q2N5Wmftc5JCcM5t1tp+sc1kqeDRhDL4XLY5X6PBZ0kav2wvVUZJJMvmSq3WXrmzDu062p+cSFYfQ==
- dependencies:
- debug "^3.0.0"
- request "2.86.0"
- uuid "^3.0.0"
+triple-beam@^1.2.0, triple-beam@^1.3.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/triple-beam/-/triple-beam-1.3.0.tgz#a595214c7298db8339eeeee083e4d10bd8cb8dd9"
+ integrity sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==
universalify@^0.1.0:
version "0.1.1"
resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.1.tgz#fa71badd4437af4c148841e3b3b165f9e9e590b7"
integrity sha1-+nG63UQ3r0wUiEHjs7Fl+enlkLc=
-uuid-1345@^0.99.6:
- version "0.99.6"
- resolved "https://registry.yarnpkg.com/uuid-1345/-/uuid-1345-0.99.6.tgz#b1270ae015a7721c7adec6c46ec169c6098aed40"
- integrity sha1-sScK4BWnchx63sbEbsFpxgmK7UA=
- dependencies:
- macaddress "^0.2.7"
+util-deprecate@^1.0.1, util-deprecate@~1.0.1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
+ integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
-uuid@^3.0.0, uuid@^3.1.0:
+uuid@^3.3.2:
version "3.3.2"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131"
integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==
-verror@1.10.0:
- version "1.10.0"
- resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400"
- integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=
+windows-native-registry@^1.0.14:
+ version "1.0.14"
+ resolved "https://registry.yarnpkg.com/windows-native-registry/-/windows-native-registry-1.0.14.tgz#35c742b1278473127cbfb3b76e0db3d1ef626872"
+ integrity sha512-C2UgyZYJYcPFjkhfNuy09CUa6wXAti4x/tLPgzudDDrqpTyczcgnBEpiablmE6j7E7ownouWTqgVcHW8HJyqhw==
dependencies:
- assert-plus "^1.0.0"
- core-util-is "1.0.2"
- extsprintf "^1.2.0"
+ nan "^2.13.2"
-winston@^2.4.0:
- version "2.4.0"
- resolved "https://registry.yarnpkg.com/winston/-/winston-2.4.0.tgz#808050b93d52661ed9fb6c26b3f0c826708b0aee"
- integrity sha1-gIBQuT1SZh7Z+2wms/DIJnCLCu4=
+winston-transport@^4.3.0:
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/winston-transport/-/winston-transport-4.3.0.tgz#df68c0c202482c448d9b47313c07304c2d7c2c66"
+ integrity sha512-B2wPuwUi3vhzn/51Uukcao4dIduEiPOcOt9HJ3QeaXgkJ5Z7UwpBzxS4ZGNHtrxrUvTwemsQiSys0ihOf8Mp1A==
dependencies:
- async "~1.0.0"
- colors "1.0.x"
- cycle "1.0.x"
- eyes "0.1.x"
- isstream "0.1.x"
+ readable-stream "^2.3.6"
+ triple-beam "^1.2.0"
+
+winston@*, winston@^3.2.1:
+ version "3.2.1"
+ resolved "https://registry.yarnpkg.com/winston/-/winston-3.2.1.tgz#63061377976c73584028be2490a1846055f77f07"
+ integrity sha512-zU6vgnS9dAWCEKg/QYigd6cgMVVNwyTzKs81XZtTFuRwJOcDdBg7AU0mXVyNbs7O5RH2zdv+BdNZUlx7mXPuOw==
+ dependencies:
+ async "^2.6.1"
+ diagnostics "^1.1.1"
+ is-stream "^1.1.0"
+ logform "^2.1.1"
+ one-time "0.0.4"
+ readable-stream "^3.1.1"
stack-trace "0.0.x"
-
-xelement@^1.0.16:
- version "1.0.16"
- resolved "https://registry.yarnpkg.com/xelement/-/xelement-1.0.16.tgz#900bb46c20fc2dffadff778a9d2dc36699d0ff7e"
- integrity sha1-kAu0bCD8Lf+t/3eKnS3DZpnQ/34=
- dependencies:
- sax "^1.2.1"
+ triple-beam "^1.3.0"
+ winston-transport "^4.3.0"
diff --git a/terminus-plugin-manager/package.json b/terminus-plugin-manager/package.json
index c1bbd486..40aeba54 100644
--- a/terminus-plugin-manager/package.json
+++ b/terminus-plugin-manager/package.json
@@ -1,12 +1,12 @@
{
"name": "terminus-plugin-manager",
- "version": "1.0.0-alpha.55",
+ "version": "1.0.73-c4-ga7d62b0",
"description": "Terminus' plugin manager",
"keywords": [
"terminus-builtin-plugin"
],
"main": "dist/index.js",
- "typings": "dist/index.d.ts",
+ "typings": "typings/index.d.ts",
"scripts": {
"build": "webpack --progress --color --display-modules",
"watch": "webpack --progress --color --watch"
@@ -17,13 +17,15 @@
"author": "Eugene Pankov",
"license": "MIT",
"devDependencies": {
- "@types/mz": "0.0.31",
- "@types/node": "7.0.12",
- "@types/semver": "^5.3.32",
- "@types/webpack-env": "1.13.0",
+ "@types/mz": "0.0.32",
+ "@types/node": "12.0.10",
+ "@types/semver": "^6.0.0",
+ "@types/webpack-env": "1.13.9",
+ "axios": "^0.19.0",
"css-loader": "^0.28.0",
+ "mz": "^2.6.0",
"ngx-pipes": "^1.6.1",
- "semver": "^5.3.0"
+ "semver": "^6.1.0"
},
"peerDependencies": {
"@angular/common": "4.0.1",
@@ -31,13 +33,8 @@
"@angular/forms": "4.0.1",
"@angular/platform-browser": "4.0.1",
"@ng-bootstrap/ng-bootstrap": "1.0.0-alpha.22",
+ "rxjs": "5.3.0",
"terminus-core": "*",
- "terminus-settings": "*",
- "rxjs": "5.3.0"
- },
- "dependencies": {
- "axios": "^0.16.2",
- "mz": "^2.6.0"
- },
- "false": {}
+ "terminus-settings": "*"
+ }
}
diff --git a/terminus-plugin-manager/src/components/pluginsSettingsTab.component.pug b/terminus-plugin-manager/src/components/pluginsSettingsTab.component.pug
index f950da21..de6378a8 100644
--- a/terminus-plugin-manager/src/components/pluginsSettingsTab.component.pug
+++ b/terminus-plugin-manager/src/components/pluginsSettingsTab.component.pug
@@ -2,67 +2,60 @@
strong Error in {{erroredPlugin}}:
pre {{errorMessage}}
-button.btn.btn-outline-info.btn-sm.pull-right((click)='openPluginsFolder()')
- i.fa.fa-folder
- span Plugins folder
+
+.d-flex
+ h3.mb-1 Installed
+ button.btn.btn-outline-info.btn-sm.ml-auto((click)='openPluginsFolder()')
+ i.fas.fa-folder
+ span Plugins folder
-h3.mb-1 Installed
+.list-group.list-group-flush.mt-2
+ .list-group-item.d-flex.align-items-center(*ngFor='let plugin of pluginManager.installedPlugins|orderBy:"name"')
+ .mr-auto.d-flex.flex-column
+ div
+ strong {{plugin.name}}
+ small.text-muted.ml-1(*ngIf='!plugin.isBuiltin') {{plugin.version}} / {{plugin.author}}
+ small.text-warning.ml-1(*ngIf='config.store.pluginBlacklist.includes(plugin.name)') Disabled
+ a.text-muted.mb-0((click)='showPluginInfo(plugin)')
+ small {{plugin.description}}
-.mb-3.d-flex.w-100.align-items-center(*ngFor='let plugin of pluginManager.installedPlugins|orderBy:"name"')
- button.btn.btn-outline-danger.active.mr-2(
- *ngIf='config.store.pluginBlacklist.includes(plugin.name)',
- (click)='enablePlugin(plugin)'
- )
- i.fa.fa-fw.fa-pause
- button.btn.btn-outline-secondary.mr-2(
- *ngIf='!config.store.pluginBlacklist.includes(plugin.name)',
- (click)='disablePlugin(plugin)'
- )
- i.fa.fa-fw.fa-check
+ button.btn.btn-primary.ml-2(
+ *ngIf='knownUpgrades[plugin.name]',
+ (click)='upgradePlugin(plugin)',
+ [disabled]='busy[plugin.name] != undefined'
+ )
+ i.fas.fa-fw.fa-arrow-up(*ngIf='busy[plugin.name] != BusyState.Installing')
+ i.fas.fa-fw.fa-circle-notch.fa-spin(*ngIf='busy[plugin.name] == BusyState.Installing')
+ span Upgrade ({{knownUpgrades[plugin.name].version}})
- .mr-auto.d-flex.flex-column
- div
- strong {{plugin.name}}
- small.text-muted.ml-1 {{plugin.version}} / {{plugin.author}}
- a.text-muted.mb-0((click)='showPluginInfo(plugin)')
- small {{plugin.description}}
+ button.btn.btn-primary.ml-2(
+ *ngIf='config.store.pluginBlacklist.includes(plugin.name)',
+ (click)='enablePlugin(plugin)'
+ )
+ i.fas.fa-fw.fa-play
+
+ button.btn.btn-secondary.ml-2(
+ *ngIf='!config.store.pluginBlacklist.includes(plugin.name)',
+ (click)='disablePlugin(plugin)'
+ )
+ i.fas.fa-fw.fa-pause
+
+ button.btn.btn-danger.ml-2(
+ (click)='uninstallPlugin(plugin)',
+ *ngIf='!plugin.isBuiltin',
+ [disabled]='busy[plugin.name] != undefined'
+ )
+ i.fas.fa-fw.fa-trash(*ngIf='busy[plugin.name] != BusyState.Uninstalling')
+ i.fas.fa-fw.fa-circle-notch.fa-spin(*ngIf='busy[plugin.name] == BusyState.Uninstalling')
- button.btn.btn-primary.ml-2(
- *ngIf='npmInstalled && knownUpgrades[plugin.name]',
- (click)='upgradePlugin(plugin)',
- [disabled]='busy[plugin.name] != undefined'
- )
- i.fa.fa-fw.fa-arrow-up(*ngIf='busy[plugin.name] != BusyState.Installing')
- i.fa.fa-fw.fa-circle-o-notch.fa-spin(*ngIf='busy[plugin.name] == BusyState.Installing')
- span Upgrade ({{knownUpgrades[plugin.name].version}})
-
- button.btn.btn-outline-danger.ml-2(
- (click)='uninstallPlugin(plugin)',
- *ngIf='!plugin.isBuiltin && npmInstalled',
- [disabled]='busy[plugin.name] != undefined'
- )
- i.fa.fa-fw.fa-trash-o(*ngIf='busy[plugin.name] != BusyState.Uninstalling')
- i.fa.fa-fw.fa-circle-o-notch.fa-spin(*ngIf='busy[plugin.name] == BusyState.Uninstalling')
-
-.text-center.mt-5(*ngIf='npmMissing')
- h4 npm not installed
- p.mb-2 npm is required to install Terminus plugins.
- .btn-group
- button.btn.btn-outline-primary((click)='downloadNPM()')
- i.fa.fa-download
- span Get npm
- button.btn.btn-outline-info((click)='checkNPM()')
- i.fa.fa-refresh
- span Try again
-
-div(*ngIf='npmInstalled')
+div
h3.mt-4 Available
.input-group.mb-3
.input-group-prepend
.input-group-text
- i.fa.fa-fw.fa-circle-o-notch.fa-spin(*ngIf='!availablePluginsReady')
- i.fa.fa-fw.fa-search(*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',
[(ngModel)]='_1',
@@ -71,19 +64,19 @@ div(*ngIf='npmInstalled')
)
- .mb-4(*ngIf='availablePlugins$')
+ .list-group.list-group-flush.mb-4(*ngIf='availablePlugins$')
ng-container(*ngFor='let plugin of (availablePlugins$|async|orderBy:"name")')
- .d-flex.w-100.align-items-center.mb-3(*ngIf='!isAlreadyInstalled(plugin)')
- button.btn.btn-primary.mr-2(
+ .list-group-item.d-flex.align-items-center(*ngIf='!isAlreadyInstalled(plugin)')
+ button.btn.btn-primary.mr-3(
(click)='installPlugin(plugin)',
[disabled]='busy[plugin.name] != undefined'
)
- i.fa.fa-fw.fa-download(*ngIf='busy[plugin.name] != BusyState.Installing')
- i.fa.fa-fw.fa-circle-o-notch.fa-spin(*ngIf='busy[plugin.name] == BusyState.Installing')
+ i.fas.fa-fw.fa-download(*ngIf='busy[plugin.name] != BusyState.Installing')
+ i.fas.fa-fw.fa-circle-notch.fa-spin(*ngIf='busy[plugin.name] == BusyState.Installing')
div((click)='showPluginInfo(plugin)')
div
strong {{plugin.name}}
small.text-muted.ml-1 {{plugin.version}} / {{plugin.author}}
- i.fa.fa-check.text-success.ml-1(*ngIf='plugin.isOfficial', title='Official')
+ i.fas.fa-check.text-success.ml-1(*ngIf='plugin.isOfficial', title='Official')
small.text-muted {{plugin.description}}
diff --git a/terminus-plugin-manager/src/components/pluginsSettingsTab.component.ts b/terminus-plugin-manager/src/components/pluginsSettingsTab.component.ts
index b52c6647..a80ddffb 100644
--- a/terminus-plugin-manager/src/components/pluginsSettingsTab.component.ts
+++ b/terminus-plugin-manager/src/components/pluginsSettingsTab.component.ts
@@ -3,31 +3,29 @@ import { debounceTime, distinctUntilChanged, first, tap, flatMap } from 'rxjs/op
import * as semver from 'semver'
import { Component, Input } from '@angular/core'
-import { ConfigService, HostAppService, ElectronService } from 'terminus-core'
-import { IPluginInfo, PluginManagerService } from '../services/pluginManager.service'
+import { ConfigService, ElectronService } from 'terminus-core'
+import { PluginInfo, PluginManagerService } from '../services/pluginManager.service'
enum BusyState { Installing, Uninstalling }
+/** @hidden */
@Component({
template: require('./pluginsSettingsTab.component.pug'),
styles: [require('./pluginsSettingsTab.component.scss')],
})
export class PluginsSettingsTabComponent {
BusyState = BusyState
- @Input() availablePlugins$: Observable
+ @Input() availablePlugins$: Observable
@Input() availablePluginsQuery$ = new BehaviorSubject('')
@Input() availablePluginsReady = false
- @Input() knownUpgrades: {[id: string]: IPluginInfo} = {}
+ @Input() knownUpgrades: {[id: string]: PluginInfo} = {}
@Input() busy: {[id: string]: BusyState} = {}
@Input() erroredPlugin: string
@Input() errorMessage: string
- @Input() npmInstalled = false
- @Input() npmMissing = false
constructor (
private electron: ElectronService,
private config: ConfigService,
- private hostApp: HostAppService,
public pluginManager: PluginManagerService
) {
}
@@ -46,35 +44,25 @@ export class PluginsSettingsTabComponent {
})
)
this.availablePlugins$.pipe(first()).subscribe(available => {
- for (let plugin of this.pluginManager.installedPlugins) {
+ for (const plugin of this.pluginManager.installedPlugins) {
this.knownUpgrades[plugin.name] = available.find(x => x.name === plugin.name && semver.gt(x.version, plugin.version))
}
})
- this.checkNPM()
}
openPluginsFolder (): void {
- this.hostApp.getShell().openItem(this.pluginManager.userPluginsPath)
- }
-
- downloadNPM (): void {
- this.hostApp.getShell().openExternal('https://nodejs.org/en/download/current/')
- }
-
- async checkNPM () {
- this.npmInstalled = await this.pluginManager.isNPMInstalled()
- this.npmMissing = !this.npmInstalled
+ this.electron.shell.openItem(this.pluginManager.userPluginsPath)
}
searchAvailable (query: string) {
this.availablePluginsQuery$.next(query)
}
- isAlreadyInstalled (plugin: IPluginInfo): boolean {
+ isAlreadyInstalled (plugin: PluginInfo): boolean {
return this.pluginManager.installedPlugins.some(x => x.name === plugin.name)
}
- async installPlugin (plugin: IPluginInfo): Promise {
+ async installPlugin (plugin: PluginInfo): Promise {
this.busy[plugin.name] = BusyState.Installing
try {
await this.pluginManager.installPlugin(plugin)
@@ -88,7 +76,7 @@ export class PluginsSettingsTabComponent {
}
}
- async uninstallPlugin (plugin: IPluginInfo): Promise {
+ async uninstallPlugin (plugin: PluginInfo): Promise {
this.busy[plugin.name] = BusyState.Uninstalling
try {
await this.pluginManager.uninstallPlugin(plugin)
@@ -102,22 +90,22 @@ export class PluginsSettingsTabComponent {
}
}
- async upgradePlugin (plugin: IPluginInfo): Promise {
+ async upgradePlugin (plugin: PluginInfo): Promise {
return this.installPlugin(this.knownUpgrades[plugin.name])
}
- showPluginInfo (plugin: IPluginInfo) {
+ showPluginInfo (plugin: PluginInfo) {
this.electron.shell.openExternal('https://www.npmjs.com/package/' + plugin.packageName)
}
- enablePlugin (plugin: IPluginInfo) {
+ enablePlugin (plugin: PluginInfo) {
this.config.store.pluginBlacklist = this.config.store.pluginBlacklist.filter(x => x !== plugin.name)
this.config.save()
this.config.requestRestart()
}
- disablePlugin (plugin: IPluginInfo) {
- this.config.store.pluginBlacklist.push(plugin.name)
+ disablePlugin (plugin: PluginInfo) {
+ this.config.store.pluginBlacklist = [...this.config.store.pluginBlacklist, plugin.name]
this.config.save()
this.config.requestRestart()
}
diff --git a/terminus-plugin-manager/src/config.ts b/terminus-plugin-manager/src/config.ts
deleted file mode 100644
index 9ea4ee4d..00000000
--- a/terminus-plugin-manager/src/config.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import { ConfigProvider } from 'terminus-core'
-
-export class PluginsConfigProvider extends ConfigProvider {
- defaults = {
- npm: 'npm',
- }
-}
diff --git a/terminus-plugin-manager/src/index.ts b/terminus-plugin-manager/src/index.ts
index e0912491..14da0428 100644
--- a/terminus-plugin-manager/src/index.ts
+++ b/terminus-plugin-manager/src/index.ts
@@ -4,12 +4,10 @@ import { FormsModule } from '@angular/forms'
import { NgPipesModule } from 'ngx-pipes'
import { NgbModule } from '@ng-bootstrap/ng-bootstrap'
-import { ConfigProvider } from 'terminus-core'
import { SettingsTabProvider } from 'terminus-settings'
import { PluginsSettingsTabComponent } from './components/pluginsSettingsTab.component'
import { PluginManagerService } from './services/pluginManager.service'
-import { PluginsConfigProvider } from './config'
import { PluginsSettingsTabProvider } from './settings'
@NgModule({
@@ -21,8 +19,6 @@ import { PluginsSettingsTabProvider } from './settings'
],
providers: [
{ provide: SettingsTabProvider, useClass: PluginsSettingsTabProvider, multi: true },
- { provide: ConfigProvider, useClass: PluginsConfigProvider, multi: true },
- PluginManagerService,
],
entryComponents: [
PluginsSettingsTabComponent,
@@ -31,6 +27,6 @@ import { PluginsSettingsTabProvider } from './settings'
PluginsSettingsTabComponent,
],
})
-export default class PluginManagerModule { }
+export default class PluginManagerModule { } // eslint-disable-line @typescript-eslint/no-extraneous-class
export { PluginManagerService }
diff --git a/terminus-plugin-manager/src/services/pluginManager.service.ts b/terminus-plugin-manager/src/services/pluginManager.service.ts
index 41f9755d..3e35a6e1 100644
--- a/terminus-plugin-manager/src/services/pluginManager.service.ts
+++ b/terminus-plugin-manager/src/services/pluginManager.service.ts
@@ -1,17 +1,14 @@
-import * as path from 'path'
-import * as fs from 'mz/fs'
-import { exec } from 'mz/child_process'
import axios from 'axios'
import { Observable, from } from 'rxjs'
import { map } from 'rxjs/operators'
import { Injectable } from '@angular/core'
-import { Logger, LogService, ConfigService, HostAppService, Platform } from 'terminus-core'
+import { Logger, LogService } from 'terminus-core'
const NAME_PREFIX = 'terminus-'
const KEYWORD = 'terminus-plugin'
const OFFICIAL_NPM_ACCOUNT = 'eugenepankov'
-export interface IPluginInfo {
+export interface PluginInfo {
name: string
description: string
packageName: string
@@ -23,59 +20,49 @@ export interface IPluginInfo {
path?: string
}
-@Injectable()
+@Injectable({ providedIn: 'root' })
export class PluginManagerService {
logger: Logger
builtinPluginsPath: string = (window as any).builtinPluginsPath
userPluginsPath: string = (window as any).userPluginsPath
- installedPlugins: IPluginInfo[] = (window as any).installedPlugins
- npmPath: string
- private envPath: string
+ installedPlugins: PluginInfo[] = (window as any).installedPlugins
+
+ private npmReady: Promise
+ private npm: any
constructor (
log: LogService,
- private config: ConfigService,
- private hostApp: HostAppService,
) {
this.logger = log.create('pluginManager')
- this.detectPath()
}
- async detectPath () {
- this.npmPath = this.config.store.npm
- this.envPath = process.env.PATH
- if (await fs.exists(this.npmPath)) {
- return
- }
- if (this.hostApp.platform !== Platform.Windows) {
- this.envPath = (await exec('$SHELL -c -i \'echo $PATH\''))[0].toString().trim()
- let searchPaths = this.envPath.split(':')
- for (let searchPath of searchPaths) {
- if (await fs.exists(path.join(searchPath, 'npm'))) {
- this.logger.debug('Found npm in', searchPath)
- this.npmPath = path.join(searchPath, 'npm')
- return
- }
+ async getNPM () {
+ if (!this.npm) {
+ if (!this.npmReady) {
+ this.npmReady = new Promise(resolve => {
+ const npm = (global as any).require('npm')
+ npm.load({
+ prefix: this.userPluginsPath,
+ }, err => {
+ if (err) {
+ this.logger.error(err)
+ }
+ this.npm = npm
+ resolve()
+ })
+ })
}
+ await this.npmReady
}
+ return this.npm
}
- async isNPMInstalled (): Promise {
- await this.detectPath()
- try {
- await exec(`${this.npmPath} -v`, { env: this.getEnv() })
- return true
- } catch (_) {
- return false
- }
- }
-
- listAvailable (query?: string): Observable {
+ listAvailable (query?: string): Observable {
return from(
axios.get(`https://www.npmjs.com/search?q=keywords%3A${KEYWORD}+${encodeURIComponent(query || '')}&from=0&size=1000`, {
headers: {
'x-spiferack': '1',
- }
+ },
})
).pipe(
map(response => response.data.objects.map(item => ({
@@ -91,18 +78,22 @@ export class PluginManagerService {
)
}
- async installPlugin (plugin: IPluginInfo) {
- await exec(`${this.npmPath} --prefix "${this.userPluginsPath}" install ${plugin.packageName}@${plugin.version}`, { env: this.getEnv() })
- this.installedPlugins = this.installedPlugins.filter(x => x.packageName !== plugin.packageName)
- this.installedPlugins.push(plugin)
+ async installPlugin (plugin: PluginInfo) {
+ (await this.getNPM()).commands.install([`${plugin.packageName}@${plugin.version}`], err => {
+ if (err) {
+ this.logger.error(err)
+ }
+ this.installedPlugins = this.installedPlugins.filter(x => x.packageName !== plugin.packageName)
+ this.installedPlugins.push(plugin)
+ })
}
- async uninstallPlugin (plugin: IPluginInfo) {
- await exec(`${this.npmPath} --prefix "${this.userPluginsPath}" remove ${plugin.packageName}`, { env: this.getEnv() })
- this.installedPlugins = this.installedPlugins.filter(x => x.packageName !== plugin.packageName)
- }
-
- private getEnv (): any {
- return Object.assign(process.env, { PATH: this.envPath })
+ async uninstallPlugin (plugin: PluginInfo) {
+ (await this.getNPM()).commands.remove([plugin.packageName], err => {
+ if (err) {
+ this.logger.error(err)
+ }
+ this.installedPlugins = this.installedPlugins.filter(x => x.packageName !== plugin.packageName)
+ })
}
}
diff --git a/terminus-plugin-manager/src/settings.ts b/terminus-plugin-manager/src/settings.ts
index a82be7d6..9405ed22 100644
--- a/terminus-plugin-manager/src/settings.ts
+++ b/terminus-plugin-manager/src/settings.ts
@@ -3,6 +3,7 @@ import { SettingsTabProvider } from 'terminus-settings'
import { PluginsSettingsTabComponent } from './components/pluginsSettingsTab.component'
+/** @hidden */
@Injectable()
export class PluginsSettingsTabProvider extends SettingsTabProvider {
id = 'plugins'
diff --git a/terminus-plugin-manager/tsconfig.json b/terminus-plugin-manager/tsconfig.json
index 1d6cfcbf..e0611107 100644
--- a/terminus-plugin-manager/tsconfig.json
+++ b/terminus-plugin-manager/tsconfig.json
@@ -3,6 +3,5 @@
"exclude": ["node_modules", "dist"],
"compilerOptions": {
"baseUrl": "src",
- "declarationDir": "dist"
}
}
diff --git a/terminus-plugin-manager/tsconfig.typings.json b/terminus-plugin-manager/tsconfig.typings.json
new file mode 100644
index 00000000..c0d2273c
--- /dev/null
+++ b/terminus-plugin-manager/tsconfig.typings.json
@@ -0,0 +1,14 @@
+{
+ "extends": "../tsconfig.json",
+ "exclude": ["node_modules", "dist", "typings"],
+ "compilerOptions": {
+ "baseUrl": "src",
+ "emitDeclarationOnly": true,
+ "declaration": true,
+ "declarationDir": "./typings",
+ "paths": {
+ "terminus-*": ["../../terminus-*"],
+ "*": ["../../app/node_modules/*"]
+ }
+ }
+}
diff --git a/terminus-plugin-manager/webpack.config.js b/terminus-plugin-manager/webpack.config.js
index 3cb34854..a15b8010 100644
--- a/terminus-plugin-manager/webpack.config.js
+++ b/terminus-plugin-manager/webpack.config.js
@@ -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,
},
@@ -43,10 +43,9 @@ module.exports = {
},
externals: [
'fs',
- 'font-manager',
+ 'net',
+ 'npm',
'path',
- 'mz/fs',
- 'mz/child_process',
/^rxjs/,
/^@angular/,
/^@ng-bootstrap/,
diff --git a/terminus-plugin-manager/yarn.lock b/terminus-plugin-manager/yarn.lock
index b094f491..04a3f498 100644
--- a/terminus-plugin-manager/yarn.lock
+++ b/terminus-plugin-manager/yarn.lock
@@ -2,27 +2,27 @@
# yarn lockfile v1
-"@types/mz@0.0.31":
- version "0.0.31"
- resolved "https://registry.yarnpkg.com/@types/mz/-/mz-0.0.31.tgz#a4d80c082fefe71e40a7c0f07d1e6555bbbc7b52"
- integrity sha1-pNgMCC/v5x5Ap8DwfR5lVbu8e1I=
+"@types/mz@0.0.32":
+ version "0.0.32"
+ resolved "https://registry.yarnpkg.com/@types/mz/-/mz-0.0.32.tgz#e8248b4e41424c052edc1725dd33650c313a3659"
+ integrity sha512-cy3yebKhrHuOcrJGkfwNHhpTXQLgmXSv1BX+4p32j+VUQ6aP2eJ5cL7OvGcAQx75fCTFaAIIAKewvqL+iwSd4g==
dependencies:
"@types/node" "*"
-"@types/node@*", "@types/node@7.0.12":
- version "7.0.12"
- resolved "https://registry.yarnpkg.com/@types/node/-/node-7.0.12.tgz#ae5f67a19c15f752148004db07cbbb372e69efc9"
- integrity sha1-rl9noZwV91IUgATbB8u7Ny5p78k=
+"@types/node@*", "@types/node@12.0.10":
+ version "12.0.10"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-12.0.10.tgz#51babf9c7deadd5343620055fc8aff7995c8b031"
+ integrity sha512-LcsGbPomWsad6wmMNv7nBLw7YYYyfdYcz6xryKYQhx89c3XXan+8Q6AJ43G5XDIaklaVkK3mE4fCb0SBvMiPSQ==
-"@types/semver@^5.3.32":
- version "5.4.0"
- resolved "https://registry.yarnpkg.com/@types/semver/-/semver-5.4.0.tgz#f3658535af7f1f502acd6da7daf405ffeb1f7ee4"
- integrity sha512-PBHCvO98hNec9A491vBbh0ZNDOVxccwKL1u2pm6fs9oDgm7SEnw0lEHqHfjsYryDxnE3zaf7LvERWEXjOp1hig==
+"@types/semver@^6.0.0":
+ version "6.0.1"
+ resolved "https://registry.yarnpkg.com/@types/semver/-/semver-6.0.1.tgz#a984b405c702fa5a7ec6abc56b37f2ba35ef5af6"
+ integrity sha512-ffCdcrEE5h8DqVxinQjo+2d1q+FV5z7iNtPofw3JsrltSoSVlOGaW0rY8XxtO9XukdTn8TaCGWmk2VFGhI70mg==
-"@types/webpack-env@1.13.0":
- version "1.13.0"
- resolved "https://registry.yarnpkg.com/@types/webpack-env/-/webpack-env-1.13.0.tgz#3044381647e11ee973c5af2e925323930f691d80"
- integrity sha1-MEQ4FkfhHulzxa8uklMjkw9pHYA=
+"@types/webpack-env@1.13.9":
+ version "1.13.9"
+ resolved "https://registry.yarnpkg.com/@types/webpack-env/-/webpack-env-1.13.9.tgz#a67287861c928ebf4159a908d1fb1a2a34d4097a"
+ integrity sha512-p8zp5xqkly3g4cCmo2mKOHI9+Z/kObmDj0BmjbDDJQlgDTiEGTbm17MEwTAusV6XceCy+bNw9q/ZHXHyKo3zkg==
alphanum-sort@^1.0.1, alphanum-sort@^1.0.2:
version "1.0.2"
@@ -70,15 +70,15 @@ autoprefixer@^6.3.1:
postcss "^5.2.16"
postcss-value-parser "^3.2.3"
-axios@^0.16.2:
- version "0.16.2"
- resolved "https://registry.yarnpkg.com/axios/-/axios-0.16.2.tgz#ba4f92f17167dfbab40983785454b9ac149c3c6d"
- integrity sha1-uk+S8XFn37q0CYN4VFS5rBScPG0=
+axios@^0.19.0:
+ version "0.19.0"
+ resolved "https://registry.yarnpkg.com/axios/-/axios-0.19.0.tgz#8e09bff3d9122e133f7b8101c8fbdd00ed3d2ab8"
+ integrity sha512-1uvKqKQta3KBxIz14F2v06AEHZ/dIoeKfbTRkK1E5oqjDnuEerLmYTgJB5AiQZHJcljpg1TuRzdjDR06qNk0DQ==
dependencies:
- follow-redirects "^1.2.3"
- is-buffer "^1.1.5"
+ follow-redirects "1.5.10"
+ is-buffer "^2.0.2"
-babel-code-frame@^6.11.0:
+babel-code-frame@^6.26.0:
version "6.26.0"
resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b"
integrity sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=
@@ -207,22 +207,22 @@ css-color-names@0.0.4:
integrity sha1-gIrcLnnPhHOAabZGyyDsJ762KeA=
css-loader@^0.28.0:
- version "0.28.7"
- resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-0.28.7.tgz#5f2ee989dd32edd907717f953317656160999c1b"
- integrity sha512-GxMpax8a/VgcfRrVy0gXD6yLd5ePYbXX/5zGgTVYp4wXtJklS8Z2VaUArJgc//f6/Dzil7BaJObdSv8eKKCPgg==
+ version "0.28.11"
+ resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-0.28.11.tgz#c3f9864a700be2711bb5a2462b2389b1a392dab7"
+ integrity sha512-wovHgjAx8ZIMGSL8pTys7edA1ClmzxHeY6n/d97gg5odgsxEgKjULPR0viqyC+FWMCL9sfqoC/QCUBo62tLvPg==
dependencies:
- babel-code-frame "^6.11.0"
+ babel-code-frame "^6.26.0"
css-selector-tokenizer "^0.7.0"
- cssnano ">=2.6.1 <4"
+ cssnano "^3.10.0"
icss-utils "^2.1.0"
loader-utils "^1.0.2"
lodash.camelcase "^4.3.0"
- object-assign "^4.0.1"
+ object-assign "^4.1.1"
postcss "^5.0.6"
- postcss-modules-extract-imports "^1.0.0"
- postcss-modules-local-by-default "^1.0.1"
- postcss-modules-scope "^1.0.0"
- postcss-modules-values "^1.1.0"
+ postcss-modules-extract-imports "^1.2.0"
+ postcss-modules-local-by-default "^1.2.0"
+ postcss-modules-scope "^1.1.0"
+ postcss-modules-values "^1.3.0"
postcss-value-parser "^3.3.0"
source-list-map "^2.0.0"
@@ -240,7 +240,7 @@ cssesc@^0.1.0:
resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-0.1.0.tgz#c814903e45623371a0477b40109aaafbeeaddbb4"
integrity sha1-yBSQPkViM3GgR3tAEJqq++6t27Q=
-"cssnano@>=2.6.1 <4":
+cssnano@^3.10.0:
version "3.10.0"
resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-3.10.0.tgz#4f38f6cea2b9b17fa01490f23f1dc68ea65c1c38"
integrity sha1-Tzj2zqK5sX+gFJDyPx3GjqZcHDg=
@@ -286,10 +286,10 @@ csso@~2.3.1:
clap "^1.0.9"
source-map "^0.5.3"
-debug@^2.4.5:
- version "2.6.8"
- resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc"
- integrity sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=
+debug@=3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
+ integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==
dependencies:
ms "2.0.0"
@@ -338,12 +338,12 @@ flatten@^1.0.2:
resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.2.tgz#dae46a9d78fbe25292258cc1e780a41d95c03782"
integrity sha1-2uRqnXj74lKSJYzB54CkHZXAN4I=
-follow-redirects@^1.2.3:
- version "1.2.4"
- resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.2.4.tgz#355e8f4d16876b43f577b0d5ce2668b9723214ea"
- integrity sha512-Suw6KewLV2hReSyEOeql+UUkBVyiBm3ok1VPrVFRZnQInWpdoZbbiG5i8aJVSjTr0yQ4Ava0Sh6/joCg1Brdqw==
+follow-redirects@1.5.10:
+ version "1.5.10"
+ resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.5.10.tgz#7b7a9f9aea2fdff36786a94ff643ed07f4ff5e2a"
+ integrity sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==
dependencies:
- debug "^2.4.5"
+ debug "=3.1.0"
function-bind@^1.0.2:
version "1.1.1"
@@ -401,10 +401,10 @@ is-absolute-url@^2.0.0:
resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-2.1.0.tgz#50530dfb84fcc9aa7dbe7852e83a37b93b9f2aa6"
integrity sha1-UFMN+4T8yap9vnhS6Do3uTufKqY=
-is-buffer@^1.1.5:
- version "1.1.5"
- resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.5.tgz#1f3b26ef613b214b88cbca23cc6c01d87961eecc"
- integrity sha1-Hzsm72E7IUuIy8ojzGwB2Hlh7sw=
+is-buffer@^2.0.2:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.3.tgz#4ecf3fcf749cbd1e472689e109ac66261a25e725"
+ integrity sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw==
is-plain-obj@^1.0.0:
version "1.1.0"
@@ -471,9 +471,9 @@ lodash.uniq@^4.5.0:
integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=
macaddress@^0.2.8:
- version "0.2.8"
- resolved "https://registry.yarnpkg.com/macaddress/-/macaddress-0.2.8.tgz#5904dc537c39ec6dbefeae902327135fa8511f12"
- integrity sha1-WQTcU3w57G2+/q6QIycTX6hRHxI=
+ version "0.2.9"
+ resolved "https://registry.yarnpkg.com/macaddress/-/macaddress-0.2.9.tgz#3579b8b9acd5b96b4553abf0f394185a86813cb3"
+ integrity sha512-k4F1JUof6cQXxNFzx3thLby4oJzXTXQueAOOts944Vqizn+Rjc2QNFenT9FJSLU1CH3PmrHRSyZs2E+Cqw+P2w==
math-expression-evaluator@^1.2.14:
version "1.2.17"
@@ -498,18 +498,18 @@ ms@2.0.0:
integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=
mz@^2.6.0:
- version "2.6.0"
- resolved "https://registry.yarnpkg.com/mz/-/mz-2.6.0.tgz#c8b8521d958df0a4f2768025db69c719ee4ef1ce"
- integrity sha1-yLhSHZWN8KTydoAl22nHGe5O8c4=
+ version "2.7.0"
+ resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32"
+ integrity sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==
dependencies:
any-promise "^1.0.0"
object-assign "^4.0.1"
thenify-all "^1.0.0"
ngx-pipes@^1.6.1:
- version "1.6.5"
- resolved "https://registry.yarnpkg.com/ngx-pipes/-/ngx-pipes-1.6.5.tgz#7dfe7bf1425b2e661ecde0e8a419e82be575dfa1"
- integrity sha512-CtiDGlQITKUszBrHo6JoBOiS8iAuqoEm7ptHMEfD3iJvzRK9tNK4ZEmmBxqUPwzAPyjeGW8ALlul1QdqFrOoSg==
+ version "1.6.6"
+ resolved "https://registry.yarnpkg.com/ngx-pipes/-/ngx-pipes-1.6.6.tgz#32bb80906c220f1e84d5cce7d6dae002cffead4b"
+ integrity sha512-mRV0xOZDd6/Jlvti4W0pDepZRIHLHd3kZ6ZzdqyGCU0dxbKVWWLTR1jlNlxN1ruMk8eO0Y8lNh6a1bEW7dJP1w==
normalize-range@^0.1.2:
version "0.1.2"
@@ -531,7 +531,7 @@ num2fraction@^1.2.2:
resolved "https://registry.yarnpkg.com/num2fraction/-/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede"
integrity sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=
-object-assign@^4.0.1, object-assign@^4.1.0:
+object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
@@ -675,14 +675,14 @@ postcss-minify-selectors@^2.0.4:
postcss "^5.0.14"
postcss-selector-parser "^2.0.0"
-postcss-modules-extract-imports@^1.0.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.2.0.tgz#66140ecece38ef06bf0d3e355d69bf59d141ea85"
- integrity sha1-ZhQOzs447wa/DT41XWm/WdFB6oU=
+postcss-modules-extract-imports@^1.2.0:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.2.1.tgz#dc87e34148ec7eab5f791f7cd5849833375b741a"
+ integrity sha512-6jt9XZwUhwmRUhb/CkyJY020PYaPJsCyt3UjbaWo6XEbH/94Hmv6MP7fG2C5NDU/BcHzyGYxNtHvM+LTf9HrYw==
dependencies:
postcss "^6.0.1"
-postcss-modules-local-by-default@^1.0.1:
+postcss-modules-local-by-default@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-1.2.0.tgz#f7d80c398c5a393fa7964466bd19500a7d61c069"
integrity sha1-99gMOYxaOT+nlkRmvRlQCn1hwGk=
@@ -690,7 +690,7 @@ postcss-modules-local-by-default@^1.0.1:
css-selector-tokenizer "^0.7.0"
postcss "^6.0.1"
-postcss-modules-scope@^1.0.0:
+postcss-modules-scope@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-1.1.0.tgz#d6ea64994c79f97b62a72b426fbe6056a194bb90"
integrity sha1-1upkmUx5+XtipytCb75gVqGUu5A=
@@ -698,7 +698,7 @@ postcss-modules-scope@^1.0.0:
css-selector-tokenizer "^0.7.0"
postcss "^6.0.1"
-postcss-modules-values@^1.1.0:
+postcss-modules-values@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-1.3.0.tgz#ecffa9d7e192518389f42ad0e83f72aec456ea20"
integrity sha1-7P+p1+GSUYOJ9CrQ6D9yrsRW6iA=
@@ -881,10 +881,10 @@ sax@~1.2.1:
resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==
-semver@^5.3.0:
- version "5.4.1"
- resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e"
- integrity sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==
+semver@^6.1.0:
+ version "6.1.2"
+ resolved "https://registry.yarnpkg.com/semver/-/semver-6.1.2.tgz#079960381376a3db62eb2edc8a3bfb10c7cfe318"
+ integrity sha512-z4PqiCpomGtWj8633oeAdXm1Kn1W++3T8epkZYnwiVgIYIJ0QHszhInYSJTYxebByQH7KVCEAn8R9duzZW2PhQ==
sort-keys@^1.0.0:
version "1.1.2"
diff --git a/terminus-settings/README.md b/terminus-settings/README.md
new file mode 100644
index 00000000..88706262
--- /dev/null
+++ b/terminus-settings/README.md
@@ -0,0 +1,23 @@
+Terminus Settings Plugin
+------------------------
+
+* tabbed settings interface
+
+Using the API:
+
+```ts
+import { SettingsTabProvider } from 'terminus-settings'
+```
+
+Exporting your subclasses:
+
+```ts
+@NgModule({
+ ...
+ providers: [
+ ...
+ { provide: SettingsTabProvider, useClass: MySettingsTab, multi: true },
+ ...
+ ]
+})
+```
diff --git a/terminus-settings/package.json b/terminus-settings/package.json
index 19178060..42d61e6c 100644
--- a/terminus-settings/package.json
+++ b/terminus-settings/package.json
@@ -1,12 +1,12 @@
{
"name": "terminus-settings",
- "version": "1.0.0-alpha.55",
+ "version": "1.0.73-c4-ga7d62b0",
"description": "Terminus terminal settings page",
"keywords": [
"terminus-builtin-plugin"
],
"main": "dist/index.js",
- "typings": "dist/src/index.d.ts",
+ "typings": "typings/index.d.ts",
"scripts": {
"build": "webpack --progress --color --display-modules",
"watch": "webpack --progress --color --watch"
@@ -17,9 +17,9 @@
"author": "Eugene Pankov",
"license": "MIT",
"devDependencies": {
- "@types/deep-equal": "1.0.0",
- "@types/node": "7.0.12",
- "@types/webpack-env": "1.13.0",
+ "@types/deep-equal": "1.0.1",
+ "@types/node": "12.0.10",
+ "@types/webpack-env": "1.13.9",
"ngx-pipes": "^1.6.1"
},
"peerDependencies": {
diff --git a/terminus-settings/src/api.ts b/terminus-settings/src/api.ts
index 3c8c841f..9f7f4cd3 100644
--- a/terminus-settings/src/api.ts
+++ b/terminus-settings/src/api.ts
@@ -1,5 +1,9 @@
+/**
+ * Extend to add your own settings tabs
+ */
export abstract class SettingsTabProvider {
id: string
+ icon: string
title: string
getComponentType (): any {
diff --git a/terminus-settings/src/buttonProvider.ts b/terminus-settings/src/buttonProvider.ts
index 381d07fe..545aa360 100644
--- a/terminus-settings/src/buttonProvider.ts
+++ b/terminus-settings/src/buttonProvider.ts
@@ -1,9 +1,10 @@
import { Injectable } from '@angular/core'
import { DomSanitizer } from '@angular/platform-browser'
-import { ToolbarButtonProvider, IToolbarButton, AppService, HostAppService, HotkeysService } from 'terminus-core'
+import { ToolbarButtonProvider, ToolbarButton, AppService, HostAppService, HotkeysService } from 'terminus-core'
import { SettingsTabComponent } from './components/settingsTab.component'
+/** @hidden */
@Injectable()
export class ButtonProvider extends ToolbarButtonProvider {
constructor (
@@ -22,7 +23,7 @@ export class ButtonProvider extends ToolbarButtonProvider {
})
}
- provide (): IToolbarButton[] {
+ provide (): ToolbarButton[] {
return [{
icon: this.domSanitizer.bypassSecurityTrustHtml(require('./icons/cog.svg')),
title: 'Settings',
@@ -33,11 +34,11 @@ export class ButtonProvider extends ToolbarButtonProvider {
}
open (): void {
- let settingsTab = this.app.tabs.find((tab) => tab instanceof SettingsTabComponent)
+ const settingsTab = this.app.tabs.find(tab => tab instanceof SettingsTabComponent)
if (settingsTab) {
this.app.selectTab(settingsTab)
} else {
- this.app.openNewTab(SettingsTabComponent)
+ this.app.openNewTabRaw(SettingsTabComponent)
}
}
}
diff --git a/terminus-settings/src/components/hotkeyInputModal.component.ts b/terminus-settings/src/components/hotkeyInputModal.component.ts
index 332b89a1..b5ee061d 100644
--- a/terminus-settings/src/components/hotkeyInputModal.component.ts
+++ b/terminus-settings/src/components/hotkeyInputModal.component.ts
@@ -6,6 +6,7 @@ import { HotkeysService } from 'terminus-core'
const INPUT_TIMEOUT = 1000
+/** @hidden */
@Component({
selector: 'hotkey-input-modal',
template: require('./hotkeyInputModal.component.pug'),
@@ -20,7 +21,7 @@ const INPUT_TIMEOUT = 1000
animate('250ms ease-out', style({
transform: 'translateX(0)',
opacity: '1',
- }))
+ })),
]),
transition(':leave', [
style({
@@ -30,10 +31,10 @@ const INPUT_TIMEOUT = 1000
animate('250ms ease-in', style({
transform: 'translateX(25px)',
opacity: '0',
- }))
- ])
- ])
- ]
+ })),
+ ]),
+ ]),
+ ],
})
export class HotkeyInputModalComponent {
@Input() value: string[] = []
diff --git a/terminus-settings/src/components/multiHotkeyInput.component.ts b/terminus-settings/src/components/multiHotkeyInput.component.ts
index 4051d99b..78f444ef 100644
--- a/terminus-settings/src/components/multiHotkeyInput.component.ts
+++ b/terminus-settings/src/components/multiHotkeyInput.component.ts
@@ -2,6 +2,7 @@ import { Component, Input, Output, EventEmitter, ChangeDetectionStrategy } from
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
import { HotkeyInputModalComponent } from './hotkeyInputModal.component'
+/** @hidden */
@Component({
selector: 'multi-hotkey-input',
template: require('./multiHotkeyInput.component.pug'),
@@ -23,7 +24,7 @@ export class MultiHotkeyInputComponent {
if (typeof this.model === 'string') {
this.model = [this.model]
}
- this.model = this.model.map(item => (typeof item === 'string') ? [item] : item)
+ this.model = this.model.map(item => typeof item === 'string' ? [item] : item)
}
editItem (item) {
diff --git a/terminus-settings/src/components/settingsTab.component.pug b/terminus-settings/src/components/settingsTab.component.pug
index fdc073f8..4da4f7f4 100644
--- a/terminus-settings/src/components/settingsTab.component.pug
+++ b/terminus-settings/src/components/settingsTab.component.pug
@@ -3,6 +3,7 @@ button.btn.btn-outline-warning.btn-block(*ngIf='config.restartRequested', '(clic
ngb-tabset.vertical(type='pills', [activeId]='activeTab')
ngb-tab(id='application')
ng-template(ngbTabTitle)
+ i.fas.fa-fw.fa-window-maximize.mr-2
| Application
ng-template(ngbTabContent)
.d-flex.align-items-center.mb-4
@@ -12,21 +13,13 @@ ngb-tabset.vertical(type='pills', [activeId]='activeTab')
.text-muted.mr-auto {{homeBase.appVersion}}
button.btn.btn-secondary.mr-3((click)='homeBase.openGitHub()')
- i.fa.fa-github
+ i.fab.fa-github
span GitHub
button.btn.btn-secondary((click)='homeBase.reportBug()')
- i.fa.fa-bug
+ i.fas.fa-bug
span Report a problem
- .form-line(*ngIf='!isShellIntegrationInstalled')
- .header
- .title Shell integration
- .description Allows quickly opening a terminal in the selected folder
- button.btn.btn-primary((click)='installShellIntegration()')
- i.fa.fa-check
- span Install
-
.form-line
.header
.title Theme
@@ -105,6 +98,12 @@ ngb-tabset.vertical(type='pills', [activeId]='activeTab')
step='0.01'
)
+ .form-line(*ngIf='hostApp.platform !== Platform.Linux')
+ .header
+ .title Shell integration
+ .description Allows quickly opening a terminal in the selected folder
+ toggle([ngModel]='isShellIntegrationInstalled', (ngModelChange)='toggleShellIntegration()')
+
.form-line
.header
.title Window frame
@@ -225,13 +224,13 @@ ngb-tabset.vertical(type='pills', [activeId]='activeTab')
.title Debugging
button.btn.btn-secondary((click)='hostApp.openDevTools()')
- i.fa.fa-bug
+ i.fas.fa-bug
span Open DevTools
.form-line
.header
.title Enable analytics
- .description We use Google Analytics
+ .description We're only tracking your Terminus and OS versions.
toggle(
[(ngModel)]='config.store.enableAnalytics',
(ngModelChange)='config.save(); config.requestRestart()',
@@ -247,6 +246,7 @@ ngb-tabset.vertical(type='pills', [activeId]='activeTab')
ngb-tab(id='hotkeys')
ng-template(ngbTabTitle)
+ i.fas.fa-fw.fa-keyboard.mr-2
| Hotkeys
ng-template(ngbTabContent)
h3.mb-3 Hotkeys
@@ -254,7 +254,7 @@ ngb-tabset.vertical(type='pills', [activeId]='activeTab')
.input-group.mb-4
.input-group-prepend
.input-group-text
- i.fa.fa-fw.fa-search
+ i.fas.fa-fw.fa-search
input.form-control(type='search', placeholder='Search hotkeys', [(ngModel)]='hotkeyFilter')
.form-group
@@ -274,6 +274,7 @@ ngb-tabset.vertical(type='pills', [activeId]='activeTab')
ngb-tab(*ngFor='let provider of settingsProviders', [id]='provider.id')
ng-template(ngbTabTitle)
+ i(class='fas fa-fw mr-2 fa-{{provider.icon || "puzzle-piece"}}')
| {{provider.title}}
ng-template(ngbTabContent)
settings-tab-body([provider]='provider')
@@ -281,6 +282,7 @@ ngb-tabset.vertical(type='pills', [activeId]='activeTab')
ngb-tab(id='config-file')
ng-template(ngbTabTitle)
+ i.fas.fa-fw.fa-code.mr-2
| Config file
ng-template.test(ngbTabContent)
.d-flex.flex-column.w-100.h-100
@@ -296,10 +298,13 @@ ngb-tabset.vertical(type='pills', [activeId]='activeTab')
[(ngModel)]='configDefaults',
readonly
)
- .mt-3
+ .mt-2.mb-2.d-flex
button.btn.btn-primary((click)='saveConfigFile()', *ngIf='isConfigFileValid()')
- i.fa.fa-check.mr-2
+ i.fas.fa-check.mr-2
| Save and apply
button.btn.btn-primary(disabled, *ngIf='!isConfigFileValid()')
- i.fa.fa-warning.mr-2
+ i.fas.fa-exclamation-triangle.mr-2
| Invalid syntax
+ button.btn.btn-secondary.ml-auto((click)='showConfigFile()')
+ i.fas.fa-external-link-square-alt.mr-2
+ | Show config file
diff --git a/terminus-settings/src/components/settingsTab.component.ts b/terminus-settings/src/components/settingsTab.component.ts
index 96c8a8da..23ebff1c 100644
--- a/terminus-settings/src/components/settingsTab.component.ts
+++ b/terminus-settings/src/components/settingsTab.component.ts
@@ -2,22 +2,23 @@ import * as yaml from 'js-yaml'
import * as os from 'os'
import { Subscription } from 'rxjs'
import { Component, Inject, Input, HostBinding } from '@angular/core'
-import { HotkeysService } from 'terminus-core'
import {
ElectronService,
DockingService,
ConfigService,
- IHotkeyDescription,
+ HotkeyDescription,
+ HotkeysService,
BaseTabComponent,
Theme,
HostAppService,
Platform,
HomeBaseService,
- ShellIntegrationService
+ ShellIntegrationService,
} from 'terminus-core'
import { SettingsTabProvider } from '../api'
+/** @hidden */
@Component({
selector: 'settings-tab',
template: require('./settingsTab.component.pug'),
@@ -29,7 +30,7 @@ import { SettingsTabProvider } from '../api'
export class SettingsTabComponent extends BaseTabComponent {
@Input() activeTab: string
hotkeyFilter = ''
- hotkeyDescriptions: IHotkeyDescription[]
+ hotkeyDescriptions: HotkeyDescription[]
screens: any[]
Platform = Platform
configDefaults: any
@@ -80,7 +81,16 @@ export class SettingsTabComponent extends BaseTabComponent {
this.isShellIntegrationInstalled = await this.shellIntegration.isInstalled()
}
- getRecoveryToken (): any {
+ async toggleShellIntegration () {
+ if (!this.isShellIntegrationInstalled) {
+ await this.shellIntegration.install()
+ } else {
+ await this.shellIntegration.remove()
+ }
+ this.isShellIntegrationInstalled = await this.shellIntegration.isInstalled()
+ }
+
+ async getRecoveryToken (): Promise {
return { type: 'app:settings' }
}
@@ -90,8 +100,7 @@ export class SettingsTabComponent extends BaseTabComponent {
}
restartApp () {
- this.electron.app.relaunch()
- this.electron.app.exit()
+ this.hostApp.relaunch()
}
saveConfigFile () {
@@ -100,6 +109,10 @@ export class SettingsTabComponent extends BaseTabComponent {
}
}
+ showConfigFile () {
+ this.electron.shell.showItemInFolder(this.config.path)
+ }
+
isConfigFileValid () {
try {
yaml.safeLoad(this.configFile)
@@ -109,14 +122,9 @@ export class SettingsTabComponent extends BaseTabComponent {
}
}
- async installShellIntegration () {
- await this.shellIntegration.install()
- this.isShellIntegrationInstalled = true
- }
-
getHotkey (id: string) {
let ptr = this.config.store.hotkeys
- for (let token of id.split(/\./g)) {
+ for (const token of id.split(/\./g)) {
ptr = ptr[token]
}
return ptr
@@ -125,7 +133,7 @@ export class SettingsTabComponent extends BaseTabComponent {
setHotkey (id: string, value) {
let ptr = this.config.store
let prop = 'hotkeys'
- for (let token of id.split(/\./g)) {
+ for (const token of id.split(/\./g)) {
ptr = ptr[prop]
prop = token
}
diff --git a/terminus-settings/src/components/settingsTab.deep.component.css b/terminus-settings/src/components/settingsTab.deep.component.css
index d985f18b..ddb9bf0c 100644
--- a/terminus-settings/src/components/settingsTab.deep.component.css
+++ b/terminus-settings/src/components/settingsTab.deep.component.css
@@ -13,6 +13,7 @@
padding: 15px 30px;
margin: 0;
overflow-y: auto;
+ height: 100%;
flex: auto;
display: flex;
position: relative;
diff --git a/terminus-settings/src/components/settingsTabBody.component.ts b/terminus-settings/src/components/settingsTabBody.component.ts
index 5060b023..9202faf7 100644
--- a/terminus-settings/src/components/settingsTabBody.component.ts
+++ b/terminus-settings/src/components/settingsTabBody.component.ts
@@ -1,13 +1,14 @@
import { Component, Input, ViewContainerRef, ViewChild, ComponentFactoryResolver, ComponentRef } from '@angular/core'
import { SettingsTabProvider } from '../api'
+/** @hidden */
@Component({
selector: 'settings-tab-body',
template: ' ',
})
export class SettingsTabBodyComponent {
@Input() provider: SettingsTabProvider
- @ViewChild('placeholder', {read: ViewContainerRef}) placeholder: ViewContainerRef
+ @ViewChild('placeholder', { read: ViewContainerRef }) placeholder: ViewContainerRef
component: ComponentRef
constructor (private componentFactoryResolver: ComponentFactoryResolver) { }
diff --git a/terminus-settings/src/config.ts b/terminus-settings/src/config.ts
index 51c1a35e..4ac51d6e 100644
--- a/terminus-settings/src/config.ts
+++ b/terminus-settings/src/config.ts
@@ -1,22 +1,23 @@
import { ConfigProvider, Platform } from 'terminus-core'
+/** @hidden */
export class SettingsConfigProvider extends ConfigProvider {
defaults = { }
platformDefaults = {
[Platform.macOS]: {
hotkeys: {
settings: ['β-,'],
- }
+ },
},
[Platform.Windows]: {
hotkeys: {
- settings: ['Ctrl-,']
- }
+ settings: ['Ctrl-,'],
+ },
},
[Platform.Linux]: {
hotkeys: {
- settings: ['Ctrl-,']
- }
+ settings: ['Ctrl-,'],
+ },
},
}
}
diff --git a/terminus-settings/src/hotkeys.ts b/terminus-settings/src/hotkeys.ts
index 08585bc1..db62ec24 100644
--- a/terminus-settings/src/hotkeys.ts
+++ b/terminus-settings/src/hotkeys.ts
@@ -1,16 +1,17 @@
import { Injectable } from '@angular/core'
-import { IHotkeyDescription, HotkeyProvider } from 'terminus-core'
+import { HotkeyDescription, HotkeyProvider } from 'terminus-core'
+/** @hidden */
@Injectable()
export class SettingsHotkeyProvider extends HotkeyProvider {
- hotkeys: IHotkeyDescription[] = [
+ hotkeys: HotkeyDescription[] = [
{
id: 'settings',
name: 'Open Settings',
},
]
- async provide (): Promise {
+ async provide (): Promise {
return this.hotkeys
}
}
diff --git a/terminus-settings/src/index.ts b/terminus-settings/src/index.ts
index 92c021ff..7708b149 100644
--- a/terminus-settings/src/index.ts
+++ b/terminus-settings/src/index.ts
@@ -4,8 +4,7 @@ import { FormsModule } from '@angular/forms'
import { NgbModule } from '@ng-bootstrap/ng-bootstrap'
import { NgPipesModule } from 'ngx-pipes'
-import { ToolbarButtonProvider, TabRecoveryProvider, HotkeyProvider, ConfigProvider } from 'terminus-core'
-import TerminusCorePlugin from 'terminus-core'
+import TerminusCorePlugin, { ToolbarButtonProvider, TabRecoveryProvider, HotkeyProvider, ConfigProvider } from 'terminus-core'
import { HotkeyInputModalComponent } from './components/hotkeyInputModal.component'
import { MultiHotkeyInputComponent } from './components/multiHotkeyInput.component'
@@ -17,6 +16,7 @@ import { RecoveryProvider } from './recoveryProvider'
import { SettingsHotkeyProvider } from './hotkeys'
import { SettingsConfigProvider } from './config'
+/** @hidden */
@NgModule({
imports: [
BrowserModule,
@@ -42,7 +42,7 @@ import { SettingsConfigProvider } from './config'
SettingsTabBodyComponent,
],
})
-export default class SettingsModule { }
+export default class SettingsModule { } // eslint-disable-line @typescript-eslint/no-extraneous-class
export * from './api'
export { SettingsTabComponent }
diff --git a/terminus-settings/src/recoveryProvider.ts b/terminus-settings/src/recoveryProvider.ts
index 442e7e2f..7ae40eb7 100644
--- a/terminus-settings/src/recoveryProvider.ts
+++ b/terminus-settings/src/recoveryProvider.ts
@@ -3,10 +3,11 @@ import { TabRecoveryProvider, RecoveredTab } from 'terminus-core'
import { SettingsTabComponent } from './components/settingsTab.component'
+/** @hidden */
@Injectable()
export class RecoveryProvider extends TabRecoveryProvider {
async recover (recoveryToken: any): Promise {
- if (recoveryToken.type === 'app:settings') {
+ if (recoveryToken && recoveryToken.type === 'app:settings') {
return { type: SettingsTabComponent }
}
return null
diff --git a/terminus-settings/tsconfig.json b/terminus-settings/tsconfig.json
index 1d6cfcbf..e0611107 100644
--- a/terminus-settings/tsconfig.json
+++ b/terminus-settings/tsconfig.json
@@ -3,6 +3,5 @@
"exclude": ["node_modules", "dist"],
"compilerOptions": {
"baseUrl": "src",
- "declarationDir": "dist"
}
}
diff --git a/terminus-settings/tsconfig.typings.json b/terminus-settings/tsconfig.typings.json
new file mode 100644
index 00000000..c0d2273c
--- /dev/null
+++ b/terminus-settings/tsconfig.typings.json
@@ -0,0 +1,14 @@
+{
+ "extends": "../tsconfig.json",
+ "exclude": ["node_modules", "dist", "typings"],
+ "compilerOptions": {
+ "baseUrl": "src",
+ "emitDeclarationOnly": true,
+ "declaration": true,
+ "declarationDir": "./typings",
+ "paths": {
+ "terminus-*": ["../../terminus-*"],
+ "*": ["../../app/node_modules/*"]
+ }
+ }
+}
diff --git a/terminus-settings/webpack.config.js b/terminus-settings/webpack.config.js
index 49376b28..e53cda9b 100644
--- a/terminus-settings/webpack.config.js
+++ b/terminus-settings/webpack.config.js
@@ -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,
},
diff --git a/terminus-settings/yarn.lock b/terminus-settings/yarn.lock
index 05f906ab..97824fd1 100644
--- a/terminus-settings/yarn.lock
+++ b/terminus-settings/yarn.lock
@@ -2,22 +2,22 @@
# yarn lockfile v1
-"@types/deep-equal@1.0.0":
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/@types/deep-equal/-/deep-equal-1.0.0.tgz#9ebeaa73d1fc4791f038a5f1440e0449ea968495"
- integrity sha1-nr6qc9H8R5HwOKXxRA4ESeqWhJU=
+"@types/deep-equal@1.0.1":
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/@types/deep-equal/-/deep-equal-1.0.1.tgz#71cfabb247c22bcc16d536111f50c0ed12476b03"
+ integrity sha512-mMUu4nWHLBlHtxXY17Fg6+ucS/MnndyOWyOe7MmwkoMYxvfQU2ajtRaEvqSUv+aVkMqH/C0NCI8UoVfRNQ10yg==
-"@types/node@7.0.12":
- version "7.0.12"
- resolved "https://registry.yarnpkg.com/@types/node/-/node-7.0.12.tgz#ae5f67a19c15f752148004db07cbbb372e69efc9"
- integrity sha1-rl9noZwV91IUgATbB8u7Ny5p78k=
+"@types/node@12.0.10":
+ version "12.0.10"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-12.0.10.tgz#51babf9c7deadd5343620055fc8aff7995c8b031"
+ integrity sha512-LcsGbPomWsad6wmMNv7nBLw7YYYyfdYcz6xryKYQhx89c3XXan+8Q6AJ43G5XDIaklaVkK3mE4fCb0SBvMiPSQ==
-"@types/webpack-env@1.13.0":
- version "1.13.0"
- resolved "https://registry.yarnpkg.com/@types/webpack-env/-/webpack-env-1.13.0.tgz#3044381647e11ee973c5af2e925323930f691d80"
- integrity sha1-MEQ4FkfhHulzxa8uklMjkw9pHYA=
+"@types/webpack-env@1.13.9":
+ version "1.13.9"
+ resolved "https://registry.yarnpkg.com/@types/webpack-env/-/webpack-env-1.13.9.tgz#a67287861c928ebf4159a908d1fb1a2a34d4097a"
+ integrity sha512-p8zp5xqkly3g4cCmo2mKOHI9+Z/kObmDj0BmjbDDJQlgDTiEGTbm17MEwTAusV6XceCy+bNw9q/ZHXHyKo3zkg==
ngx-pipes@^1.6.1:
- version "1.6.5"
- resolved "https://registry.yarnpkg.com/ngx-pipes/-/ngx-pipes-1.6.5.tgz#7dfe7bf1425b2e661ecde0e8a419e82be575dfa1"
- integrity sha512-CtiDGlQITKUszBrHo6JoBOiS8iAuqoEm7ptHMEfD3iJvzRK9tNK4ZEmmBxqUPwzAPyjeGW8ALlul1QdqFrOoSg==
+ version "1.6.6"
+ resolved "https://registry.yarnpkg.com/ngx-pipes/-/ngx-pipes-1.6.6.tgz#32bb80906c220f1e84d5cce7d6dae002cffead4b"
+ integrity sha512-mRV0xOZDd6/Jlvti4W0pDepZRIHLHd3kZ6ZzdqyGCU0dxbKVWWLTR1jlNlxN1ruMk8eO0Y8lNh6a1bEW7dJP1w==
diff --git a/terminus-ssh/package.json b/terminus-ssh/package.json
index 46076857..b7e29a59 100644
--- a/terminus-ssh/package.json
+++ b/terminus-ssh/package.json
@@ -1,12 +1,12 @@
{
"name": "terminus-ssh",
- "version": "1.0.0-alpha.55",
+ "version": "1.0.73-c4-ga7d62b0",
"description": "SSH connection manager for Terminus",
"keywords": [
"terminus-builtin-plugin"
],
"main": "dist/index.js",
- "typings": "dist/index.d.ts",
+ "typings": "typings/index.d.ts",
"scripts": {
"build": "webpack --progress --color",
"watch": "webpack --progress --color --watch"
@@ -19,26 +19,23 @@
"devDependencies": {
"@types/ssh2": "^0.5.35",
"@types/webpack-env": "^1.13.0",
- "electron": "^1.6.11",
- "ngx-toastr": "^8.0.0",
- "rxjs": "^5.4.0",
- "typescript": "^2.2.2",
- "webpack": "^2.3.3"
+ "ssh2": "^0.8.2",
+ "ssh2-streams": "^0.4.2"
},
"peerDependencies": {
"@angular/common": "^4.1.3",
"@angular/core": "^4.1.3",
"@angular/forms": "^4.1.3",
"@ng-bootstrap/ng-bootstrap": "^1.0.0-alpha.29",
+ "rxjs": "^5.4.0",
"terminus-core": "*",
"terminus-settings": "*",
"terminus-terminal": "*"
},
"optionalDependencies": {
- "wincredmgr": "^2.0.0",
- "xkeychain": "^0.0.6"
+ "windows-process-tree": "^0.2.3"
},
"dependencies": {
- "ssh2": "^0.5.5"
+ "keytar": "^4.7.0"
}
}
diff --git a/terminus-ssh/src/api.ts b/terminus-ssh/src/api.ts
index f2650340..ead3db4a 100644
--- a/terminus-ssh/src/api.ts
+++ b/terminus-ssh/src/api.ts
@@ -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,30 +26,33 @@ export interface SSHConnection {
keepaliveInterval?: number
keepaliveCountMax?: number
readyTimeout?: number
+
+ algorithms?: {[t: string]: string[]}
}
export class SSHSession extends BaseSession {
scripts?: LoginScript[]
+ shell: any
- constructor (private shell: any, conn: SSHConnection) {
+ constructor (public connection: SSHConnection) {
super()
- this.scripts = conn.scripts || []
+ this.scripts = connection.scripts || []
}
start () {
this.open = true
this.shell.on('data', data => {
- let dataString = data.toString()
+ const dataString = data.toString()
this.emitOutput(dataString)
if (this.scripts) {
let found = false
- for (let script of this.scripts) {
+ for (const script of this.scripts) {
let match = false
let cmd = ''
if (script.isRegex) {
- let re = new RegExp(script.expect, 'g')
+ const re = new RegExp(script.expect, 'g')
if (dataString.match(re)) {
cmd = dataString.replace(re, script.send)
match = true
@@ -87,15 +97,21 @@ export class SSHSession extends BaseSession {
}
resize (columns, rows) {
- this.shell.setWindow(rows, columns)
+ if (this.shell) {
+ this.shell.setWindow(rows, columns)
+ }
}
write (data) {
- this.shell.write(data)
+ if (this.shell) {
+ this.shell.write(data)
+ }
}
kill (signal?: string) {
- this.shell.signal(signal || 'TERM')
+ if (this.shell) {
+ this.shell.signal(signal || 'TERM')
+ }
}
async getChildProcesses (): Promise {
@@ -112,7 +128,7 @@ export class SSHSession extends BaseSession {
private executeUnconditionalScripts () {
if (this.scripts) {
- for (let script of this.scripts) {
+ for (const script of this.scripts) {
if (!script.expect) {
console.log('Executing script:', script.send)
this.shell.write(script.send + '\n')
@@ -125,7 +141,7 @@ export class SSHSession extends BaseSession {
}
}
-export interface ISSHConnectionGroup {
+export interface SSHConnectionGroup {
name: string
connections: SSHConnection[]
}
diff --git a/terminus-ssh/src/buttonProvider.ts b/terminus-ssh/src/buttonProvider.ts
index 054821a2..3cbc9c1e 100644
--- a/terminus-ssh/src/buttonProvider.ts
+++ b/terminus-ssh/src/buttonProvider.ts
@@ -1,9 +1,10 @@
import { Injectable } from '@angular/core'
import { DomSanitizer } from '@angular/platform-browser'
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
-import { HotkeysService, ToolbarButtonProvider, IToolbarButton } from 'terminus-core'
+import { HotkeysService, ToolbarButtonProvider, ToolbarButton } from 'terminus-core'
import { SSHModalComponent } from './components/sshModal.component'
+/** @hidden */
@Injectable()
export class ButtonProvider extends ToolbarButtonProvider {
constructor (
@@ -12,7 +13,7 @@ export class ButtonProvider extends ToolbarButtonProvider {
hotkeys: HotkeysService,
) {
super()
- hotkeys.matchedHotkey.subscribe(async (hotkey) => {
+ hotkeys.matchedHotkey.subscribe(async (hotkey: string) => {
if (hotkey === 'ssh') {
this.activate()
}
@@ -23,7 +24,7 @@ export class ButtonProvider extends ToolbarButtonProvider {
this.ngbModal.open(SSHModalComponent)
}
- provide (): IToolbarButton[] {
+ provide (): ToolbarButton[] {
return [{
icon: this.domSanitizer.bypassSecurityTrustHtml(require('./icons/globe.svg')),
weight: 5,
@@ -31,7 +32,7 @@ export class ButtonProvider extends ToolbarButtonProvider {
touchBarNSImage: 'NSTouchBarOpenInBrowserTemplate',
click: async () => {
this.activate()
- }
+ },
}]
}
}
diff --git a/terminus-ssh/src/components/editConnectionModal.component.pug b/terminus-ssh/src/components/editConnectionModal.component.pug
index e2b7ce73..24a51cf4 100644
--- a/terminus-ssh/src/components/editConnectionModal.component.pug
+++ b/terminus-ssh/src/components/editConnectionModal.component.pug
@@ -1,8 +1,7 @@
.modal-body
ngb-tabset(type='pills', [activeId]='basic')
ngb-tab(id='basic')
- ng-template(ngbTabTitle)
- | Basic Setting
+ ng-template(ngbTabTitle) General
ng-template(ngbTabContent)
.form-group
label Name
@@ -42,12 +41,22 @@
[(ngModel)]='connection.user',
)
- .alert.alert-info.d-flex.bg-transparent.text-white.align-items-center(*ngIf='hasSavedPassword')
- .mr-auto There is a saved password for this connection
- button.btn.btn-danger.ml-4((click)='clearSavedPassword()') Forget
+ .form-line
+ .header
+ .title Password
+ .description(*ngIf='!hasSavedPassword') Save a password in the keychain
+ .description(*ngIf='hasSavedPassword') There is a saved password for this connection
+ button.btn.btn-outline-success.ml-4(*ngIf='!hasSavedPassword', (click)='setPassword()')
+ i.fas.fa-key
+ span Set password
+ button.btn.btn-danger.ml-4(*ngIf='hasSavedPassword', (click)='clearSavedPassword()')
+ i.fas.fa-trash-alt
+ span Forget
- .form-group
- label Private key
+ .form-line
+ .header
+ .title Private key
+ .description Path to the private key file
.input-group
input.form-control(
type='text',
@@ -56,11 +65,10 @@
)
.input-group-btn
button.btn.btn-secondary((click)='selectPrivateKey()')
- i.fa.fa-folder-open
+ i.fas.fa-folder-open
ngb-tab(id='advanced')
- ng-template(ngbTabTitle)
- | Advanced Setting
+ ng-template(ngbTabTitle) Advanced
ng-template(ngbTabContent)
.form-group
label Keep Alive Interval (Milliseconds)
@@ -85,20 +93,40 @@
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)
- | Login Scripts
+ ng-template(ngbTabTitle) Login scripts
ng-template(ngbTabContent)
- table
+ table(*ngIf='connection.scripts.length > 0')
tr
th String to expect
th String to be sent
- th Regex
- th Optional
- th Actions
+ th.pl-2 Regex
+ th.pl-2 Optional
+ th.pl-2 Actions
tr(*ngFor='let script of connection.scripts')
- td
+ td.pr-2
input.form-control(
type='text',
[(ngModel)]='script.expect'
@@ -108,50 +136,27 @@
type='text',
[(ngModel)]='script.send'
)
- td
- toggle(
+ td.pl-2
+ checkbox(
[(ngModel)]='script.isRegex',
)
- td
- toggle(
+ td.pl-2
+ checkbox(
[(ngModel)]='script.optional',
)
- td
+ td.pl-2
.input-group.flex-nowrap
button.btn.btn-outline-info.ml-0((click)='moveScriptUp(script)')
- i.fa.fa-arrow-up
+ i.fas.fa-arrow-up
button.btn.btn-outline-info.ml-0((click)='moveScriptDown(script)')
- i.fa.fa-arrow-down
+ i.fas.fa-arrow-down
button.btn.btn-outline-danger.ml-0((click)='deleteScript(script)')
- i.fa.fa-trash-o
- tr
- td
- input.form-control(
- type='text',
- placeholder='Enter a string to expect',
- [(ngModel)]='newScript.expect'
- )
- td
- input.form-control(
- type='text',
- placeholder='Enter a string to be sent',
- [(ngModel)]='newScript.send'
- )
- td
- toggle(
- [(ngModel)]='newScript.isRegex',
- )
- td
- toggle(
- [(ngModel)]='newScript.optional',
- )
- td
- .input-group.flex-nowrap
- button.btn.btn-outline-info.ml-0((click)='addScript()')
- i.fa.fa-check
- button.btn.btn-outline-danger.ml-0((click)='clearScript()')
- i.fa.fa-trash-o
-
+ i.fas.fa-trash
+
+ button.btn.btn-outline-info.mt-2((click)='addScript()')
+ i.fas.fa-plus
+ span New item
+
.modal-footer
button.btn.btn-outline-primary((click)='save()') Save
button.btn.btn-outline-danger((click)='cancel()') Cancel
diff --git a/terminus-ssh/src/components/editConnectionModal.component.ts b/terminus-ssh/src/components/editConnectionModal.component.ts
index 560b91f5..ff250548 100644
--- a/terminus-ssh/src/components/editConnectionModal.component.ts
+++ b/terminus-ssh/src/components/editConnectionModal.component.ts
@@ -1,28 +1,76 @@
import { Component } from '@angular/core'
-import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
+import { NgbModal, 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 { PromptModalComponent } from './promptModal.component'
+import { ALGORITHMS } from 'ssh2-streams/lib/constants'
+/** @hidden */
@Component({
template: require('./editConnectionModal.component.pug'),
})
export class EditConnectionModalComponent {
connection: SSHConnection
- 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,
private hostApp: HostAppService,
private passwordStorage: PasswordStorageService,
+ private ngbModal: NgbModal,
) {
- this.newScript = { expect: '', send: '' }
+ for (const k of Object.values(SSHAlgorithmType)) {
+ const supportedAlg = {
+ [SSHAlgorithmType.KEX]: 'SUPPORTED_KEX',
+ [SSHAlgorithmType.HOSTKEY]: 'SUPPORTED_SERVER_HOST_KEY',
+ [SSHAlgorithmType.CIPHER]: 'SUPPORTED_CIPHER',
+ [SSHAlgorithmType.HMAC]: 'SUPPORTED_HMAC',
+ }[k]
+ const defaultAlg = {
+ [SSHAlgorithmType.KEX]: 'KEX',
+ [SSHAlgorithmType.HOSTKEY]: 'SERVER_HOST_KEY',
+ [SSHAlgorithmType.CIPHER]: 'CIPHER',
+ [SSHAlgorithmType.HMAC]: 'HMAC',
+ }[k]
+ this.supportedAlgorithms[k] = ALGORITHMS[supportedAlg]
+ this.defaultAlgorithms[k] = ALGORITHMS[defaultAlg]
+ }
}
async ngOnInit () {
- this.hasSavedPassword = !!(await this.passwordStorage.loadPassword(this.connection))
+ this.hasSavedPassword = !!await this.passwordStorage.loadPassword(this.connection)
+ this.connection.algorithms = this.connection.algorithms || {}
+ this.connection.scripts = this.connection.scripts || []
+
+ for (const k of Object.values(SSHAlgorithmType)) {
+ if (!this.connection.algorithms[k]) {
+ this.connection.algorithms[k] = this.defaultAlgorithms[k]
+ }
+
+ this.algorithms[k] = {}
+ for (const alg of this.connection.algorithms[k]) {
+ this.algorithms[k][alg] = true
+ }
+ }
+ }
+
+ async setPassword () {
+ const modal = this.ngbModal.open(PromptModalComponent)
+ modal.componentInstance.prompt = `Password for ${this.connection.user}@${this.connection.host}`
+ modal.componentInstance.password = true
+ try {
+ const result = await modal.result
+ if (result && result.value) {
+ this.passwordStorage.savePassword(this.connection, result.value)
+ this.hasSavedPassword = true
+ }
+ } catch { }
}
clearSavedPassword () {
@@ -31,7 +79,7 @@ export class EditConnectionModalComponent {
}
selectPrivateKey () {
- let path = this.electron.dialog.showOpenDialog(
+ const path = this.electron.dialog.showOpenDialog(
this.hostApp.getWindow(),
{
title: 'Select private key',
@@ -43,6 +91,11 @@ export class EditConnectionModalComponent {
}
save () {
+ for (const 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)
}
@@ -51,7 +104,7 @@ export class EditConnectionModalComponent {
}
moveScriptUp (script: LoginScript) {
- let index = this.connection.scripts.indexOf(script)
+ const index = this.connection.scripts.indexOf(script)
if (index > 0) {
this.connection.scripts.splice(index, 1)
this.connection.scripts.splice(index - 1, 0, script)
@@ -59,31 +112,29 @@ export class EditConnectionModalComponent {
}
moveScriptDown (script: LoginScript) {
- let index = this.connection.scripts.indexOf(script)
+ const index = this.connection.scripts.indexOf(script)
if (index >= 0 && index < this.connection.scripts.length - 1) {
this.connection.scripts.splice(index, 1)
this.connection.scripts.splice(index + 1, 0, script)
}
}
- deleteScript (script: LoginScript) {
- if (confirm(`Delete?`)) {
+ async deleteScript (script: LoginScript) {
+ if ((await this.electron.showMessageBox(
+ this.hostApp.getWindow(),
+ {
+ type: 'warning',
+ message: 'Delete this script?',
+ detail: script.expect,
+ buttons: ['Keep', 'Delete'],
+ defaultId: 1,
+ }
+ )).response === 1) {
this.connection.scripts = this.connection.scripts.filter(x => x !== script)
}
}
addScript () {
- if (!this.connection.scripts) {
- this.connection.scripts = []
- }
- this.connection.scripts.push({...this.newScript})
- this.clearScript()
- }
-
- clearScript () {
- this.newScript.expect = ''
- this.newScript.send = ''
- this.newScript.isRegex = false
- this.newScript.optional = false
+ this.connection.scripts.push({ expect: '', send: '' })
}
}
diff --git a/terminus-ssh/src/components/promptModal.component.pug b/terminus-ssh/src/components/promptModal.component.pug
index 92369ab7..1dfb759c 100644
--- a/terminus-ssh/src/components/promptModal.component.pug
+++ b/terminus-ssh/src/components/promptModal.component.pug
@@ -8,3 +8,12 @@
(keyup.enter)='ok()',
(keyup.esc)='cancel()',
)
+ .d-flex.align-items-start.mt-2
+ checkbox(
+ *ngIf='showRememberCheckbox',
+ [(ngModel)]='remember',
+ text='Remember'
+ )
+ button.btn.btn-primary.ml-auto(
+ (click)='ok()',
+ ) Enter
diff --git a/terminus-ssh/src/components/promptModal.component.ts b/terminus-ssh/src/components/promptModal.component.ts
index e67c10d3..262e0573 100644
--- a/terminus-ssh/src/components/promptModal.component.ts
+++ b/terminus-ssh/src/components/promptModal.component.ts
@@ -1,12 +1,15 @@
import { Component, Input, ViewChild, ElementRef } from '@angular/core'
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
+/** @hidden */
@Component({
template: require('./promptModal.component.pug'),
})
export class PromptModalComponent {
@Input() value: string
@Input() password: boolean
+ @Input() remember: boolean
+ @Input() showRememberCheckbox: boolean
@ViewChild('input') input: ElementRef
constructor (
@@ -20,10 +23,13 @@ export class PromptModalComponent {
}
ok () {
- this.modalInstance.close(this.value)
+ this.modalInstance.close({
+ value: this.value,
+ remember: this.remember,
+ })
}
cancel () {
- this.modalInstance.close('')
+ this.modalInstance.close(null)
}
}
diff --git a/terminus-ssh/src/components/sshModal.component.pug b/terminus-ssh/src/components/sshModal.component.pug
index 2bd90229..f1d97ae6 100644
--- a/terminus-ssh/src/components/sshModal.component.pug
+++ b/terminus-ssh/src/components/sshModal.component.pug
@@ -10,10 +10,10 @@
.list-group.mt-3(*ngIf='lastConnection')
a.list-group-item.list-group-item-action.d-flex.align-items-center((click)='connect(lastConnection)')
- i.fa.fa-fw.fa-history
+ i.fas.fa-fw.fa-history
.mr-auto {{lastConnection.name}}
button.btn.btn-outline-danger.btn-sm((click)='clearLastConnection(); $event.stopPropagation()')
- i.fa.fa-trash-o
+ i.fas.fa-trash
.list-group.mt-3.connections-list(*ngIf='childGroups.length')
ng-container(*ngFor='let group of childGroups')
@@ -27,4 +27,6 @@
.list-group-item.list-group-item-action.pl-5.d-flex.align-items-center(
*ngFor='let connection of group.connections',
(click)='connect(connection)'
- ) {{connection.name}}
+ )
+ .mr-2 {{connection.name}}
+ .text-muted {{connection.host}}
diff --git a/terminus-ssh/src/components/sshModal.component.ts b/terminus-ssh/src/components/sshModal.component.ts
index dbc79d08..ea8958fc 100644
--- a/terminus-ssh/src/components/sshModal.component.ts
+++ b/terminus-ssh/src/components/sshModal.component.ts
@@ -4,18 +4,19 @@ import { ToastrService } from 'ngx-toastr'
import { ConfigService, AppService } from 'terminus-core'
import { SettingsTabComponent } from 'terminus-settings'
import { SSHService } from '../services/ssh.service'
-import { SSHConnection, ISSHConnectionGroup } from '../api'
+import { SSHConnection, SSHConnectionGroup } from '../api'
+/** @hidden */
@Component({
template: require('./sshModal.component.pug'),
styles: [require('./sshModal.component.scss')],
})
export class SSHModalComponent {
connections: SSHConnection[]
- childFolders: ISSHConnectionGroup[]
+ childFolders: SSHConnectionGroup[]
quickTarget: string
lastConnection: SSHConnection
- childGroups: ISSHConnectionGroup[]
+ childGroups: SSHConnectionGroup[]
groupCollapsed: {[id: string]: boolean} = {}
constructor (
@@ -46,9 +47,11 @@ export class SSHModalComponent {
host = host.split(':')[0]
}
- let connection: SSHConnection = {
+ const connection: SSHConnection = {
name: this.quickTarget,
- host, user, port
+ host,
+ user,
+ port,
}
window.localStorage.lastConnection = JSON.stringify(connection)
this.connect(connection)
@@ -61,7 +64,7 @@ export class SSHModalComponent {
connect (connection: SSHConnection) {
this.close()
- this.ssh.connect(connection).catch(error => {
+ this.ssh.openTab(connection).catch(error => {
this.toastr.error(`Could not connect: ${error}`)
}).then(() => {
setTimeout(() => {
@@ -87,7 +90,7 @@ export class SSHModalComponent {
connections = connections.filter(connection => (connection.name + connection.group).toLowerCase().includes(this.quickTarget))
}
- for (let connection of connections) {
+ for (const connection of connections) {
connection.group = connection.group || null
let group = this.childGroups.find(x => x.name === connection.group)
if (!group) {
diff --git a/terminus-ssh/src/components/sshSettingsTab.component.pug b/terminus-ssh/src/components/sshSettingsTab.component.pug
index af09e18a..463c79c5 100644
--- a/terminus-ssh/src/components/sshSettingsTab.component.pug
+++ b/terminus-ssh/src/components/sshSettingsTab.component.pug
@@ -1,25 +1,28 @@
h3 Connections
-.list-group.mt-3.mb-3
+.list-group.list-group-flush.mt-3.mb-3
ng-container(*ngFor='let group of childGroups')
- .list-group-item.list-group-item-action.d-flex.align-items-center((click)='groupCollapsed[group.name] = !groupCollapsed[group.name]')
+ .list-group-item.list-group-item-action.d-flex.align-items-center(
+ (click)='groupCollapsed[group.name] = !groupCollapsed[group.name]'
+ )
.fa.fa-fw.fa-chevron-right(*ngIf='groupCollapsed[group.name]')
.fa.fa-fw.fa-chevron-down(*ngIf='!groupCollapsed[group.name]')
span.ml-3.mr-auto {{group.name || "Ungrouped"}}
button.btn.btn-outline-info.ml-2((click)='editGroup(group)')
- i.fa.fa-pencil
+ i.fas.fa-edit
button.btn.btn-outline-danger.ml-1((click)='deleteGroup(group)')
- i.fa.fa-trash-o
+ i.fas.fa-trash
ng-container(*ngIf='!groupCollapsed[group.name]')
- .list-group-item.pl-5.d-flex.align-items-center(*ngFor='let connection of group.connections')
+ .list-group-item.list-group-item-action.pl-5.d-flex.align-items-center(
+ *ngFor='let connection of group.connections',
+ (click)='editConnection(connection)'
+ )
.mr-auto
div {{connection.name}}
.text-muted {{connection.host}}
- button.btn.btn-outline-info.ml-2((click)='editConnection(connection)')
- i.fa.fa-pencil
- button.btn.btn-outline-danger.ml-1((click)='deleteConnection(connection)')
- i.fa.fa-trash-o
+ button.btn.btn-outline-danger.ml-1((click)='$event.stopPropagation(); deleteConnection(connection)')
+ i.fas.fa-trash
-button.btn.btn-outline-primary((click)='createConnection()')
- div.fa.fa-fw.fa-globe
+button.btn.btn-primary((click)='createConnection()')
+ i.fas.fa-fw.fa-plus
span.ml-2 Add connection
diff --git a/terminus-ssh/src/components/sshSettingsTab.component.ts b/terminus-ssh/src/components/sshSettingsTab.component.ts
index e5ee994e..e9d6c6f9 100644
--- a/terminus-ssh/src/components/sshSettingsTab.component.ts
+++ b/terminus-ssh/src/components/sshSettingsTab.component.ts
@@ -1,20 +1,23 @@
import { Component } from '@angular/core'
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
-import { ConfigService } from 'terminus-core'
-import { SSHConnection, ISSHConnectionGroup } from '../api'
+import { ConfigService, ElectronService, HostAppService } from 'terminus-core'
+import { SSHConnection, SSHConnectionGroup } from '../api'
import { EditConnectionModalComponent } from './editConnectionModal.component'
import { PromptModalComponent } from './promptModal.component'
+/** @hidden */
@Component({
template: require('./sshSettingsTab.component.pug'),
})
export class SSHSettingsTabComponent {
connections: SSHConnection[]
- childGroups: ISSHConnectionGroup[]
+ childGroups: SSHConnectionGroup[]
groupCollapsed: {[id: string]: boolean} = {}
constructor (
public config: ConfigService,
+ private electron: ElectronService,
+ private hostApp: HostAppService,
private ngbModal: NgbModal,
) {
this.connections = this.config.store.ssh.connections
@@ -22,14 +25,14 @@ export class SSHSettingsTabComponent {
}
createConnection () {
- let connection: SSHConnection = {
+ const connection: SSHConnection = {
name: '',
host: '',
port: 22,
user: 'root',
}
- let modal = this.ngbModal.open(EditConnectionModalComponent)
+ const modal = this.ngbModal.open(EditConnectionModalComponent)
modal.componentInstance.connection = connection
modal.result.then(result => {
this.connections.push(result)
@@ -40,17 +43,26 @@ export class SSHSettingsTabComponent {
}
editConnection (connection: SSHConnection) {
- let modal = this.ngbModal.open(EditConnectionModalComponent)
+ const modal = this.ngbModal.open(EditConnectionModalComponent, { size: 'lg' })
modal.componentInstance.connection = Object.assign({}, connection)
modal.result.then(result => {
Object.assign(connection, result)
+ this.config.store.ssh.connections = this.connections
this.config.save()
this.refresh()
})
}
- deleteConnection (connection: SSHConnection) {
- if (confirm(`Delete "${connection.name}"?`)) {
+ async deleteConnection (connection: SSHConnection) {
+ if ((await this.electron.showMessageBox(
+ this.hostApp.getWindow(),
+ {
+ type: 'warning',
+ message: `Delete "${connection.name}"?`,
+ buttons: ['Keep', 'Delete'],
+ defaultId: 1,
+ }
+ )).response === 1) {
this.connections = this.connections.filter(x => x !== connection)
this.config.store.ssh.connections = this.connections
this.config.save()
@@ -58,24 +70,33 @@ export class SSHSettingsTabComponent {
}
}
- editGroup (group: ISSHConnectionGroup) {
- let modal = this.ngbModal.open(PromptModalComponent)
+ editGroup (group: SSHConnectionGroup) {
+ const modal = this.ngbModal.open(PromptModalComponent)
modal.componentInstance.prompt = 'New group name'
modal.componentInstance.value = group.name
modal.result.then(result => {
if (result) {
- for (let connection of this.connections.filter(x => x.group === group.name)) {
- connection.group = result
+ for (const connection of this.connections.filter(x => x.group === group.name)) {
+ connection.group = result.value
}
+ this.config.store.ssh.connections = this.connections
this.config.save()
this.refresh()
}
})
}
- deleteGroup (group: ISSHConnectionGroup) {
- if (confirm(`Delete "${group}"?`)) {
- for (let connection of this.connections.filter(x => x.group === group.name)) {
+ async deleteGroup (group: SSHConnectionGroup) {
+ if ((await this.electron.showMessageBox(
+ this.hostApp.getWindow(),
+ {
+ type: 'warning',
+ message: `Delete "${group}"?`,
+ buttons: ['Keep', 'Delete'],
+ defaultId: 1,
+ }
+ )).response === 1) {
+ for (const connection of this.connections.filter(x => x.group === group.name)) {
connection.group = null
}
this.config.save()
@@ -84,9 +105,10 @@ export class SSHSettingsTabComponent {
}
refresh () {
+ this.connections = this.config.store.ssh.connections
this.childGroups = []
- for (let connection of this.connections) {
+ for (const connection of this.connections) {
connection.group = connection.group || null
let group = this.childGroups.find(x => x.name === connection.group)
if (!group) {
diff --git a/terminus-ssh/src/components/sshTab.component.scss b/terminus-ssh/src/components/sshTab.component.scss
new file mode 100644
index 00000000..31368be1
--- /dev/null
+++ b/terminus-ssh/src/components/sshTab.component.scss
@@ -0,0 +1,14 @@
+:host {
+ flex: auto;
+ display: flex;
+ flex-direction: column;
+ overflow: hidden;
+
+ &> .content {
+ flex: auto;
+ position: relative;
+ display: block;
+ overflow: hidden;
+ margin: 15px;
+ }
+}
diff --git a/terminus-ssh/src/components/sshTab.component.ts b/terminus-ssh/src/components/sshTab.component.ts
new file mode 100644
index 00000000..f7209480
--- /dev/null
+++ b/terminus-ssh/src/components/sshTab.component.ts
@@ -0,0 +1,70 @@
+import { Component } from '@angular/core'
+import { first } from 'rxjs/operators'
+import { BaseTerminalTabComponent } from 'terminus-terminal'
+import { SSHService } from '../services/ssh.service'
+import { SSHConnection, SSHSession } from '../api'
+
+/** @hidden */
+@Component({
+ template: `
+
+ `,
+ styles: [require('./sshTab.component.scss'), ...BaseTerminalTabComponent.styles],
+ animations: BaseTerminalTabComponent.animations,
+})
+export class SSHTabComponent extends BaseTerminalTabComponent {
+ connection: SSHConnection
+ ssh: SSHService
+ session: SSHSession
+
+ ngOnInit () {
+ this.logger = this.log.create('terminalTab')
+ this.ssh = this.injector.get(SSHService)
+ this.frontendReady$.pipe(first()).subscribe(() => {
+ this.initializeSession()
+ })
+
+ super.ngOnInit()
+
+ setImmediate(() => {
+ this.setTitle(this.connection.name)
+ })
+ }
+
+ async initializeSession () {
+ if (!this.connection) {
+ this.logger.error('No SSH connection info supplied')
+ return
+ }
+
+ this.session = new SSHSession(this.connection)
+ this.attachSessionHandlers()
+ this.write(`Connecting to ${this.connection.host}`)
+ const interval = setInterval(() => this.write('.'), 500)
+ try {
+ await this.ssh.connectSession(this.session, message => {
+ this.write('\r\n' + message)
+ })
+ } catch (e) {
+ this.write('\r\n')
+ this.write(e.message)
+ return
+ } finally {
+ clearInterval(interval)
+ this.write('\r\n')
+ }
+ this.session.resize(this.size.columns, this.size.rows)
+ this.session.start()
+ }
+
+ async getRecoveryToken (): Promise {
+ return {
+ type: 'app:ssh-tab',
+ connection: this.connection,
+ }
+ }
+}
diff --git a/terminus-ssh/src/config.ts b/terminus-ssh/src/config.ts
index 8b434e15..d32160df 100644
--- a/terminus-ssh/src/config.ts
+++ b/terminus-ssh/src/config.ts
@@ -1,14 +1,15 @@
import { ConfigProvider } from 'terminus-core'
+/** @hidden */
export class SSHConfigProvider extends ConfigProvider {
defaults = {
ssh: {
connections: [],
options: {
- }
+ },
},
hotkeys: {
- 'ssh': [
+ ssh: [
'Alt-S',
],
},
diff --git a/terminus-ssh/src/hotkeys.ts b/terminus-ssh/src/hotkeys.ts
new file mode 100644
index 00000000..0ee155f8
--- /dev/null
+++ b/terminus-ssh/src/hotkeys.ts
@@ -0,0 +1,17 @@
+import { Injectable } from '@angular/core'
+import { HotkeyDescription, HotkeyProvider } from 'terminus-core'
+
+/** @hidden */
+@Injectable()
+export class SSHHotkeyProvider extends HotkeyProvider {
+ hotkeys: HotkeyDescription[] = [
+ {
+ id: 'ssh',
+ name: 'Show SSH connections',
+ },
+ ]
+
+ async provide (): Promise {
+ return this.hotkeys
+ }
+}
diff --git a/terminus-ssh/src/index.ts b/terminus-ssh/src/index.ts
index d0ef1e36..a31bc12b 100644
--- a/terminus-ssh/src/index.ts
+++ b/terminus-ssh/src/index.ts
@@ -3,21 +3,22 @@ import { CommonModule } from '@angular/common'
import { FormsModule } from '@angular/forms'
import { NgbModule } from '@ng-bootstrap/ng-bootstrap'
import { ToastrModule } from 'ngx-toastr'
-import { ToolbarButtonProvider, ConfigProvider } from 'terminus-core'
-import TerminusCoreModule from 'terminus-core'
+import TerminusCoreModule, { ToolbarButtonProvider, ConfigProvider, TabRecoveryProvider, HotkeyProvider } from 'terminus-core'
import { SettingsTabProvider } from 'terminus-settings'
import { EditConnectionModalComponent } from './components/editConnectionModal.component'
import { SSHModalComponent } from './components/sshModal.component'
import { PromptModalComponent } from './components/promptModal.component'
import { SSHSettingsTabComponent } from './components/sshSettingsTab.component'
-import { SSHService } from './services/ssh.service'
-import { PasswordStorageService } from './services/passwordStorage.service'
+import { SSHTabComponent } from './components/sshTab.component'
import { ButtonProvider } from './buttonProvider'
import { SSHConfigProvider } from './config'
import { SSHSettingsTabProvider } from './settings'
+import { RecoveryProvider } from './recoveryProvider'
+import { SSHHotkeyProvider } from './hotkeys'
+/** @hidden */
@NgModule({
imports: [
NgbModule,
@@ -27,23 +28,25 @@ import { SSHSettingsTabProvider } from './settings'
TerminusCoreModule,
],
providers: [
- PasswordStorageService,
- SSHService,
{ provide: ToolbarButtonProvider, useClass: ButtonProvider, multi: true },
{ provide: ConfigProvider, useClass: SSHConfigProvider, multi: true },
{ provide: SettingsTabProvider, useClass: SSHSettingsTabProvider, multi: true },
+ { provide: TabRecoveryProvider, useClass: RecoveryProvider, multi: true },
+ { provide: HotkeyProvider, useClass: SSHHotkeyProvider, multi: true },
],
entryComponents: [
EditConnectionModalComponent,
PromptModalComponent,
SSHModalComponent,
SSHSettingsTabComponent,
+ SSHTabComponent,
],
declarations: [
EditConnectionModalComponent,
PromptModalComponent,
SSHModalComponent,
SSHSettingsTabComponent,
+ SSHTabComponent,
],
})
-export default class SSHModule { }
+export default class SSHModule { } // eslint-disable-line @typescript-eslint/no-extraneous-class
diff --git a/terminus-ssh/src/recoveryProvider.ts b/terminus-ssh/src/recoveryProvider.ts
new file mode 100644
index 00000000..4dc82d11
--- /dev/null
+++ b/terminus-ssh/src/recoveryProvider.ts
@@ -0,0 +1,18 @@
+import { Injectable } from '@angular/core'
+import { TabRecoveryProvider, RecoveredTab } from 'terminus-core'
+
+import { SSHTabComponent } from './components/sshTab.component'
+
+/** @hidden */
+@Injectable()
+export class RecoveryProvider extends TabRecoveryProvider {
+ async recover (recoveryToken: any): Promise {
+ if (recoveryToken && recoveryToken.type === 'app:ssh-tab') {
+ return {
+ type: SSHTabComponent,
+ options: { connection: recoveryToken.connection },
+ }
+ }
+ return null
+ }
+}
diff --git a/terminus-ssh/src/services/passwordStorage.service.ts b/terminus-ssh/src/services/passwordStorage.service.ts
index 83e367ef..fa5d9dd8 100644
--- a/terminus-ssh/src/services/passwordStorage.service.ts
+++ b/terminus-ssh/src/services/passwordStorage.service.ts
@@ -1,73 +1,18 @@
-import { Injectable, NgZone } from '@angular/core'
+import { Injectable } from '@angular/core'
import { SSHConnection } from '../api'
+import * as keytar from 'keytar'
-let xkeychain
-let wincredmgr
-try {
- xkeychain = require('xkeychain')
-} catch (error) {
- try {
- wincredmgr = require('wincredmgr')
- } catch (error2) {
- console.warn('No keychain manager available')
- }
-}
-
-@Injectable()
+@Injectable({ providedIn: 'root' })
export class PasswordStorageService {
- constructor (
- private zone: NgZone,
- ) { }
-
- savePassword (connection: SSHConnection, password: string) {
- if (xkeychain) {
- xkeychain.setPassword({
- account: connection.user,
- service: `ssh@${connection.host}`,
- password
- }, () => null)
- } else {
- wincredmgr.WriteCredentials(
- 'user',
- password,
- `ssh:${connection.user}@${connection.host}`,
- )
- }
+ async savePassword (connection: SSHConnection, password: string): Promise {
+ return keytar.setPassword(`ssh@${connection.host}`, connection.user, password)
}
- deletePassword (connection: SSHConnection) {
- if (xkeychain) {
- xkeychain.deletePassword({
- account: connection.user,
- service: `ssh@${connection.host}`,
- }, () => null)
- } else {
- wincredmgr.DeleteCredentials(
- `ssh:${connection.user}@${connection.host}`,
- )
- }
+ async deletePassword (connection: SSHConnection): Promise {
+ await keytar.deletePassword(`ssh@${connection.host}`, connection.user)
}
- loadPassword (connection: SSHConnection): Promise {
- return new Promise(resolve => {
- if (!wincredmgr && !xkeychain.isSupported()) {
- return resolve(null)
- }
- if (xkeychain) {
- xkeychain.getPassword(
- {
- account: connection.user,
- service: `ssh@${connection.host}`,
- },
- (_, result) => this.zone.run(() => resolve(result))
- )
- } else {
- try {
- resolve(wincredmgr.ReadCredentials(`ssh:${connection.user}@${connection.host}`).password)
- } catch (error) {
- resolve(null)
- }
- }
- })
+ async loadPassword (connection: SSHConnection): Promise {
+ return keytar.getPassword(`ssh@${connection.host}`, connection.user)
}
}
diff --git a/terminus-ssh/src/services/ssh.service.ts b/terminus-ssh/src/services/ssh.service.ts
index 6b5addb0..7b35712a 100644
--- a/terminus-ssh/src/services/ssh.service.ts
+++ b/terminus-ssh/src/services/ssh.service.ts
@@ -5,13 +5,18 @@ import * as fs from 'mz/fs'
import * as path from 'path'
import { ToastrService } from 'ngx-toastr'
import { AppService, HostAppService, Platform, Logger, LogService } from 'terminus-core'
-import { TerminalTabComponent } from 'terminus-terminal'
import { SSHConnection, SSHSession } from '../api'
import { PromptModalComponent } from '../components/promptModal.component'
+import { SSHTabComponent } from '../components/sshTab.component'
import { PasswordStorageService } from './passwordStorage.service'
-const { SSH2Stream } = require('ssh2-streams')
+import { SSH2Stream } from 'ssh2-streams'
-@Injectable()
+/* eslint-disable block-scoped-var */
+try {
+ var windowsProcessTree = require('windows-process-tree/build/Release/windows_process_tree.node') // eslint-disable-line @typescript-eslint/no-var-requires
+} catch (_) { }
+
+@Injectable({ providedIn: 'root' })
export class SSHService {
private logger: Logger
@@ -27,14 +32,31 @@ export class SSHService {
this.logger = log.create('ssh')
}
- async connect (connection: SSHConnection): Promise {
+ async openTab (connection: SSHConnection): Promise {
+ return this.zone.run(() => this.app.openNewTab(
+ SSHTabComponent,
+ { connection }
+ ) as SSHTabComponent)
+ }
+
+ async connectSession (session: SSHSession, logCallback?: (s: string) => void): Promise {
let privateKey: string = null
let privateKeyPassphrase: string = null
- let privateKeyPath = connection.privateKey
+ let privateKeyPath = session.connection.privateKey
+
+ if (!logCallback) {
+ logCallback = () => null
+ }
+
+ const log = (s: any) => {
+ logCallback(s)
+ this.logger.info(s)
+ }
+
if (!privateKeyPath) {
- let userKeyPath = path.join(process.env.HOME, '.ssh', 'id_rsa')
+ const userKeyPath = path.join(process.env.HOME, '.ssh', 'id_rsa')
if (await fs.exists(userKeyPath)) {
- this.logger.info('Using user\'s default private key:', userKeyPath)
+ log(`Using user's default private key: ${userKeyPath}`)
privateKeyPath = userKeyPath
}
}
@@ -43,40 +65,47 @@ export class SSHService {
try {
privateKey = (await fs.readFile(privateKeyPath)).toString()
} catch (error) {
- this.toastr.warning('Could not read the private key file')
+ log('Could not read the private key file')
+ this.toastr.error('Could not read the private key file')
}
if (privateKey) {
- this.logger.info('Loaded private key from', privateKeyPath)
+ log(`Loading private key from ${privateKeyPath}`)
let encrypted = privateKey.includes('ENCRYPTED')
if (privateKeyPath.toLowerCase().endsWith('.ppk')) {
encrypted = encrypted || privateKey.includes('Encryption:') && !privateKey.includes('Encryption: none')
}
if (encrypted) {
- let modal = this.ngbModal.open(PromptModalComponent)
+ const modal = this.ngbModal.open(PromptModalComponent)
+ log('Key requires passphrase')
modal.componentInstance.prompt = 'Private key passphrase'
modal.componentInstance.password = true
try {
- privateKeyPassphrase = await modal.result
- } catch (_err) { } // tslint:disable-line
+ const result = await modal.result
+ if (result) {
+ privateKeyPassphrase = result.value
+ }
+ } catch (e) { }
}
}
}
- let ssh = new Client()
+ const ssh = new Client()
let connected = false
let savedPassword: string = null
- await new Promise((resolve, reject) => {
+ await new Promise(async (resolve, reject) => {
ssh.on('ready', () => {
connected = true
if (savedPassword) {
- this.passwordStorage.savePassword(connection, savedPassword)
+ this.passwordStorage.savePassword(session.connection, savedPassword)
}
this.zone.run(resolve)
})
ssh.on('error', error => {
- this.passwordStorage.deletePassword(connection)
+ if (error.message === 'All configured authentication methods failed') {
+ this.passwordStorage.deletePassword(session.connection)
+ }
this.zone.run(() => {
if (connected) {
this.toastr.error(error.toString())
@@ -86,66 +115,105 @@ export class SSHService {
})
})
ssh.on('keyboard-interactive', (name, instructions, instructionsLang, prompts, finish) => this.zone.run(async () => {
- console.log(name, instructions, instructionsLang)
- let results = []
- for (let prompt of prompts) {
- let modal = this.ngbModal.open(PromptModalComponent)
+ log(`Keyboard-interactive auth requested: ${name}`)
+ this.logger.info('Keyboard-interactive auth:', name, instructions, instructionsLang)
+ const results = []
+ for (const prompt of prompts) {
+ const modal = this.ngbModal.open(PromptModalComponent)
modal.componentInstance.prompt = prompt.prompt
modal.componentInstance.password = !prompt.echo
- results.push(await modal.result)
+ const result = await modal.result
+ results.push(result ? result.value : '')
}
finish(results)
}))
+ ssh.on('greeting', greeting => {
+ log('Greeting: ' + greeting)
+ })
+
+ ssh.on('banner', banner => {
+ log('Banner: ' + banner)
+ })
+
let agent: string = null
if (this.hostApp.platform === Platform.Windows) {
- agent = 'pageant'
+ const pageantRunning = new Promise(resolve => {
+ windowsProcessTree.getProcessList(list => {
+ resolve(list.some(x => x.name === 'pageant.exe'))
+ }, 0)
+ })
+ if (await pageantRunning) {
+ agent = 'pageant'
+ }
} else {
agent = process.env.SSH_AUTH_SOCK
}
- ssh.connect({
- host: connection.host,
- port: connection.port || 22,
- username: connection.user,
- password: connection.privateKey ? undefined : '',
- privateKey,
- passphrase: privateKeyPassphrase,
- tryKeyboard: true,
- agent,
- agentForward: !!agent,
- keepaliveInterval: connection.keepaliveInterval,
- keepaliveCountMax: connection.keepaliveCountMax,
- readyTimeout: connection.readyTimeout,
- })
+ try {
+ ssh.connect({
+ host: session.connection.host,
+ port: session.connection.port || 22,
+ username: session.connection.user,
+ password: session.connection.privateKey ? undefined : '',
+ privateKey,
+ passphrase: privateKeyPassphrase,
+ tryKeyboard: true,
+ agent,
+ agentForward: !!agent,
+ keepaliveInterval: session.connection.keepaliveInterval,
+ keepaliveCountMax: session.connection.keepaliveCountMax,
+ readyTimeout: session.connection.readyTimeout,
+ hostVerifier: digest => {
+ log('SHA256 fingerprint: ' + digest)
+ return true
+ },
+ hostHash: 'sha256' as any,
+ algorithms: session.connection.algorithms,
+ })
+ } catch (e) {
+ this.toastr.error(e.message)
+ reject(e)
+ }
let keychainPasswordUsed = false
;(ssh as any).config.password = () => this.zone.run(async () => {
- if (connection.password) {
- this.logger.info('Using preset password')
- return connection.password
+ if (session.connection.password) {
+ log('Using preset password')
+ return session.connection.password
}
if (!keychainPasswordUsed) {
- let password = await this.passwordStorage.loadPassword(connection)
+ const password = await this.passwordStorage.loadPassword(session.connection)
if (password) {
- this.logger.info('Using saved password')
+ log('Trying saved password')
keychainPasswordUsed = true
return password
}
}
- let modal = this.ngbModal.open(PromptModalComponent)
- modal.componentInstance.prompt = `Password for ${connection.user}@${connection.host}`
+ const modal = this.ngbModal.open(PromptModalComponent)
+ modal.componentInstance.prompt = `Password for ${session.connection.user}@${session.connection.host}`
modal.componentInstance.password = true
- savedPassword = await modal.result
- return savedPassword
+ modal.componentInstance.showRememberCheckbox = true
+ try {
+ const result = await modal.result
+ if (result) {
+ if (result.remember) {
+ savedPassword = result.value
+ }
+ return result.value
+ }
+ return ''
+ } catch (_) {
+ return ''
+ }
})
})
try {
- let shell = await new Promise((resolve, reject) => {
+ const shell: any = await new Promise((resolve, reject) => {
ssh.shell({ term: 'xterm-256color' }, (err, shell) => {
if (err) {
reject(err)
@@ -155,20 +223,24 @@ export class SSHService {
})
})
- let session = new SSHSession(shell, connection)
+ session.shell = shell
- return this.zone.run(() => this.app.openNewTab(
- TerminalTabComponent,
- { session, sessionOptions: {} }
- ) as TerminalTabComponent)
+ shell.on('greeting', greeting => {
+ log(`Shell Greeting: ${greeting}`)
+ })
+
+ shell.on('banner', banner => {
+ log(`Shell Banner: ${banner}`)
+ })
} catch (error) {
- console.log(error)
+ this.toastr.error(error.message)
throw error
}
}
}
+/* eslint-disable */
const _authPassword = SSH2Stream.prototype.authPassword
-SSH2Stream.prototype.authPassword = async function (username, passwordFn) {
+SSH2Stream.prototype.authPassword = async function (username, passwordFn: any) {
_authPassword.bind(this)(username, await passwordFn())
-}
+} as any
diff --git a/terminus-ssh/src/settings.ts b/terminus-ssh/src/settings.ts
index 48827a28..e71b9c4b 100644
--- a/terminus-ssh/src/settings.ts
+++ b/terminus-ssh/src/settings.ts
@@ -3,9 +3,11 @@ import { SettingsTabProvider } from 'terminus-settings'
import { SSHSettingsTabComponent } from './components/sshSettingsTab.component'
+/** @hidden */
@Injectable()
export class SSHSettingsTabProvider extends SettingsTabProvider {
id = 'ssh'
+ icon = 'globe'
title = 'SSH'
getComponentType (): any {
diff --git a/terminus-ssh/tsconfig.json b/terminus-ssh/tsconfig.json
index d2383e0e..a863b98a 100644
--- a/terminus-ssh/tsconfig.json
+++ b/terminus-ssh/tsconfig.json
@@ -1,12 +1,7 @@
{
"extends": "../tsconfig.json",
- "exclude": ["node_modules", "dist"],
+ "exclude": ["node_modules", "dist", "typings"],
"compilerOptions": {
- "baseUrl": "src",
- "declarationDir": "dist",
- "paths": {
- "terminus-*": ["terminus-*"],
- "*": ["app/node_modules/*"]
- }
+ "baseUrl": "src"
}
}
diff --git a/terminus-ssh/tsconfig.typings.json b/terminus-ssh/tsconfig.typings.json
new file mode 100644
index 00000000..95da756c
--- /dev/null
+++ b/terminus-ssh/tsconfig.typings.json
@@ -0,0 +1,15 @@
+{
+ "extends": "../tsconfig.json",
+ "exclude": ["node_modules", "dist", "typings"],
+ "include": ["src"],
+ "compilerOptions": {
+ "baseUrl": "src",
+ "emitDeclarationOnly": true,
+ "declaration": true,
+ "declarationDir": "./typings",
+ "paths": {
+ "terminus-*": ["../../terminus-*"],
+ "*": ["../../app/node_modules/*"]
+ }
+ }
+}
diff --git a/terminus-ssh/webpack.config.js b/terminus-ssh/webpack.config.js
index 7644498a..bf5efa9a 100644
--- a/terminus-ssh/webpack.config.js
+++ b/terminus-ssh/webpack.config.js
@@ -12,13 +12,13 @@ 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,
},
resolve: {
modules: ['.', 'src', 'node_modules', '../app/node_modules'].map(x => path.join(__dirname, x)),
- extensions: ['.ts', '.js'],
+ extensions: ['.ts', '.js']
},
module: {
rules: [
@@ -43,11 +43,10 @@ module.exports = {
},
externals: [
'fs',
- 'node-ssh',
- 'xkeychain',
- 'wincredmgr',
+ 'keytar',
'path',
'ngx-toastr',
+ 'windows-process-tree/build/Release/windows_process_tree.node',
/^rxjs/,
/^@angular/,
/^@ng-bootstrap/,
diff --git a/terminus-ssh/yarn.lock b/terminus-ssh/yarn.lock
index a4b2d57d..f6423d71 100644
--- a/terminus-ssh/yarn.lock
+++ b/terminus-ssh/yarn.lock
@@ -7,11 +7,6 @@
resolved "https://registry.yarnpkg.com/@types/node/-/node-9.3.0.tgz#3a129cda7c4e5df2409702626892cb4b96546dd5"
integrity sha512-wNBfvNjzsJl4tswIZKXCFQY0lss9nKUyJnG6T94X/eqjRgI2jHZ4evdjhQYBSan/vGtF6XVXPApOmNH2rf0KKw==
-"@types/node@^7.0.18":
- version "7.0.52"
- resolved "https://registry.yarnpkg.com/@types/node/-/node-7.0.52.tgz#8990d3350375542b0c21a83cd0331e6a8fc86716"
- integrity sha512-jjpyQsKGsOF/wUElNjfPULk+d8PKvJOIXk3IUeBYYmNCy5dMWfrI+JiixYNw8ppKOlcRwWTXFl0B+i5oGrf95Q==
-
"@types/ssh2-streams@*":
version "0.1.2"
resolved "https://registry.yarnpkg.com/@types/ssh2-streams/-/ssh2-streams-0.1.2.tgz#7aa18b8c2450f17699e9ea18a76efc838188d58d"
@@ -20,85 +15,23 @@
"@types/node" "*"
"@types/ssh2@^0.5.35":
- version "0.5.35"
- resolved "https://registry.yarnpkg.com/@types/ssh2/-/ssh2-0.5.35.tgz#d6e60d59b7fc22db10abf4730aa7448babde7e3b"
- integrity sha1-1uYNWbf8ItsQq/RzCqdEi6vefjs=
+ version "0.5.38"
+ resolved "https://registry.yarnpkg.com/@types/ssh2/-/ssh2-0.5.38.tgz#71f7c8f1d0636663158561af103c385ad439c7bc"
+ integrity sha512-rMnCnd0VIEUpCD1O5V50L1I8asHMBHZUYBnG6wlim1SdUrKUn60yiNpW5BnnT6QkTExaUXVrM8N883ZPPEPtsg==
dependencies:
"@types/node" "*"
"@types/ssh2-streams" "*"
"@types/webpack-env@^1.13.0":
- version "1.13.3"
- resolved "https://registry.yarnpkg.com/@types/webpack-env/-/webpack-env-1.13.3.tgz#0ecbe70f87341767793774d3683b51aa3246434c"
- integrity sha512-lLa+/oIfCzfmjyMWmQpJWlxuw2pWRqCZojg1JVtonAiMNISOGaEtowl+mffuFg7AghO2dwYulZBGV1Od2PZQ9A==
-
-abbrev@1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8"
- integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==
-
-acorn-dynamic-import@^2.0.0:
- version "2.0.2"
- resolved "https://registry.yarnpkg.com/acorn-dynamic-import/-/acorn-dynamic-import-2.0.2.tgz#c752bd210bef679501b6c6cb7fc84f8f47158cc4"
- integrity sha1-x1K9IQvvZ5UBtsbLf8hPj0cVjMQ=
- dependencies:
- acorn "^4.0.3"
-
-acorn@^4.0.3:
- version "4.0.13"
- resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.13.tgz#105495ae5361d697bd195c825192e1ad7f253787"
- integrity sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c=
-
-acorn@^5.0.0:
- version "5.3.0"
- resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.3.0.tgz#7446d39459c54fb49a80e6ee6478149b940ec822"
- integrity sha512-Yej+zOJ1Dm/IMZzzj78OntP/r3zHEaKcyNoU2lAaxPtrseM6rF0xwqoz5Q5ysAiED9hTjI2hgtvLXitlCN1/Ug==
-
-ajv-keywords@^1.1.1:
- version "1.5.1"
- resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.5.1.tgz#314dd0a4b3368fad3dfcdc54ede6171b886daf3c"
- integrity sha1-MU3QpLM2j609/NxU7eYXG4htrzw=
-
-ajv@^4.7.0, ajv@^4.9.1:
- version "4.11.8"
- resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536"
- integrity sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=
- dependencies:
- co "^4.6.0"
- json-stable-stringify "^1.0.1"
-
-ajv@^5.1.0:
- version "5.5.2"
- resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965"
- integrity sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=
- dependencies:
- co "^4.6.0"
- fast-deep-equal "^1.0.0"
- fast-json-stable-stringify "^2.0.0"
- json-schema-traverse "^0.3.0"
-
-align-text@^0.1.1, align-text@^0.1.3:
- version "0.1.4"
- resolved "https://registry.yarnpkg.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117"
- integrity sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=
- dependencies:
- kind-of "^3.0.2"
- longest "^1.0.1"
- repeat-string "^1.5.2"
+ version "1.13.9"
+ resolved "https://registry.yarnpkg.com/@types/webpack-env/-/webpack-env-1.13.9.tgz#a67287861c928ebf4159a908d1fb1a2a34d4097a"
+ integrity sha512-p8zp5xqkly3g4cCmo2mKOHI9+Z/kObmDj0BmjbDDJQlgDTiEGTbm17MEwTAusV6XceCy+bNw9q/ZHXHyKo3zkg==
ansi-regex@^2.0.0:
version "2.1.1"
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8=
-anymatch@^1.3.0:
- version "1.3.2"
- resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-1.3.2.tgz#553dcb8f91e3c889845dfdba34c77721b90b9d7a"
- integrity sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==
- dependencies:
- micromatch "^2.1.5"
- normalize-path "^2.0.0"
-
aproba@^1.0.3:
version "1.2.0"
resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a"
@@ -112,775 +45,104 @@ are-we-there-yet@~1.1.2:
delegates "^1.0.0"
readable-stream "^2.0.6"
-arr-diff@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf"
- integrity sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=
+asn1@~0.2.0:
+ version "0.2.4"
+ resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136"
+ integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==
dependencies:
- arr-flatten "^1.0.1"
+ safer-buffer "~2.1.0"
-arr-flatten@^1.0.1:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1"
- integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==
-
-array-find-index@^1.0.1:
+bcrypt-pbkdf@^1.0.2:
version "1.0.2"
- resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1"
- integrity sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=
-
-array-unique@^0.2.1:
- version "0.2.1"
- resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53"
- integrity sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=
-
-asn1.js@^4.0.0:
- version "4.9.2"
- resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.9.2.tgz#8117ef4f7ed87cd8f89044b5bff97ac243a16c9a"
- integrity sha512-b/OsSjvWEo8Pi8H0zsDd2P6Uqo2TK2pH8gNLSJtNLM2Db0v2QaAZ0pBQJXVjAn4gBuugeVDr7s63ZogpUIwWDg==
- dependencies:
- bn.js "^4.0.0"
- inherits "^2.0.1"
- minimalistic-assert "^1.0.0"
-
-asn1@~0.2.0, asn1@~0.2.3:
- version "0.2.3"
- resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86"
- integrity sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=
-
-assert-plus@1.0.0, assert-plus@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525"
- integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=
-
-assert-plus@^0.2.0:
- version "0.2.0"
- resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.2.0.tgz#d74e1b87e7affc0db8aadb7021f3fe48101ab234"
- integrity sha1-104bh+ev/A24qttwIfP+SBAasjQ=
-
-assert@^1.1.1:
- version "1.4.1"
- resolved "https://registry.yarnpkg.com/assert/-/assert-1.4.1.tgz#99912d591836b5a6f5b345c0f07eefc08fc65d91"
- integrity sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=
- dependencies:
- util "0.10.3"
-
-async-each@^1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d"
- integrity sha1-GdOGodntxufByF04iu28xW0zYC0=
-
-async@^2.1.2:
- version "2.6.0"
- resolved "https://registry.yarnpkg.com/async/-/async-2.6.0.tgz#61a29abb6fcc026fea77e56d1c6ec53a795951f4"
- integrity sha512-xAfGg1/NTLBBKlHFmnd7PlmUW9KhVQIUuSrYem9xzFUZy13ScvtyGGejaae9iAVRiRq9+Cx7DPFaAAhCpyxyPw==
- dependencies:
- lodash "^4.14.0"
-
-asynckit@^0.4.0:
- version "0.4.0"
- resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
- integrity sha1-x57Zf380y48robyXkLzDZkdLS3k=
-
-aws-sign2@~0.6.0:
- version "0.6.0"
- resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.6.0.tgz#14342dd38dbcc94d0e5b87d763cd63612c0e794f"
- integrity sha1-FDQt0428yU0OW4fXY81jYSwOeU8=
-
-aws-sign2@~0.7.0:
- version "0.7.0"
- resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8"
- integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=
-
-aws4@^1.2.1, aws4@^1.6.0:
- version "1.6.0"
- resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e"
- integrity sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=
-
-balanced-match@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
- integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c=
-
-base64-js@^1.0.2:
- version "1.2.1"
- resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.2.1.tgz#a91947da1f4a516ea38e5b4ec0ec3773675e0886"
- integrity sha512-dwVUVIXsBZXwTuwnXI9RK8sBmgq09NDHzyR9SAph9eqk76gKK2JSQmZARC2zRC81JC2QTtxD0ARU5qTS25gIGw==
-
-bcrypt-pbkdf@^1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz#63bc5dcb61331b92bc05fd528953c33462a06f8d"
- integrity sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=
+ resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e"
+ integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=
dependencies:
tweetnacl "^0.14.3"
-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==
-
-binary-extensions@^1.0.0:
- version "1.11.0"
- resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.11.0.tgz#46aa1751fb6a2f93ee5e689bb1087d4b14c6c205"
- integrity sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=
-
-block-stream@*:
- version "0.0.9"
- resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a"
- integrity sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=
+bl@^1.0.0:
+ version "1.2.2"
+ resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.2.tgz#a160911717103c07410cef63ef51b397c025af9c"
+ integrity sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==
dependencies:
- inherits "~2.0.0"
+ readable-stream "^2.3.5"
+ safe-buffer "^5.1.1"
-bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.4.0:
- version "4.11.8"
- resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f"
- integrity sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==
-
-boom@2.x.x:
- version "2.10.1"
- resolved "https://registry.yarnpkg.com/boom/-/boom-2.10.1.tgz#39c8918ceff5799f83f9492a848f625add0c766f"
- integrity sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=
- dependencies:
- hoek "2.x.x"
-
-boom@4.x.x:
- version "4.3.1"
- resolved "https://registry.yarnpkg.com/boom/-/boom-4.3.1.tgz#4f8a3005cb4a7e3889f749030fd25b96e01d2e31"
- integrity sha1-T4owBctKfjiJ90kDD9JbluAdLjE=
- dependencies:
- hoek "4.x.x"
-
-boom@5.x.x:
- version "5.2.0"
- resolved "https://registry.yarnpkg.com/boom/-/boom-5.2.0.tgz#5dd9da6ee3a5f302077436290cb717d3f4a54e02"
- integrity sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==
- dependencies:
- hoek "4.x.x"
-
-brace-expansion@^1.1.7:
- version "1.1.8"
- resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292"
- integrity sha1-wHshHHyVLsH479Uad+8NHTmQopI=
- dependencies:
- balanced-match "^1.0.0"
- concat-map "0.0.1"
-
-braces@^1.8.2:
- version "1.8.5"
- resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7"
- integrity sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=
- dependencies:
- expand-range "^1.8.1"
- preserve "^0.2.0"
- repeat-element "^1.1.2"
-
-brorand@^1.0.1:
+buffer-alloc-unsafe@^1.1.0:
version "1.1.0"
- resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f"
- integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=
+ resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0"
+ integrity sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==
-browserify-aes@^1.0.0, browserify-aes@^1.0.4:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.1.1.tgz#38b7ab55edb806ff2dcda1a7f1620773a477c49f"
- integrity sha512-UGnTYAnB2a3YuYKIRy1/4FB2HdM866E0qC46JXvVTYKlBlZlnvfpSfY6OKfXZAkv70eJ2a1SqzpAo5CRhZGDFg==
+buffer-alloc@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec"
+ integrity sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==
dependencies:
- buffer-xor "^1.0.3"
- cipher-base "^1.0.0"
- create-hash "^1.1.0"
- evp_bytestokey "^1.0.3"
- inherits "^2.0.1"
- safe-buffer "^5.0.1"
+ buffer-alloc-unsafe "^1.1.0"
+ buffer-fill "^1.0.0"
-browserify-cipher@^1.0.0:
+buffer-fill@^1.0.0:
version "1.0.0"
- resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.0.tgz#9988244874bf5ed4e28da95666dcd66ac8fc363a"
- integrity sha1-mYgkSHS/XtTijalWZtzWasj8Njo=
- dependencies:
- browserify-aes "^1.0.4"
- browserify-des "^1.0.0"
- evp_bytestokey "^1.0.0"
+ resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c"
+ integrity sha1-+PeLdniYiO858gXNY39o5wISKyw=
-browserify-des@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.0.tgz#daa277717470922ed2fe18594118a175439721dd"
- integrity sha1-2qJ3cXRwki7S/hhZQRihdUOXId0=
- dependencies:
- cipher-base "^1.0.1"
- des.js "^1.0.0"
- inherits "^2.0.1"
-
-browserify-rsa@^4.0.0:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.0.1.tgz#21e0abfaf6f2029cf2fafb133567a701d4135524"
- integrity sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=
- dependencies:
- bn.js "^4.1.0"
- randombytes "^2.0.1"
-
-browserify-sign@^4.0.0:
- version "4.0.4"
- resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.0.4.tgz#aa4eb68e5d7b658baa6bf6a57e630cbd7a93d298"
- integrity sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=
- dependencies:
- bn.js "^4.1.1"
- browserify-rsa "^4.0.0"
- create-hash "^1.1.0"
- create-hmac "^1.1.2"
- elliptic "^6.0.0"
- inherits "^2.0.1"
- parse-asn1 "^5.0.0"
-
-browserify-zlib@^0.2.0:
- version "0.2.0"
- resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f"
- integrity sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==
- dependencies:
- pako "~1.0.5"
-
-buffer-xor@^1.0.3:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9"
- integrity sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=
-
-buffer@^4.3.0:
- version "4.9.1"
- resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.1.tgz#6d1bb601b07a4efced97094132093027c95bc298"
- integrity sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=
- dependencies:
- base64-js "^1.0.2"
- ieee754 "^1.1.4"
- isarray "^1.0.0"
-
-builtin-modules@^1.0.0:
+chownr@^1.0.1:
version "1.1.1"
- resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f"
- integrity sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=
-
-builtin-status-codes@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8"
- integrity sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=
-
-camelcase-keys@^2.0.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-2.1.0.tgz#308beeaffdf28119051efa1d932213c91b8f92e7"
- integrity sha1-MIvur/3ygRkFHvodkyITyRuPkuc=
- dependencies:
- camelcase "^2.0.0"
- map-obj "^1.0.0"
-
-camelcase@^1.0.2:
- version "1.2.1"
- resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39"
- integrity sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=
-
-camelcase@^2.0.0:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f"
- integrity sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=
-
-camelcase@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a"
- integrity sha1-MvxLn82vhF/N9+c7uXysImHwqwo=
-
-caseless@~0.12.0:
- version "0.12.0"
- resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
- integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=
-
-center-align@^0.1.1:
- version "0.1.3"
- resolved "https://registry.yarnpkg.com/center-align/-/center-align-0.1.3.tgz#aa0d32629b6ee972200411cbd4461c907bc2b7ad"
- integrity sha1-qg0yYptu6XIgBBHL1EYckHvCt60=
- dependencies:
- align-text "^0.1.3"
- lazy-cache "^1.0.3"
-
-chokidar@^1.7.0:
- version "1.7.0"
- resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.7.0.tgz#798e689778151c8076b4b360e5edd28cda2bb468"
- integrity sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=
- dependencies:
- anymatch "^1.3.0"
- async-each "^1.0.0"
- glob-parent "^2.0.0"
- inherits "^2.0.1"
- is-binary-path "^1.0.0"
- is-glob "^2.0.0"
- path-is-absolute "^1.0.0"
- readdirp "^2.0.0"
- optionalDependencies:
- fsevents "^1.0.0"
-
-cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de"
- integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==
- dependencies:
- inherits "^2.0.1"
- safe-buffer "^5.0.1"
-
-cliui@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/cliui/-/cliui-2.1.0.tgz#4b475760ff80264c762c3a1719032e91c7fea0d1"
- integrity sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=
- dependencies:
- center-align "^0.1.1"
- right-align "^0.1.1"
- wordwrap "0.0.2"
-
-cliui@^3.2.0:
- version "3.2.0"
- resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d"
- integrity sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=
- dependencies:
- string-width "^1.0.1"
- strip-ansi "^3.0.1"
- wrap-ansi "^2.0.0"
-
-co@^4.6.0:
- version "4.6.0"
- resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184"
- integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=
+ resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.1.tgz#54726b8b8fff4df053c42187e801fb4412df1494"
+ integrity sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==
code-point-at@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=
-combined-stream@^1.0.5, combined-stream@~1.0.5:
- version "1.0.5"
- resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.5.tgz#938370a57b4a51dea2c77c15d5c5fdf895164009"
- integrity sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=
- dependencies:
- delayed-stream "~1.0.0"
-
-concat-map@0.0.1:
- version "0.0.1"
- resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
- integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
-
-concat-stream@1.6.0:
- version "1.6.0"
- resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.0.tgz#0aac662fd52be78964d5532f694784e70110acf7"
- integrity sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=
- dependencies:
- inherits "^2.0.3"
- readable-stream "^2.2.2"
- typedarray "^0.0.6"
-
-console-browserify@^1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.1.0.tgz#f0241c45730a9fc6323b206dbf38edc741d0bb10"
- integrity sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=
- dependencies:
- date-now "^0.1.4"
-
console-control-strings@^1.0.0, console-control-strings@~1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e"
integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=
-constants-browserify@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75"
- integrity sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=
-
-core-util-is@1.0.2, core-util-is@~1.0.0:
+core-util-is@~1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
-create-ecdh@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.0.tgz#888c723596cdf7612f6498233eebd7a35301737d"
- integrity sha1-iIxyNZbN92EvZJgjPuvXo1MBc30=
+decompress-response@^3.3.0:
+ version "3.3.0"
+ resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3"
+ integrity sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=
dependencies:
- bn.js "^4.1.0"
- elliptic "^6.0.0"
+ mimic-response "^1.0.0"
-create-hash@^1.1.0, create-hash@^1.1.2:
- version "1.1.3"
- resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.1.3.tgz#606042ac8b9262750f483caddab0f5819172d8fd"
- integrity sha1-YGBCrIuSYnUPSDyt2rD1gZFy2P0=
- dependencies:
- cipher-base "^1.0.1"
- inherits "^2.0.1"
- ripemd160 "^2.0.0"
- sha.js "^2.4.0"
-
-create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4:
- version "1.1.6"
- resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.6.tgz#acb9e221a4e17bdb076e90657c42b93e3726cf06"
- integrity sha1-rLniIaThe9sHbpBlfEK5PjcmzwY=
- dependencies:
- cipher-base "^1.0.3"
- create-hash "^1.1.0"
- inherits "^2.0.1"
- ripemd160 "^2.0.0"
- safe-buffer "^5.0.1"
- sha.js "^2.4.8"
-
-cryptiles@2.x.x:
- version "2.0.5"
- resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8"
- integrity sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=
- dependencies:
- boom "2.x.x"
-
-cryptiles@3.x.x:
- version "3.1.2"
- resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-3.1.2.tgz#a89fbb220f5ce25ec56e8c4aa8a4fd7b5b0d29fe"
- integrity sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4=
- dependencies:
- boom "5.x.x"
-
-crypto-browserify@^3.11.0:
- version "3.12.0"
- resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec"
- integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==
- dependencies:
- browserify-cipher "^1.0.0"
- browserify-sign "^4.0.0"
- create-ecdh "^4.0.0"
- create-hash "^1.1.0"
- create-hmac "^1.1.0"
- diffie-hellman "^5.0.0"
- inherits "^2.0.1"
- pbkdf2 "^3.0.3"
- public-encrypt "^4.0.0"
- randombytes "^2.0.0"
- randomfill "^1.0.3"
-
-currently-unhandled@^0.4.1:
- version "0.4.1"
- resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea"
- integrity sha1-mI3zP+qxke95mmE2nddsF635V+o=
- dependencies:
- array-find-index "^1.0.1"
-
-dashdash@^1.12.0:
- version "1.14.1"
- resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0"
- integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=
- dependencies:
- assert-plus "^1.0.0"
-
-date-now@^0.1.4:
- version "0.1.4"
- resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b"
- integrity sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=
-
-debug@2.6.9, debug@^2.1.3, debug@^2.2.0:
- version "2.6.9"
- resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
- integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
- dependencies:
- ms "2.0.0"
-
-decamelize@^1.0.0, decamelize@^1.1.1, decamelize@^1.1.2:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
- integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=
-
-deep-extend@~0.4.0:
- version "0.4.2"
- resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.4.2.tgz#48b699c27e334bf89f10892be432f6e4c7d34a7f"
- integrity sha1-SLaZwn4zS/ifEIkr5DL25MfTSn8=
-
-delayed-stream@~1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
- integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk=
+deep-extend@^0.6.0:
+ version "0.6.0"
+ resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac"
+ integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==
delegates@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a"
integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=
-des.js@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.0.tgz#c074d2e2aa6a8a9a07dbd61f9a15c2cd83ec8ecc"
- integrity sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=
- dependencies:
- inherits "^2.0.1"
- minimalistic-assert "^1.0.0"
-
-detect-libc@^1.0.2:
+detect-libc@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b"
integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=
-diffie-hellman@^5.0.0:
- version "5.0.2"
- resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.2.tgz#b5835739270cfe26acf632099fded2a07f209e5e"
- integrity sha1-tYNXOScM/ias9jIJn97SoH8gnl4=
+end-of-stream@^1.0.0, end-of-stream@^1.1.0:
+ version "1.4.1"
+ resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43"
+ integrity sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==
dependencies:
- bn.js "^4.1.0"
- miller-rabin "^4.0.0"
- randombytes "^2.0.0"
+ once "^1.4.0"
-domain-browser@^1.1.1:
- version "1.1.7"
- resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.1.7.tgz#867aa4b093faa05f1de08c06f4d7b21fdf8698bc"
- integrity sha1-hnqksJP6oF8d4IwG9NeyH9+GmLw=
+expand-template@^2.0.3:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/expand-template/-/expand-template-2.0.3.tgz#6e14b3fcee0f3a6340ecb57d2e8918692052a47c"
+ integrity sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==
-ecc-jsbn@~0.1.1:
- version "0.1.1"
- resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz#0fc73a9ed5f0d53c38193398523ef7e543777505"
- integrity sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=
- dependencies:
- jsbn "~0.1.0"
-
-electron-download@^3.0.1:
- version "3.3.0"
- resolved "https://registry.yarnpkg.com/electron-download/-/electron-download-3.3.0.tgz#2cfd54d6966c019c4d49ad65fbe65cc9cdef68c8"
- integrity sha1-LP1U1pZsAZxNSa1l++Zcyc3vaMg=
- dependencies:
- debug "^2.2.0"
- fs-extra "^0.30.0"
- home-path "^1.0.1"
- minimist "^1.2.0"
- nugget "^2.0.0"
- path-exists "^2.1.0"
- rc "^1.1.2"
- semver "^5.3.0"
- sumchecker "^1.2.0"
-
-electron@^1.6.11:
- version "1.7.10"
- resolved "https://registry.yarnpkg.com/electron/-/electron-1.7.10.tgz#3a3e83d965fd7fafe473be8ddf8f472561b6253d"
- integrity sha1-Oj6D2WX9f6/kc76N349HJWG2JT0=
- dependencies:
- "@types/node" "^7.0.18"
- electron-download "^3.0.1"
- extract-zip "^1.0.3"
-
-elliptic@^6.0.0:
- version "6.4.0"
- resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.4.0.tgz#cac9af8762c85836187003c8dfe193e5e2eae5df"
- integrity sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8=
- dependencies:
- bn.js "^4.4.0"
- brorand "^1.0.1"
- hash.js "^1.0.0"
- hmac-drbg "^1.0.0"
- inherits "^2.0.1"
- minimalistic-assert "^1.0.0"
- minimalistic-crypto-utils "^1.0.0"
-
-emojis-list@^2.0.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389"
- integrity sha1-TapNnbAPmBmIDHn6RXrlsJof04k=
-
-enhanced-resolve@^3.3.0:
- version "3.4.1"
- resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-3.4.1.tgz#0421e339fd71419b3da13d129b3979040230476e"
- integrity sha1-BCHjOf1xQZs9oT0Smzl5BAIwR24=
- dependencies:
- graceful-fs "^4.1.2"
- memory-fs "^0.4.0"
- object-assign "^4.0.1"
- tapable "^0.2.7"
-
-errno@^0.1.3:
- version "0.1.6"
- resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.6.tgz#c386ce8a6283f14fc09563b71560908c9bf53026"
- integrity sha512-IsORQDpaaSwcDP4ZZnHxgE85werpo34VYn1Ud3mq+eUsF593faR8oCZNXrROVkpFu2TsbrNhHin0aUrTsQ9vNw==
- dependencies:
- prr "~1.0.1"
-
-error-ex@^1.2.0:
- version "1.3.1"
- resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.1.tgz#f855a86ce61adc4e8621c3cda21e7a7612c3a8dc"
- integrity sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=
- dependencies:
- is-arrayish "^0.2.1"
-
-es6-promise@^4.0.5:
- version "4.2.2"
- resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.2.tgz#f722d7769af88bd33bc13ec6605e1f92966b82d9"
- integrity sha512-LSas5vsuA6Q4nEdf9wokY5/AJYXry98i0IzXsv49rYsgDGDNDPbqAYR1Pe23iFxygfbGZNR/5VrHXBCh2BhvUQ==
-
-events@^1.0.0:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924"
- integrity sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=
-
-evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02"
- integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==
- dependencies:
- md5.js "^1.3.4"
- safe-buffer "^5.1.1"
-
-expand-brackets@^0.1.4:
- version "0.1.5"
- resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b"
- integrity sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=
- dependencies:
- is-posix-bracket "^0.1.0"
-
-expand-range@^1.8.1:
- version "1.8.2"
- resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337"
- integrity sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=
- dependencies:
- fill-range "^2.1.0"
-
-extend@~3.0.0, extend@~3.0.1:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444"
- integrity sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=
-
-extglob@^0.3.1:
- version "0.3.2"
- resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1"
- integrity sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=
- dependencies:
- is-extglob "^1.0.0"
-
-extract-zip@^1.0.3:
- version "1.6.6"
- resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-1.6.6.tgz#1290ede8d20d0872b429fd3f351ca128ec5ef85c"
- integrity sha1-EpDt6NINCHK0Kf0/NRyhKOxe+Fw=
- dependencies:
- concat-stream "1.6.0"
- debug "2.6.9"
- mkdirp "0.5.0"
- yauzl "2.4.1"
-
-extsprintf@1.3.0:
- version "1.3.0"
- resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05"
- integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=
-
-extsprintf@^1.2.0:
- version "1.4.0"
- resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f"
- integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8=
-
-fast-deep-equal@^1.0.0:
+fs-constants@^1.0.0:
version "1.0.0"
- resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz#96256a3bc975595eb36d82e9929d060d893439ff"
- integrity sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8=
-
-fast-json-stable-stringify@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2"
- integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I=
-
-fd-slicer@~1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.0.1.tgz#8b5bcbd9ec327c5041bf9ab023fd6750f1177e65"
- integrity sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=
- dependencies:
- pend "~1.2.0"
-
-filename-regex@^2.0.0:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26"
- integrity sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=
-
-fill-range@^2.1.0:
- version "2.2.3"
- resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.3.tgz#50b77dfd7e469bc7492470963699fe7a8485a723"
- integrity sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=
- dependencies:
- is-number "^2.1.0"
- isobject "^2.0.0"
- randomatic "^1.1.3"
- repeat-element "^1.1.2"
- repeat-string "^1.5.2"
-
-find-up@^1.0.0:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f"
- integrity sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=
- dependencies:
- path-exists "^2.0.0"
- pinkie-promise "^2.0.0"
-
-for-in@^1.0.1:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80"
- integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=
-
-for-own@^0.1.4:
- version "0.1.5"
- resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.5.tgz#5265c681a4f294dabbf17c9509b6763aa84510ce"
- integrity sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=
- dependencies:
- for-in "^1.0.1"
-
-forever-agent@~0.6.1:
- version "0.6.1"
- resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
- integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=
-
-form-data@~2.1.1:
- version "2.1.4"
- resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.1.4.tgz#33c183acf193276ecaa98143a69e94bfee1750d1"
- integrity sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=
- dependencies:
- asynckit "^0.4.0"
- combined-stream "^1.0.5"
- mime-types "^2.1.12"
-
-form-data@~2.3.1:
- version "2.3.1"
- resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.1.tgz#6fb94fbd71885306d73d15cc497fe4cc4ecd44bf"
- integrity sha1-b7lPvXGIUwbXPRXMSX/kzE7NRL8=
- dependencies:
- asynckit "^0.4.0"
- combined-stream "^1.0.5"
- mime-types "^2.1.12"
-
-fs-extra@^0.30.0:
- version "0.30.0"
- resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-0.30.0.tgz#f233ffcc08d4da7d432daa449776989db1df93f0"
- integrity sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A=
- dependencies:
- graceful-fs "^4.1.2"
- jsonfile "^2.1.0"
- klaw "^1.0.0"
- path-is-absolute "^1.0.0"
- rimraf "^2.2.8"
-
-fs.realpath@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
- integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8=
-
-fsevents@^1.0.0:
- version "1.1.3"
- resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.1.3.tgz#11f82318f5fe7bb2cd22965a108e9306208216d8"
- integrity sha512-WIr7iDkdmdbxu/Gh6eKEZJL6KPE74/5MEsf2whTOFNxbIoIixogroLdKYqB6FDav4Wavh/lZdzzd3b2KxIXC5Q==
- dependencies:
- nan "^2.3.0"
- node-pre-gyp "^0.6.39"
-
-fstream-ignore@^1.0.5:
- version "1.0.5"
- resolved "https://registry.yarnpkg.com/fstream-ignore/-/fstream-ignore-1.0.5.tgz#9c31dae34767018fe1d249b24dada67d092da105"
- integrity sha1-nDHa40dnAY/h0kmyTa2mfQktoQU=
- dependencies:
- fstream "^1.0.0"
- inherits "2"
- minimatch "^3.0.0"
-
-fstream@^1.0.0, fstream@^1.0.10, fstream@^1.0.2:
- version "1.0.11"
- resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.11.tgz#5c1fb1f117477114f0632a0eb4b71b3cb0fd3171"
- integrity sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=
- dependencies:
- graceful-fs "^4.1.2"
- inherits "~2.0.0"
- mkdirp ">=0.5 0"
- rimraf "2"
+ resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad"
+ integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==
gauge@~2.7.3:
version "2.7.4"
@@ -896,289 +158,26 @@ gauge@~2.7.3:
strip-ansi "^3.0.1"
wide-align "^1.1.0"
-get-caller-file@^1.0.1:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.2.tgz#f702e63127e7e231c160a80c1554acb70d5047e5"
- integrity sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=
-
-get-stdin@^4.0.1:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe"
- integrity sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=
-
-getpass@^0.1.1:
- version "0.1.7"
- resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa"
- integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=
- dependencies:
- assert-plus "^1.0.0"
-
-glob-base@^0.3.0:
- version "0.3.0"
- resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4"
- integrity sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=
- dependencies:
- glob-parent "^2.0.0"
- is-glob "^2.0.0"
-
-glob-parent@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28"
- integrity sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=
- dependencies:
- is-glob "^2.0.0"
-
-glob@^7.0.5:
- version "7.1.2"
- resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15"
- integrity sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==
- dependencies:
- fs.realpath "^1.0.0"
- inflight "^1.0.4"
- inherits "2"
- minimatch "^3.0.4"
- once "^1.3.0"
- path-is-absolute "^1.0.0"
-
-graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9:
- version "4.1.11"
- resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658"
- integrity sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=
-
-har-schema@^1.0.5:
- version "1.0.5"
- resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-1.0.5.tgz#d263135f43307c02c602afc8fe95970c0151369e"
- integrity sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4=
-
-har-schema@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92"
- integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=
-
-har-validator@~4.2.1:
- version "4.2.1"
- resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-4.2.1.tgz#33481d0f1bbff600dd203d75812a6a5fba002e2a"
- integrity sha1-M0gdDxu/9gDdID11gSpqX7oALio=
- dependencies:
- ajv "^4.9.1"
- har-schema "^1.0.5"
-
-har-validator@~5.0.3:
- version "5.0.3"
- resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.0.3.tgz#ba402c266194f15956ef15e0fcf242993f6a7dfd"
- integrity sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=
- dependencies:
- ajv "^5.1.0"
- har-schema "^2.0.0"
-
-has-flag@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa"
- integrity sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=
+github-from-package@0.0.0:
+ version "0.0.0"
+ resolved "https://registry.yarnpkg.com/github-from-package/-/github-from-package-0.0.0.tgz#97fb5d96bfde8973313f20e8288ef9a167fa64ce"
+ integrity sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=
has-unicode@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9"
integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=
-hash-base@^2.0.0:
- version "2.0.2"
- resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-2.0.2.tgz#66ea1d856db4e8a5470cadf6fce23ae5244ef2e1"
- integrity sha1-ZuodhW206KVHDK32/OI65SRO8uE=
- dependencies:
- inherits "^2.0.1"
-
-hash-base@^3.0.0:
- version "3.0.4"
- resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.0.4.tgz#5fc8686847ecd73499403319a6b0a3f3f6ae4918"
- integrity sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=
- dependencies:
- inherits "^2.0.1"
- safe-buffer "^5.0.1"
-
-hash.js@^1.0.0, hash.js@^1.0.3:
- version "1.1.3"
- resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.3.tgz#340dedbe6290187151c1ea1d777a3448935df846"
- integrity sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==
- dependencies:
- inherits "^2.0.3"
- minimalistic-assert "^1.0.0"
-
-hawk@3.1.3, hawk@~3.1.3:
- version "3.1.3"
- resolved "https://registry.yarnpkg.com/hawk/-/hawk-3.1.3.tgz#078444bd7c1640b0fe540d2c9b73d59678e8e1c4"
- integrity sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=
- dependencies:
- boom "2.x.x"
- cryptiles "2.x.x"
- hoek "2.x.x"
- sntp "1.x.x"
-
-hawk@~6.0.2:
- version "6.0.2"
- resolved "https://registry.yarnpkg.com/hawk/-/hawk-6.0.2.tgz#af4d914eb065f9b5ce4d9d11c1cb2126eecc3038"
- integrity sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ==
- dependencies:
- boom "4.x.x"
- cryptiles "3.x.x"
- hoek "4.x.x"
- sntp "2.x.x"
-
-hmac-drbg@^1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1"
- integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=
- dependencies:
- hash.js "^1.0.3"
- minimalistic-assert "^1.0.0"
- minimalistic-crypto-utils "^1.0.1"
-
-hoek@2.x.x:
- version "2.16.3"
- resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed"
- integrity sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=
-
-hoek@4.x.x:
- version "4.2.0"
- resolved "https://registry.yarnpkg.com/hoek/-/hoek-4.2.0.tgz#72d9d0754f7fe25ca2d01ad8f8f9a9449a89526d"
- integrity sha512-v0XCLxICi9nPfYrS9RL8HbYnXi9obYAeLbSP00BmnZwCK9+Ih9WOjoZ8YoHCoav2csqn4FOz4Orldsy2dmDwmQ==
-
-home-path@^1.0.1:
- version "1.0.5"
- resolved "https://registry.yarnpkg.com/home-path/-/home-path-1.0.5.tgz#788b29815b12d53bacf575648476e6f9041d133f"
- integrity sha1-eIspgVsS1Tus9XVkhHbm+QQdEz8=
-
-hosted-git-info@^2.1.4:
- version "2.5.0"
- resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.5.0.tgz#6d60e34b3abbc8313062c3b798ef8d901a07af3c"
- integrity sha512-pNgbURSuab90KbTqvRPsseaTxOJCZBD0a7t+haSN33piP9cCM4l0CqdzAif2hUqm716UovKB2ROmiabGAKVXyg==
-
-http-signature@~1.1.0:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.1.1.tgz#df72e267066cd0ac67fb76adf8e134a8fbcf91bf"
- integrity sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=
- dependencies:
- assert-plus "^0.2.0"
- jsprim "^1.2.2"
- sshpk "^1.7.0"
-
-http-signature@~1.2.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1"
- integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=
- dependencies:
- assert-plus "^1.0.0"
- jsprim "^1.2.2"
- sshpk "^1.7.0"
-
-https-browserify@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73"
- integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=
-
-ieee754@^1.1.4:
- version "1.1.8"
- resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.8.tgz#be33d40ac10ef1926701f6f08a2d86fbfd1ad3e4"
- integrity sha1-vjPUCsEO8ZJnAfbwii2G+/0a0+Q=
-
-indent-string@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-2.1.0.tgz#8e2d48348742121b4a8218b7a137e9a52049dc80"
- integrity sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=
- dependencies:
- repeating "^2.0.0"
-
-indexof@0.0.1:
- version "0.0.1"
- resolved "https://registry.yarnpkg.com/indexof/-/indexof-0.0.1.tgz#82dc336d232b9062179d05ab3293a66059fd435d"
- integrity sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=
-
-inflight@^1.0.4:
- version "1.0.6"
- resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
- integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=
- dependencies:
- once "^1.3.0"
- wrappy "1"
-
-inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3:
+inherits@~2.0.3:
version "2.0.3"
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
-inherits@2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1"
- integrity sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=
-
ini@~1.3.0:
version "1.3.5"
resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927"
integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==
-interpret@^1.0.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.1.0.tgz#7ed1b1410c6a0e0f78cf95d3b8440c63f78b8614"
- integrity sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=
-
-invert-kv@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6"
- integrity sha1-EEqOSqym09jNFXqO+L+rLXo//bY=
-
-is-arrayish@^0.2.1:
- version "0.2.1"
- resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
- integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=
-
-is-binary-path@^1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898"
- integrity sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=
- dependencies:
- binary-extensions "^1.0.0"
-
-is-buffer@^1.1.5:
- version "1.1.6"
- resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
- integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==
-
-is-builtin-module@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe"
- integrity sha1-VAVy0096wxGfj3bDDLwbHgN6/74=
- dependencies:
- builtin-modules "^1.0.0"
-
-is-dotfile@^1.0.0:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1"
- integrity sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=
-
-is-equal-shallow@^0.1.3:
- version "0.1.3"
- resolved "https://registry.yarnpkg.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534"
- integrity sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=
- dependencies:
- is-primitive "^2.0.0"
-
-is-extendable@^0.1.1:
- version "0.1.1"
- resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89"
- integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=
-
-is-extglob@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0"
- integrity sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=
-
-is-finite@^1.0.0:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa"
- integrity sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=
- dependencies:
- number-is-nan "^1.0.0"
-
is-fullwidth-code-point@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb"
@@ -1186,409 +185,64 @@ is-fullwidth-code-point@^1.0.0:
dependencies:
number-is-nan "^1.0.0"
-is-glob@^2.0.0, is-glob@^2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863"
- integrity sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=
- dependencies:
- is-extglob "^1.0.0"
-
-is-number@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f"
- integrity sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=
- dependencies:
- kind-of "^3.0.2"
-
-is-number@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195"
- integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=
- dependencies:
- kind-of "^3.0.2"
-
-is-posix-bracket@^0.1.0:
- version "0.1.1"
- resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4"
- integrity sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=
-
-is-primitive@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575"
- integrity sha1-IHurkWOEmcB7Kt8kCkGochADRXU=
-
-is-typedarray@~1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
- integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=
-
-is-utf8@^0.2.0:
- version "0.2.1"
- resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72"
- integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=
-
-isarray@0.0.1:
- version "0.0.1"
- resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf"
- integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=
-
-isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0:
+isarray@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=
-isobject@^2.0.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89"
- integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=
+keytar@^4.7.0:
+ version "4.10.0"
+ resolved "https://registry.yarnpkg.com/keytar/-/keytar-4.10.0.tgz#03897398b22d6e60dbd0b381c088b2495ff32ce5"
+ integrity sha512-oL6dF4FMX8G80zL5e1CPIUEKwZCe9XZw6JZI5YesNstamzJbyZduj7NMUEX2l72BLyWQibyZOvipmof0QbsbRQ==
dependencies:
- isarray "1.0.0"
+ nan "2.14.0"
+ prebuild-install "5.3.0"
-isstream@~0.1.2:
- version "0.1.2"
- resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
- integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=
-
-jsbn@~0.1.0:
- version "0.1.1"
- resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
- integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM=
-
-json-loader@^0.5.4:
- version "0.5.7"
- resolved "https://registry.yarnpkg.com/json-loader/-/json-loader-0.5.7.tgz#dca14a70235ff82f0ac9a3abeb60d337a365185d"
- integrity sha512-QLPs8Dj7lnf3e3QYS1zkCo+4ZwqOiF9d/nZnYozTISxXWCfNs9yuky5rJw4/W34s7POaNlbZmQGaB5NiXCbP4w==
-
-json-schema-traverse@^0.3.0:
- version "0.3.1"
- resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340"
- integrity sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=
-
-json-schema@0.2.3:
- version "0.2.3"
- resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13"
- integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=
-
-json-stable-stringify@^1.0.1:
+mimic-response@^1.0.0:
version "1.0.1"
- resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af"
- integrity sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=
- dependencies:
- jsonify "~0.0.0"
-
-json-stringify-safe@~5.0.1:
- version "5.0.1"
- resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
- integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=
-
-json5@^0.5.0, json5@^0.5.1:
- version "0.5.1"
- resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821"
- integrity sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=
-
-jsonfile@^2.1.0:
- version "2.4.0"
- resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-2.4.0.tgz#3736a2b428b87bbda0cc83b53fa3d633a35c2ae8"
- integrity sha1-NzaitCi4e72gzIO1P6PWM6NcKug=
- optionalDependencies:
- graceful-fs "^4.1.6"
-
-jsonify@~0.0.0:
- version "0.0.0"
- resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73"
- integrity sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=
-
-jsprim@^1.2.2:
- version "1.4.1"
- resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2"
- integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=
- dependencies:
- assert-plus "1.0.0"
- extsprintf "1.3.0"
- json-schema "0.2.3"
- verror "1.10.0"
-
-kind-of@^3.0.2:
- version "3.2.2"
- resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64"
- integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=
- dependencies:
- is-buffer "^1.1.5"
-
-kind-of@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57"
- integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc=
- dependencies:
- is-buffer "^1.1.5"
-
-klaw@^1.0.0:
- version "1.3.1"
- resolved "https://registry.yarnpkg.com/klaw/-/klaw-1.3.1.tgz#4088433b46b3b1ba259d78785d8e96f73ba02439"
- integrity sha1-QIhDO0azsbolnXh4XY6W9zugJDk=
- optionalDependencies:
- graceful-fs "^4.1.9"
-
-lazy-cache@^1.0.3:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e"
- integrity sha1-odePw6UEdMuAhF07O24dpJpEbo4=
-
-lcid@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835"
- integrity sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=
- dependencies:
- invert-kv "^1.0.0"
-
-load-json-file@^1.0.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0"
- integrity sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=
- dependencies:
- graceful-fs "^4.1.2"
- parse-json "^2.2.0"
- pify "^2.0.0"
- pinkie-promise "^2.0.0"
- strip-bom "^2.0.0"
-
-loader-runner@^2.3.0:
- version "2.3.0"
- resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.3.0.tgz#f482aea82d543e07921700d5a46ef26fdac6b8a2"
- integrity sha1-9IKuqC1UPgeSFwDVpG7yb9rGuKI=
-
-loader-utils@^0.2.16:
- version "0.2.17"
- resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-0.2.17.tgz#f86e6374d43205a6e6c60e9196f17c0299bfb348"
- integrity sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=
- dependencies:
- big.js "^3.1.3"
- emojis-list "^2.0.0"
- json5 "^0.5.0"
- object-assign "^4.0.1"
-
-lodash@^4.14.0:
- version "4.17.4"
- resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae"
- integrity sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=
-
-longest@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097"
- integrity sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=
-
-loud-rejection@^1.0.0:
- version "1.6.0"
- resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f"
- integrity sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=
- dependencies:
- currently-unhandled "^0.4.1"
- signal-exit "^3.0.0"
-
-map-obj@^1.0.0, map-obj@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d"
- integrity sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=
-
-md5.js@^1.3.4:
- version "1.3.4"
- resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.4.tgz#e9bdbde94a20a5ac18b04340fc5764d5b09d901d"
- integrity sha1-6b296UogpawYsENA/Fdk1bCdkB0=
- dependencies:
- hash-base "^3.0.0"
- inherits "^2.0.1"
-
-memory-fs@^0.4.0, memory-fs@~0.4.1:
- version "0.4.1"
- resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552"
- integrity sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=
- dependencies:
- errno "^0.1.3"
- readable-stream "^2.0.1"
-
-meow@^3.1.0:
- version "3.7.0"
- resolved "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb"
- integrity sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=
- dependencies:
- camelcase-keys "^2.0.0"
- decamelize "^1.1.2"
- loud-rejection "^1.0.0"
- map-obj "^1.0.1"
- minimist "^1.1.3"
- normalize-package-data "^2.3.4"
- object-assign "^4.0.1"
- read-pkg-up "^1.0.1"
- redent "^1.0.0"
- trim-newlines "^1.0.0"
-
-micromatch@^2.1.5:
- version "2.3.11"
- resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565"
- integrity sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=
- dependencies:
- arr-diff "^2.0.0"
- array-unique "^0.2.1"
- braces "^1.8.2"
- expand-brackets "^0.1.4"
- extglob "^0.3.1"
- filename-regex "^2.0.0"
- is-extglob "^1.0.0"
- is-glob "^2.0.1"
- kind-of "^3.0.2"
- normalize-path "^2.0.1"
- object.omit "^2.0.0"
- parse-glob "^3.0.4"
- regex-cache "^0.4.2"
-
-miller-rabin@^4.0.0:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d"
- integrity sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==
- dependencies:
- bn.js "^4.0.0"
- brorand "^1.0.1"
-
-mime-db@~1.30.0:
- version "1.30.0"
- resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.30.0.tgz#74c643da2dd9d6a45399963465b26d5ca7d71f01"
- integrity sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=
-
-mime-types@^2.1.12, mime-types@~2.1.17, mime-types@~2.1.7:
- version "2.1.17"
- resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.17.tgz#09d7a393f03e995a79f8af857b70a9e0ab16557a"
- integrity sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=
- dependencies:
- mime-db "~1.30.0"
-
-minimalistic-assert@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz#702be2dda6b37f4836bcb3f5db56641b64a1d3d3"
- integrity sha1-cCvi3aazf0g2vLP121ZkG2Sh09M=
-
-minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a"
- integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=
-
-minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.4:
- version "3.0.4"
- resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
- integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
- dependencies:
- brace-expansion "^1.1.7"
+ resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b"
+ integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==
minimist@0.0.8:
version "0.0.8"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=
-minimist@^1.1.0, minimist@^1.1.3, minimist@^1.2.0:
+minimist@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=
-mkdirp@0.5.0:
- version "0.5.0"
- resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.0.tgz#1d73076a6df986cd9344e15e71fcc05a4c9abf12"
- integrity sha1-HXMHam35hs2TROFecfzAWkyavxI=
- dependencies:
- minimist "0.0.8"
-
-"mkdirp@>=0.5 0", mkdirp@^0.5.1, mkdirp@~0.5.0:
+mkdirp@^0.5.1:
version "0.5.1"
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=
dependencies:
minimist "0.0.8"
-ms@2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
- integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=
+nan@2.14.0, nan@^2.10.0:
+ version "2.14.0"
+ resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c"
+ integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==
-nan@^2.3.0:
+napi-build-utils@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/napi-build-utils/-/napi-build-utils-1.0.1.tgz#1381a0f92c39d66bf19852e7873432fc2123e508"
+ integrity sha512-boQj1WFgQH3v4clhu3mTNfP+vOBxorDlE8EKiMjUlLG3C4qAESnn9AxIOkFgTR2c9LtzNjPrjS60cT27ZKBhaA==
+
+node-abi@^2.7.0:
version "2.8.0"
- resolved "https://registry.yarnpkg.com/nan/-/nan-2.8.0.tgz#ed715f3fe9de02b57a5e6252d90a96675e1f085a"
- integrity sha1-7XFfP+neArV6XmJS2QqWZ14fCFo=
-
-ngx-toastr@^8.0.0:
- version "8.1.0"
- resolved "https://registry.yarnpkg.com/ngx-toastr/-/ngx-toastr-8.1.0.tgz#3a0742e62895f88e232607843d61373d6f0d44d3"
- integrity sha512-asgeQsjm0nf6B9COL7v5Dm4p9GbIjce8eMpvMzalxAJMaWiuryngaG+72TnrmeM48D/vwOUEasvJgYVRZ6JPMg==
-
-node-libs-browser@^2.0.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.1.0.tgz#5f94263d404f6e44767d726901fff05478d600df"
- integrity sha512-5AzFzdoIMb89hBGMZglEegffzgRg+ZFoUmisQ8HI4j1KDdpx13J0taNp2y9xPbur6W61gepGDDotGBVQ7mfUCg==
+ resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-2.8.0.tgz#bd2e88dbe6a6871e6dd08553e0605779325737ec"
+ integrity sha512-1/aa2clS0pue0HjckL62CsbhWWU35HARvBDXcJtYKbYR7LnIutmpxmXbuDMV9kEviD2lP/wACOgWmmwljghHyQ==
dependencies:
- assert "^1.1.1"
- browserify-zlib "^0.2.0"
- buffer "^4.3.0"
- console-browserify "^1.1.0"
- constants-browserify "^1.0.0"
- crypto-browserify "^3.11.0"
- domain-browser "^1.1.1"
- events "^1.0.0"
- https-browserify "^1.0.0"
- os-browserify "^0.3.0"
- path-browserify "0.0.0"
- process "^0.11.10"
- punycode "^1.2.4"
- querystring-es3 "^0.2.0"
- readable-stream "^2.3.3"
- stream-browserify "^2.0.1"
- stream-http "^2.7.2"
- string_decoder "^1.0.0"
- timers-browserify "^2.0.4"
- tty-browserify "0.0.0"
- url "^0.11.0"
- util "^0.10.3"
- vm-browserify "0.0.4"
+ semver "^5.4.1"
-node-pre-gyp@^0.6.39:
- version "0.6.39"
- resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.6.39.tgz#c00e96860b23c0e1420ac7befc5044e1d78d8649"
- integrity sha512-OsJV74qxnvz/AMGgcfZoDaeDXKD3oY3QVIbBmwszTFkRisTSXbMQyn4UWzUMOtA5SVhrBZOTp0wcoSBgfMfMmQ==
- dependencies:
- detect-libc "^1.0.2"
- hawk "3.1.3"
- mkdirp "^0.5.1"
- nopt "^4.0.1"
- npmlog "^4.0.2"
- rc "^1.1.7"
- request "2.81.0"
- rimraf "^2.6.1"
- semver "^5.3.0"
- tar "^2.2.1"
- tar-pack "^3.4.0"
+noop-logger@^0.1.1:
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/noop-logger/-/noop-logger-0.1.1.tgz#94a2b1633c4f1317553007d8966fd0e841b6a4c2"
+ integrity sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI=
-nopt@^4.0.1:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d"
- integrity sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=
- dependencies:
- abbrev "1"
- osenv "^0.1.4"
-
-normalize-package-data@^2.3.2, normalize-package-data@^2.3.4:
- version "2.4.0"
- resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.4.0.tgz#12f95a307d58352075a04907b84ac8be98ac012f"
- integrity sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==
- dependencies:
- hosted-git-info "^2.1.4"
- is-builtin-module "^1.0.0"
- semver "2 || 3 || 4 || 5"
- validate-npm-package-license "^3.0.1"
-
-normalize-path@^2.0.0, normalize-path@^2.0.1:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9"
- integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=
- dependencies:
- remove-trailing-separator "^1.0.1"
-
-npmlog@^4.0.2:
+npmlog@^4.0.1:
version "4.1.2"
resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b"
integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==
@@ -1598,314 +252,87 @@ npmlog@^4.0.2:
gauge "~2.7.3"
set-blocking "~2.0.0"
-nugget@^2.0.0:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/nugget/-/nugget-2.0.1.tgz#201095a487e1ad36081b3432fa3cada4f8d071b0"
- integrity sha1-IBCVpIfhrTYIGzQy+jytpPjQcbA=
- dependencies:
- debug "^2.1.3"
- minimist "^1.1.0"
- pretty-bytes "^1.0.2"
- progress-stream "^1.1.0"
- request "^2.45.0"
- single-line-log "^1.1.2"
- throttleit "0.0.2"
-
number-is-nan@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=
-oauth-sign@~0.8.1, oauth-sign@~0.8.2:
- version "0.8.2"
- resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43"
- integrity sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=
-
-object-assign@^4.0.1, object-assign@^4.1.0:
+object-assign@^4.1.0:
version "4.1.1"
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
-object-keys@~0.4.0:
- version "0.4.0"
- resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-0.4.0.tgz#28a6aae7428dd2c3a92f3d95f21335dd204e0336"
- integrity sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=
-
-object.omit@^2.0.0:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa"
- integrity sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=
- dependencies:
- for-own "^0.1.4"
- is-extendable "^0.1.1"
-
-once@^1.3.0, once@^1.3.3:
+once@^1.3.1, once@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E=
dependencies:
wrappy "1"
-os-browserify@^0.3.0:
- version "0.3.0"
- resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27"
- integrity sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=
-
-os-homedir@^1.0.0:
+os-homedir@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3"
integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M=
-os-locale@^1.4.0:
- version "1.4.0"
- resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9"
- integrity sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=
+prebuild-install@5.3.0:
+ version "5.3.0"
+ resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-5.3.0.tgz#58b4d8344e03590990931ee088dd5401b03004c8"
+ integrity sha512-aaLVANlj4HgZweKttFNUVNRxDukytuIuxeK2boIMHjagNJCiVKWFsKF4tCE3ql3GbrD2tExPQ7/pwtEJcHNZeg==
dependencies:
- lcid "^1.0.0"
-
-os-tmpdir@^1.0.0:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
- integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=
-
-osenv@^0.1.4:
- version "0.1.4"
- resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.4.tgz#42fe6d5953df06c8064be6f176c3d05aaaa34644"
- integrity sha1-Qv5tWVPfBsgGS+bxdsPQWqqjRkQ=
- dependencies:
- os-homedir "^1.0.0"
- os-tmpdir "^1.0.0"
-
-pako@~1.0.5:
- version "1.0.6"
- resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.6.tgz#0101211baa70c4bca4a0f63f2206e97b7dfaf258"
- integrity sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg==
-
-parse-asn1@^5.0.0:
- version "5.1.0"
- resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.0.tgz#37c4f9b7ed3ab65c74817b5f2480937fbf97c712"
- integrity sha1-N8T5t+06tlx0gXtfJICTf7+XxxI=
- dependencies:
- asn1.js "^4.0.0"
- browserify-aes "^1.0.0"
- create-hash "^1.1.0"
- evp_bytestokey "^1.0.0"
- pbkdf2 "^3.0.3"
-
-parse-glob@^3.0.4:
- version "3.0.4"
- resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c"
- integrity sha1-ssN2z7EfNVE7rdFz7wu246OIORw=
- dependencies:
- glob-base "^0.3.0"
- is-dotfile "^1.0.0"
- is-extglob "^1.0.0"
- is-glob "^2.0.0"
-
-parse-json@^2.2.0:
- version "2.2.0"
- resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9"
- integrity sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=
- dependencies:
- error-ex "^1.2.0"
-
-path-browserify@0.0.0:
- version "0.0.0"
- resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.0.tgz#a0b870729aae214005b7d5032ec2cbbb0fb4451a"
- integrity sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=
-
-path-exists@^2.0.0, path-exists@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b"
- integrity sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=
- dependencies:
- pinkie-promise "^2.0.0"
-
-path-is-absolute@^1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
- integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18=
-
-path-type@^1.0.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441"
- integrity sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=
- dependencies:
- graceful-fs "^4.1.2"
- pify "^2.0.0"
- pinkie-promise "^2.0.0"
-
-pbkdf2@^3.0.3:
- version "3.0.14"
- resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.14.tgz#a35e13c64799b06ce15320f459c230e68e73bade"
- integrity sha512-gjsZW9O34fm0R7PaLHRJmLLVfSoesxztjPjE9o6R+qtVJij90ltg1joIovN9GKrRW3t1PzhDDG3UMEMFfZ+1wA==
- dependencies:
- create-hash "^1.1.2"
- create-hmac "^1.1.4"
- ripemd160 "^2.0.1"
- safe-buffer "^5.0.1"
- sha.js "^2.4.8"
-
-pend@~1.2.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50"
- integrity sha1-elfrVQpng/kRUzH89GY9XI4AelA=
-
-performance-now@^0.2.0:
- version "0.2.0"
- resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-0.2.0.tgz#33ef30c5c77d4ea21c5a53869d91b56d8f2555e5"
- integrity sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=
-
-performance-now@^2.1.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
- integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=
-
-pify@^2.0.0:
- version "2.3.0"
- resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
- integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw=
-
-pinkie-promise@^2.0.0:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa"
- integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o=
- dependencies:
- pinkie "^2.0.0"
-
-pinkie@^2.0.0:
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870"
- integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA=
-
-preserve@^0.2.0:
- version "0.2.0"
- resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b"
- integrity sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=
-
-pretty-bytes@^1.0.2:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-1.0.4.tgz#0a22e8210609ad35542f8c8d5d2159aff0751c84"
- integrity sha1-CiLoIQYJrTVUL4yNXSFZr/B1HIQ=
- dependencies:
- get-stdin "^4.0.1"
- meow "^3.1.0"
+ detect-libc "^1.0.3"
+ expand-template "^2.0.3"
+ github-from-package "0.0.0"
+ minimist "^1.2.0"
+ mkdirp "^0.5.1"
+ napi-build-utils "^1.0.1"
+ node-abi "^2.7.0"
+ noop-logger "^0.1.1"
+ npmlog "^4.0.1"
+ os-homedir "^1.0.1"
+ pump "^2.0.1"
+ rc "^1.2.7"
+ simple-get "^2.7.0"
+ tar-fs "^1.13.0"
+ tunnel-agent "^0.6.0"
+ which-pm-runs "^1.0.0"
process-nextick-args@~1.0.6:
version "1.0.7"
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3"
integrity sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=
-process@^0.11.10:
- version "0.11.10"
- resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182"
- integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI=
+process-nextick-args@~2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa"
+ integrity sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==
-progress-stream@^1.1.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/progress-stream/-/progress-stream-1.2.0.tgz#2cd3cfea33ba3a89c9c121ec3347abe9ab125f77"
- integrity sha1-LNPP6jO6OonJwSHsM0er6asSX3c=
- dependencies:
- speedometer "~0.1.2"
- through2 "~0.2.3"
-
-prr@~1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476"
- integrity sha1-0/wRS6BplaRexok/SEzrHXj19HY=
-
-public-encrypt@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.0.tgz#39f699f3a46560dd5ebacbca693caf7c65c18cc6"
- integrity sha1-OfaZ86RlYN1eusvKaTyvfGXBjMY=
- dependencies:
- bn.js "^4.1.0"
- browserify-rsa "^4.0.0"
- create-hash "^1.1.0"
- parse-asn1 "^5.0.0"
- randombytes "^2.0.1"
-
-punycode@1.3.2:
- version "1.3.2"
- resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d"
- integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=
-
-punycode@^1.2.4, punycode@^1.4.1:
- version "1.4.1"
- resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e"
- integrity sha1-wNWmOycYgArY4esPpSachN1BhF4=
-
-qs@~6.4.0:
- version "6.4.0"
- resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233"
- integrity sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=
-
-qs@~6.5.1:
- version "6.5.1"
- resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.1.tgz#349cdf6eef89ec45c12d7d5eb3fc0c870343a6d8"
- integrity sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==
-
-querystring-es3@^0.2.0:
- version "0.2.1"
- resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73"
- integrity sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=
-
-querystring@0.2.0:
- version "0.2.0"
- resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620"
- integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=
-
-randomatic@^1.1.3:
- version "1.1.7"
- resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-1.1.7.tgz#c7abe9cc8b87c0baa876b19fde83fd464797e38c"
- integrity sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==
- dependencies:
- is-number "^3.0.0"
- kind-of "^4.0.0"
-
-randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5:
- version "2.0.6"
- resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.0.6.tgz#d302c522948588848a8d300c932b44c24231da80"
- integrity sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==
- dependencies:
- safe-buffer "^5.1.0"
-
-randomfill@^1.0.3:
+pump@^1.0.0:
version "1.0.3"
- resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.3.tgz#b96b7df587f01dd91726c418f30553b1418e3d62"
- integrity sha512-YL6GrhrWoic0Eq8rXVbMptH7dAxCs0J+mh5Y0euNekPPYaxEmdVGim6GdoxoRzKW2yJoU8tueifS7mYxvcFDEQ==
+ resolved "https://registry.yarnpkg.com/pump/-/pump-1.0.3.tgz#5dfe8311c33bbf6fc18261f9f34702c47c08a954"
+ integrity sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw==
dependencies:
- randombytes "^2.0.5"
- safe-buffer "^5.1.0"
+ end-of-stream "^1.1.0"
+ once "^1.3.1"
-rc@^1.1.2, rc@^1.1.7:
- version "1.2.4"
- resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.4.tgz#a0f606caae2a3b862bbd0ef85482c0125b315fa3"
- integrity sha1-oPYGyq4qO4YrvQ74VILAElsxX6M=
+pump@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/pump/-/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909"
+ integrity sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==
dependencies:
- deep-extend "~0.4.0"
+ end-of-stream "^1.1.0"
+ once "^1.3.1"
+
+rc@^1.2.7:
+ version "1.2.8"
+ resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed"
+ integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==
+ dependencies:
+ deep-extend "^0.6.0"
ini "~1.3.0"
minimist "^1.2.0"
strip-json-comments "~2.0.1"
-read-pkg-up@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02"
- integrity sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=
- dependencies:
- find-up "^1.0.0"
- read-pkg "^1.0.0"
-
-read-pkg@^1.0.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28"
- integrity sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=
- dependencies:
- load-json-file "^1.0.0"
- normalize-package-data "^2.3.2"
- path-type "^1.0.0"
-
-readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.2.2, readable-stream@^2.3.3:
+readable-stream@^2.0.6:
version "2.3.3"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.3.tgz#368f2512d79f9d46fdfc71349ae7878bbc1eb95c"
integrity sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==
@@ -1918,303 +345,73 @@ readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable
string_decoder "~1.0.3"
util-deprecate "~1.0.1"
-readable-stream@~1.1.9:
- version "1.1.14"
- resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9"
- integrity sha1-fPTFTvZI44EwhMY23SB54WbAgdk=
+readable-stream@^2.3.0, readable-stream@^2.3.5:
+ version "2.3.6"
+ resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf"
+ integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==
dependencies:
core-util-is "~1.0.0"
- inherits "~2.0.1"
- isarray "0.0.1"
- string_decoder "~0.10.x"
+ inherits "~2.0.3"
+ isarray "~1.0.0"
+ process-nextick-args "~2.0.0"
+ safe-buffer "~5.1.1"
+ string_decoder "~1.1.1"
+ util-deprecate "~1.0.1"
-readdirp@^2.0.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.1.0.tgz#4ed0ad060df3073300c48440373f72d1cc642d78"
- integrity sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=
- dependencies:
- graceful-fs "^4.1.2"
- minimatch "^3.0.2"
- readable-stream "^2.0.2"
- set-immediate-shim "^1.0.1"
-
-redent@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/redent/-/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde"
- integrity sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=
- dependencies:
- indent-string "^2.1.0"
- strip-indent "^1.0.1"
-
-regex-cache@^0.4.2:
- version "0.4.4"
- resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.4.tgz#75bdc58a2a1496cec48a12835bc54c8d562336dd"
- integrity sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==
- dependencies:
- is-equal-shallow "^0.1.3"
-
-remove-trailing-separator@^1.0.1:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef"
- integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8=
-
-repeat-element@^1.1.2:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.2.tgz#ef089a178d1483baae4d93eb98b4f9e4e11d990a"
- integrity sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=
-
-repeat-string@^1.5.2:
- version "1.6.1"
- resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637"
- integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc=
-
-repeating@^2.0.0:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda"
- integrity sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=
- dependencies:
- is-finite "^1.0.0"
-
-request@2.81.0:
- version "2.81.0"
- resolved "https://registry.yarnpkg.com/request/-/request-2.81.0.tgz#c6928946a0e06c5f8d6f8a9333469ffda46298a0"
- integrity sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA=
- dependencies:
- aws-sign2 "~0.6.0"
- aws4 "^1.2.1"
- caseless "~0.12.0"
- combined-stream "~1.0.5"
- extend "~3.0.0"
- forever-agent "~0.6.1"
- form-data "~2.1.1"
- har-validator "~4.2.1"
- hawk "~3.1.3"
- http-signature "~1.1.0"
- is-typedarray "~1.0.0"
- isstream "~0.1.2"
- json-stringify-safe "~5.0.1"
- mime-types "~2.1.7"
- oauth-sign "~0.8.1"
- performance-now "^0.2.0"
- qs "~6.4.0"
- safe-buffer "^5.0.1"
- stringstream "~0.0.4"
- tough-cookie "~2.3.0"
- tunnel-agent "^0.6.0"
- uuid "^3.0.0"
-
-request@^2.45.0:
- version "2.83.0"
- resolved "https://registry.yarnpkg.com/request/-/request-2.83.0.tgz#ca0b65da02ed62935887808e6f510381034e3356"
- integrity sha512-lR3gD69osqm6EYLk9wB/G1W/laGWjzH90t1vEa2xuxHD5KUrSzp9pUSfTm+YC5Nxt2T8nMPEvKlhbQayU7bgFw==
- dependencies:
- aws-sign2 "~0.7.0"
- aws4 "^1.6.0"
- caseless "~0.12.0"
- combined-stream "~1.0.5"
- extend "~3.0.1"
- forever-agent "~0.6.1"
- form-data "~2.3.1"
- har-validator "~5.0.3"
- hawk "~6.0.2"
- http-signature "~1.2.0"
- is-typedarray "~1.0.0"
- isstream "~0.1.2"
- json-stringify-safe "~5.0.1"
- mime-types "~2.1.17"
- oauth-sign "~0.8.2"
- performance-now "^2.1.0"
- qs "~6.5.1"
- safe-buffer "^5.1.1"
- stringstream "~0.0.5"
- tough-cookie "~2.3.3"
- tunnel-agent "^0.6.0"
- uuid "^3.1.0"
-
-require-directory@^2.1.1:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
- integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I=
-
-require-main-filename@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1"
- integrity sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=
-
-right-align@^0.1.1:
- version "0.1.3"
- resolved "https://registry.yarnpkg.com/right-align/-/right-align-0.1.3.tgz#61339b722fe6a3515689210d24e14c96148613ef"
- integrity sha1-YTObci/mo1FWiSENJOFMlhSGE+8=
- dependencies:
- align-text "^0.1.1"
-
-rimraf@2, rimraf@^2.2.8, rimraf@^2.5.1, rimraf@^2.6.1:
- version "2.6.2"
- resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36"
- integrity sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==
- dependencies:
- glob "^7.0.5"
-
-ripemd160@^2.0.0, ripemd160@^2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.1.tgz#0f4584295c53a3628af7e6d79aca21ce57d1c6e7"
- integrity sha1-D0WEKVxTo2KK9+bXmsohzlfRxuc=
- dependencies:
- hash-base "^2.0.0"
- inherits "^2.0.1"
-
-rxjs@^5.4.0:
- version "5.5.6"
- resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-5.5.6.tgz#e31fb96d6fd2ff1fd84bcea8ae9c02d007179c02"
- integrity sha512-v4Q5HDC0FHAQ7zcBX7T2IL6O5ltl1a2GX4ENjPXg6SjDY69Cmx9v4113C99a4wGF16ClPv5Z8mghuYorVkg/kg==
- dependencies:
- symbol-observable "1.0.1"
-
-safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
+safe-buffer@^5.0.1, safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
version "5.1.1"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853"
integrity sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==
-"semver@2 || 3 || 4 || 5", semver@^5.1.0, semver@^5.3.0:
- version "5.5.0"
- resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab"
- integrity sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==
+safer-buffer@~2.1.0:
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
+ integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
-set-blocking@^2.0.0, set-blocking@~2.0.0:
+semver@^5.4.1:
+ version "5.7.0"
+ resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.0.tgz#790a7cf6fea5459bac96110b29b60412dc8ff96b"
+ integrity sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==
+
+set-blocking@~2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc=
-set-immediate-shim@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61"
- integrity sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=
-
-setimmediate@^1.0.4:
- version "1.0.5"
- resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285"
- integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=
-
-sha.js@^2.4.0, sha.js@^2.4.8:
- version "2.4.9"
- resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.9.tgz#98f64880474b74f4a38b8da9d3c0f2d104633e7d"
- integrity sha512-G8zektVqbiPHrylgew9Zg1VRB1L/DtXNUVAM6q4QLy8NE3qtHlFXTf8VLL4k1Yl6c7NMjtZUTdXV+X44nFaT6A==
- dependencies:
- inherits "^2.0.1"
- safe-buffer "^5.0.1"
-
signal-exit@^3.0.0:
version "3.0.2"
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d"
integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=
-single-line-log@^1.1.2:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/single-line-log/-/single-line-log-1.1.2.tgz#c2f83f273a3e1a16edb0995661da0ed5ef033364"
- integrity sha1-wvg/Jzo+GhbtsJlWYdoO1e8DM2Q=
+simple-concat@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.0.tgz#7344cbb8b6e26fb27d66b2fc86f9f6d5997521c6"
+ integrity sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY=
+
+simple-get@^2.7.0:
+ version "2.8.1"
+ resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-2.8.1.tgz#0e22e91d4575d87620620bc91308d57a77f44b5d"
+ integrity sha512-lSSHRSw3mQNUGPAYRqo7xy9dhKmxFXIjLjp4KHpf99GEH2VH7C3AM+Qfx6du6jhfUi6Vm7XnbEVEf7Wb6N8jRw==
dependencies:
- string-width "^1.0.1"
+ decompress-response "^3.3.0"
+ once "^1.3.1"
+ simple-concat "^1.0.0"
-sntp@1.x.x:
- version "1.0.9"
- resolved "https://registry.yarnpkg.com/sntp/-/sntp-1.0.9.tgz#6541184cc90aeea6c6e7b35e2659082443c66198"
- integrity sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=
- dependencies:
- hoek "2.x.x"
-
-sntp@2.x.x:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/sntp/-/sntp-2.1.0.tgz#2c6cec14fedc2222739caf9b5c3d85d1cc5a2cc8"
- integrity sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg==
- dependencies:
- hoek "4.x.x"
-
-source-list-map@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.0.tgz#aaa47403f7b245a92fbc97ea08f250d6087ed085"
- integrity sha512-I2UmuJSRr/T8jisiROLU3A3ltr+swpniSmNPI4Ml3ZCX6tVnDsuZzK7F2hl5jTqbZBWCEKlj5HRQiPExXLgE8A==
-
-source-map@^0.5.3, source-map@~0.5.1:
- version "0.5.7"
- resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
- integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=
-
-source-map@~0.6.1:
- version "0.6.1"
- resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
- integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
-
-spdx-correct@~1.0.0:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-1.0.2.tgz#4b3073d933ff51f3912f03ac5519498a4150db40"
- integrity sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=
- dependencies:
- spdx-license-ids "^1.0.2"
-
-spdx-expression-parse@~1.0.0:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz#9bdf2f20e1f40ed447fbe273266191fced51626c"
- integrity sha1-m98vIOH0DtRH++JzJmGR/O1RYmw=
-
-spdx-license-ids@^1.0.2:
- version "1.2.2"
- resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz#c9df7a3424594ade6bd11900d596696dc06bac57"
- integrity sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=
-
-speedometer@~0.1.2:
- version "0.1.4"
- resolved "https://registry.yarnpkg.com/speedometer/-/speedometer-0.1.4.tgz#9876dbd2a169d3115402d48e6ea6329c8816a50d"
- integrity sha1-mHbb0qFp0xFUAtSObqYynIgWpQ0=
-
-ssh2-streams@~0.1.18:
- version "0.1.20"
- resolved "https://registry.yarnpkg.com/ssh2-streams/-/ssh2-streams-0.1.20.tgz#51118d154555df5469ee1f67e0cf1e7e8a2c0e3a"
- integrity sha1-URGNFUVV31Rp7h9n4M8efoosDjo=
+ssh2-streams@^0.4.2, ssh2-streams@~0.4.4:
+ version "0.4.4"
+ resolved "https://registry.yarnpkg.com/ssh2-streams/-/ssh2-streams-0.4.4.tgz#7f07464c4b19ee93324995ec7164f110c5a13658"
+ integrity sha512-yNfPZgJO/N69TvYkpDHZBkXAXQzTpfzRkOphQu3PeUpZnrjp9VNa8RKDZkZDpjsWItay+I4NMAbZZ7DqHRt0AQ==
dependencies:
asn1 "~0.2.0"
- semver "^5.1.0"
+ bcrypt-pbkdf "^1.0.2"
streamsearch "~0.1.2"
-ssh2@^0.5.5:
- version "0.5.5"
- resolved "https://registry.yarnpkg.com/ssh2/-/ssh2-0.5.5.tgz#c7781ecd2ece7304a253cf620fab5a5c22bb2235"
- integrity sha1-x3gezS7OcwSiU89iD6taXCK7IjU=
+ssh2@^0.8.2:
+ version "0.8.4"
+ resolved "https://registry.yarnpkg.com/ssh2/-/ssh2-0.8.4.tgz#0a657d9371c1fe9f9e349bcff6144febee256aa6"
+ integrity sha512-qztb9t4b34wJSiWVpeTMVVN/5KCuBoyctBc2BcSe/Uq4NRnF0gB16Iu5p72ILhdYATcMNwB5WppzPIEs/3wB8Q==
dependencies:
- ssh2-streams "~0.1.18"
-
-sshpk@^1.7.0:
- version "1.13.1"
- resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.13.1.tgz#512df6da6287144316dc4c18fe1cf1d940739be3"
- integrity sha1-US322mKHFEMW3EwY/hzx2UBzm+M=
- dependencies:
- asn1 "~0.2.3"
- assert-plus "^1.0.0"
- dashdash "^1.12.0"
- getpass "^0.1.1"
- optionalDependencies:
- bcrypt-pbkdf "^1.0.0"
- ecc-jsbn "~0.1.1"
- jsbn "~0.1.0"
- tweetnacl "~0.14.0"
-
-stream-browserify@^2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.1.tgz#66266ee5f9bdb9940a4e4514cafb43bb71e5c9db"
- integrity sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=
- dependencies:
- inherits "~2.0.1"
- readable-stream "^2.0.2"
-
-stream-http@^2.7.2:
- version "2.8.0"
- resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.8.0.tgz#fd86546dac9b1c91aff8fc5d287b98fafb41bc10"
- integrity sha512-sZOFxI/5xw058XIRHl4dU3dZ+TTOIGJR78Dvo0oEAejIt4ou27k+3ne1zYmCV+v7UucbxIFQuOgnkTVHh8YPnw==
- dependencies:
- builtin-status-codes "^3.0.0"
- inherits "^2.0.1"
- readable-stream "^2.3.3"
- to-arraybuffer "^1.0.0"
- xtend "^4.0.0"
+ ssh2-streams "~0.4.4"
streamsearch@~0.1.2:
version "0.1.2"
@@ -2230,22 +427,19 @@ string-width@^1.0.1, string-width@^1.0.2:
is-fullwidth-code-point "^1.0.0"
strip-ansi "^3.0.0"
-string_decoder@^1.0.0, string_decoder@~1.0.3:
+string_decoder@~1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.3.tgz#0fc67d7c141825de94282dd536bec6b9bce860ab"
integrity sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==
dependencies:
safe-buffer "~5.1.0"
-string_decoder@~0.10.x:
- version "0.10.31"
- resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94"
- integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=
-
-stringstream@~0.0.4, stringstream@~0.0.5:
- version "0.0.5"
- resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878"
- integrity sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=
+string_decoder@~1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8"
+ integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==
+ dependencies:
+ safe-buffer "~5.1.0"
strip-ansi@^3.0.0, strip-ansi@^3.0.1:
version "3.0.1"
@@ -2254,114 +448,38 @@ strip-ansi@^3.0.0, strip-ansi@^3.0.1:
dependencies:
ansi-regex "^2.0.0"
-strip-bom@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e"
- integrity sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=
- dependencies:
- is-utf8 "^0.2.0"
-
-strip-indent@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-1.0.1.tgz#0c7962a6adefa7bbd4ac366460a638552ae1a0a2"
- integrity sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=
- dependencies:
- get-stdin "^4.0.1"
-
strip-json-comments@~2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo=
-sumchecker@^1.2.0:
- version "1.3.1"
- resolved "https://registry.yarnpkg.com/sumchecker/-/sumchecker-1.3.1.tgz#79bb3b4456dd04f18ebdbc0d703a1d1daec5105d"
- integrity sha1-ebs7RFbdBPGOvbwNcDodHa7FEF0=
+tar-fs@^1.13.0:
+ version "1.16.3"
+ resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-1.16.3.tgz#966a628841da2c4010406a82167cbd5e0c72d509"
+ integrity sha512-NvCeXpYx7OsmOh8zIOP/ebG55zZmxLE0etfWRbWok+q2Qo8x/vOR/IJT1taADXPe+jsiu9axDb3X4B+iIgNlKw==
dependencies:
- debug "^2.2.0"
- es6-promise "^4.0.5"
+ chownr "^1.0.1"
+ mkdirp "^0.5.1"
+ pump "^1.0.0"
+ tar-stream "^1.1.2"
-supports-color@^3.1.0:
- version "3.2.3"
- resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6"
- integrity sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=
+tar-stream@^1.1.2:
+ version "1.6.2"
+ resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.6.2.tgz#8ea55dab37972253d9a9af90fdcd559ae435c555"
+ integrity sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==
dependencies:
- has-flag "^1.0.0"
+ bl "^1.0.0"
+ buffer-alloc "^1.2.0"
+ end-of-stream "^1.0.0"
+ fs-constants "^1.0.0"
+ readable-stream "^2.3.0"
+ to-buffer "^1.1.1"
+ xtend "^4.0.0"
-symbol-observable@1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.0.1.tgz#8340fc4702c3122df5d22288f88283f513d3fdd4"
- integrity sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ=
-
-tapable@^0.2.7, tapable@~0.2.5:
- version "0.2.8"
- resolved "https://registry.yarnpkg.com/tapable/-/tapable-0.2.8.tgz#99372a5c999bf2df160afc0d74bed4f47948cd22"
- integrity sha1-mTcqXJmb8t8WCvwNdL7U9HlIzSI=
-
-tar-pack@^3.4.0:
- version "3.4.1"
- resolved "https://registry.yarnpkg.com/tar-pack/-/tar-pack-3.4.1.tgz#e1dbc03a9b9d3ba07e896ad027317eb679a10a1f"
- integrity sha512-PPRybI9+jM5tjtCbN2cxmmRU7YmqT3Zv/UDy48tAh2XRkLa9bAORtSWLkVc13+GJF+cdTh1yEnHEk3cpTaL5Kg==
- dependencies:
- debug "^2.2.0"
- fstream "^1.0.10"
- fstream-ignore "^1.0.5"
- once "^1.3.3"
- readable-stream "^2.1.4"
- rimraf "^2.5.1"
- tar "^2.2.1"
- uid-number "^0.0.6"
-
-tar@^2.2.1:
- version "2.2.1"
- resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1"
- integrity sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=
- dependencies:
- block-stream "*"
- fstream "^1.0.2"
- inherits "2"
-
-throttleit@0.0.2:
- version "0.0.2"
- resolved "https://registry.yarnpkg.com/throttleit/-/throttleit-0.0.2.tgz#cfedf88e60c00dd9697b61fdd2a8343a9b680eaf"
- integrity sha1-z+34jmDADdlpe2H90qg0OptoDq8=
-
-through2@~0.2.3:
- version "0.2.3"
- resolved "https://registry.yarnpkg.com/through2/-/through2-0.2.3.tgz#eb3284da4ea311b6cc8ace3653748a52abf25a3f"
- integrity sha1-6zKE2k6jEbbMis42U3SKUqvyWj8=
- dependencies:
- readable-stream "~1.1.9"
- xtend "~2.1.1"
-
-timers-browserify@^2.0.4:
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.4.tgz#96ca53f4b794a5e7c0e1bd7cc88a372298fa01e6"
- integrity sha512-uZYhyU3EX8O7HQP+J9fTVYwsq90Vr68xPEFo7yrVImIxYvHgukBEgOB/SgGoorWVTzGM/3Z+wUNnboA4M8jWrg==
- dependencies:
- setimmediate "^1.0.4"
-
-to-arraybuffer@^1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43"
- integrity sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=
-
-tough-cookie@~2.3.0, tough-cookie@~2.3.3:
- version "2.3.3"
- resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.3.tgz#0b618a5565b6dea90bf3425d04d55edc475a7561"
- integrity sha1-C2GKVWW23qkL80JdBNVe3EdadWE=
- dependencies:
- punycode "^1.4.1"
-
-trim-newlines@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613"
- integrity sha1-WIeWa7WCpFA6QetST301ARgVphM=
-
-tty-browserify@0.0.0:
- version "0.0.0"
- resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6"
- integrity sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=
+to-buffer@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/to-buffer/-/to-buffer-1.1.1.tgz#493bd48f62d7c43fcded313a03dcadb2e1213a80"
+ integrity sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==
tunnel-agent@^0.6.0:
version "0.6.0"
@@ -2370,138 +488,20 @@ tunnel-agent@^0.6.0:
dependencies:
safe-buffer "^5.0.1"
-tweetnacl@^0.14.3, tweetnacl@~0.14.0:
+tweetnacl@^0.14.3:
version "0.14.5"
resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=
-typedarray@^0.0.6:
- version "0.0.6"
- resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
- integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
-
-typescript@^2.2.2:
- version "2.6.2"
- resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.6.2.tgz#3c5b6fd7f6de0914269027f03c0946758f7673a4"
- integrity sha1-PFtv1/beCRQmkCfwPAlGdY92c6Q=
-
-uglify-js@^2.8.27:
- version "2.8.29"
- resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.29.tgz#29c5733148057bb4e1f75df35b7a9cb72e6a59dd"
- integrity sha1-KcVzMUgFe7Th913zW3qcty5qWd0=
- dependencies:
- source-map "~0.5.1"
- yargs "~3.10.0"
- optionalDependencies:
- uglify-to-browserify "~1.0.0"
-
-uglify-to-browserify@~1.0.0:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7"
- integrity sha1-bgkk1r2mta/jSeOabWMoUKD4grc=
-
-uid-number@^0.0.6:
- version "0.0.6"
- resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81"
- integrity sha1-DqEOgDXo61uOREnwbaHHMGY7qoE=
-
-url@^0.11.0:
- version "0.11.0"
- resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1"
- integrity sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=
- dependencies:
- punycode "1.3.2"
- querystring "0.2.0"
-
util-deprecate@~1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
-util@0.10.3, util@^0.10.3:
- version "0.10.3"
- resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9"
- integrity sha1-evsa/lCAUkZInj23/g7TeTNqwPk=
- dependencies:
- inherits "2.0.1"
-
-uuid@^3.0.0, uuid@^3.1.0:
- version "3.2.1"
- resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.2.1.tgz#12c528bb9d58d0b9265d9a2f6f0fe8be17ff1f14"
- integrity sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==
-
-validate-npm-package-license@^3.0.1:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz#2804babe712ad3379459acfbe24746ab2c303fbc"
- integrity sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=
- dependencies:
- spdx-correct "~1.0.0"
- spdx-expression-parse "~1.0.0"
-
-verror@1.10.0:
- version "1.10.0"
- resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400"
- integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=
- dependencies:
- assert-plus "^1.0.0"
- core-util-is "1.0.2"
- extsprintf "^1.2.0"
-
-vm-browserify@0.0.4:
- version "0.0.4"
- resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-0.0.4.tgz#5d7ea45bbef9e4a6ff65f95438e0a87c357d5a73"
- integrity sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=
- dependencies:
- indexof "0.0.1"
-
-watchpack@^1.3.1:
- version "1.4.0"
- resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.4.0.tgz#4a1472bcbb952bd0a9bb4036801f954dfb39faac"
- integrity sha1-ShRyvLuVK9Cpu0A2gB+VTfs5+qw=
- dependencies:
- async "^2.1.2"
- chokidar "^1.7.0"
- graceful-fs "^4.1.2"
-
-webpack-sources@^1.0.1:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.1.0.tgz#a101ebae59d6507354d71d8013950a3a8b7a5a54"
- integrity sha512-aqYp18kPphgoO5c/+NaUvEeACtZjMESmDChuD3NBciVpah3XpMEU9VAAtIaB1BsfJWWTSdv8Vv1m3T0aRk2dUw==
- dependencies:
- source-list-map "^2.0.0"
- source-map "~0.6.1"
-
-webpack@^2.3.3:
- version "2.7.0"
- resolved "https://registry.yarnpkg.com/webpack/-/webpack-2.7.0.tgz#b2a1226804373ffd3d03ea9c6bd525067034f6b1"
- integrity sha512-MjAA0ZqO1ba7ZQJRnoCdbM56mmFpipOPUv/vQpwwfSI42p5PVDdoiuK2AL2FwFUVgT859Jr43bFZXRg/LNsqvg==
- dependencies:
- acorn "^5.0.0"
- acorn-dynamic-import "^2.0.0"
- ajv "^4.7.0"
- ajv-keywords "^1.1.1"
- async "^2.1.2"
- enhanced-resolve "^3.3.0"
- interpret "^1.0.0"
- json-loader "^0.5.4"
- json5 "^0.5.1"
- loader-runner "^2.3.0"
- loader-utils "^0.2.16"
- memory-fs "~0.4.1"
- mkdirp "~0.5.0"
- node-libs-browser "^2.0.0"
- source-map "^0.5.3"
- supports-color "^3.1.0"
- tapable "~0.2.5"
- uglify-js "^2.8.27"
- watchpack "^1.3.1"
- webpack-sources "^1.0.1"
- yargs "^6.0.0"
-
-which-module@^1.0.0:
+which-pm-runs@^1.0.0:
version "1.0.0"
- resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f"
- integrity sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=
+ resolved "https://registry.yarnpkg.com/which-pm-runs/-/which-pm-runs-1.0.0.tgz#670b3afbc552e0b55df6b7780ca74615f23ad1cb"
+ integrity sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs=
wide-align@^1.1.0:
version "1.1.2"
@@ -2510,95 +510,19 @@ wide-align@^1.1.0:
dependencies:
string-width "^1.0.2"
-wincredmgr@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/wincredmgr/-/wincredmgr-2.0.0.tgz#cab8e3c6d98f0ea255d7638e82fd9f393ca7f515"
- integrity sha1-yrjjxtmPDqJV12OOgv2fOTyn9RU=
-
-window-size@0.1.0:
- version "0.1.0"
- resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d"
- integrity sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=
-
-wordwrap@0.0.2:
- version "0.0.2"
- resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f"
- integrity sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=
-
-wrap-ansi@^2.0.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85"
- integrity sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=
+windows-process-tree@^0.2.3:
+ version "0.2.3"
+ resolved "https://registry.yarnpkg.com/windows-process-tree/-/windows-process-tree-0.2.3.tgz#6b781f0a320e8a0d6434c9399add4389c709cf6e"
+ integrity sha512-SzPJSubVVsToz1g5lr2P+4mQT70gvJ9u/nlnpfkOeQcAhOuhKz5DiO1TARgR0OnVsv21LPzxbA2m/4JQkGh1wA==
dependencies:
- string-width "^1.0.1"
- strip-ansi "^3.0.1"
+ nan "^2.10.0"
wrappy@1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
-xkeychain@^0.0.6:
- version "0.0.6"
- resolved "https://registry.yarnpkg.com/xkeychain/-/xkeychain-0.0.6.tgz#1c58b3dd2f80481f8f67949c3511aa14027c2b9b"
- integrity sha1-HFiz3S+ASB+PZ5ScNRGqFAJ8K5s=
-
xtend@^4.0.0:
version "4.0.1"
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af"
integrity sha1-pcbVMr5lbiPbgg77lDofBJmNY68=
-
-xtend@~2.1.1:
- version "2.1.2"
- resolved "https://registry.yarnpkg.com/xtend/-/xtend-2.1.2.tgz#6efecc2a4dad8e6962c4901b337ce7ba87b5d28b"
- integrity sha1-bv7MKk2tjmlixJAbM3znuoe10os=
- dependencies:
- object-keys "~0.4.0"
-
-y18n@^3.2.1:
- version "3.2.1"
- resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41"
- integrity sha1-bRX7qITAhnnA136I53WegR4H+kE=
-
-yargs-parser@^4.2.0:
- version "4.2.1"
- resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-4.2.1.tgz#29cceac0dc4f03c6c87b4a9f217dd18c9f74871c"
- integrity sha1-KczqwNxPA8bIe0qfIX3RjJ90hxw=
- dependencies:
- camelcase "^3.0.0"
-
-yargs@^6.0.0:
- version "6.6.0"
- resolved "https://registry.yarnpkg.com/yargs/-/yargs-6.6.0.tgz#782ec21ef403345f830a808ca3d513af56065208"
- integrity sha1-eC7CHvQDNF+DCoCMo9UTr1YGUgg=
- dependencies:
- camelcase "^3.0.0"
- cliui "^3.2.0"
- decamelize "^1.1.1"
- get-caller-file "^1.0.1"
- os-locale "^1.4.0"
- read-pkg-up "^1.0.1"
- require-directory "^2.1.1"
- require-main-filename "^1.0.1"
- set-blocking "^2.0.0"
- string-width "^1.0.2"
- which-module "^1.0.0"
- y18n "^3.2.1"
- yargs-parser "^4.2.0"
-
-yargs@~3.10.0:
- version "3.10.0"
- resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.10.0.tgz#f7ee7bd857dd7c1d2d38c0e74efbd681d1431fd1"
- integrity sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=
- dependencies:
- camelcase "^1.0.2"
- cliui "^2.1.0"
- decamelize "^1.0.0"
- window-size "0.1.0"
-
-yauzl@2.4.1:
- version "2.4.1"
- resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.4.1.tgz#9528f442dab1b2284e58b4379bb194e22e0c4005"
- integrity sha1-lSj0QtqxsihOWLQ3m7GU4i4MQAU=
- dependencies:
- fd-slicer "~1.0.1"
diff --git a/terminus-terminal/README.md b/terminus-terminal/README.md
new file mode 100644
index 00000000..2b7a10a3
--- /dev/null
+++ b/terminus-terminal/README.md
@@ -0,0 +1,26 @@
+Terminus Terminal Plugin
+------------------------
+
+* terminal tabs
+* terminal frontends
+* session management
+* shell detection
+
+Using the API:
+
+```ts
+import { TerminalContextMenuItemProvider } from 'terminus-terminal'
+```
+
+Exporting your subclasses:
+
+```ts
+@NgModule({
+ ...
+ providers: [
+ ...
+ { provide: TerminalContextMenuItemProvider, useClass: MyContextMenu, multi: true },
+ ...
+ ]
+})
+```
diff --git a/terminus-terminal/package.json b/terminus-terminal/package.json
index f29e70fc..433b59ee 100644
--- a/terminus-terminal/package.json
+++ b/terminus-terminal/package.json
@@ -1,12 +1,12 @@
{
"name": "terminus-terminal",
- "version": "1.0.0-alpha.55",
+ "version": "1.0.73-c4-ga7d62b0",
"description": "Terminus' terminal emulation core",
"keywords": [
"terminus-builtin-plugin"
],
"main": "dist/index.js",
- "typings": "dist/src/index.d.ts",
+ "typings": "typings/index.d.ts",
"scripts": {
"build": "webpack --progress --color --display-modules",
"watch": "webpack --progress --color --watch"
@@ -17,17 +17,25 @@
"author": "Eugene Pankov",
"license": "MIT",
"devDependencies": {
- "@terminus-term/xterm": "3.8.4",
"@types/deep-equal": "^1.0.0",
- "@types/mz": "0.0.31",
- "@types/node": "7.0.12",
- "@types/webpack-env": "1.13.0",
+ "@types/mz": "0.0.32",
+ "@types/node": "12.0.10",
+ "@types/slug": "^0.9.1",
+ "@types/webpack-env": "1.13.9",
"dataurl": "0.1.0",
"deep-equal": "1.0.1",
"file-loader": "^0.11.2",
- "rage-edit-tmp": "^1.1.0",
+ "hterm-umdjs": "1.4.1",
+ "mz": "^2.6.0",
+ "ps-node": "^0.1.6",
+ "runes": "^0.4.2",
+ "slug": "^1.1.0",
"uuid": "^3.3.2",
- "xterm-addon-ligatures-tmp": "^0.1.0-beta-1"
+ "xterm": "3.15.0-beta58",
+ "xterm-addon-fit": "^0.1.0-beta3",
+ "xterm-addon-ligatures": "^0.1.0-beta-2",
+ "xterm-addon-search": "^0.1.0-beta6",
+ "xterm-addon-webgl": "^0.1.0-beta2"
},
"peerDependencies": {
"@angular/common": "4.0.1",
@@ -40,18 +48,12 @@
"terminus-settings": "*"
},
"dependencies": {
- "@types/async-lock": "0.0.19",
- "async-lock": "^1.0.0",
- "font-manager": "0.3.0",
- "hterm-umdjs": "1.4.1",
- "mz": "^2.6.0",
- "node-pty-tmp": "0.7.2",
- "ps-node": "^0.1.6",
- "runes": "^0.4.2"
+ "fontmanager-redux": "0.3.2",
+ "node-pty": "^0.9.0-beta9"
},
"optionalDependencies": {
- "macos-native-processlist": "^1.0.0",
- "windows-process-tree": "^0.2.3"
- },
- "false": {}
+ "@terminus-term/windows-process-tree": "^0.2.4",
+ "macos-native-processlist": "^1.0.1",
+ "windows-native-registry": "^1.0.14"
+ }
}
diff --git a/terminus-terminal/src/api.ts b/terminus-terminal/src/api.ts
deleted file mode 100644
index d45a4751..00000000
--- a/terminus-terminal/src/api.ts
+++ /dev/null
@@ -1,62 +0,0 @@
-import { Observable } from 'rxjs'
-import { TerminalTabComponent } from './components/terminalTab.component'
-
-export abstract class TerminalDecorator {
- // tslint:disable-next-line no-empty
- attach (_terminal: TerminalTabComponent): void { }
- // tslint:disable-next-line no-empty
- detach (_terminal: TerminalTabComponent): void { }
-}
-
-export interface ResizeEvent {
- columns: number
- rows: number
-}
-
-export interface SessionOptions {
- name?: string
- command?: string
- args?: string[]
- cwd?: string
- env?: any
- width?: number
- height?: number
- recoveryId?: string
- recoveredTruePID$?: Observable
- pauseAfterExit?: boolean
-}
-
-export abstract class SessionPersistenceProvider {
- abstract id: string
- abstract displayName: string
-
- abstract isAvailable (): boolean
- abstract async attachSession (recoveryId: any): Promise
- abstract async startSession (options: SessionOptions): Promise
- abstract async terminateSession (recoveryId: string): Promise
-}
-
-export interface ITerminalColorScheme {
- name: string
- foreground: string
- background: string
- cursor: string
- colors: string[]
-}
-
-export abstract class TerminalColorSchemeProvider {
- abstract async getSchemes (): Promise
-}
-
-export interface IShell {
- id: string
- name?: string
- command: string
- args?: string[]
- env?: any
- fsBase?: string
-}
-
-export abstract class ShellProvider {
- abstract async provide (): Promise
-}
diff --git a/terminus-terminal/src/api/baseTerminalTab.component.ts b/terminus-terminal/src/api/baseTerminalTab.component.ts
new file mode 100644
index 00000000..73cced17
--- /dev/null
+++ b/terminus-terminal/src/api/baseTerminalTab.component.ts
@@ -0,0 +1,418 @@
+import { Observable, Subject, Subscription } from 'rxjs'
+import { first } from 'rxjs/operators'
+import { ToastrService } from 'ngx-toastr'
+import { NgZone, OnInit, OnDestroy, Inject, Injector, Optional, ViewChild, HostBinding, Input, ElementRef } from '@angular/core'
+import { trigger, transition, style, animate, AnimationTriggerMetadata } from '@angular/animations'
+import { AppService, ConfigService, BaseTabComponent, ElectronService, HostAppService, HotkeysService, Platform, LogService, Logger } from 'terminus-core'
+
+import { BaseSession, SessionsService } from '../services/sessions.service'
+import { TerminalFrontendService } from '../services/terminalFrontend.service'
+
+import { Frontend } from '../frontends/frontend'
+import { ResizeEvent } from './interfaces'
+import { TerminalDecorator } from './decorator'
+import { TerminalContextMenuItemProvider } from './contextMenuProvider'
+
+/**
+ * A class to base your custom terminal tabs on
+ */
+export class BaseTerminalTabComponent extends BaseTabComponent implements OnInit, OnDestroy {
+ static template = require('../components/baseTerminalTab.component.pug')
+ static styles = [require('../components/terminalTab.component.scss')]
+ static animations: AnimationTriggerMetadata[] = [trigger('slideInOut', [
+ transition(':enter', [
+ style({ transform: 'translateY(-25%)' }),
+ animate('100ms ease-in-out', style({ transform: 'translateY(0%)' })),
+ ]),
+ transition(':leave', [
+ animate('100ms ease-in-out', style({ transform: 'translateY(-25%)' })),
+ ]),
+ ])]
+
+ session: BaseSession
+ @Input() zoom = 0
+
+ @Input() showSearchPanel = false
+
+ /** @hidden */
+ @ViewChild('content') content
+
+ /** @hidden */
+ @HostBinding('style.background-color') backgroundColor: string
+
+ /** @hidden */
+ @HostBinding('class.top-padded') topPadded: boolean
+
+ frontend: Frontend
+
+ /** @hidden */
+ frontendIsReady = false
+
+ frontendReady = new Subject()
+ size: ResizeEvent
+
+ protected logger: Logger
+ protected output = new Subject()
+ private sessionCloseSubscription: Subscription
+ private hotkeysSubscription: Subscription
+ private bellPlayer: HTMLAudioElement
+ private termContainerSubscriptions: Subscription[] = []
+
+ get input$ (): Observable { return this.frontend.input$ }
+ get output$ (): Observable { return this.output }
+ get resize$ (): Observable { return this.frontend.resize$ }
+ get alternateScreenActive$ (): Observable { return this.frontend.alternateScreenActive$ }
+ get frontendReady$ (): Observable { return this.frontendReady }
+
+ constructor (
+ public config: ConfigService,
+ public element: ElementRef,
+ protected injector: Injector,
+ protected zone: NgZone,
+ protected app: AppService,
+ protected hostApp: HostAppService,
+ protected hotkeys: HotkeysService,
+ protected sessions: SessionsService,
+ protected electron: ElectronService,
+ protected terminalContainersService: TerminalFrontendService,
+ protected toastr: ToastrService,
+ protected log: LogService,
+ @Optional() @Inject(TerminalDecorator) protected decorators: TerminalDecorator[],
+ @Optional() @Inject(TerminalContextMenuItemProvider) protected contextMenuProviders: TerminalContextMenuItemProvider[],
+ ) {
+ super()
+ this.logger = log.create('baseTerminalTab')
+ this.decorators = this.decorators || []
+ this.setTitle('Terminal')
+
+ this.hotkeysSubscription = this.hotkeys.matchedHotkey.subscribe(hotkey => {
+ if (!this.hasFocus) {
+ return
+ }
+ switch (hotkey) {
+ case 'ctrl-c':
+ if (this.frontend.getSelection()) {
+ this.frontend.copySelection()
+ this.frontend.clearSelection()
+ this.toastr.info('Copied')
+ } else {
+ this.sendInput('\x03')
+ }
+ break
+ case 'copy':
+ this.frontend.copySelection()
+ this.frontend.clearSelection()
+ this.toastr.info('Copied')
+ break
+ case 'paste':
+ this.paste()
+ break
+ case 'clear':
+ this.frontend.clear()
+ break
+ case 'zoom-in':
+ this.zoomIn()
+ break
+ case 'zoom-out':
+ this.zoomOut()
+ break
+ case 'reset-zoom':
+ this.resetZoom()
+ break
+ case 'previous-word':
+ this.sendInput('\x1bb')
+ break
+ case 'next-word':
+ this.sendInput('\x1bf')
+ break
+ case 'delete-previous-word':
+ this.sendInput('\x1b\x7f')
+ break
+ case 'delete-next-word':
+ this.sendInput('\x1bd')
+ break
+ case 'search':
+ this.showSearchPanel = true
+ setImmediate(() => {
+ this.element.nativeElement.querySelector('.search-input').focus()
+ })
+ break
+ }
+ })
+ this.bellPlayer = document.createElement('audio')
+ this.bellPlayer.src = require('../bell.ogg')
+
+ this.contextMenuProviders.sort((a, b) => a.weight - b.weight)
+ }
+
+ /** @hidden */
+ ngOnInit () {
+ this.focused$.subscribe(() => {
+ this.configure()
+ this.frontend.focus()
+ })
+
+ this.frontend = this.terminalContainersService.getFrontend(this.session)
+
+ this.frontend.ready$.subscribe(() => {
+ this.frontendIsReady = true
+ })
+
+ this.frontend.resize$.pipe(first()).subscribe(async ({ columns, rows }) => {
+ this.size = { columns, rows }
+ this.frontendReady.next()
+
+ setTimeout(() => {
+ this.session.resize(columns, rows)
+ }, 1000)
+
+ this.session.releaseInitialDataBuffer()
+ })
+
+ this.frontend.configure()
+
+ 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()
+
+ this.config.enabledServices(this.decorators).forEach((decorator) => {
+ try {
+ decorator.attach(this)
+ } catch (e) {
+ this.logger.warn('Decorator attach() throws', e)
+ }
+ })
+
+ setTimeout(() => {
+ this.output.subscribe(() => {
+ this.displayActivity()
+ })
+ }, 1000)
+
+ this.frontend.bell$.subscribe(() => {
+ if (this.config.store.terminal.bell === 'visual') {
+ this.frontend.visualBell()
+ }
+ if (this.config.store.terminal.bell === 'audible') {
+ this.bellPlayer.play()
+ }
+ })
+
+ this.frontend.focus()
+ }
+
+ async buildContextMenu (): Promise {
+ let items: Electron.MenuItemConstructorOptions[] = []
+ for (const section of await Promise.all(this.contextMenuProviders.map(x => x.getItems(this)))) {
+ items = items.concat(section)
+ items.push({ type: 'separator' })
+ }
+ items.splice(items.length - 1, 1)
+ return items
+ }
+
+ /**
+ * Feeds input into the active session
+ */
+ sendInput (data: string) {
+ this.session.write(data)
+ if (this.config.store.terminal.scrollOnInput) {
+ this.frontend.scrollToBottom()
+ }
+ }
+
+ /**
+ * Feeds input into the terminal frontend
+ */
+ write (data: string) {
+ const percentageMatch = /(^|[^\d])(\d+(\.\d+)?)%([^\d]|$)/.exec(data)
+ if (percentageMatch) {
+ const percentage = percentageMatch[3] ? parseFloat(percentageMatch[2]) : parseInt(percentageMatch[2])
+ if (percentage > 0 && percentage <= 100) {
+ this.setProgress(percentage)
+ this.logger.debug('Detected progress:', percentage)
+ }
+ } else {
+ this.setProgress(null)
+ }
+ this.frontend.write(data)
+ }
+
+ paste () {
+ let data = this.electron.clipboard.readText() as string
+ if (this.config.store.terminal.bracketedPaste) {
+ data = '\x1b[200~' + data + '\x1b[201~'
+ }
+ if (this.hostApp.platform === Platform.Windows) {
+ data = data.replace(/\r\n/g, '\r')
+ } else {
+ data = data.replace(/\n/g, '\r')
+ }
+ this.sendInput(data)
+ }
+
+ /**
+ * Applies the user settings to the terminal
+ */
+ 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
+ }
+ } else {
+ this.backgroundColor = null
+ }
+ }
+
+ zoomIn () {
+ this.zoom++
+ this.frontend.setZoom(this.zoom)
+ }
+
+ zoomOut () {
+ this.zoom--
+ this.frontend.setZoom(this.zoom)
+ }
+
+ resetZoom () {
+ this.zoom = 0
+ this.frontend.setZoom(this.zoom)
+ }
+
+ /** @hidden */
+ ngOnDestroy () {
+ this.frontend.detach(this.content.nativeElement)
+ this.detachTermContainerHandlers()
+ this.config.enabledServices(this.decorators).forEach(decorator => {
+ try {
+ decorator.detach(this)
+ } catch (e) {
+ this.logger.warn('Decorator attach() throws', e)
+ }
+ })
+ this.hotkeysSubscription.unsubscribe()
+ if (this.sessionCloseSubscription) {
+ this.sessionCloseSubscription.unsubscribe()
+ }
+ this.output.complete()
+ }
+
+ async destroy () {
+ super.destroy()
+ if (this.session && this.session.open) {
+ await this.session.destroy()
+ }
+ }
+
+ protected detachTermContainerHandlers () {
+ for (const subscription of this.termContainerSubscriptions) {
+ subscription.unsubscribe()
+ }
+ this.termContainerSubscriptions = []
+ }
+
+ protected attachTermContainerHandlers () {
+ this.detachTermContainerHandlers()
+
+ const maybeConfigure = () => {
+ if (this.hasFocus) {
+ setTimeout(() => this.configure(), 250)
+ }
+ }
+
+ this.termContainerSubscriptions = [
+ this.frontend.title$.subscribe(title => this.zone.run(() => this.setTitle(title))),
+
+ this.focused$.subscribe(() => this.frontend.enableResizing = true),
+ this.blurred$.subscribe(() => this.frontend.enableResizing = false),
+
+ this.frontend.mouseEvent$.subscribe(async event => {
+ if (event.type === 'mousedown') {
+ if (event.which === 2) {
+ this.paste()
+ event.preventDefault()
+ event.stopPropagation()
+ return
+ }
+ if (event.which === 3) {
+ if (this.config.store.terminal.rightClick === 'menu') {
+ this.hostApp.popupContextMenu(await this.buildContextMenu())
+ } else if (this.config.store.terminal.rightClick === 'paste') {
+ this.paste()
+ }
+ event.preventDefault()
+ event.stopPropagation()
+ return
+ }
+ }
+ if (event.type === 'mousewheel') {
+ let wheelDeltaY = 0
+
+ if ('wheelDeltaY' in event) {
+ wheelDeltaY = (event as MouseWheelEvent)['wheelDeltaY']
+ } else {
+ wheelDeltaY = (event as MouseWheelEvent)['deltaY']
+ }
+ if (event.ctrlKey || event.metaKey) {
+
+ if (wheelDeltaY > 0) {
+ this.zoomIn()
+ } else {
+ this.zoomOut()
+ }
+ } else if (event.altKey) {
+ event.preventDefault()
+ const delta = Math.round(wheelDeltaY / 50)
+ this.sendInput((delta > 0 ? '\u001bOA' : '\u001bOB').repeat(Math.abs(delta)))
+ }
+ }
+ }),
+
+ this.frontend.input$.subscribe(data => {
+ this.sendInput(data)
+ }),
+
+ this.frontend.resize$.subscribe(({ columns, rows }) => {
+ this.logger.debug(`Resizing to ${columns}x${rows}`)
+ this.size = { columns, rows }
+ this.zone.run(() => {
+ if (this.session && this.session.open) {
+ this.session.resize(columns, rows)
+ }
+ })
+ }),
+
+ this.hostApp.displayMetricsChanged$.subscribe(maybeConfigure),
+ this.hostApp.windowMoved$.subscribe(maybeConfigure),
+ ]
+ }
+
+ protected attachSessionHandlers () {
+ // this.session.output$.bufferTime(10).subscribe((datas) => {
+ this.session.output$.subscribe(data => {
+ this.zone.run(() => {
+ this.output.next(data)
+ this.write(data)
+ })
+ })
+
+ this.sessionCloseSubscription = this.session.closed$.subscribe(() => {
+ this.frontend.destroy()
+ this.destroy()
+ })
+ }
+}
diff --git a/terminus-terminal/src/api/colorSchemeProvider.ts b/terminus-terminal/src/api/colorSchemeProvider.ts
new file mode 100644
index 00000000..4e47d103
--- /dev/null
+++ b/terminus-terminal/src/api/colorSchemeProvider.ts
@@ -0,0 +1,8 @@
+import { TerminalColorScheme } from './interfaces'
+
+/**
+ * Extend to add more terminal color schemes
+ */
+export abstract class TerminalColorSchemeProvider {
+ abstract async getSchemes (): Promise
+}
diff --git a/terminus-terminal/src/api/contextMenuProvider.ts b/terminus-terminal/src/api/contextMenuProvider.ts
new file mode 100644
index 00000000..f76e7d6a
--- /dev/null
+++ b/terminus-terminal/src/api/contextMenuProvider.ts
@@ -0,0 +1,10 @@
+import { BaseTerminalTabComponent } from './baseTerminalTab.component'
+
+/**
+ * Extend to add more terminal context menu items
+ */
+export abstract class TerminalContextMenuItemProvider {
+ weight: number
+
+ abstract async getItems (tab: BaseTerminalTabComponent): Promise
+}
diff --git a/terminus-terminal/src/api/decorator.ts b/terminus-terminal/src/api/decorator.ts
new file mode 100644
index 00000000..b0ec0a17
--- /dev/null
+++ b/terminus-terminal/src/api/decorator.ts
@@ -0,0 +1,16 @@
+import { BaseTerminalTabComponent } from './baseTerminalTab.component'
+
+/**
+ * Extend to automatically run actions on new terminals
+ */
+export abstract class TerminalDecorator {
+ /**
+ * Called when a new terminal tab starts
+ */
+ attach (terminal: BaseTerminalTabComponent): void { } // eslint-disable-line
+
+ /**
+ * Called before a terminal tab is destroyed
+ */
+ detach (terminal: BaseTerminalTabComponent): void { } // eslint-disable-line
+}
diff --git a/terminus-terminal/src/api/interfaces.ts b/terminus-terminal/src/api/interfaces.ts
new file mode 100644
index 00000000..7477bc1c
--- /dev/null
+++ b/terminus-terminal/src/api/interfaces.ts
@@ -0,0 +1,54 @@
+import { SafeHtml } from '@angular/platform-browser'
+
+export interface ResizeEvent {
+ columns: number
+ rows: number
+}
+
+export interface SessionOptions {
+ name?: string
+ command: string
+ args: string[]
+ cwd?: string
+ env?: {[id: string]: string}
+ width?: number
+ height?: number
+ pauseAfterExit?: boolean
+ runAsAdministrator?: boolean
+}
+
+export interface Profile {
+ name: string,
+ sessionOptions: SessionOptions,
+ isBuiltin?: boolean
+ icon?: SafeHtml
+}
+
+export interface TerminalColorScheme {
+ name: string
+ foreground: string
+ background: string
+ cursor: string
+ colors: string[]
+}
+
+export interface Shell {
+ id: string
+ name?: string
+ command: string
+ args?: string[]
+ env: {[id: string]: string}
+
+ /**
+ * Base path to which shell's internal FS is relative
+ * Currently used for WSL only
+ */
+ fsBase?: string
+
+ /**
+ * SVG icon
+ */
+ icon?: SafeHtml
+
+ hidden?: boolean
+}
diff --git a/terminus-terminal/src/api/shellProvider.ts b/terminus-terminal/src/api/shellProvider.ts
new file mode 100644
index 00000000..2025ae54
--- /dev/null
+++ b/terminus-terminal/src/api/shellProvider.ts
@@ -0,0 +1,8 @@
+import { Shell } from './interfaces'
+
+/**
+ * Extend to add support for more shells
+ */
+export abstract class ShellProvider {
+ abstract async provide (): Promise
+}
diff --git a/terminus-terminal/src/bufferizedPTY.js b/terminus-terminal/src/bufferizedPTY.js
index 837086fb..b2e1ee7d 100644
--- a/terminus-terminal/src/bufferizedPTY.js
+++ b/terminus-terminal/src/bufferizedPTY.js
@@ -1,7 +1,8 @@
+/** @hidden */
module.exports = function patchPTYModule (mod) {
const oldSpawn = mod.spawn
if (mod.patched) {
- return mod
+ return
}
mod.patched = true
mod.spawn = (file, args, opt) => {
@@ -50,5 +51,4 @@ module.exports = function patchPTYModule (mod) {
})
return terminal
}
- return mod
}
diff --git a/terminus-terminal/src/buttonProvider.ts b/terminus-terminal/src/buttonProvider.ts
index b37b39bb..fd1ba078 100644
--- a/terminus-terminal/src/buttonProvider.ts
+++ b/terminus-terminal/src/buttonProvider.ts
@@ -1,24 +1,23 @@
import * as fs from 'mz/fs'
import { Injectable } from '@angular/core'
import { DomSanitizer } from '@angular/platform-browser'
-import { HotkeysService, ToolbarButtonProvider, IToolbarButton, HostAppService, ElectronService } from 'terminus-core'
+import { ToolbarButtonProvider, ToolbarButton, ElectronService } from 'terminus-core'
import { TerminalService } from './services/terminal.service'
+/** @hidden */
@Injectable()
export class ButtonProvider extends ToolbarButtonProvider {
constructor (
+ electron: ElectronService,
private terminal: TerminalService,
private domSanitizer: DomSanitizer,
- hostApp: HostAppService,
- electron: ElectronService,
- 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])) {
+ const argv: string[] = electron.remote.process.argv
+ for (const arg of argv.slice(1).concat([electron.remote.process.argv0])) {
if (await fs.exists(arg)) {
if ((await fs.stat(arg)).isDirectory()) {
this.terminal.openTab(null, arg)
@@ -29,14 +28,28 @@ export class ButtonProvider extends ToolbarButtonProvider {
}
}
- provide (): IToolbarButton[] {
- return [{
- icon: this.domSanitizer.bypassSecurityTrustHtml(require('./icons/plus.svg')),
- title: 'New terminal',
- touchBarNSImage: 'NSTouchBarAddDetailTemplate',
- click: async () => {
- this.terminal.openTab()
- }
- }]
+ provide (): ToolbarButton[] {
+ return [
+ {
+ icon: this.domSanitizer.bypassSecurityTrustHtml(require('./icons/plus.svg')),
+ title: 'New terminal',
+ touchBarNSImage: 'NSTouchBarAddDetailTemplate',
+ click: async () => {
+ this.terminal.openTab()
+ },
+ },
+ {
+ icon: this.domSanitizer.bypassSecurityTrustHtml(require('./icons/profiles.svg')),
+ title: 'New terminal with profile',
+ submenu: async () => {
+ const profiles = await this.terminal.getProfiles()
+ return profiles.map(profile => ({
+ icon: profile.icon,
+ title: profile.name,
+ click: () => this.terminal.openTab(profile),
+ }))
+ },
+ },
+ ]
}
}
diff --git a/terminus-terminal/src/colorSchemes.ts b/terminus-terminal/src/colorSchemes.ts
index 2392adbe..44d5b212 100644
--- a/terminus-terminal/src/colorSchemes.ts
+++ b/terminus-terminal/src/colorSchemes.ts
@@ -1,20 +1,24 @@
import * as fs from 'mz/fs'
import * as path from 'path'
import { Injectable } from '@angular/core'
-import { TerminalColorSchemeProvider, ITerminalColorScheme } from './api'
+import { TerminalColorSchemeProvider } from './api/colorSchemeProvider'
+import { TerminalColorScheme } from './api/interfaces'
+/** @hidden */
@Injectable()
export class HyperColorSchemes extends TerminalColorSchemeProvider {
- async getSchemes (): Promise {
- let pluginsPath = path.join(process.env.HOME, '.hyper_plugins', 'node_modules')
- if (!(await fs.exists(pluginsPath))) return []
- let plugins = await fs.readdir(pluginsPath)
+ async getSchemes (): Promise {
+ const pluginsPath = path.join(process.env.HOME, '.hyper_plugins', 'node_modules')
+ if (!await fs.exists(pluginsPath)) {
+ return []
+ }
+ const plugins = await fs.readdir(pluginsPath)
- let themes: ITerminalColorScheme[] = []
+ const themes: TerminalColorScheme[] = []
plugins.forEach(plugin => {
try {
- let module = (global as any).require(path.join(pluginsPath, plugin))
+ const module = (global as any).require(path.join(pluginsPath, plugin))
if (module.decorateConfig) {
let config: any
try {
diff --git a/terminus-terminal/src/components/appearanceSettingsTab.component.pug b/terminus-terminal/src/components/appearanceSettingsTab.component.pug
index 481d32d8..8c2cc27a 100644
--- a/terminus-terminal/src/components/appearanceSettingsTab.component.pug
+++ b/terminus-terminal/src/components/appearanceSettingsTab.component.pug
@@ -1,6 +1,6 @@
h3.mb-3 Appearance
-.row
- .col-md-6
+.d-flex
+ .mr-5
.form-line
.header
.title Frontend
@@ -12,6 +12,7 @@ h3.mb-3 Appearance
)
option(value='hterm') hterm
option(value='xterm') xterm
+ option(value='xterm-webgl') xterm (WebGL)
.form-line
.header
@@ -26,6 +27,7 @@ h3.mb-3 Appearance
)
input.form-control.w-25(
type='number',
+ max='48',
[(ngModel)]='config.store.terminal.fontSize',
(ngModelChange)='config.save()',
)
@@ -57,7 +59,7 @@ h3.mb-3 Appearance
(click)='deleteScheme(config.store.terminal.colorScheme)',
*ngIf='isCustomScheme(config.store.terminal.colorScheme)'
)
- i.fa.fa-trash-o
+ i.fas.fa-trash
.form-group(*ngIf='editingColorScheme')
label Editing
@@ -91,10 +93,10 @@ h3.mb-3 Appearance
[title]='idx',
)
- .col-md-6
+ div
.form-group
.appearance-preview(
- [style.font-family]='config.store.terminal.font',
+ [style.font-family]='getPreviewFontFamily()',
[style.font-size]='config.store.terminal.fontSize + "px"',
[style.background-color]='(config.store.terminal.background == "theme") ? null : config.store.terminal.colorScheme.background',
[style.color]='config.store.terminal.colorScheme.foreground',
diff --git a/terminus-terminal/src/components/appearanceSettingsTab.component.scss b/terminus-terminal/src/components/appearanceSettingsTab.component.scss
index da32df4f..1bef6855 100644
--- a/terminus-terminal/src/components/appearanceSettingsTab.component.scss
+++ b/terminus-terminal/src/components/appearanceSettingsTab.component.scss
@@ -3,6 +3,9 @@
margin-left: 20px;
padding: 10px;
overflow: hidden;
+ max-width: 400px;
+ max-height: 400px;
+
span {
white-space: pre;
}
diff --git a/terminus-terminal/src/components/appearanceSettingsTab.component.ts b/terminus-terminal/src/components/appearanceSettingsTab.component.ts
index e798a659..49108d4c 100644
--- a/terminus-terminal/src/components/appearanceSettingsTab.component.ts
+++ b/terminus-terminal/src/components/appearanceSettingsTab.component.ts
@@ -1,34 +1,38 @@
import { Observable } from 'rxjs'
import { debounceTime, distinctUntilChanged, map } from 'rxjs/operators'
import { exec } from 'mz/child_process'
-import deepEqual = require('deep-equal')
-const fontManager = require('font-manager')
+import deepEqual from 'deep-equal'
+const fontManager = require('fontmanager-redux') // eslint-disable-line
import { Component, Inject } from '@angular/core'
-import { ConfigService, HostAppService, Platform } from 'terminus-core'
-import { TerminalColorSchemeProvider, ITerminalColorScheme } from '../api'
+import { ConfigService, HostAppService, Platform, ElectronService } from 'terminus-core'
+import { TerminalColorSchemeProvider } from '../api/colorSchemeProvider'
+import { TerminalColorScheme } from '../api/interfaces'
+import { getCSSFontFamily } from '../utils'
+/** @hidden */
@Component({
template: require('./appearanceSettingsTab.component.pug'),
styles: [require('./appearanceSettingsTab.component.scss')],
})
export class AppearanceSettingsTabComponent {
fonts: string[] = []
- colorSchemes: ITerminalColorScheme[] = []
+ colorSchemes: TerminalColorScheme[] = []
equalComparator = deepEqual
- editingColorScheme: ITerminalColorScheme
+ editingColorScheme: TerminalColorScheme
schemeChanged = false
constructor (
@Inject(TerminalColorSchemeProvider) private colorSchemeProviders: TerminalColorSchemeProvider[],
private hostApp: HostAppService,
+ private electron: ElectronService,
public config: ConfigService,
) { }
async ngOnInit () {
if (this.hostApp.platform === Platform.Windows || this.hostApp.platform === Platform.macOS) {
- let fonts = await new Promise((resolve) => fontManager.findFonts({ monospace: true }, resolve))
- this.fonts = fonts.map(x => x.family)
+ const fonts = await new Promise((resolve) => fontManager.findFonts({ monospace: true }, resolve))
+ this.fonts = fonts.map(x => `${x.family} ${x.style}`.trim())
this.fonts.sort()
}
if (this.hostApp.platform === Platform.Linux) {
@@ -46,14 +50,14 @@ export class AppearanceSettingsTabComponent {
fontAutocomplete = (text$: Observable) => {
return text$.pipe(
- debounceTime(200),
- distinctUntilChanged(),
- map(query => this.fonts.filter(v => new RegExp(query, 'gi').test(v))),
- map(list => Array.from(new Set(list))),
- )
+ debounceTime(200),
+ distinctUntilChanged(),
+ map(query => this.fonts.filter(v => new RegExp(query, 'gi').test(v))),
+ map(list => Array.from(new Set(list))),
+ )
}
- editScheme (scheme: ITerminalColorScheme) {
+ editScheme (scheme: TerminalColorScheme) {
this.editingColorScheme = scheme
this.schemeChanged = false
}
@@ -71,8 +75,16 @@ export class AppearanceSettingsTabComponent {
this.editingColorScheme = null
}
- deleteScheme (scheme: ITerminalColorScheme) {
- if (confirm(`Delete "${scheme.name}"?`)) {
+ async deleteScheme (scheme: TerminalColorScheme) {
+ if ((await this.electron.showMessageBox(
+ this.hostApp.getWindow(),
+ {
+ type: 'warning',
+ message: `Delete "${scheme.name}"?`,
+ buttons: ['Keep', 'Delete'],
+ defaultId: 1,
+ }
+ )).response === 1) {
let schemes = this.config.store.terminal.customColorSchemes
schemes = schemes.filter(x => x !== scheme)
this.config.store.terminal.customColorSchemes = schemes
@@ -80,11 +92,15 @@ export class AppearanceSettingsTabComponent {
}
}
- isCustomScheme (scheme: ITerminalColorScheme) {
+ isCustomScheme (scheme: TerminalColorScheme) {
return this.config.store.terminal.customColorSchemes.some(x => deepEqual(x, scheme))
}
colorsTrackBy (index) {
return index
}
+
+ getPreviewFontFamily () {
+ return getCSSFontFamily(this.config.store.terminal.font)
+ }
}
diff --git a/terminus-terminal/src/components/baseTerminalTab.component.pug b/terminus-terminal/src/components/baseTerminalTab.component.pug
new file mode 100644
index 00000000..4161600a
--- /dev/null
+++ b/terminus-terminal/src/components/baseTerminalTab.component.pug
@@ -0,0 +1,7 @@
+.content(#content, [style.opacity]='frontendIsReady ? 1 : 0')
+search-panel(
+ *ngIf='showSearchPanel',
+ @slideInOut,
+ [frontend]='frontend',
+ (close)='showSearchPanel = false'
+)
diff --git a/terminus-terminal/src/components/colorPicker.component.ts b/terminus-terminal/src/components/colorPicker.component.ts
index c5adf1b0..c8c7db0c 100644
--- a/terminus-terminal/src/components/colorPicker.component.ts
+++ b/terminus-terminal/src/components/colorPicker.component.ts
@@ -1,6 +1,7 @@
import { Component, Input, Output, EventEmitter, HostListener, ViewChild } from '@angular/core'
import { NgbPopover } from '@ng-bootstrap/ng-bootstrap'
+/** @hidden */
@Component({
selector: 'color-picker',
template: require('./colorPicker.component.pug'),
@@ -28,7 +29,7 @@ export class ColorPickerComponent {
if (!this.isOpen) {
return
}
- let windowRef = (this.popover as any)._windowRef
+ const windowRef = (this.popover as any)._windowRef
if (!windowRef) {
return
}
diff --git a/terminus-terminal/src/components/editProfileModal.component.pug b/terminus-terminal/src/components/editProfileModal.component.pug
new file mode 100644
index 00000000..fa1e86bf
--- /dev/null
+++ b/terminus-terminal/src/components/editProfileModal.component.pug
@@ -0,0 +1,58 @@
+.modal-body
+ .form-group
+ label Name
+ input.form-control(
+ type='text',
+ autofocus,
+ [(ngModel)]='profile.name',
+ )
+
+ .form-group
+ label Command
+ input.form-control(
+ type='text',
+ [(ngModel)]='profile.sessionOptions.command',
+ )
+
+ .form-group
+ label Arguments
+ .input-group(
+ *ngFor='let arg of profile.sessionOptions.args; index as i; trackBy: trackByIndex',
+ )
+ input.form-control(
+ type='text',
+ [(ngModel)]='profile.sessionOptions.args[i]',
+ )
+ .input-group-btn
+ button.btn.btn-secondary((click)='profile.sessionOptions.args.splice(i, 1)')
+ i.fas.fa-trash
+
+ .mt-2
+ button.btn.btn-secondary((click)='profile.sessionOptions.args.push("")')
+ i.fas.fa-plus.mr-2
+ | Add
+
+ .form-line(*ngIf='uac.isAvailable')
+ .header
+ .title Run as administrator
+ toggle(
+ [(ngModel)]='profile.sessionOptions.runAsAdministrator',
+ )
+
+ .form-group
+ label Working directory
+ input.form-control(
+ type='text',
+ [(ngModel)]='profile.sessionOptions.cwd',
+ )
+
+ .form-group
+ label Environment
+ environment-editor(
+ type='text',
+ [(model)]='profile.sessionOptions.env',
+ )
+
+.modal-footer
+ button.btn.btn-outline-primary((click)='save()') Save
+ button.btn.btn-outline-danger((click)='cancel()') Cancel
diff --git a/terminus-terminal/src/components/editProfileModal.component.ts b/terminus-terminal/src/components/editProfileModal.component.ts
new file mode 100644
index 00000000..f395772f
--- /dev/null
+++ b/terminus-terminal/src/components/editProfileModal.component.ts
@@ -0,0 +1,35 @@
+import { Component } from '@angular/core'
+import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
+import { UACService } from '../services/uac.service'
+import { Profile } from '../api/interfaces'
+
+/** @hidden */
+@Component({
+ template: require('./editProfileModal.component.pug'),
+})
+export class EditProfileModalComponent {
+ profile: Profile
+
+ constructor (
+ public uac: UACService,
+ private modalInstance: NgbActiveModal,
+ ) {
+ }
+
+ ngOnInit () {
+ this.profile.sessionOptions.env = this.profile.sessionOptions.env || {}
+ this.profile.sessionOptions.args = this.profile.sessionOptions.args || []
+ }
+
+ save () {
+ this.modalInstance.close(this.profile)
+ }
+
+ cancel () {
+ this.modalInstance.dismiss()
+ }
+
+ trackByIndex (index) {
+ return index
+ }
+}
diff --git a/terminus-terminal/src/components/environmentEditor.component.pug b/terminus-terminal/src/components/environmentEditor.component.pug
new file mode 100644
index 00000000..bc077f44
--- /dev/null
+++ b/terminus-terminal/src/components/environmentEditor.component.pug
@@ -0,0 +1,12 @@
+.mb-2.d-flex.align-items-center(*ngFor='let pair of vars')
+ .input-group.w-50
+ input.form-control([(ngModel)]='pair.key', (blur)='emitUpdate()', placeholder='Variable name')
+ .input-group-append
+ .input-group-text =
+ input.form-control.w-50.mr-1([(ngModel)]='pair.value', (blur)='emitUpdate()', placeholder='Value')
+ button.btn.btn-secondary((click)='removeEnvironmentVar(pair.key)')
+ i.fas.fa-trash
+
+button.btn.btn-secondary((click)='addEnvironmentVar()')
+ i.fas.fa-plus.mr-2
+ span Add
diff --git a/terminus-terminal/src/components/environmentEditor.component.scss b/terminus-terminal/src/components/environmentEditor.component.scss
new file mode 100644
index 00000000..7f26ddcb
--- /dev/null
+++ b/terminus-terminal/src/components/environmentEditor.component.scss
@@ -0,0 +1,3 @@
+:host {
+ display: block;
+}
diff --git a/terminus-terminal/src/components/environmentEditor.component.ts b/terminus-terminal/src/components/environmentEditor.component.ts
new file mode 100644
index 00000000..1393b925
--- /dev/null
+++ b/terminus-terminal/src/components/environmentEditor.component.ts
@@ -0,0 +1,46 @@
+import { Component, Output, Input } from '@angular/core'
+import { Subject } from 'rxjs'
+
+/** @hidden */
+@Component({
+ selector: 'environment-editor',
+ template: require('./environmentEditor.component.pug'),
+ styles: [require('./environmentEditor.component.scss')],
+})
+export class EnvironmentEditorComponent {
+ @Output() modelChange = new Subject()
+ vars: {key: string, value: string}[] = []
+ private cachedModel: any
+
+ @Input() get model (): any {
+ return this.cachedModel
+ }
+
+ set model (value) {
+ this.vars = Object.entries(value).map(([k, v]) => ({ key: k, value: v as string }))
+ this.cachedModel = this.getModel()
+ }
+
+ getModel () {
+ const model = {}
+ for (const pair of this.vars) {
+ model[pair.key] = pair.value
+ }
+ return model
+ }
+
+ emitUpdate () {
+ this.cachedModel = this.getModel()
+ this.modelChange.next(this.cachedModel)
+ }
+
+ addEnvironmentVar () {
+ this.vars.push({ key: '', value: '' })
+ }
+
+ removeEnvironmentVar (key: string) {
+ this.vars = this.vars.filter(x => x.key !== key)
+ this.emitUpdate()
+ }
+
+}
diff --git a/terminus-terminal/src/components/searchPanel.component.pug b/terminus-terminal/src/components/searchPanel.component.pug
new file mode 100644
index 00000000..c94dfff8
--- /dev/null
+++ b/terminus-terminal/src/components/searchPanel.component.pug
@@ -0,0 +1,34 @@
+.input-group.w-100
+ input.search-input.form-control(
+ type='search',
+ [(ngModel)]='query',
+ (ngModelChange)='notFound = false',
+ [class.text-danger]='notFound',
+ (click)='$event.stopPropagation()',
+ (keyup.enter)='findNext()',
+ (keyup.esc)='close.emit()',
+ placeholder='Search...'
+ )
+ .input-group-append
+ .btn-group
+ button.btn.btn-outline-primary(
+ (click)='options.caseSensitive = !options.caseSensitive',
+ [class.active]='options.caseSensitive',
+ ngbTooltip='Case sensitivity',
+ placement='bottom'
+ )
+ i.fa.fa-fw.fa-font
+ button.btn.btn-outline-primary(
+ (click)='options.regex = !options.regex',
+ [class.active]='options.regex',
+ ngbTooltip='Regular expression',
+ placement='bottom'
+ )
+ i.fa.fa-fw.fa-asterisk
+ button.btn.btn-outline-primary(
+ (click)='options.wholeWord = !options.wholeWord',
+ [class.active]='options.wholeWord',
+ ngbTooltip='Whole word',
+ placement='bottom'
+ )
+ i.fa.fa-fw.fa-square
diff --git a/terminus-terminal/src/components/searchPanel.component.scss b/terminus-terminal/src/components/searchPanel.component.scss
new file mode 100644
index 00000000..1245e090
--- /dev/null
+++ b/terminus-terminal/src/components/searchPanel.component.scss
@@ -0,0 +1,9 @@
+:host {
+ position: fixed;
+ width: 400px;
+ align-self: center;
+ z-index: 5;
+ padding: 5px;
+ border-radius: 0 0 3px 3px;
+ background: rgba(0, 0, 0, .25);
+}
diff --git a/terminus-terminal/src/components/searchPanel.component.ts b/terminus-terminal/src/components/searchPanel.component.ts
new file mode 100644
index 00000000..e75a9d5f
--- /dev/null
+++ b/terminus-terminal/src/components/searchPanel.component.ts
@@ -0,0 +1,36 @@
+import { Component, Input, Output, EventEmitter } from '@angular/core'
+import { ToastrService } from 'ngx-toastr'
+import { Frontend, SearchOptions } from '../frontends/frontend'
+
+@Component({
+ selector: 'search-panel',
+ template: require('./searchPanel.component.pug'),
+ styles: [require('./searchPanel.component.scss')],
+})
+export class SearchPanelComponent {
+ static globalOptions: SearchOptions = {}
+ @Input() query: string
+ @Input() frontend: Frontend
+ notFound = false
+ options: SearchOptions = SearchPanelComponent.globalOptions
+
+ @Output() close = new EventEmitter()
+
+ constructor (
+ private toastr: ToastrService,
+ ) { }
+
+ findNext () {
+ if (!this.frontend.findNext(this.query, this.options)) {
+ this.notFound = true
+ this.toastr.error('Not found')
+ }
+ }
+
+ findPrevious () {
+ if (!this.frontend.findPrevious(this.query, this.options)) {
+ this.notFound = true
+ this.toastr.error('Not found')
+ }
+ }
+}
diff --git a/terminus-terminal/src/components/shellSettingsTab.component.pug b/terminus-terminal/src/components/shellSettingsTab.component.pug
index 6464c5ed..f858e363 100644
--- a/terminus-terminal/src/components/shellSettingsTab.component.pug
+++ b/terminus-terminal/src/components/shellSettingsTab.component.pug
@@ -2,23 +2,36 @@ h3.mb-3 Shell
.form-line
.header
- .title Shell
- .description Default shell for new tabs
+ .title Profile
+ .description Default profile for new tabs
select.form-control(
- [(ngModel)]='config.store.terminal.shell',
+ [(ngModel)]='config.store.terminal.profile',
(ngModelChange)='config.save()',
)
option(
- *ngFor='let shell of shells',
- [ngValue]='shell.id'
- ) {{shell.name}}
+ *ngFor='let profile of profiles',
+ [ngValue]='slug(profile.name).toLowerCase()'
+ ) {{profile.name}}
-.alert.alert-info.d-flex.align-items-center(*ngIf='config.store.terminal.shell.startsWith("wsl")')
- .mr-auto WSL terminal only supports 16 colors until ConPTY is implemented in node-pty
- button.btn.btn-secondary((click)='openConPtyInfo()') More Information
+
+.form-line(*ngIf='isConPTYAvailable')
+ .header
+ .title Use ConPTY
+ .description Enables the experimental Windows ConPTY API
+
+ toggle(
+ [(ngModel)]='config.store.terminal.useConPTY',
+ (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.profile.startsWith("WSL") && (config.store.terminal.frontend != "hterm" || !config.store.terminal.useConPTY)')
+ .mr-auto WSL terminal only supports TrueColor with ConPTY and the hterm frontend
-.form-line(*ngIf='config.store.terminal.shell == "custom"')
+.form-line(*ngIf='config.store.terminal.profile == "custom-shell"')
.header
.title Custom shell
@@ -28,20 +41,6 @@ h3.mb-3 Shell
(ngModelChange)='config.save()',
)
-.form-line(*ngIf='persistenceProviders.length > 0')
- .header
- .title Session persistence
- .description Restores tabs when Terminus is restarted
- select.form-control(
- [(ngModel)]='config.store.terminal.persistence',
- (ngModelChange)='config.save()',
- )
- option([ngValue]='null') Off
- option(
- *ngFor='let provider of persistenceProviders',
- [ngValue]='provider.id'
- ) {{provider.displayName}}
-
.form-line
.header
.title Working directory
@@ -54,20 +53,31 @@ h3.mb-3 Shell
)
.input-group-btn
button.btn.btn-secondary((click)='pickWorkingDirectory()')
- i.fa.fa-folder-open
+ i.fas.fa-folder-open
-.form-line
+.form-line.align-items-start
.header
.title Environment
.description Inject additional environment variables
- div
- .mb-2.d-flex.align-items-center(*ngFor='let pair of environmentVars')
- input.form-control.w-50([(ngModel)]='pair.key', (blur)='saveEnvironment()', placeholder='Variable name')
- input.form-control.w-50.mr-1([(ngModel)]='pair.value', (blur)='saveEnvironment()', placeholder='Value')
- button.btn.btn-secondary((click)='removeEnvironmentVar(pair.key)')
- i.fa.fa-trash-o
-
- button.btn.btn-secondary((click)='addEnvironmentVar()')
- i.fa.fa-plus.mr-2
- span Add
+ environment-editor([(model)]='this.config.store.terminal.environment')
+
+h3.mt-3 Saved Profiles
+
+.list-group.list-group-flush.mt-3.mb-3
+ .list-group-item.list-group-item-action.d-flex.align-items-center(
+ *ngFor='let profile of config.store.terminal.profiles',
+ (click)='editProfile(profile)',
+ )
+ .mr-auto
+ div {{profile.name}}
+ .text-muted {{profile.sessionOptions.command}}
+ button.btn.btn-outline-danger.ml-1((click)='$event.stopPropagation(); deleteProfile(profile)')
+ i.fas.fa-trash
+
+div(ngbDropdown, placement='top-left')
+ button.btn.btn-primary(ngbDropdownToggle)
+ i.fas.fa-fw.fa-plus
+ | New profile
+ div(ngbDropdownMenu)
+ button.dropdown-item(*ngFor='let shell of shells', (click)='newProfile(shell)') {{shell.name}}
diff --git a/terminus-terminal/src/components/shellSettingsTab.component.ts b/terminus-terminal/src/components/shellSettingsTab.component.ts
index d0c01288..e6b810eb 100644
--- a/terminus-terminal/src/components/shellSettingsTab.component.ts
+++ b/terminus-terminal/src/components/shellSettingsTab.component.ts
@@ -1,72 +1,91 @@
-import { Component, Inject } from '@angular/core'
+import slug from 'slug'
+import { Component } from '@angular/core'
+import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
import { Subscription } from 'rxjs'
-import { ConfigService, ElectronService } from 'terminus-core'
-import { IShell, ShellProvider, SessionPersistenceProvider } from '../api'
+import { ConfigService, ElectronService, HostAppService, Platform } from 'terminus-core'
+import { EditProfileModalComponent } from './editProfileModal.component'
+import { Shell, Profile } from '../api/interfaces'
+import { TerminalService } from '../services/terminal.service'
+import { WIN_BUILD_CONPTY_SUPPORTED, WIN_BUILD_CONPTY_STABLE, isWindowsBuild } from '../utils'
+/** @hidden */
@Component({
template: require('./shellSettingsTab.component.pug'),
})
export class ShellSettingsTabComponent {
- shells: IShell[] = []
- persistenceProviders: SessionPersistenceProvider[]
-
- environmentVars: {key: string, value: string}[] = []
+ shells: Shell[] = []
+ profiles: Profile[] = []
+ Platform = Platform
+ isConPTYAvailable: boolean
+ isConPTYStable: boolean
+ slug = slug
private configSubscription: Subscription
constructor (
public config: ConfigService,
+ public hostApp: HostAppService,
private electron: ElectronService,
- @Inject(ShellProvider) private shellProviders: ShellProvider[],
- @Inject(SessionPersistenceProvider) persistenceProviders: SessionPersistenceProvider[],
+ private terminalService: TerminalService,
+ private ngbModal: NgbModal,
) {
- this.persistenceProviders = this.config.enabledServices(persistenceProviders).filter(x => x.isAvailable())
-
config.store.terminal.environment = config.store.terminal.environment || {}
- this.reloadEnvironment()
- this.configSubscription = config.changed$.subscribe(() => this.reloadEnvironment())
+ this.configSubscription = this.config.changed$.subscribe(() => {
+ this.reload()
+ })
+ this.reload()
+
+ this.isConPTYAvailable = isWindowsBuild(WIN_BUILD_CONPTY_SUPPORTED)
+ this.isConPTYStable = isWindowsBuild(WIN_BUILD_CONPTY_STABLE)
}
async ngOnInit () {
- this.shells = (await Promise.all(this.config.enabledServices(this.shellProviders).map(x => x.provide()))).reduce((a, b) => a.concat(b))
- }
-
- openConPtyInfo() {
- this.electron.shell.openExternal('https://github.com/Microsoft/node-pty/issues/216')
+ this.shells = await this.terminalService.shells$.toPromise()
}
ngOnDestroy () {
this.configSubscription.unsubscribe()
}
+ async reload () {
+ this.profiles = await this.terminalService.getProfiles(true)
+ }
+
pickWorkingDirectory () {
- let shell = this.shells.find(x => x.id === this.config.store.terminal.shell)
- console.log(shell)
- let paths = this.electron.dialog.showOpenDialog({
- defaultPath: shell.fsBase,
- properties: ['openDirectory', 'showHiddenFiles'],
- })
+ const shell = this.shells.find(x => x.id === this.config.store.terminal.shell)
+ const paths = this.electron.dialog.showOpenDialog(
+ this.hostApp.getWindow(),
+ {
+ defaultPath: shell.fsBase,
+ properties: ['openDirectory', 'showHiddenFiles'],
+ }
+ )
if (paths) {
this.config.store.terminal.workingDirectory = paths[0]
}
}
- reloadEnvironment () {
- this.environmentVars = Object.entries(this.config.store.terminal.environment).map(([k, v]) => ({ key: k, value: v as string }))
- }
-
- saveEnvironment () {
- this.config.store.terminal.environment = {}
- for (let pair of this.environmentVars) {
- this.config.store.terminal.environment[pair.key] = pair.value
+ newProfile (shell: Shell) {
+ const profile: Profile = {
+ name: shell.name,
+ sessionOptions: this.terminalService.optionsFromShell(shell),
}
+ this.config.store.terminal.profiles = [profile, ...this.config.store.terminal.profiles]
+ this.config.save()
+ this.reload()
}
- addEnvironmentVar () {
- this.environmentVars.push({ key: '', value: '' })
+ editProfile (profile: Profile) {
+ const modal = this.ngbModal.open(EditProfileModalComponent)
+ modal.componentInstance.profile = Object.assign({}, profile)
+ modal.result.then(result => {
+ Object.assign(profile, result)
+ this.config.save()
+ })
}
- removeEnvironmentVar (key: string) {
- this.environmentVars = this.environmentVars.filter(x => x.key !== key)
- this.saveEnvironment()
+ deleteProfile (profile: Profile) {
+ this.config.store.terminal.profiles = this.config.store.terminal.profiles.filter(x => x !== profile)
+ this.config.save()
+ this.reload()
}
}
diff --git a/terminus-terminal/src/components/terminalSettingsTab.component.ts b/terminus-terminal/src/components/terminalSettingsTab.component.ts
index 70272ffe..85454a25 100644
--- a/terminus-terminal/src/components/terminalSettingsTab.component.ts
+++ b/terminus-terminal/src/components/terminalSettingsTab.component.ts
@@ -2,6 +2,7 @@ import { Component } from '@angular/core'
import { ConfigService, ElectronService } from 'terminus-core'
import { TerminalService } from '../services/terminal.service'
+/** @hidden */
@Component({
template: require('./terminalSettingsTab.component.pug'),
})
@@ -15,9 +16,11 @@ export class TerminalSettingsTabComponent {
openWSLVolumeMixer () {
this.electron.shell.openItem('sndvol.exe')
this.terminal.openTab({
- id: '',
- command: 'wsl.exe',
- args: ['tput', 'bel'],
+ name: null,
+ sessionOptions: {
+ command: 'wsl.exe',
+ args: ['tput', 'bel'],
+ },
}, null, true)
}
}
diff --git a/terminus-terminal/src/components/terminalTab.component.scss b/terminus-terminal/src/components/terminalTab.component.scss
index 0556f84c..b9d4414e 100644
--- a/terminus-terminal/src/components/terminalTab.component.scss
+++ b/terminus-terminal/src/components/terminalTab.component.scss
@@ -1,8 +1,13 @@
:host {
flex: auto;
display: flex;
+ flex-direction: column;
overflow: hidden;
+ &.top-padded {
+ padding-top: 20px;
+ }
+
&> .content {
flex: auto;
position: relative;
diff --git a/terminus-terminal/src/components/terminalTab.component.ts b/terminus-terminal/src/components/terminalTab.component.ts
index 5dea3b57..0caff623 100644
--- a/terminus-terminal/src/components/terminalTab.component.ts
+++ b/terminus-terminal/src/components/terminalTab.component.ts
@@ -1,123 +1,48 @@
-import { Observable, Subject, Subscription } from 'rxjs'
+import { Component, Input } from '@angular/core'
+import { Subscription } from 'rxjs'
import { first } from 'rxjs/operators'
-import { ToastrService } from 'ngx-toastr'
-import { Component, NgZone, Inject, Optional, ViewChild, HostBinding, Input } from '@angular/core'
-import { AppService, ConfigService, BaseTabComponent, BaseTabProcess, ElectronService, HostAppService, HotkeysService, Platform } from 'terminus-core'
-
-import { IShell } from '../api'
-import { Session, SessionsService } from '../services/sessions.service'
-import { TerminalService } from '../services/terminal.service'
-import { TerminalFrontendService } from '../services/terminalFrontend.service'
-
-import { TerminalDecorator, ResizeEvent, SessionOptions } from '../api'
-import { Frontend } from '../frontends/frontend'
+import { BaseTabProcess } from 'terminus-core'
+import { BaseTerminalTabComponent } from '../api/baseTerminalTab.component'
+import { SessionOptions } from '../api/interfaces'
+import { Session } from '../services/sessions.service'
+import { WIN_BUILD_CONPTY_SUPPORTED, isWindowsBuild } from '../utils'
+/** @hidden */
@Component({
selector: 'terminalTab',
- template: `
-
- `,
- styles: [require('./terminalTab.component.scss')],
+ template: BaseTerminalTabComponent.template,
+ styles: BaseTerminalTabComponent.styles,
+ animations: BaseTerminalTabComponent.animations,
})
-export class TerminalTabComponent extends BaseTabComponent {
- session: Session
+export class TerminalTabComponent extends BaseTerminalTabComponent {
@Input() sessionOptions: SessionOptions
- @Input() zoom = 0
- @ViewChild('content') content
- @HostBinding('style.background-color') backgroundColor: string
- frontend: Frontend
- sessionCloseSubscription: Subscription
- hotkeysSubscription: Subscription
- htermVisible = false
- shell: IShell
- private output = new Subject()
- private bellPlayer: HTMLAudioElement
- private contextMenu: any
- private termContainerSubscriptions: Subscription[] = []
+ private homeEndSubscription: Subscription
- get input$ (): Observable { return this.frontend.input$ }
- get output$ (): Observable { return this.output }
- get resize$ (): Observable { return this.frontend.resize$ }
- get alternateScreenActive$ (): Observable { return this.frontend.alternateScreenActive$ }
+ ngOnInit () {
+ this.logger = this.log.create('terminalTab')
+ this.session = new Session(this.config)
- constructor (
- private zone: NgZone,
- private app: AppService,
- private hostApp: HostAppService,
- private hotkeys: HotkeysService,
- private sessions: SessionsService,
- private electron: ElectronService,
- private terminalService: TerminalService,
- private terminalContainersService: TerminalFrontendService,
- public config: ConfigService,
- private toastr: ToastrService,
- @Optional() @Inject(TerminalDecorator) private decorators: TerminalDecorator[],
- ) {
- super()
- this.decorators = this.decorators || []
- this.setTitle('Terminal')
+ const isConPTY = isWindowsBuild(WIN_BUILD_CONPTY_SUPPORTED) && this.config.store.terminal.useConPTY
- this.session = new Session()
-
- this.hotkeysSubscription = this.hotkeys.matchedHotkey.subscribe(hotkey => {
+ this.homeEndSubscription = this.hotkeys.matchedHotkey.subscribe(hotkey => {
if (!this.hasFocus) {
return
}
switch (hotkey) {
- case 'ctrl-c':
- if (this.frontend.getSelection()) {
- this.frontend.copySelection()
- this.frontend.clearSelection()
- this.toastr.info('Copied')
- } else {
- this.sendInput('\x03')
- }
- break
- case 'copy':
- this.frontend.copySelection()
- this.toastr.info('Copied')
- break
- case 'paste':
- this.paste()
- break
- case 'clear':
- this.frontend.clear()
- break
- case 'zoom-in':
- this.zoomIn()
- break
- case 'zoom-out':
- this.zoomOut()
- break
- case 'reset-zoom':
- this.resetZoom()
- break
- case 'home':
- this.sendInput('\x1bOH')
- break
- case 'end':
- this.sendInput('\x1bOF')
- break
- case 'previous-word':
- this.sendInput('\x1bb')
- break
- case 'next-word':
- this.sendInput('\x1bf')
- break
- case 'delete-previous-word':
- this.sendInput('\x1b\x7f')
- break
- case 'delete-next-word':
- this.sendInput('\x1bd')
- break
+ case 'home':
+ this.sendInput(isConPTY ? '\x1b[H' : '\x1bOH')
+ break
+ case 'end':
+ this.sendInput(isConPTY ? '\x1b[F' : '\x1bOF')
+ break
}
})
- this.bellPlayer = document.createElement('audio')
- this.bellPlayer.src = require('../bell.ogg')
+
+ this.frontendReady$.pipe(first()).subscribe(() => {
+ this.initializeSession(this.size.columns, this.size.rows)
+ })
+
+ super.ngOnInit()
}
initializeSession (columns: number, rows: number) {
@@ -129,271 +54,48 @@ export class TerminalTabComponent extends BaseTabComponent {
})
)
- // this.session.output$.bufferTime(10).subscribe((datas) => {
- this.session.output$.subscribe(data => {
- this.zone.run(() => {
- this.output.next(data)
- this.write(data)
- })
- })
-
- this.sessionCloseSubscription = this.session.closed$.subscribe(() => {
- this.frontend.destroy()
- this.app.closeTab(this)
- })
+ this.attachSessionHandlers()
}
- getRecoveryToken (): any {
+ async getRecoveryToken (): Promise {
+ const cwd = this.session ? await this.session.getWorkingDirectory() : null
return {
- type: 'app:terminal',
- recoveryId: this.sessionOptions.recoveryId,
- }
- }
-
- ngOnInit () {
- this.focused$.subscribe(() => {
- this.configure()
- this.frontend.focus()
- })
-
- this.frontend = this.terminalContainersService.getFrontend(this.session)
-
- this.frontend.ready$.subscribe(() => {
- this.htermVisible = true
- })
-
- this.frontend.resize$.pipe(first()).subscribe(async ({columns, rows}) => {
- if (!this.session.open) {
- this.initializeSession(columns, rows)
- }
-
- setTimeout(() => {
- this.session.resize(columns, rows)
- }, 1000)
-
- this.session.releaseInitialDataBuffer()
- })
-
- this.frontend.configure(this.config.store)
- this.frontend.attach(this.content.nativeElement)
- this.attachTermContainerHandlers()
-
- this.configure()
-
- this.config.enabledServices(this.decorators).forEach((decorator) => {
- decorator.attach(this)
- })
-
- setTimeout(() => {
- this.output.subscribe(() => {
- this.displayActivity()
- })
- }, 1000)
-
- this.frontend.bell$.subscribe(() => {
- if (this.config.store.terminal.bell === 'visual') {
- this.frontend.visualBell()
- }
- if (this.config.store.terminal.bell === 'audible') {
- this.bellPlayer.play()
- }
- })
-
- this.contextMenu = [
- {
- label: 'New terminal',
- click: () => {
- this.zone.run(() => {
- this.terminalService.openTab(this.shell)
- })
- }
+ type: 'app:terminal-tab',
+ sessionOptions: {
+ ...this.sessionOptions,
+ cwd: cwd || this.sessionOptions.cwd,
},
- {
- label: 'Copy',
- click: () => {
- this.zone.run(() => {
- setTimeout(() => {
- this.frontend.copySelection()
- this.toastr.info('Copied')
- })
- })
- }
- },
- {
- label: 'Paste',
- click: () => {
- this.zone.run(() => {
- this.paste()
- })
- }
- },
- ]
-
- this.frontend.focus()
- }
-
- detachTermContainerHandlers () {
- for (let subscription of this.termContainerSubscriptions) {
- subscription.unsubscribe()
}
- this.termContainerSubscriptions = []
- }
-
- attachTermContainerHandlers () {
- this.detachTermContainerHandlers()
- this.termContainerSubscriptions = [
- this.frontend.title$.subscribe(title => this.zone.run(() => this.setTitle(title))),
-
- this.focused$.subscribe(() => this.frontend.enableResizing = true),
- this.blurred$.subscribe(() => this.frontend.enableResizing = false),
-
- this.frontend.mouseEvent$.subscribe(event => {
- if (event.type === 'mousedown') {
- if (event.which === 3) {
- if (this.config.store.terminal.rightClick === 'menu') {
- this.hostApp.popupContextMenu(this.contextMenu)
- } else if (this.config.store.terminal.rightClick === 'paste') {
- this.paste()
- }
- event.preventDefault()
- event.stopPropagation()
- return
- }
- }
- if (event.type === 'mousewheel') {
- let wheelDeltaY = 0
-
- if ('wheelDeltaY' in event) {
- wheelDeltaY = (event as MouseWheelEvent).wheelDeltaY
- } else {
- wheelDeltaY = (event as MouseWheelEvent).deltaY
- }
- if (event.ctrlKey || event.metaKey) {
-
- if (wheelDeltaY > 0) {
- this.zoomIn()
- } else {
- this.zoomOut()
- }
- } else if (event.altKey) {
- event.preventDefault()
- let delta = Math.round(wheelDeltaY / 50)
- this.sendInput(((delta > 0) ? '\u001bOA' : '\u001bOB').repeat(Math.abs(delta)))
- }
- }
- }),
-
- this.frontend.input$.subscribe(data => {
- this.sendInput(data)
- }),
-
- this.frontend.resize$.subscribe(({columns, rows}) => {
- console.log(`Resizing to ${columns}x${rows}`)
- this.zone.run(() => {
- if (this.session.open) {
- this.session.resize(columns, rows)
- }
- })
- })
- ]
- }
-
- sendInput (data: string) {
- this.session.write(data)
- if (this.config.store.terminal.scrollOnInput) {
- this.frontend.scrollToBottom()
- }
- }
-
- write (data: string) {
- let percentageMatch = /(^|[^\d])(\d+(\.\d+)?)%([^\d]|$)/.exec(data)
- if (percentageMatch) {
- let percentage = percentageMatch[3] ? parseFloat(percentageMatch[2]) : parseInt(percentageMatch[2])
- if (percentage > 0 && percentage <= 100) {
- this.setProgress(percentage)
- console.log('Detected progress:', percentage)
- }
- } else {
- this.setProgress(null)
- }
- this.frontend.write(data)
- }
-
- paste () {
- let data = this.electron.clipboard.readText()
- if (this.config.store.terminal.bracketedPaste) {
- data = '\x1b[200~' + data + '\x1b[201~'
- }
- if (this.hostApp.platform === Platform.Windows) {
- data = data.replace(/\r\n/g, '\r')
- } else {
- data = data.replace(/\n/g, '\r')
- }
- this.sendInput(data)
- }
-
- configure (): void {
- this.frontend.configure(this.config.store)
-
- if (this.config.store.terminal.background === 'colorScheme') {
- if (this.config.store.terminal.colorScheme.background) {
- this.backgroundColor = this.config.store.terminal.colorScheme.background
- }
- } else {
- this.backgroundColor = null
- }
- }
-
- zoomIn () {
- this.zoom++
- this.frontend.setZoom(this.zoom)
- }
-
- zoomOut () {
- this.zoom--
- this.frontend.setZoom(this.zoom)
- }
-
- resetZoom () {
- this.zoom = 0
- this.frontend.setZoom(this.zoom)
}
async getCurrentProcess (): Promise {
- let children = await this.session.getChildProcesses()
+ const children = await this.session.getChildProcesses()
if (!children.length) {
return null
}
return {
- name: children[0].command
- }
- }
-
- ngOnDestroy () {
- this.frontend.detach(this.content.nativeElement)
- this.detachTermContainerHandlers()
- this.config.enabledServices(this.decorators).forEach(decorator => {
- decorator.detach(this)
- })
- this.hotkeysSubscription.unsubscribe()
- if (this.sessionCloseSubscription) {
- this.sessionCloseSubscription.unsubscribe()
- }
- this.output.complete()
- }
-
- async destroy () {
- super.destroy()
- if (this.session && this.session.open) {
- await this.session.destroy()
+ name: children[0].command,
}
}
async canClose (): Promise {
- let children = await this.session.getChildProcesses()
+ const children = await this.session.getChildProcesses()
if (children.length === 0) {
return true
}
- return confirm(`"${children[0].command}" is still running. Close?`)
+ return (await this.electron.showMessageBox(
+ this.hostApp.getWindow(),
+ {
+ type: 'warning',
+ message: `"${children[0].command}" is still running. Close?`,
+ buttons: ['Cancel', 'Kill'],
+ defaultId: 1,
+ }
+ )).response === 1
+ }
+
+ ngOnDestroy () {
+ this.homeEndSubscription.unsubscribe()
+ super.ngOnDestroy()
}
}
diff --git a/terminus-terminal/src/config.ts b/terminus-terminal/src/config.ts
index 9adc7d93..7d733860 100644
--- a/terminus-terminal/src/config.ts
+++ b/terminus-terminal/src/config.ts
@@ -1,14 +1,18 @@
import { ConfigProvider, Platform } from 'terminus-core'
+/** @hidden */
export class TerminalConfigProvider extends ConfigProvider {
defaults = {
hotkeys: {
shell: {
__nonStructural: true,
},
+ profile: {
+ __nonStructural: true,
+ },
},
terminal: {
- frontend: 'hterm',
+ frontend: 'xterm',
autoOpen: false,
fontSize: 14,
linePadding: 0,
@@ -47,10 +51,12 @@ export class TerminalConfigProvider extends ConfigProvider {
'#C792EA',
'#89DDFF',
'#ffffff',
- ]
+ ],
},
customColorSchemes: [],
environment: {},
+ profiles: [],
+ useConPTY: true,
},
}
@@ -59,125 +65,128 @@ export class TerminalConfigProvider extends ConfigProvider {
terminal: {
font: 'Menlo',
shell: 'default',
- persistence: 'screen',
+ profile: 'user-default',
},
hotkeys: {
'ctrl-c': ['Ctrl-C'],
- 'copy': [
+ copy: [
'β-C',
],
- 'paste': [
+ paste: [
],
- 'clear': [
+ clear: [
'β-K',
],
'zoom-in': [
'β-=',
- 'β-Shift-+',
+ 'β-Shift-=',
],
'zoom-out': [
'β--',
- 'β-Shift-_',
+ 'β-Shift--',
],
'reset-zoom': [
'β-0',
],
'new-tab': [
- ['Ctrl-A', 'C'],
- ['Ctrl-A', 'Ctrl-C'],
'β-T',
'β-N',
],
- 'home': ['β-ArrowLeft', 'Home'],
- 'end': ['β-ArrowRight', 'End'],
- 'previous-word': ['β₯-ArrowLeft'],
- 'next-word': ['β₯-ArrowRight'],
+ home: ['β-Left', 'Home'],
+ end: ['β-Right', 'End'],
+ 'previous-word': ['β₯-Left'],
+ 'next-word': ['β₯-Right'],
'delete-previous-word': ['β₯-Backspace'],
'delete-next-word': ['β₯-Delete'],
+ search: [
+ 'β-F',
+ ],
},
},
[Platform.Windows]: {
terminal: {
font: 'Consolas',
shell: 'clink',
- persistence: null,
+ profile: 'cmd-clink',
rightClick: 'paste',
copyOnSelect: true,
},
hotkeys: {
'ctrl-c': ['Ctrl-C'],
- 'copy': [
+ copy: [
'Ctrl-Shift-C',
],
- 'paste': [
+ paste: [
'Ctrl-Shift-V',
],
- 'clear': [
+ clear: [
'Ctrl-L',
],
'zoom-in': [
'Ctrl-=',
- 'Ctrl-Shift-+',
+ 'Ctrl-Shift-=',
],
'zoom-out': [
'Ctrl--',
- 'Ctrl-Shift-_',
+ 'Ctrl-Shift--',
],
'reset-zoom': [
'Ctrl-0',
],
'new-tab': [
- ['Ctrl-A', 'C'],
- ['Ctrl-A', 'Ctrl-C'],
'Ctrl-Shift-T',
],
- 'home': ['Home'],
- 'end': ['End'],
- 'previous-word': ['Ctrl-ArrowLeft'],
- 'next-word': ['Ctrl-ArrowRight'],
+ home: ['Home'],
+ end: ['End'],
+ 'previous-word': ['Ctrl-Left'],
+ 'next-word': ['Ctrl-Right'],
'delete-previous-word': ['Ctrl-Backspace'],
'delete-next-word': ['Ctrl-Delete'],
+ search: [
+ 'Ctrl-Shift-F',
+ ],
},
},
[Platform.Linux]: {
terminal: {
font: 'Liberation Mono',
shell: 'default',
- persistence: 'tmux',
+ profile: 'user-default',
},
hotkeys: {
'ctrl-c': ['Ctrl-C'],
- 'copy': [
+ copy: [
'Ctrl-Shift-C',
],
- 'paste': [
+ paste: [
'Ctrl-Shift-V',
],
- 'clear': [
+ clear: [
'Ctrl-L',
],
'zoom-in': [
'Ctrl-=',
- 'Ctrl-Shift-+',
+ 'Ctrl-Shift-=',
],
'zoom-out': [
'Ctrl--',
- 'Ctrl-Shift-_',
+ 'Ctrl-Shift--',
],
'reset-zoom': [
'Ctrl-0',
],
'new-tab': [
- ['Ctrl-A', 'C'],
- ['Ctrl-A', 'Ctrl-C'],
'Ctrl-Shift-T',
],
- 'home': ['Home'],
- 'end': ['End'],
- 'previous-word': ['Ctrl-ArrowLeft'],
- 'next-word': ['Ctrl-ArrowRight'],
+ home: ['Home'],
+ end: ['End'],
+ 'previous-word': ['Ctrl-Left'],
+ 'next-word': ['Ctrl-Right'],
'delete-previous-word': ['Ctrl-Backspace'],
'delete-next-word': ['Ctrl-Delete'],
+ search: [
+ 'Ctrl-Shift-F',
+ ],
},
},
}
diff --git a/terminus-terminal/src/contextMenu.ts b/terminus-terminal/src/contextMenu.ts
new file mode 100644
index 00000000..051c8773
--- /dev/null
+++ b/terminus-terminal/src/contextMenu.ts
@@ -0,0 +1,96 @@
+import { NgZone, Injectable } from '@angular/core'
+import { ToastrService } from 'ngx-toastr'
+import { ConfigService } from 'terminus-core'
+import { UACService } from './services/uac.service'
+import { TerminalService } from './services/terminal.service'
+import { TerminalContextMenuItemProvider } from './api/contextMenuProvider'
+import { BaseTerminalTabComponent } from './api/baseTerminalTab.component'
+
+/** @hidden */
+@Injectable()
+export class NewTabContextMenu extends TerminalContextMenuItemProvider {
+ weight = 0
+
+ constructor (
+ public config: ConfigService,
+ private zone: NgZone,
+ private terminalService: TerminalService,
+ private uac: UACService,
+ ) {
+ super()
+ }
+
+ async getItems (tab: BaseTerminalTabComponent): Promise {
+ const profiles = await this.terminalService.getProfiles()
+
+ const items: Electron.MenuItemConstructorOptions[] = [
+ {
+ label: 'New terminal',
+ click: () => this.zone.run(() => {
+ this.terminalService.openTabWithOptions((tab as any).sessionOptions)
+ }),
+ },
+ {
+ label: 'New with profile',
+ submenu: profiles.map(profile => ({
+ label: profile.name,
+ click: () => this.zone.run(async () => {
+ this.terminalService.openTab(profile, await tab.session.getWorkingDirectory())
+ }),
+ })),
+ },
+ ]
+
+ if (this.uac.isAvailable) {
+ items.push({
+ label: 'New admin tab',
+ submenu: profiles.map(profile => ({
+ label: profile.name,
+ click: () => this.zone.run(async () => {
+ this.terminalService.openTabWithOptions({
+ ...profile.sessionOptions,
+ runAsAdministrator: true,
+ })
+ }),
+ })),
+ })
+ }
+
+ return items
+ }
+}
+
+/** @hidden */
+@Injectable()
+export class CopyPasteContextMenu extends TerminalContextMenuItemProvider {
+ weight = 1
+
+ constructor (
+ private zone: NgZone,
+ private toastr: ToastrService,
+ ) {
+ super()
+ }
+
+ async getItems (tab: BaseTerminalTabComponent): Promise {
+ return [
+ {
+ label: 'Copy',
+ click: () => {
+ this.zone.run(() => {
+ setTimeout(() => {
+ tab.frontend.copySelection()
+ this.toastr.info('Copied')
+ })
+ })
+ },
+ },
+ {
+ label: 'Paste',
+ click: () => {
+ this.zone.run(() => tab.paste())
+ },
+ },
+ ]
+ }
+}
diff --git a/terminus-terminal/src/frontends/frontend.ts b/terminus-terminal/src/frontends/frontend.ts
index 4e0550c5..70c75fca 100644
--- a/terminus-terminal/src/frontends/frontend.ts
+++ b/terminus-terminal/src/frontends/frontend.ts
@@ -1,7 +1,21 @@
import { Observable, Subject, AsyncSubject, ReplaySubject, BehaviorSubject } from 'rxjs'
-import { ResizeEvent } from '../api'
+import { ResizeEvent } from '../api/interfaces'
+import { ConfigService, ThemesService, HotkeysService } from 'terminus-core'
+export interface SearchOptions {
+ regex?: boolean
+ wholeWord?: boolean
+ caseSensitive?: boolean
+}
+
+/**
+ * Extend to add support for a different VT frontend implementation
+ */
export abstract class Frontend {
+ configService: ConfigService
+ themesService: ThemesService
+ hotkeysService: HotkeysService
+
enableResizing = true
protected ready = new AsyncSubject()
protected title = new ReplaySubject(1)
@@ -25,11 +39,8 @@ export abstract class Frontend {
get dragOver$ (): Observable { return this.dragOver }
get drop$ (): Observable { return this.drop }
- abstract attach (host: HTMLElement): void
- detach (host: HTMLElement): void { } // tslint:disable-line
-
destroy (): void {
- for (let o of [
+ for (const o of [
this.ready,
this.title,
this.alternateScreenActive,
@@ -45,6 +56,9 @@ export abstract class Frontend {
}
}
+ abstract attach (host: HTMLElement): void
+ detach (host: HTMLElement): void { } // eslint-disable-line
+
abstract getSelection (): string
abstract copySelection (): void
abstract clearSelection (): void
@@ -54,6 +68,9 @@ export abstract class Frontend {
abstract visualBell (): void
abstract scrollToBottom (): void
- abstract configure (configStore: any): void
+ abstract configure (): void
abstract setZoom (zoom: number): void
+
+ abstract findNext (term: string, searchOptions?: SearchOptions): boolean
+ abstract findPrevious (term: string, searchOptions?: SearchOptions): boolean
}
diff --git a/terminus-terminal/src/hterm.ts b/terminus-terminal/src/frontends/hterm.ts
similarity index 89%
rename from terminus-terminal/src/hterm.ts
rename to terminus-terminal/src/frontends/hterm.ts
index 86da4baa..43d5649c 100644
--- a/terminus-terminal/src/hterm.ts
+++ b/terminus-terminal/src/frontends/hterm.ts
@@ -1,5 +1,11 @@
+/* eslint-disable */
+
+/** @hidden */
export const hterm = require('hterm-umdjs')
+
hterm.hterm.defaultStorage = new hterm.lib.Storage.Memory()
+
+/** @hidden */
export const preferenceManager = new hterm.hterm.PreferenceManager('default')
hterm.hterm.VT.ESC['k'] = function (parseState) {
@@ -42,7 +48,7 @@ hterm.lib.wc.charWidthDisregardAmbiguous = codepoint => {
}
hterm.hterm.Terminal.prototype.applyCursorShape = function () {
- let modes = [
+ const modes = [
[hterm.hterm.Terminal.cursorShape.BLOCK, true],
[this.defaultCursorShape || hterm.hterm.Terminal.cursorShape.BLOCK, false],
[hterm.hterm.Terminal.cursorShape.BLOCK, false],
@@ -51,8 +57,7 @@ hterm.hterm.Terminal.prototype.applyCursorShape = function () {
[hterm.hterm.Terminal.cursorShape.BEAM, true],
[hterm.hterm.Terminal.cursorShape.BEAM, false],
]
- let modeNumber = this.cursorMode || 1
- console.log('mode', modeNumber)
+ const modeNumber = this.cursorMode || 1
if (modeNumber >= modes.length) {
console.warn('Unknown cursor style: ' + modeNumber)
return
@@ -73,14 +78,14 @@ hterm.hterm.VT.CSI[' q'] = function (parseState) {
}
hterm.hterm.VT.OSC['4'] = function (parseState) {
- let args = parseState.args[0].split(';')
+ const args = parseState.args[0].split(';')
- let pairCount = args.length / 2
- let colorPalette = this.terminal.getTextAttributes().colorPalette
- let responseArray = []
+ const pairCount = args.length / 2
+ const colorPalette = this.terminal.getTextAttributes().colorPalette
+ const responseArray = []
for (let pairNumber = 0; pairNumber < pairCount; ++pairNumber) {
- let colorIndex = parseInt(args[pairNumber * 2])
+ const colorIndex = parseInt(args[pairNumber * 2])
let colorValue = args[pairNumber * 2 + 1]
if (colorIndex >= colorPalette.length) {
@@ -111,7 +116,5 @@ const _collapseToEnd = Selection.prototype.collapseToEnd
Selection.prototype.collapseToEnd = function () {
try {
_collapseToEnd.apply(this)
- } catch (err) {
- // tslint-disable-line
- }
+ } catch (e) { }
}
diff --git a/terminus-terminal/src/hterm.userCSS.scss b/terminus-terminal/src/frontends/hterm.userCSS.scss
similarity index 90%
rename from terminus-terminal/src/hterm.userCSS.scss
rename to terminus-terminal/src/frontends/hterm.userCSS.scss
index d88d6e2d..4d3060be 100644
--- a/terminus-terminal/src/hterm.userCSS.scss
+++ b/terminus-terminal/src/frontends/hterm.userCSS.scss
@@ -31,5 +31,5 @@ x-row > span {
@font-face {
font-family: "monospace-fallback";
- src: url(fonts/Meslo.otf) format("opentype");
+ src: url(../fonts/Meslo.otf) format("opentype");
}
diff --git a/terminus-terminal/src/frontends/htermFrontend.ts b/terminus-terminal/src/frontends/htermFrontend.ts
index 7803379d..2111a28d 100644
--- a/terminus-terminal/src/frontends/htermFrontend.ts
+++ b/terminus-terminal/src/frontends/htermFrontend.ts
@@ -1,6 +1,8 @@
-import { Frontend } from './frontend'
-import { hterm, preferenceManager } from '../hterm'
+import { Frontend, SearchOptions } from './frontend'
+import { hterm, preferenceManager } from './hterm'
+import { getCSSFontFamily } from '../utils'
+/** @hidden */
export class HTermFrontend extends Frontend {
term: any
io: any
@@ -51,12 +53,14 @@ export class HTermFrontend extends Frontend {
this.term.onVTKeystroke('\f')
}
- configure (config: any): void {
+ configure (): void {
+ const config = this.configService.store
+
this.configuredFontSize = config.terminal.fontSize
this.configuredLinePadding = config.terminal.linePadding
this.setFontSize()
- preferenceManager.set('font-family', `"${config.terminal.font}", "monospace-fallback", monospace`)
+ preferenceManager.set('font-family', getCSSFontFamily(config.terminal.font))
preferenceManager.set('enable-bold', true)
// preferenceManager.set('audible-bell-sound', '')
preferenceManager.set('desktop-notification-bell', config.terminal.bell === 'notification')
@@ -66,6 +70,7 @@ export class HTermFrontend extends Frontend {
preferenceManager.set('ctrl-plus-minus-zero-zoom', false)
preferenceManager.set('scrollbar-visible', process.platform === 'darwin')
preferenceManager.set('copy-on-select', config.terminal.copyOnSelect)
+ preferenceManager.set('pass-meta-v', false)
preferenceManager.set('alt-is-meta', config.terminal.altIsMeta)
preferenceManager.set('alt-sends-what', 'browser-key')
preferenceManager.set('alt-gr-mode', 'ctrl-alt')
@@ -84,8 +89,7 @@ export class HTermFrontend extends Frontend {
preferenceManager.set('background-color', config.terminal.colorScheme.background)
}
} else {
- // hterm can't parse "transparent"
- preferenceManager.set('background-color', 'transparent')
+ preferenceManager.set('background-color', config.appearance.vibrancy ? 'transparent' : this.themesService.findCurrentTheme().terminalBackground)
}
this.configuredBackgroundColor = preferenceManager.get('background-color')
@@ -94,7 +98,7 @@ export class HTermFrontend extends Frontend {
return
}
- let css = require('../hterm.userCSS.scss')
+ let css = require('./hterm.userCSS.scss') // eslint-disable-line
if (!config.terminal.ligatures) {
css += `
* {
@@ -152,8 +156,23 @@ export class HTermFrontend extends Frontend {
this.term.scrollEnd()
}
+ findNext (_term: string, _searchOptions?: SearchOptions): boolean {
+ return false
+ }
+
+ findPrevious (_term: string, _searchOptions?: SearchOptions): boolean {
+ return false
+ }
+
private setFontSize () {
- preferenceManager.set('font-size', this.configuredFontSize * Math.pow(1.1, this.zoom))
+ const size = this.configuredFontSize * Math.pow(1.1, this.zoom)
+ preferenceManager.set('font-size', size)
+ if (this.term) {
+ setTimeout(() => {
+ this.term.scrollPort_.characterSize = this.term.scrollPort_.measureCharacterSize()
+ this.term.setFontSize(size)
+ })
+ }
}
private init () {
@@ -165,7 +184,6 @@ export class HTermFrontend extends Frontend {
this.io = this.term.io.push()
this.io.onVTKeystroke = this.io.sendString = data => this.input.next(data)
this.io.onTerminalResize = (columns, rows) => {
- console.log('hterm resize')
this.resize.next({ columns, rows })
}
this.ready.next(null)
@@ -219,7 +237,7 @@ export class HTermFrontend extends Frontend {
this.term.ringBell = () => this.bell.next()
- for (let screen of [this.term.primaryScreen_, this.term.alternateScreen_]) {
+ for (const screen of [this.term.primaryScreen_, this.term.alternateScreen_]) {
const _insertString = screen.insertString.bind(screen)
screen.insertString = (data) => {
_insertString(data)
@@ -228,7 +246,7 @@ export class HTermFrontend extends Frontend {
const _deleteChars = screen.deleteChars.bind(screen)
screen.deleteChars = (count) => {
- let ret = _deleteChars(count)
+ const ret = _deleteChars(count)
this.contentUpdated.next()
return ret
}
@@ -236,7 +254,7 @@ export class HTermFrontend extends Frontend {
const _expandSelection = screen.expandSelection.bind(screen)
screen.expandSelection = (selection) => {
// Drop whitespace at the end of selection
- let range = selection.getRangeAt(0)
+ const range = selection.getRangeAt(0)
if (range.endOffset > 0 && range.endContainer.nodeType === 3 && range.endContainer.textContent !== '') {
while (/[\s\S]+\s$/.test(range.endContainer.textContent.substr(0,range.endOffset))) {
range.setEnd(range.endContainer, range.endOffset - 1)
@@ -248,7 +266,7 @@ export class HTermFrontend extends Frontend {
const _measureCharacterSize = this.term.scrollPort_.measureCharacterSize.bind(this.term.scrollPort_)
this.term.scrollPort_.measureCharacterSize = () => {
- let size = _measureCharacterSize()
+ const size = _measureCharacterSize()
size.height += this.configuredLinePadding
return size
}
diff --git a/terminus-terminal/src/frontends/xterm.css b/terminus-terminal/src/frontends/xterm.css
index c045d3ba..bba9a35c 100644
--- a/terminus-terminal/src/frontends/xterm.css
+++ b/terminus-terminal/src/frontends/xterm.css
@@ -1,3 +1,182 @@
+/**
+ * Copyright (c) 2014 The xterm.js authors. All rights reserved.
+ * Copyright (c) 2012-2013, Christopher Jeffrey (MIT License)
+ * https://github.com/chjj/term.js
+ * @license MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * Originally forked from (with the author's permission):
+ * Fabrice Bellard's javascript vt100 for jslinux:
+ * http://bellard.org/jslinux/
+ * Copyright (c) 2011 Fabrice Bellard
+ * The original design remains. The terminal itself
+ * has been extended to include xterm CSI codes, among
+ * other features.
+ */
+
+/**
+ * Default styles for xterm.js
+ */
+
+.xterm {
+ font-feature-settings: "liga" 0;
+ position: relative;
+ user-select: none;
+ -ms-user-select: none;
+ -webkit-user-select: none;
+}
+
+.xterm.focus,
+.xterm:focus {
+ outline: none;
+}
+
+.xterm .xterm-helpers {
+ position: absolute;
+ top: 0;
+ /**
+ * The z-index of the helpers must be higher than the canvases in order for
+ * IMEs to appear on top.
+ */
+ z-index: 10;
+}
+
+.xterm .xterm-helper-textarea {
+ /*
+ * HACK: to fix IE's blinking cursor
+ * Move textarea out of the screen to the far left, so that the cursor is not visible.
+ */
+ position: absolute;
+ opacity: 0;
+ left: -9999em;
+ top: 0;
+ width: 0;
+ height: 0;
+ z-index: -10;
+ /** Prevent wrapping so the IME appears against the textarea at the correct position */
+ white-space: nowrap;
+ overflow: hidden;
+ resize: none;
+}
+
+.xterm .composition-view {
+ /* TODO: Composition position got messed up somewhere */
+ background: #000;
+ color: #FFF;
+ display: none;
+ position: absolute;
+ white-space: nowrap;
+ z-index: 1;
+}
+
+.xterm .composition-view.active {
+ display: block;
+}
+
+.xterm .xterm-viewport {
+ /* On OS X this is required in order for the scroll bar to appear fully opaque */
+ background-color: #000;
+ overflow-y: scroll;
+ cursor: default;
+ position: absolute;
+ right: 0;
+ left: 0;
+ top: 0;
+ bottom: 0;
+}
+
+.xterm .xterm-screen {
+ position: relative;
+}
+
+.xterm .xterm-screen canvas {
+ position: absolute;
+ left: 0;
+ top: 0;
+}
+
+.xterm .xterm-scroll-area {
+ visibility: hidden;
+}
+
+.xterm-char-measure-element {
+ display: inline-block;
+ visibility: hidden;
+ position: absolute;
+ top: 0;
+ left: -9999em;
+ line-height: normal;
+}
+
+.xterm {
+ cursor: text;
+}
+
+.xterm.enable-mouse-events {
+ /* When mouse events are enabled (eg. tmux), revert to the standard pointer cursor */
+ cursor: default;
+}
+
+.xterm.xterm-cursor-pointer {
+ cursor: pointer;
+}
+
+.xterm.column-select.focus {
+ /* Column selection mode */
+ cursor: crosshair;
+}
+
+.xterm .xterm-accessibility,
+.xterm .xterm-message {
+ position: absolute;
+ left: 0;
+ top: 0;
+ bottom: 0;
+ right: 0;
+ z-index: 100;
+ color: transparent;
+}
+
+.xterm .live-region {
+ position: absolute;
+ left: -9999px;
+ width: 1px;
+ height: 1px;
+ overflow: hidden;
+}
+
+.xterm-dim {
+ opacity: 0.5;
+}
+
+.xterm-underline {
+ text-decoration: underline;
+}
+
+/*----*/
+
+@font-face {
+ font-family: "monospace-fallback";
+ src: url(../fonts/Meslo.otf) format("opentype");
+}
+
.xterm-viewport::-webkit-scrollbar {
background: rgba(0, 0, 0, .125);
}
diff --git a/terminus-terminal/src/frontends/xtermFrontend.ts b/terminus-terminal/src/frontends/xtermFrontend.ts
index 107607db..f4cb499d 100644
--- a/terminus-terminal/src/frontends/xtermFrontend.ts
+++ b/terminus-terminal/src/frontends/xtermFrontend.ts
@@ -1,52 +1,120 @@
-import { Frontend } from './frontend'
-import { Terminal, ITheme } from '@terminus-term/xterm'
-import * as fit from '@terminus-term/xterm/src/addons/fit/fit'
-import * as ligatures from 'xterm-addon-ligatures-tmp'
-import '@terminus-term/xterm/lib/xterm.css'
+import { Frontend, SearchOptions } from './frontend'
+import { Terminal, ITheme } from 'xterm'
+import { getCSSFontFamily } from '../utils'
+import { FitAddon } from 'xterm-addon-fit'
+import { enableLigatures } from 'xterm-addon-ligatures'
+import { SearchAddon } from 'xterm-addon-search'
+import { WebglAddon } from 'xterm-addon-webgl'
import './xterm.css'
-import deepEqual = require('deep-equal')
+import deepEqual from 'deep-equal'
+import { Attributes } from 'xterm/src/common/buffer/Constants'
+import { AttributeData } from 'xterm/src/common/buffer/AttributeData'
+import { CellData } from 'xterm/src/common/buffer/CellData'
-Terminal.applyAddon(fit)
-Terminal.applyAddon(ligatures)
+const COLOR_NAMES = [
+ 'black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white',
+ 'brightBlack', 'brightRed', 'brightGreen', 'brightYellow', 'brightBlue', 'brightMagenta', 'brightCyan', 'brightWhite',
+]
+/** @hidden */
export class XTermFrontend extends Frontend {
enableResizing = true
xterm: Terminal
+ xtermCore: any
+ enableWebGL = false
private configuredFontSize = 0
private zoom = 0
- private resizeHandler: any
+ private resizeHandler: () => void
private configuredTheme: ITheme = {}
private copyOnSelect = false
+ private search = new SearchAddon()
+ private fitAddon = new FitAddon()
+ private opened = false
constructor () {
super()
this.xterm = new Terminal({
allowTransparency: true,
- enableBold: true,
})
+ this.xtermCore = (this.xterm as any)._core
- this.xterm.on('data', data => {
+ this.xterm.onData(data => {
this.input.next(data)
})
- this.xterm.on('resize', ({ cols, rows }) => {
+ this.xterm.onResize(({ cols, rows }) => {
this.resize.next({ rows, columns: cols })
})
- this.xterm.on('title', title => {
+ this.xterm.onTitleChange(title => {
this.title.next(title)
})
- this.xterm.on('selection', () => {
+ this.xterm.onSelectionChange(() => {
if (this.copyOnSelect) {
this.copySelection()
}
})
+ this.xterm.loadAddon(this.fitAddon)
+
+ const keyboardEventHandler = (name: string, event: KeyboardEvent) => {
+ this.hotkeysService.pushKeystroke(name, event)
+ let ret = true
+ if (this.hotkeysService.getCurrentPartiallyMatchedHotkeys().length !== 0) {
+ event.stopPropagation()
+ event.preventDefault()
+ ret = false
+ }
+ this.hotkeysService.processKeystrokes()
+ this.hotkeysService.emitKeyEvent(event)
+
+ return ret
+ }
+
+ this.xterm.attachCustomKeyEventHandler((event: KeyboardEvent) => {
+ if (event.getModifierState('Meta') && event.key.toLowerCase() === 'v') {
+ event.preventDefault()
+ return false
+ }
+ if (event.getModifierState('Meta') && event.key.startsWith('Arrow')) {
+ return false
+ }
+
+ return keyboardEventHandler('keydown', event)
+ })
+
+ this.xtermCore._scrollToBottom = this.xtermCore.scrollToBottom.bind(this.xtermCore)
+ this.xtermCore.scrollToBottom = () => null
+
+ this.resizeHandler = () => {
+ try {
+ this.fitAddon.fit()
+ } catch (e) {
+ // tends to throw when element wasn't shown yet
+ console.warn('Could not resize xterm', e)
+ }
+ }
+
+ this.xtermCore._keyUp = (e: KeyboardEvent) => {
+ this.xtermCore.updateCursorStyle(e)
+ keyboardEventHandler('keyup', e)
+ }
}
attach (host: HTMLElement): void {
this.xterm.open(host)
+ this.opened = true
+
+ if (this.enableWebGL) {
+ this.xterm.loadAddon(new WebglAddon())
+ }
+
+ if (this.configService.store.terminal.ligatures) {
+ enableLigatures(this.xterm)
+ }
+
this.ready.next(null)
this.ready.complete()
- this.resizeHandler = () => (this.xterm as any).fit()
+ this.xterm.loadAddon(this.search)
+
window.addEventListener('resize', this.resizeHandler)
this.resizeHandler()
@@ -57,9 +125,12 @@ export class XTermFrontend extends Frontend {
host.addEventListener('mousedown', event => this.mouseEvent.next(event as MouseEvent))
host.addEventListener('mouseup', event => this.mouseEvent.next(event as MouseEvent))
host.addEventListener('mousewheel', event => this.mouseEvent.next(event as MouseEvent))
+
+ const ro = new window['ResizeObserver'](() => this.resizeHandler())
+ ro.observe(host)
}
- detach (host: HTMLElement): void {
+ detach (_host: HTMLElement): void {
window.removeEventListener('resize', this.resizeHandler)
}
@@ -68,7 +139,10 @@ export class XTermFrontend extends Frontend {
}
copySelection (): void {
- (navigator as any).clipboard.writeText(this.getSelection())
+ require('electron').remote.clipboard.write({
+ text: this.getSelection(),
+ html: this.getSelectionAsHTML(),
+ })
}
clearSelection (): void {
@@ -88,49 +162,58 @@ export class XTermFrontend extends Frontend {
}
visualBell (): void {
- (this.xterm as any).bell()
+ this.xtermCore.bell()
}
scrollToBottom (): void {
- this.xterm.scrollToBottom()
+ this.xtermCore._scrollToBottom()
}
- configure (config: any): void {
- this.xterm.setOption('fontFamily', `"${config.terminal.font}", "monospace-fallback", monospace`)
+ configure (): void {
+ const config = this.configService.store
+
+ setImmediate(() => {
+ if (this.xterm.cols && this.xterm.rows && this.xtermCore.charMeasure) {
+ if (this.xtermCore.charMeasure) {
+ this.xtermCore.charMeasure.measure(this.xtermCore.options)
+ }
+ if (this.xtermCore.renderer) {
+ this.xtermCore.renderer._updateDimensions()
+ }
+ this.resizeHandler()
+ }
+ })
+
+ this.xterm.setOption('fontFamily', getCSSFontFamily(config.terminal.font))
this.xterm.setOption('bellStyle', config.terminal.bell)
this.xterm.setOption('cursorStyle', {
- beam: 'bar'
- }[config.terminal.cuxrsor] || config.terminal.cursor)
+ beam: 'bar',
+ }[config.terminal.cursor] || config.terminal.cursor)
this.xterm.setOption('cursorBlink', config.terminal.cursorBlink)
this.xterm.setOption('macOptionIsMeta', config.terminal.altIsMeta)
- // this.xterm.setOption('colors', )
+ this.xterm.setOption('scrollback', 100000)
this.configuredFontSize = config.terminal.fontSize
this.setFontSize()
this.copyOnSelect = config.terminal.copyOnSelect
- let theme: ITheme = {
+ const theme: ITheme = {
foreground: config.terminal.colorScheme.foreground,
- background: (config.terminal.background === 'colorScheme') ? config.terminal.colorScheme.background : 'transparent',
+ background: config.terminal.background === 'colorScheme' ? config.terminal.colorScheme.background : config.appearance.vibrancy ? 'transparent' : this.themesService.findCurrentTheme().terminalBackground,
cursor: config.terminal.colorScheme.cursor,
}
- const colorNames = [
- 'black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white',
- 'brightBlack', 'brightRed', 'brightGreen', 'brightYellow', 'brightBlue', 'brightMagenta', 'brightCyan', 'brightWhite'
- ]
-
- for (let i = 0; i < colorNames.length; i++) {
- theme[colorNames[i]] = config.terminal.colorScheme.colors[i]
+ for (let i = 0; i < COLOR_NAMES.length; i++) {
+ theme[COLOR_NAMES[i]] = config.terminal.colorScheme.colors[i]
}
- if (!deepEqual(this.configuredTheme, theme)) {
+ if (this.xtermCore._colorManager && !deepEqual(this.configuredTheme, theme)) {
this.xterm.setOption('theme', theme)
this.configuredTheme = theme
}
- if (config.terminal.ligatures && this.xterm.element) {
- (this.xterm as any).enableLigatures()
+ if (this.opened && config.terminal.ligatures) {
+ enableLigatures(this.xterm)
}
}
@@ -139,7 +222,74 @@ export class XTermFrontend extends Frontend {
this.setFontSize()
}
+ findNext (term: string, searchOptions?: SearchOptions): boolean {
+ return this.search.findNext(term, searchOptions)
+ }
+
+ findPrevious (term: string, searchOptions?: SearchOptions): boolean {
+ return this.search.findPrevious(term, searchOptions)
+ }
+
private setFontSize () {
this.xterm.setOption('fontSize', this.configuredFontSize * Math.pow(1.1, this.zoom))
+ this.resizeHandler()
+ }
+
+ private getSelectionAsHTML (): string {
+ let html = ``
+ const selection = this.xterm.getSelectionPosition()
+ if (!selection) {
+ return null
+ }
+ if (selection.startRow === selection.endRow) {
+ html += this.getLineAsHTML(selection.startRow, selection.startColumn, selection.endColumn)
+ } else {
+ html += this.getLineAsHTML(selection.startRow, selection.startColumn, this.xterm.cols)
+ for (let y = selection.startRow + 1; y < selection.endRow; y++) {
+ html += this.getLineAsHTML(y, 0, this.xterm.cols)
+ }
+ html += this.getLineAsHTML(selection.endRow, 0, selection.endColumn)
+ }
+ html += '
'
+ return html
+ }
+
+ private getHexColor (mode: number, color: number): string {
+ if (mode === Attributes.CM_RGB) {
+ const rgb = AttributeData.toColorRGB(color)
+ return rgb.map(x => x.toString(16).padStart(2, '0')).join('')
+ }
+ if (mode === Attributes.CM_P16 || mode === Attributes.CM_P256) {
+ return this.configService.store.terminal.colorScheme.colors[color]
+ }
+ return 'transparent'
+ }
+
+ private getLineAsHTML (y: number, start: number, end: number): string {
+ let html = ''
+ let lastStyle = null
+ const line = (this.xterm.buffer.getLine(y) as any)._line
+ const cell = new CellData()
+ for (let i = start; i < end; i++) {
+ line.loadCell(i, cell)
+ const fg = this.getHexColor(cell.getFgColorMode(), cell.getFgColor())
+ const bg = this.getHexColor(cell.getBgColorMode(), cell.getBgColor())
+ const style = `color: ${fg}; background: ${bg}; font-weight: ${cell.isBold() ? 'bold' : 'normal'}; font-style: ${cell.isItalic() ? 'italic' : 'normal'}; text-decoration: ${cell.isUnderline() ? 'underline' : 'none'}`
+ if (style !== lastStyle) {
+ if (lastStyle !== null) {
+ html += ''
+ }
+ html += ``
+ lastStyle = style
+ }
+ html += line.getString(i) || ' '
+ }
+ html += '
'
+ return html
}
}
+
+/** @hidden */
+export class XTermWebGLFrontend extends XTermFrontend {
+ enableWebGL = true
+}
diff --git a/terminus-terminal/src/hotkeys.ts b/terminus-terminal/src/hotkeys.ts
index 409a8f26..bb6b33c2 100644
--- a/terminus-terminal/src/hotkeys.ts
+++ b/terminus-terminal/src/hotkeys.ts
@@ -1,10 +1,12 @@
+import slug from 'slug'
import { Injectable } from '@angular/core'
-import { IHotkeyDescription, HotkeyProvider } from 'terminus-core'
+import { HotkeyDescription, HotkeyProvider } from 'terminus-core'
import { TerminalService } from './services/terminal.service'
+/** @hidden */
@Injectable()
export class TerminalHotkeyProvider extends HotkeyProvider {
- hotkeys: IHotkeyDescription[] = [
+ hotkeys: HotkeyDescription[] = [
{
id: 'copy',
name: 'Copy to clipboard',
@@ -61,17 +63,24 @@ export class TerminalHotkeyProvider extends HotkeyProvider {
id: 'ctrl-c',
name: 'Intelligent Ctrl-C (copy/abort)',
},
+ {
+ id: 'search',
+ name: 'Search',
+ },
]
constructor (
private terminal: TerminalService,
) { super() }
- async provide (): Promise {
- let shells = await this.terminal.shells$.toPromise()
- return this.hotkeys.concat(shells.map(shell => ({
- id: `shell.${shell.id}`,
- name: `New tab: ${shell.name}`
- })))
+ async provide (): Promise {
+ const profiles = await this.terminal.getProfiles()
+ return [
+ ...this.hotkeys,
+ ...profiles.map(profile => ({
+ id: `profile.${slug(profile.name).toLowerCase()}`,
+ name: `New tab: ${profile.name}`,
+ })),
+ ]
}
}
diff --git a/terminus-terminal/src/icons/clink.svg b/terminus-terminal/src/icons/clink.svg
new file mode 100644
index 00000000..b6b04d5d
--- /dev/null
+++ b/terminus-terminal/src/icons/clink.svg
@@ -0,0 +1 @@
+
diff --git a/terminus-terminal/src/icons/cmd.svg b/terminus-terminal/src/icons/cmd.svg
new file mode 100644
index 00000000..5d954144
--- /dev/null
+++ b/terminus-terminal/src/icons/cmd.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/terminus-terminal/src/icons/cmder-powershell.svg b/terminus-terminal/src/icons/cmder-powershell.svg
new file mode 100644
index 00000000..1147deca
--- /dev/null
+++ b/terminus-terminal/src/icons/cmder-powershell.svg
@@ -0,0 +1 @@
+
diff --git a/terminus-terminal/src/icons/cmder.svg b/terminus-terminal/src/icons/cmder.svg
new file mode 100644
index 00000000..3c2fc656
--- /dev/null
+++ b/terminus-terminal/src/icons/cmder.svg
@@ -0,0 +1 @@
+
diff --git a/terminus-terminal/src/icons/cygwin.svg b/terminus-terminal/src/icons/cygwin.svg
new file mode 100644
index 00000000..bda71929
--- /dev/null
+++ b/terminus-terminal/src/icons/cygwin.svg
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/terminus-terminal/src/icons/git-bash.svg b/terminus-terminal/src/icons/git-bash.svg
new file mode 100644
index 00000000..3bb9db89
--- /dev/null
+++ b/terminus-terminal/src/icons/git-bash.svg
@@ -0,0 +1 @@
+
diff --git a/terminus-terminal/src/icons/plus.svg b/terminus-terminal/src/icons/plus.svg
index e4774d87..8abefac7 100644
--- a/terminus-terminal/src/icons/plus.svg
+++ b/terminus-terminal/src/icons/plus.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/terminus-terminal/src/icons/powershell-core.svg b/terminus-terminal/src/icons/powershell-core.svg
new file mode 100644
index 00000000..5ba9285d
--- /dev/null
+++ b/terminus-terminal/src/icons/powershell-core.svg
@@ -0,0 +1 @@
+
diff --git a/terminus-terminal/src/icons/powershell.svg b/terminus-terminal/src/icons/powershell.svg
new file mode 100644
index 00000000..8d2a74ed
--- /dev/null
+++ b/terminus-terminal/src/icons/powershell.svg
@@ -0,0 +1 @@
+
diff --git a/terminus-terminal/src/icons/profiles.svg b/terminus-terminal/src/icons/profiles.svg
new file mode 100644
index 00000000..1f9b929e
--- /dev/null
+++ b/terminus-terminal/src/icons/profiles.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/terminus-terminal/src/index.ts b/terminus-terminal/src/index.ts
index 3def0646..8edb51d6 100644
--- a/terminus-terminal/src/index.ts
+++ b/terminus-terminal/src/index.ts
@@ -1,36 +1,42 @@
import * as fs from 'mz/fs'
+import slug from 'slug'
import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { FormsModule } from '@angular/forms'
import { NgbModule } from '@ng-bootstrap/ng-bootstrap'
import { ToastrModule } from 'ngx-toastr'
-import TerminusCorePlugin from 'terminus-core'
-import { HostAppService } from 'terminus-core'
-import { ToolbarButtonProvider, TabRecoveryProvider, ConfigProvider, HotkeysService, HotkeyProvider, AppService, ConfigService } from 'terminus-core'
+import TerminusCorePlugin, { HostAppService, ToolbarButtonProvider, TabRecoveryProvider, ConfigProvider, HotkeysService, HotkeyProvider, AppService, ConfigService, TabContextMenuItemProvider } from 'terminus-core'
import { SettingsTabProvider } from 'terminus-settings'
import { AppearanceSettingsTabComponent } from './components/appearanceSettingsTab.component'
-import { ShellSettingsTabComponent } from './components/shellSettingsTab.component'
import { TerminalTabComponent } from './components/terminalTab.component'
+import { ShellSettingsTabComponent } from './components/shellSettingsTab.component'
import { TerminalSettingsTabComponent } from './components/terminalSettingsTab.component'
import { ColorPickerComponent } from './components/colorPicker.component'
+import { EditProfileModalComponent } from './components/editProfileModal.component'
+import { EnvironmentEditorComponent } from './components/environmentEditor.component'
+import { SearchPanelComponent } from './components/searchPanel.component'
-import { SessionsService, BaseSession } from './services/sessions.service'
+import { BaseSession } from './services/sessions.service'
import { TerminalFrontendService } from './services/terminalFrontend.service'
import { TerminalService } from './services/terminal.service'
+import { DockMenuService } from './services/dockMenu.service'
-import { ScreenPersistenceProvider } from './persistence/screen'
-import { TMuxPersistenceProvider } from './persistence/tmux'
import { ButtonProvider } from './buttonProvider'
import { RecoveryProvider } from './recoveryProvider'
-import { SessionPersistenceProvider, TerminalColorSchemeProvider, TerminalDecorator, ShellProvider } from './api'
+import { TerminalDecorator } from './api/decorator'
+import { TerminalContextMenuItemProvider } from './api/contextMenuProvider'
+import { TerminalColorSchemeProvider } from './api/colorSchemeProvider'
+import { ShellProvider } from './api/shellProvider'
import { TerminalSettingsTabProvider, AppearanceSettingsTabProvider, ShellSettingsTabProvider } from './settings'
import { PathDropDecorator } from './pathDrop'
import { TerminalConfigProvider } from './config'
import { TerminalHotkeyProvider } from './hotkeys'
import { HyperColorSchemes } from './colorSchemes'
+import { NewTabContextMenu, CopyPasteContextMenu } from './contextMenu'
+import { SaveAsProfileContextMenu } from './tabContextMenu'
import { CmderShellProvider } from './shells/cmder'
import { CustomShellProvider } from './shells/custom'
@@ -45,8 +51,12 @@ import { WindowsDefaultShellProvider } from './shells/winDefault'
import { WindowsStockShellsProvider } from './shells/windowsStock'
import { WSLShellProvider } from './shells/wsl'
-import { hterm } from './hterm'
+import { hterm } from './frontends/hterm'
+import { Frontend } from './frontends/frontend'
+import { HTermFrontend } from './frontends/htermFrontend'
+import { XTermFrontend, XTermWebGLFrontend } from './frontends/xtermFrontend'
+/** @hidden */
@NgModule({
imports: [
BrowserModule,
@@ -56,10 +66,6 @@ import { hterm } from './hterm'
TerminusCorePlugin,
],
providers: [
- SessionsService,
- TerminalFrontendService,
- TerminalService,
-
{ provide: SettingsTabProvider, useClass: AppearanceSettingsTabProvider, multi: true },
{ provide: SettingsTabProvider, useClass: ShellSettingsTabProvider, multi: true },
{ provide: SettingsTabProvider, useClass: TerminalSettingsTabProvider, multi: true },
@@ -71,32 +77,35 @@ import { hterm } from './hterm'
{ provide: TerminalColorSchemeProvider, useClass: HyperColorSchemes, multi: true },
{ provide: TerminalDecorator, useClass: PathDropDecorator, multi: true },
- { provide: SessionPersistenceProvider, useClass: ScreenPersistenceProvider, multi: true },
- { provide: SessionPersistenceProvider, useClass: TMuxPersistenceProvider, multi: true },
-
{ provide: ShellProvider, useClass: WindowsDefaultShellProvider, multi: true },
{ provide: ShellProvider, useClass: MacOSDefaultShellProvider, multi: true },
{ provide: ShellProvider, useClass: LinuxDefaultShellProvider, multi: true },
{ provide: ShellProvider, useClass: WindowsStockShellsProvider, multi: true },
+ { provide: ShellProvider, useClass: PowerShellCoreShellProvider, multi: true },
{ provide: ShellProvider, useClass: CmderShellProvider, multi: true },
{ provide: ShellProvider, useClass: CustomShellProvider, multi: true },
{ provide: ShellProvider, useClass: Cygwin32ShellProvider, multi: true },
{ provide: ShellProvider, useClass: Cygwin64ShellProvider, multi: true },
{ provide: ShellProvider, useClass: GitBashShellProvider, multi: true },
{ provide: ShellProvider, useClass: POSIXShellsProvider, multi: true },
- { provide: ShellProvider, useClass: PowerShellCoreShellProvider, multi: true },
{ provide: ShellProvider, useClass: WSLShellProvider, multi: true },
+ { provide: TerminalContextMenuItemProvider, useClass: NewTabContextMenu, multi: true },
+ { provide: TerminalContextMenuItemProvider, useClass: CopyPasteContextMenu, multi: true },
+
+ { provide: TabContextMenuItemProvider, useClass: SaveAsProfileContextMenu, multi: true },
+
// For WindowsDefaultShellProvider
PowerShellCoreShellProvider,
WSLShellProvider,
- WindowsStockShellsProvider
+ WindowsStockShellsProvider,
],
entryComponents: [
TerminalTabComponent,
AppearanceSettingsTabComponent,
ShellSettingsTabComponent,
TerminalSettingsTabComponent,
+ EditProfileModalComponent,
],
declarations: [
ColorPickerComponent,
@@ -104,17 +113,25 @@ import { hterm } from './hterm'
AppearanceSettingsTabComponent,
ShellSettingsTabComponent,
TerminalSettingsTabComponent,
+ EditProfileModalComponent,
+ EnvironmentEditorComponent,
+ SearchPanelComponent,
+ ],
+ exports: [
+ ColorPickerComponent,
+ EnvironmentEditorComponent,
],
})
-export default class TerminalModule {
+export default class TerminalModule { // eslint-disable-line @typescript-eslint/no-extraneous-class
constructor (
app: AppService,
config: ConfigService,
hotkeys: HotkeysService,
terminal: TerminalService,
hostApp: HostAppService,
+ dockMenu: DockMenuService,
) {
- let events = [
+ const events = [
{
name: 'keydown',
htermHandler: 'onKeyDown_',
@@ -125,7 +142,7 @@ export default class TerminalModule {
},
]
events.forEach((event) => {
- let oldHandler = hterm.hterm.Keyboard.prototype[event.htermHandler]
+ const oldHandler = hterm.hterm.Keyboard.prototype[event.htermHandler]
hterm.hterm.Keyboard.prototype[event.htermHandler] = function (nativeEvent) {
hotkeys.pushKeystroke(event.name, nativeEvent)
if (hotkeys.getCurrentPartiallyMatchedHotkeys().length === 0) {
@@ -151,14 +168,15 @@ export default class TerminalModule {
if (hotkey === 'new-window') {
hostApp.newWindow()
}
- if (hotkey.startsWith('shell.')) {
- let shells = await terminal.shells$.toPromise()
- let shell = shells.find(x => x.id === hotkey.split('.')[1])
- if (shell) {
- terminal.openTab(shell)
+ if (hotkey.startsWith('profile.')) {
+ const profiles = await terminal.getProfiles()
+ const profile = profiles.find(x => slug(x.name).toLowerCase() === hotkey.split('.')[1])
+ if (profile) {
+ terminal.openTabWithOptions(profile.sessionOptions)
}
}
})
+
hostApp.cliOpenDirectory$.subscribe(async directory => {
if (await fs.exists(directory)) {
if ((await fs.stat(directory)).isDirectory()) {
@@ -167,22 +185,43 @@ export default class TerminalModule {
}
}
})
+
hostApp.cliRunCommand$.subscribe(async command => {
terminal.openTab({
- id: '',
- command: command[0],
- args: command.slice(1),
+ name: '',
+ sessionOptions: {
+ command: command[0],
+ args: command.slice(1),
+ },
}, null, true)
hostApp.bringToFront()
})
+
hostApp.cliPaste$.subscribe(text => {
if (app.activeTab instanceof TerminalTabComponent && app.activeTab.session) {
- (app.activeTab as TerminalTabComponent).sendInput(text)
+ app.activeTab.sendInput(text)
hostApp.bringToFront()
}
})
+
+ hostApp.cliOpenProfile$.subscribe(async profileName => {
+ const profile = config.store.terminal.profiles.find(x => x.name === profileName)
+ if (!profile) {
+ console.error('Requested profile', profileName, 'not found')
+ return
+ }
+ terminal.openTabWithOptions(profile.sessionOptions)
+ hostApp.bringToFront()
+ })
+
+ dockMenu.update()
}
}
-export { TerminalService, BaseSession, TerminalTabComponent, TerminalFrontendService }
-export * from './api'
+export { TerminalService, BaseSession, TerminalTabComponent, TerminalFrontendService, TerminalDecorator, TerminalContextMenuItemProvider, TerminalColorSchemeProvider, ShellProvider }
+export { Frontend, XTermFrontend, XTermWebGLFrontend, HTermFrontend }
+export { BaseTerminalTabComponent } from './api/baseTerminalTab.component'
+export * from './api/interfaces'
+
+// Deprecations
+export { TerminalColorScheme as ITerminalColorScheme, Shell as IShell } from './api/interfaces'
diff --git a/terminus-terminal/src/pathDrop.ts b/terminus-terminal/src/pathDrop.ts
index 88b98f49..e3405edb 100644
--- a/terminus-terminal/src/pathDrop.ts
+++ b/terminus-terminal/src/pathDrop.ts
@@ -1,8 +1,9 @@
import { Subscription } from 'rxjs'
import { Injectable } from '@angular/core'
-import { TerminalDecorator } from './api'
+import { TerminalDecorator } from './api/decorator'
import { TerminalTabComponent } from './components/terminalTab.component'
+/** @hidden */
@Injectable()
export class PathDropDecorator extends TerminalDecorator {
private subscriptions: Subscription[] = []
@@ -14,7 +15,7 @@ export class PathDropDecorator extends TerminalDecorator {
event.preventDefault()
}),
terminal.frontend.drop$.subscribe(event => {
- for (let file of event.dataTransfer.files as any) {
+ for (const file of event.dataTransfer.files as any) {
this.injectPath(terminal, file.path)
}
event.preventDefault()
@@ -24,14 +25,15 @@ export class PathDropDecorator extends TerminalDecorator {
}
injectPath (terminal: TerminalTabComponent, path: string) {
- if (path.indexOf(' ') >= 0) {
+ if (path.includes(' ')) {
path = `"${path}"`
}
+ path = path.replace(/\\/g, '\\\\')
terminal.sendInput(path + ' ')
}
- detach (terminal: TerminalTabComponent): void {
- for (let s of this.subscriptions) {
+ detach (_terminal: TerminalTabComponent): void {
+ for (const s of this.subscriptions) {
s.unsubscribe()
}
}
diff --git a/terminus-terminal/src/persistence/screen.ts b/terminus-terminal/src/persistence/screen.ts
deleted file mode 100644
index 8f904d5f..00000000
--- a/terminus-terminal/src/persistence/screen.ts
+++ /dev/null
@@ -1,142 +0,0 @@
-import * as fs from 'mz/fs'
-import * as path from 'path'
-import { exec, spawn } from 'mz/child_process'
-import { exec as execAsync, execFileSync } from 'child_process'
-
-import { AsyncSubject } from 'rxjs'
-import { Injectable } from '@angular/core'
-import { Logger, LogService, ElectronService } from 'terminus-core'
-import { SessionOptions, SessionPersistenceProvider } from '../api'
-
-declare function delay (ms: number): Promise
-
-interface IChildProcess {
- pid: number
- ppid: number
- command: string
-}
-
-async function listProcesses (): Promise {
- return (await exec(`ps -A -o pid,ppid,command`))[0].toString()
- .split('\n')
- .slice(1)
- .map(line => line.split(' ').filter(x => x).slice(0, 3))
- .map(([pid, ppid, command]) => {
- return {
- pid: parseInt(pid), ppid: parseInt(ppid), command
- }
- })
-}
-
-@Injectable()
-export class ScreenPersistenceProvider extends SessionPersistenceProvider {
- id = 'screen'
- displayName = 'GNU Screen'
- private logger: Logger
-
- constructor (
- log: LogService,
- private electron: ElectronService,
- ) {
- super()
- this.logger = log.create('main')
- }
-
- isAvailable () {
- try {
- execFileSync('sh', ['-c', 'which screen'])
- return true
- } catch (_) {
- return false
- }
- }
-
- async attachSession (recoveryId: any): Promise {
- let lines = await new Promise(resolve => {
- execAsync('screen -list', (_err, stdout) => {
- // returns an error code on macOS
- resolve(stdout.split('\n'))
- })
- })
- let screenPID = lines
- .filter(line => line.indexOf('.' + recoveryId) !== -1)
- .map(line => parseInt(line.trim().split('.')[0]))[0]
-
- if (!screenPID) {
- return null
- }
-
- let truePID$ = new AsyncSubject()
-
- this.extractShellPID(screenPID).then(pid => {
- truePID$.next(pid)
- truePID$.complete()
- })
-
- return {
- recoveryId,
- recoveredTruePID$: truePID$.asObservable(),
- command: 'screen',
- args: ['-d', '-r', recoveryId, '-c', await this.prepareConfig()],
- }
- }
-
- async extractShellPID (screenPID: number): Promise {
- let processes = await listProcesses()
- let child = processes.find(x => x.ppid === screenPID)
-
- if (!child) {
- throw new Error(`Could not find any children of the screen process (PID ${screenPID})!`)
- }
-
- if (child.command === 'login') {
- await delay(1000)
- child = processes.find(x => x.ppid === child.pid)
- }
-
- return child.pid
- }
-
- async startSession (options: SessionOptions): Promise {
- let recoveryId = `term-tab-${Date.now()}`
- let args = ['-d', '-m', '-c', await this.prepareConfig(), '-U', '-S', recoveryId, '-T', 'xterm-256color', '--', '-' + options.command].concat(options.args || [])
- this.logger.debug('Spawning screen with', args.join(' '))
- await spawn('screen', args, {
- cwd: options.cwd,
- env: options.env || process.env,
- })
- return recoveryId
- }
-
- async terminateSession (recoveryId: string): Promise {
- try {
- await exec(`screen -S ${recoveryId} -X quit`)
- } catch (_) {
- // screen has already quit
- }
- }
-
- private async prepareConfig (): Promise {
- let configPath = path.join(this.electron.app.getPath('userData'), 'screen-config.tmp')
- await fs.writeFile(configPath, `
- escape ^^^
- vbell off
- deflogin on
- defflow off
- term xterm-color
- bindkey "^[OH" beginning-of-line
- bindkey "^[OF" end-of-line
- bindkey "^[[H" beginning-of-line
- bindkey "^[[F" end-of-line
- bindkey "\\027[?1049h" stuff ----alternate enter-----
- bindkey "\\027[?1049l" stuff ----alternate leave-----
- termcapinfo xterm* 'hs:ts=\\E]0;:fs=\\007:ds=\\E]0;\\007'
- defhstatus "^Et"
- hardstatus off
- altscreen on
- defutf8 on
- defencoding utf8
- `, 'utf-8')
- return configPath
- }
-}
diff --git a/terminus-terminal/src/persistence/tmux.ts b/terminus-terminal/src/persistence/tmux.ts
deleted file mode 100644
index 2b55706f..00000000
--- a/terminus-terminal/src/persistence/tmux.ts
+++ /dev/null
@@ -1,248 +0,0 @@
-import { Injectable } from '@angular/core'
-import { execFileSync } from 'child_process'
-import AsyncLock = require('async-lock')
-import { ConnectableObservable, AsyncSubject, Subject } from 'rxjs'
-import { first, publish } from 'rxjs/operators'
-import * as childProcess from 'child_process'
-
-import { Logger } from 'terminus-core'
-import { SessionOptions, SessionPersistenceProvider } from '../api'
-
-declare function delay (ms: number): Promise
-
-const TMUX_CONFIG = `
- set -g status off
- set -g focus-events on
- set -g bell-action any
- set -g bell-on-alert on
- set -g visual-bell off
- set -g set-titles on
- set -g set-titles-string "#W"
- set -g window-status-format '#I:#(pwd="#{pane_current_path}"; echo \${pwd####*/})#F'
- set -g window-status-current-format '#I:#(pwd="#{pane_current_path}"; echo \${pwd####*/})#F'
- set-option -g prefix C-^
- set-option -g status-interval 1
-`
-
-export class TMuxBlock {
- time: number
- number: number
- error: boolean
- lines: string[]
-
- constructor (line: string) {
- this.time = parseInt(line.split(' ')[1])
- this.number = parseInt(line.split(' ')[2])
- this.lines = []
- }
-}
-
-export class TMuxMessage {
- type: string
- content: string
-
- constructor (line: string) {
- this.type = line.substring(0, line.indexOf(' '))
- this.content = line.substring(line.indexOf(' ') + 1)
- }
-}
-
-export class TMuxCommandProcess {
- private process: childProcess.ChildProcess
- private rawOutput$ = new Subject()
- private line$ = new Subject()
- private message$ = new Subject()
- private block$ = new Subject()
- private response$: ConnectableObservable
- private lock = new AsyncLock({ timeout: 1000 })
- private logger = new Logger(null, 'tmuxProcess')
-
- constructor () {
- this.process = childProcess.spawn('tmux', ['-C', '-f', '/dev/null', '-L', 'terminus', 'new-session', '-A', '-D', '-s', 'control'])
- this.logger.log('started')
- this.process.stdout.on('data', data => {
- // console.debug('tmux says:', data.toString())
- this.rawOutput$.next(data.toString())
- })
-
- let rawBuffer = ''
- this.rawOutput$.subscribe(raw => {
- rawBuffer += raw
- if (rawBuffer.includes('\n')) {
- let lines = rawBuffer.split('\n')
- rawBuffer = lines.pop()
- lines.forEach(line => this.line$.next(line))
- }
- })
-
- let currentBlock = null
- this.line$.subscribe(line => {
- if (currentBlock) {
- if (line.startsWith('%end ')) {
- let block = currentBlock
- currentBlock = null
- setImmediate(() => {
- this.block$.next(block)
- })
- } else if (line.startsWith('%error ')) {
- let block = currentBlock
- block.error = true
- currentBlock = null
- setImmediate(() => {
- this.block$.next(block)
- })
- } else {
- currentBlock.lines.push(line)
- }
- } else {
- if (line.startsWith('%begin ')) {
- currentBlock = new TMuxBlock(line)
- } else {
- this.message$.next(line)
- }
- }
- })
-
- this.response$ = this.block$.asObservable().pipe(publish()) as ConnectableObservable
- this.response$.connect()
-
- this.block$.subscribe(block => {
- this.logger.debug('block:', block)
- })
-
- this.message$.subscribe(message => {
- this.logger.debug('message:', message)
- })
- }
-
- command (command: string): Promise {
- return this.lock.acquire('key', () => {
- let p = this.response$.pipe(first()).toPromise()
- this.logger.debug('command:', command)
- this.process.stdin.write(command + '\n')
- return p
- }).then(response => {
- if (response.error) {
- throw response
- }
- return response
- }) as Promise
- }
-
- destroy () {
- this.rawOutput$.complete()
- this.line$.complete()
- this.block$.complete()
- this.message$.complete()
- this.process.kill('SIGTERM')
- }
-}
-
-export class TMux {
- private process: TMuxCommandProcess
- private ready: Promise
- private logger = new Logger(null, 'tmux')
-
- constructor () {
- this.process = new TMuxCommandProcess()
- this.ready = (async () => {
- for (let line of TMUX_CONFIG.split('\n')) {
- if (line) {
- try {
- await this.process.command(line)
- } catch (e) {
- this.logger.warn('Skipping failing config line:', line)
- }
- }
- }
- // Tmux sometimes sends a stray response block at start
- await delay(500)
- })()
- }
-
- async create (id: string, options: SessionOptions): Promise {
- await this.ready
- let args = [options.command].concat(options.args.slice(1))
- let cmd = args.map(x => `"${x.replace('"', '\\"')}"`).join(' ')
- await this.process.command(
- `new-session -s "${id}" -d`
- + (options.cwd ? ` -c '${options.cwd.replace("'", "\\'")}'` : '')
- + ` '${cmd}'`
- )
- }
-
- async list (): Promise {
- await this.ready
- let block = await this.process.command('list-sessions -F "#{session_name}"')
- return block.lines
- }
-
- async getPID (id: string): Promise {
- await this.ready
- let response = await this.process.command(`list-panes -t ${id} -F "#{pane_pid}"`)
- if (response.lines.length === 0) {
- return null
- } else {
- return parseInt(response.lines[0])
- }
- }
-
- async terminate (id: string): Promise {
- await this.ready
- this.process.command(`kill-session -t ${id}`).catch(() => {
- console.debug('Session already killed')
- })
- }
-}
-
-@Injectable()
-export class TMuxPersistenceProvider extends SessionPersistenceProvider {
- id = 'tmux'
- displayName = 'Tmux'
- private tmux: TMux
-
- constructor () {
- super()
- if (this.isAvailable()) {
- this.tmux = new TMux()
- }
- }
-
- isAvailable (): boolean {
- try {
- execFileSync('tmux', ['-V'])
- return true
- } catch (_) {
- return false
- }
- }
-
- async attachSession (recoveryId: any): Promise {
- let sessions = await this.tmux.list()
- if (!sessions.includes(recoveryId)) {
- return null
- }
- let truePID$ = new AsyncSubject()
- this.tmux.getPID(recoveryId).then(pid => {
- truePID$.next(pid)
- truePID$.complete()
- })
- return {
- command: 'tmux',
- args: ['-L', 'terminus', 'attach-session', '-d', '-t', recoveryId, ';', 'refresh-client'],
- recoveredTruePID$: truePID$.asObservable(),
- recoveryId,
- }
- }
-
- async startSession (options: SessionOptions): Promise {
- // TODO env
- let recoveryId = Date.now().toString()
- await this.tmux.create(recoveryId, options)
- return recoveryId
- }
-
- async terminateSession (recoveryId: string): Promise {
- await this.tmux.terminate(recoveryId)
- }
-}
diff --git a/terminus-terminal/src/recoveryProvider.ts b/terminus-terminal/src/recoveryProvider.ts
index e141bbaf..a9a061b1 100644
--- a/terminus-terminal/src/recoveryProvider.ts
+++ b/terminus-terminal/src/recoveryProvider.ts
@@ -2,25 +2,15 @@ import { Injectable } from '@angular/core'
import { TabRecoveryProvider, RecoveredTab } from 'terminus-core'
import { TerminalTabComponent } from './components/terminalTab.component'
-import { SessionsService } from './services/sessions.service'
+/** @hidden */
@Injectable()
export class RecoveryProvider extends TabRecoveryProvider {
- constructor (
- private sessions: SessionsService,
- ) {
- super()
- }
-
async recover (recoveryToken: any): Promise {
- if (recoveryToken.type === 'app:terminal') {
- let sessionOptions = await this.sessions.recover(recoveryToken.recoveryId)
- if (!sessionOptions) {
- return null
- }
+ if (recoveryToken && recoveryToken.type === 'app:terminal-tab') {
return {
type: TerminalTabComponent,
- options: { sessionOptions },
+ options: { sessionOptions: recoveryToken.sessionOptions },
}
}
return null
diff --git a/terminus-terminal/src/services/dockMenu.service.ts b/terminus-terminal/src/services/dockMenu.service.ts
new file mode 100644
index 00000000..b1ac1528
--- /dev/null
+++ b/terminus-terminal/src/services/dockMenu.service.ts
@@ -0,0 +1,46 @@
+import { NgZone, Injectable } from '@angular/core'
+import { ElectronService, ConfigService, HostAppService, Platform } from 'terminus-core'
+import { TerminalService } from './terminal.service'
+
+/** @hidden */
+@Injectable({ providedIn: 'root' })
+export class DockMenuService {
+ appVersion: string
+
+ constructor (
+ private electron: ElectronService,
+ private config: ConfigService,
+ private hostApp: HostAppService,
+ private zone: NgZone,
+ private terminalService: TerminalService,
+ ) {
+ config.changed$.subscribe(() => this.update())
+ }
+
+ update () {
+ if (this.hostApp.platform === Platform.Windows) {
+ this.electron.app.setJumpList(this.config.store.terminal.profiles.length ? [{
+ type: 'custom',
+ name: 'Profiles',
+ items: this.config.store.terminal.profiles.map(profile => ({
+ type: 'task',
+ program: process.execPath,
+ args: `profile "${profile.name}"`,
+ title: profile.name,
+ iconPath: process.execPath,
+ iconIndex: 0,
+ })),
+ }] : null)
+ }
+ if (this.hostApp.platform === Platform.macOS) {
+ this.electron.app.dock.setMenu(this.electron.Menu.buildFromTemplate(
+ this.config.store.terminal.profiles.map(profile => ({
+ label: profile.name,
+ click: () => this.zone.run(() => {
+ this.terminalService.openTabWithOptions(profile.sessionOptions)
+ }),
+ }))
+ ))
+ }
+ }
+}
diff --git a/terminus-terminal/src/services/sessions.service.ts b/terminus-terminal/src/services/sessions.service.ts
index 8e925578..f8a4ec1a 100644
--- a/terminus-terminal/src/services/sessions.service.ts
+++ b/terminus-terminal/src/services/sessions.service.ts
@@ -1,35 +1,43 @@
-import psNode = require('ps-node')
-let nodePTY
+import * as psNode from 'ps-node'
import * as fs from 'mz/fs'
+import * as os from 'os'
+import * as nodePTY from 'node-pty'
+
import { Observable, Subject } from 'rxjs'
import { first } from 'rxjs/operators'
-import { Injectable, Inject } from '@angular/core'
+import { Injectable } from '@angular/core'
import { Logger, LogService, ConfigService } from 'terminus-core'
import { exec } from 'mz/child_process'
+import { SessionOptions } from '../api/interfaces'
+import { WIN_BUILD_CONPTY_SUPPORTED, isWindowsBuild } from '../utils'
-import { SessionOptions, SessionPersistenceProvider } from '../api'
+/* eslint-disable block-scoped-var */
-let macOSNativeProcessList
try {
- macOSNativeProcessList = require('macos-native-processlist')
-} catch (e) { } // tslint:disable-line
+ var macOSNativeProcessList = require('macos-native-processlist') // eslint-disable-line @typescript-eslint/no-var-requires
+} catch { }
-let windowsProcessTree
try {
- windowsProcessTree = require('windows-process-tree')
-} catch (e) {
-} // tslint:disable-line
+ var windowsProcessTree = require('@terminus-term/windows-process-tree') // eslint-disable-line @typescript-eslint/no-var-requires
+} catch { }
-export interface IChildProcess {
+export interface ChildProcess {
pid: number
ppid: number
command: string
}
+const windowsDirectoryRegex = /([a-zA-Z]:[^\:\[\]\?\"\<\>\|]+)/mi
+const OSC1337Prefix = '\x1b]1337;'
+const OSC1337Suffix = '\x07'
+
+/**
+ * A session object for a [[BaseTerminalTabComponent]]
+ * Extend this to implement custom I/O and process management for your terminal tab
+ */
export abstract class BaseSession {
open: boolean
name: string
- recoveryId: string
truePID: number
protected output = new Subject()
protected closed = new Subject()
@@ -55,14 +63,6 @@ export abstract class BaseSession {
this.initialDataBuffer = null
}
- abstract start (options: SessionOptions)
- abstract resize (columns, rows)
- abstract write (data)
- abstract kill (signal?: string)
- abstract async getChildProcesses (): Promise
- abstract async gracefullyKillProcess (): Promise
- abstract async getWorkingDirectory (): Promise
-
async destroy (): Promise {
if (this.open) {
this.open = false
@@ -72,24 +72,40 @@ export abstract class BaseSession {
await this.gracefullyKillProcess()
}
}
+
+ abstract start (options: SessionOptions): void
+ abstract resize (columns: number, rows: number): void
+ abstract write (data: string): void
+ abstract kill (signal?: string): void
+ abstract async getChildProcesses (): Promise
+ abstract async gracefullyKillProcess (): Promise
+ abstract async getWorkingDirectory (): Promise
}
+/** @hidden */
export class Session extends BaseSession {
private pty: any
private pauseAfterExit = false
+ private guessedCWD: string
+ private reportedCWD: string
+
+ constructor (private config: ConfigService) {
+ super()
+ }
start (options: SessionOptions) {
this.name = options.name
- this.recoveryId = options.recoveryId
- let env = {
+ const env = {
...process.env,
TERM: 'xterm-256color',
+ TERM_PROGRAM: 'Terminus',
...options.env,
+ ...this.config.store.terminal.environment || {},
}
if (process.platform === 'darwin' && !process.env.LC_ALL) {
- let locale = process.env.LC_CTYPE || 'en_US.UTF-8'
+ const locale = process.env.LC_CTYPE || 'en_US.UTF-8'
Object.assign(env, {
LANG: locale,
LC_ALL: locale,
@@ -99,21 +115,27 @@ export class Session extends BaseSession {
LC_MONETARY: locale,
})
}
+
+ let cwd = options.cwd || process.env.HOME
+
+ if (!fs.existsSync(cwd)) {
+ console.warn('Ignoring non-existent CWD:', cwd)
+ cwd = null
+ }
+
this.pty = nodePTY.spawn(options.command, options.args || [], {
name: 'xterm-256color',
cols: options.width || 80,
rows: options.height || 30,
- cwd: options.cwd || process.env.HOME,
+ cwd,
env: env,
+ // `1` instead of `true` forces ConPTY even if unstable
+ experimentalUseConpty: (isWindowsBuild(WIN_BUILD_CONPTY_SUPPORTED) && this.config.store.terminal.useConPTY ? 1 : false) as any,
})
- if (options.recoveredTruePID$) {
- options.recoveredTruePID$.subscribe(pid => {
- this.truePID = pid
- })
- } else {
- this.truePID = (this.pty as any).pid
- }
+ this.guessedCWD = cwd
+
+ this.truePID = this.pty['pid']
setTimeout(async () => {
// Retrieve any possible single children now that shell has fully started
@@ -127,11 +149,14 @@ export class Session extends BaseSession {
this.open = true
this.pty.on('data-buffered', data => {
+ data = this.processOSC1337(data)
this.emitOutput(data)
+ if (process.platform === 'win32') {
+ this.guessWindowsCWD(data)
+ }
})
this.pty.on('exit', () => {
- console.log('session exit')
if (this.pauseAfterExit) {
return
} else if (this.open) {
@@ -140,7 +165,6 @@ export class Session extends BaseSession {
})
this.pty.on('close', () => {
- console.log('session close')
if (this.pauseAfterExit) {
this.emitOutput('\r\nPress any key to close\r\n')
} else if (this.open) {
@@ -151,6 +175,24 @@ export class Session extends BaseSession {
this.pauseAfterExit = options.pauseAfterExit
}
+ processOSC1337 (data: string) {
+ if (data.includes(OSC1337Prefix)) {
+ const preData = data.substring(0, data.indexOf(OSC1337Prefix))
+ let params = data.substring(data.indexOf(OSC1337Prefix) + OSC1337Prefix.length)
+ const postData = params.substring(params.indexOf(OSC1337Suffix) + OSC1337Suffix.length)
+ params = params.substring(0, params.indexOf(OSC1337Suffix))
+
+ if (params.startsWith('CurrentDir=')) {
+ this.reportedCWD = params.split('=')[1]
+ if (this.reportedCWD.startsWith('~')) {
+ this.reportedCWD = os.homedir() + this.reportedCWD.substring(1)
+ }
+ data = preData + postData
+ }
+ }
+ return data
+ }
+
resize (columns, rows) {
if (this.pty._writable) {
this.pty.resize(columns, rows)
@@ -171,12 +213,12 @@ export class Session extends BaseSession {
this.pty.kill(signal)
}
- async getChildProcesses (): Promise {
+ async getChildProcesses (): Promise {
if (!this.truePID) {
return []
}
if (process.platform === 'darwin') {
- let processes = await macOSNativeProcessList.getProcessList()
+ const processes = await macOSNativeProcessList.getProcessList()
return processes.filter(x => x.ppid === this.truePID).map(p => ({
pid: p.pid,
ppid: p.ppid,
@@ -184,7 +226,7 @@ export class Session extends BaseSession {
}))
}
if (process.platform === 'win32') {
- return await new Promise(resolve => {
+ return new Promise(resolve => {
windowsProcessTree.getProcessTree(this.truePID, tree => {
resolve(tree ? tree.children.map(child => ({
pid: child.pid,
@@ -194,12 +236,12 @@ export class Session extends BaseSession {
})
})
}
- return new Promise((resolve, reject) => {
+ return new Promise((resolve, reject) => {
psNode.lookup({ ppid: this.truePID }, (err, processes) => {
if (err) {
return reject(err)
}
- resolve(processes as IChildProcess[])
+ resolve(processes as ChildProcess[])
})
})
}
@@ -227,6 +269,9 @@ export class Session extends BaseSession {
}
async getWorkingDirectory (): Promise {
+ if (this.reportedCWD) {
+ return this.reportedCWD
+ }
if (!this.truePID) {
return null
}
@@ -244,65 +289,52 @@ export class Session extends BaseSession {
}
}
if (process.platform === 'linux') {
- return await fs.readlink(`/proc/${this.truePID}/cwd`)
+ return fs.readlink(`/proc/${this.truePID}/cwd`)
+ }
+ if (process.platform === 'win32') {
+ if (!this.guessedCWD) {
+ return null
+ }
+ try {
+ await fs.access(this.guessedCWD)
+ } catch (e) {
+ return null
+ }
+ return this.guessedCWD
}
return null
}
+
+ private guessWindowsCWD (data: string) {
+ const match = windowsDirectoryRegex.exec(data)
+ if (match) {
+ this.guessedCWD = match[0]
+ }
+ }
}
-@Injectable()
+/** @hidden */
+@Injectable({ providedIn: 'root' })
export class SessionsService {
sessions: {[id: string]: BaseSession} = {}
logger: Logger
private lastID = 0
constructor (
- @Inject(SessionPersistenceProvider) private persistenceProviders: SessionPersistenceProvider[],
- private config: ConfigService,
log: LogService,
) {
- nodePTY = require('node-pty-tmp')
- nodePTY = require('../bufferizedPTY')(nodePTY)
+ require('../bufferizedPTY')(nodePTY)
this.logger = log.create('sessions')
- this.persistenceProviders = this.config.enabledServices(this.persistenceProviders).filter(x => x.isAvailable())
- }
-
- async prepareNewSession (options: SessionOptions): Promise {
- let persistence = this.getPersistence()
- if (persistence) {
- let recoveryId = await persistence.startSession(options)
- options = await persistence.attachSession(recoveryId)
- }
- return options
}
addSession (session: BaseSession, options: SessionOptions) {
this.lastID++
options.name = `session-${this.lastID}`
session.start(options)
- let persistence = this.getPersistence()
session.destroyed$.pipe(first()).subscribe(() => {
delete this.sessions[session.name]
- if (persistence) {
- persistence.terminateSession(session.recoveryId)
- }
})
this.sessions[session.name] = session
return session
}
-
- async recover (recoveryId: string): Promise {
- let persistence = this.getPersistence()
- if (persistence) {
- return await persistence.attachSession(recoveryId)
- }
- return null
- }
-
- private getPersistence (): SessionPersistenceProvider {
- if (!this.config.store.terminal.persistence) {
- return null
- }
- return this.persistenceProviders.find(x => x.id === this.config.store.terminal.persistence) || null
- }
}
diff --git a/terminus-terminal/src/services/terminal.service.ts b/terminus-terminal/src/services/terminal.service.ts
index 10e179f7..ee551822 100644
--- a/terminus-terminal/src/services/terminal.service.ts
+++ b/terminus-terminal/src/services/terminal.service.ts
@@ -1,21 +1,28 @@
+import * as fs from 'mz/fs'
+import slug from 'slug'
import { Observable, AsyncSubject } from 'rxjs'
import { Injectable, Inject } from '@angular/core'
-import { AppService, Logger, LogService, ConfigService } from 'terminus-core'
-import { IShell, ShellProvider } from '../api'
-import { SessionsService } from './sessions.service'
+import { AppService, Logger, LogService, ConfigService, SplitTabComponent } from 'terminus-core'
+import { ShellProvider } from '../api/shellProvider'
+import { Shell, SessionOptions, Profile } from '../api/interfaces'
import { TerminalTabComponent } from '../components/terminalTab.component'
+import { UACService } from './uac.service'
-@Injectable()
+@Injectable({ providedIn: 'root' })
export class TerminalService {
- private shells = new AsyncSubject()
+ private shells = new AsyncSubject()
private logger: Logger
- get shells$ (): Observable { return this.shells }
+ /**
+ * A fresh list of all available shells
+ */
+ get shells$ (): Observable { return this.shells }
+ /** @hidden */
constructor (
private app: AppService,
- private sessions: SessionsService,
private config: ConfigService,
+ private uac: UACService,
@Inject(ShellProvider) private shellProviders: ShellProvider[],
log: LogService,
) {
@@ -27,47 +34,94 @@ export class TerminalService {
})
}
- async getShells (): Promise {
- let shellLists = await Promise.all(this.config.enabledServices(this.shellProviders).map(x => x.provide()))
- return shellLists.reduce((a, b) => a.concat(b), [])
+ async getProfiles (includeHidden?: boolean): Promise {
+ const shells = await this.shells$.toPromise()
+ return [
+ ...this.config.store.terminal.profiles,
+ ...shells.filter(x => includeHidden || !x.hidden).map(shell => ({
+ name: shell.name,
+ icon: shell.icon,
+ sessionOptions: this.optionsFromShell(shell),
+ isBuiltin: true,
+ })),
+ ]
}
- async reloadShells () {
- this.shells = new AsyncSubject()
- let shells = await this.getShells()
- this.logger.debug('Shells list:', shells)
- this.shells.next(shells)
- this.shells.complete()
- }
+ /**
+ * Launches a new terminal with a specific shell and CWD
+ * @param pause Wait for a keypress when the shell exits
+ */
+ async openTab (profile?: Profile, cwd?: string, pause?: boolean): Promise {
+ if (!profile) {
+ const profiles = await this.getProfiles(true)
+ profile = profiles.find(x => slug(x.name).toLowerCase() === this.config.store.terminal.profile) || profiles[0]
+ }
+
+ cwd = cwd || profile.sessionOptions.cwd
+
+ if (cwd && !fs.existsSync(cwd)) {
+ console.warn('Ignoring non-existent CWD:', cwd)
+ cwd = null
+ }
- async openTab (shell?: IShell, cwd?: string, pause?: boolean): Promise {
if (!cwd) {
if (this.app.activeTab instanceof TerminalTabComponent && this.app.activeTab.session) {
cwd = await this.app.activeTab.session.getWorkingDirectory()
}
+ if (this.app.activeTab instanceof SplitTabComponent) {
+ const focusedTab = this.app.activeTab.getFocusedTab()
+
+ if (focusedTab instanceof TerminalTabComponent && focusedTab.session) {
+ cwd = await focusedTab.session.getWorkingDirectory()
+ }
+ }
cwd = cwd || this.config.store.terminal.workingDirectory
cwd = cwd || null
}
- if (!shell) {
- let shells = await this.shells$.toPromise()
- shell = shells.find(x => x.id === this.config.store.terminal.shell) || shells[0]
- }
- let env: any = Object.assign({}, process.env, shell.env || {}, this.config.store.terminal.environment || {})
- this.logger.log(`Starting shell ${shell.name}`, shell)
- let sessionOptions = await this.sessions.prepareNewSession({
+ this.logger.info(`Starting profile ${profile.name}`, profile)
+ const sessionOptions = {
+ ...profile.sessionOptions,
+ pauseAfterExit: pause,
+ cwd,
+ }
+
+ return this.openTabWithOptions(sessionOptions)
+ }
+
+ optionsFromShell (shell: Shell): SessionOptions {
+ return {
command: shell.command,
args: shell.args || [],
- cwd,
- env,
- pauseAfterExit: pause,
- })
+ env: shell.env,
+ }
+ }
- this.logger.log('Using session options:', sessionOptions)
+ /**
+ * Open a terminal with custom session options
+ */
+ openTabWithOptions (sessionOptions: SessionOptions): TerminalTabComponent {
+ if (sessionOptions.runAsAdministrator && this.uac.isAvailable) {
+ sessionOptions = this.uac.patchSessionOptionsForUAC(sessionOptions)
+ }
+ this.logger.info('Using session options:', sessionOptions)
return this.app.openNewTab(
TerminalTabComponent,
- { sessionOptions, shell }
+ { sessionOptions }
) as TerminalTabComponent
}
+
+ private async getShells (): Promise {
+ const shellLists = await Promise.all(this.config.enabledServices(this.shellProviders).map(x => x.provide()))
+ return shellLists.reduce((a, b) => a.concat(b), [])
+ }
+
+ private async reloadShells () {
+ this.shells = new AsyncSubject()
+ const shells = await this.getShells()
+ this.logger.debug('Shells list:', shells)
+ this.shells.next(shells)
+ this.shells.complete()
+ }
}
diff --git a/terminus-terminal/src/services/terminalFrontend.service.ts b/terminus-terminal/src/services/terminalFrontend.service.ts
index 5978c30b..046995a0 100644
--- a/terminus-terminal/src/services/terminalFrontend.service.ts
+++ b/terminus-terminal/src/services/terminalFrontend.service.ts
@@ -1,23 +1,37 @@
import { Injectable } from '@angular/core'
-import { ConfigService } from 'terminus-core'
+import { ConfigService, ThemesService, HotkeysService } from 'terminus-core'
import { Frontend } from '../frontends/frontend'
import { HTermFrontend } from '../frontends/htermFrontend'
-import { XTermFrontend } from '../frontends/xtermFrontend'
+import { XTermFrontend, XTermWebGLFrontend } from '../frontends/xtermFrontend'
import { BaseSession } from '../services/sessions.service'
-@Injectable()
+@Injectable({ providedIn: 'root' })
export class TerminalFrontendService {
private containers = new WeakMap()
- constructor (private config: ConfigService) { }
+ /** @hidden */
+ constructor (
+ private config: ConfigService,
+ private themes: ThemesService,
+ private hotkeys: HotkeysService,
+ ) { }
- getFrontend (session: BaseSession): Frontend {
+ getFrontend (session?: BaseSession): Frontend {
+ if (!session) {
+ const frontend: Frontend = new {
+ xterm: XTermFrontend,
+ 'xterm-webgl': XTermWebGLFrontend,
+ hterm: HTermFrontend,
+ }[this.config.store.terminal.frontend]()
+ frontend.configService = this.config
+ frontend.themesService = this.themes
+ frontend.hotkeysService = this.hotkeys
+ return frontend
+ }
if (!this.containers.has(session)) {
this.containers.set(
session,
- (this.config.store.terminal.frontend === 'xterm')
- ? new XTermFrontend()
- : new HTermFrontend()
+ this.getFrontend(),
)
}
return this.containers.get(session)
diff --git a/terminus-terminal/src/services/uac.service.ts b/terminus-terminal/src/services/uac.service.ts
new file mode 100644
index 00000000..186fc141
--- /dev/null
+++ b/terminus-terminal/src/services/uac.service.ts
@@ -0,0 +1,42 @@
+import * as path from 'path'
+import { Injectable } from '@angular/core'
+import { ElectronService } from 'terminus-core'
+import { SessionOptions } from '../api/interfaces'
+
+import { WIN_BUILD_CONPTY_SUPPORTED, isWindowsBuild } from '../utils'
+
+/** @hidden */
+@Injectable({ providedIn: 'root' })
+export class UACService {
+ isAvailable = false
+
+ constructor (
+ private electron: ElectronService,
+ ) {
+ this.isAvailable = isWindowsBuild(WIN_BUILD_CONPTY_SUPPORTED)
+ }
+
+ patchSessionOptionsForUAC (sessionOptions: SessionOptions): SessionOptions {
+ let helperPath = path.join(
+ path.dirname(this.electron.app.getPath('exe')),
+ 'resources',
+ 'extras',
+ 'UAC.exe',
+ )
+
+ if (process.env.TERMINUS_DEV) {
+ helperPath = path.join(
+ path.dirname(this.electron.app.getPath('exe')),
+ '..', '..', '..',
+ 'extras',
+ 'UAC.exe',
+ )
+ }
+
+ const options = { ...sessionOptions }
+ options.args = [options.command, ...options.args]
+ options.command = helperPath
+ return options
+ }
+
+}
diff --git a/terminus-terminal/src/settings.ts b/terminus-terminal/src/settings.ts
index 3ce0606a..c485681f 100644
--- a/terminus-terminal/src/settings.ts
+++ b/terminus-terminal/src/settings.ts
@@ -5,9 +5,11 @@ import { AppearanceSettingsTabComponent } from './components/appearanceSettingsT
import { ShellSettingsTabComponent } from './components/shellSettingsTab.component'
import { TerminalSettingsTabComponent } from './components/terminalSettingsTab.component'
+/** @hidden */
@Injectable()
export class AppearanceSettingsTabProvider extends SettingsTabProvider {
id = 'terminal-appearance'
+ icon = 'palette'
title = 'Appearance'
getComponentType (): any {
@@ -15,9 +17,11 @@ export class AppearanceSettingsTabProvider extends SettingsTabProvider {
}
}
+/** @hidden */
@Injectable()
export class ShellSettingsTabProvider extends SettingsTabProvider {
id = 'terminal-shell'
+ icon = 'list-ul'
title = 'Shell'
getComponentType (): any {
@@ -25,9 +29,11 @@ export class ShellSettingsTabProvider extends SettingsTabProvider {
}
}
+/** @hidden */
@Injectable()
export class TerminalSettingsTabProvider extends SettingsTabProvider {
id = 'terminal'
+ icon = 'terminal'
title = 'Terminal'
getComponentType (): any {
diff --git a/terminus-terminal/src/shells/cmder.ts b/terminus-terminal/src/shells/cmder.ts
index eaa5bb56..b9b5dbb8 100644
--- a/terminus-terminal/src/shells/cmder.ts
+++ b/terminus-terminal/src/shells/cmder.ts
@@ -1,18 +1,22 @@
import * as path from 'path'
import { Injectable } from '@angular/core'
+import { DomSanitizer } from '@angular/platform-browser'
import { HostAppService, Platform } from 'terminus-core'
-import { ShellProvider, IShell } from '../api'
+import { ShellProvider } from '../api/shellProvider'
+import { Shell } from '../api/interfaces'
+/** @hidden */
@Injectable()
export class CmderShellProvider extends ShellProvider {
constructor (
+ private domSanitizer: DomSanitizer,
private hostApp: HostAppService,
) {
super()
}
- async provide (): Promise {
+ async provide (): Promise {
if (this.hostApp.platform !== Platform.Windows) {
return []
}
@@ -21,17 +25,36 @@ export class CmderShellProvider extends ShellProvider {
return []
}
- return [{
- id: 'cmder',
- name: 'Cmder',
- command: 'cmd.exe',
- args: [
- '/k',
- path.join(process.env.CMDER_ROOT, 'vendor', 'init.bat'),
- ],
- env: {
- TERM: 'cygwin',
- }
- }]
+ return [
+ {
+ id: 'cmder',
+ name: 'Cmder',
+ command: 'cmd.exe',
+ args: [
+ '/k',
+ path.join(process.env.CMDER_ROOT, 'vendor', 'init.bat'),
+ ],
+ icon: this.domSanitizer.bypassSecurityTrustHtml(require('../icons/cmder.svg')),
+ env: {
+ TERM: 'cygwin',
+ },
+ },
+ {
+ id: 'cmderps',
+ name: 'Cmder PowerShell',
+ command: 'powershell.exe',
+ args: [
+ '-ExecutionPolicy',
+ 'Bypass',
+ '-nologo',
+ '-noprofile',
+ '-noexit',
+ '-command',
+ `Invoke-Expression '. ''${path.join(process.env.CMDER_ROOT, 'vendor', 'profile.ps1')}'''`,
+ ],
+ icon: this.domSanitizer.bypassSecurityTrustHtml(require('../icons/cmder-powershell.svg')),
+ env: {},
+ },
+ ]
}
}
diff --git a/terminus-terminal/src/shells/custom.ts b/terminus-terminal/src/shells/custom.ts
index 223f1881..d1e29e6c 100644
--- a/terminus-terminal/src/shells/custom.ts
+++ b/terminus-terminal/src/shells/custom.ts
@@ -1,8 +1,10 @@
import { Injectable } from '@angular/core'
import { ConfigService } from 'terminus-core'
-import { ShellProvider, IShell } from '../api'
+import { ShellProvider } from '../api/shellProvider'
+import { Shell } from '../api/interfaces'
+/** @hidden */
@Injectable()
export class CustomShellProvider extends ShellProvider {
constructor (
@@ -11,13 +13,14 @@ export class CustomShellProvider extends ShellProvider {
super()
}
- async provide (): Promise {
- let args = this.config.store.terminal.customShell.split(' ')
+ async provide (): Promise {
+ const args = this.config.store.terminal.customShell.split(' ')
return [{
id: 'custom',
name: 'Custom shell',
command: args[0],
args: args.slice(1),
+ env: {},
}]
}
}
diff --git a/terminus-terminal/src/shells/cygwin32.ts b/terminus-terminal/src/shells/cygwin32.ts
index d51e6ec4..cebc72e2 100644
--- a/terminus-terminal/src/shells/cygwin32.ts
+++ b/terminus-terminal/src/shells/cygwin32.ts
@@ -1,24 +1,33 @@
import * as path from 'path'
import { Injectable } from '@angular/core'
-import { Registry } from 'rage-edit-tmp'
+import { DomSanitizer } from '@angular/platform-browser'
import { HostAppService, Platform } from 'terminus-core'
-import { ShellProvider, IShell } from '../api'
+import { ShellProvider } from '../api/shellProvider'
+import { Shell } from '../api/interfaces'
+/* eslint-disable block-scoped-var */
+
+try {
+ var wnr = require('windows-native-registry') // eslint-disable-line @typescript-eslint/no-var-requires
+} catch { }
+
+/** @hidden */
@Injectable()
export class Cygwin32ShellProvider extends ShellProvider {
constructor (
+ private domSanitizer: DomSanitizer,
private hostApp: HostAppService,
) {
super()
}
- async provide (): Promise {
+ async provide (): Promise {
if (this.hostApp.platform !== Platform.Windows) {
return []
}
- let cygwinPath = await Registry.get('HKLM\\Software\\WOW6432Node\\Cygwin\\setup', 'rootdir')
+ const cygwinPath = wnr.getRegistryValue(wnr.HK.LM, 'Software\\WOW6432Node\\Cygwin\\setup', 'rootdir')
if (!cygwinPath) {
return []
@@ -28,9 +37,10 @@ export class Cygwin32ShellProvider extends ShellProvider {
id: 'cygwin32',
name: 'Cygwin (32 bit)',
command: path.join(cygwinPath, 'bin', 'bash.exe'),
+ icon: this.domSanitizer.bypassSecurityTrustHtml(require('../icons/cygwin.svg')),
env: {
TERM: 'cygwin',
- }
+ },
}]
}
}
diff --git a/terminus-terminal/src/shells/cygwin64.ts b/terminus-terminal/src/shells/cygwin64.ts
index ce509265..d75dbc1a 100644
--- a/terminus-terminal/src/shells/cygwin64.ts
+++ b/terminus-terminal/src/shells/cygwin64.ts
@@ -1,24 +1,33 @@
import * as path from 'path'
import { Injectable } from '@angular/core'
-import { Registry } from 'rage-edit-tmp'
+import { DomSanitizer } from '@angular/platform-browser'
import { HostAppService, Platform } from 'terminus-core'
-import { ShellProvider, IShell } from '../api'
+import { ShellProvider } from '../api/shellProvider'
+import { Shell } from '../api/interfaces'
+/* eslint-disable block-scoped-var */
+
+try {
+ var wnr = require('windows-native-registry') // eslint-disable-line @typescript-eslint/no-var-requires
+} catch { }
+
+/** @hidden */
@Injectable()
export class Cygwin64ShellProvider extends ShellProvider {
constructor (
+ private domSanitizer: DomSanitizer,
private hostApp: HostAppService,
) {
super()
}
- async provide (): Promise {
+ async provide (): Promise {
if (this.hostApp.platform !== Platform.Windows) {
return []
}
- let cygwinPath = await Registry.get('HKLM\\Software\\Cygwin\\setup', 'rootdir')
+ const cygwinPath = wnr.getRegistryValue(wnr.HK.LM, 'Software\\Cygwin\\setup', 'rootdir')
if (!cygwinPath) {
return []
@@ -28,9 +37,10 @@ export class Cygwin64ShellProvider extends ShellProvider {
id: 'cygwin64',
name: 'Cygwin',
command: path.join(cygwinPath, 'bin', 'bash.exe'),
+ icon: this.domSanitizer.bypassSecurityTrustHtml(require('../icons/cygwin.svg')),
env: {
TERM: 'cygwin',
- }
+ },
}]
}
}
diff --git a/terminus-terminal/src/shells/gitBash.ts b/terminus-terminal/src/shells/gitBash.ts
index d8df08b8..f197bad1 100644
--- a/terminus-terminal/src/shells/gitBash.ts
+++ b/terminus-terminal/src/shells/gitBash.ts
@@ -1,27 +1,36 @@
import * as path from 'path'
import { Injectable } from '@angular/core'
-import { Registry } from 'rage-edit-tmp'
+import { DomSanitizer } from '@angular/platform-browser'
import { HostAppService, Platform } from 'terminus-core'
-import { ShellProvider, IShell } from '../api'
+import { ShellProvider } from '../api/shellProvider'
+import { Shell } from '../api/interfaces'
+/* eslint-disable block-scoped-var */
+
+try {
+ var wnr = require('windows-native-registry') // eslint-disable-line @typescript-eslint/no-var-requires
+} catch { }
+
+/** @hidden */
@Injectable()
export class GitBashShellProvider extends ShellProvider {
constructor (
+ private domSanitizer: DomSanitizer,
private hostApp: HostAppService,
) {
super()
}
- async provide (): Promise {
+ async provide (): Promise {
if (this.hostApp.platform !== Platform.Windows) {
return []
}
- let gitBashPath = await Registry.get('HKLM\\Software\\GitForWindows', 'InstallPath')
+ let gitBashPath = wnr.getRegistryValue(wnr.HK.LM, 'Software\\GitForWindows', 'InstallPath')
if (!gitBashPath) {
- gitBashPath = await Registry.get('HKCU\\Software\\GitForWindows', 'InstallPath')
+ gitBashPath = wnr.getRegistryValue(wnr.HK.CU, 'Software\\GitForWindows', 'InstallPath')
}
if (!gitBashPath) {
@@ -32,10 +41,11 @@ export class GitBashShellProvider extends ShellProvider {
id: 'git-bash',
name: 'Git-Bash',
command: path.join(gitBashPath, 'bin', 'bash.exe'),
- args: [ '--login', '-i' ],
+ args: ['--login', '-i'],
+ icon: this.domSanitizer.bypassSecurityTrustHtml(require('../icons/git-bash.svg')),
env: {
TERM: 'cygwin',
- }
+ },
}]
}
}
diff --git a/terminus-terminal/src/shells/linuxDefault.ts b/terminus-terminal/src/shells/linuxDefault.ts
index d55a78a2..903db827 100644
--- a/terminus-terminal/src/shells/linuxDefault.ts
+++ b/terminus-terminal/src/shells/linuxDefault.ts
@@ -2,8 +2,10 @@ import * as fs from 'mz/fs'
import { Injectable } from '@angular/core'
import { HostAppService, Platform, LogService, Logger } from 'terminus-core'
-import { ShellProvider, IShell } from '../api'
+import { ShellProvider } from '../api/shellProvider'
+import { Shell } from '../api/interfaces'
+/** @hidden */
@Injectable()
export class LinuxDefaultShellProvider extends ShellProvider {
private logger: Logger
@@ -16,18 +18,19 @@ export class LinuxDefaultShellProvider extends ShellProvider {
this.logger = log.create('linuxDefaultShell')
}
- async provide (): Promise