diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 34169db..4b1bbde 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -286,7 +286,7 @@ jobs: } >> "$GITHUB_STEP_SUMMARY" - name: Upload coverage reports to Codecov - uses: codecov/codecov-action@v5 + uses: codecov/codecov-action@v7 with: files: ./coverage/coverage.out flags: Go ${{ env.GO_VERSION }} @@ -401,7 +401,7 @@ jobs: - name: Extract metadata id: meta - uses: docker/metadata-action@v5 + uses: docker/metadata-action@v6 with: images: | ${{ env.IMAGE_NAME }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1c9d888..7d1ca73 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -111,7 +111,7 @@ jobs: - name: Extract metadata id: meta - uses: docker/metadata-action@v5 + uses: docker/metadata-action@v6 with: images: | ${{ env.IMAGE_NAME }} diff --git a/.golangci.yml b/.golangci.yml index 8e3f690..97e730b 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -346,15 +346,16 @@ linters: # stylecheck settings staticcheck: - checks: [ - "all", - "-ST1000", - "-ST1003", - "-ST1016", - "-ST1020", - "-ST1021", - "-ST1022", - ] + checks: + [ + "all", + "-ST1000", + "-ST1003", + "-ST1016", + "-ST1020", + "-ST1021", + "-ST1022", + ] # maintidx settings maintidx: diff --git a/internal/exporters/example_test.go b/internal/exporters/example_test.go index aaa63bb..66760ad 100644 --- a/internal/exporters/example_test.go +++ b/internal/exporters/example_test.go @@ -12,15 +12,19 @@ import ( "github.com/kjanat/articulate-parser/internal/services" ) -// tempOutput returns a path inside a fresh temp dir plus a cleanup func, so -// example exports don't pollute the package source tree. Example functions -// can't take *testing.T, so t.TempDir is unavailable here. -func tempOutput(name string) (path string, cleanup func()) { +// exportToTemp runs export against a path in a fresh temp dir and removes the +// dir afterwards. Example functions can't take *testing.T, so t.TempDir is +// unavailable here. +func exportToTemp(name string, export func(path string) error) { dir, err := os.MkdirTemp("", "exporters-example-*") if err != nil { log.Fatal(err) } - return filepath.Join(dir, name), func() { _ = os.RemoveAll(dir) } + err = export(filepath.Join(dir, name)) + _ = os.RemoveAll(dir) + if err != nil { + log.Fatal(err) + } } // ExampleNewFactory demonstrates creating an exporter factory. @@ -82,12 +86,9 @@ func ExampleMarkdownExporter_Export() { } // Export to markdown file - out, cleanup := tempOutput("output.md") - defer cleanup() - err := exporter.Export(course, out) - if err != nil { - log.Fatal(err) - } + exportToTemp("output.md", func(path string) error { + return exporter.Export(course, path) + }) fmt.Println("Export complete") // Output: Export complete @@ -106,12 +107,9 @@ func ExampleDocxExporter_Export() { } // Export to Word document - out, cleanup := tempOutput("output.docx") - defer cleanup() - err := exporter.Export(course, out) - if err != nil { - log.Fatal(err) - } + exportToTemp("output.docx", func(path string) error { + return exporter.Export(course, path) + }) fmt.Println("DOCX export complete") // Output: DOCX export complete @@ -138,12 +136,9 @@ func ExampleHTMLExporter_Export() { } // Export to HTML file - out, cleanup := tempOutput("output.html") - defer cleanup() - err := exporter.Export(course, out) - if err != nil { - log.Fatal(err) - } + exportToTemp("output.html", func(path string) error { + return exporter.Export(course, path) + }) fmt.Println("HTML export complete") // Output: HTML export complete diff --git a/internal/exporters/html_styles.css b/internal/exporters/html_styles.css index fd06f64..7952763 100644 --- a/internal/exporters/html_styles.css +++ b/internal/exporters/html_styles.css @@ -1,181 +1,175 @@ body { - font-family: - -apple-system, - BlinkMacSystemFont, - "Segoe UI", - Roboto, - Oxygen, - Ubuntu, - Cantarell, - sans-serif; - line-height: 1.6; - color: #333; - max-width: 800px; - margin: 0 auto; - padding: 20px; - background-color: #f9f9f9; + font-family: + -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, + Cantarell, sans-serif; + line-height: 1.6; + color: #333; + max-width: 800px; + margin: 0 auto; + padding: 20px; + background-color: #f9f9f9; } header { - background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); - color: white; - padding: 2rem; - border-radius: 10px; - margin-bottom: 2rem; - box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + color: white; + padding: 2rem; + border-radius: 10px; + margin-bottom: 2rem; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); } header h1 { - margin: 0; - font-size: 2.5rem; - font-weight: 300; + margin: 0; + font-size: 2.5rem; + font-weight: 300; } .course-description { - margin-top: 1rem; - font-size: 1.1rem; - opacity: 0.9; + margin-top: 1rem; + font-size: 1.1rem; + opacity: 0.9; } .course-info { - background: white; - padding: 1.5rem; - border-radius: 8px; - margin-bottom: 2rem; - box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); + background: white; + padding: 1.5rem; + border-radius: 8px; + margin-bottom: 2rem; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); } .course-info h2 { - margin-top: 0; - color: #4a5568; - border-bottom: 2px solid #e2e8f0; - padding-bottom: 0.5rem; + margin-top: 0; + color: #4a5568; + border-bottom: 2px solid #e2e8f0; + padding-bottom: 0.5rem; } .course-info ul { - list-style: none; - padding: 0; + list-style: none; + padding: 0; } .course-info li { - margin: 0.5rem 0; - padding: 0.5rem; - background: #f7fafc; - border-radius: 4px; + margin: 0.5rem 0; + padding: 0.5rem; + background: #f7fafc; + border-radius: 4px; } .course-section { - background: #4299e1; - color: white; - padding: 1.5rem; - border-radius: 8px; - margin: 2rem 0; - box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); + background: #4299e1; + color: white; + padding: 1.5rem; + border-radius: 8px; + margin: 2rem 0; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); } .course-section h2 { - margin: 0; - font-weight: 400; + margin: 0; + font-weight: 400; } .lesson { - background: white; - padding: 2rem; - border-radius: 8px; - margin: 2rem 0; - box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); - border-left: 4px solid #4299e1; + background: white; + padding: 2rem; + border-radius: 8px; + margin: 2rem 0; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); + border-left: 4px solid #4299e1; } .lesson h3 { - margin-top: 0; - color: #2d3748; - font-size: 1.5rem; + margin-top: 0; + color: #2d3748; + font-size: 1.5rem; } .lesson-description { - margin: 1rem 0; - padding: 1rem; - background: #f7fafc; - border-radius: 4px; - border-left: 3px solid #4299e1; + margin: 1rem 0; + padding: 1rem; + background: #f7fafc; + border-radius: 4px; + border-left: 3px solid #4299e1; } .item { - margin: 1.5rem 0; - padding: 1rem; - border-radius: 6px; - background: #fafafa; - border: 1px solid #e2e8f0; + margin: 1.5rem 0; + padding: 1rem; + border-radius: 6px; + background: #fafafa; + border: 1px solid #e2e8f0; } .item h4 { - margin-top: 0; - color: #4a5568; - font-size: 1.2rem; - text-transform: capitalize; + margin-top: 0; + color: #4a5568; + font-size: 1.2rem; + text-transform: capitalize; } .text-item { - background: #f0fff4; - border-left: 3px solid #48bb78; + background: #f0fff4; + border-left: 3px solid #48bb78; } .list-item { - background: #fffaf0; - border-left: 3px solid #ed8936; + background: #fffaf0; + border-left: 3px solid #ed8936; } .knowledge-check { - background: #e6fffa; - border-left: 3px solid #38b2ac; + background: #e6fffa; + border-left: 3px solid #38b2ac; } .multimedia-item { - background: #faf5ff; - border-left: 3px solid #9f7aea; + background: #faf5ff; + border-left: 3px solid #9f7aea; } .interactive-item { - background: #fff5f5; - border-left: 3px solid #f56565; + background: #fff5f5; + border-left: 3px solid #f56565; } .unknown-item { - background: #f7fafc; - border-left: 3px solid #a0aec0; + background: #f7fafc; + border-left: 3px solid #a0aec0; } .answers { - margin: 1rem 0; + margin: 1rem 0; } .answers h5 { - margin: 0.5rem 0; - color: #4a5568; + margin: 0.5rem 0; + color: #4a5568; } .answers ol { - margin: 0.5rem 0; - padding-left: 1.5rem; + margin: 0.5rem 0; + padding-left: 1.5rem; } .answers li { - margin: 0.3rem 0; - padding: 0.3rem; + margin: 0.3rem 0; + padding: 0.3rem; } .correct-answer { - background: #c6f6d5; - border-radius: 3px; - font-weight: bold; + background: #c6f6d5; + border-radius: 3px; + font-weight: bold; } .correct-answer::after { - content: " ✓"; - color: #38a169; + content: " ✓"; + color: #38a169; } .feedback { - margin: 1rem 0; - padding: 1rem; - background: #edf2f7; - border-radius: 4px; - border-left: 3px solid #4299e1; - font-style: italic; + margin: 1rem 0; + padding: 1rem; + background: #edf2f7; + border-radius: 4px; + border-left: 3px solid #4299e1; + font-style: italic; } .media-info { - background: #edf2f7; - padding: 1rem; - border-radius: 4px; - margin: 0.5rem 0; + background: #edf2f7; + padding: 1rem; + border-radius: 4px; + margin: 0.5rem 0; } .media-info strong { - color: #4a5568; + color: #4a5568; } hr { - border: none; - height: 2px; - background: linear-gradient(to right, #667eea, #764ba2); - margin: 2rem 0; - border-radius: 1px; + border: none; + height: 2px; + background: linear-gradient(to right, #667eea, #764ba2); + margin: 2rem 0; + border-radius: 1px; } ul { - padding-left: 1.5rem; + padding-left: 1.5rem; } li { - margin: 0.5rem 0; + margin: 0.5rem 0; }