Merge remote-tracking branch 'upstream/master' into pr/jerch/5178
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
# xterm.js Copilot Instructions
|
||||
|
||||
## Architecture Overview
|
||||
|
||||
**Core Structure**: xterm.js is a multi-target terminal emulator with three main distributions:
|
||||
- `src/browser/`: Full-featured browser terminal with DOM rendering
|
||||
- `src/headless/`: Server-side terminal for Node.js (no DOM)
|
||||
- `src/common/`: Shared core logic (parsing, buffer management, terminal state)
|
||||
|
||||
**Key Classes**:
|
||||
- `Terminal` (browser/headless): Public API wrapper
|
||||
- `CoreTerminal` (common): Core terminal logic and state
|
||||
- `CoreBrowserTerminal` (browser): Browser-specific terminal implementation
|
||||
|
||||
## Development Workflow
|
||||
|
||||
**Build System**:
|
||||
```bash
|
||||
npm run build && npm run esbuild # Build all TypeScript and bundle
|
||||
```
|
||||
|
||||
**Testing**:
|
||||
- Unit tests: `npm run test-unit` (Mocha)
|
||||
- Unit tests filtering to file: `npm run test-unit -- **/fileName.ts
|
||||
- Per-addon unit tests: `npm run test-unit addons/addon-image/out-esbuild/*.test.js`
|
||||
- Integration tests: `npm run test-integration` (Playwright across Chrome/Firefox/WebKit)
|
||||
- Integration tests by file: `npm run test-integration -- test/playwright/InputHandler.test.ts`. Never use grep to filter tests, it doesn't work
|
||||
- Integration tests by addon: `npm run test-integration --suite=addon-search`. Suites always follow the format `addon-<something>`
|
||||
|
||||
## Addon Development Pattern
|
||||
|
||||
All addons follow this structure:
|
||||
```typescript
|
||||
export class MyAddon implements ITerminalAddon {
|
||||
activate(terminal: Terminal): void {
|
||||
// Called when loaded via terminal.loadAddon()
|
||||
// Register handlers, access terminal APIs
|
||||
}
|
||||
dispose(): void {
|
||||
// Cleanup when addon is disposed
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Key Examples**:
|
||||
- `addons/addon-fit/`: Terminal sizing
|
||||
- `addons/addon-webgl/`: GPU-accelerated rendering
|
||||
- `addons/addon-search/`: Text search functionality
|
||||
|
||||
## Project-Specific Conventions
|
||||
|
||||
**TypeScript Project Structure**: Uses TypeScript project references (`tsconfig.all.json`) for incremental builds across browser/headless/addons.
|
||||
|
||||
**API Design**:
|
||||
- Browser and headless terminals share the same public API
|
||||
- Proposed APIs require `allowProposedApi: true` option
|
||||
- Constructor-only options (cols, rows) cannot be changed after instantiation
|
||||
|
||||
**Testing Utilities**: Use `TestUtils.ts` helpers:
|
||||
- `openTerminal(ctx, options)` for setup
|
||||
- `pollFor(page, fn, expectedValue)` for async assertions
|
||||
- `writeSync(page, data)` for terminal input
|
||||
|
||||
## Common Patterns
|
||||
|
||||
**Parser Integration**: Register custom escape sequence handlers:
|
||||
```typescript
|
||||
terminal.parser.registerCsiHandler('m', params => {
|
||||
// Handle SGR sequences
|
||||
return true; // Handled
|
||||
});
|
||||
```
|
||||
|
||||
**Buffer Access**: Read terminal content via buffer API:
|
||||
```typescript
|
||||
const line = terminal.buffer.active.getLine(0);
|
||||
const cell = line?.getCell(0);
|
||||
```
|
||||
|
||||
**Events**: All terminals emit standard events (onData, onResize, onRender) plus platform-specific ones.
|
||||
|
||||
## Critical Implementation Details
|
||||
|
||||
- Terminal rendering uses either DOM or WebGL renderers
|
||||
- Buffer lines are immutable; create new instances for modifications
|
||||
- Character width handling supports Unicode 11+ and grapheme clustering
|
||||
- Mouse events translate web events to terminal protocols (X10, VT200, etc.)
|
||||
- Color theming supports both palette and true color modes
|
||||
|
||||
## Writing unit tests
|
||||
|
||||
- Unit tests live alongside the source code file of the thing it's testing with a .test.ts suffix.
|
||||
@@ -0,0 +1,8 @@
|
||||
---
|
||||
applyTo: '**/*.test.ts'
|
||||
---
|
||||
When writing unit tests follow these rules:
|
||||
|
||||
- When writing unit tests for addons, always create a real xterm.js instance instead of mocking it.
|
||||
- Prefer `assert.ok` over `assert.notStrictEqual` when checking something is undefined or not.
|
||||
- Avoid comments as most tests should be self-documenting.
|
||||
+56
-54
@@ -12,17 +12,17 @@ jobs:
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Use Node.js 18.x
|
||||
- name: Use Node.js 22.x
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18.x
|
||||
cache: 'yarn'
|
||||
node-version: 22.x
|
||||
cache: 'npm'
|
||||
- name: Install dependencies
|
||||
run: yarn --frozen-lockfile
|
||||
run: npm ci
|
||||
- name: Setup and run tsc
|
||||
run: yarn setup
|
||||
run: npm run setup
|
||||
- name: Esbuild
|
||||
run: yarn esbuild
|
||||
run: npm run esbuild
|
||||
- name: Zip artifacts
|
||||
run: |
|
||||
zip -r compressed-build \
|
||||
@@ -44,6 +44,9 @@ jobs:
|
||||
./addons/addon-ligatures/lib/* \
|
||||
./addons/addon-ligatures/out/* \
|
||||
./addons/addon-ligatures/out-*/* \
|
||||
./addons/addon-progress/lib/* \
|
||||
./addons/addon-progress/out/* \
|
||||
./addons/addon-progress/out-*/* \
|
||||
./addons/addon-search/lib/* \
|
||||
./addons/addon-search/out/* \
|
||||
./addons/addon-search/out-*/* \
|
||||
@@ -66,7 +69,7 @@ jobs:
|
||||
./addons/addon-webgl/out/* \
|
||||
./addons/addon-webgl/out-*st/*
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: build-artifacts
|
||||
path: compressed-build.zip
|
||||
@@ -77,21 +80,20 @@ jobs:
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Use Node.js 18.x
|
||||
- name: Use Node.js 22.x
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18.x
|
||||
cache: 'yarn'
|
||||
node-version: 22.x
|
||||
cache: 'npm'
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
yarn --frozen-lockfile
|
||||
yarn install-addons
|
||||
npm ci
|
||||
- name: Lint code
|
||||
env:
|
||||
NODE_OPTIONS: --max_old_space_size=4096
|
||||
run: yarn lint
|
||||
run: npm run lint
|
||||
- name: Lint API
|
||||
run: yarn lint-api
|
||||
run: npm run lint-api
|
||||
|
||||
test-unit-coverage:
|
||||
needs: build
|
||||
@@ -99,16 +101,15 @@ jobs:
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Use Node.js 18.x
|
||||
- name: Use Node.js 22.x
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18.x
|
||||
cache: 'yarn'
|
||||
node-version: 22.x
|
||||
cache: 'npm'
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
yarn --frozen-lockfile
|
||||
yarn install-addons
|
||||
- uses: actions/download-artifact@v3
|
||||
npm ci
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: build-artifacts
|
||||
- name: Unzip artifacts
|
||||
@@ -122,7 +123,7 @@ jobs:
|
||||
ls -R
|
||||
- name: Unit test coverage
|
||||
run: |
|
||||
yarn test-unit-coverage --forbid-only
|
||||
npm run test-unit-coverage --forbid-only
|
||||
EXIT_CODE=$?
|
||||
./node_modules/.bin/nyc report --reporter=cobertura
|
||||
exit $EXIT_CODE
|
||||
@@ -131,7 +132,7 @@ jobs:
|
||||
timeout-minutes: 20
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [18]
|
||||
node-version: [22]
|
||||
runs-on: [ubuntu, macos, windows]
|
||||
runs-on: ${{ matrix.runs-on }}-latest
|
||||
steps:
|
||||
@@ -140,17 +141,16 @@ jobs:
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}.x
|
||||
cache: 'yarn'
|
||||
cache: 'npm'
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
yarn --frozen-lockfile
|
||||
yarn install-addons
|
||||
npm ci
|
||||
- name: Wait for build job
|
||||
uses: NathanFirmo/wait-for-other-job@v1.1.1
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
job: build
|
||||
- uses: actions/download-artifact@v3
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: build-artifacts
|
||||
- name: Unzip artifacts
|
||||
@@ -163,27 +163,26 @@ jobs:
|
||||
fi
|
||||
ls -R
|
||||
- name: Unit tests
|
||||
run: yarn test-unit --forbid-only
|
||||
run: npm run test-unit --forbid-only
|
||||
|
||||
test-integration:
|
||||
timeout-minutes: 20
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [18] # just one as integration tests are about testing in browser
|
||||
runs-on: [ubuntu] # macos is flaky
|
||||
node-version: [22] # just one as integration tests are about testing in browser
|
||||
runs-on: [ubuntu-22.04] # macos is flaky
|
||||
browser: [chromium, firefox, webkit]
|
||||
runs-on: ${{ matrix.runs-on }}-latest
|
||||
runs-on: ${{ matrix.runs-on }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Use Node.js ${{ matrix.node-version }}.x
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}.x
|
||||
cache: 'yarn'
|
||||
cache: 'npm'
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
yarn --frozen-lockfile
|
||||
yarn install-addons
|
||||
npm ci
|
||||
- name: Install playwright
|
||||
run: npx playwright install --with-deps ${{ matrix.browser }}
|
||||
- name: Wait for build job
|
||||
@@ -191,7 +190,7 @@ jobs:
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
job: build
|
||||
- uses: actions/download-artifact@v3
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: build-artifacts
|
||||
- name: Unzip artifacts
|
||||
@@ -203,53 +202,56 @@ jobs:
|
||||
unzip -o compressed-build.zip
|
||||
fi
|
||||
ls -R
|
||||
- name: Build demo
|
||||
run: yarn esbuild-demo
|
||||
- name: Build demo client
|
||||
run: npm run esbuild-demo-client
|
||||
- name: Build demo server
|
||||
run: npm run esbuild-demo-server
|
||||
- name: Integration tests (core) # Tests use 50% workers to reduce flakiness
|
||||
run: yarn test-integration-${{ matrix.browser }} --workers=50% --forbid-only --suite=core
|
||||
run: npm run test-integration-${{ matrix.browser }} --workers=50% --forbid-only --suite=core
|
||||
- name: Integration tests (addon-attach)
|
||||
run: yarn test-integration-${{ matrix.browser }} --workers=50% --forbid-only --suite=addon-attach
|
||||
run: npm run test-integration-${{ matrix.browser }} --workers=50% --forbid-only --suite=addon-attach
|
||||
- name: Integration tests (addon-clipboard)
|
||||
run: yarn test-integration-${{ matrix.browser }} --workers=50% --forbid-only --suite=addon-clipboard
|
||||
run: npm run test-integration-${{ matrix.browser }} --workers=50% --forbid-only --suite=addon-clipboard
|
||||
- name: Integration tests (addon-fit)
|
||||
run: yarn test-integration-${{ matrix.browser }} --workers=50% --forbid-only --suite=addon-fit
|
||||
run: npm run test-integration-${{ matrix.browser }} --workers=50% --forbid-only --suite=addon-fit
|
||||
- name: Integration tests (addon-image)
|
||||
run: yarn test-integration-${{ matrix.browser }} --workers=50% --forbid-only --suite=addon-image
|
||||
run: npm run test-integration-${{ matrix.browser }} --workers=50% --forbid-only --suite=addon-image
|
||||
- name: Integration tests (addon-progress)
|
||||
run: npm run test-integration-${{ matrix.browser }} --workers=50% --forbid-only --suite=addon-progress
|
||||
- name: Integration tests (addon-search)
|
||||
run: yarn test-integration-${{ matrix.browser }} --workers=50% --forbid-only --suite=addon-search
|
||||
run: npm run test-integration-${{ matrix.browser }} --workers=50% --forbid-only --suite=addon-search
|
||||
- name: Integration tests (addon-serialize)
|
||||
run: yarn test-integration-${{ matrix.browser }} --workers=50% --forbid-only --suite=addon-serialize
|
||||
run: npm run test-integration-${{ matrix.browser }} --workers=50% --forbid-only --suite=addon-serialize
|
||||
- name: Integration tests (addon-unicode-graphemes)
|
||||
run: yarn test-integration-${{ matrix.browser }} --workers=50% --forbid-only --suite=addon-unicode-graphemes
|
||||
run: npm run test-integration-${{ matrix.browser }} --workers=50% --forbid-only --suite=addon-unicode-graphemes
|
||||
- name: Integration tests (addon-unicode11)
|
||||
run: yarn test-integration-${{ matrix.browser }} --workers=50% --forbid-only --suite=addon-unicode11
|
||||
run: npm run test-integration-${{ matrix.browser }} --workers=50% --forbid-only --suite=addon-unicode11
|
||||
- name: Integration tests (addon-web-fonts)
|
||||
run: yarn test-integration-${{ matrix.browser }} --workers=50% --forbid-only --suite=addon-web-fonts
|
||||
run: npm run test-integration-${{ matrix.browser }} --workers=50% --forbid-only --suite=addon-web-fonts
|
||||
- name: Integration tests (addon-web-links)
|
||||
run: yarn test-integration-${{ matrix.browser }} --workers=50% --forbid-only --suite=addon-web-links
|
||||
run: npm run test-integration-${{ matrix.browser }} --workers=50% --forbid-only --suite=addon-web-links
|
||||
- name: Integration tests (addon-webgl)
|
||||
run: yarn test-integration-${{ matrix.browser }} --workers=50% --forbid-only --suite=addon-webgl
|
||||
run: npm run test-integration-${{ matrix.browser }} --workers=50% --forbid-only --suite=addon-webgl
|
||||
|
||||
release-dry-run:
|
||||
needs: build
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [18]
|
||||
node-version: [22]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Use Node.js ${{ matrix.node-version }}.x
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}.x
|
||||
cache: 'yarn'
|
||||
cache: 'npm'
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
yarn --frozen-lockfile
|
||||
yarn install-addons
|
||||
npm ci
|
||||
- name: Install playwright
|
||||
run: npx playwright install
|
||||
- uses: actions/download-artifact@v3
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: build-artifacts
|
||||
- name: Unzip artifacts
|
||||
@@ -263,7 +265,7 @@ jobs:
|
||||
ls -R
|
||||
- name: Package headless
|
||||
run: |
|
||||
yarn package-headless
|
||||
npm run package-headless
|
||||
node ./bin/package_headless.js
|
||||
- name: Publish to npm (dry run)
|
||||
run: node ./bin/publish.js --dry
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
name: "Copilot Setup Steps"
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
paths:
|
||||
- .github/workflows/copilot-setup-steps.yml
|
||||
pull_request:
|
||||
paths:
|
||||
- .github/workflows/copilot-setup-steps.yml
|
||||
|
||||
jobs:
|
||||
copilot-setup-steps:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
- name: Use Node.js 22.x
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 22.x
|
||||
cache: 'npm'
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
- name: Setup and run tsc
|
||||
run: npm run setup
|
||||
- name: Esbuild
|
||||
run: npm run esbuild
|
||||
@@ -11,18 +11,18 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Use Node.js 18.x
|
||||
- name: Use Node.js 22.x
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18.x
|
||||
cache: 'yarn'
|
||||
node-version: 22.x
|
||||
cache: 'npm'
|
||||
- name: Install dependencies
|
||||
run: yarn --frozen-lockfile
|
||||
run: npm ci
|
||||
- name: Build
|
||||
run: yarn setup
|
||||
run: npm run setup
|
||||
- name: Package headless
|
||||
run: |
|
||||
yarn package-headless
|
||||
npm run package-headless
|
||||
node ./bin/package_headless.js
|
||||
- name: Publish to npm
|
||||
env:
|
||||
|
||||
Reference in New Issue
Block a user