* Sonar: explicit imports, fn paths for closures, extract helpers for cognitive complexity
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
* Fix imports
* Fix serde imports
* Fix engine imports
* Fix clippy gate and a type error from the explicit-import change
Remove the unused imports the review flagged (cf.rs, pivot.rs, tables.rs, cmd/sheet.rs) so clippy -D warnings passes, and point the backstage parent-folder lookup at Path::to_str, which the fn-path rewrite had broken.
Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>
* Apply rustfmt to the explicit-import cleanup so the fmt gate passes
* Share the per-directory font path expansion in theme.rs
The candidate font lists repeated the same loop over the Linux font
directories in every role. A single helper expands them in the same order,
so the lookup order is unchanged and the duplicated blocks go away.
🤖 Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>
* Read the Windows fonts folder in one place in theme.rs
Every script-font list repeated the same WINDIR lookup. A single helper
returns the same path, so the duplicated lines go away without changing
which font files are tried.
🤖 Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>
* Build the light and dark UI palettes from one table in theme.rs
Tokens::light() and Tokens::dark() listed the same 40 colour fields in the
same order, so every change had to be made twice. A single palette
constructor takes the mode and picks each colour's value, so each field is
written once and both modes keep their exact colours.
🤖 Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>
* Share the Noto CJK font list between the CJK script lists in theme.rs
The Japanese, Simplified and Korean lists each repeated the same loop over
the Linux CJK directories with a different locale file name. One helper
builds that loop, and each list keeps its own face index, so the lookup
order is unchanged.
🤖 Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>
* Share Linux Noto directory list across Thai and Hebrew font lookups
Removes the duplicated directory arrays flagged by SonarCloud new-code duplication.
* Reuse in_dirs for Thai and Hebrew Noto font candidates
Removes the remaining duplicated per-directory loops flagged by SonarCloud.
* Share one font-list builder for the Thai and Hebrew faces
The two per-script functions repeated the same Windows, macOS, Linux and
variable-font setup. A single script_fonts helper now builds both lists,
keeping the candidate order unchanged, which clears the Sonar duplication gate.
---------
Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-authored-by: Codebuff <noreply@codebuff.com>
Found while testing crates/functions/src/text.rs:326-340
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Typed entry, VALUE and arithmetic now read $(1,234), $ (5) and (5)% as
negative numbers, as Excel 365 does. Parentheses no longer nest: (-5),
((5)), $5% and dates in parentheses stay text. This changes main's
((100)) from 100 to text; the no-recursion guard from #2180 is kept and
its test now asserts the new result.
From the local CodeRabbit review: the result was bounded per match, but
one match's expansion was built whole first, so a replacement repeating
$0 10,000 times over a 32,767-character match allocated about 330 MB
before the check. The replacement is now split into pieces as regex's
Captures::expand reads it (template_expands_like_regex checks they agree)
and appended piece by piece within the bound: 327 MB peak became 7 MB
(regexreplace_bounds_its_result).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019Nnsfu3QGqjD1aFZbBgUWP
- Text coercion: digits too many for a finite number are not a number,
and a fraction must come out finite, so "1 <400 digits>/<400 digits>"
(inf/inf) no longer coerces to NaN (test overlong_digits_stay_text).
- VLOOKUP/HLOOKUP and the D-functions' field index refuse NaN, which
passed their "< 1" checks and became index 0, then underflowed
(test nan_index_is_a_value_error; hostile_inputs_never_panic now also
passes NaN and infinity to every function).
- REGEXREPLACE replaces match by match and gives up once the result can
only be too long, instead of building every replacement first: the
32,767 x 32,767 worst case went from 1.05 GB peak to 7 MB
(test regexreplace_bounds_its_result).
#2165 (MAP's size check) is already fixed on main by the broadcast cap
(836b2698, #2182), whose test covers MAP.
Also adds my contributors/people.toml entry.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019Nnsfu3QGqjD1aFZbBgUWP
Excel 365 reads a dollar sign before accounting parentheses ($(1,234),
$ (5)) and a percent sign after them ((5)%) as negative numbers when the
text is typed, coerced by arithmetic or passed to VALUE. GridCraft gave
#VALUE! for these.
The parentheses branch no longer recurses: Excel reads only an unsigned
plain number or fraction inside, so (-5), ((5)), ($-5), and dates or
times in parentheses are now #VALUE! as in Excel (they used to give 5
or a negative serial). $5% is #VALUE! too: Excel never combines the
currency and percent signs.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Thai number words with บาท / สตางค์ / ถ้วน, rounded to satang, ล้าน
repeating per six digits, ลบ for negatives.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>