Split common into primitives and runtime layers
Reorganize src/common per issue #5963: move building blocks under primitives/ and services/integration under runtime/. Preserve existing common/* import paths via TypeScript path mapping. Add src/ARCHITECTURE.md documenting modules and goals. Fix two relative imports broken by the directory depth change. Co-authored-by: Daniel Imms <Tyriar@users.noreply.github.com>
This commit is contained in:
co-authored by
Daniel Imms
parent
43e8365f0e
commit
9a65429a30
@@ -11,6 +11,8 @@
|
||||
"removeComments": true,
|
||||
"paths": {
|
||||
"common/*": [
|
||||
"../../../src/common/primitives/*",
|
||||
"../../../src/common/runtime/*",
|
||||
"../../../src/common/*"
|
||||
],
|
||||
"browser/*": [
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
"removeComments": true,
|
||||
"paths": {
|
||||
"common/*": [
|
||||
"../../../src/common/primitives/*",
|
||||
"../../../src/common/runtime/*",
|
||||
"../../../src/common/*"
|
||||
],
|
||||
"browser/*": [
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
"removeComments": true,
|
||||
"paths": {
|
||||
"common/*": [
|
||||
"../../../src/common/primitives/*",
|
||||
"../../../src/common/runtime/*",
|
||||
"../../../src/common/*"
|
||||
],
|
||||
"browser/*": [
|
||||
|
||||
@@ -13,7 +13,11 @@
|
||||
],
|
||||
"paths": {
|
||||
"browser/*": [ "../../../src/browser/*" ],
|
||||
"common/*": [ "../../../src/common/*" ],
|
||||
"common/*": [
|
||||
"../../../src/common/primitives/*",
|
||||
"../../../src/common/runtime/*",
|
||||
"../../../src/common/*"
|
||||
],
|
||||
"@xterm/addon-image": [ "../typings/addon-image.d.ts" ],
|
||||
"*": [ "./*" ]
|
||||
}
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
"removeComments": true,
|
||||
"paths": {
|
||||
"common/*": [
|
||||
"../../../src/common/primitives/*",
|
||||
"../../../src/common/runtime/*",
|
||||
"../../../src/common/*"
|
||||
],
|
||||
"browser/*": [
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
],
|
||||
"paths": {
|
||||
"common/*": [
|
||||
"../../../src/common/primitives/*",
|
||||
"../../../src/common/runtime/*",
|
||||
"../../../src/common/*"
|
||||
],
|
||||
"browser/*": [
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
"removeComments": true,
|
||||
"paths": {
|
||||
"common/*": [
|
||||
"../../../src/common/primitives/*",
|
||||
"../../../src/common/runtime/*",
|
||||
"../../../src/common/*"
|
||||
],
|
||||
"browser/*": [
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
],
|
||||
"paths": {
|
||||
"common/*": [
|
||||
"../../../src/common/primitives/*",
|
||||
"../../../src/common/runtime/*",
|
||||
"../../../src/common/*"
|
||||
],
|
||||
"browser/*": [
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
"removeComments": true,
|
||||
"paths": {
|
||||
"common/*": [
|
||||
"../../../src/common/primitives/*",
|
||||
"../../../src/common/runtime/*",
|
||||
"../../../src/common/*"
|
||||
],
|
||||
"browser/*": [
|
||||
|
||||
@@ -12,7 +12,11 @@
|
||||
"target": "es2021",
|
||||
"module": "nodenext",
|
||||
"paths": {
|
||||
"common/*": ["../../../src/common/*"],
|
||||
"common/*": [
|
||||
"../../../src/common/primitives/*",
|
||||
"../../../src/common/runtime/*",
|
||||
"../../../src/common/*"
|
||||
],
|
||||
"browser/*": ["../../../src/browser/*"],
|
||||
"SerializeAddon": ["../src/SerializeAddon"],
|
||||
"@xterm/addon-serialize": [
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
"removeComments": true,
|
||||
"paths": {
|
||||
"common/*": [
|
||||
"../../../src/common/primitives/*",
|
||||
"../../../src/common/runtime/*",
|
||||
"../../../src/common/*"
|
||||
],
|
||||
"browser/*": [
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
"removeComments": true,
|
||||
"paths": {
|
||||
"common/*": [
|
||||
"../../../src/common/primitives/*",
|
||||
"../../../src/common/runtime/*",
|
||||
"../../../src/common/*"
|
||||
],
|
||||
"browser/*": [
|
||||
|
||||
@@ -9,7 +9,11 @@
|
||||
"target": "es2015",
|
||||
"module": "nodenext",
|
||||
"paths": {
|
||||
"common/*": ["../../../src/common/*"],
|
||||
"common/*": [
|
||||
"../../../src/common/primitives/*",
|
||||
"../../../src/common/runtime/*",
|
||||
"../../../src/common/*"
|
||||
],
|
||||
"browser/*": ["../../../src/browser/*"],
|
||||
"UnicodeGraphemeProvider": ["../src/UnicodeGraphemeProvider"],
|
||||
"@xterm/addon-unicode-graphemes": [
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
"strict": true,
|
||||
"paths": {
|
||||
"common/*": [
|
||||
"../../../src/common/primitives/*",
|
||||
"../../../src/common/runtime/*",
|
||||
"../../../src/common/*"
|
||||
],
|
||||
"@xterm/addon-unicode-graphemes": [
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
"removeComments": true,
|
||||
"paths": {
|
||||
"common/*": [
|
||||
"../../../src/common/primitives/*",
|
||||
"../../../src/common/runtime/*",
|
||||
"../../../src/common/*"
|
||||
],
|
||||
"browser/*": [
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
"strict": true,
|
||||
"paths": {
|
||||
"common/*": [
|
||||
"../../../src/common/primitives/*",
|
||||
"../../../src/common/runtime/*",
|
||||
"../../../src/common/*"
|
||||
],
|
||||
"@xterm/addon-unicode11": [
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
"removeComments": true,
|
||||
"paths": {
|
||||
"common/*": [
|
||||
"../../../src/common/primitives/*",
|
||||
"../../../src/common/runtime/*",
|
||||
"../../../src/common/*"
|
||||
],
|
||||
"browser/*": [
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
"removeComments": true,
|
||||
"paths": {
|
||||
"common/*": [
|
||||
"../../../src/common/primitives/*",
|
||||
"../../../src/common/runtime/*",
|
||||
"../../../src/common/*"
|
||||
],
|
||||
"browser/*": [
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
"removeComments": true,
|
||||
"paths": {
|
||||
"common/*": [
|
||||
"../../../src/common/primitives/*",
|
||||
"../../../src/common/runtime/*",
|
||||
"../../../src/common/*"
|
||||
],
|
||||
"browser/*": [
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
"removeComments": true,
|
||||
"paths": {
|
||||
"common/*": [
|
||||
"../../../src/common/primitives/*",
|
||||
"../../../src/common/runtime/*",
|
||||
"../../../src/common/*"
|
||||
],
|
||||
"browser/*": [
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
"removeComments": true,
|
||||
"paths": {
|
||||
"common/*": [
|
||||
"../../../src/common/primitives/*",
|
||||
"../../../src/common/runtime/*",
|
||||
"../../../src/common/*"
|
||||
],
|
||||
"browser/*": [
|
||||
|
||||
+3
-1
@@ -190,7 +190,9 @@ if (config.addon) {
|
||||
...outConfig,
|
||||
entryPoints: [
|
||||
'src/browser/**/*.ts',
|
||||
'src/common/**/*.ts',
|
||||
'src/common/primitives/**/*.ts',
|
||||
'src/common/runtime/**/*.ts',
|
||||
'src/common/*.ts',
|
||||
'src/headless/**/*.ts'
|
||||
],
|
||||
outdir: 'out-esbuild/'
|
||||
|
||||
+1
-1
@@ -81,7 +81,7 @@ function checkAndPublishPackage(packageDir, repoCommit, peerDependencies, update
|
||||
|
||||
// Update Version.ts with the new version
|
||||
if (updateVersionTs) {
|
||||
const versionTsPath = path.join(packageDir, 'src/common/Version.ts');
|
||||
const versionTsPath = path.join(packageDir, 'src/common/primitives/Version.ts');
|
||||
const versionTsContent = fs.readFileSync(versionTsPath, 'utf8');
|
||||
const updatedVersionTs = versionTsContent.replace(
|
||||
/export const XTERM_VERSION = '[^']+';/,
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
# xterm.js source architecture
|
||||
|
||||
This document describes how `src/` is organized, with emphasis on the shared core under `src/common/`. The layout follows the refined proposal in [issue #5963](https://github.com/xtermjs/xterm.js/issues/5963): separate **primitives** (building blocks) from **runtime** (services and integration), while **browser** and **headless** remain target-specific entry points.
|
||||
|
||||
## Layer overview
|
||||
|
||||
```mermaid
|
||||
flowchart BT
|
||||
primitives["common/primitives<br/>building blocks, high test coverage expected"]
|
||||
runtime["common/runtime<br/>services, integration"]
|
||||
browser["browser<br/>DOM terminal target"]
|
||||
headless["headless<br/>Node terminal target"]
|
||||
|
||||
runtime --> primitives
|
||||
browser --> runtime
|
||||
headless --> runtime
|
||||
```
|
||||
|
||||
| Layer | Path | Role |
|
||||
| --- | --- | --- |
|
||||
| Primitives | `src/common/primitives/` | Low-level, mostly stateless building blocks: buffer, parser, escape/input helpers, static data, and shared utilities. These modules should be easy to unit test in isolation. |
|
||||
| Runtime | `src/common/runtime/` | Stateful services (DI), `CoreTerminal`, `InputHandler`, public API adapters under `public/`, and other code that wires primitives into a working terminal core. |
|
||||
| Shared types | `src/common/Types.ts` | Cross-cutting interfaces and types used by both layers (kept at the `common/` root until a stricter module API is introduced). |
|
||||
| Browser target | `src/browser/` | Browser-only rendering, input, and the public `Terminal` wrapper. |
|
||||
| Headless target | `src/headless/` | Node-oriented terminal without DOM; same public API shape as the browser build where applicable. |
|
||||
|
||||
## `common/primitives/`
|
||||
|
||||
| Area | Contents |
|
||||
| --- | --- |
|
||||
| Root utilities | `Async`, `CircularList`, `Color`, `Event`, `Lifecycle`, `MultiKeyMap`, `Platform`, `SortedList`, `StringBuilder`, `TaskQueue`, `Version` |
|
||||
| `buffer/` | Screen buffer, cells, lines, markers, reflow |
|
||||
| `data/` | Static tables (`Charsets`, `EscapeSequences`) |
|
||||
| `input/` | UTF decoding, keyboard helpers, write buffer, color parsing |
|
||||
| `parser/` | Escape-sequence parser (CSI, OSC, DCS, APC) |
|
||||
|
||||
**Goals**
|
||||
|
||||
- Prefer comprehensive unit tests here; behavior should be understandable without constructing the full terminal stack.
|
||||
- Avoid importing from `runtime/` when possible. Some legacy edges still reach into `common/services` (for example buffer logging hooks); tightening that is follow-up work, not a blocker for the folder split.
|
||||
- Future work may split primitives into finer TypeScript projects (`base`, `encoding`, `buffer`, …) with enforced one-way references.
|
||||
|
||||
## `common/runtime/`
|
||||
|
||||
| Area | Contents |
|
||||
| --- | --- |
|
||||
| `services/` | Dependency-injection services (`BufferService`, `OptionsService`, `CoreService`, …) |
|
||||
| `public/` | Public API surface adapters (`AddonManager`, buffer/parser API views) |
|
||||
| Root integration | `CoreTerminal`, `InputHandler`, `WindowsMode`, test helpers (`TestUtils.test.ts`) |
|
||||
|
||||
**Goals**
|
||||
|
||||
- Own composition: instantiation, service registry, and the large integration classes (`InputHandler`).
|
||||
- May depend on `primitives/` and on `common/Types.ts`; must not be depended on by primitives in the steady state (existing cycles are technical debt to remove incrementally).
|
||||
- Integration and addon-facing behavior is validated by unit tests here and by browser/headless/integration tests at the target layer.
|
||||
|
||||
## Import paths
|
||||
|
||||
Source continues to use the existing `common/...` import prefix (for example `common/buffer/Buffer`, `common/services/Services`). TypeScript `paths` in `tsconfig.json` files map that prefix onto `primitives/`, `runtime/`, and the `common/` root so this restructure did not require mass import rewrites.
|
||||
|
||||
## Targets vs core
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
subgraph core["Shared core"]
|
||||
primitives
|
||||
runtime
|
||||
end
|
||||
browser --> runtime
|
||||
headless --> runtime
|
||||
```
|
||||
|
||||
Browser and headless add platform code (renderers, DOM, Node specifics) on top of the same runtime core. Addons and the demo build against the published packages; their tsconfigs use the same `common/*` path mapping.
|
||||
|
||||
## Related issues
|
||||
|
||||
- [#5963](https://github.com/xtermjs/xterm.js/issues/5963) — module split and TypeScript project structure
|
||||
- [#5896](https://github.com/xtermjs/xterm.js/issues/5896) — relative imports (possible follow-up)
|
||||
- [#5897](https://github.com/xtermjs/xterm.js/issues/5897) — `import/no-cycle` lint enforcement
|
||||
@@ -53,7 +53,7 @@ import { C0, C1ESCAPED } from 'common/data/EscapeSequences';
|
||||
import { toRgbString } from 'common/input/XParseColor';
|
||||
import { DecorationService } from 'common/services/DecorationService';
|
||||
import { IDecorationService } from 'common/services/Services';
|
||||
import { WindowsOptionsReportType } from '../common/InputHandler';
|
||||
import { WindowsOptionsReportType } from 'common/InputHandler';
|
||||
import { AccessibilityManager } from './AccessibilityManager';
|
||||
import { Linkifier } from './Linkifier';
|
||||
import { Emitter, EventUtils, type IEvent } from 'common/Event';
|
||||
|
||||
@@ -11,7 +11,11 @@
|
||||
],
|
||||
"skipLibCheck": true,
|
||||
"paths": {
|
||||
"common/*": [ "./../common/*" ],
|
||||
"common/*": [
|
||||
"./../common/primitives/*",
|
||||
"./../common/runtime/*",
|
||||
"./../common/*"
|
||||
],
|
||||
"*": [ "./../*" ]
|
||||
}
|
||||
},
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@ import { NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE, DEFAULT_ATTR, Content,
|
||||
import { BufferLine } from 'common/buffer//BufferLine';
|
||||
import { BufferLineStringCache } from 'common/buffer/BufferLineStringCache';
|
||||
import { CellData } from 'common/buffer/CellData';
|
||||
import { CharData, IBufferLine, ICellData } from '../Types';
|
||||
import { CharData, IBufferLine, ICellData } from 'common/Types';
|
||||
import { assert } from 'chai';
|
||||
import { AttributeData } from 'common/buffer/AttributeData';
|
||||
import { createCellData, NULL_CELL_DATA, extendedAttributes } from 'common/TestUtils.test';
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user