Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
3 changes: 1 addition & 2 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,10 @@ src/interpreter/plugin/3rdparty
*.config.js
karma.*
doc
test/unit/_setupFiles/*.js
test/_setupFiles/*.js

# Auto-generated directories
commonjs
coverage
dist
doc
es
Expand Down
2 changes: 1 addition & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ module.exports = {
},
parserOptions: {
tsconfigRootDir: __dirname,
project: './tsconfig.test.json',
project: './tsconfig.json',
createDefaultProgram: true,
},
extends: [
Expand Down
14 changes: 0 additions & 14 deletions .github/codecov.yml

This file was deleted.

69 changes: 0 additions & 69 deletions .github/workflows/performance.yml

This file was deleted.

7 changes: 1 addition & 6 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,7 @@ jobs:

- name: Run tests
run: |
npm run test:unit.ci -- --coverage

- name: Upload coverage to Codecov
uses: codecov/codecov-action@6004246f47ab62d32be025ce173b241cd84ac58e # https://github.com/codecov/codecov-action/releases/tag/v1.0.13
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
npm run test:ci

browser-tests:
strategy:
Expand Down
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
.idea/
.vscode
/commonjs/
/coverage/
/dist/
/doc/
/docs/api/
Expand Down
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,20 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),

## [Unreleased]

## [3.2.0] - 2026-02-19

### Added

- Added a new function: IRR. [#1591](https://github.com/handsontable/hyperformula/issues/1591)
- Added a new function: N. [#1585](https://github.com/handsontable/hyperformula/issues/1585)
- Added a new function: VALUE. [#1592](https://github.com/handsontable/hyperformula/issues/1592)

### Fixed

- Fixed `Error Map maximum size exceeded` error when loading big spreadsheets. [#1602](https://github.com/handsontable/hyperformula/issues/1602)

## [3.1.1] - 2025-12-18

### Fixed

- Fixed an issue where cells were not recalculated after adding, removing and renaming sheets. [#1116](https://github.com/handsontable/hyperformula/issues/1116)
Expand Down
95 changes: 95 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Project Overview

HyperFormula is a headless spreadsheet engine written in TypeScript. It parses and evaluates Excel-compatible formulas and can run in browser or Node.js environments. The library implements ~400 built-in functions with support for custom functions, undo/redo, CRUD operations, and i18n (17 languages).

## Build & Development Commands

```bash
npm install # Install dependencies
npm run compile # TypeScript compilation to lib/
npm run bundle-all # Full build: compile + bundle all formats
npm run lint # Run ESLint
npm run lint:fix # Auto-fix lint issues
```

## Testing

```bash
npm test # Full suite: lint + unit + browser + compatibility
npm run test:unit # Jest unit tests only
npm run test:watch # Jest watch mode (run tests on file changes)
npm run test:coverage # Unit tests with coverage report
npm run test:browser # Karma browser tests (Chrome/Firefox)
npm run test:performance # Run performance benchmarks
npm run test:compatibility # Excel compatibility tests
```

Test files are located in `test/unit/` and follow the pattern `*.spec.ts`.

## Architecture

### Core Components

- **`src/HyperFormula.ts`** - Main engine class, public API entry point
- **`src/parser/`** - Formula parsing using Chevrotain parser generator
- **`src/interpreter/`** - Formula evaluation engine
- **`src/DependencyGraph/`** - Cell dependency tracking and recalculation order
- **`src/CrudOperations.ts`** - Create/Read/Update/Delete operations on sheets and cells

### Function Plugins (`src/interpreter/plugin/`)

All spreadsheet functions are implemented as plugins extending `FunctionPlugin`. Each plugin:
- Declares `implementedFunctions` static property mapping function names to metadata
- Uses `runFunction()` helper for argument validation, coercion, and array handling
- Registers function translations in `src/i18n/languages/`

To add a new function:
1. Create or modify a plugin in `src/interpreter/plugin/`
2. Add function metadata to `implementedFunctions`
3. Implement the function method
4. Add translations to all language files in `src/i18n/languages/`
5. Add tests in `test/unit/interpreter/`

### i18n (`src/i18n/languages/`)

Function name translations for each supported language. When adding new functions, translations can be found at:
- https://support.microsoft.com/en-us/office/excel-functions-translator-f262d0c0-991c-485b-89b6-32cc8d326889
- http://dolf.trieschnigg.nl/excel/index.php

## Output Formats

The build produces multiple output formats:
- `commonjs/` - CommonJS modules (main entry)
- `es/` - ES modules (.mjs files)
- `dist/` - UMD bundles for browsers
- `typings/` - TypeScript declaration files

## Contributing Guidelines

- Create feature branches, never commit directly to master
- Target the `develop` branch for pull requests
- Add tests for all changes in `test/` folder
- Run linter before submitting (`npm run lint`)
- Maintain compatibility with Excel and Google Sheets behavior
- In documentation, commit messages, pull request descriptions and code comments, do not mention Claude Code nor LLM models used for code generation

## Response Guidelines

- By default speak ultra-concisely, using as few words as you can, unless asked otherwise.
- Focus solely on instructions and provide relevant responses.
- Ask questions to remove ambiguity and make sure you're speaking about the right thing.
- Ask questions if you need more information to provide an accurate answer.
- If you don't know something, simply say, "I don't know," and ask for help.
- Present your answer in a structured way, use bullet lists, numbered lists, tables, etc.
- When asked for specific content, start the response with the requested info immediately.
- When answering based on context, support your claims by quoting exact fragments of available documents.

## Code Style

- When generating code, prefer functional approach whenever possible (in JS/TS use filter, map and reduce functions).
- Make the code self-documenting. Use meaningfull names for classes, functions, valiables etc. Add code comments only when necessary.
- Add jsdocs to all classes and functions.
11 changes: 2 additions & 9 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,7 @@ setup: ## Setup project
compile: ## Compile to javascript
@npm run compile

test: ## Run tests
@npm run test

unit: ## Run unit tests
@npm run test:unit
check: typecheck lint ## Check whether code is working correctly (types + lint)

test-ci: ## Separate test configuration for CI environment
@npm run test
Expand All @@ -26,9 +22,6 @@ lint: ## Show linting errors
lint-fix: ## Fix linting errors
@npm run lint:fix

coverage: ## Run tests and show coverage
@npm run test:coverage

doc: ## Generate documentation
@npm run typedoc:build

Expand Down Expand Up @@ -65,6 +58,6 @@ verify-production-licenses:
help: ## Show all make commands
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'

.PHONY: test coverage benchmark doc servedoc
.PHONY: test doc servedoc

.DEFAULT_GOAL := help
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,16 @@

---

> 🚀 **We're hiring!** Join HyperFormula team as a **Senior Software Engineer**. [See the role and apply](https://handsontable.traffit.com/public/an/4b09e1395bf8ea42ef86db4c4657992c2f48673d).

HyperFormula is a headless spreadsheet built in TypeScript, serving as both a parser and evaluator of spreadsheet formulas. It can be integrated into your browser or utilized as a service with Node.js as your back-end technology.

## What HyperFormula can be used for?

HyperFormula doesn't assume any existing user interface, making it a general-purpose library that can be used in various business applications. Here are some examples:

- Deterministic compute layer for AI & LLMs
- Calculated fields in CRM and ERP software
- Custom spreadsheet-like app
- Business logic builder
- Forms and form builder
Expand Down
87 changes: 87 additions & 0 deletions docs/.vuepress/components/HiringBanner.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
<template>
<div class="hf-hiring-banner">
<span class="hf-hiring-banner__emoji" aria-hidden="true">🚀</span>
<span class="hf-hiring-banner__text">
Join HyperFormula team as a Senior Software Engineer
</span>
<a
class="hf-hiring-banner__cta"
href="https://handsontable.traffit.com/public/an/4b09e1395bf8ea42ef86db4c4657992c2f48673d"
target="_blank"
rel="noopener"
>
See the role and apply
</a>
</div>
</template>

<script>
export default {
name: 'HiringBanner',
};
</script>

<style scoped>
:global(:root) {
--hf-banner-height: 32px;
}

.hf-hiring-banner {
position: fixed;
bottom: 0;
left: 0;
right: 0;
z-index: 2000;
display: flex;
align-items: center;
gap: 0.75rem;
min-height: var(--hf-banner-height);
padding: 0.65rem 1rem;
background: linear-gradient(90deg, #0b63ce, #0f8fef);
color: #fff;
font-weight: 600;
font-size: 0.95rem;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
}

.hf-hiring-banner__emoji {
font-size: 1.1rem;
}

.hf-hiring-banner__text {
flex: 1;
}

.hf-hiring-banner__cta {
color: #0b63ce;
background: #fff;
padding: 0.4rem 0.9rem;
border-radius: 999px;
font-weight: 700;
text-decoration: none;
transition: transform 0.1s ease, box-shadow 0.15s ease, background 0.15s ease;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.12);
}

.hf-hiring-banner__cta:hover,
.hf-hiring-banner__cta:focus {
background: #e8f3ff;
transform: translateY(-1px);
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.16);
}

:global(.theme-container) {
padding-bottom: calc(var(--hf-banner-height) + 1rem);
}

@media (max-width: 640px) {
.hf-hiring-banner {
flex-direction: column;
align-items: stretch;
}

.hf-hiring-banner__cta {
text-align: center;
}
}
</style>
Loading
Loading