Add TEXTJOIN function with i18n and documentation#1640
Add TEXTJOIN function with i18n and documentation#1640marcin-kordas-hoc wants to merge 12 commits intodevelopfrom
Conversation
* Fix package-lock file * Docs: remove CodeSandbox embedded demos and add links to working exa,ples in Stackblitz (#1621)
Implement Excel-compatible TEXTJOIN(delimiter, ignore_empty, text1, ...) as a native function in TextPlugin alongside CONCATENATE. The function joins text from multiple strings/ranges with a configurable delimiter and optionally skips empty strings. Returns #VALUE! when the result exceeds 32,767 characters (Excel cell content limit). - Add TEXTJOIN metadata and method to TextPlugin.ts - Add TextJoinResultTooLong error message to error-message.ts - Add function name translations to all 17 language files - Add 7 test cases covering ignore_empty, ranges, edge cases https://claude.ai/code/session_0138Q9YKLkHZ9geHUsEC6zFr
- Rewrite TEXTJOIN to accept range/array as delimiter argument with cycling behavior
(e.g., TEXTJOIN({"-","/"}, TRUE, "a","b","c") → "a-b/c")
- Change parameter types from STRING to ANY to support ranges without expandRanges
- Manually flatten text ranges and coerce values to strings
- Add 26 dedicated unit tests in test/textjoin.spec.ts covering:
- Basic functionality (literal strings, ranges, empty delimiter)
- ignore_empty behavior (empty cells, ="" cells, all-empty ranges)
- Array/range delimiter cycling
- Type coercion (numbers, booleans)
- Error propagation (#DIV/0!, #N/A)
- Edge cases (32767 char limit, mixed scalar and range args)
- Add array delimiter smoke test
https://claude.ai/code/session_0138Q9YKLkHZ9geHUsEC6zFr
- Remove dead code: redundant CellError check after coerceScalarToString in flattenArgToStrings - Remove empty no-op afterEach callback from textjoin test suite
Per code review: smoke.spec.ts should stay minimal. All TEXTJOIN tests are now consolidated in textjoin.spec.ts, covering individual cell references, single-ref args, and explicit empty-string vs null cell behaviour for ignore_empty=TRUE/FALSE.
- Delete test/textjoin.spec.ts (tests moved to hyperformula-tests) - Fix TEXTJOIN position in built-in-functions.md: move between TEXT and TRIM
- Replace `as string` cast with explicit CellError check on coerceScalarToString return value - Remove duplicate textjoin/flattenArgToStrings methods introduced during rebase
|
Code review is billed via overage credits. To resume reviews, an organization admin can raise the monthly limit in Settings → Usage. Once credits are available, push a new commit or reopen this pull request to trigger a review. |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Autofix Details
Bugbot Autofix prepared a fix for the issue found in the latest run.
- ✅ Fixed: Template literal variable won't interpolate in markdown links
- Replaced plain markdown links with Vue dynamic
:hrefbindings using backtick template literals so$page.buildDateURIEncodedis properly interpolated at render time, matching the pattern used by the original iframe:srcbindings.
- Replaced plain markdown links with Vue dynamic
Or push these changes by commenting:
@cursor push bbcf633ee4
Preview (bbcf633ee4)
diff --git a/docs/guide/custom-functions.md b/docs/guide/custom-functions.md
--- a/docs/guide/custom-functions.md
+++ b/docs/guide/custom-functions.md
@@ -358,7 +358,7 @@
## Working demo
-Explore the full working example on [Stackblitz](https://stackblitz.com/github/handsontable/hyperformula-demos/tree/3.2.x/custom-functions?v=${$page.buildDateURIEncoded}).
+Explore the full working example on <a :href="`https://stackblitz.com/github/handsontable/hyperformula-demos/tree/3.2.x/custom-functions?v=${$page.buildDateURIEncoded}`">Stackblitz</a>.
This demo contains the implementation of both the
[`GREET`](#add-a-simple-custom-function) and
diff --git a/docs/guide/integration-with-angular.md b/docs/guide/integration-with-angular.md
--- a/docs/guide/integration-with-angular.md
+++ b/docs/guide/integration-with-angular.md
@@ -6,4 +6,4 @@
## Demo
-Explore the full working example on [Stackblitz](https://stackblitz.com/github/handsontable/hyperformula-demos/tree/3.2.x/angular-demo?v=${$page.buildDateURIEncoded}).
+Explore the full working example on <a :href="`https://stackblitz.com/github/handsontable/hyperformula-demos/tree/3.2.x/angular-demo?v=${$page.buildDateURIEncoded}`">Stackblitz</a>.
diff --git a/docs/guide/integration-with-react.md b/docs/guide/integration-with-react.md
--- a/docs/guide/integration-with-react.md
+++ b/docs/guide/integration-with-react.md
@@ -6,4 +6,4 @@
## Demo
-Explore the full working example on [Stackblitz](https://stackblitz.com/github/handsontable/hyperformula-demos/tree/3.2.x/react-demo?v=${$page.buildDateURIEncoded}).
+Explore the full working example on <a :href="`https://stackblitz.com/github/handsontable/hyperformula-demos/tree/3.2.x/react-demo?v=${$page.buildDateURIEncoded}`">Stackblitz</a>.
diff --git a/docs/guide/integration-with-svelte.md b/docs/guide/integration-with-svelte.md
--- a/docs/guide/integration-with-svelte.md
+++ b/docs/guide/integration-with-svelte.md
@@ -6,4 +6,4 @@
## Demo
-Explore the full working example on [Stackblitz](https://stackblitz.com/github/handsontable/hyperformula-demos/tree/3.2.x/svelte-demo?v=${$page.buildDateURIEncoded}).
+Explore the full working example on <a :href="`https://stackblitz.com/github/handsontable/hyperformula-demos/tree/3.2.x/svelte-demo?v=${$page.buildDateURIEncoded}`">Stackblitz</a>.
diff --git a/docs/guide/integration-with-vue.md b/docs/guide/integration-with-vue.md
--- a/docs/guide/integration-with-vue.md
+++ b/docs/guide/integration-with-vue.md
@@ -31,7 +31,7 @@
## Demo
-Explore the full working example on [Stackblitz](https://stackblitz.com/github/handsontable/hyperformula-demos/tree/3.2.x/vue-3-demo?v=${$page.buildDateURIEncoded}).
+Explore the full working example on <a :href="`https://stackblitz.com/github/handsontable/hyperformula-demos/tree/3.2.x/vue-3-demo?v=${$page.buildDateURIEncoded}`">Stackblitz</a>.
::: tip
This demo uses the [Vue 3](https://v3.vuejs.org/) framework. If you are looking for an example using Vue 2, check out the [code on GitHub](https://github.com/handsontable/hyperformula-demos/tree/2.5.x/vue-demo).This Bugbot Autofix run was free. To enable autofix for future PRs, go to the Cursor dashboard.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
| } | ||
| let result = parts[0] | ||
| for (let i = 1; i < parts.length; i++) { | ||
| result += delimiters[(i - 1) % delimiters.length] + parts[i] |
There was a problem hiding this comment.
No guard against empty delimiters array causes corruption
Low Severity
If delimiters is an empty array (e.g., from an unusual SimpleRangeValue with no data), the expression delimiters[(i - 1) % delimiters.length] computes a modulo by zero, producing NaN as the index. delimiters[NaN] evaluates to undefined, which gets coerced to the literal string "undefined" during concatenation, silently corrupting the result instead of returning an error.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## develop #1640 +/- ##
===========================================
- Coverage 97.18% 97.18% -0.01%
===========================================
Files 172 172
Lines 14836 14870 +34
Branches 3258 3266 +8
===========================================
+ Hits 14418 14451 +33
- Misses 418 419 +1
🚀 New features to boost your workflow:
|
Performance comparison of head (7aca32c) vs base (4042b04) |



Summary
Adds the
TEXTJOINfunction — joins text from multiple strings and/or ranges with a configurable delimiter.Replaces #1625 (was opened from fork, now from upstream branch directly).
Features
ignore_emptyparameter to skip empty stringsbuilt-in-functions.mdImplementation
textjoinmethod +flattenArgToStringshelper inTextPluginrepeatLastArgs: 1metadata pattern (same as SUMPRODUCT, etc.)CellErrorcheck oncoerceScalarToStringreturn valueChanged files
src/interpreter/plugin/TextPlugin.tstextjoin()+flattenArgToStrings()src/error-message.tsTextJoinResultTooLongmessagesrc/i18n/languages/*.ts(17 files)docs/guide/built-in-functions.mdReview feedback addressed (from #1625)
hyperformula-testsrepo (companion PR pending)as stringcast inflattenArgToStringsTest plan
hyperformula-tests/unit/interpreter/function-textjoin.spec.tsNote
Medium Risk
Adds new formula evaluation logic (
TEXTJOIN) including range flattening, type coercion, and new error handling; main risk is subtle compatibility/edge-case differences and potential performance impact when joining large ranges.Overview
Adds the
TEXTJOINspreadsheet function to the interpreter (TextPlugin), supporting scalar or range delimiters (cycled between joined values), optional skipping of empty strings, and coercion of scalar values to strings with error propagation.Introduces a new
#VALUE!error message when the joined result exceeds 32,767 characters, and wiresTEXTJOINinto i18n function-name dictionaries across all supported languages. Updates the built-in functions guide to documentTEXTJOINsyntax and behavior.Written by Cursor Bugbot for commit 7aca32c. This will update automatically on new commits. Configure here.