Back to Handsontable

Technology Stack

.ai/STACK.md

18.0.011.0 KB
Original Source

Technology Stack

Languages

Primary:

  • TypeScript - Core library (handsontable/src/), all source files are .ts
  • SCSS/CSS - Styling and themes (handsontable/src/**/*.scss, handsontable/styles/)

Secondary:

  • TypeScript - Framework wrappers (wrappers/react-wrapper/src/, wrappers/angular-wrapper/, wrappers/vue3/src/)
  • TypeScript - Walkontable rendering engine (handsontable/src/3rdparty/walkontable/), excluded from the main tsconfig.json (has its own separate build/test pipeline)
  • HTML - Test runners (handsontable/test/E2ERunner.html, handsontable/src/3rdparty/walkontable/test/SpecRunner.html)

Important: Type declarations are auto-generated by tsc --emitDeclarationOnly (build:types task in scripts/tasks.json, uses tsconfig.build-types.json) and output directly to handsontable/tmp/*.d.ts. Do not hand-edit them. tsconfig.json uses strict: false, noImplicitAny: true. Walkontable (src/3rdparty/walkontable/) is also TypeScript, with its own separate build/test pipeline. Central shared types live in src/core/settings.ts (GridSettings, Events, HookKey) and src/core/types.ts (HotInstance).

Runtime

Environment:

  • Node.js 22 (specified in .nvmrc)
  • Browser-only library at runtime (no server-side logic)

Package Manager:

  • pnpm 10.30.2 (specified in root package.json packageManager field)
  • Activate via: corepack enable && corepack prepare [email protected] --activate
  • Lockfile: pnpm-lock.yaml present
  • Workspace config: pnpm-workspace.yaml

Frameworks

Core:

  • No framework - vanilla JavaScript data grid library
  • Walkontable - internal rendering engine (handsontable/src/3rdparty/walkontable/src/)

Framework Wrappers:

  • React 18 - wrappers/react-wrapper/ (@handsontable/react-wrapper)
  • Angular 16+ - wrappers/angular-wrapper/ (@handsontable/angular-wrapper)
  • Vue 3.2+ - wrappers/vue3/ (@handsontable/vue3)

Testing:

  • Jest 27 - Unit tests (handsontable/jest.config.js, *.unit.js files, jsdom environment, jest-jasmine2 runner)
  • Jasmine 3.4 - E2E browser tests (*.spec.js files, run via Puppeteer)
  • Puppeteer 24 - Headless Chrome for E2E tests
  • Playwright 1.58 - Visual regression tests (visual-tests/)
  • @testing-library/react 14 - React wrapper tests
  • @vue/test-utils 2.0.0-rc.16 - Vue 3 wrapper tests
  • jest-preset-angular 14 - Angular wrapper tests (requires NODE_OPTIONS=--openssl-legacy-provider)

Build/Dev:

  • Rspack 1.7 (@rspack/core, @rspack/cli) - Core library bundling (handsontable/rspack.config.js + handsontable/.config/). Migrated from Webpack 5; the .config/ folder name is kept for historical reasons.
  • Rollup 4 - React and Vue 3 wrapper bundling
  • SWC 1.x (@swc/core, @swc/helpers) - TypeScript/JavaScript transpilation for all builds: Rspack uses builtin:swc-loader with separate rules for .js (ecmascript) and .ts/.tsx (typescript), and file-per-file transpilation runs through handsontable/scripts/swc-transpile.mjs which handles .ts/.tsx in addition to .js (used by build:commonjs, build:es, build:languages.es)
  • Babel 7 - Retained only for Jest unit tests via babel-jest (see handsontable/babel.config.js); no longer used for production or test bundles
  • ng-packagr 16 - Angular library packaging
  • Sass 1.58 - SCSS compilation
  • TypeScript ^6.0.0 (core source + auto-generated types via build:types script using tsconfig.build-types.json), 5.1.6 (Angular), 4.x (Vue 3)

Key Dependencies

Critical (runtime):

  • None. Number formatting uses the native Intl.NumberFormat API. HTML sanitization is user-provided via the sanitizer option.

User-supplied (bring your own):

  • hyperformula ^3.0.0 - Spreadsheet formula engine (devDependency for tests only; users must install it themselves to use the Formulas plugin)

Angular wrapper runtime:

  • rxjs ^7.8.1 - Reactive extensions for Angular
  • tslib ^2.3.0 - TypeScript runtime helpers
  • zone.js ~0.13.0 - Angular change detection

Build tooling (key devDependencies):

  • eslint ^8.57.1 (core) / 8 (wrappers) - Linting with Airbnb base config
  • eslint-plugin-handsontable - Custom ESLint rules (handsontable/.config/plugin/eslint/)
  • eslint-plugin-compat - Browser API compatibility enforcement
  • stylelint 16 - CSS/SCSS linting
  • env-cmd 9 - Injects environment variables from hot.config.js during build
  • cross-env 7 - Cross-platform environment variable setting
  • rspack.CssExtractRspackPlugin - CSS extraction from Rspack bundles (drop-in replacement for the former mini-css-extract-plugin)
  • rspack.LightningCssMinimizerRspackPlugin - CSS minification via Lightning CSS (replaces the former css-minimizer-webpack-plugin)

Configuration

Environment:

  • Build environment variables defined in hot.config.js (root): HOT_FILENAME, HOT_VERSION, HOT_PACKAGE_NAME, HOT_BUILD_DATE, HOT_RELEASE_DATE
  • Injected via env-cmd -f ../hot.config.js in all build/test scripts
  • No .env files in the repository (air-gapped environment support)

Rspack configs (handsontable/.config/): (folder name predates the Webpack→Rspack migration)

  • base.js - Base configuration (UMD output, library name Handsontable, builtin:swc-loader for JS/TS with separate rules for .js ecmascript and .ts/.tsx typescript)
  • development.js / production.js - Dev and production UMD build configs
  • watch.js - Dev watcher config (used by npm run watch)
  • styles-development.js / styles-production.js - CSS build configs
  • themes-css-development.js / themes-css-production.js - Theme CSS builds
  • themes-umd-development.js / themes-umd-production.js - Theme UMD builds
  • languages-development.js / languages-production.js - i18n language pack builds
  • walkontable.js - Walkontable standalone build
  • test-e2e.js / test-e2e-esm-cjs.js / test-mobile.js / test-production.js / test-walkontable.js - Test bundle configs (consumed by test:*.dump scripts)
  • loader/forbidden-imports-loader.js - Custom Rspack loader that replaces the former babel-plugin-forbidden-imports (enforces the E2E allow-list in test-e2e.js)
  • plugin/eslint/ - In-repo ESLint plugin (eslint-plugin-handsontable), linked via file:.config/plugin/eslint

Babel environments (handsontable/babel.config.js):

  • Only one env remains: commonjs - used by Jest unit tests via babel-jest (@babel/plugin-transform-runtime + @babel/plugin-transform-modules-commonjs). Every other former env (commonjs_dist, es, es_languages, commonjs_e2e) was removed when Babel was swapped out for SWC; the babel.config.js header comment states this explicitly.
  • BABEL_ENV=commonjs / BABEL_ENV=commonjs_e2e still appear in several package.json scripts that invoke rspack. Those assignments are effectively dead — Rspack uses builtin:swc-loader and ignores BABEL_ENV. They are kept to avoid churn in scripts but do not select a Babel environment.

SWC pipeline (replaces Babel for everything except Jest):

  • Rspack bundles (rspack.config.js + .config/*) - JS/TS transpiled by builtin:swc-loader using targets from browser-targets.js
  • handsontable/scripts/swc-transpile.mjs - File-per-file transpiler driven by @swc/core; produces the tmp/ output consumed by wrappers. Handles .ts/.tsx in addition to .js. Covers CJS (build:commonjs), ESM (build:es, .mjs output), and i18n language packs with auto-registration (build:languages.es --lang-registration)
  • handsontable/scripts/run.mjs - Unified dispatcher for all npm run scripts; reads task definitions and pipeline graphs from handsontable/scripts/tasks.json; runs tasks quietly with spinner on TTY, supports --parallel (DAG scheduler) and --sequential modes
  • handsontable/scripts/tasks.json - Single source of truth for all build/lint/test task commands, their deps, mode, and cwd; also defines named pipelines (ordered step sequences). Edit this file to add, remove, or change any build/lint/test step — do not add raw shell commands to package.json scripts for the core package

Linting:

  • .eslintrc.js (root) - Monorepo-level ESLint config
  • handsontable/.eslintrc.js - Core-specific ESLint with custom rules
  • Custom ESLint plugin at handsontable/.config/plugin/eslint/ with rules:
    • no-native-error-throw - Must use throwWithCause() from src/helpers/errors.ts
    • restricted-module-imports - No imports from barrel index files
    • require-async-in-it - it() callbacks in spec files must be async
    • require-await - Specific HOT API calls must be await-ed

Testing:

  • handsontable/jest.config.js - Jest config (jsdom environment, jest-jasmine2 runner, *.unit.js pattern)
  • Module aliases in Jest: handsontable -> src/, walkontable -> src/3rdparty/walkontable/src/
  • CSS/SCSS mocked via handsontable/test/__mocks__/styleMock.js
  • E2E test dump scripts use Rspack to bundle test helpers and spec files before Puppeteer execution

Build Outputs

OutputPathFormat
UMD bundleshandsontable/dist/handsontable.js, handsontable/dist/handsontable.full.jsUMD
Minified bundleshandsontable/dist/handsontable.min.js, handsontable/dist/handsontable.full.min.jsUMD (minified)
CommonJS moduleshandsontable/tmp/*.jsCJS
ES moduleshandsontable/tmp/*.mjsESM
Compiled CSShandsontable/styles/CSS
Language packshandsontable/dist/languages/, handsontable/languages/UMD + ESM
Theme bundleshandsontable/dist/themes/UMD + CSS

Two build variants:

  • handsontable.js - Base build, external dependencies not bundled
  • handsontable.full.js - Includes HyperFormula bundled in

Wrappers consume tmp/ output via pnpm workspace linking ("handsontable": "workspace:^" override in root package.json).

CSS Themes

  • ht-theme-main - Default modern theme
  • ht-theme-classic - Legacy Handsontable theme
  • ht-theme-horizon - Alternative design theme
  • Each theme has -no-icons variant
  • Themes use CSS custom property tokens (design system) declared in Figma

Platform Requirements

Development:

  • Node.js 22 (enforced via .nvmrc)
  • pnpm 10.30.2 (via corepack)
  • No Docker, databases, or external services required

Production (browser targets):

  • Chrome (two latest major versions)
  • Firefox (two latest major versions)
  • Safari (two latest major versions)
  • Edge (two latest major versions)
  • Enforced via eslint-plugin-compat

CDN distribution:

  • jsDelivr: dist/handsontable.full.min.js
  • unpkg: dist/handsontable.full.min.js

CI/CD

Platform: GitHub Actions (.github/workflows/)

Key workflows:

  • test.yml - Main test pipeline (unit, E2E, Walkontable, wrapper tests)
  • build-all.yml - Full build verification
  • code-quality.yml - Linting and code quality checks
  • linter.yml - ESLint checks
  • publish.yml - Package publishing pipeline to npm
  • docs-staging.yml / docs-production.yml - Documentation deployment (Netlify)
  • docs-visual-tests.yml - Visual regression testing for docs
  • changelog.yml - Changelog verification
  • audit.yml - Security audit
  • pkg-pr-new.yml - PR package preview