parent
							
								
									d379ffff9b
								
							
						
					
					
						commit
						9bb3c18df9
					
				| 
						 | 
				
			
			@ -0,0 +1,20 @@
 | 
			
		|||
kind: pipeline
 | 
			
		||||
name: default
 | 
			
		||||
steps:
 | 
			
		||||
- name: build
 | 
			
		||||
  image: golang:1.17.2
 | 
			
		||||
  commands:
 | 
			
		||||
    - git tag $DRONE_TAG
 | 
			
		||||
    - bash make.sh
 | 
			
		||||
    - echo -n "latest,${DRONE_TAG#v}" > .tags
 | 
			
		||||
- name: gitea_release
 | 
			
		||||
  image: plugins/gitea-release
 | 
			
		||||
  settings:
 | 
			
		||||
    api_key:
 | 
			
		||||
      from_secret: gitea_api_key
 | 
			
		||||
    base_url: https://kumoly.io
 | 
			
		||||
    files: dist/*
 | 
			
		||||
    checksum:
 | 
			
		||||
      - sha256
 | 
			
		||||
trigger:
 | 
			
		||||
  event: tag
 | 
			
		||||
| 
						 | 
				
			
			@ -1,2 +1,3 @@
 | 
			
		|||
node_modules
 | 
			
		||||
.parcel-cache
 | 
			
		||||
dist
 | 
			
		||||
							
								
								
									
										29
									
								
								README.md
								
								
								
								
							
							
						
						
									
										29
									
								
								README.md
								
								
								
								
							| 
						 | 
				
			
			@ -1 +1,28 @@
 | 
			
		|||
# goshell
 | 
			
		||||
# gterm
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## Usage
 | 
			
		||||
 | 
			
		||||
```shell
 | 
			
		||||
Usage: gterm [options]
 | 
			
		||||
  -addr string
 | 
			
		||||
        address to bind (default ":8000")
 | 
			
		||||
  -allow string
 | 
			
		||||
        restrict ip
 | 
			
		||||
  -dev
 | 
			
		||||
        is development mode
 | 
			
		||||
  -log-level int
 | 
			
		||||
        log level (default 9)
 | 
			
		||||
  -name string
 | 
			
		||||
        the application title (default "gterm")
 | 
			
		||||
  -shell string
 | 
			
		||||
        the shell behind (default "bash")
 | 
			
		||||
  -v    show version
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Install
 | 
			
		||||
 | 
			
		||||
```shell
 | 
			
		||||
sudo rm -f /usr/local/bin/gterm
 | 
			
		||||
sudo sh -c "curl -fsSL RELEASE_URL | tar -C /usr/local/bin/ -xz"
 | 
			
		||||
```
 | 
			
		||||
| 
						 | 
				
			
			@ -2,27 +2,78 @@ package main
 | 
			
		|||
 | 
			
		||||
import (
 | 
			
		||||
	"flag"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"os"
 | 
			
		||||
 | 
			
		||||
	"kumoly.io/lib/klog"
 | 
			
		||||
	"kumoly.io/lib/ksrv"
 | 
			
		||||
	"kumoly.io/tools/gterm"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var Version = "0.0.0"
 | 
			
		||||
var Build = "alpha"
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	flagAppName string = "gterm"
 | 
			
		||||
	flagAddr    string
 | 
			
		||||
	flagShell   string
 | 
			
		||||
	flagAllowIP  string
 | 
			
		||||
	flagAppName  string = "gterm"
 | 
			
		||||
	flagAddr     string
 | 
			
		||||
	flagShell    string
 | 
			
		||||
	flagLogLevel int
 | 
			
		||||
	flagDev      bool
 | 
			
		||||
	flagVer      bool
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	flag.StringVar(&flagAppName, "name", "gterm", "the application title")
 | 
			
		||||
	flag.StringVar(&flagAddr, "addr", ":8000", "address to bind")
 | 
			
		||||
	flag.StringVar(&flagShell, "shell", "bash", "the shell behind")
 | 
			
		||||
	flag.BoolVar(&flagDev, "dev", false, "is development mode")
 | 
			
		||||
	flag.IntVar(&flagLogLevel, "log-level", 9, "log level")
 | 
			
		||||
	flag.StringVar(&flagAllowIP, "allow", "", "restrict ip")
 | 
			
		||||
	flag.BoolVar(&flagVer, "v", false, "show version")
 | 
			
		||||
 | 
			
		||||
	flag.Usage = func() {
 | 
			
		||||
		fmt.Fprintf(os.Stderr, "Usage: gterm [options]\n")
 | 
			
		||||
		flag.PrintDefaults()
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func main() {
 | 
			
		||||
	flag.Parse()
 | 
			
		||||
	if flagVer {
 | 
			
		||||
		fmt.Printf("%v - %v\n", Version, Build)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	klog.LEVEL = klog.Llevel(flagLogLevel)
 | 
			
		||||
	klog.PROD = !flagDev
 | 
			
		||||
 | 
			
		||||
	server := ksrv.New()
 | 
			
		||||
	g := gterm.New()
 | 
			
		||||
	g.AppName = flagAppName
 | 
			
		||||
	g.Cmd = flagShell
 | 
			
		||||
 | 
			
		||||
	server.Handle(g).Listen(flagAddr).Serve()
 | 
			
		||||
	server := &http.Server{
 | 
			
		||||
		Addr:    flagAddr,
 | 
			
		||||
		Handler: Middleware(g),
 | 
			
		||||
	}
 | 
			
		||||
	server.ListenAndServe()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Middleware(next http.Handler) http.Handler {
 | 
			
		||||
	log := klog.Sub(flagAppName)
 | 
			
		||||
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
		defer func() {
 | 
			
		||||
			if err := recover(); err != nil {
 | 
			
		||||
				log.Error(err)
 | 
			
		||||
			}
 | 
			
		||||
		}()
 | 
			
		||||
		if flagAllowIP != "" {
 | 
			
		||||
			if !ksrv.MatchIPGlob(ksrv.GetIP(r), flagAllowIP) {
 | 
			
		||||
				w.WriteHeader(http.StatusForbidden)
 | 
			
		||||
				w.Write([]byte("permission denied"))
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		next.ServeHTTP(w, r)
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										1
									
								
								go.mod
								
								
								
								
							
							
						
						
									
										1
									
								
								go.mod
								
								
								
								
							| 
						 | 
				
			
			@ -5,7 +5,6 @@ go 1.17
 | 
			
		|||
require (
 | 
			
		||||
	github.com/creack/pty v1.1.17
 | 
			
		||||
	github.com/gorilla/websocket v1.4.2
 | 
			
		||||
	github.com/rs/xid v1.3.0
 | 
			
		||||
	kumoly.io/lib/klog v0.0.8
 | 
			
		||||
	kumoly.io/lib/ksrv v0.0.2-0.20211112060911-0d61b343a298
 | 
			
		||||
)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										2
									
								
								go.sum
								
								
								
								
							
							
						
						
									
										2
									
								
								go.sum
								
								
								
								
							| 
						 | 
				
			
			@ -4,8 +4,6 @@ github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0U
 | 
			
		|||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
 | 
			
		||||
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
 | 
			
		||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
 | 
			
		||||
github.com/rs/xid v1.3.0 h1:6NjYksEUlhurdVehpc7S7dk6DAmcKv8V9gG0FsVN2U4=
 | 
			
		||||
github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
 | 
			
		||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
			
		||||
golang.org/x/sys v0.0.0-20211103235746-7861aae1554b h1:1VkfZQv42XQlA/jchYumAnv1UPo6RgF9rJFkTgZIxO4=
 | 
			
		||||
golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										24
									
								
								gterm.go
								
								
								
								
							
							
						
						
									
										24
									
								
								gterm.go
								
								
								
								
							| 
						 | 
				
			
			@ -14,14 +14,13 @@ import (
 | 
			
		|||
 | 
			
		||||
	"github.com/creack/pty"
 | 
			
		||||
	"github.com/gorilla/websocket"
 | 
			
		||||
	"github.com/rs/xid"
 | 
			
		||||
	"kumoly.io/lib/klog"
 | 
			
		||||
	"kumoly.io/lib/ksrv"
 | 
			
		||||
	"kumoly.io/lib/ksrv/engine"
 | 
			
		||||
	"kumoly.io/tools/gterm/public"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
//go:embed index.html
 | 
			
		||||
//go:embed public/index.html
 | 
			
		||||
var index string
 | 
			
		||||
 | 
			
		||||
var tmpl *engine.Engine
 | 
			
		||||
| 
						 | 
				
			
			@ -68,10 +67,23 @@ func New() *GTerm {
 | 
			
		|||
	// if g.BufferSize == 0 {
 | 
			
		||||
	// 	g.BufferSize = 512
 | 
			
		||||
	// }
 | 
			
		||||
	go func() {
 | 
			
		||||
		//print pool
 | 
			
		||||
		log := klog.Sub("gterm")
 | 
			
		||||
		for {
 | 
			
		||||
			cons := []string{}
 | 
			
		||||
			for k := range pool {
 | 
			
		||||
				cons = append(cons, k)
 | 
			
		||||
			}
 | 
			
		||||
			log.Info("current connections: ", cons)
 | 
			
		||||
			time.Sleep(5 * time.Minute)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}()
 | 
			
		||||
	return >erm{
 | 
			
		||||
		AppName:    "GTERM",
 | 
			
		||||
		Cmd:        "bash",
 | 
			
		||||
		Envs:       os.Environ(),
 | 
			
		||||
		Envs:       append(os.Environ(), "TERM=xterm-256color"),
 | 
			
		||||
		Timeout:    20 * time.Second,
 | 
			
		||||
		ErrorLimit: 10,
 | 
			
		||||
		BufferSize: 512,
 | 
			
		||||
| 
						 | 
				
			
			@ -111,7 +123,7 @@ func (g *GTerm) App(w http.ResponseWriter, r *http.Request) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
func (g *GTerm) WS(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
	id := ksrv.GetIP(r) + " : " + xid.New().String()
 | 
			
		||||
	id := fmt.Sprintf("[%02d] %s", ctr(), ksrv.GetIP(r))
 | 
			
		||||
	pool[id] = make(chan struct{}, 1)
 | 
			
		||||
	defer func() {
 | 
			
		||||
		close(pool[id])
 | 
			
		||||
| 
						 | 
				
			
			@ -226,7 +238,7 @@ func (g *GTerm) WS(w http.ResponseWriter, r *http.Request) {
 | 
			
		|||
			if !ok {
 | 
			
		||||
				dataType = "uunknown"
 | 
			
		||||
			}
 | 
			
		||||
			l.Info(fmt.Sprintf("received %s (type: %v) message of size %v byte(s) from xterm.js with key sequence: %v", dataType, messageType, dataLength, dataBuffer))
 | 
			
		||||
			l.Debug(fmt.Sprintf("received %s (type: %v) message of size %v byte(s) from xterm.js with key sequence: %v", dataType, messageType, dataLength, dataBuffer))
 | 
			
		||||
 | 
			
		||||
			// process
 | 
			
		||||
			if dataLength == -1 { // invalid
 | 
			
		||||
| 
						 | 
				
			
			@ -243,7 +255,7 @@ func (g *GTerm) WS(w http.ResponseWriter, r *http.Request) {
 | 
			
		|||
						l.Warn(fmt.Sprintf("failed to unmarshal received resize message '%s': %s", string(resizeMessage), err))
 | 
			
		||||
						continue
 | 
			
		||||
					}
 | 
			
		||||
					l.InfoF(klog.H{"rows": ttySize.Rows, "columns": ttySize.Cols}, "resizing tty...")
 | 
			
		||||
					l.DebugF(klog.H{"rows": ttySize.Rows, "columns": ttySize.Cols}, "resizing tty...")
 | 
			
		||||
					if err := pty.Setsize(tty, &pty.Winsize{
 | 
			
		||||
						Rows: ttySize.Rows,
 | 
			
		||||
						Cols: ttySize.Cols,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -41,7 +41,7 @@
 | 
			
		|||
 | 
			
		||||
<body>
 | 
			
		||||
  <div id="terminal"></div>
 | 
			
		||||
  <script src="./main.js"></script>
 | 
			
		||||
  <script  type="module"  src="./main.js"></script>
 | 
			
		||||
</body>
 | 
			
		||||
 | 
			
		||||
</html>
 | 
			
		||||
							
								
								
									
										20
									
								
								main.js
								
								
								
								
							
							
						
						
									
										20
									
								
								main.js
								
								
								
								
							| 
						 | 
				
			
			@ -7,7 +7,7 @@ import { WebLinksAddon } from 'xterm-addon-web-links';
 | 
			
		|||
import 'xterm/css/xterm.css'
 | 
			
		||||
 | 
			
		||||
(function() {
 | 
			
		||||
    var terminal = new Terminal({
 | 
			
		||||
    const terminal = new Terminal({
 | 
			
		||||
      screenKeys: true,
 | 
			
		||||
      useStyle: true,
 | 
			
		||||
      cursorBlink: true,
 | 
			
		||||
| 
						 | 
				
			
			@ -16,19 +16,20 @@ import 'xterm/css/xterm.css'
 | 
			
		|||
      screenReaderMode: true,
 | 
			
		||||
      cols: 128,
 | 
			
		||||
    });
 | 
			
		||||
    terminal.open(document.getElementById("terminal"));
 | 
			
		||||
    const fitAddon = new FitAddon();
 | 
			
		||||
    terminal.loadAddon(fitAddon);
 | 
			
		||||
    var protocol = (location.protocol === "https:") ? "wss://" : "ws://";
 | 
			
		||||
    var url = protocol + location.host + "/ws"
 | 
			
		||||
    var ws = new WebSocket(url);
 | 
			
		||||
    var attachAddon = new AttachAddon.AttachAddon(ws);
 | 
			
		||||
    var fitAddon = new FitAddon.FitAddon();
 | 
			
		||||
    terminal.loadAddon(fitAddon);
 | 
			
		||||
    var webLinksAddon = new WebLinksAddon.WebLinksAddon();
 | 
			
		||||
    const ws = new WebSocket(url);
 | 
			
		||||
    const attachAddon = new AttachAddon(ws);
 | 
			
		||||
    const webLinksAddon = new WebLinksAddon();
 | 
			
		||||
    terminal.loadAddon(webLinksAddon);
 | 
			
		||||
    var unicode11Addon = new Unicode11Addon.Unicode11Addon();
 | 
			
		||||
    const unicode11Addon = new Unicode11Addon();
 | 
			
		||||
    terminal.loadAddon(unicode11Addon);
 | 
			
		||||
    var serializeAddon = new SerializeAddon.SerializeAddon();
 | 
			
		||||
    const serializeAddon = new SerializeAddon();
 | 
			
		||||
    terminal.loadAddon(serializeAddon);
 | 
			
		||||
    terminal.open(document.getElementById("terminal"));
 | 
			
		||||
    fitAddon.fit();
 | 
			
		||||
    ws.onclose = function(event) {
 | 
			
		||||
      console.log(event);
 | 
			
		||||
      terminal.write('\r\n\nconnection has been terminated from the server-side (hit refresh to restart)\n')
 | 
			
		||||
| 
						 | 
				
			
			@ -50,6 +51,7 @@ import 'xterm/css/xterm.css'
 | 
			
		|||
        console.log(event);
 | 
			
		||||
      });
 | 
			
		||||
      window.onresize = function() {
 | 
			
		||||
        console.log("resize")
 | 
			
		||||
        fitAddon.fit();
 | 
			
		||||
      };
 | 
			
		||||
    };
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,29 @@
 | 
			
		|||
VERSION=$(git describe --tags --abbrev=0)
 | 
			
		||||
if [ $? -ne 0 ]; then VERSION=$DRONE_TAG; fi
 | 
			
		||||
BUILD=$(git rev-parse --short HEAD)
 | 
			
		||||
if [ $? -ne 0 ]; then BUILD=${DRONE_COMMIT:0:7}; fi
 | 
			
		||||
 | 
			
		||||
PROJ=gterm
 | 
			
		||||
DIST=dist
 | 
			
		||||
 | 
			
		||||
LDFLAGS="-ldflags \"-X main.Version=${VERSION} -X main.Build=${BUILD} -w -s\""
 | 
			
		||||
FAILURES=""
 | 
			
		||||
 | 
			
		||||
PLATFORMS="darwin/amd64 darwin/arm64"
 | 
			
		||||
PLATFORMS="$PLATFORMS linux/amd64"
 | 
			
		||||
 | 
			
		||||
for PLATFORM in $PLATFORMS; do
 | 
			
		||||
  GOOS=${PLATFORM%/*}
 | 
			
		||||
  GOARCH=${PLATFORM#*/}
 | 
			
		||||
  BIN_FILENAME="${PROJ}"
 | 
			
		||||
  CMD="GOOS=${GOOS} GOARCH=${GOARCH} go build ${LDFLAGS} -o ${DIST}/${BIN_FILENAME} cmd/gterm/main.go"
 | 
			
		||||
  echo "${CMD}"
 | 
			
		||||
  eval $CMD || FAILURES="${FAILURES} ${PLATFORM}"
 | 
			
		||||
  sh -c "cd ${DIST} && tar -czf ${PROJ}-${VERSION}-${GOOS}-${GOARCH}.tar.gz ${BIN_FILENAME} && rm ${BIN_FILENAME}"
 | 
			
		||||
done
 | 
			
		||||
 | 
			
		||||
if [[ "${FAILURES}" != "" ]]; then
 | 
			
		||||
  echo ""
 | 
			
		||||
  echo "${SCRIPT_NAME} failed on: ${FAILURES}"
 | 
			
		||||
  exit 1
 | 
			
		||||
fi
 | 
			
		||||
							
								
								
									
										11
									
								
								package.json
								
								
								
								
							
							
						
						
									
										11
									
								
								package.json
								
								
								
								
							| 
						 | 
				
			
			@ -1,10 +1,12 @@
 | 
			
		|||
{
 | 
			
		||||
  "name": "gterm",
 | 
			
		||||
  "version": "1.0.0",
 | 
			
		||||
  "main": "index.js",
 | 
			
		||||
  "repository": "git@kumoly.io:tools/gterm.git",
 | 
			
		||||
  "author": "Evan Chen <evanchen@kumoly.io>",
 | 
			
		||||
  "license": "MIT",
 | 
			
		||||
  "scripts": {
 | 
			
		||||
    "build":"rm public/*.js public/*.css && yarn parcel build index.html"
 | 
			
		||||
  },
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
    "parcel": "^2.0.1",
 | 
			
		||||
    "xterm": "^4.15.0",
 | 
			
		||||
| 
						 | 
				
			
			@ -13,5 +15,12 @@
 | 
			
		|||
    "xterm-addon-serialize": "^0.6.1",
 | 
			
		||||
    "xterm-addon-unicode11": "^0.3.0",
 | 
			
		||||
    "xterm-addon-web-links": "^0.4.0"
 | 
			
		||||
  },
 | 
			
		||||
  "targets":{
 | 
			
		||||
    "default":{
 | 
			
		||||
      "distDir":"public",
 | 
			
		||||
      "publicUrl":"./",
 | 
			
		||||
      "sourceMap": false
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,5 +2,5 @@ package public
 | 
			
		|||
 | 
			
		||||
import "embed"
 | 
			
		||||
 | 
			
		||||
//go:embed js favicon.ico
 | 
			
		||||
//go:embed *
 | 
			
		||||
var FS embed.FS
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| 
						 | 
				
			
			@ -0,0 +1 @@
 | 
			
		|||
.xterm{position:relative;user-select:none;-ms-user-select:none;-webkit-user-select:none}.xterm.focus,.xterm:focus{outline:none}.xterm .xterm-helpers{position:absolute;top:0;z-index:5}.xterm .xterm-helper-textarea{border:0;height:0;left:-9999em;margin:0;opacity:0;overflow:hidden;padding:0;position:absolute;resize:none;top:0;white-space:nowrap;width:0;z-index:-5}.xterm .composition-view{background:#000;color:#fff;display:none;position:absolute;white-space:nowrap;z-index:1}.xterm .composition-view.active{display:block}.xterm .xterm-viewport{background-color:#000;bottom:0;cursor:default;left:0;overflow-y:scroll;position:absolute;right:0;top:0}.xterm .xterm-screen{position:relative}.xterm .xterm-screen canvas{left:0;position:absolute;top:0}.xterm .xterm-scroll-area{visibility:hidden}.xterm-char-measure-element{display:inline-block;left:-9999em;line-height:normal;position:absolute;top:0;visibility:hidden}.xterm{cursor:text}.xterm.enable-mouse-events{cursor:default}.xterm.xterm-cursor-pointer{cursor:pointer}.xterm.column-select.focus{cursor:crosshair}.xterm .xterm-accessibility,.xterm .xterm-message{bottom:0;color:transparent;left:0;position:absolute;right:0;top:0;z-index:10}.xterm .live-region{height:1px;left:-9999px;overflow:hidden;position:absolute;width:1px}.xterm-dim{opacity:.5}.xterm-underline{text-decoration:underline}.xterm-strikethrough{text-decoration:line-through}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1 @@
 | 
			
		|||
<!DOCTYPE html><html><head><link rel="stylesheet" href="index.6999253a.css"><title>{{.AppName}}</title><style>body::-webkit-scrollbar,div::-webkit-scrollbar,html::-webkit-scrollbar{display:none;width:0}body,html{margin:0;overflow:hidden;padding:0}div#terminal{height:100%;left:0;position:absolute;top:0;width:100%}div#terminal div{height:100%}.xterm-screen,.xterm-viewport{height:100%;margin:0;padding:0}</style></head><body> <div id="terminal"></div> <script type="module" src="index.434ad47d.js"></script> </body></html>
 | 
			
		||||
		Loading…
	
		Reference in New Issue