@particle-academy/holy-sheet 2.11.0 → 2.11.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +76 -0
- package/dist/{chunk-OL6E7DE5.js → chunk-Y32UXRQ6.js} +322 -75
- package/dist/chunk-Y32UXRQ6.js.map +1 -0
- package/dist/cli.cjs +320 -73
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +1 -1
- package/dist/index.cjs +320 -73
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +70 -3
- package/dist/index.d.ts +70 -3
- package/dist/index.js +2 -2
- package/package.json +1 -1
- package/dist/chunk-OL6E7DE5.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,82 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
10
10
|
|
|
11
11
|
## [Unreleased]
|
|
12
12
|
|
|
13
|
+
## [2.11.2] - 2026-10-28
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
`Agent.lint()` now follows Excel's formula semantics in the places below,
|
|
18
|
+
ported from PHP holy-sheet 2.11.1 (plus lazy `IF`, which all three linters
|
|
19
|
+
gain together). What you will notice: **fewer false `#NAME?` and `#DIV/0!`
|
|
20
|
+
reports** on formulas Excel accepts, and **some new true positives** on
|
|
21
|
+
formulas Excel rejects or errors on that the linter used to pass. `lint()`'s
|
|
22
|
+
signature and the issue shape `{sheet, address, formula, error, hint}` are
|
|
23
|
+
unchanged. Nothing to do unless you assert on the exact set of issues a formula
|
|
24
|
+
produces. Error labels and hint texts are byte-identical to PHP and Python.
|
|
25
|
+
|
|
26
|
+
- **`IF` evaluates only the branch it takes.** `=IF(A2=0,0,1/A2)` with A2 = 0
|
|
27
|
+
used to lint as `#DIV/0!`; it now lints clean, as does any error in the
|
|
28
|
+
untaken branch. That branch is still parsed, so a syntax error or an unknown
|
|
29
|
+
function there is still `#NAME?`. An error in the condition still propagates,
|
|
30
|
+
after the whole `IF` has been parsed. `IFERROR` is not in the linter's
|
|
31
|
+
vocabulary and is still `#NAME?`.
|
|
32
|
+
- **`%` is postfix percent.** `=50%` is 0.5 and `=A1%` is A1/100; these used to
|
|
33
|
+
lint as `#NAME?`. A binary `%` such as `=10%2`, which the linter used to
|
|
34
|
+
evaluate as `10/100*2`, is now reported, because Excel rejects it.
|
|
35
|
+
- **`^` binds tighter than `*` and `/`.** `=2*3^2` is 18, not 36. It stays
|
|
36
|
+
left-associative (`=2^3^2` is 64) and below negation (`=-2^2` is 4), as in
|
|
37
|
+
Excel.
|
|
38
|
+
- **A doubled quote inside text is one quote.** `="a""b"` is the three
|
|
39
|
+
characters `a"b`; it used to lint as `#NAME?`. A text literal that never
|
|
40
|
+
closes (`="abc`) is now reported instead of passing.
|
|
41
|
+
- **IF reads its condition as Excel does.** Text is TRUE or FALSE only when it
|
|
42
|
+
spells one of them, in any case: `"false"` used to count as TRUE. Any other
|
|
43
|
+
text, `""` included, is now `#VALUE!` (a new true positive; it used to pass).
|
|
44
|
+
An error in the condition now propagates instead of picking a branch.
|
|
45
|
+
- **Comparisons follow Excel's type order.** Numeric text is text, and Excel
|
|
46
|
+
sorts text above every number: `="5">9` is TRUE and `="10"=10` is FALSE (both
|
|
47
|
+
used to compare as numbers). Text compares without regard to case
|
|
48
|
+
(`="a"="A"` is TRUE), logicals sort above text, and a blank cell equals 0,
|
|
49
|
+
`""` and FALSE. An error on either side now propagates instead of being
|
|
50
|
+
compared as text. Text is ordered by code point, as PHP and Python order it.
|
|
51
|
+
- **A `#NAME?` hint says which kind it is.** The label is still `#NAME?`, but
|
|
52
|
+
every cause used to get one hint, "references an unknown function or has a
|
|
53
|
+
syntax error". A malformed formula now gets `Syntax error: <what and
|
|
54
|
+
where>...`; an unknown function gets `Unknown function VLOOKUP. ...`; a
|
|
55
|
+
`#NAME?` inherited from another cell names that cell; and an exception inside
|
|
56
|
+
the linter itself says it is a linter defect. Match on the hint's prefix if
|
|
57
|
+
you need to tell them apart.
|
|
58
|
+
- **An unknown function is `#NAME?` wherever it sits.** `=IF(FALSE, FOO(1), 1)`
|
|
59
|
+
used to pass, because the error was a value that IF discarded. Excel resolves
|
|
60
|
+
names first, so it is `#NAME?` there and now here (a new true positive).
|
|
61
|
+
- **`ROUND` rounds the decimal value, half away from zero.** `=ROUND(1.005,2)`
|
|
62
|
+
was 1, `=ROUND(0.285,2)` 0.28 and `=ROUND(8.325,2)` 8.32, because the digits
|
|
63
|
+
were shifted in binary, where 1.005 is 1.00499999.... They are now 1.01, 0.29
|
|
64
|
+
and 8.33, as in Excel, PHP and Python.
|
|
65
|
+
- **The tokenizer uses PHP's ASCII character classes.** A no-break space, or a
|
|
66
|
+
letter such as `é` outside a text literal, is now a syntax error, as it is in
|
|
67
|
+
PHP; the no-break space used to be skipped as whitespace.
|
|
68
|
+
|
|
69
|
+
## [2.11.1] - 2026-10-27
|
|
70
|
+
|
|
71
|
+
### Fixed
|
|
72
|
+
|
|
73
|
+
- **An explicit `{value: <string>}` cell is now written as a string, exactly
|
|
74
|
+
as given**, matching PHP holy-sheet and holy-sheet-py. Numeric-string
|
|
75
|
+
coercion used to run on the object form too, so `{value: "+1"}` was written
|
|
76
|
+
as the number 1, `{value: "007"}` as 7 and `{value: "1e5"}` as 100000: a
|
|
77
|
+
phone prefix, zip code or part number lost its characters with no error.
|
|
78
|
+
This applies in `rows` and in the sparse `cells` map, under any column type
|
|
79
|
+
or number format, and to a `set_cell` op's `value`. Unchanged: a BARE string
|
|
80
|
+
in a row or a `cells` entry is still coerced (`"+1"` is still 1) and a bare
|
|
81
|
+
`"=..."` is still a formula; an object value that is already a number is
|
|
82
|
+
still a number; and a string under a `date` / `datetime` display format is
|
|
83
|
+
still converted to a date serial. `read()` returns such a cell as the same
|
|
84
|
+
string.
|
|
85
|
+
**What a consumer must do:** if you relied on `{value: "100"}` becoming a
|
|
86
|
+
number, pass the number (`{value: 100}`) or the bare string (`"100"`).
|
|
87
|
+
Otherwise nothing.
|
|
88
|
+
|
|
13
89
|
## [2.11.0] - 2026-10-27
|
|
14
90
|
|
|
15
91
|
### Added
|