From 2f4ae3f4d80abeab252ebc4ff667b581b3b06dcd Mon Sep 17 00:00:00 2001 From: Joongi Kim Date: Thu, 9 Feb 2017 17:52:15 +0900 Subject: [PATCH] refs #9: Replace terminal.js with xterm. * xterm-js is better maintained and has explicit support to CJK. * Currently printing works okay (Korean chars occupy exactly the space of two alphabet chars) but typing does not work. :( * TODO: embed CSS as one of Sorna's static asset. --- assets/js/main.js | 1 + assets/js/webterm.js | 32 +++++++++++++++++++++++++------- package.json | 6 ++++-- webpack.config.js | 4 ++++ webpack.dev.config.js | 4 ++++ yarn.lock | 25 +++++++++++++++++++++++-- 6 files changed, 61 insertions(+), 11 deletions(-) diff --git a/assets/js/main.js b/assets/js/main.js index 4ecc4d2..ab2b451 100644 --- a/assets/js/main.js +++ b/assets/js/main.js @@ -33,6 +33,7 @@ Sorna.loadWebterm = (resolve) => { resolve(); }); } + // TODO: inject CSS from Sorna.assetRoot }; class _Utils { diff --git a/assets/js/webterm.js b/assets/js/webterm.js index c128bff..f8aeb6b 100644 --- a/assets/js/webterm.js +++ b/assets/js/webterm.js @@ -1,9 +1,24 @@ 'use strict'; -const Terminal = require('terminal.js'); +const Terminal = require('xterm'); const SockJS = require('sockjs-client'); const Writable = require('stream').Writable; +function b64EncodeUnicode(str) { + return window.btoa(unescape(encodeURIComponent( str ))); + //return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function(match, p1) { + // return String.fromCharCode('0x' + p1); + //})); +} + +function b64DecodeUnicode(str) { + return decodeURIComponent(escape(window.atob( str ))); + //return decodeURIComponent(Array.prototype.map.call(atob(str), function(c) { + // return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2); + //}).join('')); +} + + class SocketWritable extends Writable { constructor(sessId, sock) { super(); @@ -15,7 +30,7 @@ class SocketWritable extends Writable { let msg = JSON.stringify({ "sid": this._sessId, "type": "stdin", - "chars": btoa(chunk), + "chars": b64EncodeUnicode(chunk), }); this._sock.send(msg); if (cb) cb(); @@ -58,8 +73,9 @@ class Webterm { return; } - this.term = new Terminal(this.container); - this.term.state.reset(); + this.term = new Terminal(); + this.term.open(this.container); + this.term.reset(); this.term.write("Loading your terminal...\r\n"); let url = "//" + document.domain @@ -67,7 +83,9 @@ class Webterm { this._sock = new SockJS(url); this.writable = new SocketWritable(this.sessId, this._sock); - this.term.dom(this.container).pipe(this.writable); + this.term.on('data', (data) => { + this.writable.write(data); + }); let is_settled = false; @@ -104,7 +122,7 @@ class Webterm { let data = JSON.parse(e.data); switch (data.type) { case "out": - this.term.write(atob(data.data)); + this.term.write(b64DecodeUnicode(data.data)); break; case "error": this.term.write('\r\n\x1b[37;41;1m Ooops, we got a server error! \x1b[0;31m\r\n' + data.reason + '\x1b[0m\r\n'); @@ -190,7 +208,7 @@ class Webterm { numRows = Math.min(numRows, opts.maxRows); if (opts.maxCols > 0) numCols = Math.min(numCols, opts.maxCols); - this.term.state.resize({rows: numRows, columns: numCols}); + this.term.resize(numCols, numRows); if (this._connected) { this._sock.send(JSON.stringify({ "sid": this.sessId, diff --git a/package.json b/package.json index 06e9f06..d031021 100644 --- a/package.json +++ b/package.json @@ -7,9 +7,11 @@ "fabric": ">=1.7.3", "msgpack-lite": ">=0.1.20", "sockjs-client": "^1.1.2", - "terminal.js": "^1.0.7", + "ts-loader": "^2.0.0", + "typescript": "^2.1.6", "webpack": ">=2.2", - "webpack-dashboard": "^0.3.0" + "webpack-dashboard": "^0.3.0", + "xterm": "^2.3.1" }, "dependencies": { "fabric": ">=1.7.3", diff --git a/webpack.config.js b/webpack.config.js index 8d7c375..dc7f190 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -12,8 +12,12 @@ const config = { module: { loaders: [ { test: /\.js$/, exclude: /node_modules/, loader: "babel-loader" }, + { test: /\.tsx?$/, loader: "ts-loader" }, ], }, + resolve: { + extensions: ['', '.webpack.js', '.web.js', '.ts', '.tsx', '.js'], + }, devtool: 'hidden-source-map', plugins: [ new webpack.optimize.UglifyJsPlugin({ diff --git a/webpack.dev.config.js b/webpack.dev.config.js index 0a4c54f..c93a6c2 100644 --- a/webpack.dev.config.js +++ b/webpack.dev.config.js @@ -16,8 +16,12 @@ const config = { module: { loaders: [ { test: /\.js$/, exclude: /node_modules/, loader: "babel-loader" }, + { test: /\.tsx?$/, loader: "ts-loader" }, ], }, + resolve: { + extensions: ['', '.webpack.js', '.web.js', '.ts', '.tsx', '.js'], + }, devtool: 'inline-source-map', devServer: { port: 8002, diff --git a/yarn.lock b/yarn.lock index 8013135..a683e39 100644 --- a/yarn.lock +++ b/yarn.lock @@ -897,6 +897,10 @@ code-point-at@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" +colors@^1.0.3: + version "1.1.2" + resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63" + combined-stream@^1.0.5, combined-stream@~1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.5.tgz#938370a57b4a51dea2c77c15d5c5fdf895164009" @@ -1820,7 +1824,7 @@ loader-runner@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.3.0.tgz#f482aea82d543e07921700d5a46ef26fdac6b8a2" -loader-utils@^0.2.11, loader-utils@^0.2.16: +loader-utils@^0.2.11, loader-utils@^0.2.16, loader-utils@^0.2.6: version "0.2.16" resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-0.2.16.tgz#f08632066ed8282835dff88dfb52704765adee6d" dependencies: @@ -2420,7 +2424,7 @@ ripemd160@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-1.0.1.tgz#93a4bbd4942bc574b69a8fa57c71de10ecca7d6e" -"semver@2 || 3 || 4 || 5", semver@~5.3.0: +"semver@2 || 3 || 4 || 5", semver@^5.0.1, semver@~5.3.0: version "5.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" @@ -2676,6 +2680,15 @@ tough-cookie@~2.3.0: dependencies: punycode "^1.4.1" +ts-loader@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-2.0.0.tgz#26f382b51951bf5db4c88ea5f3b156c1cfdd813f" + dependencies: + colors "^1.0.3" + enhanced-resolve "^3.0.0" + loader-utils "^0.2.6" + semver "^5.0.1" + tty-browserify@0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" @@ -2694,6 +2707,10 @@ type-check@~0.3.2: dependencies: prelude-ls "~1.1.2" +typescript@^2.1.6: + version "2.1.6" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.1.6.tgz#40c7e6e9e5da7961b7718b55505f9cac9487a607" + uglify-js@^2.7.5: version "2.7.5" resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.7.5.tgz#4612c0c7baaee2ba7c487de4904ae122079f2ca8" @@ -2900,6 +2917,10 @@ xtend@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" +xterm@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/xterm/-/xterm-2.3.1.tgz#78acbcb1f88dac85916c7abb94424c827238849f" + y18n@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41"