Skip to content

Contributing

Daniel Imms edited this page Jul 9, 2024 · 21 revisions

Xterm.js is maintained by several core team members, but we would love to receive contributions from everyone!

To contribute either code, documentation or issues to xterm.js please read the Contributing document beforehand. All you need to contribute is an editor that supports JavaScript/TypeScript, a browser. You will need Node.js installed locally to get all the features working in the demo.

Running the Demo

⚠️ The xterm.js repo contains a barebones demo implementation, designed for the development and evaluation of the library only. Note that exposing the demo to the public as is would introduce security risks for the host.

Prerequisites

Building

Building the demo involves several watch scripts each run in separate terminals. If you're using VS Code there is a build task setup such that Ctrl/Cmd+Shift+b will run all the tasks for you.

# Compiles core, all addons and integration tests to out-esbuild/, this also
# bundles non-minified versions core and addons to lib/
yarn run esbuild-watch

# Verify typescript types (since esbuild does not do this) and outputs to out/
yarn run tsc-watch

# Bundles the demo
yarn run esbuild-demo-watch

# Runs the demo server
yarn start

If these all run successfully, you should be able to access the demo at http://127.0.0.1:3000

Testing

Unit tests

Unit tests are run with yarn test-unit:

# All unit tests
yarn test-unit

# Absolute file path
yarn test-unit out-esbuild/browser/Terminal.test.js

# Filter by wildcard
yarn test-unit out-esbuild/**/Terminal.test.js

# Specific addon unit tests tests
yarn test-unit addons/addon-image/out-esbuild/*.test.js

# Multiple files
yarn test-unit out-esbuild/**/Terminal.test.js out-esbuild/**/InputHandler.test.js

These use mocha to run all .test.js files within the esbuild output (out-esbuild/).

Integration tests

Integration tests are run with yarn test-integration:

# All integration tests
yarn test-integration

# Core integration tests
yarn test-integration --suite=core

# Specific addon integration tests
yarn test-integration --suite=addon-search

These use @playwright/test to run all tests within the esbuild test output (out-esbuild-test/).

Architecture

Layering

The project uses a layered architecture similar to VS Code's where the project is split into 3 modules:

  • common: The lowest level module, it can run in either a browser or a node.js environment and does not depend on anything.
  • browser: Can run only in a browser environment and depends on common, the public directory contains the API for xterm
  • headless: Depends on common, the public directory contains the API for xterm-headless

Any public directory contains code that implements the public API, for example browser/public/Terminal.ts implements an API façade by wrapping internal objects from browser and common the wraps the objects in browser. It is not recommended for any xterm.js embedder to touch the internal objects (private API) as what they do and whether they even exist is not guaranteed and could change, even across patch versions.

Dependency injection

Dependency injection (DI) in xterm.js is implemented using a simplified version of that used in VS Code. To use it decorations are used, here is an example of injecting IBufferService into a constructor:

class Example {
  constructor(
    @IBufferService bufferService: IBufferService
  ) {
  }
}

In order for DI to work this class must be created using the IInstantiationService:

const example = instantiationService.createInstance(Example);

To implement a new service it must contain a serviceBrand property and then be registered to the IInstantiationService:

interface IExampleService {
  serviceBrand: undefined;
}
class ExampleServiceImpl implements IExampleService {
  public serviceBrand: undefined;
}

const exampleServiceImpl = new ExampleServiceImpl();
this._instantiationService.setService(IExampleService, exampleServiceImpl);

Addons

Several addons are built by the xterm.js team are located in this repository under the addons/ folder. They are in their own separate folders and are treated as individual npm modules, but during development they leverage the dependencies in the root-level package.json file.

Build system

Here is a diagram that shows the flow and depenendencies of the build system used in the Building section:

build-flow

Enabling debug mode

Xterm.js has a debug mode that allows you to view what's being evaluated by the terminal. To enable this mode, run the demo and execute the following in the console:

term.setOption('logLevel', 'debug');

Any data sent to the terminal should be output in the console.

Third party dependencies

We prefer to not include any non-dev third party dependencies in order to keep our code minimal, performant and secure. If you plan on adding a dependency on a third party library it's a good idea to discuss the need in an issue with the maintainers first.