Compare commits
1 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
44b4f5ccf8 |
@@ -1,346 +0,0 @@
|
||||
{
|
||||
"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"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "hammster",
|
||||
"name": "Hans Koch",
|
||||
"avatar_url": "https://avatars0.githubusercontent.com/u/1093709?v=4",
|
||||
"profile": "https://hans-koch.me",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "ThePuzzlemaker",
|
||||
"name": "Dak Smyth",
|
||||
"avatar_url": "https://avatars3.githubusercontent.com/u/12666617?v=4",
|
||||
"profile": "http://thepuzzlemaker.info",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "yfwz100",
|
||||
"name": "Wang Zhi",
|
||||
"avatar_url": "https://avatars2.githubusercontent.com/u/983211?v=4",
|
||||
"profile": "http://yfwz100.github.io",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "jack1142",
|
||||
"name": "jack1142",
|
||||
"avatar_url": "https://avatars0.githubusercontent.com/u/6032823?v=4",
|
||||
"profile": "https://github.com/jack1142",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "hdougie",
|
||||
"name": "Howie Douglas",
|
||||
"avatar_url": "https://avatars1.githubusercontent.com/u/450799?v=4",
|
||||
"profile": "https://github.com/hdougie",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "ckaczor",
|
||||
"name": "Chris Kaczor",
|
||||
"avatar_url": "https://avatars2.githubusercontent.com/u/180906?v=4",
|
||||
"profile": "https://chriskaczor.com",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "boxmein",
|
||||
"name": "Johannes Kadak",
|
||||
"avatar_url": "https://avatars1.githubusercontent.com/u/358714?v=4",
|
||||
"profile": "https://www.boxmein.net",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "LeSeulArtichaut",
|
||||
"name": "LeSeulArtichaut",
|
||||
"avatar_url": "https://avatars1.githubusercontent.com/u/38361244?v=4",
|
||||
"profile": "https://github.com/LeSeulArtichaut",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "CyrilTaylor",
|
||||
"name": "Cyril Taylor",
|
||||
"avatar_url": "https://avatars0.githubusercontent.com/u/12631466?v=4",
|
||||
"profile": "https://github.com/CyrilTaylor",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "nstefanou",
|
||||
"name": "nstefanou",
|
||||
"avatar_url": "https://avatars3.githubusercontent.com/u/51129173?v=4",
|
||||
"profile": "https://github.com/nstefanou",
|
||||
"contributions": [
|
||||
"code",
|
||||
"plugin"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "orin220444",
|
||||
"name": "orin220444",
|
||||
"avatar_url": "https://avatars3.githubusercontent.com/u/30747229?v=4",
|
||||
"profile": "https://github.com/orin220444",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "Goobles",
|
||||
"name": "Gobius Dolhain",
|
||||
"avatar_url": "https://avatars3.githubusercontent.com/u/8776771?v=4",
|
||||
"profile": "https://github.com/Goobles",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "3l0w",
|
||||
"name": "Gwilherm Folliot",
|
||||
"avatar_url": "https://avatars2.githubusercontent.com/u/37798980?v=4",
|
||||
"profile": "https://github.com/3l0w",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "dimitory",
|
||||
"name": "Dmitry Pronin",
|
||||
"avatar_url": "https://avatars0.githubusercontent.com/u/475955?v=4",
|
||||
"profile": "https://github.com/Dimitory",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "JonathanBeverley",
|
||||
"name": "Jonathan Beverley",
|
||||
"avatar_url": "https://avatars1.githubusercontent.com/u/20328966?v=4",
|
||||
"profile": "https://github.com/JonathanBeverley",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "zend",
|
||||
"name": "Zenghai Liang",
|
||||
"avatar_url": "https://avatars1.githubusercontent.com/u/25160?v=4",
|
||||
"profile": "https://github.com/zend",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "matishadow",
|
||||
"name": "Mateusz Tracz",
|
||||
"avatar_url": "https://avatars0.githubusercontent.com/u/9083085?v=4",
|
||||
"profile": "https://about.me/matishadow",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "pinpins",
|
||||
"name": "pinpin",
|
||||
"avatar_url": "https://avatars3.githubusercontent.com/u/36234677?v=4",
|
||||
"profile": "https://zergpool.com",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "TakuroOnoda",
|
||||
"name": "Takuro Onoda",
|
||||
"avatar_url": "https://avatars0.githubusercontent.com/u/1407926?v=4",
|
||||
"profile": "https://github.com/TakuroOnoda",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
}
|
||||
],
|
||||
"contributorsPerLine": 7,
|
||||
"projectName": "terminus",
|
||||
"projectOwner": "Eugeny",
|
||||
"repoType": "github",
|
||||
"repoHost": "https://github.com",
|
||||
"commitConvention": "none",
|
||||
"skipCi": true
|
||||
}
|
119
.eslintrc.yml
@@ -1,119 +0,0 @@
|
||||
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-floating-promises': off
|
||||
'@typescript-eslint/prefer-readonly': off
|
||||
'@typescript-eslint/require-await': off
|
||||
'@typescript-eslint/strict-boolean-expressions': off
|
||||
'@typescript-eslint/no-misused-promises': off
|
||||
'@typescript-eslint/typedef': off
|
||||
'@typescript-eslint/consistent-type-imports': 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: off
|
||||
'@typescript-eslint/brace-style':
|
||||
- error
|
||||
- 1tbs
|
||||
- allowSingleLine: true
|
||||
computed-property-spacing:
|
||||
- error
|
||||
- never
|
||||
comma-dangle: off
|
||||
'@typescript-eslint/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
|
||||
no-var: error
|
||||
object-curly-spacing:
|
||||
- error
|
||||
- always
|
||||
quote-props:
|
||||
- warn
|
||||
- as-needed
|
||||
- keywords: true
|
||||
numbers: true
|
||||
quotes: off
|
||||
'@typescript-eslint/quotes':
|
||||
- error
|
||||
- single
|
||||
- allowTemplateLiterals: true
|
||||
'@typescript-eslint/no-non-null-assertion': off
|
||||
'@typescript-eslint/no-unnecessary-condition': off
|
||||
'@typescript-eslint/no-untyped-public-signature': off # bugs out on constructors
|
||||
'@typescript-eslint/restrict-template-expressions': off
|
||||
'@typescript-eslint/no-dynamic-delete': off
|
||||
'@typescript-eslint/prefer-nullish-coalescing': off
|
||||
'@typescript-eslint/prefer-readonly-parameter-types': off
|
||||
'@typescript-eslint/no-unsafe-member-access': off
|
||||
'@typescript-eslint/no-unsafe-call': off
|
||||
'@typescript-eslint/no-unsafe-return': off
|
||||
'@typescript-eslint/no-base-to-string': off # broken in typescript-eslint
|
||||
'@typescript-eslint/no-unsafe-assignment': off
|
||||
'@typescript-eslint/naming-convention': off
|
||||
'@typescript-eslint/lines-between-class-members':
|
||||
- error
|
||||
- exceptAfterSingleLine: true
|
||||
'@typescript-eslint/dot-notation': off
|
||||
'@typescript-eslint/no-confusing-void-expression': off
|
||||
'@typescript-eslint/no-implicit-any-catch': off
|
||||
'@typescript-eslint/member-ordering': off
|
||||
'@typescript-eslint/no-var-requires': off
|
||||
'@typescript-eslint/no-shadow': off
|
3
.github/FUNDING.yml
vendored
@@ -1,3 +0,0 @@
|
||||
github: eugeny
|
||||
open_collective: terminus
|
||||
ko_fi: eugeny
|
18
.github/stale.yml
vendored
@@ -1,18 +0,0 @@
|
||||
# Number of days of inactivity before an issue becomes stale
|
||||
daysUntilStale: 180
|
||||
# Number of days of inactivity before a stale issue is closed
|
||||
daysUntilClose: 90
|
||||
# Issues with these labels will never be considered stale
|
||||
exemptLabels:
|
||||
- "T: Enhancement"
|
||||
- "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
|
||||
markComment: >
|
||||
This issue has been automatically marked as stale because it has not had
|
||||
recent activity. It will be closed in two weeks unless you comment.
|
||||
|
||||
Thank you for your contributions.
|
||||
# Comment to post when closing a stale issue. Set to `false` to disable
|
||||
closeComment: false
|
30
.github/workflows/docs.yml
vendored
@@ -1,30 +0,0 @@
|
||||
name: Docs
|
||||
on: push
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-18.04
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v1
|
||||
|
||||
- name: Installing Node
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 10
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
eval $(ssh-agent -s)
|
||||
ssh-add <(echo "$DOCS_PRIVATE_KEY")
|
||||
yarn cache clean
|
||||
cd app
|
||||
yarn
|
||||
cd ..
|
||||
rm app/node_modules/.yarn-integrity
|
||||
yarn
|
||||
yarn run docs
|
||||
rsync -e "ssh -o StrictHostKeyChecking=no" -arv docs/api/ root@ajenti.org:/srv/terminus-docs/
|
||||
|
||||
env:
|
||||
DOCS_PRIVATE_KEY: ${{ secrets.DOCS_PRIVATE_KEY }}
|
29
.github/workflows/lint.yml
vendored
@@ -1,29 +0,0 @@
|
||||
name: Lint
|
||||
on: [push, pull_request]
|
||||
jobs:
|
||||
build:
|
||||
runs-on: macOS-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v1
|
||||
|
||||
- name: Installing Node
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 15
|
||||
|
||||
- name: Install deps
|
||||
run: |
|
||||
npm i -g yarn@1.19.1
|
||||
cd app
|
||||
yarn
|
||||
cd ..
|
||||
rm app/node_modules/.yarn-integrity
|
||||
yarn
|
||||
|
||||
- name: Build typings
|
||||
run: yarn run build:typings
|
||||
|
||||
- name: Lint
|
||||
run: yarn run lint
|
73
.github/workflows/linux.yml
vendored
@@ -1,73 +0,0 @@
|
||||
name: Linux Build
|
||||
on: [push, pull_request]
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v1
|
||||
|
||||
- name: Install Node
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 15
|
||||
|
||||
- name: Install deps
|
||||
run: |
|
||||
npm i -g yarn@1.19.1
|
||||
cd app
|
||||
yarn
|
||||
cd ..
|
||||
rm app/node_modules/.yarn-integrity
|
||||
yarn
|
||||
|
||||
- name: Build native deps
|
||||
run: scripts/build-native.js
|
||||
|
||||
- name: Webpack
|
||||
run: yarn run build
|
||||
|
||||
- name: Prepackage plugins
|
||||
run: scripts/prepackage-plugins.js
|
||||
|
||||
- name: Build packages
|
||||
run: scripts/build-linux.js
|
||||
env:
|
||||
DEBUG: electron-builder,electron-builder:*
|
||||
GH_TOKEN: ${{ secrets.GH_TOKEN }}
|
||||
|
||||
- name: Package artifacts
|
||||
run: |
|
||||
mkdir artifact-deb
|
||||
mv dist/*.deb artifact-deb/ || true
|
||||
mkdir artifact-rpm
|
||||
mv dist/*.rpm artifact-rpm/ || true
|
||||
mkdir artifact-snap
|
||||
mv dist/*.snap artifact-snap/ || true
|
||||
mkdir artifact-tar.gz
|
||||
mv dist/*.tar.gz artifact-tar.gz/ || true
|
||||
|
||||
- uses: actions/upload-artifact@master
|
||||
name: Upload DEB
|
||||
with:
|
||||
name: Linux .deb
|
||||
path: artifact-deb
|
||||
|
||||
- uses: actions/upload-artifact@master
|
||||
name: Upload RPM
|
||||
with:
|
||||
name: Linux .rpm
|
||||
path: artifact-rpm
|
||||
|
||||
- uses: actions/upload-artifact@master
|
||||
name: Upload Snap
|
||||
with:
|
||||
name: Linux .snap
|
||||
path: artifact-snap
|
||||
|
||||
- uses: actions/upload-artifact@master
|
||||
name: Upload tarball
|
||||
with:
|
||||
name: Linux tarball
|
||||
path: artifact-tar.gz
|
81
.github/workflows/macos.yml
vendored
@@ -1,81 +0,0 @@
|
||||
name: macOS Build
|
||||
on: [push, pull_request]
|
||||
jobs:
|
||||
build:
|
||||
runs-on: macos-11.0
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- arch: x86_64
|
||||
- arch: arm64
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v1
|
||||
|
||||
- name: Installing Node
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 15
|
||||
|
||||
- name: Install deps
|
||||
run: |
|
||||
sudo npm i -g yarn@1.22.1
|
||||
cd app
|
||||
yarn
|
||||
cd ..
|
||||
rm app/node_modules/.yarn-integrity
|
||||
yarn
|
||||
|
||||
- name: Build native deps
|
||||
run: scripts/build-native.js
|
||||
env:
|
||||
ARCH: ${{matrix.arch}}
|
||||
|
||||
- name: Webpack
|
||||
run: yarn run build
|
||||
|
||||
- name: Prepackage plugins
|
||||
run: scripts/prepackage-plugins.js
|
||||
env:
|
||||
ARCH: ${{matrix.arch}}
|
||||
|
||||
- run: sed -i '' 's/updateInfo = await/\/\/updateInfo = await/g' node_modules/app-builder-lib/out/targets/ArchiveTarget.js
|
||||
|
||||
- name: Build and sign packages
|
||||
run: scripts/build-macos.js
|
||||
if: github.repository == 'Eugeny/terminus' && github.event_name == 'push'
|
||||
env:
|
||||
ARCH: ${{matrix.arch}}
|
||||
GH_TOKEN: ${{ secrets.GH_TOKEN }}
|
||||
CSC_LINK: ${{ secrets.CSC_LINK }}
|
||||
CSC_KEY_PASSWORD: ${{ secrets.CSC_KEY_PASSWORD }}
|
||||
APPSTORE_USERNAME: ${{ secrets.APPSTORE_USERNAME }}
|
||||
APPSTORE_PASSWORD: ${{ secrets.APPSTORE_PASSWORD }}
|
||||
# DEBUG: electron-builder,electron-builder:*
|
||||
|
||||
- name: Build packages without signing
|
||||
run: scripts/build-macos.js
|
||||
if: github.repository != 'Eugeny/terminus' || github.event_name != 'push'
|
||||
env:
|
||||
ARCH: ${{matrix.arch}}
|
||||
# DEBUG: electron-builder,electron-builder:*
|
||||
|
||||
- name: Package artifacts
|
||||
run: |
|
||||
mkdir artifact-pkg
|
||||
mv dist/*.pkg artifact-pkg/
|
||||
mkdir artifact-zip
|
||||
mv dist/*.zip artifact-zip/
|
||||
|
||||
- uses: actions/upload-artifact@master
|
||||
name: Upload PKG
|
||||
with:
|
||||
name: macOS .pkg (${{matrix.arch}})
|
||||
path: artifact-pkg
|
||||
|
||||
- uses: actions/upload-artifact@master
|
||||
name: Upload ZIP
|
||||
with:
|
||||
name: macOS .zip (${{matrix.arch}})
|
||||
path: artifact-zip
|
54
.github/workflows/windows.yml
vendored
@@ -1,54 +0,0 @@
|
||||
name: Windows Build
|
||||
on: [push, pull_request]
|
||||
jobs:
|
||||
build:
|
||||
runs-on: windows-2016
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v1
|
||||
|
||||
- name: Installing Node
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 15
|
||||
|
||||
- name: Build
|
||||
shell: powershell
|
||||
run: |
|
||||
npm i -g yarn@1.19.1
|
||||
yarn
|
||||
node scripts/build-native.js
|
||||
yarn run build
|
||||
node scripts/prepackage-plugins.js
|
||||
|
||||
- name: Build and sign packages
|
||||
run: node scripts/build-windows.js
|
||||
if: github.repository == 'Eugeny/terminus' && github.event_name == 'push'
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GH_TOKEN }}
|
||||
WIN_CSC_LINK: ${{ secrets.WIN_CSC_LINK }}
|
||||
WIN_CSC_KEY_PASSWORD: ${{ secrets.WIN_CSC_KEY_PASSWORD }}
|
||||
|
||||
- name: Build packages without signing
|
||||
run: node scripts/build-windows.js
|
||||
if: github.repository != 'Eugeny/terminus' || github.event_name != 'push'
|
||||
|
||||
- name: Package artifacts
|
||||
run: |
|
||||
mkdir artifact-setup
|
||||
mv dist/*-setup.exe artifact-setup/
|
||||
mkdir artifact-portable
|
||||
mv dist/*-portable.zip artifact-portable/
|
||||
|
||||
- uses: actions/upload-artifact@master
|
||||
name: Upload installer
|
||||
with:
|
||||
name: Installer
|
||||
path: artifact-setup
|
||||
|
||||
- uses: actions/upload-artifact@master
|
||||
name: Upload portable build
|
||||
with:
|
||||
name: Portable build
|
||||
path: artifact-portable
|
16
.gitignore
vendored
@@ -5,17 +5,11 @@ node_modules
|
||||
|
||||
build/files.wxs
|
||||
dist
|
||||
*/dist
|
||||
*/typings
|
||||
*.tsbuildinfo
|
||||
|
||||
*.xcworkspacedata
|
||||
*.xcuserstate
|
||||
*.wixpdb
|
||||
|
||||
.DS_Store
|
||||
.DS_Store?
|
||||
|
||||
coverage
|
||||
.nyc_output
|
||||
npm-debug.log
|
||||
@@ -23,13 +17,3 @@ npm-debug.log
|
||||
builtin-plugins
|
||||
package-lock.json
|
||||
yarn-error.log
|
||||
|
||||
docs/api
|
||||
.travis.ssh.key
|
||||
*.code-workspace
|
||||
|
||||
.electron-symbols
|
||||
sentry.properties
|
||||
sentry-symbols.js
|
||||
|
||||
terminus-ssh/util/pagent.exe
|
||||
|
14
.mergify.yml
@@ -1,14 +0,0 @@
|
||||
pull_request_rules:
|
||||
- name: automatic merge on CI success and review
|
||||
conditions:
|
||||
- "status-success=Windows Build / Build"
|
||||
- "status-success=macOS Build / Build"
|
||||
- "status-success=Linux Build / Build"
|
||||
- "status-success=continuous-integration/appveyor/pr"
|
||||
- "#approved-reviews-by>=1"
|
||||
- "#changes-requested-reviews-by=0"
|
||||
- base=master
|
||||
actions:
|
||||
merge:
|
||||
method: merge
|
||||
strict: true
|
44
.travis.yml
@@ -1,36 +1,46 @@
|
||||
language: node_js
|
||||
node_js: 15
|
||||
node_js: 7
|
||||
|
||||
services:
|
||||
- docker
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- node_modules
|
||||
- app/node_modules
|
||||
|
||||
stages:
|
||||
- Build
|
||||
- name: Docs
|
||||
- build
|
||||
- name: deploy
|
||||
if: branch = master
|
||||
|
||||
jobs:
|
||||
include:
|
||||
- stage: 'Docs'
|
||||
- stage: build
|
||||
os: linux
|
||||
if: branch = master
|
||||
script:
|
||||
- '[ -z "${encrypted_4e2fb4889ef8_iv}" ] && exit 0 || true'
|
||||
- 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/
|
||||
env: BUILD_FOR=linux
|
||||
script: ./travis.sh
|
||||
|
||||
dist: xenial
|
||||
- stage: build
|
||||
os: osx
|
||||
env: BUILD_FOR=macos
|
||||
script: ./travis.sh
|
||||
|
||||
- stage: deploy
|
||||
os: linux
|
||||
env: BUILD_FOR=linux STAGE=deploy
|
||||
script: ./travis.sh
|
||||
|
||||
dist: trusty
|
||||
sudo: false
|
||||
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- rpm
|
||||
- wine
|
||||
- mono-runtime
|
||||
- yarn
|
||||
- libsecret-1-dev
|
||||
sources:
|
||||
- sourceline: 'deb https://dl.yarnpkg.com/debian/ stable main'
|
||||
key_url: 'https://dl.yarnpkg.com/debian/pubkey.gpg'
|
||||
|
@@ -92,11 +92,11 @@ Plugins provide functionality by exporting singular or multi providers:
|
||||
|
||||
```javascript
|
||||
import { NgModule, Injectable } from '@angular/core'
|
||||
import { ToolbarButtonProvider, ToolbarButton } from 'terminus-core'
|
||||
import { ToolbarButtonProvider, IToolbarButton } from 'terminus-core'
|
||||
|
||||
@Injectable()
|
||||
export class MyButtonProvider extends ToolbarButtonProvider {
|
||||
provide (): ToolbarButton[] {
|
||||
provide (): IToolbarButton[] {
|
||||
return [{
|
||||
icon: 'star',
|
||||
title: 'Foobar',
|
||||
@@ -118,5 +118,3 @@ export default class MyModule { }
|
||||
|
||||
|
||||
See `terminus-core/src/api.ts`, `terminus-settings/src/api.ts` and `terminus-terminal/src/api.ts` for the available extension points.
|
||||
|
||||
Publish your plugin on NPM with a `terminus-plugin` keyword to make it appear in the Plugin Manager.
|
||||
|
120
README.md
@@ -1,130 +1,42 @@
|
||||

|
||||
|
||||
|
||||
<p align="center">
|
||||
<a href="https://raw.githubusercontent.com/Eugeny/terminus/master/LICENSE"><img alt="GitHub" src="https://img.shields.io/github/license/eugeny/terminus.svg?label=License&style=flat-square"></a> <a href="https://ci.appveyor.com/project/Eugeny/terminus"><img alt="AppVeyor" src="https://img.shields.io/appveyor/ci/eugeny/terminus.svg?label=CI&logo=appveyor&logoColor=white&style=flat-square"></a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/Eugeny/terminus/releases/latest"><img alt="GitHub All Releases" src="https://img.shields.io/github/downloads/eugeny/terminus/total.svg?label=DOWNLOAD&logo=github&style=for-the-badge"></a> <a href="https://ci.appveyor.com/project/Eugeny/terminus/build/artifacts"><img src="https://img.shields.io/badge/download-nightly%20build-magenta.svg?logo=appveyor&style=for-the-badge"/></a> <a href="https://gitter.im/terminus-terminal/community"><img alt="Gitter" src="https://img.shields.io/gitter/room/terminus/community.svg?color=blue&logo=gitter&style=for-the-badge"></a>
|
||||
</p>
|
||||
[](https://travis-ci.org/Eugeny/terminus) [](https://ci.appveyor.com/project/Eugeny/terminus) [](https://raw.githubusercontent.com/Eugeny/terminus/master/LICENSE) [](https://github.com/Eugeny/terminus/releases/latest)
|
||||
[](https://app.fossa.io/projects/git%2Bhttps%3A%2F%2Fgithub.com%2FEugeny%2Fterminus?ref=badge_shield)
|
||||
|
||||
----
|
||||
|
||||
**Terminus** is a highly configurable terminal emulator for Windows, macOS and Linux
|
||||
**Terminus** is a terminal heavily inspired by Hyper. It is, however, designed for people who need to get things done.
|
||||
|
||||
* Integrated SSH client and connection manager
|
||||
* 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
|
||||
* Direct file transfer from/to SSH sessions via Zmodem
|
||||
* Full Unicode support including double-width characters
|
||||
* Doesn't choke on fast-flowing outputs
|
||||
* Proper shell experience on Windows including tab completion (via Clink)
|
||||
|
||||
|
||||
[](https://ko-fi.com/eugeny)
|
||||
* Proper shell-like experience on Windows including tab completion (via Clink)
|
||||
* CMD, PowerShell, PowerShell Core, Cygwin, Cmder, Git-Bash and WSL (Bash on Windows) support
|
||||
* Tab persistence on macOS and Linux
|
||||
|
||||
---
|
||||
|
||||
* **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)
|
||||
|
||||
---
|
||||
|
||||
# Portable
|
||||
|
||||
For portable in windows, user can create folder `data` at the same directory as `Terminal.exe` to save the settings.
|
||||
|
||||
# Plugins
|
||||
|
||||
Plugins and themes can be installed directly from the Settings view inside Terminus.
|
||||
Plugins 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
|
||||
* [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
|
||||
* [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)
|
||||
* [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-scrollbar) - 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
|
||||
|
||||
---
|
||||
|
||||
# Contributing
|
||||
|
||||
Pull requests and plugins are welcome!
|
||||
Pull requests and plugins are welcome! Publish your plugin on NPM with a `terminus-plugin` keyword to make it appear in the Plugin Manager.
|
||||
|
||||
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.
|
||||
See [HACKING.md](https://github.com/Eugeny/terminus/blob/master/HACKING.md) for a very brief plugin development tutorial!
|
||||
|
||||
---
|
||||
|
||||
Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
|
||||
|
||||
<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
|
||||
<!-- prettier-ignore-start -->
|
||||
<!-- markdownlint-disable -->
|
||||
<table>
|
||||
<tr>
|
||||
<td align="center"><a href="http://www.russellmyers.com"><img src="https://avatars2.githubusercontent.com/u/184085?v=4" width="100px;" alt=""/><br /><sub><b>Russell Myers</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=mezner" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://www.morwire.com"><img src="https://avatars1.githubusercontent.com/u/3991658?v=4" width="100px;" alt=""/><br /><sub><b>Austin Warren</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=ehwarren" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/Drachenkaetzchen"><img src="https://avatars1.githubusercontent.com/u/162974?v=4" width="100px;" alt=""/><br /><sub><b>Felicia Hummel</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=Drachenkaetzchen" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/mikemaccana"><img src="https://avatars2.githubusercontent.com/u/172594?v=4" width="100px;" alt=""/><br /><sub><b>Mike MacCana</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=mikemaccana" title="Tests">⚠️</a> <a href="#design-mikemaccana" title="Design">🎨</a></td>
|
||||
<td align="center"><a href="https://github.com/yxuko"><img src="https://avatars1.githubusercontent.com/u/1786317?v=4" width="100px;" alt=""/><br /><sub><b>Yacine Kanzari</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=yxuko" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/BBJip"><img src="https://avatars2.githubusercontent.com/u/32908927?v=4" width="100px;" alt=""/><br /><sub><b>BBJip</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=BBJip" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/Futagirl"><img src="https://avatars2.githubusercontent.com/u/33533958?v=4" width="100px;" alt=""/><br /><sub><b>Futagirl</b></sub></a><br /><a href="#design-Futagirl" title="Design">🎨</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://www.levrik.io"><img src="https://avatars3.githubusercontent.com/u/9491603?v=4" width="100px;" alt=""/><br /><sub><b>Levin Rickert</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=levrik" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://kwonoj.github.io"><img src="https://avatars2.githubusercontent.com/u/1210596?v=4" width="100px;" alt=""/><br /><sub><b>OJ Kwon</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=kwonoj" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/Domain"><img src="https://avatars2.githubusercontent.com/u/903197?v=4" width="100px;" alt=""/><br /><sub><b>domain</b></sub></a><br /><a href="#plugin-Domain" title="Plugin/utility libraries">🔌</a> <a href="https://github.com/Eugeny/terminus/commits?author=Domain" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://www.jbrumond.me"><img src="https://avatars1.githubusercontent.com/u/195127?v=4" width="100px;" alt=""/><br /><sub><b>James Brumond</b></sub></a><br /><a href="#plugin-kbjr" title="Plugin/utility libraries">🔌</a></td>
|
||||
<td align="center"><a href="http://www.growingwiththeweb.com"><img src="https://avatars0.githubusercontent.com/u/2193314?v=4" width="100px;" alt=""/><br /><sub><b>Daniel Imms</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=Tyriar" title="Code">💻</a> <a href="#plugin-Tyriar" title="Plugin/utility libraries">🔌</a> <a href="https://github.com/Eugeny/terminus/commits?author=Tyriar" title="Tests">⚠️</a></td>
|
||||
<td align="center"><a href="https://github.com/baflo"><img src="https://avatars2.githubusercontent.com/u/834350?v=4" width="100px;" alt=""/><br /><sub><b>Florian Bachmann</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=baflo" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://michael-kuehnel.de"><img src="https://avatars2.githubusercontent.com/u/441011?v=4" width="100px;" alt=""/><br /><sub><b>Michael Kühnel</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=mischah" title="Code">💻</a> <a href="#design-mischah" title="Design">🎨</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/NieLeben"><img src="https://avatars3.githubusercontent.com/u/47182955?v=4" width="100px;" alt=""/><br /><sub><b>Tilmann Meyer</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=NieLeben" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://www.jubeat.net"><img src="https://avatars3.githubusercontent.com/u/11289158?v=4" width="100px;" alt=""/><br /><sub><b>PM Extra</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/issues?q=author%3APMExtra" title="Bug reports">🐛</a></td>
|
||||
<td align="center"><a href="https://jjuhas.keybase.pub//"><img src="https://avatars1.githubusercontent.com/u/6438760?v=4" width="100px;" alt=""/><br /><sub><b>Jonathan</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=IgnusG" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://hans-koch.me"><img src="https://avatars0.githubusercontent.com/u/1093709?v=4" width="100px;" alt=""/><br /><sub><b>Hans Koch</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=hammster" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://thepuzzlemaker.info"><img src="https://avatars3.githubusercontent.com/u/12666617?v=4" width="100px;" alt=""/><br /><sub><b>Dak Smyth</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=ThePuzzlemaker" title="Code">💻</a></td>
|
||||
<td align="center"><a href="http://yfwz100.github.io"><img src="https://avatars2.githubusercontent.com/u/983211?v=4" width="100px;" alt=""/><br /><sub><b>Wang Zhi</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=yfwz100" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/jack1142"><img src="https://avatars0.githubusercontent.com/u/6032823?v=4" width="100px;" alt=""/><br /><sub><b>jack1142</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=jack1142" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/hdougie"><img src="https://avatars1.githubusercontent.com/u/450799?v=4" width="100px;" alt=""/><br /><sub><b>Howie Douglas</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=hdougie" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://chriskaczor.com"><img src="https://avatars2.githubusercontent.com/u/180906?v=4" width="100px;" alt=""/><br /><sub><b>Chris Kaczor</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=ckaczor" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://www.boxmein.net"><img src="https://avatars1.githubusercontent.com/u/358714?v=4" width="100px;" alt=""/><br /><sub><b>Johannes Kadak</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=boxmein" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/LeSeulArtichaut"><img src="https://avatars1.githubusercontent.com/u/38361244?v=4" width="100px;" alt=""/><br /><sub><b>LeSeulArtichaut</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=LeSeulArtichaut" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/CyrilTaylor"><img src="https://avatars0.githubusercontent.com/u/12631466?v=4" width="100px;" alt=""/><br /><sub><b>Cyril Taylor</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=CyrilTaylor" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/nstefanou"><img src="https://avatars3.githubusercontent.com/u/51129173?v=4" width="100px;" alt=""/><br /><sub><b>nstefanou</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=nstefanou" title="Code">💻</a> <a href="#plugin-nstefanou" title="Plugin/utility libraries">🔌</a></td>
|
||||
<td align="center"><a href="https://github.com/orin220444"><img src="https://avatars3.githubusercontent.com/u/30747229?v=4" width="100px;" alt=""/><br /><sub><b>orin220444</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=orin220444" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/Goobles"><img src="https://avatars3.githubusercontent.com/u/8776771?v=4" width="100px;" alt=""/><br /><sub><b>Gobius Dolhain</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=Goobles" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/3l0w"><img src="https://avatars2.githubusercontent.com/u/37798980?v=4" width="100px;" alt=""/><br /><sub><b>Gwilherm Folliot</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=3l0w" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/Dimitory"><img src="https://avatars0.githubusercontent.com/u/475955?v=4" width="100px;" alt=""/><br /><sub><b>Dmitry Pronin</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=dimitory" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/JonathanBeverley"><img src="https://avatars1.githubusercontent.com/u/20328966?v=4" width="100px;" alt=""/><br /><sub><b>Jonathan Beverley</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=JonathanBeverley" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://github.com/zend"><img src="https://avatars1.githubusercontent.com/u/25160?v=4" width="100px;" alt=""/><br /><sub><b>Zenghai Liang</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=zend" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://about.me/matishadow"><img src="https://avatars0.githubusercontent.com/u/9083085?v=4" width="100px;" alt=""/><br /><sub><b>Mateusz Tracz</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=matishadow" title="Code">💻</a></td>
|
||||
<td align="center"><a href="https://zergpool.com"><img src="https://avatars3.githubusercontent.com/u/36234677?v=4" width="100px;" alt=""/><br /><sub><b>pinpin</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=pinpins" title="Code">💻</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"><a href="https://github.com/TakuroOnoda"><img src="https://avatars0.githubusercontent.com/u/1407926?v=4" width="100px;" alt=""/><br /><sub><b>Takuro Onoda</b></sub></a><br /><a href="https://github.com/Eugeny/terminus/commits?author=TakuroOnoda" title="Code">💻</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<!-- markdownlint-enable -->
|
||||
<!-- prettier-ignore-end -->
|
||||
<!-- ALL-CONTRIBUTORS-LIST:END -->
|
||||
|
||||
This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
|
||||
## License
|
||||
[](https://app.fossa.io/projects/git%2Bhttps%3A%2F%2Fgithub.com%2FEugeny%2Fterminus?ref=badge_large)
|
||||
|
Before Width: | Height: | Size: 4.9 KiB |
@@ -1,55 +1,91 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 23.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 1024 1024" style="enable-background:new 0 0 1024 1024;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:url(#SVGID_1_);}
|
||||
.st1{opacity:0.16;fill:url(#SVGID_2_);}
|
||||
.st2{fill:url(#SVGID_3_);}
|
||||
.st3{opacity:0.16;fill:url(#SVGID_4_);}
|
||||
.st4{fill:url(#SVGID_5_);}
|
||||
.st5{opacity:0.15;fill:url(#SVGID_6_);}
|
||||
.st6{fill:url(#SVGID_7_);}
|
||||
</style>
|
||||
<g>
|
||||
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="260.9675" y1="871.1813" x2="919.1845" y2="491.1596">
|
||||
<stop offset="0" style="stop-color:#669ABD"/>
|
||||
<stop offset="1" style="stop-color:#77DBDB"/>
|
||||
</linearGradient>
|
||||
<polygon class="st0" points="297.54,934.52 882.6,596.72 882.61,427.82 297.54,765.65 "/>
|
||||
<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="553.5051" y1="617.8278" x2="626.647" y2="744.5132">
|
||||
<stop offset="0.5588" style="stop-color:#000000;stop-opacity:0"/>
|
||||
<stop offset="1" style="stop-color:#000000"/>
|
||||
</linearGradient>
|
||||
<polygon class="st1" points="297.54,934.52 882.6,596.72 882.61,427.82 297.54,765.65 "/>
|
||||
</g>
|
||||
<g>
|
||||
<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="114.6631" y1="744.5275" x2="334.0905" y2="871.2141">
|
||||
<stop offset="0" style="stop-color:#6A8FAD"/>
|
||||
<stop offset="1" style="stop-color:#669ABD"/>
|
||||
</linearGradient>
|
||||
<polygon class="st2" points="151.23,681.18 151.22,850.09 297.54,934.52 297.54,765.65 "/>
|
||||
<linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="260.9478" y1="744.5281" x2="187.8059" y2="871.2135">
|
||||
<stop offset="0.5588" style="stop-color:#000000;stop-opacity:0"/>
|
||||
<stop offset="1" style="stop-color:#000000"/>
|
||||
</linearGradient>
|
||||
<polygon class="st3" points="151.23,681.18 151.22,850.09 297.54,934.52 297.54,765.65 "/>
|
||||
</g>
|
||||
<g>
|
||||
<linearGradient id="SVGID_5_" gradientUnits="userSpaceOnUse" x1="114.663" y1="237.793" x2="553.5026" y2="491.1571">
|
||||
<stop offset="0" style="stop-color:#6A8FAD"/>
|
||||
<stop offset="1" style="stop-color:#669ABD"/>
|
||||
</linearGradient>
|
||||
<polygon class="st4" points="151.23,174.45 151.21,343.36 443.79,512.27 590.08,427.81 "/>
|
||||
<linearGradient id="SVGID_6_" gradientUnits="userSpaceOnUse" x1="370.6562" y1="301.1281" x2="297.5094" y2="427.8221">
|
||||
<stop offset="0.5588" style="stop-color:#000000;stop-opacity:0"/>
|
||||
<stop offset="1" style="stop-color:#000000"/>
|
||||
</linearGradient>
|
||||
<polygon class="st5" points="151.23,174.45 151.21,343.36 443.79,512.27 590.08,427.81 "/>
|
||||
</g>
|
||||
<linearGradient id="SVGID_7_" gradientUnits="userSpaceOnUse" x1="78.0912" y1="554.4979" x2="736.3375" y2="174.4593">
|
||||
<stop offset="0" style="stop-color:#CCECFF"/>
|
||||
<stop offset="1" style="stop-color:#9FECED"/>
|
||||
</linearGradient>
|
||||
<polygon class="st6" points="297.51,765.64 151.23,681.18 590.08,427.81 151.23,174.45 297.5,90 882.61,427.82 "/>
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="150mm"
|
||||
height="150mm"
|
||||
viewBox="0 0 150 150"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
inkscape:version="0.92.2 (5c3e80d, 2017-08-06)"
|
||||
sodipodi:docname="logo.svg"
|
||||
inkscape:export-filename="/home/eugene/Work/term/build/icons/512x512.png"
|
||||
inkscape:export-xdpi="86.699997"
|
||||
inkscape:export-ydpi="86.699997">
|
||||
<defs
|
||||
id="defs2" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="0.49497475"
|
||||
inkscape:cx="85.897128"
|
||||
inkscape:cy="375.72042"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:snap-bbox="true"
|
||||
inkscape:window-width="1366"
|
||||
inkscape:window-height="692"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0"
|
||||
inkscape:snap-intersection-paths="true"
|
||||
inkscape:object-paths="true" />
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-10.356544,-82.309525)">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path138"
|
||||
style="opacity:0.9;fill:#bfd9f1;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.12037313px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
|
||||
d="M 33.048081,103.66303 101.30357,143.02426 80.80219,154.86063 33.048089,125.73315 Z"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path116"
|
||||
style="opacity:0.9;fill:#6666af;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.12037313px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
|
||||
d="m 141.59934,143.95811 0.051,23.16109 -87.420905,49.42651 -0.0034,-22.16232 z"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path118"
|
||||
style="opacity:0.9;fill:#bfd9f1;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.12037313px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
|
||||
d="m 33.233182,182.28294 20.992812,12.1202 0.0034,22.16208 -20.996251,-12.19239 z"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<path
|
||||
style="opacity:0.9;fill:#9dbef0;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.12649226px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
|
||||
d="m 52.236336,92.196079 -19.484508,11.249681 68.551742,39.5785 -68.366041,39.4708 21.107487,12.18633 68.366044,-39.4708 19.48451,-11.24968 z"
|
||||
id="path134"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccccccc" />
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 3.5 KiB |
@@ -1,29 +1,26 @@
|
||||
/** @hidden */
|
||||
module.exports = function patchPTYModule (mod) {
|
||||
module.exports = function patchPTYModule (path) {
|
||||
const mod = require(path)
|
||||
const oldSpawn = mod.spawn
|
||||
if (mod.patched) {
|
||||
return
|
||||
return mod
|
||||
}
|
||||
mod.patched = true
|
||||
mod.spawn = (file, args, opt) => {
|
||||
let terminal = oldSpawn(file, args, opt)
|
||||
let timeout = null
|
||||
let buffer = Buffer.from('')
|
||||
let buffer = ''
|
||||
let lastFlush = 0
|
||||
let nextTimeout = 0
|
||||
|
||||
// Minimum prebuffering window (ms) if the input is non-stop flowing
|
||||
const minWindow = 10
|
||||
|
||||
// Maximum buffering time (ms) until output must be flushed unconditionally
|
||||
const maxWindow = 100
|
||||
const maxWindow = 250
|
||||
const minWindow = 50
|
||||
|
||||
function flush () {
|
||||
if (buffer.length) {
|
||||
if (buffer) {
|
||||
terminal.emit('data-buffered', buffer)
|
||||
}
|
||||
lastFlush = Date.now()
|
||||
buffer = Buffer.from('')
|
||||
buffer = ''
|
||||
}
|
||||
|
||||
function reschedule () {
|
||||
@@ -38,20 +35,16 @@ module.exports = function patchPTYModule (mod) {
|
||||
}
|
||||
|
||||
terminal.on('data', data => {
|
||||
if (typeof data === 'string') {
|
||||
data = Buffer.from(data)
|
||||
}
|
||||
buffer = Buffer.concat([buffer, data])
|
||||
buffer += data
|
||||
if (Date.now() - lastFlush > maxWindow) {
|
||||
// Taking too much time buffering, flush to keep things interactive
|
||||
flush()
|
||||
} else {
|
||||
if (Date.now() > nextTimeout - maxWindow / 10) {
|
||||
// Extend the window if it's expiring
|
||||
if (Date.now() > nextTimeout - (minWindow / 10)) {
|
||||
reschedule()
|
||||
}
|
||||
}
|
||||
})
|
||||
return terminal
|
||||
}
|
||||
return mod
|
||||
}
|
@@ -1,4 +0,0 @@
|
||||
owner: eugeny
|
||||
repo: terminus
|
||||
provider: github
|
||||
updaterCacheDirName: terminus-updater
|
@@ -8,15 +8,17 @@ html
|
||||
window.nodeRequire = require
|
||||
script(src='./preload.js')
|
||||
script(src='./bundle.js', defer)
|
||||
style#custom-css
|
||||
style.
|
||||
body { transition: 0.5s background; }
|
||||
body
|
||||
style#custom-css
|
||||
app-root
|
||||
.preload-logo
|
||||
div
|
||||
.terminus-logo
|
||||
h1.terminus-title Terminus
|
||||
sup α
|
||||
sup α
|
||||
.progress
|
||||
.bar(style='width: 0%')
|
||||
|
||||
|
||||
|
230
app/lib/app.ts
@@ -1,230 +0,0 @@
|
||||
import { app, ipcMain, Menu, Tray, shell, screen, globalShortcut, MenuItemConstructorOptions } from 'electron'
|
||||
import { loadConfig } from './config'
|
||||
import { Window, WindowOptions } from './window'
|
||||
|
||||
export class Application {
|
||||
private tray: Tray
|
||||
private windows: Window[] = []
|
||||
|
||||
constructor () {
|
||||
ipcMain.on('app:config-change', (_event, config) => {
|
||||
this.broadcast('host:config-change', config)
|
||||
})
|
||||
|
||||
ipcMain.on('app:register-global-hotkey', (_event, specs) => {
|
||||
globalShortcut.unregisterAll()
|
||||
for (const spec of specs) {
|
||||
globalShortcut.register(spec, () => {
|
||||
this.onGlobalHotkey()
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
const configData = loadConfig()
|
||||
if (process.platform === 'linux') {
|
||||
app.commandLine.appendSwitch('no-sandbox')
|
||||
if (((configData.appearance || {}).opacity || 1) !== 1) {
|
||||
app.commandLine.appendSwitch('enable-transparent-visuals')
|
||||
app.disableHardwareAcceleration()
|
||||
}
|
||||
}
|
||||
|
||||
app.commandLine.appendSwitch('disable-http-cache')
|
||||
app.commandLine.appendSwitch('lang', 'EN')
|
||||
app.allowRendererProcessReuse = false
|
||||
|
||||
for (const flag of configData.flags || [['force_discrete_gpu', '0']]) {
|
||||
app.commandLine.appendSwitch(flag[0], flag[1])
|
||||
}
|
||||
}
|
||||
|
||||
init (): void {
|
||||
screen.on('display-metrics-changed', () => this.broadcast('host:display-metrics-changed'))
|
||||
screen.on('display-added', () => this.broadcast('host:displays-changed'))
|
||||
screen.on('display-removed', () => this.broadcast('host:displays-changed'))
|
||||
}
|
||||
|
||||
async newWindow (options?: WindowOptions): Promise<Window> {
|
||||
const window = new Window(options)
|
||||
this.windows.push(window)
|
||||
window.visible$.subscribe(visible => {
|
||||
if (visible) {
|
||||
this.disableTray()
|
||||
} else {
|
||||
this.enableTray()
|
||||
}
|
||||
})
|
||||
window.closed$.subscribe(() => {
|
||||
this.windows = this.windows.filter(x => x !== window)
|
||||
})
|
||||
if (process.platform === 'darwin') {
|
||||
this.setupMenu()
|
||||
}
|
||||
await window.ready
|
||||
return window
|
||||
}
|
||||
|
||||
onGlobalHotkey (): void {
|
||||
if (this.windows.some(x => x.isFocused())) {
|
||||
for (const window of this.windows) {
|
||||
window.hide()
|
||||
}
|
||||
} else {
|
||||
for (const window of this.windows) {
|
||||
window.present()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
presentAllWindows (): void {
|
||||
for (const window of this.windows) {
|
||||
window.present()
|
||||
}
|
||||
}
|
||||
|
||||
broadcast (event: string, ...args: any[]): void {
|
||||
for (const window of this.windows) {
|
||||
window.send(event, ...args)
|
||||
}
|
||||
}
|
||||
|
||||
async send (event: string, ...args: any[]): Promise<void> {
|
||||
if (!this.hasWindows()) {
|
||||
await this.newWindow()
|
||||
}
|
||||
this.windows.filter(w => !w.isDestroyed())[0].send(event, ...args)
|
||||
}
|
||||
|
||||
enableTray (): void {
|
||||
if (this.tray) {
|
||||
return
|
||||
}
|
||||
if (process.platform === 'darwin') {
|
||||
this.tray = new Tray(`${app.getAppPath()}/assets/tray-darwinTemplate.png`)
|
||||
this.tray.setPressedImage(`${app.getAppPath()}/assets/tray-darwinHighlightTemplate.png`)
|
||||
} else {
|
||||
this.tray = new Tray(`${app.getAppPath()}/assets/tray.png`)
|
||||
}
|
||||
|
||||
this.tray.on('click', () => setTimeout(() => this.focus()))
|
||||
|
||||
const contextMenu = Menu.buildFromTemplate([{
|
||||
label: 'Show',
|
||||
click: () => this.focus(),
|
||||
}])
|
||||
|
||||
if (process.platform !== 'darwin') {
|
||||
this.tray.setContextMenu(contextMenu)
|
||||
}
|
||||
|
||||
this.tray.setToolTip(`Terminus ${app.getVersion()}`)
|
||||
}
|
||||
|
||||
disableTray (): void {
|
||||
if (this.tray) {
|
||||
this.tray.destroy()
|
||||
this.tray = null
|
||||
}
|
||||
}
|
||||
|
||||
hasWindows (): boolean {
|
||||
return !!this.windows.length
|
||||
}
|
||||
|
||||
focus (): void {
|
||||
for (const window of this.windows) {
|
||||
window.show()
|
||||
}
|
||||
}
|
||||
|
||||
handleSecondInstance (argv: string[], cwd: string): void {
|
||||
this.presentAllWindows()
|
||||
this.windows[this.windows.length - 1].handleSecondInstance(argv, cwd)
|
||||
}
|
||||
|
||||
private setupMenu () {
|
||||
const template: MenuItemConstructorOptions[] = [
|
||||
{
|
||||
label: 'Application',
|
||||
submenu: [
|
||||
{ role: 'about', label: 'About Terminus' },
|
||||
{ type: 'separator' },
|
||||
{
|
||||
label: 'Preferences',
|
||||
accelerator: 'Cmd+,',
|
||||
click: async () => {
|
||||
if (!this.hasWindows()) {
|
||||
await this.newWindow()
|
||||
}
|
||||
this.windows[0].send('host:preferences-menu')
|
||||
},
|
||||
},
|
||||
{ type: 'separator' },
|
||||
{ role: 'services', submenu: [] },
|
||||
{ type: 'separator' },
|
||||
{ role: 'hide' },
|
||||
{ role: 'hideOthers' },
|
||||
{ role: 'unhide' },
|
||||
{ type: 'separator' },
|
||||
{
|
||||
label: 'Quit',
|
||||
accelerator: 'Cmd+Q',
|
||||
click () {
|
||||
app.quit()
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'Edit',
|
||||
submenu: [
|
||||
{ role: 'undo' },
|
||||
{ role: 'redo' },
|
||||
{ type: 'separator' },
|
||||
{ role: 'cut' },
|
||||
{ role: 'copy' },
|
||||
{ role: 'paste' },
|
||||
{ role: 'pasteAndMatchStyle' },
|
||||
{ role: 'delete' },
|
||||
{ role: 'selectAll' },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'View',
|
||||
submenu: [
|
||||
{ role: 'reload' },
|
||||
{ role: 'forceReload' },
|
||||
{ role: 'toggleDevTools' },
|
||||
{ type: 'separator' },
|
||||
{ role: 'resetZoom' },
|
||||
{ role: 'zoomIn' },
|
||||
{ role: 'zoomOut' },
|
||||
{ type: 'separator' },
|
||||
{ role: 'togglefullscreen' },
|
||||
],
|
||||
},
|
||||
{
|
||||
role: 'window',
|
||||
submenu: [
|
||||
{ role: 'minimize' },
|
||||
{ role: 'zoom' },
|
||||
{ type: 'separator' },
|
||||
{ role: 'front' },
|
||||
],
|
||||
},
|
||||
{
|
||||
role: 'help',
|
||||
submenu: [
|
||||
{
|
||||
label: 'Website',
|
||||
click () {
|
||||
shell.openExternal('https://eugeny.github.io/terminus')
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
Menu.setApplicationMenu(Menu.buildFromTemplate(template))
|
||||
}
|
||||
}
|
@@ -1,45 +0,0 @@
|
||||
import { app } from 'electron'
|
||||
|
||||
export function parseArgs (argv: string[], cwd: string): any {
|
||||
if (argv[0].includes('node')) {
|
||||
argv = argv.slice(1)
|
||||
}
|
||||
|
||||
return require('yargs')
|
||||
.usage('terminus [command] [arguments]')
|
||||
.command('open [directory]', 'open a shell in a directory', {
|
||||
directory: { type: 'string', 'default': 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',
|
||||
type: 'boolean',
|
||||
describe: 'Perform shell escaping',
|
||||
}).positional('text', {
|
||||
type: 'string',
|
||||
})
|
||||
})
|
||||
.version('version', '', app.getVersion())
|
||||
.option('debug', {
|
||||
alias: 'd',
|
||||
describe: 'Show DevTools on start',
|
||||
type: 'boolean',
|
||||
})
|
||||
.option('hidden', {
|
||||
describe: 'Start minimized',
|
||||
type: 'boolean',
|
||||
})
|
||||
.option('version', {
|
||||
alias: 'v',
|
||||
describe: 'Show version and exit',
|
||||
type: 'boolean',
|
||||
})
|
||||
.help('help')
|
||||
.parse(argv.slice(1))
|
||||
}
|
@@ -1,13 +0,0 @@
|
||||
import * as fs from 'fs'
|
||||
import * as path from 'path'
|
||||
import * as yaml from 'js-yaml'
|
||||
import { app } from 'electron'
|
||||
|
||||
export function loadConfig (): any {
|
||||
const configPath = path.join(app.getPath('userData'), 'config.yaml')
|
||||
if (fs.existsSync(configPath)) {
|
||||
return yaml.safeLoad(fs.readFileSync(configPath, 'utf8'))
|
||||
} else {
|
||||
return {}
|
||||
}
|
||||
}
|
@@ -1,68 +0,0 @@
|
||||
import './portable'
|
||||
import './sentry'
|
||||
import './lru'
|
||||
import { app, ipcMain, Menu } from 'electron'
|
||||
import { parseArgs } from './cli'
|
||||
import { Application } from './app'
|
||||
import electronDebug = require('electron-debug')
|
||||
|
||||
if (!process.env.TERMINUS_PLUGINS) {
|
||||
process.env.TERMINUS_PLUGINS = ''
|
||||
}
|
||||
|
||||
const application = new Application()
|
||||
|
||||
ipcMain.on('app:new-window', () => {
|
||||
application.newWindow()
|
||||
})
|
||||
|
||||
app.on('activate', () => {
|
||||
if (!application.hasWindows()) {
|
||||
application.newWindow()
|
||||
} else {
|
||||
application.focus()
|
||||
}
|
||||
})
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
app.quit()
|
||||
})
|
||||
|
||||
process.on('uncaughtException' as any, err => {
|
||||
console.log(err)
|
||||
application.broadcast('uncaughtException', err)
|
||||
})
|
||||
|
||||
app.on('second-instance', (_event, argv, cwd) => {
|
||||
application.handleSecondInstance(argv, cwd)
|
||||
})
|
||||
|
||||
const argv = parseArgs(process.argv, process.cwd())
|
||||
|
||||
if (!app.requestSingleInstanceLock()) {
|
||||
app.quit()
|
||||
app.exit(0)
|
||||
}
|
||||
|
||||
if (argv.d) {
|
||||
electronDebug({
|
||||
isEnabled: true,
|
||||
showDevTools: true,
|
||||
devToolsMode: 'undocked',
|
||||
})
|
||||
}
|
||||
|
||||
app.on('ready', () => {
|
||||
if (process.platform === 'darwin') {
|
||||
app.dock.setMenu(Menu.buildFromTemplate([
|
||||
{
|
||||
label: 'New window',
|
||||
click () {
|
||||
this.app.newWindow()
|
||||
},
|
||||
},
|
||||
]))
|
||||
}
|
||||
application.init()
|
||||
application.newWindow({ hidden: argv.hidden })
|
||||
})
|
@@ -1,17 +0,0 @@
|
||||
import * as LRU from 'lru-cache'
|
||||
import * as fs from 'fs'
|
||||
const lru = new LRU({ max: 256, maxAge: 250 })
|
||||
const origLstat = fs.realpathSync.bind(fs)
|
||||
|
||||
// NB: The biggest offender of thrashing realpathSync is the node module system
|
||||
// itself, which we can't get into via any sane means.
|
||||
require('fs').realpathSync = function (p) {
|
||||
let r = lru.get(p)
|
||||
if (r) {
|
||||
return r
|
||||
}
|
||||
|
||||
r = origLstat(p)
|
||||
lru.set(p, r)
|
||||
return r
|
||||
}
|
@@ -1,24 +0,0 @@
|
||||
import * as path from 'path'
|
||||
import * as fs from 'fs'
|
||||
|
||||
let appPath: string | null = null
|
||||
try {
|
||||
appPath = path.dirname(require('electron').app.getPath('exe'))
|
||||
} catch {
|
||||
appPath = path.dirname(require('electron').remote.app.getPath('exe'))
|
||||
}
|
||||
|
||||
if (null != appPath) {
|
||||
if (fs.existsSync(path.join(appPath, 'terminus-data'))) {
|
||||
fs.renameSync(path.join(appPath, 'terminus-data'), path.join(appPath, 'data'))
|
||||
}
|
||||
const portableData = path.join(appPath, 'data')
|
||||
if (fs.existsSync(portableData)) {
|
||||
console.log('reset user data to ' + portableData)
|
||||
try {
|
||||
require('electron').app.setPath('userData', portableData)
|
||||
} catch {
|
||||
require('electron').remote.app.setPath('userData', portableData)
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,21 +0,0 @@
|
||||
const { init } = String(process.type) === 'main' ? require('@sentry/electron/dist/main') : require('@sentry/electron/dist/renderer')
|
||||
import * as isDev from 'electron-is-dev'
|
||||
|
||||
|
||||
const SENTRY_DSN = 'https://4717a0a7ee0b4429bd3a0f06c3d7eec3@sentry.io/181876'
|
||||
let release = null
|
||||
try {
|
||||
release = require('electron').app.getVersion()
|
||||
} catch {
|
||||
release = require('electron').remote.app.getVersion()
|
||||
}
|
||||
|
||||
if (!isDev) {
|
||||
init({
|
||||
dsn: SENTRY_DSN,
|
||||
release,
|
||||
integrations (integrations) {
|
||||
return integrations.filter(integration => integration.name !== 'Breadcrumbs')
|
||||
},
|
||||
})
|
||||
}
|
@@ -1,390 +0,0 @@
|
||||
import * as glasstron from 'glasstron'
|
||||
if (process.platform === 'win32' || process.platform === 'linux') {
|
||||
glasstron.init()
|
||||
}
|
||||
|
||||
import { Subject, Observable } from 'rxjs'
|
||||
import { debounceTime } from 'rxjs/operators'
|
||||
import { BrowserWindow, app, ipcMain, Rectangle, Menu, screen, BrowserWindowConstructorOptions } from 'electron'
|
||||
import ElectronConfig = require('electron-config')
|
||||
import * as os from 'os'
|
||||
import * as path from 'path'
|
||||
|
||||
import { parseArgs } from './cli'
|
||||
import { loadConfig } from './config'
|
||||
|
||||
let DwmEnableBlurBehindWindow: any = null
|
||||
if (process.platform === 'win32') {
|
||||
DwmEnableBlurBehindWindow = require('windows-blurbehind').DwmEnableBlurBehindWindow
|
||||
}
|
||||
|
||||
export interface WindowOptions {
|
||||
hidden?: boolean
|
||||
}
|
||||
|
||||
abstract class GlasstronWindow extends BrowserWindow {
|
||||
blurType: string
|
||||
abstract setBlur (_: boolean)
|
||||
}
|
||||
|
||||
export class Window {
|
||||
ready: Promise<void>
|
||||
private visible = new Subject<boolean>()
|
||||
private closed = new Subject<void>()
|
||||
private window: GlasstronWindow
|
||||
private windowConfig: ElectronConfig
|
||||
private windowBounds: Rectangle
|
||||
private closing = false
|
||||
private lastVibrancy: {enabled: boolean, type?: string} | null = null
|
||||
private disableVibrancyWhileDragging = false
|
||||
private configStore: any
|
||||
|
||||
get visible$ (): Observable<boolean> { return this.visible }
|
||||
get closed$ (): Observable<void> { return this.closed }
|
||||
|
||||
constructor (options?: WindowOptions) {
|
||||
this.configStore = loadConfig()
|
||||
|
||||
options = options || {}
|
||||
|
||||
this.windowConfig = new ElectronConfig({ name: 'window' })
|
||||
this.windowBounds = this.windowConfig.get('windowBoundaries')
|
||||
|
||||
const maximized = this.windowConfig.get('maximized')
|
||||
const bwOptions: BrowserWindowConstructorOptions = {
|
||||
width: 800,
|
||||
height: 600,
|
||||
title: 'Terminus',
|
||||
minWidth: 400,
|
||||
minHeight: 300,
|
||||
webPreferences: {
|
||||
nodeIntegration: true,
|
||||
preload: path.join(__dirname, 'sentry.js'),
|
||||
backgroundThrottling: false,
|
||||
enableRemoteModule: true,
|
||||
},
|
||||
frame: false,
|
||||
show: false,
|
||||
backgroundColor: '#00000000',
|
||||
}
|
||||
|
||||
if (this.windowBounds) {
|
||||
Object.assign(bwOptions, this.windowBounds)
|
||||
const closestDisplay = screen.getDisplayNearestPoint( { x: this.windowBounds.x, y: this.windowBounds.y } )
|
||||
|
||||
const [left1, top1, right1, bottom1] = [this.windowBounds.x, this.windowBounds.y, this.windowBounds.x + this.windowBounds.width, this.windowBounds.y + this.windowBounds.height]
|
||||
const [left2, top2, right2, bottom2] = [closestDisplay.bounds.x, closestDisplay.bounds.y, closestDisplay.bounds.x + closestDisplay.bounds.width, closestDisplay.bounds.y + closestDisplay.bounds.height]
|
||||
|
||||
if ((left2 > right1 || right2 < left1 || top2 > bottom1 || bottom2 < top1) && !maximized) {
|
||||
bwOptions.x = closestDisplay.bounds.width / 2 - bwOptions.width / 2
|
||||
bwOptions.y = closestDisplay.bounds.height / 2 - bwOptions.height / 2
|
||||
}
|
||||
}
|
||||
|
||||
if ((this.configStore.appearance || {}).frame === 'native') {
|
||||
bwOptions.frame = true
|
||||
} else {
|
||||
if (process.platform === 'darwin') {
|
||||
bwOptions.titleBarStyle = 'hiddenInset'
|
||||
}
|
||||
}
|
||||
|
||||
this.window = new glasstron.BrowserWindow(bwOptions)
|
||||
|
||||
this.window.once('ready-to-show', () => {
|
||||
if (process.platform === 'darwin') {
|
||||
this.window.setVibrancy('window')
|
||||
} else if (process.platform === 'win32' && (this.configStore.appearance || {}).vibrancy) {
|
||||
this.setVibrancy(true)
|
||||
}
|
||||
|
||||
if (!options.hidden) {
|
||||
if (maximized) {
|
||||
this.window.maximize()
|
||||
} else {
|
||||
this.window.show()
|
||||
}
|
||||
this.window.focus()
|
||||
this.window.moveTop()
|
||||
}
|
||||
})
|
||||
|
||||
this.window.on('blur', () => {
|
||||
if (this.configStore.appearance?.dockHideOnBlur) {
|
||||
this.hide()
|
||||
}
|
||||
})
|
||||
|
||||
this.window.loadURL(`file://${app.getAppPath()}/dist/index.html?${this.window.id}`, { extraHeaders: 'pragma: no-cache\n' })
|
||||
|
||||
if (process.platform !== 'darwin') {
|
||||
this.window.setMenu(null)
|
||||
}
|
||||
|
||||
this.setupWindowManagement()
|
||||
|
||||
this.ready = new Promise(resolve => {
|
||||
const listener = event => {
|
||||
if (event.sender === this.window.webContents) {
|
||||
ipcMain.removeListener('app:ready', listener as any)
|
||||
resolve()
|
||||
}
|
||||
}
|
||||
ipcMain.on('app:ready', listener)
|
||||
})
|
||||
}
|
||||
|
||||
setVibrancy (enabled: boolean, type?: string, userRequested?: boolean): void {
|
||||
if (userRequested ?? true) {
|
||||
this.lastVibrancy = { enabled, type }
|
||||
}
|
||||
if (process.platform === 'win32') {
|
||||
if (parseFloat(os.release()) >= 10) {
|
||||
this.window.blurType = enabled ? type === 'fluent' ? 'acrylic' : 'blurbehind' : null
|
||||
this.window.setBlur(enabled)
|
||||
} else {
|
||||
DwmEnableBlurBehindWindow(this.window, enabled)
|
||||
}
|
||||
} else if (process.platform === 'linux') {
|
||||
this.window.setBackgroundColor(enabled ? '#00000000' : '#131d27')
|
||||
this.window.setBlur(enabled)
|
||||
} else {
|
||||
this.window.setVibrancy(enabled ? 'dark' : null as any) // electron issue 20269
|
||||
}
|
||||
}
|
||||
|
||||
show (): void {
|
||||
this.window.show()
|
||||
this.window.moveTop()
|
||||
}
|
||||
|
||||
focus (): void {
|
||||
this.window.focus()
|
||||
}
|
||||
|
||||
send (event: string, ...args: any[]): void {
|
||||
if (!this.window) {
|
||||
return
|
||||
}
|
||||
this.window.webContents.send(event, ...args)
|
||||
if (event === 'host:config-change') {
|
||||
this.configStore = args[0]
|
||||
}
|
||||
}
|
||||
|
||||
isDestroyed (): boolean {
|
||||
return !this.window || this.window.isDestroyed()
|
||||
}
|
||||
|
||||
isFocused (): boolean {
|
||||
return this.window.isFocused()
|
||||
}
|
||||
|
||||
hide (): void {
|
||||
if (process.platform === 'darwin') {
|
||||
// Lose focus
|
||||
Menu.sendActionToFirstResponder('hide:')
|
||||
}
|
||||
this.window.blur()
|
||||
if (process.platform !== 'darwin') {
|
||||
this.window.hide()
|
||||
}
|
||||
}
|
||||
|
||||
present (): void {
|
||||
if (!this.window.isVisible()) {
|
||||
// unfocused, invisible
|
||||
this.window.show()
|
||||
this.window.focus()
|
||||
} else {
|
||||
if (!this.configStore.appearance?.dock || this.configStore.appearance?.dock === 'off') {
|
||||
// not docked, visible
|
||||
setTimeout(() => {
|
||||
this.window.show()
|
||||
this.window.focus()
|
||||
})
|
||||
} else {
|
||||
if (this.configStore.appearance?.dockAlwaysOnTop) {
|
||||
// docked, visible, on top
|
||||
this.window.hide()
|
||||
} else {
|
||||
// docked, visible, not on top
|
||||
this.window.focus()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
handleSecondInstance (argv: string[], cwd: string): void {
|
||||
this.send('host:second-instance', parseArgs(argv, cwd), cwd)
|
||||
}
|
||||
|
||||
private setupWindowManagement () {
|
||||
this.window.on('show', () => {
|
||||
this.visible.next(true)
|
||||
this.send('host:window-shown')
|
||||
})
|
||||
|
||||
this.window.on('hide', () => {
|
||||
this.visible.next(false)
|
||||
})
|
||||
|
||||
const moveSubscription = new Observable<void>(observer => {
|
||||
this.window.on('move', () => observer.next())
|
||||
}).pipe(debounceTime(250)).subscribe(() => {
|
||||
this.send('host:window-moved')
|
||||
})
|
||||
|
||||
this.window.on('closed', () => {
|
||||
moveSubscription.unsubscribe()
|
||||
})
|
||||
|
||||
this.window.on('enter-full-screen', () => this.send('host:window-enter-full-screen'))
|
||||
this.window.on('leave-full-screen', () => this.send('host:window-leave-full-screen'))
|
||||
|
||||
this.window.on('close', event => {
|
||||
if (!this.closing) {
|
||||
event.preventDefault()
|
||||
this.send('host:window-close-request')
|
||||
return
|
||||
}
|
||||
this.windowConfig.set('windowBoundaries', this.windowBounds)
|
||||
this.windowConfig.set('maximized', this.window.isMaximized())
|
||||
})
|
||||
|
||||
this.window.on('closed', () => {
|
||||
this.destroy()
|
||||
})
|
||||
|
||||
this.window.on('resize', () => {
|
||||
if (!this.window.isMaximized()) {
|
||||
this.windowBounds = this.window.getBounds()
|
||||
}
|
||||
})
|
||||
|
||||
this.window.on('move', () => {
|
||||
if (!this.window.isMaximized()) {
|
||||
this.windowBounds = this.window.getBounds()
|
||||
}
|
||||
})
|
||||
|
||||
this.window.on('focus', () => {
|
||||
this.send('host:window-focused')
|
||||
})
|
||||
|
||||
ipcMain.on('window-focus', event => {
|
||||
if (!this.window || event.sender !== this.window.webContents) {
|
||||
return
|
||||
}
|
||||
this.window.focus()
|
||||
})
|
||||
|
||||
ipcMain.on('window-maximize', event => {
|
||||
if (!this.window || event.sender !== this.window.webContents) {
|
||||
return
|
||||
}
|
||||
this.window.maximize()
|
||||
})
|
||||
|
||||
ipcMain.on('window-unmaximize', event => {
|
||||
if (!this.window || event.sender !== this.window.webContents) {
|
||||
return
|
||||
}
|
||||
this.window.unmaximize()
|
||||
})
|
||||
|
||||
ipcMain.on('window-toggle-maximize', event => {
|
||||
if (!this.window || event.sender !== this.window.webContents) {
|
||||
return
|
||||
}
|
||||
if (this.window.isMaximized()) {
|
||||
this.window.unmaximize()
|
||||
} else {
|
||||
this.window.maximize()
|
||||
}
|
||||
})
|
||||
|
||||
ipcMain.on('window-minimize', event => {
|
||||
if (!this.window || event.sender !== this.window.webContents) {
|
||||
return
|
||||
}
|
||||
this.window.minimize()
|
||||
})
|
||||
|
||||
ipcMain.on('window-set-bounds', (event, bounds) => {
|
||||
if (!this.window || event.sender !== this.window.webContents) {
|
||||
return
|
||||
}
|
||||
this.window.setBounds(bounds)
|
||||
})
|
||||
|
||||
ipcMain.on('window-set-always-on-top', (event, flag) => {
|
||||
if (!this.window || event.sender !== this.window.webContents) {
|
||||
return
|
||||
}
|
||||
this.window.setAlwaysOnTop(flag)
|
||||
})
|
||||
|
||||
ipcMain.on('window-set-vibrancy', (event, enabled, type) => {
|
||||
if (!this.window || event.sender !== this.window.webContents) {
|
||||
return
|
||||
}
|
||||
this.setVibrancy(enabled, type)
|
||||
})
|
||||
|
||||
ipcMain.on('window-set-title', (event, title) => {
|
||||
if (!this.window || event.sender !== this.window.webContents) {
|
||||
return
|
||||
}
|
||||
this.window.setTitle(title)
|
||||
})
|
||||
|
||||
ipcMain.on('window-bring-to-front', event => {
|
||||
if (!this.window || event.sender !== this.window.webContents) {
|
||||
return
|
||||
}
|
||||
if (this.window.isMinimized()) {
|
||||
this.window.restore()
|
||||
}
|
||||
this.window.show()
|
||||
this.window.moveTop()
|
||||
})
|
||||
|
||||
ipcMain.on('window-close', event => {
|
||||
if (!this.window || event.sender !== this.window.webContents) {
|
||||
return
|
||||
}
|
||||
this.closing = true
|
||||
this.window.close()
|
||||
})
|
||||
|
||||
this.window.webContents.on('new-window', event => event.preventDefault())
|
||||
|
||||
ipcMain.on('window-set-disable-vibrancy-while-dragging', (_event, value) => {
|
||||
this.disableVibrancyWhileDragging = value
|
||||
})
|
||||
|
||||
let moveEndedTimeout: number|null = null
|
||||
const onBoundsChange = () => {
|
||||
if (!this.lastVibrancy?.enabled || !this.disableVibrancyWhileDragging) {
|
||||
return
|
||||
}
|
||||
this.setVibrancy(false, undefined, false)
|
||||
if (moveEndedTimeout) {
|
||||
clearTimeout(moveEndedTimeout)
|
||||
}
|
||||
moveEndedTimeout = setTimeout(() => {
|
||||
this.setVibrancy(this.lastVibrancy.enabled, this.lastVibrancy.type)
|
||||
}, 50)
|
||||
}
|
||||
this.window.on('move', onBoundsChange)
|
||||
this.window.on('resize', onBoundsChange)
|
||||
}
|
||||
|
||||
private destroy () {
|
||||
this.window = null
|
||||
this.closed.next()
|
||||
this.visible.complete()
|
||||
this.closed.complete()
|
||||
}
|
||||
}
|
300
app/main.js
Normal file
@@ -0,0 +1,300 @@
|
||||
if (process.platform == 'win32' && require('electron-squirrel-startup')) process.exit(0)
|
||||
|
||||
const electron = require('electron')
|
||||
let electronVibrancy
|
||||
if (process.platform != 'linux') {
|
||||
electronVibrancy = require('electron-vibrancy')
|
||||
}
|
||||
|
||||
if (process.argv.indexOf('--debug') !== -1) {
|
||||
require('electron-debug')({enabled: true, showDevTools: 'undocked'})
|
||||
}
|
||||
|
||||
let app = electron.app
|
||||
|
||||
let secondInstance = app.makeSingleInstance((argv, cwd) => {
|
||||
app.window.webContents.send('host:second-instance', argv, cwd)
|
||||
})
|
||||
|
||||
if (secondInstance) {
|
||||
app.quit()
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
const yaml = require('js-yaml')
|
||||
const path = require('path')
|
||||
const fs = require('fs')
|
||||
const Config = require('electron-config')
|
||||
let windowConfig = new Config({name: 'window'})
|
||||
|
||||
|
||||
if (!process.env.TERMINUS_PLUGINS) {
|
||||
process.env.TERMINUS_PLUGINS = ''
|
||||
}
|
||||
|
||||
setWindowVibrancy = (enabled) => {
|
||||
if (enabled && !app.window.vibrancyViewID) {
|
||||
app.window.vibrancyViewID = electronVibrancy.SetVibrancy(app.window, 0)
|
||||
} else if (!enabled && app.window.vibrancyViewID) {
|
||||
electronVibrancy.RemoveView(app.window, app.window.vibrancyViewID)
|
||||
app.window.vibrancyViewID = null
|
||||
}
|
||||
}
|
||||
|
||||
setupWindowManagement = () => {
|
||||
app.window.on('show', () => {
|
||||
app.window.webContents.send('host:window-shown')
|
||||
if (app.tray) {
|
||||
app.tray.destroy()
|
||||
app.tray = null
|
||||
}
|
||||
})
|
||||
|
||||
app.window.on('hide', (e) => {
|
||||
if (!app.tray) {
|
||||
setupTray()
|
||||
}
|
||||
})
|
||||
|
||||
app.window.on('enter-full-screen', () => app.window.webContents.send('host:window-enter-full-screen'))
|
||||
app.window.on('leave-full-screen', () => app.window.webContents.send('host:window-leave-full-screen'))
|
||||
|
||||
app.window.on('close', (e) => {
|
||||
windowConfig.set('windowBoundaries', app.window.getBounds())
|
||||
})
|
||||
|
||||
app.window.on('closed', () => {
|
||||
app.window = null
|
||||
})
|
||||
|
||||
electron.ipcMain.on('window-focus', () => {
|
||||
app.window.focus()
|
||||
})
|
||||
|
||||
electron.ipcMain.on('window-maximize', () => {
|
||||
app.window.maximize()
|
||||
})
|
||||
|
||||
electron.ipcMain.on('window-unmaximize', () => {
|
||||
app.window.unmaximize()
|
||||
})
|
||||
|
||||
electron.ipcMain.on('window-toggle-maximize', () => {
|
||||
if (app.window.isMaximized()) {
|
||||
app.window.unmaximize()
|
||||
} else {
|
||||
app.window.maximize()
|
||||
}
|
||||
})
|
||||
|
||||
electron.ipcMain.on('window-minimize', () => {
|
||||
app.window.minimize()
|
||||
})
|
||||
|
||||
electron.ipcMain.on('window-set-bounds', (event, bounds) => {
|
||||
app.window.setBounds(bounds)
|
||||
})
|
||||
|
||||
electron.ipcMain.on('window-set-always-on-top', (event, flag) => {
|
||||
app.window.setAlwaysOnTop(flag)
|
||||
})
|
||||
|
||||
electron.ipcMain.on('window-set-vibrancy', (event, enabled) => {
|
||||
setWindowVibrancy(enabled)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
setupTray = () => {
|
||||
if (process.platform == 'darwin') {
|
||||
app.tray = new electron.Tray(`${app.getAppPath()}/assets/tray-darwinTemplate.png`)
|
||||
app.tray.setPressedImage(`${app.getAppPath()}/assets/tray-darwinHighlightTemplate.png`)
|
||||
} else {
|
||||
app.tray = new electron.Tray(`${app.getAppPath()}/assets/tray.png`)
|
||||
}
|
||||
|
||||
app.tray.on('click', () => {
|
||||
app.window.show()
|
||||
app.window.focus()
|
||||
})
|
||||
|
||||
const contextMenu = electron.Menu.buildFromTemplate([{
|
||||
label: 'Show',
|
||||
click () {
|
||||
app.window.show()
|
||||
app.window.focus()
|
||||
}
|
||||
}])
|
||||
|
||||
if (process.platform != 'darwin') {
|
||||
app.tray.setContextMenu(contextMenu)
|
||||
}
|
||||
|
||||
app.tray.setToolTip(`Terminus ${app.getVersion()}`)
|
||||
}
|
||||
|
||||
|
||||
setupMenu = () => {
|
||||
let template = [{
|
||||
label: "Application",
|
||||
submenu: [
|
||||
{ role: 'about', label: 'About Terminus' },
|
||||
{ type: 'separator' },
|
||||
{
|
||||
label: 'Preferences',
|
||||
accelerator: 'Cmd+,',
|
||||
click () {
|
||||
app.window.webContents.send('host:preferences-menu')
|
||||
}
|
||||
},
|
||||
{ type: 'separator' },
|
||||
{ role: 'services', submenu: [] },
|
||||
{ type: 'separator' },
|
||||
{ role: 'hide' },
|
||||
{ role: 'hideothers' },
|
||||
{ role: 'unhide' },
|
||||
{ type: 'separator' },
|
||||
{
|
||||
label: 'Quit',
|
||||
accelerator: 'Cmd+Q',
|
||||
click () {
|
||||
app.quit()
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
label: "Edit",
|
||||
submenu: [
|
||||
{role: 'undo'},
|
||||
{role: 'redo'},
|
||||
{type: 'separator'},
|
||||
{role: 'cut'},
|
||||
{role: 'copy'},
|
||||
{role: 'paste'},
|
||||
{role: 'pasteandmatchstyle'},
|
||||
{role: 'delete'},
|
||||
{role: 'selectall'}
|
||||
]
|
||||
},
|
||||
{
|
||||
label: 'View',
|
||||
submenu: [
|
||||
{role: 'reload'},
|
||||
{role: 'forcereload'},
|
||||
{role: 'toggledevtools'},
|
||||
{type: 'separator'},
|
||||
{role: 'resetzoom'},
|
||||
{role: 'zoomin'},
|
||||
{role: 'zoomout'},
|
||||
{type: 'separator'},
|
||||
{role: 'togglefullscreen'}
|
||||
]
|
||||
},
|
||||
{
|
||||
role: 'window',
|
||||
submenu: [
|
||||
{role: 'minimize'},
|
||||
{role: 'zoom'},
|
||||
{type: 'separator'},
|
||||
{role: 'front'}
|
||||
]
|
||||
},
|
||||
{
|
||||
role: 'help',
|
||||
submenu: [
|
||||
{
|
||||
label: 'Website',
|
||||
click () { electron.shell.openExternal('https://eugeny.github.io/terminus') }
|
||||
}
|
||||
]
|
||||
}]
|
||||
|
||||
electron.Menu.setApplicationMenu(electron.Menu.buildFromTemplate(template))
|
||||
}
|
||||
|
||||
|
||||
start = () => {
|
||||
let t0 = Date.now()
|
||||
|
||||
let configPath = path.join(electron.app.getPath('userData'), 'config.yaml')
|
||||
let configData
|
||||
if (fs.existsSync(configPath)) {
|
||||
configData = yaml.safeLoad(fs.readFileSync(configPath, 'utf8'))
|
||||
} else {
|
||||
configData = {}
|
||||
}
|
||||
|
||||
let options = {
|
||||
width: 800,
|
||||
height: 600,
|
||||
title: 'Terminus',
|
||||
minWidth: 400,
|
||||
minHeight: 300,
|
||||
webPreferences: {webSecurity: false},
|
||||
frame: false,
|
||||
show: false,
|
||||
}
|
||||
Object.assign(options, windowConfig.get('windowBoundaries'))
|
||||
|
||||
if ((configData.appearance || {}).frame == 'native') {
|
||||
options.frame = true
|
||||
} else {
|
||||
if (process.platform == 'darwin') {
|
||||
options.titleBarStyle = 'hiddenInset'
|
||||
}
|
||||
}
|
||||
|
||||
if (process.platform == 'linux') {
|
||||
options.backgroundColor = '#131d27'
|
||||
}
|
||||
|
||||
app.commandLine.appendSwitch('disable-http-cache')
|
||||
|
||||
app.window = new electron.BrowserWindow(options)
|
||||
app.window.once('ready-to-show', () => {
|
||||
if (process.platform == 'darwin') {
|
||||
app.window.setVibrancy('dark')
|
||||
} else if (process.platform == 'windows') {
|
||||
setWindowVibrancy(true)
|
||||
}
|
||||
app.window.show()
|
||||
app.window.focus()
|
||||
})
|
||||
app.window.loadURL(`file://${app.getAppPath()}/dist/index.html`, {extraHeaders: "pragma: no-cache\n"})
|
||||
|
||||
if (process.platform != 'darwin') {
|
||||
app.window.setMenu(null)
|
||||
}
|
||||
|
||||
setupWindowManagement()
|
||||
|
||||
if (process.platform == 'darwin') {
|
||||
setupMenu()
|
||||
} else {
|
||||
app.window.setMenu(null)
|
||||
}
|
||||
|
||||
console.info(`Host startup: ${Date.now() - t0}ms`)
|
||||
t0 = Date.now()
|
||||
electron.ipcMain.on('app:ready', () => {
|
||||
console.info(`App startup: ${Date.now() - t0}ms`)
|
||||
})
|
||||
}
|
||||
|
||||
app.on('ready', start)
|
||||
|
||||
app.on('activate', () => {
|
||||
if (!app.window)
|
||||
start()
|
||||
else {
|
||||
app.window.show()
|
||||
app.window.focus()
|
||||
}
|
||||
})
|
||||
|
||||
process.on('uncaughtException', function(err) {
|
||||
console.log(err)
|
||||
app.window.webContents.send('uncaughtException', err)
|
||||
})
|
@@ -1,62 +1,39 @@
|
||||
{
|
||||
"name": "terminus",
|
||||
"description": "A terminal for a modern age",
|
||||
"repository": "https://github.com/eugeny/terminus",
|
||||
"author": {
|
||||
"name": "Eugene Pankov",
|
||||
"email": "e@ajenti.org"
|
||||
},
|
||||
"main": "dist/main.js",
|
||||
"main": "main.js",
|
||||
"version": "1.0.0-alpha.1",
|
||||
"scripts": {
|
||||
"build": "webpack --progress --color --display-modules",
|
||||
"watch": "webpack --progress --color --watch"
|
||||
},
|
||||
"dependencies": {
|
||||
"@angular/animations": "^9.1.9",
|
||||
"@angular/common": "^9.1.11",
|
||||
"@angular/compiler": "^9.1.9",
|
||||
"@angular/core": "^9.1.9",
|
||||
"@angular/forms": "^9.1.11",
|
||||
"@angular/platform-browser": "^9.1.9",
|
||||
"@angular/platform-browser-dynamic": "^9.1.9",
|
||||
"@ng-bootstrap/ng-bootstrap": "^6.1.0",
|
||||
"@terminus-term/node-pty": "0.10.0-beta10",
|
||||
"electron-config": "2.0.0",
|
||||
"electron-debug": "^3.0.1",
|
||||
"electron-is-dev": "1.1.0",
|
||||
"fontmanager-redux": "1.0.0",
|
||||
"glasstron": "0.0.5",
|
||||
"js-yaml": "3.14.0",
|
||||
"keytar": "^7.2.0",
|
||||
"mz": "^2.7.0",
|
||||
"ngx-toastr": "^12.0.1",
|
||||
"npm": "7.0.15",
|
||||
"@angular/animations": "6.0.2",
|
||||
"@angular/common": "6.0.2",
|
||||
"@angular/compiler": "6.0.2",
|
||||
"@angular/core": "6.0.2",
|
||||
"@angular/forms": "6.0.2",
|
||||
"@angular/platform-browser": "6.0.2",
|
||||
"@angular/platform-browser-dynamic": "6.0.2",
|
||||
"@ng-bootstrap/ng-bootstrap": "^2.0.0",
|
||||
"devtron": "1.4.0",
|
||||
"electron-config": "0.2.1",
|
||||
"electron-debug": "^1.0.1",
|
||||
"electron-is-dev": "0.1.2",
|
||||
"electron-squirrel-startup": "^1.0.0",
|
||||
"electron-vibrancy": "^0.1.3",
|
||||
"js-yaml": "3.8.2",
|
||||
"mz": "^2.6.0",
|
||||
"ngx-toastr": "^8.7.3",
|
||||
"path": "0.12.7",
|
||||
"rxjs": "^6.5.5",
|
||||
"rxjs-compat": "^6.6.0",
|
||||
"yargs": "^15.4.1",
|
||||
"zone.js": "^0.11.3"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"macos-native-processlist": "^2.0.0",
|
||||
"serialport": "^9.0.4",
|
||||
"windows-blurbehind": "^1.0.1",
|
||||
"windows-native-registry": "^3.0.0",
|
||||
"windows-process-tree": "^0.2.4"
|
||||
"rxjs": "^6.1.0",
|
||||
"zone.js": "~0.8.26"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/mz": "0.0.32",
|
||||
"@types/node": "14.14.14",
|
||||
"node-abi": "2.19.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"terminus-community-color-schemes": "*",
|
||||
"terminus-core": "*",
|
||||
"terminus-plugin-manager": "*",
|
||||
"terminus-serial": "*",
|
||||
"terminus-settings": "*",
|
||||
"terminus-ssh": "*",
|
||||
"terminus-terminal": "*"
|
||||
"@types/mz": "0.0.31"
|
||||
}
|
||||
}
|
||||
|
@@ -1,23 +1,21 @@
|
||||
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
||||
import { NgModule } from '@angular/core'
|
||||
import { BrowserModule } from '@angular/platform-browser'
|
||||
import { NgbModule } from '@ng-bootstrap/ng-bootstrap'
|
||||
import { ToastrModule } from 'ngx-toastr'
|
||||
|
||||
export function getRootModule (plugins: any[]) {
|
||||
const imports = [
|
||||
let imports = [
|
||||
BrowserModule,
|
||||
...plugins,
|
||||
NgbModule,
|
||||
NgbModule.forRoot(),
|
||||
ToastrModule.forRoot({
|
||||
positionClass: 'toast-bottom-center',
|
||||
toastClass: 'toast',
|
||||
preventDuplicates: true,
|
||||
extendedTimeOut: 5000,
|
||||
}),
|
||||
]
|
||||
const bootstrap = [
|
||||
...plugins.filter(x => x.bootstrap).map(x => x.bootstrap),
|
||||
let bootstrap = [
|
||||
...(plugins.filter(x => x.bootstrap).map(x => x.bootstrap)),
|
||||
]
|
||||
|
||||
if (bootstrap.length === 0) {
|
||||
@@ -27,7 +25,7 @@ export function getRootModule (plugins: any[]) {
|
||||
@NgModule({
|
||||
imports,
|
||||
bootstrap,
|
||||
}) class RootModule { } // eslint-disable-line @typescript-eslint/no-extraneous-class
|
||||
}) class RootModule { }
|
||||
|
||||
return RootModule
|
||||
}
|
||||
|
@@ -1,9 +1,38 @@
|
||||
import '../lib/lru'
|
||||
import 'source-sans-pro/source-sans-pro.css'
|
||||
import 'source-code-pro/source-code-pro.css'
|
||||
import '@fortawesome/fontawesome-free/css/solid.css'
|
||||
import '@fortawesome/fontawesome-free/css/brands.css'
|
||||
import '@fortawesome/fontawesome-free/css/regular.css'
|
||||
import '@fortawesome/fontawesome-free/css/fontawesome.css'
|
||||
import 'source-sans-pro'
|
||||
import 'font-awesome/css/font-awesome.css'
|
||||
import 'ngx-toastr/toastr.css'
|
||||
import './preload.scss'
|
||||
|
||||
import * as Raven from 'raven-js'
|
||||
|
||||
const SENTRY_DSN = 'https://4717a0a7ee0b4429bd3a0f06c3d7eec3@sentry.io/181876'
|
||||
|
||||
Raven.config(
|
||||
SENTRY_DSN,
|
||||
{
|
||||
release: require('electron').remote.app.getVersion(),
|
||||
dataCallback: (data: any) => {
|
||||
const normalize = (filename) => {
|
||||
let splitArray = filename.split('/')
|
||||
return splitArray[splitArray.length - 1]
|
||||
}
|
||||
|
||||
data.exception.values[0].stacktrace.frames.forEach(frame => {
|
||||
frame.filename = normalize(frame.filename)
|
||||
})
|
||||
|
||||
data.culprit = data.exception.values[0].stacktrace.frames[0].filename
|
||||
|
||||
return data
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
process.on('uncaughtException', (err) => {
|
||||
Raven.captureException(err)
|
||||
console.error(err)
|
||||
})
|
||||
|
||||
const childProcess = require('child_process')
|
||||
childProcess.spawn = require('electron').remote.require('child_process').spawn
|
||||
childProcess.exec = require('electron').remote.require('child_process').exec
|
||||
|
@@ -1,51 +1,38 @@
|
||||
import 'zone.js'
|
||||
import 'core-js/proposals/reflect-metadata'
|
||||
import 'core-js/es7/reflect'
|
||||
import 'core-js/core/delay'
|
||||
import 'rxjs'
|
||||
|
||||
import * as isDev from 'electron-is-dev'
|
||||
|
||||
import './global.scss'
|
||||
import './toastr.scss'
|
||||
|
||||
import { enableProdMode, NgModuleRef, ApplicationRef } from '@angular/core'
|
||||
import { enableDebugTools } from '@angular/platform-browser'
|
||||
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'
|
||||
|
||||
import { getRootModule } from './app.module'
|
||||
import { findPlugins, loadPlugins, PluginInfo } from './plugins'
|
||||
|
||||
// Always land on the start view
|
||||
location.hash = ''
|
||||
|
||||
;(process as any).enablePromiseAPI = true
|
||||
import { enableProdMode, NgModuleRef } from '@angular/core'
|
||||
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'
|
||||
|
||||
if (process.platform === 'win32' && !('HOME' in process.env)) {
|
||||
process.env.HOME = `${process.env.HOMEDRIVE}${process.env.HOMEPATH}`
|
||||
import { getRootModule } from './app.module'
|
||||
import { findPlugins, loadPlugins, IPluginInfo } from './plugins'
|
||||
|
||||
if (process.platform === 'win32') {
|
||||
process.env.HOME = process.env.HOMEDRIVE + process.env.HOMEPATH
|
||||
}
|
||||
|
||||
if (isDev) {
|
||||
if (require('electron-is-dev')) {
|
||||
console.warn('Running in debug mode')
|
||||
} else {
|
||||
enableProdMode()
|
||||
}
|
||||
|
||||
async function bootstrap (plugins: PluginInfo[], safeMode = false): Promise<NgModuleRef<any>> {
|
||||
async function bootstrap (plugins: IPluginInfo[], safeMode = false): Promise<NgModuleRef<any>> {
|
||||
if (safeMode) {
|
||||
plugins = plugins.filter(x => x.isBuiltin)
|
||||
}
|
||||
const pluginsModules = await loadPlugins(plugins, (current, total) => {
|
||||
(document.querySelector('.progress .bar') as HTMLElement).style.width = `${100 * current / total}%` // eslint-disable-line
|
||||
let pluginsModules = await loadPlugins(plugins, (current, total) => {
|
||||
(document.querySelector('.progress .bar') as HTMLElement).style.width = 100 * current / total + '%'
|
||||
})
|
||||
const module = getRootModule(pluginsModules)
|
||||
let module = getRootModule(pluginsModules)
|
||||
window['rootModule'] = module
|
||||
return platformBrowserDynamic().bootstrapModule(module).then(moduleRef => {
|
||||
if (isDev) {
|
||||
const applicationRef = moduleRef.injector.get(ApplicationRef)
|
||||
const componentRef = applicationRef.components[0]
|
||||
enableDebugTools(componentRef)
|
||||
}
|
||||
return moduleRef
|
||||
})
|
||||
return await platformBrowserDynamic().bootstrapModule(module)
|
||||
}
|
||||
|
||||
findPlugins().then(async plugins => {
|
||||
|
@@ -1,97 +0,0 @@
|
||||
body {
|
||||
min-height: 100vh;
|
||||
overflow: hidden;
|
||||
background: #1D272D;
|
||||
}
|
||||
|
||||
.modal-dialog, .modal-backdrop, .no-drag {
|
||||
-webkit-app-region: no-drag;
|
||||
}
|
||||
|
||||
.selectable {
|
||||
user-select: text;
|
||||
}
|
||||
|
||||
[ngbradiogroup] input[type="radio"] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.btn {
|
||||
& > svg {
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
|
||||
.form-line {
|
||||
display: flex;
|
||||
border-top: 1px solid rgba(0, 0, 0, 0.2);
|
||||
align-items: center;
|
||||
padding: 10px 0;
|
||||
margin: 0;
|
||||
min-height: 64px;
|
||||
|
||||
.header {
|
||||
margin-right: auto;
|
||||
|
||||
.title {
|
||||
}
|
||||
|
||||
.description {
|
||||
font-size: 13px;
|
||||
opacity: .5;
|
||||
}
|
||||
}
|
||||
|
||||
&>.form-control, &>.input-group {
|
||||
width: 33%;
|
||||
}
|
||||
}
|
||||
|
||||
input[type=range] {
|
||||
-webkit-appearance: none;
|
||||
background: transparent;
|
||||
outline: none;
|
||||
padding: 0;
|
||||
|
||||
&:focus {
|
||||
border-color: transparent;
|
||||
}
|
||||
|
||||
@mixin thumb() {
|
||||
-webkit-appearance: none;
|
||||
display: block;
|
||||
height: 12px;
|
||||
width: 12px;
|
||||
background: #aaa;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
margin-top: -4px;
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.95);
|
||||
transition: 0.25s background;
|
||||
|
||||
&:hover {
|
||||
background: #777;
|
||||
}
|
||||
|
||||
&:active {
|
||||
background: #666;
|
||||
}
|
||||
}
|
||||
|
||||
&::-webkit-slider-thumb { @include thumb(); }
|
||||
&::-moz-range-thumb { @include thumb(); }
|
||||
&::-ms-thumb { @include thumb(); }
|
||||
&::thumb { @include thumb(); }
|
||||
|
||||
@mixin track() {
|
||||
height: 4px;
|
||||
background: #111;
|
||||
margin: 3px 0 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
&::-webkit-slider-runnable-track { @include track(); }
|
||||
&:focus::-webkit-slider-runnable-track { @include track(); }
|
||||
&::-moz-range-track { @include track(); }
|
||||
&::-ms-track { @include track(); }
|
||||
}
|
@@ -1,8 +1,10 @@
|
||||
import * as fs from 'mz/fs'
|
||||
import * as path from 'path'
|
||||
const nodeModule = require('module') // eslint-disable-line @typescript-eslint/no-var-requires
|
||||
const nodeModule = require('module')
|
||||
const nodeRequire = (global as any).require
|
||||
|
||||
declare function delay (ms: number): Promise<void>
|
||||
|
||||
function normalizePath (path: string): string {
|
||||
const cygwinPrefix = '/cygdrive/'
|
||||
if (path.startsWith(cygwinPrefix)) {
|
||||
@@ -12,23 +14,20 @@ function normalizePath (path: string): string {
|
||||
return path
|
||||
}
|
||||
|
||||
global['module'].paths.map((x: string) => nodeModule.globalPaths.push(normalizePath(x)))
|
||||
nodeRequire.main.paths.map(x => nodeModule.globalPaths.push(normalizePath(x)))
|
||||
|
||||
if (process.env.TERMINUS_DEV) {
|
||||
if (process.env.DEV) {
|
||||
nodeModule.globalPaths.unshift(path.dirname(require('electron').remote.app.getAppPath()))
|
||||
}
|
||||
|
||||
const builtinPluginsPath = process.env.TERMINUS_DEV ? path.dirname(require('electron').remote.app.getAppPath()) : path.join((process as any).resourcesPath, 'builtin-plugins')
|
||||
const builtinPluginsPath = process.env.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('userData'),
|
||||
require('electron').remote.app.getPath('appData'),
|
||||
'terminus',
|
||||
'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'))
|
||||
@@ -37,9 +36,9 @@ if (process.env.TERMINUS_PLUGINS) {
|
||||
process.env.TERMINUS_PLUGINS.split(':').map(x => nodeModule.globalPaths.push(normalizePath(x)))
|
||||
}
|
||||
|
||||
export type ProgressCallback = (current: number, total: number) => void // eslint-disable-line @typescript-eslint/no-type-alias
|
||||
export declare type ProgressCallback = (current, total) => void
|
||||
|
||||
export interface PluginInfo {
|
||||
export interface IPluginInfo {
|
||||
name: string
|
||||
description: string
|
||||
packageName: string
|
||||
@@ -63,7 +62,6 @@ const builtinModules = [
|
||||
'ngx-toastr',
|
||||
'rxjs',
|
||||
'rxjs/operators',
|
||||
'rxjs-compat/Subject',
|
||||
'terminus-core',
|
||||
'terminus-settings',
|
||||
'terminus-terminal',
|
||||
@@ -72,61 +70,47 @@ const builtinModules = [
|
||||
|
||||
const cachedBuiltinModules = {}
|
||||
builtinModules.forEach(m => {
|
||||
const label = 'Caching ' + m
|
||||
console.time(label)
|
||||
cachedBuiltinModules[m] = nodeRequire(m)
|
||||
console.timeEnd(label)
|
||||
})
|
||||
|
||||
const originalRequire = (global as any).require
|
||||
;(global as any).require = function (query: string) {
|
||||
const originalRequire = nodeRequire('module').prototype.require
|
||||
nodeRequire('module').prototype.require = function (query) {
|
||||
if (cachedBuiltinModules[query]) {
|
||||
return cachedBuiltinModules[query]
|
||||
}
|
||||
return originalRequire.apply(this, [query])
|
||||
return originalRequire.apply(this, arguments)
|
||||
}
|
||||
|
||||
const originalModuleRequire = nodeModule.prototype.require
|
||||
nodeModule.prototype.require = function (query: string) {
|
||||
if (cachedBuiltinModules[query]) {
|
||||
return cachedBuiltinModules[query]
|
||||
}
|
||||
return originalModuleRequire.call(this, query)
|
||||
}
|
||||
|
||||
export async function findPlugins (): Promise<PluginInfo[]> {
|
||||
const paths = nodeModule.globalPaths
|
||||
let foundPlugins: PluginInfo[] = []
|
||||
const candidateLocations: { pluginDir: string, packageName: string }[] = []
|
||||
const PREFIX = 'terminus-'
|
||||
export async function findPlugins (): Promise<IPluginInfo[]> {
|
||||
let paths = nodeModule.globalPaths
|
||||
let foundPlugins: IPluginInfo[] = []
|
||||
let candidateLocations: { pluginDir: string, packageName: string }[] = []
|
||||
|
||||
for (let pluginDir of paths) {
|
||||
pluginDir = normalizePath(pluginDir)
|
||||
if (!await fs.exists(pluginDir)) {
|
||||
continue
|
||||
}
|
||||
const pluginNames = await fs.readdir(pluginDir)
|
||||
let 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 (const packageName of pluginNames) {
|
||||
if (packageName.startsWith(PREFIX)) {
|
||||
candidateLocations.push({ pluginDir, packageName })
|
||||
}
|
||||
for (let packageName of pluginNames) {
|
||||
candidateLocations.push({ pluginDir, packageName })
|
||||
}
|
||||
}
|
||||
|
||||
for (const { pluginDir, packageName } of candidateLocations) {
|
||||
const pluginPath = path.join(pluginDir, packageName)
|
||||
const infoPath = path.join(pluginPath, 'package.json')
|
||||
for (let { pluginDir, packageName } of candidateLocations) {
|
||||
let pluginPath = path.join(pluginDir, packageName)
|
||||
let infoPath = path.join(pluginPath, 'package.json')
|
||||
if (!await fs.exists(infoPath)) {
|
||||
continue
|
||||
}
|
||||
|
||||
const name = packageName.substring(PREFIX.length)
|
||||
let name = packageName.substring('terminus-'.length)
|
||||
|
||||
if (foundPlugins.some(x => x.name === name)) {
|
||||
console.info(`Plugin ${packageName} already exists, overriding`)
|
||||
@@ -134,7 +118,7 @@ export async function findPlugins (): Promise<PluginInfo[]> {
|
||||
}
|
||||
|
||||
try {
|
||||
const info = JSON.parse(await fs.readFile(infoPath, { encoding: 'utf-8' }))
|
||||
let 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
|
||||
}
|
||||
@@ -155,32 +139,27 @@ export async function findPlugins (): Promise<PluginInfo[]> {
|
||||
}
|
||||
}
|
||||
|
||||
foundPlugins.sort((a, b) => a.name > b.name ? 1 : -1)
|
||||
|
||||
;(window as any).installedPlugins = foundPlugins
|
||||
(window as any).installedPlugins = foundPlugins
|
||||
return foundPlugins
|
||||
}
|
||||
|
||||
export async function loadPlugins (foundPlugins: PluginInfo[], progress: ProgressCallback): Promise<any[]> {
|
||||
const plugins: any[] = []
|
||||
export async function loadPlugins (foundPlugins: IPluginInfo[], progress: ProgressCallback): Promise<any[]> {
|
||||
let plugins: any[] = []
|
||||
progress(0, 1)
|
||||
let index = 0
|
||||
for (const foundPlugin of foundPlugins) {
|
||||
for (let foundPlugin of foundPlugins) {
|
||||
console.info(`Loading ${foundPlugin.name}: ${nodeRequire.resolve(foundPlugin.path)}`)
|
||||
progress(index, foundPlugins.length)
|
||||
try {
|
||||
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
|
||||
let packageModule = nodeRequire(foundPlugin.path)
|
||||
let pluginModule = packageModule.default.forRoot ? packageModule.default.forRoot() : packageModule.default
|
||||
pluginModule['pluginName'] = foundPlugin.name
|
||||
pluginModule['bootstrap'] = packageModule.bootstrap
|
||||
plugins.push(pluginModule)
|
||||
console.timeEnd(label)
|
||||
await new Promise(x => setTimeout(x, 50))
|
||||
} catch (error) {
|
||||
console.error(`Could not load ${foundPlugin.name}:`, error)
|
||||
}
|
||||
await delay(1)
|
||||
index++
|
||||
}
|
||||
progress(1, 1)
|
||||
|
@@ -58,3 +58,17 @@
|
||||
color: #842fe0;
|
||||
}
|
||||
}
|
||||
|
||||
.modal-dialog, .modal-backdrop {
|
||||
-webkit-app-region: no-drag;
|
||||
}
|
||||
|
||||
[ngbradiogroup] input[type="radio"] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
body {
|
||||
min-height: 100vh;
|
||||
overflow: hidden;
|
||||
background: rgba(0,0,0,.4);
|
||||
}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import { Component } from '@angular/core'
|
||||
|
||||
@Component({
|
||||
template: '<app-root></app-root>',
|
||||
template: '<app-root></app-root>'
|
||||
})
|
||||
export class RootComponent { } // eslint-disable-line @typescript-eslint/no-extraneous-class
|
||||
export class RootComponent { }
|
||||
|
@@ -2,18 +2,12 @@
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 20px;
|
||||
|
||||
.toast {
|
||||
box-shadow: 0 1px 0 rgba(0,0,0,.25);
|
||||
padding: 10px;
|
||||
background-image: none;
|
||||
width: auto;
|
||||
flex-basis: auto;
|
||||
|
||||
&.toast-error {
|
||||
background-color: #BD362F;
|
||||
}
|
||||
|
||||
&.toast-info {
|
||||
background-color: #555;
|
||||
|
@@ -9,6 +9,7 @@
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"sourceMap": true,
|
||||
"noUnusedParameters": true,
|
||||
"noImplicitReturns": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noUnusedParameters": true,
|
||||
@@ -16,7 +17,7 @@
|
||||
"lib": [
|
||||
"dom",
|
||||
"es2015",
|
||||
"es2015.iterable",
|
||||
"es2015.iterable.ts",
|
||||
"es2017",
|
||||
"es7"
|
||||
]
|
||||
|
@@ -1,30 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"baseUrl": "./lib",
|
||||
"module": "commonjs",
|
||||
"target": "es2017",
|
||||
"declaration": false,
|
||||
"noImplicitAny": false,
|
||||
"removeComments": false,
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"sourceMap": true,
|
||||
"noUnusedParameters": true,
|
||||
"noImplicitReturns": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noUnusedLocals": true,
|
||||
"lib": [
|
||||
"dom",
|
||||
"es2015",
|
||||
"es2015.iterable",
|
||||
"es2017",
|
||||
"es7"
|
||||
]
|
||||
},
|
||||
"compileOnSave": false,
|
||||
"exclude": [
|
||||
"dist",
|
||||
"node_modules",
|
||||
"*/node_modules"
|
||||
]
|
||||
}
|
@@ -5,21 +5,16 @@ module.exports = {
|
||||
name: 'terminus',
|
||||
target: 'node',
|
||||
entry: {
|
||||
'index.ignore': 'file-loader?name=index.html!pug-html-loader!' + path.resolve(__dirname, './index.pug'),
|
||||
sentry: path.resolve(__dirname, 'lib/sentry.ts'),
|
||||
preload: path.resolve(__dirname, 'src/entry.preload.ts'),
|
||||
bundle: path.resolve(__dirname, 'src/entry.ts'),
|
||||
},
|
||||
mode: process.env.TERMINUS_DEV ? 'development' : 'production',
|
||||
optimization:{
|
||||
minimize: false,
|
||||
'index.ignore': 'file-loader?name=index.html!val-loader!pug-html-loader!' + path.resolve(__dirname, './index.pug'),
|
||||
'preload': path.resolve(__dirname, 'src/entry.preload.ts'),
|
||||
'bundle': path.resolve(__dirname, 'src/entry.ts'),
|
||||
},
|
||||
context: __dirname,
|
||||
devtool: 'source-map',
|
||||
output: {
|
||||
path: path.join(__dirname, 'dist'),
|
||||
pathinfo: true,
|
||||
filename: '[name].js',
|
||||
filename: '[name].js'
|
||||
},
|
||||
resolve: {
|
||||
modules: ['src/', 'node_modules', '../node_modules', 'assets/'].map(x => path.join(__dirname, x)),
|
||||
@@ -33,8 +28,8 @@ module.exports = {
|
||||
loader: 'awesome-typescript-loader',
|
||||
options: {
|
||||
configFileName: path.resolve(__dirname, 'tsconfig.json'),
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
{ test: /\.scss$/, use: ['style-loader', 'css-loader', 'sass-loader'] },
|
||||
{ test: /\.css$/, use: ['style-loader', 'css-loader', 'sass-loader'] },
|
||||
@@ -43,20 +38,20 @@ module.exports = {
|
||||
use: {
|
||||
loader: 'file-loader',
|
||||
options: {
|
||||
name: 'images/[name].[ext]',
|
||||
},
|
||||
},
|
||||
name: 'images/[name].[ext]'
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
test: /\.(ttf|eot|otf|woff|woff2)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
|
||||
use: {
|
||||
loader: 'file-loader',
|
||||
options: {
|
||||
name: 'fonts/[name].[ext]',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
name: 'fonts/[name].[ext]'
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
externals: {
|
||||
'@angular/core': 'commonjs @angular/core',
|
||||
@@ -66,21 +61,17 @@ module.exports = {
|
||||
'@angular/forms': 'commonjs @angular/forms',
|
||||
'@angular/common': 'commonjs @angular/common',
|
||||
'@ng-bootstrap/ng-bootstrap': 'commonjs @ng-bootstrap/ng-bootstrap',
|
||||
child_process: 'commonjs child_process',
|
||||
electron: 'commonjs electron',
|
||||
'child_process': 'commonjs child_process',
|
||||
'electron': 'commonjs electron',
|
||||
'electron-is-dev': 'commonjs electron-is-dev',
|
||||
fs: 'commonjs fs',
|
||||
'ngx-toastr': 'commonjs ngx-toastr',
|
||||
module: 'commonjs module',
|
||||
mz: 'commonjs mz',
|
||||
path: 'commonjs path',
|
||||
rxjs: 'commonjs rxjs',
|
||||
'module': 'commonjs module',
|
||||
'mz': 'commonjs mz',
|
||||
'path': 'commonjs path',
|
||||
'rxjs': 'commonjs rxjs',
|
||||
'zone.js': 'commonjs zone.js/dist/zone.js',
|
||||
},
|
||||
plugins: [
|
||||
new webpack.optimize.ModuleConcatenationPlugin(),
|
||||
new webpack.DefinePlugin({
|
||||
'process.type': '"renderer"'
|
||||
}),
|
||||
],
|
||||
}
|
||||
|
@@ -1,53 +0,0 @@
|
||||
const path = require('path')
|
||||
const webpack = require('webpack')
|
||||
|
||||
module.exports = {
|
||||
name: 'terminus-main',
|
||||
target: 'node',
|
||||
entry: {
|
||||
main: path.resolve(__dirname, 'lib/index.ts'),
|
||||
},
|
||||
mode: process.env.TERMINUS_DEV ? 'development' : 'production',
|
||||
context: __dirname,
|
||||
devtool: 'source-map',
|
||||
output: {
|
||||
path: path.join(__dirname, 'dist'),
|
||||
pathinfo: true,
|
||||
filename: '[name].js',
|
||||
},
|
||||
resolve: {
|
||||
modules: ['lib/', 'node_modules', '../node_modules'].map(x => path.join(__dirname, x)),
|
||||
extensions: ['.ts', '.js'],
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.ts$/,
|
||||
use: {
|
||||
loader: 'awesome-typescript-loader',
|
||||
options: {
|
||||
configFileName: path.resolve(__dirname, 'tsconfig.main.json'),
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
externals: {
|
||||
electron: 'commonjs electron',
|
||||
'electron-config': 'commonjs electron-config',
|
||||
'electron-vibrancy': 'commonjs electron-vibrancy',
|
||||
fs: 'commonjs fs',
|
||||
glasstron: 'commonjs glasstron',
|
||||
mz: 'commonjs mz',
|
||||
path: 'commonjs path',
|
||||
yargs: 'commonjs yargs',
|
||||
'windows-swca': 'commonjs windows-swca',
|
||||
'windows-blurbehind': 'commonjs windows-blurbehind',
|
||||
},
|
||||
plugins: [
|
||||
new webpack.optimize.ModuleConcatenationPlugin(),
|
||||
new webpack.DefinePlugin({
|
||||
'process.type': '"main"',
|
||||
}),
|
||||
],
|
||||
}
|
2759
app/yarn.lock
18
appveyor.yml
@@ -4,25 +4,23 @@ platform:
|
||||
- x64
|
||||
|
||||
environment:
|
||||
nodejs_version: "15"
|
||||
nodejs_version: "7"
|
||||
|
||||
cache:
|
||||
- '%USERPROFILE%\.electron'
|
||||
|
||||
version: "{build}"
|
||||
|
||||
install:
|
||||
- ps: Install-Product node $env:nodejs_version $env:platform
|
||||
- yarn
|
||||
- npm install
|
||||
- node scripts/install-deps.js
|
||||
- node scripts/build-native.js
|
||||
|
||||
build_script:
|
||||
- yarn run build
|
||||
- npm run build
|
||||
- node scripts/prepackage-plugins.js
|
||||
- node scripts/build-windows.js
|
||||
|
||||
artifacts:
|
||||
- path: 'dist\*.exe'
|
||||
|
||||
cache:
|
||||
- node_modules
|
||||
- "*\\node_modules"
|
||||
- "%USERPROFILE%\\.electron"
|
||||
- "%LOCALAPPDATA%\\Yarn"
|
||||
- path: 'dist\win\*.exe'
|
||||
|
Before Width: | Height: | Size: 8.9 KiB After Width: | Height: | Size: 4.3 KiB |
Before Width: | Height: | Size: 950 B After Width: | Height: | Size: 644 B |
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 8.3 KiB |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 2.3 KiB |
@@ -1,57 +1,124 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 23.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 1024 1024" style="enable-background:new 0 0 1024 1024;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{opacity:0.8;fill:#00232E;}
|
||||
.st1{fill:url(#SVGID_1_);}
|
||||
.st2{opacity:0.16;fill:url(#SVGID_2_);}
|
||||
.st3{fill:url(#SVGID_3_);}
|
||||
.st4{opacity:0.16;fill:url(#SVGID_4_);}
|
||||
.st5{fill:url(#SVGID_5_);}
|
||||
.st6{opacity:0.15;fill:url(#SVGID_6_);}
|
||||
.st7{fill:url(#SVGID_7_);}
|
||||
</style>
|
||||
<polygon class="st0" points="449.5,645.47 407.51,621.23 533.47,548.5 407.51,475.77 449.5,451.53 617.45,548.5 "/>
|
||||
<g>
|
||||
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="439.0065" y1="603.0394" x2="627.9464" y2="493.9549">
|
||||
<stop offset="0" style="stop-color:#669ABD"/>
|
||||
<stop offset="1" style="stop-color:#77DBDB"/>
|
||||
</linearGradient>
|
||||
<polygon class="st1" points="449.5,621.22 617.45,524.25 617.45,475.77 449.5,572.75 "/>
|
||||
<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="522.9788" y1="530.3148" x2="543.9741" y2="566.6795">
|
||||
<stop offset="0.5588" style="stop-color:#000000;stop-opacity:0"/>
|
||||
<stop offset="1" style="stop-color:#000000"/>
|
||||
</linearGradient>
|
||||
<polygon class="st2" points="449.5,621.22 617.45,524.25 617.45,475.77 449.5,572.75 "/>
|
||||
</g>
|
||||
<g>
|
||||
<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="397.0101" y1="566.6837" x2="459.9963" y2="603.0487">
|
||||
<stop offset="0" style="stop-color:#6A8FAD"/>
|
||||
<stop offset="1" style="stop-color:#669ABD"/>
|
||||
</linearGradient>
|
||||
<polygon class="st3" points="407.51,548.5 407.5,596.99 449.5,621.22 449.5,572.75 "/>
|
||||
<linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="439.0009" y1="566.6838" x2="418.0056" y2="603.0486">
|
||||
<stop offset="0.5588" style="stop-color:#000000;stop-opacity:0"/>
|
||||
<stop offset="1" style="stop-color:#000000"/>
|
||||
</linearGradient>
|
||||
<polygon class="st4" points="407.51,548.5 407.5,596.99 449.5,621.22 449.5,572.75 "/>
|
||||
</g>
|
||||
<g>
|
||||
<linearGradient id="SVGID_5_" gradientUnits="userSpaceOnUse" x1="397.0101" y1="421.2265" x2="522.9781" y2="493.9542">
|
||||
<stop offset="0" style="stop-color:#6A8FAD"/>
|
||||
<stop offset="1" style="stop-color:#669ABD"/>
|
||||
</linearGradient>
|
||||
<polygon class="st5" points="407.51,403.04 407.5,451.53 491.49,500.01 533.48,475.77 "/>
|
||||
<linearGradient id="SVGID_6_" gradientUnits="userSpaceOnUse" x1="470.4924" y1="439.4067" x2="449.4958" y2="475.774">
|
||||
<stop offset="0.5588" style="stop-color:#000000;stop-opacity:0"/>
|
||||
<stop offset="1" style="stop-color:#000000"/>
|
||||
</linearGradient>
|
||||
<polygon class="st6" points="407.51,403.04 407.5,451.53 491.49,500.01 533.48,475.77 "/>
|
||||
</g>
|
||||
<linearGradient id="SVGID_7_" gradientUnits="userSpaceOnUse" x1="386.5123" y1="512.136" x2="575.4605" y2="403.0467">
|
||||
<stop offset="0" style="stop-color:#CCECFF"/>
|
||||
<stop offset="1" style="stop-color:#9FECED"/>
|
||||
</linearGradient>
|
||||
<polygon class="st7" points="449.5,572.74 407.51,548.5 533.48,475.77 407.51,403.04 449.49,378.8 617.45,475.77 "/>
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="150mm"
|
||||
height="150mm"
|
||||
viewBox="0 0 150 150"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
inkscape:version="0.92.2 (5c3e80d, 2017-08-06)"
|
||||
sodipodi:docname="icon.svg"
|
||||
inkscape:export-filename="/home/eugene/Work/term/build/icons/512x512.png"
|
||||
inkscape:export-xdpi="86.699997"
|
||||
inkscape:export-ydpi="86.699997">
|
||||
<defs
|
||||
id="defs2">
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient4649">
|
||||
<stop
|
||||
style="stop-color:#000316;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop4645" />
|
||||
<stop
|
||||
style="stop-color:#190065;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop4647" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4649"
|
||||
id="linearGradient4651"
|
||||
x1="89.26284"
|
||||
y1="85.146751"
|
||||
x2="89.26284"
|
||||
y2="229.47229"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.82182032,0,0,0.82182032,15.208802,28.029361)" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="0.49497475"
|
||||
inkscape:cx="85.897128"
|
||||
inkscape:cy="375.72042"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:snap-bbox="true"
|
||||
inkscape:window-width="1366"
|
||||
inkscape:window-height="692"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0"
|
||||
inkscape:snap-intersection-paths="true"
|
||||
inkscape:object-paths="true" />
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-10.356544,-82.309525)">
|
||||
<rect
|
||||
id="rect168"
|
||||
width="123.27305"
|
||||
height="123.27305"
|
||||
x="23.72002"
|
||||
y="95.673004"
|
||||
style="fill:url(#linearGradient4651);fill-opacity:1;stroke-width:0.21743995"
|
||||
rx="8.2182035"
|
||||
ry="8.2182035" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path138"
|
||||
style="opacity:0.9;fill:#bfd9f1;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.82182032px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
|
||||
d="m 47.511243,117.17807 50.067023,28.8724 -15.038249,8.68226 -35.028768,-21.3657 z"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path116"
|
||||
style="opacity:0.9;fill:#6666af;fill-rule:evenodd;stroke:none;stroke-width:0.82182032px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1;fill-opacity:1"
|
||||
d="m 127.13617,146.73547 0.0374,16.98921 -64.125308,36.25552 -0.0025,-16.25659 z"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path118"
|
||||
style="opacity:0.9;fill:#bfd9f1;fill-rule:evenodd;stroke:none;stroke-width:0.82182032px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1;fill-opacity:1"
|
||||
d="m 47.647019,174.84764 15.398727,8.89046 0.0025,16.25641 -15.401249,-8.94341 z"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<path
|
||||
style="opacity:0.9;fill:#9dbef0;fill-rule:evenodd;stroke:none;stroke-width:0.82630885px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1;fill-opacity:1"
|
||||
d="m 61.586284,108.76679 -14.292349,8.25191 50.284331,29.03177 -50.148115,28.95277 15.482843,8.93896 50.148116,-28.95277 14.29235,-8.25191 z"
|
||||
id="path134"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccccccc" />
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 4.4 KiB |
@@ -1,3 +0,0 @@
|
||||
!macro customInit
|
||||
nsExec::Exec '"$LOCALAPPDATA\terminus\Update.exe" --uninstall -s'
|
||||
!macroend
|
@@ -1,7 +0,0 @@
|
||||
#!/bin/bash
|
||||
cat > '/usr/bin/${executable}' << END
|
||||
#!/bin/sh
|
||||
'/opt/${productFilename}/${executable}' --no-sandbox $@
|
||||
END
|
||||
|
||||
chmod +x '/usr/bin/${executable}'
|
@@ -1,16 +0,0 @@
|
||||
const fs = require('fs')
|
||||
const signHook = require('./afterSignHook')
|
||||
|
||||
module.exports = async function (params) {
|
||||
// notarize the app on Mac OS only.
|
||||
if (process.platform !== 'darwin' || !process.env.GITHUB_REF || !process.env.GITHUB_REF.startsWith('refs/tags/')) {
|
||||
return
|
||||
}
|
||||
console.log('afterBuild hook triggered')
|
||||
|
||||
let pkgName = fs.readdirSync('dist').find(x => x.endsWith('.pkg'))
|
||||
signHook({
|
||||
appOutDir: 'dist',
|
||||
_pathOverride: pkgName,
|
||||
})
|
||||
}
|
@@ -1,35 +0,0 @@
|
||||
// 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) {
|
||||
// notarize the app on Mac OS only.
|
||||
if (process.platform !== 'darwin' || !process.env.GITHUB_REF || !process.env.GITHUB_REF.startsWith('refs/tags/')) {
|
||||
return
|
||||
}
|
||||
console.log('afterSign hook triggered', params)
|
||||
|
||||
let appId = 'org.terminus'
|
||||
|
||||
let appPath = path.join(params.appOutDir, params._pathOverride || `${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}`)
|
||||
}
|
@@ -1,18 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.cs.allow-jit</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.allow-dyld-environment-variables</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.disable-library-validation</key>
|
||||
<true/>
|
||||
<key>com.apple.security.device.microphone</key>
|
||||
<true/>
|
||||
<key>com.apple.security.device.camera</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
Before Width: | Height: | Size: 361 KiB After Width: | Height: | Size: 106 KiB |
92
build/windows/icon.svg
Normal file
@@ -0,0 +1,92 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="1024"
|
||||
height="1024"
|
||||
viewBox="0 0 270.93332 270.93333"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
inkscape:version="0.92.3 (2405546, 2018-03-11)"
|
||||
sodipodi:docname="icon.svg"
|
||||
inkscape:export-filename="D:\Users\Ich\Downloads\64x64.png"
|
||||
inkscape:export-xdpi="6"
|
||||
inkscape:export-ydpi="6">
|
||||
<defs
|
||||
id="defs2" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="0.35355339"
|
||||
inkscape:cx="-57.249603"
|
||||
inkscape:cy="781.4887"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:snap-bbox="true"
|
||||
inkscape:window-width="1858"
|
||||
inkscape:window-height="1050"
|
||||
inkscape:window-x="54"
|
||||
inkscape:window-y="1079"
|
||||
inkscape:window-maximized="1"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0"
|
||||
inkscape:snap-intersection-paths="true"
|
||||
inkscape:object-paths="true"
|
||||
units="px" />
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-47.511065,70.941737)">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path138"
|
||||
style="opacity:0.9;fill:#bfd9f1;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.43524027px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
|
||||
d="M 64.949149,-45.402272 213.30911,40.153203 168.74736,65.880709 64.949181,2.5692907 Z"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path116"
|
||||
style="opacity:0.9;fill:#6666af;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.43524027px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
|
||||
d="m 301.0092,42.179959 -0.003,50.177506 -190.42255,107.635545 -0.003,-48.17143 z"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path118"
|
||||
style="opacity:0.9;fill:#bfd9f1;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.43524027px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
|
||||
d="m 64.948697,125.47711 45.629963,26.34447 0.005,48.17143 -45.637407,-26.50135 z"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<path
|
||||
style="opacity:0.9;fill:#9dbef0;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.44854069px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1"
|
||||
d="M 105.39355,-70.939125 64.949149,-45.402272 213.30911,40.153203 64.948697,125.47711 110.57866,151.82158 260.4947,65.557719 301.0092,42.179959 Z"
|
||||
id="path134"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccccccc" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 9.2 KiB |
@@ -1,10 +1,6 @@
|
||||
|
||||
### Changes
|
||||
|
||||
##### v0.4.9
|
||||
|
||||
- Fixed broken Doskey on Win10 (#438, #451)
|
||||
|
||||
##### v0.4.8
|
||||
|
||||
- Environment variable 'clink_profile' overrides Clink's profile path (#390).
|
@@ -136,7 +136,7 @@ h6 { font-size: 1.00em; }
|
||||
<!-- ----------------------------------------------------- -->
|
||||
<body onload="go();">
|
||||
<div id="header">
|
||||
<div id="title">Clink v0.4.9</div>
|
||||
<div id="title">Clink v0.4.8</div>
|
||||
<div id="url">
|
||||
<a href="http://github.com/mridgers/clink">
|
||||
http://github.com/mridgers/clink
|
||||
@@ -697,10 +697,6 @@ The current cursor position within the line buffer.
|
||||
|
||||
### Changes
|
||||
|
||||
##### v0.4.9
|
||||
|
||||
- Fixed broken Doskey on Win10 (#438, #451)
|
||||
|
||||
##### v0.4.8
|
||||
|
||||
- Environment variable 'clink_profile' overrides Clink's profile path (#390).
|
BIN
clink/clink_x64.exe
Normal file
BIN
clink/clink_x86.exe
Normal file
BIN
docs/background.jpeg
Normal file
After Width: | Height: | Size: 2.6 MiB |
BIN
docs/dist/assets/background.jpeg
vendored
Normal file
After Width: | Height: | Size: 2.6 MiB |
BIN
docs/dist/assets/terminal.png
vendored
Normal file
After Width: | Height: | Size: 21 KiB |
1
docs/dist/bundle.js
vendored
Normal file
BIN
docs/dist/fonts/background.jpeg
vendored
Normal file
After Width: | Height: | Size: 2.6 MiB |
7
docs/index.html
Normal file
@@ -0,0 +1,7 @@
|
||||
<!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"></script><title>Terminus</title></head><body><div class="mt-5 mb-5" id="header"><div class="text-center"><h1>Terminus</h1><div class="subtitle mb-3">A terminal for a more modern age</div><a class="btn btn-lg btn-outline-dark mt-4" href="https://github.com/Eugeny/terminus/releases/latest" target="_blank"><strong>DOWNLOAD</strong></a><a class="btn btn-lg btn-outline-secondary mt-4 ml-3" href="https://github.com/Eugeny/terminus" target="_blank"><strong>GITHUB</strong></a></div></div><div class="background-stripe"><div class="overlay overlay1"></div><div class="overlay overlay2"></div><div class="terminal"></div></div><div class="container mt-5 mb-5"><div class="d-flex flex-wrap flex-md-nowrap"><div class="w-100"><div class="feature">windows</div><div class="feature">linux</div><div class="feature">macos</div><br><div class="feature">powershell</div><div class="feature">wsl</div><div class="feature">cygwin</div><div class="feature">git-bash</div><div class="feature">cmder</div><div class="feature">clink</div></div><div class="w-100"><div class="feature">full unicode</div><div class="feature">global hotkey</div><div class="feature">plugins</div><div class="feature">tab recovery</div><div class="feature">custom css</div><div class="feature">themes</div><div class="feature">font ligatures</div><div class="feature">clickable paths</div><div class="feature">tabs on top/bottom</div><div class="feature">vibrancy</div><div class="feature">bracketed paste</div></div></div></div><div class="container mt-5 mb-5"><div class="text-center"><a class="btn btn-lg btn-outline-secondary mt-5" href="/terminus/#header"><strong>BEAM ME UP</strong></a></div></div><div class="background-stripe2"><div class="overlay overlay1"></div></div><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');</script></body></html>
|
1
docs/index.js
Normal file
@@ -0,0 +1 @@
|
||||
import './styles.scss'
|
69
docs/index.pug
Normal file
@@ -0,0 +1,69 @@
|
||||
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
|
||||
a.btn.btn-lg.btn-outline-secondary.mt-5(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');
|
BIN
docs/kofi.png
Before Width: | Height: | Size: 7.3 KiB |
24
docs/package.json
Normal file
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"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"
|
||||
}
|
||||
}
|
BIN
docs/readme.png
Before Width: | Height: | Size: 1.6 MiB After Width: | Height: | Size: 862 KiB |
141
docs/styles.scss
Normal file
@@ -0,0 +1,141 @@
|
||||
$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;
|
||||
}
|
||||
}
|
||||
}
|
BIN
docs/terminal.png
Normal file
After Width: | Height: | Size: 21 KiB |
27
docs/webpack.config.js
Normal file
@@ -0,0 +1,27 @@
|
||||
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]'
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
}
|
@@ -1,69 +0,0 @@
|
||||
---
|
||||
appId: org.terminus
|
||||
productName: Terminus
|
||||
compression: normal
|
||||
npmRebuild: false
|
||||
afterSign: "./build/mac/afterSignHook.js"
|
||||
afterAllArtifactBuild: "./build/mac/afterBuildHook.js"
|
||||
files:
|
||||
- "**/*"
|
||||
- dist
|
||||
extraResources:
|
||||
- builtin-plugins
|
||||
- extras
|
||||
publish:
|
||||
- provider: github
|
||||
|
||||
win:
|
||||
icon: "./build/windows/icon.ico"
|
||||
artifactName: terminus-${version}-portable.${ext}
|
||||
rfc3161TimeStampServer: http://sha256timestamp.ws.symantec.com/sha256/timestamp
|
||||
nsis:
|
||||
oneClick: false
|
||||
artifactName: terminus-${version}-setup.${ext}
|
||||
installerIcon: "./build/windows/icon.ico"
|
||||
|
||||
mac:
|
||||
category: public.app-category.video
|
||||
icon: "./build/mac/icon.icns"
|
||||
artifactName: terminus-${version}-macos-${env.ARCH}.${ext}
|
||||
hardenedRuntime: true
|
||||
entitlements: "./build/mac/entitlements.plist"
|
||||
entitlementsInherit: "./build/mac/entitlements.plist"
|
||||
extendInfo:
|
||||
NSRequiresAquaSystemAppearance: false
|
||||
NSCameraUsageDescription: "A subprocess requests access to the device's camera."
|
||||
NSMicrophoneUsageDescription: "A subprocess requests access to the device's microphone."
|
||||
NSLocationUsageDescription: "A subprocess requests access to the user's location information."
|
||||
NSDesktopFolderUsageDescription: "A subprocess requests access to the user's Desktop folder."
|
||||
NSDocumentsFolderUsageDescription: "A subprocess requests access to the user's Documents folder."
|
||||
NSDownloadsFolderUsageDescription: "A subprocess requests access to the user's Downloads folder."
|
||||
NSNetworkVolumesUsageDescription: 'A subprocess requests access to files on a network volume.'
|
||||
NSRemovableVolumesUsageDescription: 'A subprocess requests access to files on a removable volume.'
|
||||
|
||||
linux:
|
||||
category: Utilities
|
||||
icon: "./build/icons"
|
||||
artifactName: terminus-${version}-linux.${ext}
|
||||
executableArgs:
|
||||
- "--no-sandbox"
|
||||
snap:
|
||||
plugs:
|
||||
- default
|
||||
- system-files
|
||||
- system-observe
|
||||
deb:
|
||||
depends:
|
||||
- gconf2
|
||||
- gconf-service
|
||||
- gnome-keyring
|
||||
- libnotify4
|
||||
- libsecret-1-0
|
||||
- libappindicator1
|
||||
- libxtst6
|
||||
- libnss3
|
||||
afterInstall: build/linux/after-install.tpl
|
||||
rpm:
|
||||
depends:
|
||||
- screen
|
||||
- gnome-keyring
|
BIN
extras/UAC.exe
@@ -1,31 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>NSServices</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>NSBackgroundColorName</key>
|
||||
<string>background</string>
|
||||
<key>NSIconName</key>
|
||||
<string>NSActionTemplate</string>
|
||||
<key>NSMenuItem</key>
|
||||
<dict>
|
||||
<key>default</key>
|
||||
<string>Open Terminus here</string>
|
||||
</dict>
|
||||
<key>NSMessage</key>
|
||||
<string>runWorkflowAsService</string>
|
||||
<key>NSRequiredContext</key>
|
||||
<dict>
|
||||
<key>NSApplicationIdentifier</key>
|
||||
<string>com.apple.finder</string>
|
||||
</dict>
|
||||
<key>NSSendFileTypes</key>
|
||||
<array>
|
||||
<string>public.item</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
Before Width: | Height: | Size: 3.6 KiB |
@@ -1,136 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>files</key>
|
||||
<dict/>
|
||||
<key>files2</key>
|
||||
<dict>
|
||||
<key>QuickLook/Thumbnail.png</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
tv0Qtgo8zZ9+sQPQDNdKJHm7jeQ=
|
||||
</data>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
8nlfnBbkORcam9cE84KuxM9Lgf6hYU0jehepX8sSNDU=
|
||||
</data>
|
||||
</dict>
|
||||
<key>document.wflow</key>
|
||||
<dict>
|
||||
<key>cdhash</key>
|
||||
<data>
|
||||
VK77ipNZktBsDCcUfnfht774juM=
|
||||
</data>
|
||||
<key>requirement</key>
|
||||
<string>identifier document and anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] /* exists */ and certificate leaf[field.1.2.840.113635.100.6.1.13] /* exists */ and certificate leaf[subject.OU] = V4JSMC46SY</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>rules</key>
|
||||
<dict>
|
||||
<key>^Resources/</key>
|
||||
<true/>
|
||||
<key>^Resources/.*\.lproj/</key>
|
||||
<dict>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>1000</real>
|
||||
</dict>
|
||||
<key>^Resources/.*\.lproj/locversion.plist$</key>
|
||||
<dict>
|
||||
<key>omit</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>1100</real>
|
||||
</dict>
|
||||
<key>^Resources/Base\.lproj/</key>
|
||||
<dict>
|
||||
<key>weight</key>
|
||||
<real>1010</real>
|
||||
</dict>
|
||||
<key>^version.plist$</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>rules2</key>
|
||||
<dict>
|
||||
<key>.*\.dSYM($|/)</key>
|
||||
<dict>
|
||||
<key>weight</key>
|
||||
<real>11</real>
|
||||
</dict>
|
||||
<key>^(.*/)?\.DS_Store$</key>
|
||||
<dict>
|
||||
<key>omit</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>2000</real>
|
||||
</dict>
|
||||
<key>^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/</key>
|
||||
<dict>
|
||||
<key>nested</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>10</real>
|
||||
</dict>
|
||||
<key>^.*</key>
|
||||
<true/>
|
||||
<key>^Info\.plist$</key>
|
||||
<dict>
|
||||
<key>omit</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>20</real>
|
||||
</dict>
|
||||
<key>^PkgInfo$</key>
|
||||
<dict>
|
||||
<key>omit</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>20</real>
|
||||
</dict>
|
||||
<key>^Resources/</key>
|
||||
<dict>
|
||||
<key>weight</key>
|
||||
<real>20</real>
|
||||
</dict>
|
||||
<key>^Resources/.*\.lproj/</key>
|
||||
<dict>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>1000</real>
|
||||
</dict>
|
||||
<key>^Resources/.*\.lproj/locversion.plist$</key>
|
||||
<dict>
|
||||
<key>omit</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>1100</real>
|
||||
</dict>
|
||||
<key>^Resources/Base\.lproj/</key>
|
||||
<dict>
|
||||
<key>weight</key>
|
||||
<real>1010</real>
|
||||
</dict>
|
||||
<key>^[^/]+$</key>
|
||||
<dict>
|
||||
<key>nested</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>10</real>
|
||||
</dict>
|
||||
<key>^embedded\.provisionprofile$</key>
|
||||
<dict>
|
||||
<key>weight</key>
|
||||
<real>20</real>
|
||||
</dict>
|
||||
<key>^version\.plist$</key>
|
||||
<dict>
|
||||
<key>weight</key>
|
||||
<real>20</real>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
@@ -1,226 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>AMApplicationBuild</key>
|
||||
<string>444.38</string>
|
||||
<key>AMApplicationVersion</key>
|
||||
<string>2.9</string>
|
||||
<key>AMDocumentVersion</key>
|
||||
<string>2</string>
|
||||
<key>actions</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>action</key>
|
||||
<dict>
|
||||
<key>AMAccepts</key>
|
||||
<dict>
|
||||
<key>Container</key>
|
||||
<string>List</string>
|
||||
<key>Optional</key>
|
||||
<true/>
|
||||
<key>Types</key>
|
||||
<array>
|
||||
<string>com.apple.cocoa.string</string>
|
||||
</array>
|
||||
</dict>
|
||||
<key>AMActionVersion</key>
|
||||
<string>2.0.3</string>
|
||||
<key>AMApplication</key>
|
||||
<array>
|
||||
<string>Automator</string>
|
||||
</array>
|
||||
<key>AMParameterProperties</key>
|
||||
<dict>
|
||||
<key>COMMAND_STRING</key>
|
||||
<dict/>
|
||||
<key>CheckedForUserDefaultShell</key>
|
||||
<dict/>
|
||||
<key>inputMethod</key>
|
||||
<dict/>
|
||||
<key>shell</key>
|
||||
<dict/>
|
||||
<key>source</key>
|
||||
<dict/>
|
||||
</dict>
|
||||
<key>AMProvides</key>
|
||||
<dict>
|
||||
<key>Container</key>
|
||||
<string>List</string>
|
||||
<key>Types</key>
|
||||
<array>
|
||||
<string>com.apple.cocoa.string</string>
|
||||
</array>
|
||||
</dict>
|
||||
<key>ActionBundlePath</key>
|
||||
<string>/System/Library/Automator/Run Shell Script.action</string>
|
||||
<key>ActionName</key>
|
||||
<string>Run Shell Script</string>
|
||||
<key>ActionParameters</key>
|
||||
<dict>
|
||||
<key>COMMAND_STRING</key>
|
||||
<string>/Applications/Terminus.app/Contents/MacOS/terminus open "$1"</string>
|
||||
<key>CheckedForUserDefaultShell</key>
|
||||
<true/>
|
||||
<key>inputMethod</key>
|
||||
<integer>1</integer>
|
||||
<key>shell</key>
|
||||
<string>/bin/sh</string>
|
||||
<key>source</key>
|
||||
<string></string>
|
||||
</dict>
|
||||
<key>BundleIdentifier</key>
|
||||
<string>com.apple.RunShellScript</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>2.0.3</string>
|
||||
<key>CanShowSelectedItemsWhenRun</key>
|
||||
<false/>
|
||||
<key>CanShowWhenRun</key>
|
||||
<true/>
|
||||
<key>Category</key>
|
||||
<array>
|
||||
<string>AMCategoryUtilities</string>
|
||||
</array>
|
||||
<key>Class Name</key>
|
||||
<string>RunShellScriptAction</string>
|
||||
<key>InputUUID</key>
|
||||
<string>CDBAB8D4-B8B8-4FBB-9115-B4082FB99E1C</string>
|
||||
<key>Keywords</key>
|
||||
<array>
|
||||
<string>Shell</string>
|
||||
<string>Script</string>
|
||||
<string>Command</string>
|
||||
<string>Run</string>
|
||||
<string>Unix</string>
|
||||
</array>
|
||||
<key>OutputUUID</key>
|
||||
<string>96B5890B-A95F-4BF2-8E5A-38E07A849C33</string>
|
||||
<key>UUID</key>
|
||||
<string>62251AFB-502C-4EA0-821C-D9B8CA96E6EE</string>
|
||||
<key>UnlocalizedApplications</key>
|
||||
<array>
|
||||
<string>Automator</string>
|
||||
</array>
|
||||
<key>arguments</key>
|
||||
<dict>
|
||||
<key>0</key>
|
||||
<dict>
|
||||
<key>default value</key>
|
||||
<integer>0</integer>
|
||||
<key>name</key>
|
||||
<string>inputMethod</string>
|
||||
<key>required</key>
|
||||
<string>0</string>
|
||||
<key>type</key>
|
||||
<string>0</string>
|
||||
<key>uuid</key>
|
||||
<string>0</string>
|
||||
</dict>
|
||||
<key>1</key>
|
||||
<dict>
|
||||
<key>default value</key>
|
||||
<string></string>
|
||||
<key>name</key>
|
||||
<string>source</string>
|
||||
<key>required</key>
|
||||
<string>0</string>
|
||||
<key>type</key>
|
||||
<string>0</string>
|
||||
<key>uuid</key>
|
||||
<string>1</string>
|
||||
</dict>
|
||||
<key>2</key>
|
||||
<dict>
|
||||
<key>default value</key>
|
||||
<false/>
|
||||
<key>name</key>
|
||||
<string>CheckedForUserDefaultShell</string>
|
||||
<key>required</key>
|
||||
<string>0</string>
|
||||
<key>type</key>
|
||||
<string>0</string>
|
||||
<key>uuid</key>
|
||||
<string>2</string>
|
||||
</dict>
|
||||
<key>3</key>
|
||||
<dict>
|
||||
<key>default value</key>
|
||||
<string></string>
|
||||
<key>name</key>
|
||||
<string>COMMAND_STRING</string>
|
||||
<key>required</key>
|
||||
<string>0</string>
|
||||
<key>type</key>
|
||||
<string>0</string>
|
||||
<key>uuid</key>
|
||||
<string>3</string>
|
||||
</dict>
|
||||
<key>4</key>
|
||||
<dict>
|
||||
<key>default value</key>
|
||||
<string>/bin/sh</string>
|
||||
<key>name</key>
|
||||
<string>shell</string>
|
||||
<key>required</key>
|
||||
<string>0</string>
|
||||
<key>type</key>
|
||||
<string>0</string>
|
||||
<key>uuid</key>
|
||||
<string>4</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>isViewVisible</key>
|
||||
<true/>
|
||||
<key>location</key>
|
||||
<string>529.000000:305.000000</string>
|
||||
<key>nibPath</key>
|
||||
<string>/System/Library/Automator/Run Shell Script.action/Contents/Resources/Base.lproj/main.nib</string>
|
||||
</dict>
|
||||
<key>isViewVisible</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</array>
|
||||
<key>connectors</key>
|
||||
<dict/>
|
||||
<key>workflowMetaData</key>
|
||||
<dict>
|
||||
<key>applicationBundleID</key>
|
||||
<string>com.apple.finder</string>
|
||||
<key>applicationBundleIDsByPath</key>
|
||||
<dict>
|
||||
<key>/System/Library/CoreServices/Finder.app</key>
|
||||
<string>com.apple.finder</string>
|
||||
</dict>
|
||||
<key>applicationPath</key>
|
||||
<string>/System/Library/CoreServices/Finder.app</string>
|
||||
<key>applicationPaths</key>
|
||||
<array>
|
||||
<string>/System/Library/CoreServices/Finder.app</string>
|
||||
</array>
|
||||
<key>inputTypeIdentifier</key>
|
||||
<string>com.apple.Automator.fileSystemObject</string>
|
||||
<key>outputTypeIdentifier</key>
|
||||
<string>com.apple.Automator.nothing</string>
|
||||
<key>presentationMode</key>
|
||||
<integer>15</integer>
|
||||
<key>processesInput</key>
|
||||
<integer>0</integer>
|
||||
<key>serviceApplicationBundleID</key>
|
||||
<string>com.apple.finder</string>
|
||||
<key>serviceApplicationPath</key>
|
||||
<string>/System/Library/CoreServices/Finder.app</string>
|
||||
<key>serviceInputTypeIdentifier</key>
|
||||
<string>com.apple.Automator.fileSystemObject</string>
|
||||
<key>serviceOutputTypeIdentifier</key>
|
||||
<string>com.apple.Automator.nothing</string>
|
||||
<key>serviceProcessesInput</key>
|
||||
<integer>0</integer>
|
||||
<key>systemImageName</key>
|
||||
<string>NSActionTemplate</string>
|
||||
<key>useAutomaticInputType</key>
|
||||
<integer>0</integer>
|
||||
<key>workflowTypeIdentifier</key>
|
||||
<string>com.apple.Automator.servicesMenu</string>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
@@ -1,31 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>NSServices</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>NSBackgroundColorName</key>
|
||||
<string>background</string>
|
||||
<key>NSIconName</key>
|
||||
<string>NSActionTemplate</string>
|
||||
<key>NSMenuItem</key>
|
||||
<dict>
|
||||
<key>default</key>
|
||||
<string>Paste path into Terminus</string>
|
||||
</dict>
|
||||
<key>NSMessage</key>
|
||||
<string>runWorkflowAsService</string>
|
||||
<key>NSRequiredContext</key>
|
||||
<dict>
|
||||
<key>NSApplicationIdentifier</key>
|
||||
<string>com.apple.finder</string>
|
||||
</dict>
|
||||
<key>NSSendFileTypes</key>
|
||||
<array>
|
||||
<string>public.item</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
Before Width: | Height: | Size: 3.6 KiB |