From 0af118dfb6114398fdbd7258948fb8db3f770cbe Mon Sep 17 00:00:00 2001 From: Kuba Sekowski Date: Mon, 31 Aug 2026 16:30:18 +0200 Subject: [PATCH 1/6] HF-359: Restructure the repository as a monorepo Implements the migration steps recorded in dev-docs/MONOREPO.md. - src/, test/ and the whole engine toolchain (tsconfig, jest, karma, webpack, babel, .config/, typedoc) move into hyperformula/, which becomes the published package and carries its own README, CHANGELOG, LICENSE and .nvmrc. - The root package.json becomes a private workspace root listing hyperformula and hyperformula-ui, with fan-out scripts. Linting is the deliberate exception: it still runs once from the root over the whole repository, so nothing between packages falls through the gap. - docs/ becomes its own package, installed separately with `npm run docs:install`, so the VuePress 1.x tree never reaches an engine install. It takes ownership of its deployment: wrangler.jsonc and worker/ move under it. - hyperformula-ui/ is created as a placeholder; the package is imported from the formula-builder repository separately. - Every .nvmrc says 22, and each package keeps its own CHANGELOG.md in the existing Keep a Changelog form. Three things the move forced, none of them cosmetic: The built-in-functions generator moved to docs/script/. It uses @vuepress/shared-utils for slugs, and that package requires markdown-it-emoji and an older lru-cache major without declaring either, relying on vuepress to hoist them. Outside a full VuePress tree it cannot load at all, so the generator has to live where that tree is. Three paths in the portal were written from the old repository root and broke when VuePress started building from docs/ as its own package: the code-snippet plugin fell back to process.cwd() and looked for docs/docs/examples/, graph.vue imported the engine bundle from ../../../dist, and dest wrote the site to docs/docs/. All three are now anchored explicitly. The engine dev-docs pages stay in the single root dev-docs/ rather than being split into a package-level copy as the plan sketched. Two directories fragment the single source of truth and force every page to know which scope it was written from. Verified end to end: npm ci, lint (0 errors, 54011 warnings - the exact pre-move baseline), jest (502 suites, 6232 passed), tsc --noEmit, bundle-all including the publish-package check, the function-docs generator, typedoc, and the full portal build (217 pages) plus the Cloudflare asset step. Co-Authored-By: Claude Opus 5 --- .claude/settings.json | 30 +- .../skills/hyperformula-code-review/SKILL.md | 2 +- .claude/skills/hyperformula-dev/SKILL.md | 36 +- .../skills/hyperformula-function-dev/SKILL.md | 10 +- .../skills/hyperformula-unit-testing/SKILL.md | 8 +- .claude/skills/i18n-translations/SKILL.md | 4 +- .claude/skills/pr-creation/SKILL.md | 2 +- .../skills/test-writing-discipline/SKILL.md | 2 +- .claude/skills/writing-docs-pages/SKILL.md | 4 +- .eslintignore | 46 +- .eslintrc.js | 4 +- .github/workflows/build-docs.yml | 2 +- .github/workflows/lint.yml | 4 +- .github/workflows/performance.yml | 10 +- .github/workflows/publish.yml | 2 +- .github/workflows/test.yml | 8 +- .gitignore | 26 +- .worktreeinclude | 4 +- AGENTS.md | 2 +- CHANGELOG.md | 704 +- README.md | 125 +- dev-docs/AGENT-TOOLING.md | 4 +- dev-docs/ARCHITECTURE.md | 64 +- dev-docs/BUILD.md | 21 +- dev-docs/CODE-STYLE.md | 12 +- dev-docs/DEFINITION-OF-DONE.md | 8 +- dev-docs/DEPENDENCY-GRAPH.md | 4 +- dev-docs/DOC-STANDARDS.md | 4 +- dev-docs/FUNCTION-CATALOGUE.md | 2 +- dev-docs/I18N.md | 6 +- dev-docs/INTERPRETER.md | 14 +- dev-docs/MONOREPO.md | 84 +- dev-docs/PARSER.md | 2 +- dev-docs/README.md | 14 +- dev-docs/STRUCTURE.md | 113 +- dev-docs/TESTING.md | 14 +- dev-docs/WORKTREES.md | 10 +- docs/.nvmrc | 1 + docs/.vuepress/build.config.js | 4 +- docs/.vuepress/components/graph.vue | 2 +- docs/.vuepress/config.js | 11 +- docs/README.md | 4 +- docs/package-lock.json | 21354 ++++++++++ docs/package.json | 43 + .../script}/formatFunctionSyntax.ts | 2 +- .../script}/generate-builtin-functions-doc.ts | 8 +- .../script}/renderBuiltinFunctionsTable.ts | 2 +- {worker => docs/worker}/index.js | 0 wrangler.jsonc => docs/wrangler.jsonc | 2 +- hyperformula-ui/README.md | 7 + .../.config}/babel/add-import-extension.js | 0 .../.config}/karma/base.js | 0 .../.config}/karma/debug.js | 0 .../.config}/source-license-header.js | 0 .../.config}/webpack/base.js | 0 .../.config}/webpack/development.js | 0 .../.config}/webpack/languages.js | 0 .../.config}/webpack/production.js | 0 .npmignore => hyperformula/.npmignore | 0 hyperformula/.nvmrc | 1 + .typedoc.md.ts => hyperformula/.typedoc.md.ts | 6 +- .typedoc.ts => hyperformula/.typedoc.ts | 0 hyperformula/AGENTS.md | 12 + hyperformula/CHANGELOG.md | 700 + {src => hyperformula}/CLAUDE.md | 0 hyperformula/LICENSE.txt | 34 + hyperformula/README.md | 116 + .../babel.config.js | 0 ht.config.js => hyperformula/ht.config.js | 0 jasmine.json => hyperformula/jasmine.json | 0 jest.config.js => hyperformula/jest.config.js | 0 karma.conf.js => hyperformula/karma.conf.js | 0 .../karma.starter.ts | 0 hyperformula/package.json | 612 + {src => hyperformula/src}/AGENTS.md | 8 +- .../src}/AbsoluteCellRange.ts | 0 .../src}/ArgumentSanitization.ts | 0 {src => hyperformula/src}/ArraySize.ts | 0 {src => hyperformula/src}/ArrayValue.ts | 0 .../src}/BuildEngineFactory.ts | 0 .../src}/CLAUDE.md | 0 {src => hyperformula/src}/Cell.ts | 0 .../src}/CellContentParser.ts | 0 {src => hyperformula/src}/CellDependency.ts | 0 {src => hyperformula/src}/CellValue.ts | 0 .../src}/ClipboardOperations.ts | 0 {src => hyperformula/src}/Config.ts | 0 {src => hyperformula/src}/ConfigParams.ts | 0 {src => hyperformula/src}/ContentChanges.ts | 0 {src => hyperformula/src}/CrudOperations.ts | 0 {src => hyperformula/src}/DateTimeDefault.ts | 0 {src => hyperformula/src}/DateTimeHelper.ts | 0 hyperformula/src/DependencyGraph/AGENTS.md | 6 + .../AddressMapping/AddressMapping.ts | 0 .../AddressMapping/AddressMappingStrategy.ts | 0 .../ChooseAddressMappingPolicy.ts | 0 .../AddressMapping/DenseStrategy.ts | 0 .../AddressMapping/SparseStrategy.ts | 0 .../src}/DependencyGraph/ArrayMapping.ts | 0 .../src/DependencyGraph}/CLAUDE.md | 0 .../src}/DependencyGraph/CellVertex.ts | 0 .../src}/DependencyGraph/DependencyGraph.ts | 0 .../src}/DependencyGraph/EmptyCellVertex.ts | 0 .../src}/DependencyGraph/FormulaVertex.ts | 0 .../src}/DependencyGraph/Graph.ts | 0 .../DependencyGraph/ParsingErrorVertex.ts | 0 .../src}/DependencyGraph/ProcessableValue.ts | 0 .../src}/DependencyGraph/RangeMapping.ts | 0 .../src}/DependencyGraph/RangeVertex.ts | 0 .../src}/DependencyGraph/SheetMapping.ts | 0 .../SheetReferenceRegistrar.ts | 0 .../src}/DependencyGraph/TopSort.ts | 0 .../src}/DependencyGraph/ValueCellVertex.ts | 0 .../src}/DependencyGraph/Vertex.ts | 0 .../collectAddressesDependentToRange.ts | 0 .../src}/DependencyGraph/index.ts | 0 {src => hyperformula/src}/Destroy.ts | 0 {src => hyperformula/src}/Emitter.ts | 0 {src => hyperformula/src}/Evaluator.ts | 0 {src => hyperformula/src}/Exporter.ts | 0 {src => hyperformula/src}/GraphBuilder.ts | 0 {src => hyperformula/src}/HyperFormula.ts | 0 .../src}/LazilyTransformingAstService.ts | 0 .../src}/Lookup/AdvancedFind.ts | 0 .../src}/Lookup/ColumnBinarySearch.ts | 0 .../src}/Lookup/ColumnIndex.ts | 0 .../src}/Lookup/RowSearchStrategy.ts | 0 .../src}/Lookup/SearchStrategy.ts | 0 {src => hyperformula/src}/Maybe.ts | 0 {src => hyperformula/src}/NamedExpressions.ts | 0 .../src}/NumberLiteralHelper.ts | 0 {src => hyperformula/src}/Operations.ts | 0 {src => hyperformula/src}/Serialization.ts | 0 {src => hyperformula/src}/Sheet.ts | 0 {src => hyperformula/src}/SimpleRangeValue.ts | 0 {src => hyperformula/src}/Span.ts | 0 {src => hyperformula/src}/StringHelper.ts | 0 {src => hyperformula/src}/UndoRedo.ts | 0 .../src}/absolutizeDependencies.ts | 0 .../AddColumnsTransformer.ts | 0 .../AddRowsTransformer.ts | 0 .../CleanOutOfScopeDependenciesTransformer.ts | 0 .../CombinedTransformer.ts | 0 .../MoveCellsTransformer.ts | 0 .../RemoveColumnsTransformer.ts | 0 .../RemoveRowsTransformer.ts | 0 .../RenameSheetTransformer.ts | 0 .../dependencyTransformers/Transformer.ts | 0 {src => hyperformula/src}/error-message.ts | 0 {src => hyperformula/src}/errors.ts | 0 {src => hyperformula/src}/format/format.ts | 0 {src => hyperformula/src}/format/parser.ts | 0 {src => hyperformula/src}/generatorUtils.ts | 0 .../src}/helpers/licenseKeyHelper.ts | 0 .../src}/helpers/licenseKeyValidator.ts | 0 {src => hyperformula/src}/i18n/AGENTS.md | 4 +- .../src/i18n}/CLAUDE.md | 0 .../src}/i18n/TranslationPackage.ts | 0 {src => hyperformula/src}/i18n/index.ts | 0 .../src}/i18n/languages/csCZ.ts | 0 .../src}/i18n/languages/daDK.ts | 0 .../src}/i18n/languages/deDE.ts | 0 .../src}/i18n/languages/enGB.ts | 0 .../src}/i18n/languages/enUS.ts | 0 .../src}/i18n/languages/esES.ts | 0 .../src}/i18n/languages/fiFI.ts | 0 .../src}/i18n/languages/frFR.ts | 0 .../src}/i18n/languages/huHU.ts | 0 .../src}/i18n/languages/idID.ts | 0 .../src}/i18n/languages/index.ts | 0 .../src}/i18n/languages/itIT.ts | 0 .../src}/i18n/languages/nbNO.ts | 0 .../src}/i18n/languages/nlNL.ts | 0 .../src}/i18n/languages/plPL.ts | 0 .../src}/i18n/languages/ptPT.ts | 0 .../src}/i18n/languages/ruRU.ts | 0 .../src}/i18n/languages/svSE.ts | 0 .../src}/i18n/languages/trTR.ts | 0 {src => hyperformula/src}/index.ts | 0 hyperformula/src/interpreter/AGENTS.md | 6 + .../src}/interpreter/ArithmeticHelper.ts | 0 .../src/interpreter}/CLAUDE.md | 0 .../src}/interpreter/Criterion.ts | 0 .../interpreter/CriterionFunctionCompute.ts | 0 .../src}/interpreter/FunctionRegistry.ts | 0 .../src}/interpreter/Interpreter.ts | 0 .../src}/interpreter/InterpreterState.ts | 0 .../src}/interpreter/InterpreterValue.ts | 0 .../src}/interpreter/binarySearch.ts | 0 .../interpreter/functionMetadata/AGENTS.md | 4 +- .../interpreter/functionMetadata}/CLAUDE.md | 0 .../functionMetadata/FunctionDescription.ts | 0 .../buildFunctionDescriptions.ts | 0 .../categories/array-manipulation.ts | 0 .../functionMetadata/categories/database.ts | 0 .../categories/date-and-time.ts | 0 .../categories/engineering.ts | 0 .../functionMetadata/categories/financial.ts | 0 .../categories/information.ts | 0 .../functionMetadata/categories/logical.ts | 0 .../categories/lookup-and-reference.ts | 0 .../categories/math-and-trigonometry.ts | 0 .../categories/matrix-functions.ts | 0 .../functionMetadata/categories/operator.ts | 0 .../categories/statistical.ts | 0 .../functionMetadata/categories/text.ts | 0 .../interpreter/functionMetadata/index.ts | 0 .../protectedFunctionMetadata.ts | 0 .../src}/interpreter/index.ts | 0 .../plugin/3rdparty/bessel/bessel.ts | 0 .../plugin/3rdparty/jstat/jstat.ts | 0 .../src}/interpreter/plugin/AGENTS.md | 4 +- .../src}/interpreter/plugin/AbsPlugin.ts | 0 .../src}/interpreter/plugin/AddressPlugin.ts | 0 .../src}/interpreter/plugin/ArrayPlugin.ts | 0 .../src}/interpreter/plugin/BitShiftPlugin.ts | 0 .../plugin/BitwiseLogicOperationsPlugin.ts | 0 .../src}/interpreter/plugin/BooleanPlugin.ts | 0 .../src/interpreter/plugin}/CLAUDE.md | 0 .../src}/interpreter/plugin/CharPlugin.ts | 0 .../src}/interpreter/plugin/CodePlugin.ts | 0 .../src}/interpreter/plugin/ComplexPlugin.ts | 0 .../plugin/ConditionalAggregationPlugin.ts | 0 .../interpreter/plugin/CountBlankPlugin.ts | 0 .../interpreter/plugin/CountUniquePlugin.ts | 0 .../src}/interpreter/plugin/DatabasePlugin.ts | 0 .../src}/interpreter/plugin/DateTimePlugin.ts | 0 .../src}/interpreter/plugin/DegreesPlugin.ts | 0 .../src}/interpreter/plugin/DeltaPlugin.ts | 0 .../src}/interpreter/plugin/ExpPlugin.ts | 0 .../interpreter/plugin/FinancialPlugin.ts | 0 .../interpreter/plugin/FormulaTextPlugin.ts | 0 .../src}/interpreter/plugin/FunctionPlugin.ts | 0 .../interpreter/plugin/HyperlinkPlugin.ts | 0 .../interpreter/plugin/InformationPlugin.ts | 0 .../src}/interpreter/plugin/IsEvenPlugin.ts | 0 .../src}/interpreter/plugin/IsOddPlugin.ts | 0 .../interpreter/plugin/LogarithmPlugin.ts | 0 .../src}/interpreter/plugin/LookupPlugin.ts | 0 .../interpreter/plugin/MathConstantsPlugin.ts | 0 .../src}/interpreter/plugin/MathPlugin.ts | 0 .../src}/interpreter/plugin/MatrixPlugin.ts | 0 .../src}/interpreter/plugin/MedianPlugin.ts | 0 .../src}/interpreter/plugin/ModuloPlugin.ts | 0 .../plugin/NumericAggregationPlugin.ts | 0 .../interpreter/plugin/PercentilePlugin.ts | 0 .../src}/interpreter/plugin/PowerPlugin.ts | 0 .../src}/interpreter/plugin/RadiansPlugin.ts | 0 .../plugin/RadixConversionPlugin.ts | 0 .../src}/interpreter/plugin/RandomPlugin.ts | 0 .../src}/interpreter/plugin/RomanPlugin.ts | 0 .../src}/interpreter/plugin/RoundingPlugin.ts | 0 .../src}/interpreter/plugin/SequencePlugin.ts | 0 .../interpreter/plugin/SimpleArithmertic.ts | 0 .../src}/interpreter/plugin/SortPlugin.ts | 0 .../src}/interpreter/plugin/SqrtPlugin.ts | 0 .../plugin/StatisticalAggregationPlugin.ts | 0 .../interpreter/plugin/StatisticalPlugin.ts | 0 .../src}/interpreter/plugin/SumprodPlugin.ts | 0 .../src}/interpreter/plugin/TextPlugin.ts | 0 .../interpreter/plugin/TrigonometryPlugin.ts | 0 .../src}/interpreter/plugin/UniquePlugin.ts | 0 .../src}/interpreter/plugin/VersionPlugin.ts | 0 .../src}/interpreter/plugin/index.ts | 0 hyperformula/src/parser/AGENTS.md | 6 + {src => hyperformula/src}/parser/Address.ts | 0 {src => hyperformula/src}/parser/Ast.ts | 0 {test => hyperformula/src/parser}/CLAUDE.md | 0 {src => hyperformula/src}/parser/Cache.ts | 0 .../src}/parser/CellAddress.ts | 0 .../src}/parser/CellReferenceMatcher.ts | 0 .../src}/parser/ColumnAddress.ts | 0 .../src}/parser/FormulaParser.ts | 0 .../src}/parser/LexerConfig.ts | 0 .../src}/parser/NamedExpressionMatcher.ts | 0 .../src}/parser/ParserConfig.ts | 0 .../src}/parser/ParserWithCaching.ts | 0 .../src}/parser/RelativeDependency.ts | 0 .../src}/parser/RowAddress.ts | 0 {src => hyperformula/src}/parser/Unparser.ts | 0 .../parser/addressRepresentationConverters.ts | 0 .../src}/parser/binaryOpTokenMap.ts | 0 .../src}/parser/collectDependencies.ts | 0 {src => hyperformula/src}/parser/index.ts | 0 .../src}/parser/parser-consts.ts | 0 .../src}/statistics/EmptyStatistics.ts | 0 .../src}/statistics/StatType.ts | 0 .../src}/statistics/Statistics.ts | 0 {src => hyperformula/src}/statistics/index.ts | 0 {test => hyperformula/test}/AGENTS.md | 4 +- hyperformula/test/CLAUDE.md | 1 + {test => hyperformula/test}/README.md | 0 .../test}/_setupFiles/babel.js | 0 .../test}/_setupFiles/bootstrap.ts | 0 .../test}/_setupFiles/globalSetup.ts | 0 .../test}/_setupFiles/jest/bootstrap.ts | 0 .../test}/_setupFiles/jest/toEqualError.ts | 0 .../test}/_setupFiles/jsdom.js | 0 .../test}/_setupFiles/matchers/index.ts | 0 .../_setupFiles/matchers/toContainEqual.ts | 0 .../_setupFiles/matchers/toEqualError.ts | 0 .../_setupFiles/matchers/toMatchObject.ts | 0 {test => hyperformula/test}/fetch-tests.sh | 0 {test => hyperformula/test}/smoke.spec.ts | 0 {test => hyperformula/test}/tsconfig.json | 0 tsconfig.json => hyperformula/tsconfig.json | 0 .../tsconfig.test.json | 0 .../webpack.config.js | 0 package-lock.json | 32106 +++++++--------- package.json | 632 +- script/check-file.js | 2 +- src/DependencyGraph/AGENTS.md | 6 - src/interpreter/AGENTS.md | 6 - src/parser/AGENTS.md | 6 - 314 files changed, 36298 insertions(+), 20835 deletions(-) create mode 100644 docs/.nvmrc create mode 100644 docs/package-lock.json create mode 100644 docs/package.json rename {script => docs/script}/formatFunctionSyntax.ts (96%) rename {script => docs/script}/generate-builtin-functions-doc.ts (92%) rename {script => docs/script}/renderBuiltinFunctionsTable.ts (99%) rename {worker => docs/worker}/index.js (100%) rename wrangler.jsonc => docs/wrangler.jsonc (97%) create mode 100644 hyperformula-ui/README.md rename {.config => hyperformula/.config}/babel/add-import-extension.js (100%) rename {.config => hyperformula/.config}/karma/base.js (100%) rename {.config => hyperformula/.config}/karma/debug.js (100%) rename {.config => hyperformula/.config}/source-license-header.js (100%) rename {.config => hyperformula/.config}/webpack/base.js (100%) rename {.config => hyperformula/.config}/webpack/development.js (100%) rename {.config => hyperformula/.config}/webpack/languages.js (100%) rename {.config => hyperformula/.config}/webpack/production.js (100%) rename .npmignore => hyperformula/.npmignore (100%) create mode 100644 hyperformula/.nvmrc rename .typedoc.md.ts => hyperformula/.typedoc.md.ts (59%) rename .typedoc.ts => hyperformula/.typedoc.ts (100%) create mode 100644 hyperformula/AGENTS.md create mode 100644 hyperformula/CHANGELOG.md rename {src => hyperformula}/CLAUDE.md (100%) create mode 100644 hyperformula/LICENSE.txt create mode 100644 hyperformula/README.md rename babel.config.js => hyperformula/babel.config.js (100%) rename ht.config.js => hyperformula/ht.config.js (100%) rename jasmine.json => hyperformula/jasmine.json (100%) rename jest.config.js => hyperformula/jest.config.js (100%) rename karma.conf.js => hyperformula/karma.conf.js (100%) rename karma.starter.ts => hyperformula/karma.starter.ts (100%) create mode 100644 hyperformula/package.json rename {src => hyperformula/src}/AGENTS.md (51%) rename {src => hyperformula/src}/AbsoluteCellRange.ts (100%) rename {src => hyperformula/src}/ArgumentSanitization.ts (100%) rename {src => hyperformula/src}/ArraySize.ts (100%) rename {src => hyperformula/src}/ArrayValue.ts (100%) rename {src => hyperformula/src}/BuildEngineFactory.ts (100%) rename {src/DependencyGraph => hyperformula/src}/CLAUDE.md (100%) rename {src => hyperformula/src}/Cell.ts (100%) rename {src => hyperformula/src}/CellContentParser.ts (100%) rename {src => hyperformula/src}/CellDependency.ts (100%) rename {src => hyperformula/src}/CellValue.ts (100%) rename {src => hyperformula/src}/ClipboardOperations.ts (100%) rename {src => hyperformula/src}/Config.ts (100%) rename {src => hyperformula/src}/ConfigParams.ts (100%) rename {src => hyperformula/src}/ContentChanges.ts (100%) rename {src => hyperformula/src}/CrudOperations.ts (100%) rename {src => hyperformula/src}/DateTimeDefault.ts (100%) rename {src => hyperformula/src}/DateTimeHelper.ts (100%) create mode 100644 hyperformula/src/DependencyGraph/AGENTS.md rename {src => hyperformula/src}/DependencyGraph/AddressMapping/AddressMapping.ts (100%) rename {src => hyperformula/src}/DependencyGraph/AddressMapping/AddressMappingStrategy.ts (100%) rename {src => hyperformula/src}/DependencyGraph/AddressMapping/ChooseAddressMappingPolicy.ts (100%) rename {src => hyperformula/src}/DependencyGraph/AddressMapping/DenseStrategy.ts (100%) rename {src => hyperformula/src}/DependencyGraph/AddressMapping/SparseStrategy.ts (100%) rename {src => hyperformula/src}/DependencyGraph/ArrayMapping.ts (100%) rename {src/i18n => hyperformula/src/DependencyGraph}/CLAUDE.md (100%) rename {src => hyperformula/src}/DependencyGraph/CellVertex.ts (100%) rename {src => hyperformula/src}/DependencyGraph/DependencyGraph.ts (100%) rename {src => hyperformula/src}/DependencyGraph/EmptyCellVertex.ts (100%) rename {src => hyperformula/src}/DependencyGraph/FormulaVertex.ts (100%) rename {src => hyperformula/src}/DependencyGraph/Graph.ts (100%) rename {src => hyperformula/src}/DependencyGraph/ParsingErrorVertex.ts (100%) rename {src => hyperformula/src}/DependencyGraph/ProcessableValue.ts (100%) rename {src => hyperformula/src}/DependencyGraph/RangeMapping.ts (100%) rename {src => hyperformula/src}/DependencyGraph/RangeVertex.ts (100%) rename {src => hyperformula/src}/DependencyGraph/SheetMapping.ts (100%) rename {src => hyperformula/src}/DependencyGraph/SheetReferenceRegistrar.ts (100%) rename {src => hyperformula/src}/DependencyGraph/TopSort.ts (100%) rename {src => hyperformula/src}/DependencyGraph/ValueCellVertex.ts (100%) rename {src => hyperformula/src}/DependencyGraph/Vertex.ts (100%) rename {src => hyperformula/src}/DependencyGraph/collectAddressesDependentToRange.ts (100%) rename {src => hyperformula/src}/DependencyGraph/index.ts (100%) rename {src => hyperformula/src}/Destroy.ts (100%) rename {src => hyperformula/src}/Emitter.ts (100%) rename {src => hyperformula/src}/Evaluator.ts (100%) rename {src => hyperformula/src}/Exporter.ts (100%) rename {src => hyperformula/src}/GraphBuilder.ts (100%) rename {src => hyperformula/src}/HyperFormula.ts (100%) rename {src => hyperformula/src}/LazilyTransformingAstService.ts (100%) rename {src => hyperformula/src}/Lookup/AdvancedFind.ts (100%) rename {src => hyperformula/src}/Lookup/ColumnBinarySearch.ts (100%) rename {src => hyperformula/src}/Lookup/ColumnIndex.ts (100%) rename {src => hyperformula/src}/Lookup/RowSearchStrategy.ts (100%) rename {src => hyperformula/src}/Lookup/SearchStrategy.ts (100%) rename {src => hyperformula/src}/Maybe.ts (100%) rename {src => hyperformula/src}/NamedExpressions.ts (100%) rename {src => hyperformula/src}/NumberLiteralHelper.ts (100%) rename {src => hyperformula/src}/Operations.ts (100%) rename {src => hyperformula/src}/Serialization.ts (100%) rename {src => hyperformula/src}/Sheet.ts (100%) rename {src => hyperformula/src}/SimpleRangeValue.ts (100%) rename {src => hyperformula/src}/Span.ts (100%) rename {src => hyperformula/src}/StringHelper.ts (100%) rename {src => hyperformula/src}/UndoRedo.ts (100%) rename {src => hyperformula/src}/absolutizeDependencies.ts (100%) rename {src => hyperformula/src}/dependencyTransformers/AddColumnsTransformer.ts (100%) rename {src => hyperformula/src}/dependencyTransformers/AddRowsTransformer.ts (100%) rename {src => hyperformula/src}/dependencyTransformers/CleanOutOfScopeDependenciesTransformer.ts (100%) rename {src => hyperformula/src}/dependencyTransformers/CombinedTransformer.ts (100%) rename {src => hyperformula/src}/dependencyTransformers/MoveCellsTransformer.ts (100%) rename {src => hyperformula/src}/dependencyTransformers/RemoveColumnsTransformer.ts (100%) rename {src => hyperformula/src}/dependencyTransformers/RemoveRowsTransformer.ts (100%) rename {src => hyperformula/src}/dependencyTransformers/RenameSheetTransformer.ts (100%) rename {src => hyperformula/src}/dependencyTransformers/Transformer.ts (100%) rename {src => hyperformula/src}/error-message.ts (100%) rename {src => hyperformula/src}/errors.ts (100%) rename {src => hyperformula/src}/format/format.ts (100%) rename {src => hyperformula/src}/format/parser.ts (100%) rename {src => hyperformula/src}/generatorUtils.ts (100%) rename {src => hyperformula/src}/helpers/licenseKeyHelper.ts (100%) rename {src => hyperformula/src}/helpers/licenseKeyValidator.ts (100%) rename {src => hyperformula/src}/i18n/AGENTS.md (68%) rename {src/interpreter => hyperformula/src/i18n}/CLAUDE.md (100%) rename {src => hyperformula/src}/i18n/TranslationPackage.ts (100%) rename {src => hyperformula/src}/i18n/index.ts (100%) rename {src => hyperformula/src}/i18n/languages/csCZ.ts (100%) rename {src => hyperformula/src}/i18n/languages/daDK.ts (100%) rename {src => hyperformula/src}/i18n/languages/deDE.ts (100%) rename {src => hyperformula/src}/i18n/languages/enGB.ts (100%) rename {src => hyperformula/src}/i18n/languages/enUS.ts (100%) rename {src => hyperformula/src}/i18n/languages/esES.ts (100%) rename {src => hyperformula/src}/i18n/languages/fiFI.ts (100%) rename {src => hyperformula/src}/i18n/languages/frFR.ts (100%) rename {src => hyperformula/src}/i18n/languages/huHU.ts (100%) rename {src => hyperformula/src}/i18n/languages/idID.ts (100%) rename {src => hyperformula/src}/i18n/languages/index.ts (100%) rename {src => hyperformula/src}/i18n/languages/itIT.ts (100%) rename {src => hyperformula/src}/i18n/languages/nbNO.ts (100%) rename {src => hyperformula/src}/i18n/languages/nlNL.ts (100%) rename {src => hyperformula/src}/i18n/languages/plPL.ts (100%) rename {src => hyperformula/src}/i18n/languages/ptPT.ts (100%) rename {src => hyperformula/src}/i18n/languages/ruRU.ts (100%) rename {src => hyperformula/src}/i18n/languages/svSE.ts (100%) rename {src => hyperformula/src}/i18n/languages/trTR.ts (100%) rename {src => hyperformula/src}/index.ts (100%) create mode 100644 hyperformula/src/interpreter/AGENTS.md rename {src => hyperformula/src}/interpreter/ArithmeticHelper.ts (100%) rename {src/interpreter/functionMetadata => hyperformula/src/interpreter}/CLAUDE.md (100%) rename {src => hyperformula/src}/interpreter/Criterion.ts (100%) rename {src => hyperformula/src}/interpreter/CriterionFunctionCompute.ts (100%) rename {src => hyperformula/src}/interpreter/FunctionRegistry.ts (100%) rename {src => hyperformula/src}/interpreter/Interpreter.ts (100%) rename {src => hyperformula/src}/interpreter/InterpreterState.ts (100%) rename {src => hyperformula/src}/interpreter/InterpreterValue.ts (100%) rename {src => hyperformula/src}/interpreter/binarySearch.ts (100%) rename {src => hyperformula/src}/interpreter/functionMetadata/AGENTS.md (66%) rename {src/interpreter/plugin => hyperformula/src/interpreter/functionMetadata}/CLAUDE.md (100%) rename {src => hyperformula/src}/interpreter/functionMetadata/FunctionDescription.ts (100%) rename {src => hyperformula/src}/interpreter/functionMetadata/buildFunctionDescriptions.ts (100%) rename {src => hyperformula/src}/interpreter/functionMetadata/categories/array-manipulation.ts (100%) rename {src => hyperformula/src}/interpreter/functionMetadata/categories/database.ts (100%) rename {src => hyperformula/src}/interpreter/functionMetadata/categories/date-and-time.ts (100%) rename {src => hyperformula/src}/interpreter/functionMetadata/categories/engineering.ts (100%) rename {src => hyperformula/src}/interpreter/functionMetadata/categories/financial.ts (100%) rename {src => hyperformula/src}/interpreter/functionMetadata/categories/information.ts (100%) rename {src => hyperformula/src}/interpreter/functionMetadata/categories/logical.ts (100%) rename {src => hyperformula/src}/interpreter/functionMetadata/categories/lookup-and-reference.ts (100%) rename {src => hyperformula/src}/interpreter/functionMetadata/categories/math-and-trigonometry.ts (100%) rename {src => hyperformula/src}/interpreter/functionMetadata/categories/matrix-functions.ts (100%) rename {src => hyperformula/src}/interpreter/functionMetadata/categories/operator.ts (100%) rename {src => hyperformula/src}/interpreter/functionMetadata/categories/statistical.ts (100%) rename {src => hyperformula/src}/interpreter/functionMetadata/categories/text.ts (100%) rename {src => hyperformula/src}/interpreter/functionMetadata/index.ts (100%) rename {src => hyperformula/src}/interpreter/functionMetadata/protectedFunctionMetadata.ts (100%) rename {src => hyperformula/src}/interpreter/index.ts (100%) rename {src => hyperformula/src}/interpreter/plugin/3rdparty/bessel/bessel.ts (100%) rename {src => hyperformula/src}/interpreter/plugin/3rdparty/jstat/jstat.ts (100%) rename {src => hyperformula/src}/interpreter/plugin/AGENTS.md (66%) rename {src => hyperformula/src}/interpreter/plugin/AbsPlugin.ts (100%) rename {src => hyperformula/src}/interpreter/plugin/AddressPlugin.ts (100%) rename {src => hyperformula/src}/interpreter/plugin/ArrayPlugin.ts (100%) rename {src => hyperformula/src}/interpreter/plugin/BitShiftPlugin.ts (100%) rename {src => hyperformula/src}/interpreter/plugin/BitwiseLogicOperationsPlugin.ts (100%) rename {src => hyperformula/src}/interpreter/plugin/BooleanPlugin.ts (100%) rename {src/parser => hyperformula/src/interpreter/plugin}/CLAUDE.md (100%) rename {src => hyperformula/src}/interpreter/plugin/CharPlugin.ts (100%) rename {src => hyperformula/src}/interpreter/plugin/CodePlugin.ts (100%) rename {src => hyperformula/src}/interpreter/plugin/ComplexPlugin.ts (100%) rename {src => hyperformula/src}/interpreter/plugin/ConditionalAggregationPlugin.ts (100%) rename {src => hyperformula/src}/interpreter/plugin/CountBlankPlugin.ts (100%) rename {src => hyperformula/src}/interpreter/plugin/CountUniquePlugin.ts (100%) rename {src => hyperformula/src}/interpreter/plugin/DatabasePlugin.ts (100%) rename {src => hyperformula/src}/interpreter/plugin/DateTimePlugin.ts (100%) rename {src => hyperformula/src}/interpreter/plugin/DegreesPlugin.ts (100%) rename {src => hyperformula/src}/interpreter/plugin/DeltaPlugin.ts (100%) rename {src => hyperformula/src}/interpreter/plugin/ExpPlugin.ts (100%) rename {src => hyperformula/src}/interpreter/plugin/FinancialPlugin.ts (100%) rename {src => hyperformula/src}/interpreter/plugin/FormulaTextPlugin.ts (100%) rename {src => hyperformula/src}/interpreter/plugin/FunctionPlugin.ts (100%) rename {src => hyperformula/src}/interpreter/plugin/HyperlinkPlugin.ts (100%) rename {src => hyperformula/src}/interpreter/plugin/InformationPlugin.ts (100%) rename {src => hyperformula/src}/interpreter/plugin/IsEvenPlugin.ts (100%) rename {src => hyperformula/src}/interpreter/plugin/IsOddPlugin.ts (100%) rename {src => hyperformula/src}/interpreter/plugin/LogarithmPlugin.ts (100%) rename {src => hyperformula/src}/interpreter/plugin/LookupPlugin.ts (100%) rename {src => hyperformula/src}/interpreter/plugin/MathConstantsPlugin.ts (100%) rename {src => hyperformula/src}/interpreter/plugin/MathPlugin.ts (100%) rename {src => hyperformula/src}/interpreter/plugin/MatrixPlugin.ts (100%) rename {src => hyperformula/src}/interpreter/plugin/MedianPlugin.ts (100%) rename {src => hyperformula/src}/interpreter/plugin/ModuloPlugin.ts (100%) rename {src => hyperformula/src}/interpreter/plugin/NumericAggregationPlugin.ts (100%) rename {src => hyperformula/src}/interpreter/plugin/PercentilePlugin.ts (100%) rename {src => hyperformula/src}/interpreter/plugin/PowerPlugin.ts (100%) rename {src => hyperformula/src}/interpreter/plugin/RadiansPlugin.ts (100%) rename {src => hyperformula/src}/interpreter/plugin/RadixConversionPlugin.ts (100%) rename {src => hyperformula/src}/interpreter/plugin/RandomPlugin.ts (100%) rename {src => hyperformula/src}/interpreter/plugin/RomanPlugin.ts (100%) rename {src => hyperformula/src}/interpreter/plugin/RoundingPlugin.ts (100%) rename {src => hyperformula/src}/interpreter/plugin/SequencePlugin.ts (100%) rename {src => hyperformula/src}/interpreter/plugin/SimpleArithmertic.ts (100%) rename {src => hyperformula/src}/interpreter/plugin/SortPlugin.ts (100%) rename {src => hyperformula/src}/interpreter/plugin/SqrtPlugin.ts (100%) rename {src => hyperformula/src}/interpreter/plugin/StatisticalAggregationPlugin.ts (100%) rename {src => hyperformula/src}/interpreter/plugin/StatisticalPlugin.ts (100%) rename {src => hyperformula/src}/interpreter/plugin/SumprodPlugin.ts (100%) rename {src => hyperformula/src}/interpreter/plugin/TextPlugin.ts (100%) rename {src => hyperformula/src}/interpreter/plugin/TrigonometryPlugin.ts (100%) rename {src => hyperformula/src}/interpreter/plugin/UniquePlugin.ts (100%) rename {src => hyperformula/src}/interpreter/plugin/VersionPlugin.ts (100%) rename {src => hyperformula/src}/interpreter/plugin/index.ts (100%) create mode 100644 hyperformula/src/parser/AGENTS.md rename {src => hyperformula/src}/parser/Address.ts (100%) rename {src => hyperformula/src}/parser/Ast.ts (100%) rename {test => hyperformula/src/parser}/CLAUDE.md (100%) rename {src => hyperformula/src}/parser/Cache.ts (100%) rename {src => hyperformula/src}/parser/CellAddress.ts (100%) rename {src => hyperformula/src}/parser/CellReferenceMatcher.ts (100%) rename {src => hyperformula/src}/parser/ColumnAddress.ts (100%) rename {src => hyperformula/src}/parser/FormulaParser.ts (100%) rename {src => hyperformula/src}/parser/LexerConfig.ts (100%) rename {src => hyperformula/src}/parser/NamedExpressionMatcher.ts (100%) rename {src => hyperformula/src}/parser/ParserConfig.ts (100%) rename {src => hyperformula/src}/parser/ParserWithCaching.ts (100%) rename {src => hyperformula/src}/parser/RelativeDependency.ts (100%) rename {src => hyperformula/src}/parser/RowAddress.ts (100%) rename {src => hyperformula/src}/parser/Unparser.ts (100%) rename {src => hyperformula/src}/parser/addressRepresentationConverters.ts (100%) rename {src => hyperformula/src}/parser/binaryOpTokenMap.ts (100%) rename {src => hyperformula/src}/parser/collectDependencies.ts (100%) rename {src => hyperformula/src}/parser/index.ts (100%) rename {src => hyperformula/src}/parser/parser-consts.ts (100%) rename {src => hyperformula/src}/statistics/EmptyStatistics.ts (100%) rename {src => hyperformula/src}/statistics/StatType.ts (100%) rename {src => hyperformula/src}/statistics/Statistics.ts (100%) rename {src => hyperformula/src}/statistics/index.ts (100%) rename {test => hyperformula/test}/AGENTS.md (70%) create mode 120000 hyperformula/test/CLAUDE.md rename {test => hyperformula/test}/README.md (100%) rename {test => hyperformula/test}/_setupFiles/babel.js (100%) rename {test => hyperformula/test}/_setupFiles/bootstrap.ts (100%) rename {test => hyperformula/test}/_setupFiles/globalSetup.ts (100%) rename {test => hyperformula/test}/_setupFiles/jest/bootstrap.ts (100%) rename {test => hyperformula/test}/_setupFiles/jest/toEqualError.ts (100%) rename {test => hyperformula/test}/_setupFiles/jsdom.js (100%) rename {test => hyperformula/test}/_setupFiles/matchers/index.ts (100%) rename {test => hyperformula/test}/_setupFiles/matchers/toContainEqual.ts (100%) rename {test => hyperformula/test}/_setupFiles/matchers/toEqualError.ts (100%) rename {test => hyperformula/test}/_setupFiles/matchers/toMatchObject.ts (100%) rename {test => hyperformula/test}/fetch-tests.sh (100%) rename {test => hyperformula/test}/smoke.spec.ts (100%) rename {test => hyperformula/test}/tsconfig.json (100%) rename tsconfig.json => hyperformula/tsconfig.json (100%) rename tsconfig.test.json => hyperformula/tsconfig.test.json (100%) rename webpack.config.js => hyperformula/webpack.config.js (100%) delete mode 100644 src/DependencyGraph/AGENTS.md delete mode 100644 src/interpreter/AGENTS.md delete mode 100644 src/parser/AGENTS.md diff --git a/.claude/settings.json b/.claude/settings.json index 53a19a46f5..18ccf56583 100644 --- a/.claude/settings.json +++ b/.claude/settings.json @@ -4,29 +4,23 @@ ], "permissions": { "deny": [ - "Read(./lib/**)", - "Read(./es/**)", - "Read(./commonjs/**)", - "Read(./dist/**)", - "Read(./languages/**)", - "Read(./typings/**)", + "Read(./hyperformula/lib/**)", + "Read(./hyperformula/es/**)", + "Read(./hyperformula/commonjs/**)", + "Read(./hyperformula/dist/**)", + "Read(./hyperformula/languages/**)", + "Read(./hyperformula/typings/**)", + "Read(./hyperformula/coverage/**)", + "Read(./hyperformula/test-jest/**)", + "Read(./hyperformula/test-jasmine/**)", + "Read(./hyperformula/typedoc/**)", + "Read(./hyperformula/storage/**)", "Read(./docs/api/**)", "Read(./docs/functions/**)", "Read(./docs/guide/built-in-functions.md)", "Read(./docs/.vuepress/dist/**)", "Read(./docs/.vuepress/api-sidebar.json)", - "Read(./docs/.vuepress/api-sidebar-relative.json)", - "Read(./typedoc/**)", - "Read(./doc/**)", - "Read(./coverage/**)", - "Read(./test-jest/**)", - "Read(./test-jasmine/**)", - "Read(./storage/**)" - ] - }, - "worktree": { - "symlinkDirectories": [ - "node_modules" + "Read(./docs/.vuepress/api-sidebar-relative.json)" ] }, "hooks": { diff --git a/.claude/skills/hyperformula-code-review/SKILL.md b/.claude/skills/hyperformula-code-review/SKILL.md index acffff47d1..ca4de891f8 100644 --- a/.claude/skills/hyperformula-code-review/SKILL.md +++ b/.claude/skills/hyperformula-code-review/SKILL.md @@ -37,7 +37,7 @@ Allocation in a per-cell or per-vertex loop; work that could be hoisted out of t ## 5. Public API -`src/HyperFormula.ts` and its exported types are the contract. A signature, return-type, or behaviour change is breaking and needs a migration-guide section and an explicit note. JSDoc here is published output — review it as documentation. +`hyperformula/src/HyperFormula.ts` and its exported types are the contract. A signature, return-type, or behaviour change is breaking and needs a migration-guide section and an explicit note. JSDoc here is published output — review it as documentation. ## 6. Process diff --git a/.claude/skills/hyperformula-dev/SKILL.md b/.claude/skills/hyperformula-dev/SKILL.md index 61df2081c0..9f35da5526 100644 --- a/.claude/skills/hyperformula-dev/SKILL.md +++ b/.claude/skills/hyperformula-dev/SKILL.md @@ -1,12 +1,12 @@ --- name: hyperformula-dev -paths: src/** +paths: hyperformula/src/** description: > - Use for ANY work touching the HyperFormula engine in `src/`: fixing bugs, adding features, + Use for ANY work touching the HyperFormula engine in `hyperformula/src/`: fixing bugs, adding features, changing the public API, working on the parser, the interpreter, the dependency graph, CRUD operations, configuration options, named expressions, or number and date formats. Also use for how-to questions about engine internals (how recalculation works, why a formula - returns an error, where a value is coerced). Triggers on file paths under `src/`, or when the + returns an error, where a value is coerced). Triggers on file paths under `hyperformula/src/`, or when the user describes a symptom in a calculation without naming a file. This is the primary entry point for engine development — when in doubt, load it. --- @@ -17,7 +17,7 @@ Always: | File | Why | |---|---| -| [`ARCHITECTURE.md`](../../../dev-docs/ARCHITECTURE.md) | The pipeline, the core modules, and the invariants that hold everywhere in `src/` | +| [`ARCHITECTURE.md`](../../../dev-docs/ARCHITECTURE.md) | The pipeline, the core modules, and the invariants that hold everywhere in `hyperformula/src/` | | [`CODE-STYLE.md`](../../../dev-docs/CODE-STYLE.md) | Style, and which paths are hot enough that complexity matters | | [`DEFINITION-OF-DONE.md`](../../../dev-docs/DEFINITION-OF-DONE.md) | What the change must contain before review | @@ -25,11 +25,11 @@ Then the page for the stage you are changing: | File | For | |---|---| -| [`PARSER.md`](../../../dev-docs/PARSER.md) | `src/parser/` — formula text to AST, and back | -| [`INTERPRETER.md`](../../../dev-docs/INTERPRETER.md) | `src/interpreter/` — AST to value, and built-in functions | -| [`DEPENDENCY-GRAPH.md`](../../../dev-docs/DEPENDENCY-GRAPH.md) | `src/DependencyGraph/` — dependency tracking and recalculation order | -| [`FUNCTION-CATALOGUE.md`](../../../dev-docs/FUNCTION-CATALOGUE.md) | `src/interpreter/functionMetadata/` — function descriptions | -| [`I18N.md`](../../../dev-docs/I18N.md) | `src/i18n/` — function-name translations | +| [`PARSER.md`](../../../dev-docs/PARSER.md) | `hyperformula/src/parser/` — formula text to AST, and back | +| [`INTERPRETER.md`](../../../dev-docs/INTERPRETER.md) | `hyperformula/src/interpreter/` — AST to value, and built-in functions | +| [`DEPENDENCY-GRAPH.md`](../../../dev-docs/DEPENDENCY-GRAPH.md) | `hyperformula/src/DependencyGraph/` — dependency tracking and recalculation order | +| [`FUNCTION-CATALOGUE.md`](../../../dev-docs/FUNCTION-CATALOGUE.md) | `hyperformula/src/interpreter/functionMetadata/` — function descriptions | +| [`I18N.md`](../../../dev-docs/I18N.md) | `hyperformula/src/i18n/` — function-name translations | | [`TESTING.md`](../../../dev-docs/TESTING.md) | Writing the test the change needs | ## 2. Locate the stage before changing anything @@ -38,14 +38,14 @@ The engine is a pipeline: `CellContentParser` → `parser/` → `GraphBuilder` | Symptom | Stage | |---|---| -| Does not parse, or parses wrongly | `src/parser/` | -| `getCellFormula` returns something the user never typed | `src/parser/Unparser.ts` | -| A function returns the wrong value or error | `src/interpreter/plugin/` — skill `hyperformula-function-dev` | -| Value right, but stale after an edit | `src/DependencyGraph/`, `src/Evaluator.ts` | -| Wrong after adding or removing rows or columns | `src/dependencyTransformers/`, `LazilyTransformingAstService.ts` | -| Wrong in one language only | `src/i18n/languages/` — skill `i18n-translations` | -| Coercion or comparison is wrong | `src/interpreter/ArithmeticHelper.ts` | -| The public API disagrees with its docs | `src/HyperFormula.ts` | +| Does not parse, or parses wrongly | `hyperformula/src/parser/` | +| `getCellFormula` returns something the user never typed | `hyperformula/src/parser/Unparser.ts` | +| A function returns the wrong value or error | `hyperformula/src/interpreter/plugin/` — skill `hyperformula-function-dev` | +| Value right, but stale after an edit | `hyperformula/src/DependencyGraph/`, `hyperformula/src/Evaluator.ts` | +| Wrong after adding or removing rows or columns | `hyperformula/src/dependencyTransformers/`, `LazilyTransformingAstService.ts` | +| Wrong in one language only | `hyperformula/src/i18n/languages/` — skill `i18n-translations` | +| Coercion or comparison is wrong | `hyperformula/src/interpreter/ArithmeticHelper.ts` | +| The public API disagrees with its docs | `hyperformula/src/HyperFormula.ts` | A bug that looks like an interpreter problem is often a parser or graph problem. Confirm which before editing. Use the `typescript-lsp` plugin to find a definition or its callers; grep is for text, not symbols. @@ -53,7 +53,7 @@ A bug that looks like an interpreter problem is often a parser or graph problem. Write the failing test before the fix and watch it fail — skill `test-writing-discipline`. For a calculation bug the smallest reproduction is a two-line `buildFromArray` plus one `getCellValue`. -If `test/hyperformula-tests/` is absent, `npm run test:jest` runs only the smoke tests and reports a clean pass over almost nothing. Run `npm run test:setup-private` first, and after every branch switch. +If `hyperformula/test/hyperformula-tests/` is absent, `npm run test:jest` runs only the smoke tests and reports a clean pass over almost nothing. Run `npm run test:setup-private` first, and after every branch switch. ## 4. Change, then run the fast loop diff --git a/.claude/skills/hyperformula-function-dev/SKILL.md b/.claude/skills/hyperformula-function-dev/SKILL.md index e5e50d48bc..5db30aac44 100644 --- a/.claude/skills/hyperformula-function-dev/SKILL.md +++ b/.claude/skills/hyperformula-function-dev/SKILL.md @@ -1,6 +1,6 @@ --- name: hyperformula-function-dev -paths: src/interpreter/** +paths: hyperformula/src/interpreter/** description: Use when adding a new built-in spreadsheet function to HyperFormula, changing an existing one's signature, arguments, return type, or error behaviour, or when a function returns the wrong value or the wrong error. Covers the FunctionPlugin contract, runFunction and argument metadata, the function metadata catalogue, translations, and the full end-to-end checklist. --- @@ -18,10 +18,10 @@ description: Use when adding a new built-in spreadsheet function to HyperFormula A function is not done until all five agree. Each omission fails differently, and three of them fail silently. -1. **Implementation** — the plugin class in `src/interpreter/plugin/`, plus its `implementedFunctions` entry keyed by the canonical English id. -2. **Catalogue entry** — `src/interpreter/functionMetadata/categories/.ts`. Parameter **count** must match `implementedFunctions`, or the authored names and descriptions are discarded at run time with only a console warning. A missing entry fails the docs build. -3. **Translations** — every file in `src/i18n/languages/`. -4. **Tests** — in `test/`. +1. **Implementation** — the plugin class in `hyperformula/src/interpreter/plugin/`, plus its `implementedFunctions` entry keyed by the canonical English id. +2. **Catalogue entry** — `hyperformula/src/interpreter/functionMetadata/categories/.ts`. Parameter **count** must match `implementedFunctions`, or the authored names and descriptions are discarded at run time with only a console warning. A missing entry fails the docs build. +3. **Translations** — every file in `hyperformula/src/i18n/languages/`. +4. **Tests** — in `hyperformula/test/`. 5. **Changelog** — skill `changelog-creation`. ## 3. Declare the two things nothing cross-checks diff --git a/.claude/skills/hyperformula-unit-testing/SKILL.md b/.claude/skills/hyperformula-unit-testing/SKILL.md index d6596ae850..c571d49d12 100644 --- a/.claude/skills/hyperformula-unit-testing/SKILL.md +++ b/.claude/skills/hyperformula-unit-testing/SKILL.md @@ -1,7 +1,7 @@ --- name: hyperformula-unit-testing -paths: test/** -description: Use when writing or modifying tests for HyperFormula, or when a change to `src/` needs test coverage. Covers the two suites, fetching the private suite, how to build an engine in a test, and what a function or CRUD change must cover. +paths: hyperformula/test/** +description: Use when writing or modifying tests for HyperFormula, or when a change to `hyperformula/src/` needs test coverage. Covers the two suites, fetching the private suite, how to build an engine in a test, and what a function or CRUD change must cover. --- ## 1. Read the relevant files from `dev-docs/` @@ -11,7 +11,7 @@ description: Use when writing or modifying tests for HyperFormula, or when a cha | [`TESTING.md`](../../../dev-docs/TESTING.md) | The two suites, how to write a case, and what each kind of change must cover | | [`WORKTREES.md`](../../../dev-docs/WORKTREES.md) | Only when working in a linked worktree, where the private suite is absent entirely | -And [`test/README.md`](../../../test/README.md) for how the private suite is fetched and the environment variables it honours. +And [`hyperformula/test/README.md`](../../../hyperformula/test/README.md) for how the private suite is fetched and the environment variables it honours. ## 2. Attach the private suite before trusting anything @@ -19,7 +19,7 @@ And [`test/README.md`](../../../test/README.md) for how the private suite is fet npm run test:setup-private ``` -Run it after every branch switch. Without `test/hyperformula-tests/` the Jest run covers only the smoke tests and reports a clean pass over almost nothing — the most common false signal in this repository. `test:performance` and `test:compatibility` fail on a missing path rather than an assertion; read the error before concluding the code is broken. +Run it after every branch switch. Without `hyperformula/test/hyperformula-tests/` the Jest run covers only the smoke tests and reports a clean pass over almost nothing — the most common false signal in this repository. `test:performance` and `test:compatibility` fail on a missing path rather than an assertion; read the error before concluding the code is broken. ## 3. Write the case from the requirement diff --git a/.claude/skills/i18n-translations/SKILL.md b/.claude/skills/i18n-translations/SKILL.md index 08bd5b49e4..a464ceb99e 100644 --- a/.claude/skills/i18n-translations/SKILL.md +++ b/.claude/skills/i18n-translations/SKILL.md @@ -1,6 +1,6 @@ --- name: i18n-translations -paths: src/i18n/** +paths: hyperformula/src/i18n/** description: Use when adding a built-in function that needs translated names, adding a language pack, or fixing a function name that is wrong in one language. Covers the translation sources, the rules, and what breaks when a key is missing. --- @@ -32,4 +32,4 @@ npm run lint ## Adding a whole language pack -The file, its export in `src/i18n/languages/index.ts`, a key set identical to the other packs, a changelog entry, and `npm run bundle:languages` for the standalone UMD build. +The file, its export in `hyperformula/src/i18n/languages/index.ts`, a key set identical to the other packs, a changelog entry, and `npm run bundle:languages` for the standalone UMD build. diff --git a/.claude/skills/pr-creation/SKILL.md b/.claude/skills/pr-creation/SKILL.md index 2837d631fe..017a3a86d9 100644 --- a/.claude/skills/pr-creation/SKILL.md +++ b/.claude/skills/pr-creation/SKILL.md @@ -23,7 +23,7 @@ npm run lint npm run test:jest ``` -A green Jest run without `test/hyperformula-tests/` covers only the smoke tests. Confirm the suite is attached before calling it green. Do not open a pull request on a red run and describe it as ready. +A green Jest run without `hyperformula/test/hyperformula-tests/` covers only the smoke tests. Confirm the suite is attached before calling it green. Do not open a pull request on a red run and describe it as ready. ## 4. Push and open the pull request diff --git a/.claude/skills/test-writing-discipline/SKILL.md b/.claude/skills/test-writing-discipline/SKILL.md index 35bf9d1126..0a1506c7f6 100644 --- a/.claude/skills/test-writing-discipline/SKILL.md +++ b/.claude/skills/test-writing-discipline/SKILL.md @@ -23,7 +23,7 @@ When a test is red the default assumption is that the code is wrong. Changing th ## 5. Run it again and read the output -Never claim a test passes because the reasoning is sound. And before treating green as coverage, confirm `test/hyperformula-tests/` is present — `npm run test:setup-private`. +Never claim a test passes because the reasoning is sound. And before treating green as coverage, confirm `hyperformula/test/hyperformula-tests/` is present — `npm run test:setup-private`. ## If you cannot make it pass honestly diff --git a/.claude/skills/writing-docs-pages/SKILL.md b/.claude/skills/writing-docs-pages/SKILL.md index 97654218d6..bea08a959d 100644 --- a/.claude/skills/writing-docs-pages/SKILL.md +++ b/.claude/skills/writing-docs-pages/SKILL.md @@ -19,8 +19,8 @@ And [`docs/README.md`](../../../docs/README.md), for what the portal contains an | To change | Edit | Then run | |---|---|---| -| What the functions page says about a function | its catalogue entry in `src/interpreter/functionMetadata/categories/` | `npm run docs:generate-function-docs` | -| The API reference | the JSDoc in `src/` | `npm run typedoc:build-api` | +| What the functions page says about a function | its catalogue entry in `hyperformula/src/interpreter/functionMetadata/categories/` | `npm run docs:generate-function-docs` | +| The API reference | the JSDoc in `hyperformula/src/` | `npm run typedoc:build-api` | | A guide | the file in `docs/guide/` | `npm run docs:dev` | `docs/guide/built-in-functions.md` and `docs/api/` are git-ignored build output. Editing them is always wrong, and the edit disappears on the next build. diff --git a/.eslintignore b/.eslintignore index 03546876e2..eb2e684e29 100644 --- a/.eslintignore +++ b/.eslintignore @@ -5,24 +5,44 @@ node_modules docs/examples/ # 3rd party -src/interpreter/plugin/3rdparty +hyperformula/src/interpreter/plugin/3rdparty # Configurations *.config.js -karma.* +hyperformula/*.config.js +hyperformula/.config/ +hyperformula/karma.* doc -test/_setupFiles/*.js +hyperformula/test/_setupFiles/*.js + +# Scripts, not linted +script + +# The source language packs, deliberately, and only for now. +# +# The old ignore list carried a bare `languages` entry, meant for the build +# output. An unanchored pattern matches a directory of that name at ANY depth, +# so it also excluded hyperformula/src/i18n/languages/ - and the `sort-keys` +# override that targets those files has therefore never run. Anchoring the +# build-output entry below exposed 881 pre-existing violations in them. +# +# Sorting 19 translation files is a change of its own, not a side effect of +# moving directories around. Delete this entry in that change. +hyperformula/src/i18n/languages # Auto-generated directories -commonjs -coverage -dist +hyperformula/commonjs +hyperformula/coverage +hyperformula/dist +hyperformula/es +hyperformula/languages +hyperformula/lib +hyperformula/test-jasmine +hyperformula/test-jest +hyperformula/typings +docs/.vuepress/dist doc -es -languages -lib -script -test-jasmine -test-jest typedoc -typings + +# The docs generator, like the rest of script/ +docs/script diff --git a/.eslintrc.js b/.eslintrc.js index a5e9976e13..6841494966 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -15,7 +15,7 @@ module.exports = { }, parserOptions: { tsconfigRootDir: __dirname, - project: './tsconfig.json', + project: './hyperformula/tsconfig.json', createDefaultProgram: true, }, extends: [ @@ -134,7 +134,7 @@ module.exports = { { files: ['**/src/**/*.ts'], rules: { - 'license-header/header': [ 'error', './.config/source-license-header.js' ], + 'license-header/header': [ 'error', './hyperformula/.config/source-license-header.js' ], } }, { diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index 60c43dfc32..5ef21e7919 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -34,4 +34,4 @@ jobs: run: npm ci - name: Build docs - run: npm run docs:build + run: npm run docs:install && npm run docs:build diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 936ef53fa2..b745b1a0b4 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -36,10 +36,10 @@ jobs: with: ssh-key: ${{ secrets.DEPLOY_TOKEN }} repository: handsontable/hyperformula-tests - path: test/hyperformula-tests + path: hyperformula/test/hyperformula-tests - name: Fetch hyperformula-tests and sync branches - run: cd test && ./fetch-tests.sh + run: cd hyperformula/test && ./fetch-tests.sh - name: Install dependencies run: npm ci diff --git a/.github/workflows/performance.yml b/.github/workflows/performance.yml index 9ef3c8190c..f53491ade3 100644 --- a/.github/workflows/performance.yml +++ b/.github/workflows/performance.yml @@ -34,16 +34,16 @@ jobs: with: ssh-key: ${{ secrets.DEPLOY_TOKEN }} repository: handsontable/hyperformula-tests - path: test/hyperformula-tests + path: hyperformula/test/hyperformula-tests - name: Fetch hyperformula-tests and sync branches - run: cd test && ./fetch-tests.sh + run: cd hyperformula/test && ./fetch-tests.sh - name: (base) Install dependencies run: npm ci - name: (base) Run performance tests - run: npm run benchmark:write-to-file base.json + run: npm run benchmark:write-to-file --workspace=hyperformula base.json - name: (head) Checkout main repository uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # https://github.com/actions/checkout/releases/tag/v2.3.4 @@ -55,11 +55,11 @@ jobs: - name: (head) Run performance tests run: | - npm run benchmark:write-to-file head.json + npm run benchmark:write-to-file --workspace=hyperformula head.json - name: Compare the results run: | - npm run benchmark:compare-benchmarks base.json head.json performance-report.md + npm run benchmark:compare-benchmarks --workspace=hyperformula base.json head.json performance-report.md - name: Publish a comment - header uses: marocchino/sticky-pull-request-comment@6804b5ad49d19c10c9ae7cf5057352f7ff333f31 # https://github.com/marocchino/sticky-pull-request-comment/tree/v1.6.0 diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index c87e1f36d1..8eebea9a1a 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -28,7 +28,7 @@ jobs: run: npm ci - name: Build docs - run: npm run docs:build + run: npm run docs:install && npm run docs:build - name: Deploy to GH pages uses: peaceiris/actions-gh-pages@ba0b7df03e25ff29c924be8149041119e9421ea6 # https://github.com/peaceiris/actions-gh-pages/releases/tag/v3.5.6 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 9486ae9250..264d67847b 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -36,10 +36,10 @@ jobs: with: ssh-key: ${{ secrets.DEPLOY_TOKEN }} repository: handsontable/hyperformula-tests - path: test/hyperformula-tests + path: hyperformula/test/hyperformula-tests - name: Fetch hyperformula-tests and sync branches - run: cd test && ./fetch-tests.sh + run: cd hyperformula/test && ./fetch-tests.sh - name: Install dependencies run: npm ci @@ -74,10 +74,10 @@ jobs: with: ssh-key: ${{ secrets.DEPLOY_TOKEN }} repository: handsontable/hyperformula-tests - path: test/hyperformula-tests + path: hyperformula/test/hyperformula-tests - name: Fetch hyperformula-tests and sync branches - run: cd test && ./fetch-tests.sh + run: cd hyperformula/test && ./fetch-tests.sh - name: Install dependencies run: npm ci diff --git a/.gitignore b/.gitignore index 886d7289b9..809a15f95c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,29 +1,29 @@ .idea/ .vscode -/commonjs/ -/coverage/ -/dist/ -/doc/ +/hyperformula/commonjs/ +/hyperformula/coverage/ +/hyperformula/dist/ +/hyperformula/doc/ /docs/api/ /docs/functions/ /docs/.vuepress/dist/ /docs/.vuepress/api-sidebar-relative.json /docs/.vuepress/api-sidebar.json -/typedoc/ -/es/ -/languages/ -/lib/ -/test-jasmine/ -/test-jest/ +/hyperformula/typedoc/ +/hyperformula/es/ +/hyperformula/languages/ +/hyperformula/lib/ +/hyperformula/test-jasmine/ +/hyperformula/test-jest/ node_modules/ -/typings/ -/storage/ +/hyperformula/typings/ +/hyperformula/storage/ *.iml dev*.html .DS_Store -/test/hyperformula-tests/ +/hyperformula/test/hyperformula-tests/ # Generated at docs:build from built-in-functions.tmpl.md (HF-249 single-source); do not commit. docs/guide/built-in-functions.md diff --git a/.worktreeinclude b/.worktreeinclude index c2c6c2f70d..cc74ccea0e 100644 --- a/.worktreeinclude +++ b/.worktreeinclude @@ -19,7 +19,7 @@ # builds do not survive it. Run `npm ci`, or symlink it # with `worktree.symlinkDirectories`. # -# test/hyperformula-tests/ +# hyperformula/test/hyperformula-tests/ # The private suite is BRANCH-MATCHED to this repository # (test/fetch-tests.sh checks out the branch of the same # name). A copy carries the source branch's tests and @@ -27,7 +27,7 @@ # suite at all. Run `npm run test:setup-private` in the # worktree instead. # -# lib/ dist/ es/ commonjs/ typings/ languages/ +# hyperformula/{lib,dist,es,commonjs,typings,languages}/ # Build outputs. A stale copy makes `npm run test:browser` # and the bundle checks pass or fail against the other # branch's build. Run `npm run bundle-all`. diff --git a/AGENTS.md b/AGENTS.md index e6affa7325..2720a341b6 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -12,7 +12,7 @@ Read [`dev-docs/README.md`](dev-docs/README.md) first. It indexes the rest. | You are working on | Read | |---|---| -| Anything in `src/` | [`dev-docs/ARCHITECTURE.md`](dev-docs/ARCHITECTURE.md) | +| Anything in `hyperformula/src/` | [`dev-docs/ARCHITECTURE.md`](dev-docs/ARCHITECTURE.md) | | Formula parsing | [`dev-docs/PARSER.md`](dev-docs/PARSER.md) | | Formula evaluation, or a built-in function | [`dev-docs/INTERPRETER.md`](dev-docs/INTERPRETER.md) | | Function descriptions in the API and the docs | [`dev-docs/FUNCTION-CATALOGUE.md`](dev-docs/FUNCTION-CATALOGUE.md) | diff --git a/CHANGELOG.md b/CHANGELOG.md index 7e535ebc20..aff252c039 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,700 +1,12 @@ -# HyperFormula changelog +# Changelog -All notable changes to this project will be documented in this file. +Each package in this repository keeps its own changelog and releases on its own cadence. -The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to -[Semantic Versioning](https://semver.org/spec/v2.0.0.html). +| Package | Changelog | +|---|---| +| `hyperformula` | [`hyperformula/CHANGELOG.md`](hyperformula/CHANGELOG.md) | +| `hyperformula-ui` | not yet imported — see [`dev-docs/MONOREPO.md`](dev-docs/MONOREPO.md) | -## [Unreleased] +The documentation portal in `docs/` is not published and keeps no changelog. -### Fixed - -- Fixed the MAXPOOL and MEDIANPOOL functions throwing an uncaught `TypeError` instead of returning the `#VALUE!` error when the range dimensions are not a whole multiple of the window size and the stride. [#1718](https://github.com/handsontable/hyperformula/pull/1718) -- Fixed the `MOD` function returning a remainder with the sign of the dividend instead of the sign of the divisor, which made the results differ from Excel and Google Sheets for arguments with opposite signs (e.g. `=MOD(-3, 12)` now returns `9` instead of `-3`). [#1747](https://github.com/handsontable/hyperformula/issues/1747) - -## [3.4.0] - 2026-08-10 - -### Added - -- Added the `getAvailableFunctions()` and `getFunctionDetails()` instance methods for retrieving function metadata. [#1692](https://github.com/handsontable/hyperformula/pull/1692) -- Added new functions: VSTACK, HSTACK. [#1698](https://github.com/handsontable/hyperformula/pull/1698) -- Added a new function: `XIRR`. [#1701](https://github.com/handsontable/hyperformula/pull/1701) -- Added the UNIQUE function. [#1708](https://github.com/handsontable/hyperformula/pull/1708) -- Added the SORT function. [#1707](https://github.com/handsontable/hyperformula/pull/1707) -- Added an Indonesian (Bahasa Indonesia) language pack. [#1674](https://github.com/handsontable/hyperformula/pull/1674) -- Added a `stringifyCurrency` config option that lets you plug in a custom currency formatter for the `TEXT` function. [#1145](https://github.com/handsontable/hyperformula/issues/1145) - -### Fixed - -- Fixed the behavior of `MATCH`, `VLOOKUP`, `HLOOKUP`, and `XLOOKUP` functions when the search range contained empty cells. [#1697](https://github.com/handsontable/hyperformula/pull/1697) -- Fixed the `VLOOKUP`, `HLOOKUP`, and `XLOOKUP` functions to return `0` instead of an empty value when the matched cell in the result range is empty. [#1697](https://github.com/handsontable/hyperformula/pull/1697) -- Fixed the page freezing when entering a long string of digits containing a non-digit character near the end (e.g. `012...789a` or `012...789 123`) into a cell. [#1520](https://github.com/handsontable/hyperformula/issues/1520) - -## [3.3.0] - 2026-05-20 - -### Added - -- Added 12 database functions: DCOUNT, DSUM, DAVERAGE, DMAX, DMIN, DGET, DPRODUCT, DCOUNTA, DSTDEV, DSTDEVP, DVAR, DVARP. [#1652](https://github.com/handsontable/hyperformula/pull/1652) -- Added new functions: PERCENTILE, PERCENTILE.INC, PERCENTILE.EXC, QUARTILE, QUARTILE.INC, QUARTILE.EXC. [#1650](https://github.com/handsontable/hyperformula/pull/1650) -- Added `maxPendingLazyTransformations` configuration option to control memory usage by limiting accumulated transformations before cleanup. [#1629](https://github.com/handsontable/hyperformula/issues/1629) -- Added a new function: TEXTJOIN. [#1640](https://github.com/handsontable/hyperformula/pull/1640) -- Added a new function: SEQUENCE. [#1645](https://github.com/handsontable/hyperformula/pull/1645) - -### Fixed - -- Fixed a memory leak in `LazilyTransformingAstService` where the transformations array grew unboundedly, causing increasing memory usage over time. [#1629](https://github.com/handsontable/hyperformula/issues/1629) -- Fixed a memory leak in `UndoRedo` where `oldData` entries for evicted undo stack entries were never cleaned up, causing increasing memory usage over time. [#1629](https://github.com/handsontable/hyperformula/issues/1629) -- Fixed the IRR function returning `#NUM!` error when the initial investment significantly exceeds the sum of returns. [#1628](https://github.com/handsontable/hyperformula/issues/1628) -- Fixed the ADDRESS function ignoring `defaultValue` when arguments are syntactically empty (e.g., `=ADDRESS(2,3,,FALSE())`). [#1632](https://github.com/handsontable/hyperformula/issues/1632) - -## [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) -- Fixed an issue where overwriting a non-computed cell caused the `Value of the formula cell is not computed` error. [#1194](https://github.com/handsontable/hyperformula/issues/1194) - -## [3.1.0] - 2025-10-14 - -### Changed - -- Renamed the `arraySizeMethod` parameter in the `FunctionMetadata` interface to `sizeOfResultArrayMethod`. The `arraySizeMethod` is deprecated and will be removed in one of the next major releases. [#1401](https://github.com/handsontable/hyperformula/issues/1401) -- Renamed the `arrayFunction` parameter in the `FunctionMetadata` interface to `enableArrayArithmeticForArguments`. The `arrayFunction` is deprecated and will be removed in one of the next major releases. [#1401](https://github.com/handsontable/hyperformula/issues/1401) - -### Fixed - -- Fixed an issue where the `OFFSET` function was ignoring the sheet reference in the provided address. [#1477](https://github.com/handsontable/hyperformula/issues/1477) - -## [3.0.1] - 2025-08-11 - -### Fixed - -- Fixed `Edge does not exist` error when a named expression is used twice in the same formula. [#1102](https://github.com/handsontable/hyperformula/issues/1102) -- Fixed typos in the built-in functions guide. [#1517](https://github.com/handsontable/hyperformula/issues/1517) -- Fixed an issue where named expressions added on engine initialization were not updated on changes. [#1501](https://github.com/handsontable/hyperformula/issues/1501) - -## [3.0.0] - 2025-01-14 - -### Added - -- Added a new function: XLOOKUP. [#1458](https://github.com/handsontable/hyperformula/issues/1458) - -### Changed - -- **Breaking change**: Changed ES module build to use `mjs` files and `exports` property in `package.json` to make importing language files possible in Node environment. [#1344](https://github.com/handsontable/hyperformula/issues/1344) -- **Breaking change**: Changed the default value of the `precisionRounding` configuration option to `10`. [#1300](https://github.com/handsontable/hyperformula/issues/1300) -- Make methods `simpleCellAddressToString` and `simpleCellRangeToString` more logical and easier to use. [#1151](https://github.com/handsontable/hyperformula/issues/1151) - -### Removed - -- **Breaking change**: Removed the `binarySearchThreshold` configuration option. [#1439](https://github.com/handsontable/hyperformula/issues/1439) - -## [2.7.1] - 2024-07-18 - -### Fixed - -- Fixed an issue where adding or removing columns with `DenseStrategy` for address mapping resulted in the `Cannot read properties of undefined (reading 'splice')` error. [#1406](https://github.com/handsontable/hyperformula/issues/1406) - -## [2.7.0] - 2024-04-10 - -### Added - -- Added method `getNamedExpressionsFromFormula` to extract named expressions from formulas. [#1365](https://github.com/handsontable/hyperformula/issues/1365) -- Added `context` config option for passing data to custom functions. [#1396](https://github.com/handsontable/hyperformula/issues/1396) - -## [2.6.2] - 2024-02-15 - -### Changed - -- Removed `unorm` dependency. [#1370](https://github.com/handsontable/hyperformula/issues/1370) - -## [2.6.1] - 2023-12-27 - -### Fixed - -- Fixed an issue where operating on ranges of incompatible sizes resulted in a runtime exception. [#1267](https://github.com/handsontable/hyperformula/issues/1267) -- Fixed an issue where the `simpleCellAddressFromString()` method was crashing when called with a non-ASCII character in an unquoted sheet name. [#1312](https://github.com/handsontable/hyperformula/issues/1312) -- Fixed an issue where adding a row to a very large spreadsheet resulted in the `Maximum call stack size exceeded` error. [#1332](https://github.com/handsontable/hyperformula/issues/1332) -- Fixed an issue where using a column-range reference to an empty sheet as a function argument resulted in the `Incorrect array size` error. [#1147](https://github.com/handsontable/hyperformula/issues/1147) -- Fixed an issue where the SUBSTITUTE function wasn't working correctly with regex special characters. [#1289](https://github.com/handsontable/hyperformula/issues/1289) -- Fixed a typo in the JSDoc comment of the `HyperFormula` class. [#1323](https://github.com/handsontable/hyperformula/issues/1323) - -## [2.6.0] - 2023-09-19 - -### Added - -- Exported the `EmptyValue` symbol as a public API. This allows custom functions to handle empty cell - values. [#1232](https://github.com/handsontable/hyperformula/issues/1265) - -### Changed - -- Improved the efficiency of the default date/time parsing - methods. [#876](https://github.com/handsontable/hyperformula/issues/876) -- Improved the efficiency of the operations on the dependency - graph. [#876](https://github.com/handsontable/hyperformula/issues/876) - -### Fixed - -- Fixed a bug where neighboring exported changes of an array formula were - missing. [#1291](https://github.com/handsontable/hyperformula/issues/1291) -- Fixed a typo in the source code of the `MatrixPlugin`. [#1306](https://github.com/handsontable/hyperformula/issues/1306) - -## [2.5.0] - 2023-05-29 - -### Added - -- Added a new function: ADDRESS. [#1221](https://github.com/handsontable/hyperformula/issues/1221) -- Added a new function: HYPERLINK. [#1215](https://github.com/handsontable/hyperformula/issues/1215) -- Added a new function: IFS. [#1157](https://github.com/handsontable/hyperformula/issues/1157) - -### Changed - -- Optimized the `updateConfig()` method to rebuild HyperFormula only when the new configuration is different from the - old one. [#1251](https://github.com/handsontable/hyperformula/issues/1251) - -### Fixed - -- Fixed the SEARCH function to be case-insensitive regardless of HyperFormula's - configuration. [#1225](https://github.com/handsontable/hyperformula/issues/1225) - -## [2.4.0] - 2023-04-24 - -### Added - -- Exported the `CellError` class as a public API. [#1232](https://github.com/handsontable/hyperformula/issues/1232) -- Exported the `SimpleRangeValue` class as a public - API. [#1178](https://github.com/handsontable/hyperformula/issues/1178) - -### Fixed - -- Fixed an `EmptyCellVertex` data integrity issue between the `AddressMapping` and `DependencyGraph` - objects. [#1188](https://github.com/handsontable/hyperformula/issues/1188) -- Fixed a build issue with M1- and M2-chip MacBooks. [#1166](https://github.com/handsontable/hyperformula/issues/1166) -- Fixed an issue where the order of items returned by `removeColumns()` depended on the address mapping - policy. [#1205](https://github.com/handsontable/hyperformula/issues/1205) - -## [2.3.1] - 2023-03-03 - -### Fixed - -- Fixed an issue where expression names were not allowed to start with a cell - reference. [#1058](https://github.com/handsontable/hyperformula/issues/1058) -- Fixed an issue where expression names were allowed to start with R1C1-notation references. For better compatibility - with other spreadsheet software, strings such as `R4C5`, `RC1000`, `R1C` or `RC` can't be used in expression names - anymore. [#1058](https://github.com/handsontable/hyperformula/issues/1058) -- Fixed an issue where using reversed ranges with absolute addressing could cause the `Incorrect array size` - error. [#1106](https://github.com/handsontable/hyperformula/issues/1106) -- Fixed an issue where removing a sheet (`removeSheet()`) without clearing it - (`clearSheet()`) could cause an error. [#1121](https://github.com/handsontable/hyperformula/issues/1121) - -## [2.3.0] - 2022-12-22 - -### Added - -- Exported the `ArraySize` class as a public API. [#843](https://github.com/handsontable/hyperformula/issues/843) -- Renamed an internal interface from `ArgumentTypes` to `FunctionArgumentType`, and exported it as a public - API. [#1108](https://github.com/handsontable/hyperformula/pull/1108) -- Exported `ImplementedFunctions` and `FunctionMetadata` as public - APIs. [#1108](https://github.com/handsontable/hyperformula/pull/1108) - -## [2.2.0] - 2022-11-17 - -### Added - -- Added an American English (`enUS`) language pack. It's a convenience alias: it contains the same translations as the - existing British English (`enGB`) language pack. [#1025](https://github.com/handsontable/hyperformula/issues/1025) - -### Fixed - -- Fixed functions VLOOKUP and HLOOKUP to handle duplicates in the way specified by - the [OpenDocument](https://docs.oasis-open.org/office/OpenDocument/v1.3/os/part4-formula/OpenDocument-v1.3-os-part4-formula.html#HLOOKUP) - standard. [#1072](https://github.com/handsontable/hyperformula/issues/1072) -- Fixed the MATCH function to handle descending ranges in the way specified by - the [OpenDocument](https://docs.oasis-open.org/office/OpenDocument/v1.3/os/part4-formula/OpenDocument-v1.3-os-part4-formula.html#MATCH) - standard. [#1063](https://github.com/handsontable/hyperformula/issues/1063) - -## [2.1.0] - 2022-09-08 - -### Added - -- Added two new functions: MAXIFS and MINIFS. [#1049](https://github.com/handsontable/hyperformula/issues/1049) - -### Changed - -- Changed the rounding strategy of the default time-parsing function to be independent of the `timeFormats` - configuration option. Now, time values are always rounded to the nearest millisecond (0.001 s). - [#953](https://github.com/handsontable/hyperformula/issues/953) - -### Fixed - -- Fixed a rounding issue that caused the TEXT function to incorrectly convert dates and times to - strings. [#1043](https://github.com/handsontable/hyperformula/issues/1043) -- Fixed an issue where functions SUMIF, SUMIFS, COUNTIF, COUNTIFS, and AVERAGEIF incorrectly handled complex numeric - values. [#951](https://github.com/handsontable/hyperformula/issues/951) - -### Removed - -- Removed all polyfills from the CommonJS build and the ES modules build. In the UMD build, kept only the polyfills - required by the [supported browsers](https://hyperformula.handsontable.com/docs/guide/supported-browsers.html). - [#1011](https://github.com/handsontable/hyperformula/issues/1011) - -## [2.0.1] - 2022-06-14 - -### Changed - -- Changed the following npm scripts (used internally): `docs`, `docs:api`, - `docs:dev`, `docs:build`, `coverage`, `typings:check`. [#977](https://github.com/handsontable/hyperformula/issues/977) - -### Fixed - -- Fixed an issue where it was impossible to add a custom function with no - `parameters`. [#968](https://github.com/handsontable/hyperformula/issues/968) - -## [2.0.0] - 2022-04-14 - -For more information on this release, see: - -- [Release notes](https://hyperformula.handsontable.com/docs/guide/release-notes.html) -- [Blog post](https://handsontable.com/blog/articles/2022/04/whats-new-in-hyperformula-2.0.0) -- [Migration guide](https://hyperformula.handsontable.com/docs/guide/migration-from-1.x-to-2.0.html) - -### Added - -- Added support for reversed ranges. [#834](https://github.com/handsontable/hyperformula/issues/834) -- Added a new configuration option, `ignoreWhiteSpace`, which allows for parsing formulas that contain whitespace - characters of any kind. [#898](https://github.com/handsontable/hyperformula/issues/898) - -### Changed - -- **Breaking change**: Removed the `gpu.js` dependency and its use, to speed up the installation - time. [#812](https://github.com/handsontable/hyperformula/issues/812) -- **Breaking change**: Removed the deprecated `gpujs` and `gpuMode` - configuration options. [#812](https://github.com/handsontable/hyperformula/issues/812) - -### Fixed - -- Fixed an issue where the RATE function didn't converge for some - inputs. [#905](https://github.com/handsontable/hyperformula/issues/905) - -## [1.3.1] - 2022-01-11 - -### Fixed - -- Fixed an issue where warnings about deprecated configuration options were getting - duplicated. [#882](https://github.com/handsontable/hyperformula/issues/882) - -## [1.3.0] - 2021-10-20 - -### Added - -- Added a new static property: `defaultConfig`. [#822](https://github.com/handsontable/hyperformula/issues/822) -- The `getFillRangeData()` method can now use one sheet for its source and another sheet for its - target. [#836](https://github.com/handsontable/hyperformula/issues/836) - -### Fixed - -- Fixed the handling of Unicode characters and non-letter characters in the - `PROPER` function. [#811](https://github.com/handsontable/hyperformula/issues/811) -- Fixed unnecessary warnings caused by deprecated configuration - options. [#830](https://github.com/handsontable/hyperformula/issues/830) -- Fixed the `SUMPRODUCT` function. [#810](https://github.com/handsontable/hyperformula/issues/810) - -## [1.2.0] - 2021-09-23 - -### Changed - -- Removed `gpu.js` from optional dependencies and marked config options `gpujs` - and `gpuMode` as deprecated. - -## [1.1.0] - 2021-08-12 - -### Added - -- Added support for the array arithmetic mode in the `calculateFormula()` - method. [#782](https://github.com/handsontable/hyperformula/issues/782) -- Added a new `CellType` returned by `getCellType`: `CellType.ARRAYFORMULA`. It's assigned to the top-left corner of an - array, and is recognized by the - `isCellPartOfArray()` and `doesCellHaveFormula()` - methods. [#781](https://github.com/handsontable/hyperformula/issues/781) - -### Changed - -- Deprecated the `binarySearchThreshold` configuration option, as every search of sorted data always uses binary - search. [#791](https://github.com/handsontable/hyperformula/issues/791) - -### Fixed - -- Fixed an issue with searching sorted data. [#787](https://github.com/handsontable/hyperformula/issues/787) -- Fixed the `destroy` method to properly destroy HyperFormula - instances. [#788](https://github.com/handsontable/hyperformula/issues/788) - -## [1.0.0] - 2021-07-15 - -### Added - -- Added support for array arithmetic. [#628](https://github.com/handsontable/hyperformula/issues/628) -- Added performance improvements for array handling. [#629](https://github.com/handsontable/hyperformula/issues/629) -- Added ARRAYFORMULA function. [#630](https://github.com/handsontable/hyperformula/issues/630) -- Added FILTER function. [#668](https://github.com/handsontable/hyperformula/issues/668) -- Added ARRAY_CONSTRAIN function. [#661](https://github.com/handsontable/hyperformula/issues/661) -- Added casting to scalars from non-range arrays. [#663](https://github.com/handsontable/hyperformula/issues/663) -- Added support for range interpolation. [#665](https://github.com/handsontable/hyperformula/issues/665) -- Added parsing of arrays in formulas (together with respective config options for separators). - [#671](https://github.com/handsontable/hyperformula/issues/671) -- Added support for vectorization of scalar functions. [#673](https://github.com/handsontable/hyperformula/issues/673) -- Added support for time in JS `Date()` objects on the - input. [#648](https://github.com/handsontable/hyperformula/issues/648) -- Added validation of API argument types for simple - types. [#654](https://github.com/handsontable/hyperformula/issues/654) -- Added named expression handling to engine factories. [#680](https://github.com/handsontable/hyperformula/issues/680) -- Added `getAllNamedExpressionsSerialized` method. [#680](https://github.com/handsontable/hyperformula/issues/680) -- Added parsing of arrays in formulas (together with respective config options for separators). - [#671](https://github.com/handsontable/hyperformula/issues/671) -- Added utility function for filling ranges with source from other - range. [#678](https://github.com/handsontable/hyperformula/issues/678) -- Added pretty print for detailedCellError. [#712](https://github.com/handsontable/hyperformula/issues/712) -- Added `simpleCellRangeFromString` and `simpleCellRangeToString` - helpers. [#720](https://github.com/handsontable/hyperformula/issues/720) -- Added `CellError` to exports. [#736](https://github.com/handsontable/hyperformula/issues/736) -- Added mapping policies to the exports: `AlwaysDense`, `AlwaysSparse`, - `DenseSparseChooseBasedOnThreshold`. [#747](https://github.com/handsontable/hyperformula/issues/747) -- Added `#SPILL!` error type. [#708](https://github.com/handsontable/hyperformula/issues/708) -- Added large tests for CRUD interactions. [#755](https://github.com/handsontable/hyperformula/issues/755) -- Added support for array arithmetic in plugins. [#766](https://github.com/handsontable/hyperformula/issues/766) -- Added a flag to `getFillRangeData` to support different types of - offsetting. [#767](https://github.com/handsontable/hyperformula/issues/767) - -### Changed - -- **Breaking change**: Changed API of many sheet-related methods to take sheetId instead of sheetName as an - argument. [#645](https://github.com/handsontable/hyperformula/issues/645) -- **Breaking change**: Removed support for matrix formulas (`{=FORMULA}`) - notation. Engine now supports formulas returning array of values (instead of only scalars). - [#652](https://github.com/handsontable/hyperformula/issues/652) -- **Breaking change**: Removed numeric matrix detection along with matrixDetection and matrixDetectionThreshold config - options. [#669](https://github.com/handsontable/hyperformula/issues/669) -- **Breaking change**: Changed API of the following methods to take - `SimpleCellRange` type argument: `copy`, `cut`, `getCellDependents`, - `getCellPrecedents`, `getFillRangeData`, `getRangeFormulas`, - `getRangeSerialized`, `getRangeValues`, `isItPossibleToMoveCells`, - `isItPossibleToSetCellContents`, `moveCells`. [#687](https://github.com/handsontable/hyperformula/issues/687) -- **Breaking change**: Changed the AGPLv3 license to GPLv3. -- **Breaking change**: Removed the free non-commercial license. -- **Breaking change**: Changed behaviour of `setCellContents` so that it is possible to override space occupied by - spilled array. [#708](https://github.com/handsontable/hyperformula/issues/708) -- **Breaking change**: Changed behaviour of `addRows/removeRows` so that it is possible to add/remove rows across - spilled array without changing array size. [#708](https://github.com/handsontable/hyperformula/issues/708) -- **Breaking change**: Changed behaviour of `addColumns/removeColumns` so that it is possible to add/remove columns - across spilled array without changing array size. [#732](https://github.com/handsontable/hyperformula/issues/732) -- **Breaking change**: Changed config options [#747](https://github.com/handsontable/hyperformula/issues/747): - -| before | after | -|-----------------------|----------------------| -| matrixColumnSeparator | arrayColumnSeparator | -| matrixRowSeparator | arrayRowSeparator | - -- **Breaking change**: Changed CellType.MATRIX to - CellType.ARRAY [#747](https://github.com/handsontable/hyperformula/issues/747) -- **Breaking change**: Changed API methods [#747](https://github.com/handsontable/hyperformula/issues/747): - -| before | after | -|--------------------|-------------------| -| matrixMapping | arrrayMapping | -| isCellPartOfMatrix | isCellPartOfArray | - -- **Breaking change**: Changed Exceptions [#747](https://github.com/handsontable/hyperformula/issues/747): - -| before | after | -|------------------------------|-----------------------------| -| SourceLocationHasMatrixError | SourceLocationHasArrayError | -| TargetLocationHasMatrixError | TargetLocationHasArrayError | - -- Changed SWITCH function, so it takes array as its first argument. -- Changed TRANSPOSE function, so it works with data of any - type. [#708](https://github.com/handsontable/hyperformula/issues/708) -- Changed the way how we include `gpu.js` making it even more - optional [#753](https://github.com/handsontable/hyperformula/issues/753) - -### Fixed - -- Fixed an issue with arrays and cruds. [#651](https://github.com/handsontable/hyperformula/issues/651) -- Fixed handling of arrays for ROWS/COLUMNS functions. [#677](https://github.com/handsontable/hyperformula/issues/677) -- Fixed an issue with nested named expressions. [#679](https://github.com/handsontable/hyperformula/issues/679) -- Fixed an issue with matrixDetection + number parsing. [#686](https://github.com/handsontable/hyperformula/issues/686) -- Fixed an issue with NOW and TODAY functions. [#709](https://github.com/handsontable/hyperformula/issues/709) -- Fixed an issue with MIN/MAX function caches. [#711](https://github.com/handsontable/hyperformula/issues/711) -- Fixed an issue with caching and order of evaluation. [#735](https://github.com/handsontable/hyperformula/issues/735) - -## [0.6.2] - 2021-05-26 - -### Changed - -- Modified a private field in one of the classes to ensure broader compatibility with older TypeScript - versions. [#681](https://github.com/handsontable/hyperformula/issues/681) - -## [0.6.1] - 2021-05-24 - -### Changed - -- Remove redundant `'assert'` dependency from the code. [#672](https://github.com/handsontable/hyperformula/issues/672) - -### Fixed - -- Fixed library support for IE11. The `unorm` package is added to the - dependencies. [#675](https://github.com/handsontable/hyperformula/issues/675) - -## [0.6.0] - 2021-04-27 - -### Added - -- Added two new fired events, for suspending and resuming - execution. [#637](https://github.com/handsontable/hyperformula/issues/637) -- Added listing in scopes to `listNamedExpressions` - method. [#638](https://github.com/handsontable/hyperformula/issues/638) - -### Changed - -- **Breaking change**: Moved `GPU.js` from `dependencies` to `devDependencies` - and `optionalDependencies`. [#642](https://github.com/handsontable/hyperformula/issues/642) - -### Fixed - -- Fixed issues with scoped named - expression. [#646](https://github.com/handsontable/hyperformula/issues/646) [#641](https://github.com/handsontable/hyperformula/issues/641) -- Fixed an issue with losing formating info about DateTime - numbers. [#626](https://github.com/handsontable/hyperformula/issues/626) - -## [0.5.0] - 2021-04-15 - -### Added - -- Added support for row and column reordering. [#343](https://github.com/handsontable/hyperformula/issues/343) -- Added type inferrence for subtypes for number. [#313](https://github.com/handsontable/hyperformula/issues/313) -- Added parsing of number literals containing '%' or currency symbol (default - '$'). [#590](https://github.com/handsontable/hyperformula/issues/590) -- Added ability to fallback to plain CPU implementation for functions that uses - GPU.js [#355](https://github.com/handsontable/hyperformula/issues/355) - -### Changed - -- **Breaking change**: A change to the type of value returned via serialization - methods. [#617](https://github.com/handsontable/hyperformula/issues/617) -- An input value should be preserved through serialization more - precisely. [#617](https://github.com/handsontable/hyperformula/issues/617) -- GPU.js constructor needs to be provided directly to engine - configuration. [#355](https://github.com/handsontable/hyperformula/issues/355) -- A deprecated config option vlookupThreshold has been - removed. [#620](https://github.com/handsontable/hyperformula/issues/620) - -### Fixed - -- Fixed minor issue. [#631](https://github.com/handsontable/hyperformula/issues/631) -- Fixed a bug with serialization of some addresses after - CRUDs. [#587](https://github.com/handsontable/hyperformula/issues/587) -- Fixed a bug with MEDIAN function implementation. [#601](https://github.com/handsontable/hyperformula/issues/601) -- Fixed a bug with copy-paste operation that could cause out of scope - references [#591](https://github.com/handsontable/hyperformula/issues/591) -- Fixed a bug with date parsing. [#614](https://github.com/handsontable/hyperformula/issues/614) -- Fixed a bug where accent/case sensitivity was ignored for - LOOKUPs. [#621](https://github.com/handsontable/hyperformula/issues/621) -- Fixed a bug with handling of no time format/no date format - scenarios. [#616](https://github.com/handsontable/hyperformula/issues/616) - -## [0.4.0] - 2020-12-17 - -### Added - -- Added 50 mathematical functions: ROMAN, ARABIC, FACT, FACTDOUBLE, COMBIN, COMBINA, GCD, LCM, MROUND, MULTINOMIAL, - QUOTIENT, RANDBETWEEN, SERIESSUM, SIGN, SQRTPI, SUMX2MY2, SUMX2PY2, SUMXMY2, CEILING.MATH, FLOOR.MATH, FLOOR, - CEILING.PRECISE, FLOOR.PRECISE, ISO.CEILING, COMPLEX, IMABS, IMAGINARY, IMARGUMENT, IMCONJUGATE, IMCOS, IMCOSH, IMCOT, - IMCSC, IMCSCH, IMDIV, IMEXP, IMLN, IMLOG10, IMLOG2, IMPOWER, IMPRODUCT, IMREAL, IMSEC, IMSECH, IMSIN, IMSINH, IMSQRT, - IMSUB, IMSUM, - IMTAN. [#537](https://github.com/handsontable/hyperformula/issues/537) [#582](https://github.com/handsontable/hyperformula/issues/582) [#281](https://github.com/handsontable/hyperformula/issues/281) [#581](https://github.com/handsontable/hyperformula/issues/581) -- Added 106 statistical functions: EXPON.DIST, EXPONDIST, FISHER, FISHERINV, GAMMA, GAMMA.DIST, GAMMADIST, GAMMALN, - GAMMALN.PRECISE, GAMMA.INV, GAMMAINV, GAUSS, BETA.DIST, BETADIST, BETA.INV, BETAINV, BINOM.DIST, BINOMDIST, BINOM.INV, - BESSELI, BESSELJ, BESSELK, BESSELY, CHISQ.DIST, CHISQ.DIST.RT, CHISQ.INV, CHISQ.INV.RT, CHIDIST, CHIINV, F.DIST, - F.DIST.RT, F.INV, F.INV.RT, FDIST, FINV, WEIBULL, WEIBULL.DIST, HYPGEOMDIST, HYPGEOM.DIST, T.DIST, T.DIST.2T, - T.DIST.RT, T.INV, T.INV.2T, TDIST, TINV, LOGNORM.DIST, LOGNORMDIST, LOGNORM.INV, LOGINV, NORM.DIST, NORMDIST, - NORM.S.DIST, NORMSDIST, NORM.INV, NORMINV, NORM.S.INV, NORMSINV, PHI, NEGBINOM.DIST, NEGBINOMDIST, POISSON, - POISSON.DIST, LARGE, SMALL, AVEDEV, CONFIDENCE, CONFIDENCE.NORM, CONFIDENCE.T, DEVSQ, GEOMEAN, HARMEAN, CRITBINOM, - COVAR, COVARIANCE.P, COVARIANCE.S, PEARSON, RSQ, STANDARDIZE, Z.TEST, ZTEST, F.TEST, FTEST, STEYX, SLOPE, CHITEST, - CHISQ.TEST, T.TEST, TTEST, SKEW.P, SKEW, WEIBULLDIST, VARS, TINV2T, TDISTRT, TDIST2T, STDEVS, FINVRT, FDISTRT, - CHIDISTRT, CHIINVRT, COVARIANCEP, COVARIANCES, LOGNORMINV, POISSONDIST, - SKEWP. [#152](https://github.com/handsontable/hyperformula/issues/152) [#154](https://github.com/handsontable/hyperformula/issues/154) [#160](https://github.com/handsontable/hyperformula/issues/160) -- Added function aliases mechanism. [#569](https://github.com/handsontable/hyperformula/issues/569) -- Added support for scientific notation. [#579](https://github.com/handsontable/hyperformula/issues/579) -- Added support for complex numbers. [#281](https://github.com/handsontable/hyperformula/issues/281) - -### Changed - -- A **breaking change**: CEILING function implementation to be consistent with existing - implementations. [#582](https://github.com/handsontable/hyperformula/issues/582) - -### Fixed - -- Fixed a problem with dependencies not collected for specific - functions. [#550](https://github.com/handsontable/hyperformula/issues/550) [#549](https://github.com/handsontable/hyperformula/issues/549) -- Fixed a minor problem with dependencies under nested - parenthesis. [#549](https://github.com/handsontable/hyperformula/issues/549) [#558](https://github.com/handsontable/hyperformula/issues/558) -- Fixed a problem with HLOOKUP/VLOOKUP getting stuck in binary - search. [#559](https://github.com/handsontable/hyperformula/issues/559) [#562](https://github.com/handsontable/hyperformula/issues/562) -- Fixed a problem with the logic of dependency - resolving. [#561](https://github.com/handsontable/hyperformula/issues/561) [#563](https://github.com/handsontable/hyperformula/issues/563) -- Fixed a minor bug with ATAN2 function. [#581](https://github.com/handsontable/hyperformula/issues/581) - -## [0.3.0] - 2020-10-22 - -### Added - -- Added 9 text functions EXACT, LOWER, UPPER, MID, T, SUBSTITUTE, REPLACE, UNICODE, - UNICHAR. [#159](https://github.com/handsontable/hyperformula/issues/159) -- Added 5 datetime functions: INTERVAL, NETWORKDAYS, NETWORKDAYS.INTL, WORKDAY, - WORKDAY.INTL. [#153](https://github.com/handsontable/hyperformula/issues/153) -- Added 3 information functions HLOOKUP, ROW, COLUMN. [#520](https://github.com/handsontable/hyperformula/issues/520) -- Added 5 financial functions FVSCHEDULE, NPV, MIRR, PDURATION, - XNPV. [#542](https://github.com/handsontable/hyperformula/issues/542) -- Added 12 statistical functions VAR.P, VAR.S, VARA, VARPA, STDEV.P, STDEV.S, STDEVA, STDEVPA, VARP, VAR, STDEVP, - STDEV. [#536](https://github.com/handsontable/hyperformula/issues/536) -- Added 2 mathematical functions SUBTOTAL, PRODUCT. [#536](https://github.com/handsontable/hyperformula/issues/536) -- Added 15 operator functions HF.ADD, HF.CONCAT, HF.DIVIDE, HF.EQ, HF.GT, HF.GTE, HF.LT, HF.LTE, HF.MINUS, HF.MULTIPLY, - HF.NE, HF.POW, HF.UMINUS, HF.UNARY_PERCENT, HF.UPLUS. [#543](https://github.com/handsontable/hyperformula/issues/543) - -### Fixed - -- Fixed multiple issues with VLOOKUP - function. [#526](https://github.com/handsontable/hyperformula/issues/526) [#528](https://github.com/handsontable/hyperformula/issues/528) -- Fixed MATCH and INDEX functions compatiblity. [#520](https://github.com/handsontable/hyperformula/issues/520) -- Fixed issue with config update that does not preserve named - expressions. [#527](https://github.com/handsontable/hyperformula/issues/527) -- Fixed minor issue with arithmetic operations error - messages. [#532](https://github.com/handsontable/hyperformula/issues/532) - -## [0.2.0] - 2020-09-22 - -### Added - -- Added 9 text functions LEN, TRIM, PROPER, CLEAN, REPT, RIGHT, LEFT, SEARCH, - FIND. [#221](https://github.com/handsontable/hyperformula/issues/221) -- Added helper methods for keeping track of cell/range dependencies: - `getCellPrecedents` and `getCellDependents`. [#441](https://github.com/handsontable/hyperformula/issues/441) -- Added 22 financial functions FV, PMT, PPMT, IPMT, CUMIPMT, CUMPRINC, DB, DDB, DOLLARDE, DOLLARFR, EFFECT, ISPMT, - NOMINAL, NPER, RATE, PV, RRI, SLN, SYD, TBILLEQ, TBILLPRICE, - TBILLYIELD. [#494](https://github.com/handsontable/hyperformula/issues/494) -- Added FORMULATEXT function. [#422](https://github.com/handsontable/hyperformula/issues/422) -- Added 8 information functions ISERR, ISNA, ISREF, NA, SHEET, SHEETS, ISBINARY, - ISFORMULA. [#481](https://github.com/handsontable/hyperformula/issues/481) -- Added 15 date functions: WEEKDAY, DATEVALUE, HOUR, MINUTE, SECOND, TIME, TIMEVALUE, NOW, TODAY, EDATE, WEEKNUM, - ISOWEEKNUM, DATEDIF, DAYS360, YEARFRAC. [#483](https://github.com/handsontable/hyperformula/issues/483) -- Added 13 trigonometry functions: SEC, CSC, SINH, COSH, TANH, COTH, SECH, CSCH, ACOT, ASINH, ACOSH, ATANH, - ACOTH. [#485](https://github.com/handsontable/hyperformula/issues/485) -- Added 6 engineering functions: OCT2BIN, OCT2DEC, OCT2HEX, HEX2BIN, HEX2OCT, - HEX2DEC. [#497](https://github.com/handsontable/hyperformula/issues/497) -- Added a configuration option to evaluate reference to an empty cells as a - zero. [#476](https://github.com/handsontable/hyperformula/issues/476) -- Added new error type: missing licence. [#306](https://github.com/handsontable/hyperformula/issues/306) -- Added detailed error messages for error values. [#506](https://github.com/handsontable/hyperformula/issues/506) -- Added ability to handle more characters in quoted sheet - names. [#509](https://github.com/handsontable/hyperformula/issues/509) -- Added support for escaping apostrophe character in quoted sheet - names. [#64](https://github.com/handsontable/hyperformula/issues/64) - -### Changed - -- Operation `moveCells` creating cyclic dependencies does not cause losing original - formula. [#479](https://github.com/handsontable/hyperformula/issues/479) -- Simplified adding new function modules, reworked (simplified) implementations of existing - modules. [#480](https://github.com/handsontable/hyperformula/issues/480) - -### Fixed - -- Fixed hardcoding of languages in i18n tests. [#471](https://github.com/handsontable/hyperformula/issues/471) -- Fixed many compilation warnings based on LGTM - analysis. [#473](https://github.com/handsontable/hyperformula/issues/473) -- Fixed `moveCells` behaviour when moving part of a - range. [#479](https://github.com/handsontable/hyperformula/issues/479) -- Fixed `moveColumns`/`moveRows` inconsistent behaviour. [#479](https://github.com/handsontable/hyperformula/issues/479) -- Fixed undo of `moveColumns`/`moveRows` operations. [#479](https://github.com/handsontable/hyperformula/issues/479) -- Fixed name-collision issue in translations. [#486](https://github.com/handsontable/hyperformula/issues/486) -- Fixed bug in concatenation + `nullValue`. [#495](https://github.com/handsontable/hyperformula/issues/495) -- Fixed bug when undoing irreversible operation. [#502](https://github.com/handsontable/hyperformula/issues/502) -- Fixed minor issue with CHAR function logic. [#510](https://github.com/handsontable/hyperformula/issues/510) -- Fixed `simpleCellAddressToString` behaviour when converting quoted sheet - names. [#514](https://github.com/handsontable/hyperformula/issues/514) -- Fixed issues with numeric aggregation functions. [#515](https://github.com/handsontable/hyperformula/issues/515) - -## [0.1.3] - 2020-07-21 - -### Fixed - -- Fixed a bug in coercion of empty string to boolean - value. [#453](https://github.com/handsontable/hyperformula/issues/453) - -## [0.1.2] - 2020-07-13 - -### Fixed - -- Fixed a bug in topological ordering module. [#442](https://github.com/handsontable/hyperformula/issues/442) - -## [0.1.1] - 2020-07-01 - -### Fixed - -- Fixed a typo in a config option from `useRegularExpresssions` to - `useRegularExpressions`. [#437](https://github.com/handsontable/hyperformula/issues/437) - -## [0.1.0] - 2020-06-25 - -### Added - -- Core functionality of the engine; -- Support for data types: String, Error, Number, Date, Time, DateTime, Duration, Distinct Logical; -- Support for logical operators: =, <>, >, <, >=, <=; -- Support for arithmetic operators: +, -, \*, /, %; -- Support for text operator: &; -- CRUD operations: - - modifying the value of a single cell, - - adding/deleting row/column, - - reading the value or formula from the selected cell, - - moving a cell or a block of cells, - - deleting a subset of rows or columns, - - recalculating and refreshing of a worksheet, - - batching CRUD operations, - - support for wildcards and regex inside criterion functions like SUMIF, COUNTIF, - - named expressions support, - - support for cut, copy, paste, - - undo/redo support; -- Following functions: ABS(), ACOS(), AND(), ASIN(), ATAN(), ATAN2(), AVERAGE(), AVERAGEA(), AVERAGEIF(), BASE(), - BIN2DEC(), BIN2HEX()BIN2OCT(), BITAND(), BITLSHIFT(), BITOR(), BITRSHIFT(), BITXOR(), CEILING(), CHAR(), CHOOSE(), - CODE(), COLUMNS(), CONCATENATE(), CORREL(), COS(), COT(), COUNT(), COUNTA(), COUNTBLANK(), COUNTIF(), COUNTIFS(), - COUNTUNIQUE(), DATE(), DAY(), DAYS(), DEC2BIN(), DEC2HEX(), DEC2OCT(), DECIMAL(), DEGREES(), DELTA(), E(), EOMONTH(), - ERF(), ERFC(), EVEN(), EXP(), FALSE(), IF(), IFERROR(), IFNA(), INDEX(), INT(), ISBLANK(), ISERROR(), ISEVEN(), - ISLOGICAL(), ISNONTEXT(), ISNUMBER(), ISODD(), ISTEXT(), LN(), LOG(), LOG10(), MATCH(), MAX(), MAXA(), MAXPOOL(), - MEDIAN(), MEDIANPOOL(), MIN(), MINA(), MMULT(), MOD(), MONTH(), NOT(), ODD(), OFFSET(), OR(), PI(), POWER(), RADIANS() - , RAND(), ROUND(), ROUNDDOWN(), ROUNDUP(), ROWS(), SIN(), SPLIT(), SQRT(), SUM(), SUMIF(), SUMIFS(), SUMPRODUCT(), - SUMSQ(), SWITCH(), TAN(), TEXT(), TRANSPOSE(), TRUE(), TRUNC(), VLOOKUP(), XOR(), YEAR(); -- Support for volatile functions; -- Cultures supports - can be configured according to the application need; -- Custom functions support; -- Set http://docs.oasis-open.org/office/v1.2/OpenDocument-v1.2-part2.html as a standard to follow; -- Error handling: - - Division by zero: #DIV/0!, - - Unknown function name: #NAME?, - - Wrong type of argument in a function or wrong type of operator: #VALUE!, - - Invalid numeric values: #NUM!, - - No value available: #N/A, - - Cyclic dependency: #CYCLE!, - - Wrong address reference: #REF; -- Built-in function translation support for 16 languages: English, Czech, Danish, Dutch, Finnish, French, German, - Hungarian, Italian, Norwegian, Polish, Portuguese, Russian, Spanish, Swedish, Turkish. +Entries follow [Keep a Changelog](https://keepachangelog.com/en/1.0.0/); the format and the rules for writing one are in [`dev-docs/DOC-STANDARDS.md`](dev-docs/DOC-STANDARDS.md#the-changelog). diff --git a/README.md b/README.md index 8d3d14707b..eadb350300 100644 --- a/README.md +++ b/README.md @@ -1,116 +1,39 @@ -
-

- - HyperFormula - A headless spreadsheet, a parser and evaluator of Excel formulas - -

+# HyperFormula monorepo -

- An open-source headless spreadsheet for business web apps -

+[HyperFormula](https://hyperformula.handsontable.com/) is a headless spreadsheet calculation engine in TypeScript. It parses formulas, tracks cell dependencies, and recalculates incrementally, in the browser and in Node. -

- npm total downloads - npm monthly downloads - GitHub contributors - Known Vulnerabilities -
- FOSSA Status - GitHub Workflow Status - codecov -

+This repository holds the engine and everything built around it. ---- +| Directory | What it is | Published | +|---|---|---| +| [`hyperformula/`](hyperformula/) | The calculation engine. **Start here** — its [README](hyperformula/README.md) is the product documentation. | yes | +| [`hyperformula-ui/`](hyperformula-ui/) | UI components for working with HyperFormula. Not imported yet. | yes | +| [`docs/`](docs/) | The documentation portal. Installed separately; not a workspace member. | no | -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 -- Educational app -- Online calculator - -## Features - -- [Function syntax compatible with Microsoft Excel](https://hyperformula.handsontable.com/docs/guide/compatibility-with-microsoft-excel.html) and [Google Sheets](https://hyperformula.handsontable.com/docs/guide/compatibility-with-google-sheets.html) -- High-speed parsing and evaluation of spreadsheet formulas -- [A library of ~400 built-in functions](https://hyperformula.handsontable.com/docs/guide/built-in-functions.html) -- [Support for custom functions](https://hyperformula.handsontable.com/docs/guide/custom-functions.html) -- [Support for Node.js](https://hyperformula.handsontable.com/docs/guide/server-side-installation.html#install-with-npm-or-yarn) -- [Support for undo/redo](https://hyperformula.handsontable.com/docs/guide/undo-redo.html) -- [Support for CRUD operations](https://hyperformula.handsontable.com/docs/guide/basic-operations.html) -- [Support for clipboard](https://hyperformula.handsontable.com/docs/guide/clipboard-operations.html) -- [Support for named expressions](https://hyperformula.handsontable.com/docs/guide/named-expressions.html) -- [Support for data sorting](https://hyperformula.handsontable.com/docs/guide/sorting-data.html) -- [Support for formula localization with 17 built-in languages](https://hyperformula.handsontable.com/docs/guide/i18n-features.html) -- Easy integration with any front-end or back-end application -- GPLv3 or a [commercial license](https://handsontable.com/get-a-quote) -- Maintained by the team that stands behind the [Handsontable](https://handsontable.com/) data grid - -## Documentation - -- [Client-side installation](https://hyperformula.handsontable.com/docs/guide/client-side-installation.html) -- [Server-side installation](https://hyperformula.handsontable.com/docs/guide/server-side-installation.html) -- [Basic usage](https://hyperformula.handsontable.com/docs/guide/basic-usage.html) -- [Configuration options](https://hyperformula.handsontable.com/docs/guide/configuration-options.html) -- [List of built-in functions](https://hyperformula.handsontable.com/docs/guide/built-in-functions.html) -- [API Reference](https://hyperformula.handsontable.com/docs/api/) - -## Integrations - -- [Integration with React](https://hyperformula.handsontable.com/docs/guide/integration-with-react.html#demo) -- [Integration with Angular](https://hyperformula.handsontable.com/docs/guide/integration-with-angular.html#demo) -- [Integration with Vue](https://hyperformula.handsontable.com/docs/guide/integration-with-vue.html#demo) -- [Integration with Svelte](https://hyperformula.handsontable.com/docs/guide/integration-with-svelte.html#demo) - -## Installation and usage - -Install the library from [npm](https://www.npmjs.com/package/hyperformula) like so: +## Getting started ```bash -npm install hyperformula +npm ci # installs the workspace +npm run test:setup-private # attaches the private test suite, if you have access +npm run test:jest # the fast test loop +npm run bundle-all # every bundle for the engine ``` -Once installed, you can use it to develop applications tailored to your specific business needs. Here, we've used it to craft a form that calculates mortgage payments using the `PMT` formula. - -```js -import { HyperFormula } from 'hyperformula'; - -// Create a HyperFormula instance -const hf = HyperFormula.buildEmpty({ licenseKey: 'gpl-v3' }); - -// Add an empty sheet -const sheetName = hf.addSheet('Mortgage Calculator'); -const sheetId = hf.getSheetId(sheetName); - -// Enter the mortgage parameters -hf.addNamedExpression('AnnualInterestRate', '8%'); -hf.addNamedExpression('NumberOfMonths', 360); -hf.addNamedExpression('LoanAmount', 800000); +Root scripts fan out to the packages; run a package's own scripts from its directory, or with `--workspace=hyperformula`. -// Use the PMT function to calculate the monthly payment -hf.setCellContents({ sheet: sheetId, row: 0, col: 0 }, [['Monthly Payment', '=PMT(AnnualInterestRate/12, NumberOfMonths, -LoanAmount)']]); +The documentation portal installs on its own: -// Display the result -console.log(`${hf.getCellValue({ sheet: sheetId, row: 0, col: 0 })}: ${hf.getCellValue({ sheet: sheetId, row: 0, col: 1 })}`); +```bash +npm run docs:install +npm run docs:dev ``` -[Run this code in StackBlitz](https://stackblitz.com/github/handsontable/hyperformula-demos/tree/3.4.x/mortgage-calculator) - -HyperFormula ships an official Claude skill and machine-readable docs, so your AI coding agent can scaffold, configure, and debug HyperFormula correctly. To install the skill in Claude Code, or to point Cursor, GitHub Copilot, or another agent at the docs, see [Set up your coding agent](https://hyperformula.handsontable.com/docs/guide/setup-coding-agent.html). - -## Contributing - -Contributions are welcome, but before you make them, please read the [Contributing Guide](https://hyperformula.handsontable.com/docs/guide/contributing.html) and accept the [Contributor License Agreement](https://goo.gl/forms/yuutGuN0RjsikVpM2). +## Contributing and development -## License +- External contributors: [`CONTRIBUTING.md`](CONTRIBUTING.md) +- Everyone working on the source, including AI agents: [`dev-docs/README.md`](dev-docs/README.md) — architecture, build, testing, standards, and the definition of done +- AI coding agents: [`AGENTS.md`](AGENTS.md) -HyperFormula is available under two different licenses: GPLv3 and proprietary. The proprietary license can be purchased by [contacting our team](https://handsontable.com/get-a-quote) at Handsontable. +## Licence -Copyright (c) Handsoncode +GPL-3.0-only, plus a commercial licence. See [`LICENSE.txt`](LICENSE.txt). diff --git a/dev-docs/AGENT-TOOLING.md b/dev-docs/AGENT-TOOLING.md index 3c372dfbe5..cd7e30d221 100644 --- a/dev-docs/AGENT-TOOLING.md +++ b/dev-docs/AGENT-TOOLING.md @@ -21,7 +21,7 @@ Committed, so every developer gets the same setup. | Key | Why | |---|---| | `enabledPlugins` | `typescript-lsp` — language-server go-to-definition and find-references. Use it instead of grepping for a symbol's definition or callers; grep stays right for text searches. | -| `permissions.deny` | Blocks agent reads of every generated and built path. The build outputs are git-ignored, so content searches already skip them, but nothing otherwise stops an agent opening `dist/hyperformula.js` or answering a behaviour question from `typings/` instead of `src/`. | +| `permissions.deny` | Blocks agent reads of every generated and built path. The build outputs are git-ignored, so content searches already skip them, but nothing otherwise stops an agent opening `dist/hyperformula.js` or answering a behaviour question from `typings/` instead of `hyperformula/src/`. | | `worktree.symlinkDirectories` | Symlinks `node_modules` into each worktree rather than duplicating it. See [`WORKTREES.md`](WORKTREES.md). | | `hooks` | The `PostToolUse` lint hook below. | @@ -56,7 +56,7 @@ A skill holds the **steps**: what to do, in what order, and what to check. It do | Skill | For | |---|---| -| `hyperformula-dev` | Any work in `src/` — the entry point | +| `hyperformula-dev` | Any work in `hyperformula/src/` — the entry point | | `hyperformula-function-dev` | Adding or changing a built-in function | | `hyperformula-unit-testing` | Writing or modifying tests | | `test-writing-discipline` | Any red test, and any test that might be going green for the wrong reason | diff --git a/dev-docs/ARCHITECTURE.md b/dev-docs/ARCHITECTURE.md index 3bb617ce39..f2f5996ead 100644 --- a/dev-docs/ARCHITECTURE.md +++ b/dev-docs/ARCHITECTURE.md @@ -33,26 +33,26 @@ HyperFormula is a headless spreadsheet calculation engine. No UI, no DOM, no ser | Module | Role | |---|---| -| `src/HyperFormula.ts` | The public API. Every documented method lives here; JSDoc on it is the API reference. | -| `src/BuildEngineFactory.ts` | Constructs an engine from sheets, data, and config. | -| `src/Config.ts`, `src/ConfigParams.ts` | Configuration options, defaults, and validation. | -| `src/CrudOperations.ts` | Create/read/update/delete on sheets and cells. Validates before mutating. | -| `src/Operations.ts` | The mutation primitives `CrudOperations` composes. | -| `src/UndoRedo.ts` | The undo/redo stack, expressed in terms of those primitives. | -| `src/parser/` | Formula text to AST, and back (`Unparser`). Caches parsed formulas. | -| `src/interpreter/` | AST to value. Owns the function registry and every built-in function. | -| `src/DependencyGraph/` | Vertices, edges, address mapping, range mapping, topological sort. | -| `src/dependencyTransformers/` | Rewrites ASTs when rows, columns, or sheets are added, removed, or moved. | -| `src/Evaluator.ts` | Drives recalculation over the graph. | -| `src/NamedExpressions.ts` | Named expression storage and scoping. | -| `src/Serialization.ts`, `src/Exporter.ts` | Read values, formulas, and serialized content back out. | -| `src/i18n/` | Function-name translations, one file per language. | -| `src/format/` | Number and date format parsing. | -| `src/statistics/` | Instrumentation counters used by the performance benchmarks. | +| `hyperformula/src/HyperFormula.ts` | The public API. Every documented method lives here; JSDoc on it is the API reference. | +| `hyperformula/src/BuildEngineFactory.ts` | Constructs an engine from sheets, data, and config. | +| `hyperformula/src/Config.ts`, `hyperformula/src/ConfigParams.ts` | Configuration options, defaults, and validation. | +| `hyperformula/src/CrudOperations.ts` | Create/read/update/delete on sheets and cells. Validates before mutating. | +| `hyperformula/src/Operations.ts` | The mutation primitives `CrudOperations` composes. | +| `hyperformula/src/UndoRedo.ts` | The undo/redo stack, expressed in terms of those primitives. | +| `hyperformula/src/parser/` | Formula text to AST, and back (`Unparser`). Caches parsed formulas. | +| `hyperformula/src/interpreter/` | AST to value. Owns the function registry and every built-in function. | +| `hyperformula/src/DependencyGraph/` | Vertices, edges, address mapping, range mapping, topological sort. | +| `hyperformula/src/dependencyTransformers/` | Rewrites ASTs when rows, columns, or sheets are added, removed, or moved. | +| `hyperformula/src/Evaluator.ts` | Drives recalculation over the graph. | +| `hyperformula/src/NamedExpressions.ts` | Named expression storage and scoping. | +| `hyperformula/src/Serialization.ts`, `hyperformula/src/Exporter.ts` | Read values, formulas, and serialized content back out. | +| `hyperformula/src/i18n/` | Function-name translations, one file per language. | +| `hyperformula/src/format/` | Number and date format parsing. | +| `hyperformula/src/statistics/` | Instrumentation counters used by the performance benchmarks. | ## The parser -`src/parser/` wraps the [Chevrotain](https://chevrotain.io/) parser generator. +`hyperformula/src/parser/` wraps the [Chevrotain](https://chevrotain.io/) parser generator. - `LexerConfig.ts` and `ParserConfig.ts` build the token set from the active language and config — the lexer is **language-dependent**, because function names are translated. - `ParserWithCaching.ts` is the entry point; identical formula strings resolve from `Cache.ts` rather than being reparsed. @@ -61,16 +61,16 @@ HyperFormula is a headless spreadsheet calculation engine. No UI, no DOM, no ser ## The interpreter -`src/interpreter/Interpreter.ts` evaluates an AST node against an `InterpreterState`. +`hyperformula/src/interpreter/Interpreter.ts` evaluates an AST node against an `InterpreterState`. - `FunctionRegistry.ts` maps a function id to the plugin that implements it. Custom functions register through the same registry, and may override a built-in id. -- Every built-in function lives in a plugin under `src/interpreter/plugin/` extending `FunctionPlugin`. See [`src/interpreter/plugin/AGENTS.md`](../src/interpreter/plugin/AGENTS.md). -- `src/interpreter/functionMetadata/` holds the human-readable description of each function — a separate, id-keyed source from the implementation. See [`FUNCTION-CATALOGUE.md`](FUNCTION-CATALOGUE.md). +- Every built-in function lives in a plugin under `hyperformula/src/interpreter/plugin/` extending `FunctionPlugin`. See [`hyperformula/src/interpreter/plugin/AGENTS.md`](../hyperformula/src/interpreter/plugin/AGENTS.md). +- `hyperformula/src/interpreter/functionMetadata/` holds the human-readable description of each function — a separate, id-keyed source from the implementation. See [`FUNCTION-CATALOGUE.md`](FUNCTION-CATALOGUE.md). - `ArithmeticHelper.ts` centralises coercion and comparison. Reach for it rather than writing coercion inside a function. ## The dependency graph -`src/DependencyGraph/` is what makes recalculation incremental. +`hyperformula/src/DependencyGraph/` is what makes recalculation incremental. - `Graph.ts` holds the vertices and edges; `TopSort.ts` produces the evaluation order and detects cycles. - Vertex kinds: `ValueCellVertex`, `FormulaVertex`, `EmptyCellVertex`, `RangeVertex`, `ParsingErrorVertex`. @@ -79,27 +79,27 @@ HyperFormula is a headless spreadsheet calculation engine. No UI, no DOM, no ser ## Invariants -Everything in `src/` ships, runs in the browser and in Node, and sits on the hot path of a calculation engine. These hold everywhere in it. +Everything in `hyperformula/src/` ships, runs in the browser and in Node, and sits on the hot path of a calculation engine. These hold everywhere in it. -- **Headless.** No DOM, no network, no filesystem. A dependency that reaches for `window`, `document`, or `fs` does not belong in `src/`. +- **Headless.** No DOM, no network, no filesystem. A dependency that reaches for `window`, `document`, or `fs` does not belong in `hyperformula/src/`. - **Incremental.** A change recalculates the affected subgraph, never the whole sheet. Anything that forces a full recalculation is a performance regression, not an implementation detail. - **Language-dependent parsing.** Function names, argument separators, and error literals all vary by language. Never hard-code an English function name in the parser or the interpreter. -- **Errors are values.** Return a `CellError` with a message from `src/error-message.ts`. A throw reachable from evaluation escapes one cell and takes the whole recalculation with it. +- **Errors are values.** Return a `CellError` with a message from `hyperformula/src/error-message.ts`. A throw reachable from evaluation escapes one cell and takes the whole recalculation with it. - **Coercion goes through `ArithmeticHelper`.** Spreadsheet coercion is not JavaScript coercion, and it is already implemented once. -- **Public API stability.** `src/HyperFormula.ts` and the types it exports are the contract. The JSDoc on it **is** the published API reference — write it for the reader of the docs portal. See [`DEFINITION-OF-DONE.md`](DEFINITION-OF-DONE.md) for what a breaking change requires. -- **Tests, always.** Every change here ships a test in `test/`; a bug fix ships one that fails against the unfixed code. See [`TESTING.md`](TESTING.md). +- **Public API stability.** `hyperformula/src/HyperFormula.ts` and the types it exports are the contract. The JSDoc on it **is** the published API reference — write it for the reader of the docs portal. See [`DEFINITION-OF-DONE.md`](DEFINITION-OF-DONE.md) for what a breaking change requires. +- **Tests, always.** Every change here ships a test in `hyperformula/test/`; a bug fix ships one that fails against the unfixed code. See [`TESTING.md`](TESTING.md). ## Subsystem references | Subsystem | Page | |---|---| -| `src/parser/` | [`PARSER.md`](PARSER.md) | -| `src/interpreter/`, including `plugin/` | [`INTERPRETER.md`](INTERPRETER.md) | -| `src/interpreter/functionMetadata/` | [`FUNCTION-CATALOGUE.md`](FUNCTION-CATALOGUE.md) | -| `src/DependencyGraph/` | [`DEPENDENCY-GRAPH.md`](DEPENDENCY-GRAPH.md) | -| `src/i18n/` | [`I18N.md`](I18N.md) | +| `hyperformula/src/parser/` | [`PARSER.md`](PARSER.md) | +| `hyperformula/src/interpreter/`, including `plugin/` | [`INTERPRETER.md`](INTERPRETER.md) | +| `hyperformula/src/interpreter/functionMetadata/` | [`FUNCTION-CATALOGUE.md`](FUNCTION-CATALOGUE.md) | +| `hyperformula/src/DependencyGraph/` | [`DEPENDENCY-GRAPH.md`](DEPENDENCY-GRAPH.md) | +| `hyperformula/src/i18n/` | [`I18N.md`](I18N.md) | -## Everything else in `src/` +## Everything else in `hyperformula/src/` - `HyperFormula.ts` — the public API. Every method here is documented output. - `CrudOperations.ts` / `Operations.ts` / `UndoRedo.ts` — CRUD validates, `Operations` mutates, `UndoRedo` records. A new mutation needs all three, or undo silently diverges. diff --git a/dev-docs/BUILD.md b/dev-docs/BUILD.md index d4645d0d5f..4a5e6fe251 100644 --- a/dev-docs/BUILD.md +++ b/dev-docs/BUILD.md @@ -6,15 +6,22 @@ This page holds only what the guide does not cover. ## Install -Node version is pinned in [`.nvmrc`](../.nvmrc) — 22, the same everywhere in the repository. The repository uses npm with a committed `package-lock.json`, so install with `npm ci`, not `npm install`. +Node version is pinned in [`.nvmrc`](../.nvmrc) — 22, the same in every package. The repository uses npm workspaces with a committed `package-lock.json`, so install with `npm ci`, not `npm install`. + +```bash +npm ci # the workspace: hyperformula, hyperformula-ui +npm run docs:install # the portal, which is not a workspace member +``` + +Root scripts fan out to the packages. `npm run lint` is the exception: it runs once, from the root, over the whole repository. To run a package's own scripts, work from its directory or pass `--workspace=hyperformula`. ## The intermediate build -`npm run compile` runs `tsc` into `lib/`. Every bundle reads `lib/`, not `src/`, so a bundle built without recompiling ships the previous source. +`npm run compile` runs `tsc` into `hyperformula/lib/`. Every bundle reads `lib/`, not `hyperformula/src/`, so a bundle built without recompiling ships the previous source. `npm run bundle-all` chains `clean`, `compile`, every `bundle:*`, then `verify-bundles`. The individual `bundle:*` scripts recompile first unless `HF_COMPILE=1` is set — `script/if-ne-env.js` is what skips the redundant recompile inside `bundle-all`. -`npm run clean` removes `coverage/`, `commonjs/`, `dist/`, `es/`, `languages/`, `lib/`, `typings/`, and `test-jasmine/`. +`npm run clean` removes, inside `hyperformula/`, `coverage/`, `commonjs/`, `dist/`, `es/`, `languages/`, `lib/`, `typings/`, and `test-jasmine/`. `languages/` — the standalone UMD language packs — is a build output like the rest, and is missing from the guide's list of output formats. @@ -22,8 +29,10 @@ Node version is pinned in [`.nvmrc`](../.nvmrc) — 22, the same everywhere in t | File | Generated by | Rule | |---|---|---| -| `docs/api/` | `npm run typedoc:build-api` | Never edit. Change the JSDoc in `src/`. | -| `docs/guide/built-in-functions.md` | `npm run docs:generate-function-docs`, from `built-in-functions.tmpl.md` and the metadata catalogue | Never edit, never commit. | +| `docs/api/` | `npm run typedoc:build-api` — TypeDoc runs inside `hyperformula/`, where the `tsconfig.json` is, and writes across into the portal | Never edit. Change the JSDoc in `hyperformula/src/`. | +| `docs/guide/built-in-functions.md` | `npm run docs:generate-function-docs`, which runs `docs/script/generate-builtin-functions-doc.ts` against the metadata catalogue | Never edit, never commit. Needs the portal installed. | + +The generator lives in `docs/script/` rather than beside the engine build scripts because it uses `@vuepress/shared-utils` for slugs, and that package only resolves inside a full VuePress dependency tree. Both are git-ignored, and both are regenerated as the first step of `docs:dev` and `docs:build`. `docs:generate-function-docs` is a gate, not a formatter: it fails the build on a missing catalogue entry or a `'Custom'` category. See [`FUNCTION-CATALOGUE.md`](FUNCTION-CATALOGUE.md). @@ -37,7 +46,7 @@ The portal is served by a Cloudflare Worker. | `npm run docs:deploy:cf` | `wrangler deploy` — production | | `npm run docs:preview:cf` | `wrangler versions upload` — a per-branch preview URL | -Config is [`wrangler.jsonc`](../wrangler.jsonc); the Worker entry point is [`worker/index.js`](../worker/index.js). +Config is [`docs/wrangler.jsonc`](../docs/wrangler.jsonc); the Worker entry point is [`docs/worker/index.js`](../docs/worker/index.js). ## Release and licences diff --git a/dev-docs/CODE-STYLE.md b/dev-docs/CODE-STYLE.md index 85ee2231cd..cc85085e2a 100644 --- a/dev-docs/CODE-STYLE.md +++ b/dev-docs/CODE-STYLE.md @@ -26,13 +26,13 @@ Hot paths worth knowing about before touching them: | Path | Why it is hot | |---|---| -| `src/interpreter/` function implementations | Runs once per formula, and once per cell for array-broadcast arguments | -| `src/DependencyGraph/` vertex and range mapping | Every read and every structural change goes through it | -| `src/Evaluator.ts` | Walks the whole recalculation order | -| `src/parser/ParserWithCaching.ts` | Cache misses reparse; a change that defeats the cache is a regression | -| `src/LazilyTransformingAstService.ts` | Deferred AST rewrites after row/column/sheet operations | +| `hyperformula/src/interpreter/` function implementations | Runs once per formula, and once per cell for array-broadcast arguments | +| `hyperformula/src/DependencyGraph/` vertex and range mapping | Every read and every structural change goes through it | +| `hyperformula/src/Evaluator.ts` | Walks the whole recalculation order | +| `hyperformula/src/parser/ParserWithCaching.ts` | Cache misses reparse; a change that defeats the cache is a regression | +| `hyperformula/src/LazilyTransformingAstService.ts` | Deferred AST rewrites after row/column/sheet operations | ## TypeScript -- The public API surface is `src/HyperFormula.ts` and the types it exports; `npm run bundle:typings` emits them into `typings/`. +- The public API surface is `hyperformula/src/HyperFormula.ts` and the types it exports; `npm run bundle:typings` emits them into `typings/`. - `npm run verify:typings` (`tsc --noEmit`) must pass. A change that only compiles because of an `as` cast usually has a modelling problem behind it. diff --git a/dev-docs/DEFINITION-OF-DONE.md b/dev-docs/DEFINITION-OF-DONE.md index 0be743a922..a60c83da7a 100644 --- a/dev-docs/DEFINITION-OF-DONE.md +++ b/dev-docs/DEFINITION-OF-DONE.md @@ -2,11 +2,11 @@ Every change to production code — bug fix, feature, or improvement — must include all of the following **before** a code review is requested. -1. **The production change**, including every supported language pack in `src/i18n/languages/` when function names are involved. -2. **Automatic tests** in `test/`: +1. **The production change**, including every supported language pack in `hyperformula/src/i18n/languages/` when function names are involved. +2. **Automatic tests** in `hyperformula/test/`: - bug fix — at least one test that reproduces the bug; - new feature — a set of tests that precisely describe the feature; - - pull requests from external contributors put tests in `test/`; the internal team adds them to the private repository through a separate pull request. + - pull requests from external contributors put tests in `hyperformula/test/`; the internal team adds them to the private repository through a separate pull request. See [`TESTING.md`](TESTING.md). 3. **Documentation updates** matching the change. A breaking change also needs a section in the migration guide. See [`DOC-STANDARDS.md`](DOC-STANDARDS.md). 4. **JSDoc** on classes and functions, plus a high-level description of the concepts used in any complex fragment. @@ -27,7 +27,7 @@ Every change in the pull request must be relevant to the issue it solves. Unrela ## Breaking changes -The public API is `src/HyperFormula.ts` and the types it exports. Avoid breaking it. When a change genuinely requires a break: +The public API is `hyperformula/src/HyperFormula.ts` and the types it exports. Avoid breaking it. When a change genuinely requires a break: - state it explicitly in the pull request description and the changelog entry; - add a migration-guide section describing what breaks and what to do instead; diff --git a/dev-docs/DEPENDENCY-GRAPH.md b/dev-docs/DEPENDENCY-GRAPH.md index 58871ab28b..ba031fccae 100644 --- a/dev-docs/DEPENDENCY-GRAPH.md +++ b/dev-docs/DEPENDENCY-GRAPH.md @@ -1,6 +1,6 @@ # The dependency graph -`src/DependencyGraph/` is what makes recalculation incremental. Vertices are cells and ranges, edges are dependencies, and a topological sort gives the evaluation order. +`hyperformula/src/DependencyGraph/` is what makes recalculation incremental. Vertices are cells and ranges, edges are dependencies, and a topological sort gives the evaluation order. ## The pieces @@ -19,7 +19,7 @@ ## Rules - **Ranges stay collapsed.** Expanding a range into per-cell edges turns `SUM(A1:A100000)` into 100 000 edges and destroys the performance the engine exists for. If you need per-cell information, ask whether the range vertex can answer instead. -- **Every structural change must keep the mappings consistent.** Adding or removing a row moves addresses; the address mapping, the range mapping, and the array mapping all have to agree afterwards, or a later read resolves to the wrong vertex. Structural changes are paired with `src/dependencyTransformers/` and `src/LazilyTransformingAstService.ts`, which defers the AST rewrites until a formula is actually read. +- **Every structural change must keep the mappings consistent.** Adding or removing a row moves addresses; the address mapping, the range mapping, and the array mapping all have to agree afterwards, or a later read resolves to the wrong vertex. Structural changes are paired with `hyperformula/src/dependencyTransformers/` and `hyperformula/src/LazilyTransformingAstService.ts`, which defers the AST rewrites until a formula is actually read. - **Cycles are a value, not an exception.** `TopSort` detects them and the affected cells get a `CYCLE` error. Never let a cycle throw or loop. - **`EmptyCellVertex` is not "no vertex".** An empty cell that something depends on still needs a vertex, or the dependency is lost when it is later filled. - This is the hottest code in the engine after the interpreter — every read and every structural change goes through it. diff --git a/dev-docs/DOC-STANDARDS.md b/dev-docs/DOC-STANDARDS.md index cceaa0a562..e3987e8757 100644 --- a/dev-docs/DOC-STANDARDS.md +++ b/dev-docs/DOC-STANDARDS.md @@ -1,6 +1,6 @@ # Documentation standards -These apply across the whole repository: guides, the API reference, JSDoc inside `src/`, the changelog, migration guides, and README files. +These apply across the whole repository: guides, the API reference, JSDoc inside `hyperformula/src/`, the changelog, migration guides, and README files. *How* to write a page — structure, chunking, language, code examples, and the self-review checklist — is [`DOCS-CONTENT-GUIDE.md`](DOCS-CONTENT-GUIDE.md). This page is *when* documentation is required and what it must be true about. @@ -21,7 +21,7 @@ This is not a licence to make a guide unreadable on its own. A guide page repeat | File | Generated by | Rule | |---|---|---| -| `docs/api/` | `npm run typedoc:build-api` | Never edit. Change the JSDoc in `src/`. | +| `docs/api/` | `npm run typedoc:build-api` | Never edit. Change the JSDoc in `hyperformula/src/`. | | `docs/guide/built-in-functions.md` | `npm run docs:generate-function-docs` | Never edit, never commit. Change the metadata catalogue — see [`FUNCTION-CATALOGUE.md`](FUNCTION-CATALOGUE.md). | Both are git-ignored. A missing `docs/api/` folder means it has not been built yet; run `npm run docs:build`. diff --git a/dev-docs/FUNCTION-CATALOGUE.md b/dev-docs/FUNCTION-CATALOGUE.md index 1d230413dc..561f02eadb 100644 --- a/dev-docs/FUNCTION-CATALOGUE.md +++ b/dev-docs/FUNCTION-CATALOGUE.md @@ -1,6 +1,6 @@ # The function metadata catalogue -`src/interpreter/functionMetadata/categories/` holds the human-readable metadata for every built-in function: `shortDescription`, `parameters` (`snake_case` names, each with a description), `examples`, `documentationUrl`, and the category. +`hyperformula/src/interpreter/functionMetadata/categories/` holds the human-readable metadata for every built-in function: `shortDescription`, `parameters` (`snake_case` names, each with a description), `examples`, `documentationUrl`, and the category. It is the single source of truth for two consumers: diff --git a/dev-docs/I18N.md b/dev-docs/I18N.md index 767014dc88..65fc5eed35 100644 --- a/dev-docs/I18N.md +++ b/dev-docs/I18N.md @@ -1,10 +1,10 @@ # Internationalization and function translations -HyperFormula provides localized function names for every built-in language. Translation files live in [`src/i18n/languages/`](../src/i18n/languages/), one per language. +HyperFormula provides localized function names for every built-in language. Translation files live in [`hyperformula/src/i18n/languages/`](../hyperformula/src/i18n/languages/), one per language. A new function must ship translations for **all** built-in languages in the same change. A missing key is not caught by the type checker in every path, and it degrades silently to a formula that cannot be parsed in that language. -Parsing is language-dependent: the lexer builds its token set from the active translation package (`src/parser/LexerConfig.ts`). Never hard-code an English function name in the parser or the interpreter. +Parsing is language-dependent: the lexer builds its token set from the active translation package (`hyperformula/src/parser/LexerConfig.ts`). Never hard-code an English function name in the parser or the interpreter. ## Where to find a translation @@ -23,7 +23,7 @@ Parsing is language-dependent: the lexer builds its token set from the active tr ## Adding a language pack -A new pack needs the file in `src/i18n/languages/`, its export in `src/i18n/languages/index.ts`, a key set identical to the other packs, and a changelog entry. `npm run bundle:languages` produces the standalone UMD build. +A new pack needs the file in `hyperformula/src/i18n/languages/`, its export in `hyperformula/src/i18n/languages/index.ts`, a key set identical to the other packs, and a changelog entry. `npm run bundle:languages` produces the standalone UMD build. ## Testing diff --git a/dev-docs/INTERPRETER.md b/dev-docs/INTERPRETER.md index d858760880..5caa950216 100644 --- a/dev-docs/INTERPRETER.md +++ b/dev-docs/INTERPRETER.md @@ -1,6 +1,6 @@ # The interpreter -`src/interpreter/` evaluates an AST node against an `InterpreterState` and returns an `InterpreterValue`. +`hyperformula/src/interpreter/` evaluates an AST node against an `InterpreterState` and returns an `InterpreterValue`. ## The pieces @@ -19,13 +19,13 @@ ## Rules - **Coerce through `ArithmeticHelper`.** Never write ad-hoc string-to-number or value-to-boolean conversion inside a function; the coercion rules are spreadsheet semantics, not JavaScript semantics, and they are already implemented once. -- **Errors are values.** Return a `CellError` with a message from `src/error-message.ts`. Do not throw: a thrown error escapes the evaluation of one cell and takes the recalculation with it. +- **Errors are values.** Return a `CellError` with a message from `hyperformula/src/error-message.ts`. Do not throw: a thrown error escapes the evaluation of one cell and takes the recalculation with it. - **The registry is keyed by id, not by implementation.** A custom plugin can be registered over a built-in id. Do not assume the plugin you are reading is the one that will answer for that id at run time. - **This is the hot path.** `Interpreter.evaluateAst` runs once per formula, and once per cell for array-broadcast arguments. Allocation inside a per-cell loop is measurable. ## Built-in functions -Every built-in function lives in a plugin class under `src/interpreter/plugin/` extending `FunctionPlugin`. One file per plugin; a plugin holds one function or a family of related ones. +Every built-in function lives in a plugin class under `hyperformula/src/interpreter/plugin/` extending `FunctionPlugin`. One file per plugin; a plugin holds one function or a family of related ones. ```ts export class AbsPlugin extends FunctionPlugin implements FunctionPluginTypecheck { @@ -77,7 +77,7 @@ Pass the raw args, the state, `this.metadata('ID')`, and a plain implementation ### Never -- **Never throw.** Return a `CellError` with a message from `src/error-message.ts`. +- **Never throw.** Return a `CellError` with a message from `hyperformula/src/error-message.ts`. - **Never hand-roll coercion.** Declare the `argumentType` and let `runFunction` coerce, or use `ArithmeticHelper`. - **Never describe Excel's behaviour when HyperFormula deviates.** Implement what is specified, then record the deviation in [`docs/guide/list-of-differences.md`](../docs/guide/list-of-differences.md). - **Never allocate inside a per-cell loop** when the value can be hoisted. @@ -86,10 +86,10 @@ Pass the raw args, the state, `this.metadata('ID')`, and a plain implementation All five, or the failure is silent: -1. the plugin implementation in `src/interpreter/plugin/`; +1. the plugin implementation in `hyperformula/src/interpreter/plugin/`; 2. its `implementedFunctions` metadata; -3. the catalogue entry in `src/interpreter/functionMetadata/categories/` — see [`FUNCTION-CATALOGUE.md`](FUNCTION-CATALOGUE.md); -4. **every** language file in `src/i18n/languages/` — see [`I18N.md`](I18N.md); +3. the catalogue entry in `hyperformula/src/interpreter/functionMetadata/categories/` — see [`FUNCTION-CATALOGUE.md`](FUNCTION-CATALOGUE.md); +4. **every** language file in `hyperformula/src/i18n/languages/` — see [`I18N.md`](I18N.md); 5. tests — see [`TESTING.md`](TESTING.md). Skill: `hyperformula-function-dev`. diff --git a/dev-docs/MONOREPO.md b/dev-docs/MONOREPO.md index 80137a1400..51a7e7936a 100644 --- a/dev-docs/MONOREPO.md +++ b/dev-docs/MONOREPO.md @@ -1,75 +1,25 @@ -# Target monorepo layout +# The monorepo migration -This repository is becoming a monorepo (HF-359). The layout it stands at today is [`STRUCTURE.md`](STRUCTURE.md). +The move landed in HF-359. The layout as it now stands is [`STRUCTURE.md`](STRUCTURE.md); this page records what the migration decided, what it deliberately left alone, and what is still outstanding. -## Packages +## Still outstanding -| Package | Directory | Purpose | Published | -|---|---|---|---| -| `hyperformula` | `hyperformula/` | The calculation engine. Everything in `src/` and `test/` today. | yes | -| `hyperformula-ui` | `hyperformula-ui/` | UI components for working with HyperFormula: reference highlighting, inline formula editor, function help. | yes | -| `hyperformula-docs` | `docs/` | The VuePress documentation portal. | no | +1. **Import `hyperformula-ui`.** The directory exists and is listed in the root `workspaces` array; the package itself is imported from the formula-builder repository in a separate change, preserving its history. It keeps the scope it publishes under today. When it lands it needs an `.nvmrc` saying `22`, a `CHANGELOG.md`, and an `AGENTS.md` with a `CLAUDE.md` symlink. +2. **Path-filter CI.** Each package's jobs should run only when its own paths change, with full runs on `develop`, `master`, and release branches. Not done here on purpose: a naive `paths:` filter on a workflow that branch protection lists as a required check leaves the check permanently pending, and pull requests become unmergeable. Doing it safely needs the required-checks list, which lives in repository settings rather than in the tree, and the `dorny/paths-filter`-plus-single-gate shape that the Handsontable monorepo uses. -`docs/` is not a workspace member: the portal drags in a large, old dependency tree (VuePress, `--openssl-legacy-provider`) that must not reach an engine install. It keeps its own `package.json` and is installed separately. +## What the migration decided -## Tree +- **npm workspaces, not pnpm.** A package-manager migration is a risk the move did not need to carry at the same time. +- **`docs/` is not a workspace member.** VuePress 1.x and its `--openssl-legacy-provider` dependency tree must never reach an engine install. It installs on its own with `npm run docs:install`, and CI installs it before building the portal. +- **One `dev-docs/`, at the root.** The original plan put an engine-scope copy inside `hyperformula/`. That was dropped: two directories fragment the single source of truth, and every page would have to know which scope it was written from. The engine's subsystem pages live here alongside the repository-wide ones. +- **Every package versions and releases on its own cadence**, with its own `CHANGELOG.md` in the existing Keep a Changelog form. No fragment mechanism. +- **Every `.nvmrc` says `22`.** +- **Linting stays at the root**, run once over the whole repository, so nothing between packages falls through the gap. +- **The private test suite stays branch-matched.** Only its checkout path moved, to `hyperformula/test/hyperformula-tests/`. Its specs needed no change: they import the engine relatively, and the depth from a spec to the package root is unchanged. -``` -hyperformula/ # repository root — private, workspace root -├── AGENTS.md # monorepo-wide rules + routing map -├── CLAUDE.md -> AGENTS.md -├── README.md CONTRIBUTING.md CHANGELOG.md LICENSE.txt -├── package.json # private: true, npm workspaces, fan-out scripts -├── package-lock.json -├── .nvmrc # 22, like every other one here -├── .worktreeinclude -├── .claude/ -│ ├── settings.json # hooks, enabledPlugins, worktree settings -│ └── skills/ # ALL skills, scoped by the `paths` frontmatter field -├── dev-docs/ # monorepo-scope reference -│ -├── hyperformula/ # ── package: the engine -│ ├── AGENTS.md CLAUDE.md -> AGENTS.md -│ ├── package.json .nvmrc CHANGELOG.md -│ ├── dev-docs/ # engine-scope reference -│ ├── src/ -│ │ ├── AGENTS.md CLAUDE.md -> AGENTS.md -│ │ ├── parser/ AGENTS.md -│ │ ├── interpreter/ AGENTS.md -│ │ │ ├── plugin/ AGENTS.md -│ │ │ └── functionMetadata/ AGENTS.md -│ │ ├── DependencyGraph/ AGENTS.md -│ │ ├── i18n/languages/ AGENTS.md -│ │ └── dependencyTransformers/ format/ helpers/ Lookup/ statistics/ -│ └── test/ AGENTS.md README.md -│ └── hyperformula-tests/ # private suite, git-ignored, branch-matched -│ -├── hyperformula-ui/ # ── package: the UI components -│ ├── AGENTS.md CLAUDE.md -> AGENTS.md -│ ├── package.json .nvmrc CHANGELOG.md -│ ├── dev-docs/ -│ └── src/ test/ -│ -├── docs/ # ── documentation portal (NOT a workspace member) -│ ├── AGENTS.md CLAUDE.md -> AGENTS.md README.md -│ ├── package.json .nvmrc -│ ├── wrangler.jsonc # deploy config for the portal -│ ├── worker/index.js # Cloudflare Worker serving the built portal -│ └── guide/ api/ .vuepress/ -│ -├── examples/ # images and CSV fixtures used by the docs -├── script/ AGENTS.md README.md -└── .github/workflows/ # path-filtered per-package jobs -``` +## Two things the move uncovered -## Migration steps +Both were pre-existing, and both are recorded here because the next person will otherwise rediscover them the hard way. -1. **Move `src/` and `test/` into `hyperformula/`.** Mechanical, but it invalidates every path in CI, in `tsconfig.json`, `jest.config.js`, `karma.conf.js`, `.eslintignore`, and the docs generator scripts. The private suite's specs need no change: they import the engine relatively, and the depth from a spec to the package root is unchanged. -2. **Add `workspaces` to the root `package.json`** and make it `private: true`. Move the build scripts down into `hyperformula/package.json`, leaving fan-out scripts at the root. -3. **Give `docs/` its own `package.json`** and take it out of the root dependency tree. -4. **Move `wrangler.jsonc` and `worker/` under `docs/`.** Update `wrangler.jsonc`'s `main`, the `docs:*:cf` scripts, and `script/prepare-cf-assets.js` in the same change. Verify with `npm run docs:preview:cf` — a broken `main` path fails only at deploy time. -5. **Bring in `hyperformula-ui`**, preserving its history. -6. **Split `CHANGELOG.md` per package**, each keeping the current Keep a Changelog form. -7. **Give every package an `.nvmrc` saying `22`.** -8. **Update the private test suite's checkout path**, from `test/hyperformula-tests/` to `hyperformula/test/hyperformula-tests/`, in `fetch-tests.sh`, `.gitignore`, the three workflows that check it out, and `.worktreeinclude`. It stays branch-matched. -9. **Path-filter CI.** Each package's jobs run only when its paths change; full runs on `develop`, `master`, and release branches. +- **The source language packs were never linted.** The old ignore list carried a bare `languages` entry meant for the build output. An unanchored pattern matches a directory of that name at any depth, so it also excluded `src/i18n/languages/`, and the `sort-keys` override targeting those files never ran. Anchoring the build-output entry exposed 881 violations. They are excluded again, deliberately and with a comment, in [`.eslintignore`](../.eslintignore); sorting 19 translation files is a change of its own. +- **`@vuepress/shared-utils` only works inside a full VuePress dependency tree.** It requires `markdown-it-emoji` and a `lru-cache` major it does not declare, and relied on `vuepress` hoisting them. That is why the built-in-functions generator moved into `docs/script/`, where that tree exists, rather than staying beside the engine build scripts. diff --git a/dev-docs/PARSER.md b/dev-docs/PARSER.md index 8826357559..10d586d473 100644 --- a/dev-docs/PARSER.md +++ b/dev-docs/PARSER.md @@ -1,6 +1,6 @@ # The parser -`src/parser/` turns a formula string into an AST plus its relative dependencies, and turns an AST back into a string. It wraps the [Chevrotain](https://chevrotain.io/) parser generator. +`hyperformula/src/parser/` turns a formula string into an AST plus its relative dependencies, and turns an AST back into a string. It wraps the [Chevrotain](https://chevrotain.io/) parser generator. ## The pieces diff --git a/dev-docs/README.md b/dev-docs/README.md index dfc2cf9611..7c841cef89 100644 --- a/dev-docs/README.md +++ b/dev-docs/README.md @@ -21,18 +21,18 @@ In every directory, `CLAUDE.md` is a symlink to its sibling `AGENTS.md`. Edit `A | File | Contents | |---|---| | [`STRUCTURE.md`](STRUCTURE.md) | Repository tree and what lives where. | -| [`ARCHITECTURE.md`](ARCHITECTURE.md) | How the engine works: the pipeline, the core modules, and the invariants that hold everywhere in `src/`. | +| [`ARCHITECTURE.md`](ARCHITECTURE.md) | How the engine works: the pipeline, the core modules, and the invariants that hold everywhere in `hyperformula/src/`. | | [`MONOREPO.md`](MONOREPO.md) | The monorepo layout this repository is moving to. | ### Subsystems | File | Contents | |---|---| -| [`PARSER.md`](PARSER.md) | `src/parser/` — formula text to AST, and back. | -| [`INTERPRETER.md`](INTERPRETER.md) | `src/interpreter/` — AST to value, and how a built-in function is written. | -| [`DEPENDENCY-GRAPH.md`](DEPENDENCY-GRAPH.md) | `src/DependencyGraph/` — dependency tracking and recalculation order. | -| [`FUNCTION-CATALOGUE.md`](FUNCTION-CATALOGUE.md) | `src/interpreter/functionMetadata/` — what the API and the docs say about each function. | -| [`I18N.md`](I18N.md) | `src/i18n/` — function-name translations and where to source them. | +| [`PARSER.md`](PARSER.md) | `hyperformula/src/parser/` — formula text to AST, and back. | +| [`INTERPRETER.md`](INTERPRETER.md) | `hyperformula/src/interpreter/` — AST to value, and how a built-in function is written. | +| [`DEPENDENCY-GRAPH.md`](DEPENDENCY-GRAPH.md) | `hyperformula/src/DependencyGraph/` — dependency tracking and recalculation order. | +| [`FUNCTION-CATALOGUE.md`](FUNCTION-CATALOGUE.md) | `hyperformula/src/interpreter/functionMetadata/` — what the API and the docs say about each function. | +| [`I18N.md`](I18N.md) | `hyperformula/src/i18n/` — function-name translations and where to source them. | ### Working on a change @@ -53,7 +53,7 @@ In every directory, `CLAUDE.md` is a symlink to its sibling `AGENTS.md`. Edit `A | Where | For | |---|---| | [`docs/README.md`](../docs/README.md) | Running and extending the documentation portal | -| [`test/README.md`](../test/README.md) | Attaching the private test suite | +| [`hyperformula/test/README.md`](../hyperformula/test/README.md) | Attaching the private test suite | | [`script/README.md`](../script/README.md) | What each build and release script does | | [`CHANGELOG.md`](../CHANGELOG.md) | Release history | | [`.github/pull_request_template.md`](../.github/pull_request_template.md) | The pull request template | diff --git a/dev-docs/STRUCTURE.md b/dev-docs/STRUCTURE.md index fa6cf6487a..d579c96bdf 100644 --- a/dev-docs/STRUCTURE.md +++ b/dev-docs/STRUCTURE.md @@ -1,68 +1,81 @@ # Repository structure -The layout as it stands today. For the monorepo layout this repository is moving to, see [`MONOREPO.md`](MONOREPO.md). +A monorepo. Three top-level directories hold code; the rest is repository-wide. ``` . -├── src/ # Source code -│ ├── HyperFormula.ts # Main engine class, public API entry point -│ ├── BuildEngineFactory.ts # Engine construction from sheets, data, and config -│ ├── Config.ts, ConfigParams.ts # Engine configuration and its defaults -│ ├── CrudOperations.ts # Create/read/update/delete on sheets and cells -│ ├── Operations.ts, UndoRedo.ts # Operation primitives and the undo/redo stack -│ ├── Evaluator.ts # Recalculation driver -│ ├── Serialization.ts, Exporter.ts # Reading values and formulas back out -│ ├── NamedExpressions.ts # Named expression store -│ ├── parser/ # Formula parsing (Chevrotain parser generator) -│ ├── interpreter/ # Formula evaluation -│ │ ├── plugin/ # Built-in spreadsheet function plugins -│ │ └── functionMetadata/ # Human-readable metadata for every built-in function -│ ├── DependencyGraph/ # Cell dependency tracking and recalculation order -│ ├── dependencyTransformers/ # AST rewrites when rows/columns/sheets move -│ ├── i18n/languages/ # Function-name translations, one file per language -│ ├── format/ # Number and date format parsing -│ ├── helpers/ # Shared utilities -│ ├── Lookup/ # Lookup/search strategies used by lookup functions -│ └── statistics/ # Instrumentation counters -├── test/ # Smoke tests; the full suite is fetched here -│ ├── README.md # How to attach the private suite -│ ├── smoke.spec.ts # Public smoke tests -│ ├── fetch-tests.sh # Clones/updates the private test repository -│ └── hyperformula-tests/ # Private suite (git-ignored, branch-matched) -├── docs/ # Public documentation portal (VuePress) +├── hyperformula/ # ── package: the calculation engine (published) +│ ├── src/ # Source code +│ │ ├── HyperFormula.ts # Main engine class, public API entry point +│ │ ├── parser/ # Formula parsing (Chevrotain parser generator) +│ │ ├── interpreter/ # Formula evaluation +│ │ │ ├── plugin/ # Built-in spreadsheet function plugins +│ │ │ └── functionMetadata/ # Human-readable metadata for every built-in +│ │ ├── DependencyGraph/ # Cell dependency tracking and recalculation order +│ │ ├── dependencyTransformers/ # AST rewrites when rows/columns/sheets move +│ │ ├── i18n/languages/ # Function-name translations, one file per language +│ │ ├── format/ helpers/ Lookup/ statistics/ +│ ├── test/ # Smoke tests; the private suite mounts here +│ │ ├── smoke.spec.ts # Public smoke tests +│ │ ├── fetch-tests.sh # Clones/updates the private test repository +│ │ └── hyperformula-tests/ # Private suite (git-ignored, branch-matched) +│ ├── .config/ # webpack, karma, and babel config factories +│ ├── tsconfig.json jest.config.js karma.conf.js webpack.config.js +│ ├── babel.config.js ht.config.js jasmine.json .npmignore +│ ├── .typedoc.ts .typedoc.md.ts # API reference generation, output into docs/api +│ ├── package.json .nvmrc CHANGELOG.md README.md LICENSE.txt +│ └── AGENTS.md CLAUDE.md +│ +├── hyperformula-ui/ # ── package: UI components (not imported yet) +│ +├── docs/ # ── the documentation portal (NOT a workspace member) │ ├── guide/ # Markdown guides -│ ├── api/ # API reference (generated from JSDoc; git-ignored) -│ └── .vuepress/ # VuePress configuration, theme, components -├── script/ # Maintenance, docs-generation, and release scripts -├── worker/ # Cloudflare Worker that serves the built docs +│ ├── api/ # API reference (generated; git-ignored) +│ ├── examples/ # Code examples embedded in guides +│ ├── .vuepress/ # VuePress configuration, theme, components, plugins +│ ├── script/ # Generates guide/built-in-functions.md +│ ├── worker/index.js # Cloudflare Worker serving the built portal +│ ├── wrangler.jsonc # Its deploy configuration +│ ├── package.json .nvmrc +│ └── AGENTS.md CLAUDE.md README.md +│ +├── script/ # Repository-wide scripts: build checks, release, agent hooks ├── examples/ # Images and CSV fixtures used by the docs -├── dev-docs/ # Developer reference (this directory) -├── .claude/ # Claude Code settings, skills, and agents +├── dev-docs/ # Developer reference (this directory; start at README.md) +├── .ai/ # One sentence pointing at dev-docs/, for agents that look here +├── .claude/ # Claude Code settings, skills, and hooks ├── .github/ # CI workflows, issue and PR templates -├── AGENTS.md # Always-loaded agent rules and routing map -├── CLAUDE.md # Symlink to AGENTS.md -├── CONTRIBUTING.md # Guide for external contributors -├── README.md # Project overview -└── CHANGELOG.md +├── .eslintrc.js .eslintignore # Linting, run once from the root over everything +├── package.json # Private workspace root: fan-out scripts only +├── package-lock.json .nvmrc .worktreeinclude +├── AGENTS.md CLAUDE.md README.md CONTRIBUTING.md CHANGELOG.md LICENSE.txt +└── CODE_OF_CONDUCT.md ``` -## Build outputs +## Workspaces + +`workspaces` in the root `package.json` lists `hyperformula` and `hyperformula-ui`. `npm ci` at the root installs both into a shared `node_modules`. -All git-ignored, all produced by `npm run bundle-all` (see [`BUILD.md`](BUILD.md)): +**`docs/` is deliberately outside the workspace.** The portal drags in a large, old dependency tree (VuePress 1.x, `--openssl-legacy-provider`) that must not reach an engine install. It has its own `package.json` and installs separately with `npm run docs:install`. -| Directory | Contents | +## Where a command runs + +| Command | Runs in | |---|---| -| `lib/` | `tsc` output, the input to every bundle | -| `es/` | ES modules (`.mjs`) | -| `commonjs/` | CommonJS modules | -| `dist/` | UMD bundles, minified and not, base and `.full` | -| `languages/` | Standalone UMD language packs | -| `typings/` | Public `.d.ts` declarations | +| `npm run lint` | The root, over the whole repository | +| `npm run test:jest`, `bundle-all`, `compile` | Fanned out to `hyperformula` | +| `npm run docs:*` | Orchestrated from the root across both `hyperformula` and `docs` | + +Run a package's own scripts from its directory, or with `--workspace=hyperformula`. See [`BUILD.md`](BUILD.md). + +## Build outputs + +All git-ignored, all under `hyperformula/`: `lib/` (`tsc` output, the input to every bundle), `es/`, `commonjs/`, `dist/`, `languages/`, `typings/`. The portal's output is `docs/.vuepress/dist/`, and `docs/api/` plus `docs/guide/built-in-functions.md` are generated. -Never edit these, and never read them to answer a question about behaviour — read `src/` instead. +Never edit these, and never read them to answer a question about behaviour — read `hyperformula/src/` instead. ## Directories with their own `AGENTS.md` -Each of these carries rules that load only when an agent works inside it: +`hyperformula/`, `hyperformula/src/`, `hyperformula/src/parser/`, `hyperformula/src/interpreter/`, `hyperformula/src/interpreter/plugin/`, `hyperformula/src/interpreter/functionMetadata/`, `hyperformula/src/DependencyGraph/`, `hyperformula/src/i18n/`, `hyperformula/test/`, `docs/`, and `script/`. -`src/`, `src/parser/`, `src/interpreter/`, `src/interpreter/plugin/`, `src/interpreter/functionMetadata/`, `src/DependencyGraph/`, `src/i18n/`, `docs/`, `test/`, `script/`. +Each is a pointer of a few lines — what the directory is, and which `dev-docs/` page or local `README.md` holds the detail. They load automatically when an agent reads a file in that subtree, so they stay small on purpose. diff --git a/dev-docs/TESTING.md b/dev-docs/TESTING.md index 9d6b9c47ca..2fcc3b5f52 100644 --- a/dev-docs/TESTING.md +++ b/dev-docs/TESTING.md @@ -4,10 +4,10 @@ | Suite | Where | Who has it | |---|---|---| -| Smoke tests | [`test/smoke.spec.ts`](../test/smoke.spec.ts) | Everyone, in this repository | -| Full suite | `test/hyperformula-tests/` | Internal team and anyone granted access | +| Smoke tests | [`hyperformula/test/smoke.spec.ts`](../hyperformula/test/smoke.spec.ts) | Everyone, in this repository | +| Full suite | `hyperformula/test/hyperformula-tests/` | Internal team and anyone granted access | -The full suite is kept in a separate private repository and is **git-ignored** here. It carries the unit tests, the browser and compatibility runs, and the performance benchmarks. External contributors put their tests in `test/`; the internal team moves them into the private repository through a separate pull request. +The full suite is kept in a separate private repository and is **git-ignored** here. It carries the unit tests, the browser and compatibility runs, and the performance benchmarks. External contributors put their tests in `hyperformula/test/`; the internal team moves them into the private repository through a separate pull request. ## Fetching the private suite @@ -15,7 +15,7 @@ The full suite is kept in a separate private repository and is **git-ignored** h npm run test:setup-private ``` -**Run it after every branch switch.** The suite is branch-matched, so skipping it runs the previous branch's tests against the current source: the results are meaningless, and they look like ordinary passes and failures. How the fetch works, and the environment variables it honours, are in [`test/README.md`](../test/README.md). In a fresh git worktree the directory is absent entirely — see [`WORKTREES.md`](WORKTREES.md). +**Run it after every branch switch.** The suite is branch-matched, so skipping it runs the previous branch's tests against the current source: the results are meaningless, and they look like ordinary passes and failures. How the fetch works, and the environment variables it honours, are in [`hyperformula/test/README.md`](../hyperformula/test/README.md). In a fresh git worktree the directory is absent entirely — see [`WORKTREES.md`](WORKTREES.md). ## Running tests @@ -26,14 +26,14 @@ npm run test:setup-private | `npm run test:watch` | Jest in watch mode | | `npm run test:coverage` | Jest with coverage | | `npm run test:browser` | Karma, against the `dist` build | -| `npm run test:compatibility` | `test/compatibility/test-compatibility.sh` | +| `npm run test:compatibility` | `hyperformula/test/compatibility/test-compatibility.sh` | | `npm run test:performance` | The basic and CRUD benchmarks | -`test:performance`, `test:compatibility`, and the benchmark scripts all live inside `test/hyperformula-tests/`. Without the private suite they fail with a missing path, not with a test failure — read the error before concluding that something is broken. +`test:performance`, `test:compatibility`, and the benchmark scripts all live inside `hyperformula/test/hyperformula-tests/`. Without the private suite they fail with a missing path, not with a test failure — read the error before concluding that something is broken. ## What a change must cover -- Every change to `src/` needs tests in `test/`. This is part of the [definition of done](DEFINITION-OF-DONE.md), not a suggestion. +- Every change to `hyperformula/src/` needs tests in `hyperformula/test/`. This is part of the [definition of done](DEFINITION-OF-DONE.md), not a suggestion. - **Bug fix**: at least one test that reproduces the bug — it must fail against the unfixed code. Write it first and watch it fail. - **New feature**: a set of tests that describe the feature precisely enough to serve as its specification. - Cover more than the happy path: boundary values, empty and invalid input, error results, and interaction with related features. diff --git a/dev-docs/WORKTREES.md b/dev-docs/WORKTREES.md index 1f38856d36..0ba3b90a88 100644 --- a/dev-docs/WORKTREES.md +++ b/dev-docs/WORKTREES.md @@ -6,17 +6,17 @@ Claude Code can run a session — or an isolated subagent — in a `git worktree | Missing | Why it matters | Fix | |---|---|---| -| `node_modules/` | Nothing runs. | `npm ci` in the worktree, or symlink it — see below | -| `test/hyperformula-tests/` | The private suite is git-ignored, so every `npm run test:jest` run covers only the smoke tests | `npm run test:setup-private` | +| `node_modules/` | Nothing runs. | `npm ci` in the worktree | +| `hyperformula/test/hyperformula-tests/` | The private suite is git-ignored, so every `npm run test:jest` run covers only the smoke tests | `npm run test:setup-private` | | `lib/`, `dist/`, `es/`, `commonjs/`, `typings/`, `languages/` | `npm run test:browser` and the bundle checks have nothing to run against | `npm run bundle-all` | | `docs/api/`, `docs/guide/built-in-functions.md` | The docs build fails, or serves nothing | `npm run docs:build` | | `.dev.vars*` | `wrangler` commands fail | Copied automatically — see [`.worktreeinclude`](../.worktreeinclude) | ## The branch-matched test suite is the trap -`test/fetch-tests.sh` checks out the branch of the **same name** in the private test repository. Two consequences in a worktree: +`hyperformula/test/fetch-tests.sh` checks out the branch of the **same name** in the private test repository. Two consequences in a worktree: -1. Copying `test/hyperformula-tests/` from the main checkout brings the *other* branch's tests. They will run, and they will report results that have nothing to do with the code in front of you. `.worktreeinclude` deliberately does not copy it. +1. Copying `hyperformula/test/hyperformula-tests/` from the main checkout brings the *other* branch's tests. They will run, and they will report results that have nothing to do with the code in front of you. `.worktreeinclude` deliberately does not copy it. 2. Run `npm run test:setup-private` once per worktree, and again after any branch switch inside it. ## Symlinking `node_modules` @@ -35,4 +35,4 @@ This is safe while HyperFormula is a single package: there is exactly one `node_ ## Sparse checkouts -`worktree.sparsePaths` limits what git writes to disk. It buys little today — this repository is small and `src/` is needed by everything. It becomes worth setting once the packages in [`MONOREPO.md`](MONOREPO.md) exist and a task can be scoped to one of them. +`worktree.sparsePaths` limits what git writes to disk. It buys little today — this repository is small and `hyperformula/src/` is needed by everything. It becomes worth setting once the packages in [`MONOREPO.md`](MONOREPO.md) exist and a task can be scoped to one of them. diff --git a/docs/.nvmrc b/docs/.nvmrc new file mode 100644 index 0000000000..2bd5a0a98a --- /dev/null +++ b/docs/.nvmrc @@ -0,0 +1 @@ +22 diff --git a/docs/.vuepress/build.config.js b/docs/.vuepress/build.config.js index 633ea41f32..85a777e5d8 100644 --- a/docs/.vuepress/build.config.js +++ b/docs/.vuepress/build.config.js @@ -2,11 +2,11 @@ * Docs build configuration. * Override any of these via environment variables: * DOCS_BASE — public base path (must start and end with `/`) - * DOCS_DEST — output directory (relative to repo root) + * DOCS_DEST — output directory (relative to the docs/ package root) * DOCS_HOSTNAME — absolute origin used for the sitemap */ module.exports = { base: '/docs/', - dest: 'docs/.vuepress/dist/docs', + dest: '.vuepress/dist/docs', hostname: 'https://hyperformula.handsontable.com', }; diff --git a/docs/.vuepress/components/graph.vue b/docs/.vuepress/components/graph.vue index 9c518f1968..edfccddffd 100644 --- a/docs/.vuepress/components/graph.vue +++ b/docs/.vuepress/components/graph.vue @@ -5,7 +5,7 @@