Skip to content

feat: prepare calamine-styles for maintained promotion - #1

Draft
wolfiesch wants to merge 68 commits into
masterfrom
styles
Draft

feat: prepare calamine-styles for maintained promotion#1
wolfiesch wants to merge 68 commits into
masterfrom
styles

Conversation

@wolfiesch

@wolfiesch wolfiesch commented Aug 31, 2026

Copy link
Copy Markdown
Collaborator

Purpose

Promote the actual calamine-styles implementation branch into the repository's default source line.

The current default branch is an unchanged upstream snapshot, while WolfXL Community consumes the separately published calamine-styles crate. Keeping the implementation only on an unreviewed side branch makes source ownership, CI status, and release provenance ambiguous.

Current contents

  • style model and XLSX style parser
  • styled-cell reader integration
  • examples, benchmarks, and style fixtures
  • crate identity calamine-styles 0.1.0
  • Rust and typo workflows

Required before merge

  • rebase the fork onto current supported upstream Calamine rather than the old 0.33-era base
  • repair all Rust/typo CI failures
  • correct package repository metadata to the canonical SynthGL location
  • document the maintained delta and upstreaming strategy
  • generate release provenance/SBOM for the next crate release
  • verify WolfXL/Community against the rebased crate

Exact-head validation

At f4d43585cc5cb7e2bafc1bca4e4b9882cfb1f596:

  • exact-head Rust 1.83 (declared MSRV), stable, beta, and nightly build/test lanes pass
  • exact-head typo checks pass
  • local stable and Rust 1.83 cargo test --all-features pass: 80 library tests, 133 integration tests with 1 ignored, and 60 documentation tests with 1 ignored
  • local cargo fmt --all -- --check, strict all-target/all-feature Clippy, Rust 1.83 all-target/all-feature check, cargo package --allow-dirty, and git diff --check pass
  • value-only range/formula reads avoid discarded per-cell Style clones while the public styled streaming API remains styled
  • StyleRange constructs sparse runs without materializing the bounding rectangle, reserves sparse-gap slot zero, uses u32 run IDs without the prior u16 aliasing, and indexes cumulative run endpoints for O(log runs) random access
  • worksheet_style() compacts the workbook palette to distinct styles used by the sheet; an explicit s="0" retains real cellXfs style zero while an omitted style remains unstyled
  • populated cells without an explicit s inherit effective formatting with cell > customFormat row > column precedence; inherited number formats also drive value conversion, and the column lookup is bounded to 16,384 entries
  • cells with no explicit or inherited style use cell XF 0 for typed value conversion while StyleRange retains the omitted-vs-explicit/inherited representation distinction
  • trait-dispatched worksheet layout delegates to the corrected parser; grouped column spans, OOXML booleans, bounds, and implicit row indexes are covered
  • metadata-only column records inherit the worksheet or library default width, while an explicit zero width remains zero
  • metadata-only row records inherit the worksheet or library default height, while an explicit zero height remains zero; implicit and explicit row indexes are covered
  • cell XFs honor explicit false values for all six apply* formatting flags while preserving the branch's omitted-flag compatibility behavior
  • cell XFs resolve valid cellStyleXfs[xfId] bases before overrides, so false apply flags retain inherited font, fill, border, number format, alignment, protection, and CellFormat
  • indexed colors use zero-based OOXML offsets and bounded workbook overrides in cell styles, shared rich text, and inline rich text
  • workbook theme relationships resolve the actual internal theme part; theme slots and finite in-range tints follow SpreadsheetML/OOXML ordering and transforms
  • rich text retains numeric conversions and all string-compatible serde paths (char, bytes, byte buffers, and enums), including Unicode scalar chars
  • Data and DataRef rich-text values compare to str/&str by concatenated run text without allocating
  • explicit rich-text off/none run properties remain present so they can override inherited formatting rather than collapsing to plain strings
  • Style::has_visible_properties() includes font name, size, family, underline, strikethrough, and number formats in addition to the existing visible fields
  • font emphasis honors omitted/true/false OOXML booleans, rotation 255 maps to stacked text, and present protection records retain Excel's default locked behavior
  • only invariant built-in number-format codes are exposed; locale-dependent or unknown IDs preserve their source ID with a documented empty code
  • custom number-format codes preserve decoded OOXML format-language escapes in public NumberFormat::format_code and use that same faithful code for typed value conversion
  • diagonal directions come from the parent <border> attributes, including self-closing diagonal sides and malformed-boolean rejection
  • standard mediumDashDot and mediumDashDotDot borders have distinct public BorderStyle variants; this intentional enum expansion is an exhaustive-match API consideration for the maintained release
  • valid centerContinuous alignment has a distinct public HorizontalAlignment::CenterContinuous variant; focused coverage audits every SpreadsheetML horizontal and vertical alignment token, and this intentional enum expansion is another exhaustive-match API consideration for the maintained release
  • the README and STYLE_FEATURE.md document the real worksheet_style() -> StyleRange API, its relative coordinates, concrete color/alignment types, and value/style separation; replacement guide examples were compile-checked
  • formatted inline strings preserve rich-text runs, explicitly empty inline strings remain present, and font-only shared-string runs stay rich
  • XLS, XLSB, and ODS style/layout calls distinguish valid unsupported sheets from unknown names
  • all inline review findings through the completed 7535dcd review have commit-and-test replies and are resolved; an exact-head re-review is required before readiness

Exact-head Rust run · Exact-head typo run

This establishes a green, packageable 0.33-era fork baseline. Current upstream reports Calamine 0.36.1 with Rust 1.88, so the rebase must explicitly resolve both API delta and whether the fork retains Rust 1.83 or adopts the newer floor. It does not establish current-upstream parity; the upstream rebase, downstream verification, and release provenance remain merge blockers.

This PR is intentionally draft: it makes the real source delta visible and reviewable, but should not merge until the upstream and CI gates above are complete.


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

ddimaria and others added 30 commits July 23, 2025 12:44
Resolved conflicts:
- src/xlsx/cells_reader.rs: Kept fork's style support, added upstream's shared_index fix for non-monotonic si numbers
- src/xlsx/mod.rs: Kept fork's full style parsing (fonts, fills, borders, alignment), integrated upstream's Reference enum for better shared formula handling
- tests/test.rs: Kept fork's style tests, added upstream's tests for issues tafia#573, tafia#587, tafia#589, tafia#594

New upstream features merged:
- Shared formula fixes for row/column ranges (E:F, 5:6)
- Absolute reference handling in shared formulas
- Non-monotonic si number support
- ODS DoS protection via cell limits
- Table loading improvements
- Fixed shared formula offset calculation by properly looking up base formulas
  and applying offset using replace_cell_names function
- Fixed chart worksheet detection (NotAWorksheet error) to return empty range
  instead of XmlEof error for non-worksheet sheets

Fixes tests: issue_391_shared_formula, non_monotonic_si_shared_formula,
shared_formula_reversed, column_row_ranges, issue_565_multi_axis_shared_formula,
issue_567_absolute_shared_formula, issue_438_charts
Resolves merge conflicts in Cargo.toml (rstest version) and
tests/test.rs (pivot table tests vs style tests — keep both).

This merge adds:
- Style struct with Font/Fill/Borders/Alignment/NumberFormat/Protection
- styles.xml parser (src/xlsx/style_parser.rs)
- worksheet_style() API returning row×col style grid
- RLE-compressed StyleRange for memory efficiency

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Set package.name = "calamine-styles" with version 0.1.0
- Add crate metadata: description, keywords, authors
- Replace README with calamine-styles specific docs

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

Copy link
Copy Markdown
Collaborator Author

@codex review

Please review exact head 1361d58135bff8a775bc6ab6044fa28ad53b964a. Exact-head Rust 1.83/stable/beta/nightly and typo runs are green; all inline threads have commit-and-test evidence and are resolved. The PR intentionally remains draft because the upstream rebase, downstream verification, and release-provenance gates remain open.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1361d58135

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/xlsx/style_parser.rs Outdated
Comment thread src/xlsx/style_parser.rs Outdated
Comment thread src/xlsx/style_parser.rs Outdated
Parse font emphasis booleans, map text rotation 255 to stacked text, and preserve the default locked protection state. Reject malformed values with focused regressions.

Copy link
Copy Markdown
Collaborator Author

@codex review

Please re-review exact head 934f220bc75607e614182a5dc8d4027865185ff7. The three findings from the prior review are fixed with focused tests and commit evidence; exact-head Rust 1.83/stable/beta/nightly and typo runs are green, and all 25 inline threads are resolved. Keep this PR draft—the upstream rebase gates remain open.

Clarify that omitted locked/hidden behavior is supplied by Excel rather than declared as a CT_CellProtection schema default.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 934f220bc7

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/xlsx/mod.rs Outdated
Comment thread src/xlsx/mod.rs Outdated
Comment thread src/de.rs

Copy link
Copy Markdown
Collaborator Author

@codex review

Please review final exact head 0a2f351f0bafa19ec42aa8bc721e7cb862656192. This differs from 934f220 only by a precision correction identifying omitted protection behavior as Excel behavior rather than a CT_CellProtection schema default. Exact-head Rust 1.83/stable/beta/nightly and typo runs are green; all 25 inline threads remain resolved. Keep the PR draft due the documented upstream/downstream/provenance gates.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0a2f351f0b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/xlsx/cells_reader.rs Outdated
Comment thread src/xlsx/mod.rs Outdated
Comment thread src/style.rs Outdated
Comment thread src/xlsx/mod.rs Outdated
Comment thread STYLE_FEATURE.md Outdated
Honor explicit OOXML apply flags when materializing styles, compact each worksheet palette to the styles it actually uses, and expose rich-text plain values through all string-compatible serde deserializers.

Add focused regressions for explicit false/true apply flags, sparse repeated style IDs, multi-run rich text, and Unicode scalar chars.
Keep an explicit cellXfs index zero distinct from an omitted style, preserve rich-text run properties that explicitly disable inherited formatting, and recognize all visible font and number-format properties.

Track implicit SpreadsheetML row indexes, add focused regressions, and replace the style guide's value-range examples with compile-checked StyleRange usage.

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c8b8575607

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/datatype.rs
Comment thread src/xlsx/mod.rs
Compare owned and borrowed rich-text values to strings by their concatenated run text without allocating, and align all DataRef string variants with those semantics.

Keep absent column widths distinct from explicit zero, resolving metadata-only column records through the worksheet or library default with focused regressions.

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 97a8ef6881

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/xlsx/mod.rs Outdated
Keep an omitted row height distinct from explicit zero, resolving hidden and border-metadata rows through the worksheet or library default while preserving valid zero and historical malformed-height behavior.

Cover worksheet and library defaults, explicit and implicit row indexes, explicit zero, and malformed metadata cases.

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 31a7151350

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/xlsx/cells_reader.rs Outdated
Comment thread src/xlsx/mod.rs Outdated
Comment thread src/xlsx/style_parser.rs
Preserve effective row and column styles for cells without an explicit
cell XF, including number-format conversion. Resolve cellStyleXfs bases
before applying cell-XF overrides, and expose both standard medium
dash-dot border variants.

Add focused regressions for precedence, inherited formats, all apply
flags, and border token mappings.

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ac0ce40069

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/xlsx/cells_reader.rs
Comment thread src/style.rs Outdated
Use cell XF zero for value conversion when a cell omits its style
attribute without conflating omitted and explicit/inherited styles in
StyleRange. Index cumulative RLE run endpoints so random style access is
logarithmic rather than scanning from the first run.

Add regressions for the XF-zero representation boundary and 4,096
alternating run boundaries with iterator/get consistency.

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: cc6e1582b5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/xlsx/style_parser.rs
Represent SpreadsheetML centerContinuous explicitly and verify every
horizontal and vertical alignment token remains distinct.

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7535dcdf7c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/xlsx/mod.rs Outdated
Expose decoded custom format codes without stripping their format-language
escapes, while continuing to use the same raw code for value conversion.

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f4d43585cc

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/xlsx/style_parser.rs
for attr in e.attributes() {
let attr = attr?;
if attr.key.as_ref() == b"val" {
name = Some(String::from_utf8_lossy(&attr.value).to_string());

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Decode XML entities in font names

When a font name contains an XML-escaped character, such as <name val="A&amp;B"/>, Attribute::value still contains the encoded attribute text, so this stores A&amp;B rather than the actual font name A&B. The rich-text rFont path uses the same raw conversion, causing both worksheet styles and formatted text runs to expose incorrect names; decode and unescape the attribute with the XML reader's decoder.

Useful? React with 👍 / 👎.

Comment thread src/xlsx/style_parser.rs
Comment on lines +177 to +180
let (red, green, blue) = OOXML_INDEXED_COLORS
.get(usize::from(index))
.copied()
.unwrap_or((0, 0, 0));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Handle the indexed system-background color

For a valid color using indexed="65", SpreadsheetML defines this reserved index as the system background color, but the 64-entry lookup falls through here and resolves every out-of-range index to black. Fonts, fills, borders, or rich-text runs using index 65 are therefore exposed with the foreground color instead of the expected background color; handle the reserved system foreground/background indices separately rather than mapping both through the black fallback.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants