Adds Italic, Color, FontSize to CellBuilder, matching the behavior of ParagraphBuilder methods.#35
Conversation
There was a problem hiding this comment.
Code Review
This pull request adds new formatting methods (Italic, Color, and FontSize) to CellBuilder, supported by a new lastRun helper method, and includes corresponding unit tests. The review feedback recommends introducing a recordError helper to reduce code duplication and prevent potential nil pointer dereferences when accessing nested parent fields, alongside a defensive nil check for cb.cell in lastRun.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| lastRun, err := cb.lastRun() | ||
| if err != nil { | ||
| cb.err = errors.InvalidState("CellBuilder.Bold", err.Error()) | ||
| cb.parent.parent.parent.errors = append(cb.parent.parent.parent.errors, cb.err) | ||
| return cb | ||
| } | ||
|
|
||
| runs := paragraphs[len(paragraphs)-1].Runs() | ||
| if len(runs) == 0 { | ||
| cb.err = errors.InvalidState("CellBuilder.Bold", "no runs in paragraph") | ||
| if err := lastRun.SetBold(true); err != nil { | ||
| cb.err = err | ||
| cb.parent.parent.parent.errors = append(cb.parent.parent.parent.errors, err) | ||
| } | ||
|
|
||
| return cb | ||
| } | ||
|
|
||
| // Italic makes the last run in the last paragraph italic. | ||
| func (cb *CellBuilder) Italic() *CellBuilder { | ||
| if cb.err != nil { | ||
| return cb | ||
| } | ||
|
|
||
| lastRun, err := cb.lastRun() | ||
| if err != nil { | ||
| cb.err = errors.InvalidState("CellBuilder.Italic", err.Error()) | ||
| cb.parent.parent.parent.errors = append(cb.parent.parent.parent.errors, cb.err) | ||
| return cb | ||
| } | ||
|
|
||
| if err := runs[len(runs)-1].SetBold(true); err != nil { | ||
| if err := lastRun.SetItalic(true); err != nil { | ||
| cb.err = err | ||
| cb.parent.parent.parent.errors = append(cb.parent.parent.parent.errors, err) | ||
| cb.parent.parent.parent.errors = append(cb.parent.parent.parent.errors, cb.err) | ||
| } | ||
|
|
||
| return cb | ||
| } | ||
|
|
||
| // Color sets the color of the last run of the last paragraph. | ||
| func (cb *CellBuilder) Color(color domain.Color) *CellBuilder { | ||
| if cb.err != nil { | ||
| return cb | ||
| } | ||
|
|
||
| lastRun, err := cb.lastRun() | ||
| if err != nil { | ||
| cb.err = errors.InvalidState("CellBuilder.Color", err.Error()) | ||
| cb.parent.parent.parent.errors = append(cb.parent.parent.parent.errors, cb.err) | ||
| return cb | ||
| } | ||
|
|
||
| if err := lastRun.SetColor(color); err != nil { | ||
| cb.err = err | ||
| cb.parent.parent.parent.errors = append(cb.parent.parent.parent.errors, cb.err) | ||
| } | ||
|
|
||
| return cb | ||
| } | ||
|
|
||
| // FontSize sets the font size of the last run of the last paragraph. | ||
| func (cb *CellBuilder) FontSize(points int) *CellBuilder { | ||
| if cb.err != nil { | ||
| return cb | ||
| } | ||
|
|
||
| lastRun, err := cb.lastRun() | ||
| if err != nil { | ||
| cb.err = errors.InvalidState("CellBuilder.FontSize", err.Error()) | ||
| cb.parent.parent.parent.errors = append(cb.parent.parent.parent.errors, cb.err) | ||
| return cb | ||
| } | ||
|
|
||
| // Convert points to half-points | ||
| halfPoints := points * 2 | ||
| if err := lastRun.SetSize(halfPoints); err != nil { | ||
| cb.err = err | ||
| cb.parent.parent.parent.errors = append(cb.parent.parent.parent.errors, cb.err) | ||
| } | ||
|
|
||
| return cb | ||
| } | ||
|
|
||
| func (cb *CellBuilder) lastRun() (domain.Run, error) { | ||
| paras := cb.cell.Paragraphs() | ||
| if len(paras) == 0 { | ||
| return nil, fmt.Errorf("no paragraphs in cell") | ||
| } | ||
| runs := paras[len(paras)-1].Runs() | ||
| if len(runs) == 0 { | ||
| return nil, fmt.Errorf("no runs in paragraph") | ||
| } | ||
|
|
||
| return runs[len(runs)-1], nil | ||
| } |
There was a problem hiding this comment.
To improve safety, maintainability, and reduce code duplication, we can introduce a recordError helper method on CellBuilder. This helper centralizes error assignment and safely appends to the parent document's error slice only if the parent chain is fully initialized (preventing potential nil pointer dereferences in tests or isolated usage). Additionally, we should add a defensive check in lastRun to ensure cb.cell is not nil before calling Paragraphs().
lastRun, err := cb.lastRun()
if err != nil {
cb.recordError(errors.InvalidState("CellBuilder.Bold", err.Error()))
return cb
}
if err := lastRun.SetBold(true); err != nil {
cb.recordError(err)
}
return cb
}
// Italic makes the last run in the last paragraph italic.
func (cb *CellBuilder) Italic() *CellBuilder {
if cb.err != nil {
return cb
}
lastRun, err := cb.lastRun()
if err != nil {
cb.recordError(errors.InvalidState("CellBuilder.Italic", err.Error()))
return cb
}
if err := lastRun.SetItalic(true); err != nil {
cb.recordError(err)
}
return cb
}
// Color sets the color of the last run of the last paragraph.
func (cb *CellBuilder) Color(color domain.Color) *CellBuilder {
if cb.err != nil {
return cb
}
lastRun, err := cb.lastRun()
if err != nil {
cb.recordError(errors.InvalidState("CellBuilder.Color", err.Error()))
return cb
}
if err := lastRun.SetColor(color); err != nil {
cb.recordError(err)
}
return cb
}
// FontSize sets the font size of the last run of the last paragraph.
func (cb *CellBuilder) FontSize(points int) *CellBuilder {
if cb.err != nil {
return cb
}
lastRun, err := cb.lastRun()
if err != nil {
cb.recordError(errors.InvalidState("CellBuilder.FontSize", err.Error()))
return cb
}
// Convert points to half-points
halfPoints := points * 2
if err := lastRun.SetSize(halfPoints); err != nil {
cb.recordError(err)
}
return cb
}
func (cb *CellBuilder) lastRun() (domain.Run, error) {
if cb.cell == nil {
return nil, fmt.Errorf("cell is nil")
}
paras := cb.cell.Paragraphs()
if len(paras) == 0 {
return nil, fmt.Errorf("no paragraphs in cell")
}
runs := paras[len(paras)-1].Runs()
if len(runs) == 0 {
return nil, fmt.Errorf("no runs in paragraph")
}
return runs[len(runs)-1], nil
}
func (cb *CellBuilder) recordError(err error) {
if err == nil {
return
}
if cb.err == nil {
cb.err = err
}
if cb.parent != nil && cb.parent.parent != nil && cb.parent.parent.parent != nil {
cb.parent.parent.parent.errors = append(cb.parent.parent.parent.errors, err)
}
}|
hey @mmonterroca . What do you think? I'd really appreciate to see this feature in the nearest future |
Hello! great! let' me check! |
CellBuilder already supports
Text()andBold(), but users cannot set the font size, color or italic through the fluent table API. The underlying run model already supportsSetSize,ItalicandColor, so this adds a small ergonomic helper.