Commit 313b79d8 authored by Phil Hughes's avatar Phil Hughes

Merge branch '25990-improve-web-terminal' into 'master'

Move xterm to a node dependency and remove it from vendor's folder

Closes #49741

See merge request gitlab-org/gitlab-ce!20588
parents 30c960d4 26b8209e
import 'vendor/xterm/encoding-indexes'; import Terminal from './terminal';
import 'vendor/xterm/encoding';
import Terminal from 'vendor/xterm/xterm';
import 'vendor/xterm/fit';
import './terminal';
window.Terminal = Terminal; export default () => new Terminal({ selector: '#terminal' });
export default () => new gl.Terminal({ selector: '#terminal' });
/* global Terminal */
import $ from 'jquery'; import $ from 'jquery';
import { Terminal } from 'xterm';
import * as fit from 'xterm/lib/addons/fit/fit';
(() => { export default class GLTerminal {
class GLTerminal { constructor(options = {}) {
this.options = Object.assign({}, {
constructor(options) { cursorBlink: true,
this.options = options || {}; screenKeys: true,
}, options);
if (!Object.prototype.hasOwnProperty.call(this.options, 'cursorBlink')) {
this.options.cursorBlink = true;
}
if (!Object.prototype.hasOwnProperty.call(this.options, 'screenKeys')) { this.container = document.querySelector(options.selector);
this.options.screenKeys = true;
}
this.container = document.querySelector(options.selector); this.setSocketUrl();
this.createTerminal();
this.setSocketUrl(); $(window)
this.createTerminal(); .off('resize.terminal')
$(window).off('resize.terminal').on('resize.terminal', () => { .on('resize.terminal', () => {
this.terminal.fit(); this.terminal.fit();
}); });
} }
setSocketUrl() {
const { protocol, hostname, port } = window.location;
const wsProtocol = protocol === 'https:' ? 'wss://' : 'ws://';
const path = this.container.dataset.projectPath;
setSocketUrl() { this.socketUrl = `${wsProtocol}${hostname}:${port}${path}`;
const { protocol, hostname, port } = window.location; }
const wsProtocol = protocol === 'https:' ? 'wss://' : 'ws://';
const path = this.container.dataset.projectPath;
this.socketUrl = `${wsProtocol}${hostname}:${port}${path}`; createTerminal() {
} Terminal.applyAddon(fit);
createTerminal() { this.terminal = new Terminal(this.options);
this.terminal = new Terminal(this.options);
this.socket = new WebSocket(this.socketUrl, ['terminal.gitlab.com']);
this.socket.binaryType = 'arraybuffer';
this.terminal.open(this.container); this.socket = new WebSocket(this.socketUrl, ['terminal.gitlab.com']);
this.socket.onopen = () => { this.runTerminal(); }; this.socket.binaryType = 'arraybuffer';
this.socket.onerror = () => { this.handleSocketFailure(); };
}
runTerminal() { this.terminal.open(this.container);
const decoder = new TextDecoder('utf-8'); this.terminal.fit();
const encoder = new TextEncoder('utf-8'); this.terminal.focus();
this.terminal.on('data', (data) => { this.socket.onopen = () => {
this.socket.send(encoder.encode(data)); this.runTerminal();
}); };
this.socket.onerror = () => {
this.handleSocketFailure();
};
}
this.socket.addEventListener('message', (ev) => { runTerminal() {
this.terminal.write(decoder.decode(ev.data)); const decoder = new TextDecoder('utf-8');
}); const encoder = new TextEncoder('utf-8');
this.isTerminalInitialized = true; this.terminal.on('data', data => {
this.terminal.fit(); this.socket.send(encoder.encode(data));
} });
handleSocketFailure() { this.socket.addEventListener('message', ev => {
this.terminal.write('\r\nConnection failure'); this.terminal.write(decoder.decode(ev.data));
} });
this.isTerminalInitialized = true;
this.terminal.fit();
} }
window.gl = window.gl || {}; handleSocketFailure() {
gl.Terminal = GLTerminal; this.terminal.write('\r\nConnection failure');
})(); }
}
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
- page_title 'Terminal', "#{@build.name} (##{@build.id})", 'Jobs' - page_title 'Terminal', "#{@build.name} (##{@build.id})", 'Jobs'
- content_for :page_specific_javascripts do - content_for :page_specific_javascripts do
= stylesheet_link_tag "xterm/xterm" = stylesheet_link_tag "xterm.css"
.terminal-container{ class: container_class } .terminal-container{ class: container_class }
#terminal{ data: { project_path: terminal_project_job_path(@project, @build, format: :ws) } } #terminal{ data: { project_path: terminal_project_job_path(@project, @build, format: :ws) } }
---
title: Move xterm to a node dependency and remove it from vendor's folder
merge_request: 20588
author:
type: other
...@@ -133,7 +133,6 @@ module Gitlab ...@@ -133,7 +133,6 @@ module Gitlab
config.assets.precompile << "print.css" config.assets.precompile << "print.css"
config.assets.precompile << "notify.css" config.assets.precompile << "notify.css"
config.assets.precompile << "mailers/*.css" config.assets.precompile << "mailers/*.css"
config.assets.precompile << "xterm/xterm.css"
config.assets.precompile << "page_bundles/ide.css" config.assets.precompile << "page_bundles/ide.css"
config.assets.precompile << "performance_bar.css" config.assets.precompile << "performance_bar.css"
config.assets.precompile << "lib/ace.js" config.assets.precompile << "lib/ace.js"
...@@ -149,6 +148,10 @@ module Gitlab ...@@ -149,6 +148,10 @@ module Gitlab
config.assets.precompile << "icons.json" config.assets.precompile << "icons.json"
config.assets.precompile << "illustrations/*.svg" config.assets.precompile << "illustrations/*.svg"
# Import css for xterm
config.assets.paths << "#{config.root}/node_modules/xterm/src/"
config.assets.precompile << "xterm.css"
# Version of your assets, change this if you want to expire all your assets # Version of your assets, change this if you want to expire all your assets
config.assets.version = '1.0' config.assets.version = '1.0'
......
...@@ -103,7 +103,8 @@ ...@@ -103,7 +103,8 @@
"webpack-bundle-analyzer": "^2.13.1", "webpack-bundle-analyzer": "^2.13.1",
"webpack-cli": "^3.0.8", "webpack-cli": "^3.0.8",
"webpack-stats-plugin": "^0.2.1", "webpack-stats-plugin": "^0.2.1",
"worker-loader": "^2.0.0" "worker-loader": "^2.0.0",
"xterm": "^3.5.0"
}, },
"devDependencies": { "devDependencies": {
"axios-mock-adapter": "^1.15.0", "axios-mock-adapter": "^1.15.0",
......
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
/*
* Fit terminal columns and rows to the dimensions of its
* DOM element.
*
* Approach:
* - Rows: Truncate the division of the terminal parent element height
* by the terminal row height
*
* - Columns: Truncate the division of the terminal parent element width by
* the terminal character width (apply display: inline at the
* terminal row and truncate its width with the current number
* of columns)
*/
(function (fit) {
if (typeof exports === 'object' && typeof module === 'object') {
/*
* CommonJS environment
*/
module.exports = fit(require('./xterm'));
} else if (typeof define == 'function') {
/*
* Require.js is available
*/
define(['./xterm'], fit);
} else {
/*
* Plain browser environment
*/
fit(window.Terminal);
}
})(function (Xterm) {
/**
* This module provides methods for fitting a terminal's size to a parent container.
*
* @module xterm/addons/fit/fit
*/
var exports = {};
exports.proposeGeometry = function (term) {
var parentElementStyle = window.getComputedStyle(term.element.parentElement),
parentElementHeight = parseInt(parentElementStyle.getPropertyValue('height')),
parentElementWidth = parseInt(parentElementStyle.getPropertyValue('width')),
elementStyle = window.getComputedStyle(term.element),
elementPaddingVer = parseInt(elementStyle.getPropertyValue('padding-top')) + parseInt(elementStyle.getPropertyValue('padding-bottom')),
elementPaddingHor = parseInt(elementStyle.getPropertyValue('padding-right')) + parseInt(elementStyle.getPropertyValue('padding-left')),
availableHeight = parentElementHeight - elementPaddingVer,
availableWidth = parentElementWidth - elementPaddingHor,
container = term.rowContainer,
subjectRow = term.rowContainer.firstElementChild,
contentBuffer = subjectRow.innerHTML,
characterHeight,
rows,
characterWidth,
cols,
geometry;
subjectRow.style.display = 'inline';
subjectRow.innerHTML = 'W'; // Common character for measuring width, although on monospace
characterWidth = subjectRow.getBoundingClientRect().width;
subjectRow.style.display = ''; // Revert style before calculating height, since they differ.
characterHeight = parseInt(subjectRow.offsetHeight);
subjectRow.innerHTML = contentBuffer;
rows = parseInt(availableHeight / characterHeight);
cols = parseInt(availableWidth / characterWidth) - 1;
geometry = {cols: cols, rows: rows};
return geometry;
};
exports.fit = function (term) {
var geometry = exports.proposeGeometry(term);
term.resize(geometry.cols, geometry.rows);
};
Xterm.prototype.proposeGeometry = function () {
return exports.proposeGeometry(this);
};
Xterm.prototype.fit = function () {
return exports.fit(this);
};
return exports;
});
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
...@@ -8006,6 +8006,10 @@ xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.1: ...@@ -8006,6 +8006,10 @@ xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.1:
version "4.0.1" version "4.0.1"
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af"
xterm@^3.5.0:
version "3.5.0"
resolved "https://registry.yarnpkg.com/xterm/-/xterm-3.5.0.tgz#ba3f464bc5730c9d259ebe62131862224db9ddcc"
y18n@^3.2.1: y18n@^3.2.1:
version "3.2.1" version "3.2.1"
resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41"
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment