mirror of
https://github.com/Eugeny/tabby.git
synced 2025-06-08 13:30:02 +00:00
.
This commit is contained in:
parent
b7745bdd5b
commit
8beda026c1
2
Makefile
2
Makefile
@ -6,7 +6,7 @@ SHORT_VERSION=$(shell python -c 'import subprocess; v = subprocess.check_output(
|
|||||||
all: run
|
all: run
|
||||||
|
|
||||||
run:
|
run:
|
||||||
DEV=1 ./node_modules/.bin/electron ./app
|
DEV=1 ./node_modules/.bin/electron ./app --debug
|
||||||
|
|
||||||
lint:
|
lint:
|
||||||
tslint -c tslint.json app/src/*.ts app/src/**/*.ts
|
tslint -c tslint.json app/src/*.ts app/src/**/*.ts
|
||||||
|
@ -1,141 +0,0 @@
|
|||||||
@brand-primary: #f7e61d;
|
|
||||||
@brand-success: #5cb85c;
|
|
||||||
@brand-info: #5bc0de;
|
|
||||||
@brand-warning: #f0ad4e;
|
|
||||||
@brand-danger: #FF1C01;
|
|
||||||
|
|
||||||
// New
|
|
||||||
@brand-primary: #f7e61d;
|
|
||||||
@brand-success: #42B500;
|
|
||||||
@brand-info: #01BAEF;
|
|
||||||
@brand-warning: #DB8A00;
|
|
||||||
@brand-danger: #EF2F00;
|
|
||||||
|
|
||||||
|
|
||||||
@control-shadow: 0 1px 1px rgba(0,0,0,.25);
|
|
||||||
@control-shadow-active: 0 1px 1px rgba(0,0,0,.25) inset, @control-shadow;
|
|
||||||
@control-dropdown-shadow: 0 0 50px rgba(0,0,0,.5), @control-shadow;
|
|
||||||
@form-accent: #DBCA00;
|
|
||||||
@form-accent-bright: @brand-primary;
|
|
||||||
|
|
||||||
|
|
||||||
@body-bg: #1D272D;
|
|
||||||
@text-color: #aaa;
|
|
||||||
|
|
||||||
@font-family-sans-serif: "Source Sans Pro", "PT Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
|
|
||||||
@icon-font-path: "../fonts/";
|
|
||||||
@component-active-color: rgba(0,0,0,.15);
|
|
||||||
@component-active-color: darken(@component-active-bg, 30%);
|
|
||||||
@table-bg: #444;
|
|
||||||
@table-bg-accent: rgba(255,255,255,.15);
|
|
||||||
@table-bg-hover: #666;
|
|
||||||
@table-border-color: #2e2e2e;
|
|
||||||
@table-line-border-color: #4f4f4f;
|
|
||||||
|
|
||||||
@btn-default-color: @text-color;
|
|
||||||
@btn-default-bg: #243D49;
|
|
||||||
@btn-default-border: transparent;
|
|
||||||
@btn-primary-color: @component-active-color;
|
|
||||||
@btn-primary-border: #584E00;
|
|
||||||
@btn-danger-border: rgba(0,0,0,.5);
|
|
||||||
@btn-danger-color: white;
|
|
||||||
@btn-danger-bg: #FF4630;
|
|
||||||
@btn-danger-border: transparent;//@brand-danger;
|
|
||||||
@btn-link-disabled-color: darken(@text-color, 20%);
|
|
||||||
|
|
||||||
@input-bg: #11181C;
|
|
||||||
@input-bg-disabled: #2a2f31;
|
|
||||||
@input-color: #bbb;
|
|
||||||
@input-border: #3a3a3a;
|
|
||||||
@input-group-addon-border-color: @input-bg;
|
|
||||||
@input-color-placeholder: #777;
|
|
||||||
@input-group-addon-bg: @input-bg;
|
|
||||||
|
|
||||||
@dropdown-bg: rgba(64,64,64,.95); //@body-bg;
|
|
||||||
@dropdown-link-color: @text-color;
|
|
||||||
@dropdown-link-hover-color: #ddd;
|
|
||||||
@dropdown-link-hover-bg: #444;
|
|
||||||
@dropdown-link-disabled-color: darken(@text-color, 5%);
|
|
||||||
@navbar-default-bg: #23272A;
|
|
||||||
@navbar-default-border: #111;
|
|
||||||
|
|
||||||
|
|
||||||
@nav-tabs-border-color: #666;
|
|
||||||
@nav-tabs-link-hover-border-color: transparent;
|
|
||||||
|
|
||||||
@nav-tabs-active-link-hover-bg: rgba(255,255,255,.1);
|
|
||||||
@nav-tabs-active-link-hover-color: @brand-primary;
|
|
||||||
@nav-tabs-active-link-border-color: @brand-primary;
|
|
||||||
@nav-tabs-active-link-hover-border-color: @brand-primary;
|
|
||||||
|
|
||||||
|
|
||||||
@pagination-color: @btn-default-color;
|
|
||||||
@pagination-bg: @btn-default-bg;
|
|
||||||
@pagination-border: @btn-default-border;
|
|
||||||
|
|
||||||
@pagination-hover-color: @btn-default-color;
|
|
||||||
@pagination-hover-bg: lighten(@btn-default-bg, 5%);
|
|
||||||
@pagination-hover-border: @btn-default-border;
|
|
||||||
|
|
||||||
@pagination-active-color: @brand-primary;
|
|
||||||
@pagination-active-bg: darken(@btn-default-bg, 5%);
|
|
||||||
@pagination-active-border: @btn-default-border;
|
|
||||||
|
|
||||||
@pagination-disabled-color: @btn-link-disabled-color;
|
|
||||||
@pagination-disabled-bg: darken(@btn-default-bg, 5%);
|
|
||||||
@pagination-disabled-border: @btn-default-border;
|
|
||||||
//@state-success-bg: #234116; //#dff0d8;
|
|
||||||
//@state-info-bg: #0C3A50; //#d9edf7;
|
|
||||||
//@state-danger-bg: #9E3B3B;///#f2dede;
|
|
||||||
@popover-bg: rgba(64,64,64,.95);
|
|
||||||
@popover-arrow-color: #444;
|
|
||||||
@progress-bg: #555;
|
|
||||||
@list-group-bg: rgba(255,255,255,.1);
|
|
||||||
@list-group-disabled-bg: #333;
|
|
||||||
@list-group-border: transparent;
|
|
||||||
@list-group-line-border: rgba(255,255,255,.1);
|
|
||||||
@list-group-hover-bg: rgba(255,255,255,.2);
|
|
||||||
@list-group-link-color: @text-color;
|
|
||||||
@list-group-link-heading-color: @text-color;
|
|
||||||
@list-group-active-bg: rgba(255,255,255,.3);
|
|
||||||
@list-group-active-border: transparent;
|
|
||||||
|
|
||||||
|
|
||||||
@panel-bg: @table-bg;
|
|
||||||
@panel-inner-border: @table-border-color;
|
|
||||||
@panel-footer-bg: #666;
|
|
||||||
@panel-default-text: #ddd;
|
|
||||||
@panel-default-border: @table-border-color;
|
|
||||||
@panel-default-heading-bg: #666;
|
|
||||||
@well-bg: #222;
|
|
||||||
@badge-bg: #333;
|
|
||||||
@badge-active-bg: #333;
|
|
||||||
@code-bg: #222;
|
|
||||||
@pre-bg: #222;
|
|
||||||
@pre-color: #bbb;
|
|
||||||
@blockquote-border-color: #444;
|
|
||||||
@page-header-border-color: #444;
|
|
||||||
|
|
||||||
|
|
||||||
@alert-bg: #2A2A2A;
|
|
||||||
|
|
||||||
@state-success-text: @brand-success;
|
|
||||||
@state-success-bg: @alert-bg;
|
|
||||||
@state-success-border: @state-success-text;
|
|
||||||
|
|
||||||
@state-info-text: @brand-info;
|
|
||||||
@state-info-bg: @alert-bg;
|
|
||||||
@state-info-border: @state-info-text;
|
|
||||||
|
|
||||||
@state-warning-text: #F27208;
|
|
||||||
@state-warning-bg: @alert-bg;
|
|
||||||
@state-warning-border: @state-warning-text;
|
|
||||||
|
|
||||||
@state-danger-text: @brand-danger;
|
|
||||||
@state-danger-bg: @alert-bg;
|
|
||||||
@state-danger-border: @state-danger-text;
|
|
||||||
|
|
||||||
|
|
||||||
@border-radius-base: 1px;
|
|
||||||
@border-radius-large: 3px;
|
|
||||||
@border-radius-small: 1px;
|
|
47
app/defaultConfig.yaml
Normal file
47
app/defaultConfig.yaml
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
hotkeys:
|
||||||
|
new-tab:
|
||||||
|
- ['Ctrl-A', 'C']
|
||||||
|
- ['Ctrl-A', 'Ctrl-C']
|
||||||
|
- 'Ctrl-Shift-T'
|
||||||
|
close-tab:
|
||||||
|
- 'Ctrl-Shift-W'
|
||||||
|
- ['Ctrl-A', 'K']
|
||||||
|
toggle-last-tab:
|
||||||
|
- ['Ctrl-A', 'A']
|
||||||
|
- ['Ctrl-A', 'Ctrl-A']
|
||||||
|
next-tab:
|
||||||
|
- 'Ctrl-Shift-ArrowRight'
|
||||||
|
- ['Ctrl-A', 'N']
|
||||||
|
previous-tab:
|
||||||
|
- 'Ctrl-Shift-ArrowLeft'
|
||||||
|
- ['Ctrl-A', 'P']
|
||||||
|
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']
|
@ -10,5 +10,8 @@
|
|||||||
"electron-is-dev": "^0.1.2",
|
"electron-is-dev": "^0.1.2",
|
||||||
"path": "^0.12.7",
|
"path": "^0.12.7",
|
||||||
"pty.js": "https://github.com/Tyriar/pty.js/tarball/c75c2dcb6dcad83b0cb3ef2ae42d0448fb912642"
|
"pty.js": "https://github.com/Tyriar/pty.js/tarball/c75c2dcb6dcad83b0cb3ef2ae42d0448fb912642"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"js-yaml": "^3.8.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@ import { LogService } from 'services/log'
|
|||||||
import { HotkeysService } from 'services/hotkeys'
|
import { HotkeysService } from 'services/hotkeys'
|
||||||
import { ModalService } from 'services/modal'
|
import { ModalService } from 'services/modal'
|
||||||
import { NotifyService } from 'services/notify'
|
import { NotifyService } from 'services/notify'
|
||||||
|
import { PluginDispatcherService } from 'services/pluginDispatcher'
|
||||||
import { QuitterService } from 'services/quitter'
|
import { QuitterService } from 'services/quitter'
|
||||||
import { SessionsService } from 'services/sessions'
|
import { SessionsService } from 'services/sessions'
|
||||||
import { LocalStorageService } from 'angular2-localstorage/LocalStorageEmitter'
|
import { LocalStorageService } from 'angular2-localstorage/LocalStorageEmitter'
|
||||||
@ -42,6 +43,7 @@ import { TerminalComponent } from 'components/terminal'
|
|||||||
LogService,
|
LogService,
|
||||||
ModalService,
|
ModalService,
|
||||||
NotifyService,
|
NotifyService,
|
||||||
|
PluginDispatcherService,
|
||||||
QuitterService,
|
QuitterService,
|
||||||
SessionsService,
|
SessionsService,
|
||||||
LocalStorageService,
|
LocalStorageService,
|
||||||
@ -63,4 +65,8 @@ import { TerminalComponent } from 'components/terminal'
|
|||||||
AppComponent
|
AppComponent
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class AppModule {}
|
export class AppModule {
|
||||||
|
constructor (pluginDispatcher: PluginDispatcherService) {
|
||||||
|
pluginDispatcher.register(require('./plugin.hyperlinks').default)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
@import "~bootstrap/less/variables.less";
|
@import "~variables.less";
|
||||||
@import "~bootstrap/variables.less";
|
@import "~mixins.less";
|
||||||
|
|
||||||
|
|
||||||
:host {
|
:host {
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -17,20 +18,6 @@
|
|||||||
@tabs-height: 40px;
|
@tabs-height: 40px;
|
||||||
@tab-border-radius: 4px;
|
@tab-border-radius: 4px;
|
||||||
|
|
||||||
.button-states() {
|
|
||||||
transition: 0.125s all;
|
|
||||||
border: none;
|
|
||||||
background: transparent;
|
|
||||||
|
|
||||||
&:hover:not(.active) {
|
|
||||||
background: rgba(255, 255, 255, .033);
|
|
||||||
}
|
|
||||||
|
|
||||||
&:active:not(.active) {
|
|
||||||
background: rgba(0, 0, 0, .1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.titlebar {
|
.titlebar {
|
||||||
height: @titlebar-height;
|
height: @titlebar-height;
|
||||||
background: #141c23;
|
background: #141c23;
|
||||||
@ -50,8 +37,15 @@
|
|||||||
line-height: @titlebar-height - 2px;
|
line-height: @titlebar-height - 2px;
|
||||||
padding: 0 15px;
|
padding: 0 15px;
|
||||||
font-size: 8px;
|
font-size: 8px;
|
||||||
|
color: #444;
|
||||||
|
background: transparent;
|
||||||
|
transition: 0.25s all;
|
||||||
|
|
||||||
.button-states();
|
.button-states();
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,8 +132,11 @@
|
|||||||
|
|
||||||
border: none;
|
border: none;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
opacity: 0;
|
color: @text-color;
|
||||||
|
|
||||||
transition: 0.25s all;
|
transition: 0.25s all;
|
||||||
|
display: block;
|
||||||
|
opacity: 0;
|
||||||
|
|
||||||
@button-size: @tabs-height * 0.6;
|
@button-size: @tabs-height * 0.6;
|
||||||
width: @button-size;
|
width: @button-size;
|
||||||
@ -149,7 +146,6 @@
|
|||||||
margin-top: (@tabs-height - @button-size) * 0.4;
|
margin-top: (@tabs-height - @button-size) * 0.4;
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
|
|
||||||
display: block;
|
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
|
|
||||||
@ -163,6 +159,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&:hover button {
|
&:hover button {
|
||||||
|
transition: 0.25s opacity;
|
||||||
|
display: block;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -81,6 +81,12 @@ export class AppComponent {
|
|||||||
if (hotkey == 'new-tab') {
|
if (hotkey == 'new-tab') {
|
||||||
this.newTab()
|
this.newTab()
|
||||||
}
|
}
|
||||||
|
if (hotkey.startsWith('tab-')) {
|
||||||
|
let index = parseInt(hotkey.split('-')[1])
|
||||||
|
if (index <= this.tabs.length) {
|
||||||
|
this.selectTab(this.tabs[index - 1])
|
||||||
|
}
|
||||||
|
}
|
||||||
if (this.activeTab) {
|
if (this.activeTab) {
|
||||||
if (hotkey == 'close-tab') {
|
if (hotkey == 'close-tab') {
|
||||||
this.closeTab(this.activeTab)
|
this.closeTab(this.activeTab)
|
||||||
@ -137,7 +143,10 @@ export class AppComponent {
|
|||||||
}
|
}
|
||||||
this.activeTab = tab
|
this.activeTab = tab
|
||||||
setImmediate(() => {
|
setImmediate(() => {
|
||||||
this.elementRef.nativeElement.querySelector(':scope .tab.active iframe').focus()
|
let iframe = this.elementRef.nativeElement.querySelector(':scope .tab.active iframe')
|
||||||
|
if (iframe) {
|
||||||
|
iframe.focus()
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Component, Input, ChangeDetectionStrategy, trigger, style, animate, transition, state } from '@angular/core'
|
import { Component, Input, trigger, style, animate, transition } from '@angular/core'
|
||||||
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Component, ChangeDetectionStrategy, Input, trigger, style, animate, transition, state } from '@angular/core'
|
import { Component, Input, trigger, style, animate, transition, state } from '@angular/core'
|
||||||
import { HotkeysService, PartialHotkeyMatch } from 'services/hotkeys'
|
import { HotkeysService, PartialHotkeyMatch } from 'services/hotkeys'
|
||||||
|
|
||||||
|
|
||||||
@ -33,7 +33,7 @@ import { HotkeysService, PartialHotkeyMatch } from 'services/hotkeys'
|
|||||||
})
|
})
|
||||||
export class HotkeyHintComponent {
|
export class HotkeyHintComponent {
|
||||||
@Input() partialHotkeyMatches: PartialHotkeyMatch[]
|
@Input() partialHotkeyMatches: PartialHotkeyMatch[]
|
||||||
private keyTimeoutInterval: NodeJS.Timer = null
|
private keyTimeoutInterval: number = null
|
||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
public hotkeys: HotkeysService,
|
public hotkeys: HotkeysService,
|
||||||
|
@ -14,7 +14,7 @@ const INPUT_TIMEOUT = 2000
|
|||||||
export class HotkeyInputModalComponent {
|
export class HotkeyInputModalComponent {
|
||||||
private keySubscription: Subscription
|
private keySubscription: Subscription
|
||||||
private lastKeyEvent: number
|
private lastKeyEvent: number
|
||||||
private keyTimeoutInterval: NodeJS.Timer
|
private keyTimeoutInterval: number = null
|
||||||
|
|
||||||
@Input() value: string[] = []
|
@Input() value: string[] = []
|
||||||
@Input() timeoutProgress = 0
|
@Input() timeoutProgress = 0
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
:host {
|
:host {
|
||||||
|
overflow-y: auto;
|
||||||
|
|
||||||
>.modal-body {
|
>.modal-body {
|
||||||
padding: 0 0 20px !important;
|
padding: 0 0 20px !important;
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,13 @@
|
|||||||
ngb-tabset(type='tabs nav-justified')
|
ngb-tabset(type='tabs')
|
||||||
|
ngb-tab
|
||||||
|
template(ngbTabTitle)
|
||||||
|
| General
|
||||||
|
template(ngbTabContent)
|
||||||
|
.form-group
|
||||||
|
label Font
|
||||||
|
input.form-control(type='text', [ngbTypeahead]='fontAutocomplete', '[(ngModel)]'='font')
|
||||||
ngb-tab
|
ngb-tab
|
||||||
template(ngbTabTitle)
|
template(ngbTabTitle)
|
||||||
i.fa.fa-keyboard-o
|
|
||||||
| Hotkeys
|
| Hotkeys
|
||||||
template(ngbTabContent)
|
template(ngbTabContent)
|
||||||
.form-group
|
.form-group
|
||||||
|
@ -2,6 +2,11 @@ import { Component } from '@angular/core'
|
|||||||
import { ElectronService } from 'services/electron'
|
import { ElectronService } from 'services/electron'
|
||||||
import { HostAppService, PLATFORM_WINDOWS, PLATFORM_LINUX, PLATFORM_MAC } from 'services/hostApp'
|
import { HostAppService, PLATFORM_WINDOWS, PLATFORM_LINUX, PLATFORM_MAC } from 'services/hostApp'
|
||||||
import { ConfigService } from 'services/config'
|
import { ConfigService } from 'services/config'
|
||||||
|
import { Observable } from 'rxjs/Observable'
|
||||||
|
import 'rxjs/add/operator/map'
|
||||||
|
import 'rxjs/add/operator/debounceTime'
|
||||||
|
import 'rxjs/add/operator/distinctUntilChanged'
|
||||||
|
const childProcessPromise = nodeRequire('child-process-promise')
|
||||||
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@ -27,9 +32,29 @@ export class SettingsPaneComponent {
|
|||||||
isLinux: boolean
|
isLinux: boolean
|
||||||
year: number
|
year: number
|
||||||
version: string
|
version: string
|
||||||
|
fonts: string[] = []
|
||||||
|
|
||||||
globalHotkey = ['Ctrl+Shift+G']
|
globalHotkey = ['Ctrl+Shift+G']
|
||||||
|
|
||||||
|
ngOnInit () {
|
||||||
|
childProcessPromise.exec('fc-list :spacing=mono').then((result) => {
|
||||||
|
this.fonts = result.stdout
|
||||||
|
.split('\n')
|
||||||
|
.filter((x) => !!x)
|
||||||
|
.map((x) => x.split(':')[1].trim())
|
||||||
|
.map((x) => x.split(',')[0].trim())
|
||||||
|
this.fonts.sort()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fontAutocomplete = (text$: Observable<string>) => {
|
||||||
|
return text$
|
||||||
|
.debounceTime(200)
|
||||||
|
.distinctUntilChanged()
|
||||||
|
.map(query => this.fonts.filter(v => new RegExp(query, 'gi').test(v)))
|
||||||
|
.map(list => Array.from(new Set(list)))
|
||||||
|
}
|
||||||
|
|
||||||
ngOnDestroy() {
|
ngOnDestroy() {
|
||||||
this.config.save()
|
this.config.save()
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
import { Component, NgZone, Input, Output, EventEmitter, ElementRef } from '@angular/core'
|
import { Component, NgZone, Input, Output, EventEmitter, ElementRef } from '@angular/core'
|
||||||
import { ConfigService } from 'services/config'
|
import { ConfigService } from 'services/config'
|
||||||
|
import { PluginDispatcherService } from 'services/pluginDispatcher'
|
||||||
|
|
||||||
import { Session } from 'services/sessions'
|
import { Session } from 'services/sessions'
|
||||||
|
|
||||||
const hterm = require('hterm-commonjs')
|
const hterm = require('hterm-commonjs')
|
||||||
|
const dataurl = require('dataurl')
|
||||||
|
|
||||||
|
|
||||||
hterm.hterm.VT.ESC['k'] = function(parseState) {
|
hterm.hterm.VT.ESC['k'] = function(parseState) {
|
||||||
@ -21,7 +23,19 @@ hterm.hterm.VT.ESC['k'] = function(parseState) {
|
|||||||
|
|
||||||
hterm.hterm.defaultStorage = new hterm.lib.Storage.Memory()
|
hterm.hterm.defaultStorage = new hterm.lib.Storage.Memory()
|
||||||
const pmgr = new hterm.hterm.PreferenceManager('default')
|
const pmgr = new hterm.hterm.PreferenceManager('default')
|
||||||
pmgr.set('user-css', ``)
|
pmgr.set('user-css', dataurl.convert({
|
||||||
|
data: `
|
||||||
|
a {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
mimetype: 'text/css',
|
||||||
|
charset: 'utf8',
|
||||||
|
}))
|
||||||
pmgr.set('font-size', 12)
|
pmgr.set('font-size', 12)
|
||||||
pmgr.set('background-color', '#1D272D')
|
pmgr.set('background-color', '#1D272D')
|
||||||
pmgr.set('color-palette-overrides', {
|
pmgr.set('color-palette-overrides', {
|
||||||
@ -43,18 +57,20 @@ export class TerminalComponent {
|
|||||||
@Input() session: Session
|
@Input() session: Session
|
||||||
title: string
|
title: string
|
||||||
@Output() titleChange = new EventEmitter()
|
@Output() titleChange = new EventEmitter()
|
||||||
private terminal: any
|
terminal: any
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private zone: NgZone,
|
private zone: NgZone,
|
||||||
private elementRef: ElementRef,
|
private elementRef: ElementRef,
|
||||||
public config: ConfigService,
|
public config: ConfigService,
|
||||||
|
private pluginDispatcher: PluginDispatcherService,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit () {
|
ngOnInit () {
|
||||||
let io
|
let io
|
||||||
this.terminal = new hterm.hterm.Terminal()
|
this.terminal = new hterm.hterm.Terminal()
|
||||||
|
this.pluginDispatcher.emit('preTerminalInit', { terminal: this.terminal })
|
||||||
this.terminal.setWindowTitle = (title) => {
|
this.terminal.setWindowTitle = (title) => {
|
||||||
this.zone.run(() => {
|
this.zone.run(() => {
|
||||||
this.title = title
|
this.title = title
|
||||||
@ -83,6 +99,7 @@ export class TerminalComponent {
|
|||||||
this.session.releaseInitialDataBuffer()
|
this.session.releaseInitialDataBuffer()
|
||||||
}
|
}
|
||||||
this.terminal.decorate(this.elementRef.nativeElement)
|
this.terminal.decorate(this.elementRef.nativeElement)
|
||||||
|
this.pluginDispatcher.emit('postTerminalInit', { terminal: this.terminal })
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy () {
|
ngOnDestroy () {
|
||||||
|
@ -1,6 +1,3 @@
|
|||||||
import 'source-sans-pro'
|
import 'source-sans-pro'
|
||||||
|
|
||||||
import 'font-awesome/css/font-awesome.css'
|
import 'font-awesome/css/font-awesome.css'
|
||||||
|
|
||||||
import '../assets/toaster-custom.less'
|
import '../assets/toaster-custom.less'
|
||||||
import '../assets/bootstrap/bootstrap.less'
|
|
||||||
|
@ -1,5 +1,16 @@
|
|||||||
@import "~bootstrap/include.less";
|
@import "~variables.less";
|
||||||
|
@import "~mixins.less";
|
||||||
|
|
||||||
|
* {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
font-family: @font-family;
|
||||||
|
font-size: @font-size;
|
||||||
|
color: @text-color;
|
||||||
|
}
|
||||||
|
|
||||||
html.platform-win32 {
|
html.platform-win32 {
|
||||||
body.focused {
|
body.focused {
|
||||||
@ -85,25 +96,37 @@ ngb-modal-window.fade.in {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ngb-tabset {
|
ngb-tabset {
|
||||||
>ul.nav-tabs.nav-justified {
|
>ul.nav-tabs {
|
||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
background: rgba(0,0,0,.25);
|
background: rgba(0,0,0,.25);
|
||||||
|
display: flex;
|
||||||
|
align-items: start;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
|
||||||
.nav-item .nav-link {
|
.nav-item {
|
||||||
background: transparent;
|
flex: none;
|
||||||
border: none;
|
display: flex;
|
||||||
|
|
||||||
&.active {
|
.nav-link {
|
||||||
background: rgba(0,0,0,.5);
|
background: transparent;
|
||||||
border-bottom: 1px solid #777;
|
border: none;
|
||||||
}
|
padding: 10px 15px;
|
||||||
|
color: @text-color;
|
||||||
|
text-decoration: none;
|
||||||
|
|
||||||
i {
|
&.active {
|
||||||
display: block;
|
background: rgba(0,0,0,.5);
|
||||||
text-align: center;
|
border-bottom: 1px solid #777;
|
||||||
font-size: 18px;
|
}
|
||||||
margin: 0 0 5px;
|
|
||||||
|
i {
|
||||||
|
display: block;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 18px;
|
||||||
|
margin: 0 0 5px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -134,3 +157,21 @@ ngb-tabset {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ngb-typeahead-window {
|
||||||
|
max-height: 200px;
|
||||||
|
overflow-y: auto;
|
||||||
|
|
||||||
|
>button {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
border-bottom: 1px solid @dark-border;
|
||||||
|
.list-group-item-style();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-group-item {
|
||||||
|
.list-group-item-style();
|
||||||
|
}
|
||||||
|
24
app/src/mixins.less
Normal file
24
app/src/mixins.less
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
@import "~variables.less";
|
||||||
|
|
||||||
|
.button-states() {
|
||||||
|
transition: 0.125s all;
|
||||||
|
border: none;
|
||||||
|
|
||||||
|
&:hover:not(.active) {
|
||||||
|
background: rgba(255, 255, 255, .033);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active:not(.active),
|
||||||
|
&.active {
|
||||||
|
background: rgba(0, 0, 0, .1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-group-item-style() {
|
||||||
|
display: block;
|
||||||
|
padding: 10px 15px;
|
||||||
|
background: @component-bg;
|
||||||
|
color: @text-color;
|
||||||
|
text-align: left;
|
||||||
|
.button-states();
|
||||||
|
}
|
123
app/src/plugin.hyperlinks.ts
Normal file
123
app/src/plugin.hyperlinks.ts
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
import * as fs from 'fs'
|
||||||
|
import { ElectronService } from 'services/electron'
|
||||||
|
|
||||||
|
|
||||||
|
abstract class Handler {
|
||||||
|
constructor (protected plugin) { }
|
||||||
|
regex: string
|
||||||
|
convert (uri: string): string { return uri }
|
||||||
|
verify (_uri: string): boolean { return true }
|
||||||
|
abstract handle (uri: string): void
|
||||||
|
}
|
||||||
|
|
||||||
|
class URLHandler extends Handler {
|
||||||
|
regex = 'http(s)?://[^\\s;\'"]+[^.,;\\s]'
|
||||||
|
|
||||||
|
handle (uri: string) {
|
||||||
|
this.plugin.electron.shell.openExternal(uri)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class FileHandler extends Handler {
|
||||||
|
regex = '/[^\\s.,;\'"]+'
|
||||||
|
|
||||||
|
verify (uri: string) {
|
||||||
|
return fs.existsSync(uri)
|
||||||
|
}
|
||||||
|
|
||||||
|
handle (uri: string) {
|
||||||
|
this.plugin.electron.shell.openExternal('file://' + uri)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class HyperlinksPlugin {
|
||||||
|
handlers = []
|
||||||
|
handlerClasses = [
|
||||||
|
URLHandler,
|
||||||
|
FileHandler,
|
||||||
|
]
|
||||||
|
electron: ElectronService
|
||||||
|
|
||||||
|
constructor ({ electron }) {
|
||||||
|
this.electron = electron
|
||||||
|
this.handlers = this.handlerClasses.map((x) => new x(this))
|
||||||
|
}
|
||||||
|
|
||||||
|
preTerminalInit ({ terminal }) {
|
||||||
|
const oldInsertString = terminal.screen_.constructor.prototype.insertString
|
||||||
|
const oldDeleteChars = terminal.screen_.constructor.prototype.deleteChars
|
||||||
|
terminal.screen_.insertString = (...args) => {
|
||||||
|
let ret = oldInsertString.bind(terminal.screen_)(...args)
|
||||||
|
this.insertLinks(terminal.screen_)
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
terminal.screen_.deleteChars = (...args) => {
|
||||||
|
let ret = oldDeleteChars.bind(terminal.screen_)(...args)
|
||||||
|
this.insertLinks(terminal.screen_)
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
insertLinks (screen) {
|
||||||
|
const traverse = (element) => {
|
||||||
|
Array.from(element.childNodes).forEach((node) => {
|
||||||
|
if (node.nodeName == '#text') {
|
||||||
|
element.replaceChild(this.urlizeNode(node), node)
|
||||||
|
} else if (node.nodeName != 'A') {
|
||||||
|
traverse(node)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
screen.rowsArray.forEach((x) => traverse(x))
|
||||||
|
}
|
||||||
|
|
||||||
|
urlizeNode (node) {
|
||||||
|
let matches = []
|
||||||
|
this.handlers.forEach((handler) => {
|
||||||
|
let regex = new RegExp(handler.regex, 'gi')
|
||||||
|
let match
|
||||||
|
while (match = regex.exec(node.textContent)) {
|
||||||
|
let uri = handler.convert(match[0])
|
||||||
|
if (!handler.verify(uri)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
matches.push({
|
||||||
|
start: regex.lastIndex - match[0].length,
|
||||||
|
end: regex.lastIndex,
|
||||||
|
text: match[0],
|
||||||
|
uri,
|
||||||
|
handler
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (matches.length == 0) {
|
||||||
|
return node
|
||||||
|
}
|
||||||
|
|
||||||
|
matches.sort((a, b) => a.start < b.start ? -1 : 1)
|
||||||
|
|
||||||
|
let span = document.createElement('span')
|
||||||
|
let position = 0
|
||||||
|
matches.forEach((match) => {
|
||||||
|
if (match.start < position) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (match.start > position) {
|
||||||
|
span.appendChild(document.createTextNode(node.textContent.slice(position, match.start)))
|
||||||
|
}
|
||||||
|
|
||||||
|
let a = document.createElement('a')
|
||||||
|
a.textContent = match.text
|
||||||
|
a.addEventListener('click', () => {
|
||||||
|
match.handler.handle(match.uri)
|
||||||
|
})
|
||||||
|
span.appendChild(a)
|
||||||
|
|
||||||
|
position = match.end
|
||||||
|
})
|
||||||
|
span.appendChild(document.createTextNode(node.textContent.slice(position)))
|
||||||
|
return span
|
||||||
|
}
|
||||||
|
}
|
@ -1,40 +1,40 @@
|
|||||||
|
import * as yaml from 'js-yaml'
|
||||||
|
import * as path from 'path'
|
||||||
|
import * as fs from 'fs'
|
||||||
import { Injectable } from '@angular/core'
|
import { Injectable } from '@angular/core'
|
||||||
const Config = nodeRequire('electron-config')
|
import { ElectronService } from 'services/electron'
|
||||||
|
|
||||||
|
const defaultConfig : IConfigData = require('../../defaultConfig.yaml')
|
||||||
|
|
||||||
|
export interface IConfigData {
|
||||||
|
hotkeys?: any
|
||||||
|
}
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ConfigService {
|
export class ConfigService {
|
||||||
constructor() {
|
constructor (
|
||||||
this.config = new Config({name: 'config'})
|
electron: ElectronService
|
||||||
|
) {
|
||||||
|
this.path = path.join(electron.app.getPath('userData'), 'config.yaml')
|
||||||
this.load()
|
this.load()
|
||||||
}
|
}
|
||||||
|
|
||||||
private config: any
|
private path: string
|
||||||
private store: any
|
private store: IConfigData
|
||||||
|
|
||||||
set(key: string, value: any) {
|
load () {
|
||||||
this.store.set(key, value)
|
if (fs.existsSync(this.path)) {
|
||||||
this.save()
|
this.store = yaml.safeLoad(fs.readFileSync(this.path, 'utf8'))
|
||||||
|
} else {
|
||||||
|
this.store = {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
get(key: string): any {
|
save () {
|
||||||
return this.store[key]
|
fs.writeFileSync(this.path, yaml.safeDump(this.store), 'utf8')
|
||||||
}
|
}
|
||||||
|
|
||||||
has(key: string): boolean {
|
full () : IConfigData {
|
||||||
return this.store[key] != undefined
|
return Object.assign({}, defaultConfig, this.store)
|
||||||
}
|
|
||||||
|
|
||||||
delete(key: string) {
|
|
||||||
delete this.store[key]
|
|
||||||
this.save()
|
|
||||||
}
|
|
||||||
|
|
||||||
load() {
|
|
||||||
this.store = this.config.store
|
|
||||||
}
|
|
||||||
|
|
||||||
save() {
|
|
||||||
this.config.store = this.store
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,6 @@ const hterm = require('hterm-commonjs')
|
|||||||
export interface HotkeyDescription {
|
export interface HotkeyDescription {
|
||||||
id: string,
|
id: string,
|
||||||
name: string,
|
name: string,
|
||||||
defaults: string[][],
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PartialHotkeyMatch {
|
export interface PartialHotkeyMatch {
|
||||||
@ -21,27 +20,62 @@ const HOTKEYS: HotkeyDescription[] = [
|
|||||||
{
|
{
|
||||||
id: 'new-tab',
|
id: 'new-tab',
|
||||||
name: 'New tab',
|
name: 'New tab',
|
||||||
defaults: [['Ctrl+Shift+T'], ['Ctrl+A', 'C']],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'close-tab',
|
id: 'close-tab',
|
||||||
name: 'Close tab',
|
name: 'Close tab',
|
||||||
defaults: [['Ctrl+Shift+W'], ['Ctrl+A', 'K']],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'toggle-last-tab',
|
id: 'toggle-last-tab',
|
||||||
name: 'Toggle last tab',
|
name: 'Toggle last tab',
|
||||||
defaults: [['Ctrl+A', 'A'], ['Ctrl+A', 'Ctrl+A']],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'next-tab',
|
id: 'next-tab',
|
||||||
name: 'Next tab',
|
name: 'Next tab',
|
||||||
defaults: [['Ctrl+Shift-ArrowRight'], ['Ctrl+A', 'N']],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'previous-tab',
|
id: 'previous-tab',
|
||||||
name: 'Previous tab',
|
name: 'Previous tab',
|
||||||
defaults: [['Ctrl+Shift-ArrowLeft'], ['Ctrl+A', 'P']],
|
},
|
||||||
|
{
|
||||||
|
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',
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -86,10 +120,6 @@ export class HotkeysService {
|
|||||||
oldHandler.bind(this)(nativeEvent)
|
oldHandler.bind(this)(nativeEvent)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
if (!config.get('hotkeys')) {
|
|
||||||
config.set('hotkeys', {})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
emitNativeEvent (name, nativeEvent) {
|
emitNativeEvent (name, nativeEvent) {
|
||||||
@ -122,18 +152,21 @@ export class HotkeysService {
|
|||||||
|
|
||||||
registerHotkeys () {
|
registerHotkeys () {
|
||||||
this.electron.globalShortcut.unregisterAll()
|
this.electron.globalShortcut.unregisterAll()
|
||||||
this.electron.globalShortcut.register('`', () => {
|
// TODO
|
||||||
|
this.electron.globalShortcut.register('PrintScreen', () => {
|
||||||
this.globalHotkey.emit()
|
this.globalHotkey.emit()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
getHotkeysConfig () {
|
getHotkeysConfig () {
|
||||||
let keys = {}
|
let keys = {}
|
||||||
for (let key of HOTKEYS) {
|
for (let key in this.config.full().hotkeys) {
|
||||||
keys[key.id] = key.defaults
|
let value = this.config.full().hotkeys[key]
|
||||||
}
|
if (typeof value == 'string') {
|
||||||
for (let key in this.config.get('hotkeys')) {
|
value = [value]
|
||||||
keys[key] = this.config.get('hotkeys')[key]
|
}
|
||||||
|
value = value.map((item) => (typeof item == 'string') ? [item] : item)
|
||||||
|
keys[key] = value
|
||||||
}
|
}
|
||||||
return keys
|
return keys
|
||||||
}
|
}
|
||||||
|
@ -52,7 +52,7 @@ export function stringifyKeySequence(events: NativeKeyEvent[]): string[] {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
itemKeys.push(lastEvent.key)
|
itemKeys.push(lastEvent.key)
|
||||||
items.push(itemKeys.join('+'))
|
items.push(itemKeys.join('-'))
|
||||||
}
|
}
|
||||||
lastEvent = event
|
lastEvent = event
|
||||||
}
|
}
|
||||||
|
32
app/src/services/pluginDispatcher.ts
Normal file
32
app/src/services/pluginDispatcher.ts
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import { Injectable } from '@angular/core'
|
||||||
|
import { ConfigService } from 'services/config'
|
||||||
|
import { ElectronService } from 'services/electron'
|
||||||
|
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class PluginDispatcherService {
|
||||||
|
plugins = []
|
||||||
|
|
||||||
|
constructor (
|
||||||
|
private config: ConfigService,
|
||||||
|
private electron: ElectronService,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
register (plugin) {
|
||||||
|
if (!this.plugins.includes(plugin)) {
|
||||||
|
this.plugins.push(new plugin({
|
||||||
|
config: this.config,
|
||||||
|
electron: this.electron,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
emit (event: string, parameters: any) {
|
||||||
|
this.plugins.forEach((plugin) => {
|
||||||
|
if (plugin[event]) {
|
||||||
|
plugin[event].bind(plugin)(parameters)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
16
app/src/variables.less
Normal file
16
app/src/variables.less
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
@brand-primary: #f7e61d;
|
||||||
|
@brand-success: #42B500;
|
||||||
|
@brand-info: #01BAEF;
|
||||||
|
@brand-warning: #DB8A00;
|
||||||
|
@brand-danger: #EF2F00;
|
||||||
|
|
||||||
|
@body-bg: #1D272D;
|
||||||
|
@text-color: #aaa;
|
||||||
|
|
||||||
|
@font-family: "Source Sans Pro";
|
||||||
|
@font-size: 14px;
|
||||||
|
|
||||||
|
@dark-border: rgba(0,0,0,.25);
|
||||||
|
@light-border: rgba(255,255,255,.25);
|
||||||
|
|
||||||
|
@component-bg: #161d21;
|
107
npm-debug.log
Normal file
107
npm-debug.log
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
0 info it worked if it ends with ok
|
||||||
|
1 verbose cli [ '/usr/bin/nodejs', '/usr/bin/npm', 'i', '-D', '@types/data-url' ]
|
||||||
|
2 info using npm@4.1.2
|
||||||
|
3 info using node@v7.6.0
|
||||||
|
4 silly loadCurrentTree Starting
|
||||||
|
5 silly install loadCurrentTree
|
||||||
|
6 silly install readLocalPackageData
|
||||||
|
7 silly fetchPackageMetaData @types/data-url
|
||||||
|
8 silly fetchNamedPackageData @types/data-url
|
||||||
|
9 silly mapToRegistry name @types/data-url
|
||||||
|
10 silly mapToRegistry scope (from package name) @types
|
||||||
|
11 verbose mapToRegistry no registry URL found in name for scope @types
|
||||||
|
12 silly mapToRegistry using default registry
|
||||||
|
13 silly mapToRegistry registry https://registry.npmjs.org/
|
||||||
|
14 silly mapToRegistry data Result {
|
||||||
|
14 silly mapToRegistry raw: '@types/data-url',
|
||||||
|
14 silly mapToRegistry scope: '@types',
|
||||||
|
14 silly mapToRegistry escapedName: '@types%2fdata-url',
|
||||||
|
14 silly mapToRegistry name: '@types/data-url',
|
||||||
|
14 silly mapToRegistry rawSpec: '',
|
||||||
|
14 silly mapToRegistry spec: 'latest',
|
||||||
|
14 silly mapToRegistry type: 'tag' }
|
||||||
|
15 silly mapToRegistry uri https://registry.npmjs.org/@types%2fdata-url
|
||||||
|
16 verbose request uri https://registry.npmjs.org/@types%2fdata-url
|
||||||
|
17 verbose request no auth needed
|
||||||
|
18 info attempt registry request try #1 at 5:03:52 PM
|
||||||
|
19 verbose request using bearer token for auth
|
||||||
|
20 verbose request id 5b615716d245b7ec
|
||||||
|
21 http request GET https://registry.npmjs.org/@types%2fdata-url
|
||||||
|
22 http 404 https://registry.npmjs.org/@types%2fdata-url
|
||||||
|
23 verbose headers { 'content-type': 'application/json',
|
||||||
|
23 verbose headers 'cache-control': 'max-age=0',
|
||||||
|
23 verbose headers 'content-length': '2',
|
||||||
|
23 verbose headers 'accept-ranges': 'bytes',
|
||||||
|
23 verbose headers date: 'Sun, 05 Mar 2017 16:03:53 GMT',
|
||||||
|
23 verbose headers via: '1.1 varnish',
|
||||||
|
23 verbose headers connection: 'keep-alive',
|
||||||
|
23 verbose headers 'x-served-by': 'cache-hhn1546-HHN',
|
||||||
|
23 verbose headers 'x-cache': 'MISS',
|
||||||
|
23 verbose headers 'x-cache-hits': '0',
|
||||||
|
23 verbose headers 'x-timer': 'S1488729833.041564,VS0,VE332',
|
||||||
|
23 verbose headers vary: 'Accept-Encoding' }
|
||||||
|
24 silly get cb [ 404,
|
||||||
|
24 silly get { 'content-type': 'application/json',
|
||||||
|
24 silly get 'cache-control': 'max-age=0',
|
||||||
|
24 silly get 'content-length': '2',
|
||||||
|
24 silly get 'accept-ranges': 'bytes',
|
||||||
|
24 silly get date: 'Sun, 05 Mar 2017 16:03:53 GMT',
|
||||||
|
24 silly get via: '1.1 varnish',
|
||||||
|
24 silly get connection: 'keep-alive',
|
||||||
|
24 silly get 'x-served-by': 'cache-hhn1546-HHN',
|
||||||
|
24 silly get 'x-cache': 'MISS',
|
||||||
|
24 silly get 'x-cache-hits': '0',
|
||||||
|
24 silly get 'x-timer': 'S1488729833.041564,VS0,VE332',
|
||||||
|
24 silly get vary: 'Accept-Encoding' } ]
|
||||||
|
25 silly fetchPackageMetaData Error: Registry returned 404 for GET on https://registry.npmjs.org/@types%2fdata-url
|
||||||
|
25 silly fetchPackageMetaData at makeError (/usr/lib/node_modules/npm/node_modules/npm-registry-client/lib/request.js:304:12)
|
||||||
|
25 silly fetchPackageMetaData at CachingRegistryClient.<anonymous> (/usr/lib/node_modules/npm/node_modules/npm-registry-client/lib/request.js:282:14)
|
||||||
|
25 silly fetchPackageMetaData at Request._callback (/usr/lib/node_modules/npm/node_modules/npm-registry-client/lib/request.js:212:14)
|
||||||
|
25 silly fetchPackageMetaData at Request.self.callback (/usr/lib/node_modules/npm/node_modules/request/request.js:186:22)
|
||||||
|
25 silly fetchPackageMetaData at emitTwo (events.js:106:13)
|
||||||
|
25 silly fetchPackageMetaData at Request.emit (events.js:192:7)
|
||||||
|
25 silly fetchPackageMetaData at Request.<anonymous> (/usr/lib/node_modules/npm/node_modules/request/request.js:1081:10)
|
||||||
|
25 silly fetchPackageMetaData at emitOne (events.js:96:13)
|
||||||
|
25 silly fetchPackageMetaData at Request.emit (events.js:189:7)
|
||||||
|
25 silly fetchPackageMetaData at IncomingMessage.<anonymous> (/usr/lib/node_modules/npm/node_modules/request/request.js:1001:12)
|
||||||
|
25 silly fetchPackageMetaData error for @types/data-url { Error: Registry returned 404 for GET on https://registry.npmjs.org/@types%2fdata-url
|
||||||
|
25 silly fetchPackageMetaData at makeError (/usr/lib/node_modules/npm/node_modules/npm-registry-client/lib/request.js:304:12)
|
||||||
|
25 silly fetchPackageMetaData at CachingRegistryClient.<anonymous> (/usr/lib/node_modules/npm/node_modules/npm-registry-client/lib/request.js:282:14)
|
||||||
|
25 silly fetchPackageMetaData at Request._callback (/usr/lib/node_modules/npm/node_modules/npm-registry-client/lib/request.js:212:14)
|
||||||
|
25 silly fetchPackageMetaData at Request.self.callback (/usr/lib/node_modules/npm/node_modules/request/request.js:186:22)
|
||||||
|
25 silly fetchPackageMetaData at emitTwo (events.js:106:13)
|
||||||
|
25 silly fetchPackageMetaData at Request.emit (events.js:192:7)
|
||||||
|
25 silly fetchPackageMetaData at Request.<anonymous> (/usr/lib/node_modules/npm/node_modules/request/request.js:1081:10)
|
||||||
|
25 silly fetchPackageMetaData at emitOne (events.js:96:13)
|
||||||
|
25 silly fetchPackageMetaData at Request.emit (events.js:189:7)
|
||||||
|
25 silly fetchPackageMetaData at IncomingMessage.<anonymous> (/usr/lib/node_modules/npm/node_modules/request/request.js:1001:12) pkgid: '@types/data-url', statusCode: 404, code: 'E404' }
|
||||||
|
26 silly rollbackFailedOptional Starting
|
||||||
|
27 silly rollbackFailedOptional Finishing
|
||||||
|
28 silly runTopLevelLifecycles Finishing
|
||||||
|
29 silly install printInstalled
|
||||||
|
30 verbose stack Error: Registry returned 404 for GET on https://registry.npmjs.org/@types%2fdata-url
|
||||||
|
30 verbose stack at makeError (/usr/lib/node_modules/npm/node_modules/npm-registry-client/lib/request.js:304:12)
|
||||||
|
30 verbose stack at CachingRegistryClient.<anonymous> (/usr/lib/node_modules/npm/node_modules/npm-registry-client/lib/request.js:282:14)
|
||||||
|
30 verbose stack at Request._callback (/usr/lib/node_modules/npm/node_modules/npm-registry-client/lib/request.js:212:14)
|
||||||
|
30 verbose stack at Request.self.callback (/usr/lib/node_modules/npm/node_modules/request/request.js:186:22)
|
||||||
|
30 verbose stack at emitTwo (events.js:106:13)
|
||||||
|
30 verbose stack at Request.emit (events.js:192:7)
|
||||||
|
30 verbose stack at Request.<anonymous> (/usr/lib/node_modules/npm/node_modules/request/request.js:1081:10)
|
||||||
|
30 verbose stack at emitOne (events.js:96:13)
|
||||||
|
30 verbose stack at Request.emit (events.js:189:7)
|
||||||
|
30 verbose stack at IncomingMessage.<anonymous> (/usr/lib/node_modules/npm/node_modules/request/request.js:1001:12)
|
||||||
|
31 verbose statusCode 404
|
||||||
|
32 verbose pkgid @types/data-url
|
||||||
|
33 verbose cwd /home/eugene/Work/term
|
||||||
|
34 error Linux 4.8.0-39-generic
|
||||||
|
35 error argv "/usr/bin/nodejs" "/usr/bin/npm" "i" "-D" "@types/data-url"
|
||||||
|
36 error node v7.6.0
|
||||||
|
37 error npm v4.1.2
|
||||||
|
38 error code E404
|
||||||
|
39 error 404 Registry returned 404 for GET on https://registry.npmjs.org/@types%2fdata-url
|
||||||
|
40 error 404
|
||||||
|
41 error 404 '@types/data-url' is not in the npm registry.
|
||||||
|
42 error 404 You should bug the author to publish it (or use the name yourself!)
|
||||||
|
43 error 404 Note that you can also install from a
|
||||||
|
44 error 404 tarball, folder, http url, or git url.
|
||||||
|
45 verbose exit [ 1, true ]
|
17
package.json
17
package.json
@ -2,8 +2,9 @@
|
|||||||
"name": "term",
|
"name": "term",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"apply-loader": "^0.1.0",
|
"apply-loader": "^0.1.0",
|
||||||
"awesome-typescript-loader": "2.2.4",
|
"awesome-typescript-loader": "3.0.8",
|
||||||
"css-loader": "0.26.1",
|
"css-loader": "0.26.1",
|
||||||
|
"dataurl": "^0.1.0",
|
||||||
"electron": "^1.4.13",
|
"electron": "^1.4.13",
|
||||||
"electron-builder": "10.6.1",
|
"electron-builder": "10.6.1",
|
||||||
"electron-osx-sign": "electron-userland/electron-osx-sign#f092181a1bffa2b3248a23ee28447a47e14a8f04",
|
"electron-osx-sign": "electron-userland/electron-osx-sign#f092181a1bffa2b3248a23ee28447a47e14a8f04",
|
||||||
@ -11,6 +12,7 @@
|
|||||||
"file-loader": "^0.9.0",
|
"file-loader": "^0.9.0",
|
||||||
"font-awesome": "4.7.0",
|
"font-awesome": "4.7.0",
|
||||||
"html-loader": "^0.4.4",
|
"html-loader": "^0.4.4",
|
||||||
|
"json-loader": "^0.5.4",
|
||||||
"less": "^2.7.1",
|
"less": "^2.7.1",
|
||||||
"less-loader": "^2.2.3",
|
"less-loader": "^2.2.3",
|
||||||
"node-gyp": "^3.4.0",
|
"node-gyp": "^3.4.0",
|
||||||
@ -21,11 +23,11 @@
|
|||||||
"style-loader": "^0.13.1",
|
"style-loader": "^0.13.1",
|
||||||
"to-string-loader": "^1.1.5",
|
"to-string-loader": "^1.1.5",
|
||||||
"tslint": "4.2.0",
|
"tslint": "4.2.0",
|
||||||
"typescript": "2.1.1",
|
"typescript": "2.2.1",
|
||||||
"typings": "2.0.0",
|
|
||||||
"url-loader": "^0.5.7",
|
"url-loader": "^0.5.7",
|
||||||
"val-loader": "^0.5.0",
|
"val-loader": "^0.5.0",
|
||||||
"webpack": "2.2.0-rc.4"
|
"webpack": "2.2.0-rc.4",
|
||||||
|
"yaml-loader": "^0.4.0"
|
||||||
},
|
},
|
||||||
"build": {
|
"build": {
|
||||||
"appId": "com.elements.benchmark",
|
"appId": "com.elements.benchmark",
|
||||||
@ -62,15 +64,20 @@
|
|||||||
"@angular/platform-server": "2.3.1",
|
"@angular/platform-server": "2.3.1",
|
||||||
"@angular/router": "3.3.1",
|
"@angular/router": "3.3.1",
|
||||||
"@ng-bootstrap/ng-bootstrap": "^1.0.0-alpha.15",
|
"@ng-bootstrap/ng-bootstrap": "^1.0.0-alpha.15",
|
||||||
|
"@types/core-js": "^0.9.35",
|
||||||
|
"@types/electron": "^1.4.33",
|
||||||
|
"@types/js-yaml": "^3.5.29",
|
||||||
|
"@types/node": "^7.0.5",
|
||||||
|
"@types/pty.js": "^0.2.32",
|
||||||
"angular2-localstorage": "github:AilisObrian/angular2-localstorage",
|
"angular2-localstorage": "github:AilisObrian/angular2-localstorage",
|
||||||
"angular2-perfect-scrollbar": "^1.1.0",
|
"angular2-perfect-scrollbar": "^1.1.0",
|
||||||
"angular2-toaster": "^1.1.0",
|
"angular2-toaster": "^1.1.0",
|
||||||
"bootstrap": "^3.3.7",
|
"bootstrap": "^3.3.7",
|
||||||
"core-js": "^2.4.1",
|
"core-js": "^2.4.1",
|
||||||
|
"hterm-commonjs": "^1.0.0",
|
||||||
"jquery": "^3.1.1",
|
"jquery": "^3.1.1",
|
||||||
"rxjs": "5.0.0-rc.4",
|
"rxjs": "5.0.0-rc.4",
|
||||||
"source-sans-pro": "^2.0.10",
|
"source-sans-pro": "^2.0.10",
|
||||||
"hterm-commonjs": "^1.0.0",
|
|
||||||
"zone.js": "0.7.2"
|
"zone.js": "0.7.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
11
typings.json
11
typings.json
@ -1,11 +0,0 @@
|
|||||||
{
|
|
||||||
"globalDependencies": {
|
|
||||||
"core-js": "registry:dt/core-js#0.0.0+20160914114559",
|
|
||||||
"electron": "registry:dt/electron#1.3.3+20161012142539",
|
|
||||||
"jquery": "registry:dt/jquery#1.10.0+20160929162922",
|
|
||||||
"node": "registry:dt/node#6.0.0+20161014191813"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"pty.js": "registry:dt/pty.js#0.2.7-1+20161128184045"
|
|
||||||
}
|
|
||||||
}
|
|
@ -64,6 +64,7 @@ module.exports = {
|
|||||||
name: 'fonts/[name].[hash:8].[ext]'
|
name: 'fonts/[name].[hash:8].[ext]'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{ test: /\.yaml$/, loader: "json-loader!yaml-loader" },
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
externals: {
|
externals: {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user