diff --git a/internal/converter/epub.go b/internal/converter/epub.go index 8a203766..bf929f9f 100644 --- a/internal/converter/epub.go +++ b/internal/converter/epub.go @@ -5,6 +5,7 @@ package converter import ( "crypto/md5" "fmt" + "html" "net/url" "os" "path/filepath" @@ -123,9 +124,7 @@ func ConvertHTMLToEPUB(htmlContent string, outputPath string, options EPUBOption // Prepend source URL if provided if options.SourceURL != "" { - sourceHeader := fmt.Sprintf(`
Source: %s
`, - options.SourceURL, options.SourceURL) - processedHTML = sourceHeader + processedHTML + processedHTML = sourceHeaderHTML(options.SourceURL) + processedHTML } // Add the main content section @@ -144,6 +143,13 @@ func ConvertHTMLToEPUB(htmlContent string, outputPath string, options EPUBOption return nil } +// sourceHeaderHTML renders the attribution line linking back to the source. +func sourceHeaderHTML(sourceURL string) string { + escaped := html.EscapeString(sourceURL) + return fmt.Sprintf(`Source: %s
`, + escaped, escaped) +} + // ConvertHTMLFileToEPUB reads an HTML file and converts it to EPUB. func ConvertHTMLFileToEPUB(htmlPath string, options EPUBOptions) (string, error) { logging.Logf("[EPUB] ConvertHTMLFileToEPUB: processing %s", htmlPath) diff --git a/internal/converter/epub_test.go b/internal/converter/epub_test.go new file mode 100644 index 00000000..48d9de00 --- /dev/null +++ b/internal/converter/epub_test.go @@ -0,0 +1,51 @@ +package converter + +import ( + "strings" + "testing" +) + +func TestSourceHeaderHTMLEscapesURL(t *testing.T) { + tests := []struct { + name string + sourceURL string + unwanted string + }{ + { + name: "quote closing the href attribute", + sourceURL: `https://example.com/x">`, + unwanted: "