* 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>
Security-sweep findings from the scan at revision ac8da7d4 (storytold-
gridcraft-agent-findings.json), no longer exploitable on main at 72c1d57d.
Each change caps work or storage per sheet/part so a hostile file cannot buy
unbounded work with ordinary bytes; each has a regression test:
- finding 2 (package.rs): a part rejected by the MAX_PART size gate is
charged its declared compressed size up front, so a loop of oversized
parts still ends the allowance instead of re-entering the package.
- finding 4 (xml.rs): elements past the kept-node cap are consumed and
dropped instead of kept — parse cost stays linear, memory stops growing
with the same input (a small compressed workbook previously asked for
gigabytes of declared-sized metadata tree).
- finding 10 (records.rs): .remaining() caches the suffix of a shared
string's Continue parts, so crossing N Continue records is O(N) instead
of O(N^2) in records scanned per character.
- finding 9 (xls shared formulas): the SHRFMLA master template is parsed
once and re-emitted per dependent cell instead of decoded and reprinted
for every referencing cell.
- findings 3, 6, 8 (sheet_read.rs): hyperlink-cell expansion, conditional-
format kept range cells and dynamic-array (deleted-spill) checks are
capped with one import warning each instead of the compact-workbook
multi-gigabyte allocation or the scanned-per-cell cost.
- finding 31 (core/parse.rs): datetime recognition no longer reparses a
prefix at every space with a time-shaped tail; an all-digit field length
is gated before the derivation machinery runs, staying linear in the
text.
🤖 Generated with Codebuff
Co-authored-by: Codebuff <noreply@codebuff.com>
Sheet names starting with '.' or reading as R1C1 (R, C, RC, R1C1...) were saved
unquoted, so Excel could not open the file; PivotTable sources and ADDRESS left
cell-like names (A1) bare. The quoting rule, unquoting and sheet splitting now
live once in gridcraft_core::addr and replace the copies in the formula printer,
pivot, ADDRESS, chart, xlsx, Solver, Go To and the Name Box (which now reads ''
as ').
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
A category range two or more columns wide beside a column of values (year beside month, Excel's
multiLvlStrRef) was read as one flat list: 36 rows in two columns became 72 categories, the
series sat in the left half of the plot and the years and months shared one row of labels.
Saving wrote the range as a plain strRef, so Excel lost the two-level axis too.
- gridcraft_core::category_levels: the shape of a category range beside its values (levels are
columns when the points run down the rows, rows when they run along the columns; up to three
outer levels), shared by the chart and xlsx crates.
- ChartData.category_levels: the outer levels, nearest the labels first, one entry per category,
non-empty where a group starts. resolve fills it; a single column is unchanged.
- render: the outer levels in rows under the labels, a group's name centred under its categories
with a separator at each boundary; in bar charts in columns beside the labels.
- xlsx: <c:cat> written as multiLvlStrRef with the level caches (innermost first), so the axis
survives a round trip.
Tests in core (shapes), chart (resolve and layout for columns, bars and a row of values) and
xlsx (written XML, read-back, stability, a single column stays strRef). chart-parity, gaps § 4
and the ROADMAP progress log updated.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>