From 6317ce268b71463342b9b14a0ab81d4dc7cde3c8 Mon Sep 17 00:00:00 2001 From: Kaj Kowalski Date: Thu, 6 Nov 2025 03:55:07 +0100 Subject: [PATCH] refactor(exporters): replace deprecated strings.Title with cases.Title The `strings.Title` function is deprecated because it does not handle Unicode punctuation correctly. This change replaces its usage in the DOCX, HTML, and Markdown exporters with the recommended `golang.org/x/text/cases` package. This ensures more robust and accurate title-casing for item headings. --- go.mod | 5 ++++- go.sum | 2 ++ internal/exporters/docx.go | 5 ++++- internal/exporters/html.go | 5 ++++- internal/exporters/markdown.go | 5 ++++- 5 files changed, 18 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index be2de2b..964d893 100644 --- a/go.mod +++ b/go.mod @@ -2,7 +2,10 @@ module github.com/kjanat/articulate-parser go 1.24.0 -require github.com/fumiama/go-docx v0.0.0-20250506085032-0c30fd09304b +require ( + github.com/fumiama/go-docx v0.0.0-20250506085032-0c30fd09304b + golang.org/x/text v0.30.0 +) require ( github.com/fumiama/imgsz v0.0.4 // indirect diff --git a/go.sum b/go.sum index a03a79a..eb4ab92 100644 --- a/go.sum +++ b/go.sum @@ -4,3 +4,5 @@ github.com/fumiama/imgsz v0.0.4 h1:Lsasu2hdSSFS+vnD+nvR1UkiRMK7hcpyYCC0FzgSMFI= github.com/fumiama/imgsz v0.0.4/go.mod h1:bISOQVTlw9sRytPwe8ir7tAaEmyz9hSNj9n8mXMBG0E= golang.org/x/image v0.32.0 h1:6lZQWq75h7L5IWNk0r+SCpUJ6tUVd3v4ZHnbRKLkUDQ= golang.org/x/image v0.32.0/go.mod h1:/R37rrQmKXtO6tYXAjtDLwQgFLHmhW+V6ayXlxzP2Pc= +golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k= +golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM= diff --git a/internal/exporters/docx.go b/internal/exporters/docx.go index a6488eb..8ac0b7b 100644 --- a/internal/exporters/docx.go +++ b/internal/exporters/docx.go @@ -11,6 +11,8 @@ import ( "github.com/kjanat/articulate-parser/internal/interfaces" "github.com/kjanat/articulate-parser/internal/models" "github.com/kjanat/articulate-parser/internal/services" + "golang.org/x/text/cases" + "golang.org/x/text/language" ) // DocxExporter implements the Exporter interface for DOCX format. @@ -119,7 +121,8 @@ func (e *DocxExporter) exportItem(doc *docx.Docx, item *models.Item) { // Add item type as heading if item.Type != "" { itemPara := doc.AddParagraph() - itemPara.AddText(strings.Title(item.Type)).Size("24").Bold() + caser := cases.Title(language.English) + itemPara.AddText(caser.String(item.Type)).Size("24").Bold() } // Add sub-items diff --git a/internal/exporters/html.go b/internal/exporters/html.go index c8c4b0f..04ba217 100644 --- a/internal/exporters/html.go +++ b/internal/exporters/html.go @@ -12,6 +12,8 @@ import ( "github.com/kjanat/articulate-parser/internal/interfaces" "github.com/kjanat/articulate-parser/internal/models" "github.com/kjanat/articulate-parser/internal/services" + "golang.org/x/text/cases" + "golang.org/x/text/language" ) // HTMLExporter implements the Exporter interface for HTML format. @@ -441,7 +443,8 @@ func (e *HTMLExporter) processDividerItem(buf *bytes.Buffer) { func (e *HTMLExporter) processUnknownItem(buf *bytes.Buffer, item models.Item) { if len(item.Items) > 0 { buf.WriteString("
\n") - buf.WriteString(fmt.Sprintf("

%s Content

\n", strings.Title(item.Type))) + caser := cases.Title(language.English) + buf.WriteString(fmt.Sprintf("

%s Content

\n", caser.String(item.Type))) for _, subItem := range item.Items { e.processGenericSubItem(buf, subItem) } diff --git a/internal/exporters/markdown.go b/internal/exporters/markdown.go index 776b575..d67bf0d 100644 --- a/internal/exporters/markdown.go +++ b/internal/exporters/markdown.go @@ -11,6 +11,8 @@ import ( "github.com/kjanat/articulate-parser/internal/interfaces" "github.com/kjanat/articulate-parser/internal/models" "github.com/kjanat/articulate-parser/internal/services" + "golang.org/x/text/cases" + "golang.org/x/text/language" ) // MarkdownExporter implements the Exporter interface for Markdown format. @@ -269,7 +271,8 @@ func (e *MarkdownExporter) processDividerItem(buf *bytes.Buffer) { // processUnknownItem handles unknown or unsupported item types func (e *MarkdownExporter) processUnknownItem(buf *bytes.Buffer, item models.Item, headingPrefix string) { if len(item.Items) > 0 { - buf.WriteString(fmt.Sprintf("%s %s Content\n\n", headingPrefix, strings.Title(item.Type))) + caser := cases.Title(language.English) + buf.WriteString(fmt.Sprintf("%s %s Content\n\n", headingPrefix, caser.String(item.Type))) for _, subItem := range item.Items { e.processGenericSubItem(buf, subItem) }