Skip to content

Commit b56c9fa

Browse files
committed
refactor: Align with Go conventions and improve maintainability
Renames the `OriginalUrl` field to `OriginalURL` across media models to adhere to Go's common initialisms convention. The `json` tag is unchanged to maintain API compatibility. Introduces constants for exporter formats (e.g., `FormatMarkdown`, `FormatDocx`) to eliminate the use of magic strings, enhancing type safety and making the code easier to maintain. Additionally, this commit includes several minor code quality improvements: - Wraps file-writing errors in exporters to provide more context. - Removes redundant package-level comments from test files. - Applies various minor linting fixes throughout the codebase.
1 parent d8e4d97 commit b56c9fa

26 files changed

+53
-77
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -467,7 +467,7 @@ jobs:
467467
# Process a local file (mount current directory)
468468
docker run --rm -v $(pwd):/workspace ghcr.io/${{ github.repository }}:latest /workspace/input.json markdown /workspace/output.md
469469
```
470-
470+
471471
EOF
472472
473473
# Security and quality analysis workflows

internal/config/config_test.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
// Package config_test provides tests for the config package.
21
package config
32

43
import (

internal/exporters/bench_test.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
// Package exporters_test provides benchmarks for all exporters.
21
package exporters
32

43
import (

internal/exporters/docx.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ func (e *DocxExporter) Export(course *models.Course, outputPath string) error {
6969

7070
// Ensure output directory exists and add .docx extension
7171
if !strings.HasSuffix(strings.ToLower(outputPath), ".docx") {
72-
outputPath = outputPath + ".docx"
72+
outputPath += ".docx"
7373
}
7474

7575
// Create the file
@@ -198,5 +198,5 @@ func (e *DocxExporter) exportSubItem(doc *docx.Docx, subItem *models.SubItem) {
198198
// Returns:
199199
// - A string representing the supported format ("docx")
200200
func (e *DocxExporter) SupportedFormat() string {
201-
return "docx"
201+
return FormatDocx
202202
}

internal/exporters/docx_test.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
// Package exporters_test provides tests for the docx exporter.
21
package exporters
32

43
import (
@@ -331,7 +330,7 @@ func TestDocxExporter_ComplexCourse(t *testing.T) {
331330
Caption: "<p>Watch this introductory video</p>",
332331
Media: &models.Media{
333332
Video: &models.VideoMedia{
334-
OriginalUrl: "https://example.com/intro.mp4",
333+
OriginalURL: "https://example.com/intro.mp4",
335334
Duration: 300,
336335
},
337336
},
@@ -359,7 +358,7 @@ func TestDocxExporter_ComplexCourse(t *testing.T) {
359358
Caption: "<p>Course overview diagram</p>",
360359
Media: &models.Media{
361360
Image: &models.ImageMedia{
362-
OriginalUrl: "https://example.com/overview.png",
361+
OriginalURL: "https://example.com/overview.png",
363362
},
364363
},
365364
},

internal/exporters/factory.go

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
// Package exporters provides implementations of the Exporter interface
2-
// for converting Articulate Rise courses into various file formats.
31
package exporters
42

53
import (
@@ -10,6 +8,13 @@ import (
108
"github.com/kjanat/articulate-parser/internal/services"
119
)
1210

11+
// Format constants for supported export formats.
12+
const (
13+
FormatMarkdown = "markdown"
14+
FormatDocx = "docx"
15+
FormatHTML = "html"
16+
)
17+
1318
// Factory implements the ExporterFactory interface.
1419
// It creates appropriate exporter instances based on the requested format.
1520
type Factory struct {
@@ -36,11 +41,11 @@ func NewFactory(htmlCleaner *services.HTMLCleaner) interfaces.ExporterFactory {
3641
// Format strings are case-insensitive (e.g., "markdown", "DOCX").
3742
func (f *Factory) CreateExporter(format string) (interfaces.Exporter, error) {
3843
switch strings.ToLower(format) {
39-
case "markdown", "md":
44+
case FormatMarkdown, "md":
4045
return NewMarkdownExporter(f.htmlCleaner), nil
41-
case "docx", "word":
46+
case FormatDocx, "word":
4247
return NewDocxExporter(f.htmlCleaner), nil
43-
case "html", "htm":
48+
case FormatHTML, "htm":
4449
return NewHTMLExporter(f.htmlCleaner), nil
4550
default:
4651
return nil, fmt.Errorf("unsupported export format: %s", format)
@@ -50,5 +55,5 @@ func (f *Factory) CreateExporter(format string) (interfaces.Exporter, error) {
5055
// SupportedFormats returns a list of all supported export formats,
5156
// including both primary format names and their aliases.
5257
func (f *Factory) SupportedFormats() []string {
53-
return []string{"markdown", "md", "docx", "word", "html", "htm"}
58+
return []string{FormatMarkdown, "md", FormatDocx, "word", FormatHTML, "htm"}
5459
}

internal/exporters/factory_test.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
// Package exporters_test provides tests for the exporter factory.
21
package exporters
32

43
import (

internal/exporters/html.go

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
// Package exporters provides implementations of the Exporter interface
2-
// for converting Articulate Rise courses into various file formats.
31
package exporters
42

53
import (
@@ -112,7 +110,10 @@ func (e *HTMLExporter) Export(course *models.Course, outputPath string) error {
112110
buf.WriteString("</html>\n")
113111

114112
// #nosec G306 - 0644 is appropriate for export files that should be readable by others
115-
return os.WriteFile(outputPath, buf.Bytes(), 0o644)
113+
if err := os.WriteFile(outputPath, buf.Bytes(), 0o644); err != nil {
114+
return fmt.Errorf("failed to write HTML file: %w", err)
115+
}
116+
return nil
116117
}
117118

118119
// SupportedFormat returns the format name this exporter supports
@@ -121,7 +122,7 @@ func (e *HTMLExporter) Export(course *models.Course, outputPath string) error {
121122
// Returns:
122123
// - A string representing the supported format ("html")
123124
func (e *HTMLExporter) SupportedFormat() string {
124-
return "html"
125+
return FormatHTML
125126
}
126127

127128
// getDefaultCSS returns basic CSS styling for the HTML document.
@@ -390,7 +391,7 @@ func (e *HTMLExporter) processMultimediaItem(buf *bytes.Buffer, item models.Item
390391
if subItem.Media != nil {
391392
if subItem.Media.Video != nil {
392393
buf.WriteString(" <div class=\"media-info\">\n")
393-
fmt.Fprintf(buf, " <p><strong>Video:</strong> %s</p>\n", html.EscapeString(subItem.Media.Video.OriginalUrl))
394+
fmt.Fprintf(buf, " <p><strong>Video:</strong> %s</p>\n", html.EscapeString(subItem.Media.Video.OriginalURL))
394395
if subItem.Media.Video.Duration > 0 {
395396
fmt.Fprintf(buf, " <p><strong>Duration:</strong> %d seconds</p>\n", subItem.Media.Video.Duration)
396397
}
@@ -411,7 +412,7 @@ func (e *HTMLExporter) processImageItem(buf *bytes.Buffer, item models.Item) {
411412
for _, subItem := range item.Items {
412413
if subItem.Media != nil && subItem.Media.Image != nil {
413414
buf.WriteString(" <div class=\"media-info\">\n")
414-
fmt.Fprintf(buf, " <p><strong>Image:</strong> %s</p>\n", html.EscapeString(subItem.Media.Image.OriginalUrl))
415+
fmt.Fprintf(buf, " <p><strong>Image:</strong> %s</p>\n", html.EscapeString(subItem.Media.Image.OriginalURL))
415416
buf.WriteString(" </div>\n")
416417
}
417418
if subItem.Caption != "" {

internal/exporters/html_test.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
// Package exporters_test provides tests for the html exporter.
21
package exporters
32

43
import (
@@ -270,7 +269,7 @@ func TestHTMLExporter_ProcessMultimediaItem(t *testing.T) {
270269
Title: "<p>Video Title</p>",
271270
Media: &models.Media{
272271
Video: &models.VideoMedia{
273-
OriginalUrl: "https://example.com/video.mp4",
272+
OriginalURL: "https://example.com/video.mp4",
274273
Duration: 120,
275274
},
276275
},
@@ -315,7 +314,7 @@ func TestHTMLExporter_ProcessImageItem(t *testing.T) {
315314
{
316315
Media: &models.Media{
317316
Image: &models.ImageMedia{
318-
OriginalUrl: "https://example.com/image.png",
317+
OriginalURL: "https://example.com/image.png",
319318
},
320319
},
321320
Caption: "<p>Image caption</p>",

internal/exporters/markdown.go

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
// Package exporters provides implementations of the Exporter interface
2-
// for converting Articulate Rise courses into various file formats.
31
package exporters
42

53
import (
@@ -82,12 +80,15 @@ func (e *MarkdownExporter) Export(course *models.Course, outputPath string) erro
8280
}
8381

8482
// #nosec G306 - 0644 is appropriate for export files that should be readable by others
85-
return os.WriteFile(outputPath, buf.Bytes(), 0o644)
83+
if err := os.WriteFile(outputPath, buf.Bytes(), 0o644); err != nil {
84+
return fmt.Errorf("failed to write markdown file: %w", err)
85+
}
86+
return nil
8687
}
8788

8889
// SupportedFormat returns "markdown".
8990
func (e *MarkdownExporter) SupportedFormat() string {
90-
return "markdown"
91+
return FormatMarkdown
9192
}
9293

9394
// processItemToMarkdown converts a course item into Markdown format.
@@ -170,7 +171,7 @@ func (e *MarkdownExporter) processMediaSubItem(buf *bytes.Buffer, subItem models
170171
// processVideoMedia processes video media content.
171172
func (e *MarkdownExporter) processVideoMedia(buf *bytes.Buffer, media *models.Media) {
172173
if media.Video != nil {
173-
fmt.Fprintf(buf, "**Video**: %s\n", media.Video.OriginalUrl)
174+
fmt.Fprintf(buf, "**Video**: %s\n", media.Video.OriginalURL)
174175
if media.Video.Duration > 0 {
175176
fmt.Fprintf(buf, "**Duration**: %d seconds\n", media.Video.Duration)
176177
}
@@ -180,7 +181,7 @@ func (e *MarkdownExporter) processVideoMedia(buf *bytes.Buffer, media *models.Me
180181
// processImageMedia processes image media content.
181182
func (e *MarkdownExporter) processImageMedia(buf *bytes.Buffer, media *models.Media) {
182183
if media.Image != nil {
183-
fmt.Fprintf(buf, "**Image**: %s\n", media.Image.OriginalUrl)
184+
fmt.Fprintf(buf, "**Image**: %s\n", media.Image.OriginalURL)
184185
}
185186
}
186187

@@ -189,7 +190,7 @@ func (e *MarkdownExporter) processImageItem(buf *bytes.Buffer, item models.Item,
189190
fmt.Fprintf(buf, "%s Image\n\n", headingPrefix)
190191
for _, subItem := range item.Items {
191192
if subItem.Media != nil && subItem.Media.Image != nil {
192-
fmt.Fprintf(buf, "**Image**: %s\n", subItem.Media.Image.OriginalUrl)
193+
fmt.Fprintf(buf, "**Image**: %s\n", subItem.Media.Image.OriginalURL)
193194
}
194195
if subItem.Caption != "" {
195196
caption := e.htmlCleaner.CleanHTML(subItem.Caption)

0 commit comments

Comments
 (0)