Add logo feature
This commit is contained in:
@@ -279,17 +279,19 @@ func generateS3HTML(entries []indexgen.FileEntry, opts *indexgen.Options, client
|
|||||||
|
|
||||||
// Prepare template data (similar to ProcessDir in indexgen)
|
// Prepare template data (similar to ProcessDir in indexgen)
|
||||||
data := struct {
|
data := struct {
|
||||||
DirName string
|
DirName string
|
||||||
Entries []indexgen.FileEntry
|
Entries []indexgen.FileEntry
|
||||||
DirAppend bool
|
DirAppend bool
|
||||||
OutputFile string
|
OutputFile string
|
||||||
IsRoot bool
|
IsRoot bool
|
||||||
|
WatermarkURL string
|
||||||
}{
|
}{
|
||||||
DirName: opts.TopDir, // Use bucket name as directory name
|
DirName: opts.TopDir, // Use bucket name as directory name
|
||||||
Entries: entries,
|
Entries: entries,
|
||||||
DirAppend: opts.DirAppend,
|
DirAppend: opts.DirAppend,
|
||||||
OutputFile: opts.OutputFile,
|
OutputFile: opts.OutputFile,
|
||||||
IsRoot: isRoot,
|
IsRoot: isRoot,
|
||||||
|
WatermarkURL: opts.WatermarkURL,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate HTML content in memory
|
// Generate HTML content in memory
|
||||||
@@ -345,6 +347,7 @@ func main() {
|
|||||||
var s3URL string
|
var s3URL string
|
||||||
var dryRun bool
|
var dryRun bool
|
||||||
var showIndexFiles bool
|
var showIndexFiles bool
|
||||||
|
var watermarkURL string
|
||||||
|
|
||||||
// Set defaults
|
// Set defaults
|
||||||
opts.DirAppend = true
|
opts.DirAppend = true
|
||||||
@@ -359,6 +362,7 @@ func main() {
|
|||||||
flag.StringVar(&excludeRegexStr, "x", "", "exclude files matching regular expression")
|
flag.StringVar(&excludeRegexStr, "x", "", "exclude files matching regular expression")
|
||||||
flag.BoolVar(&opts.Verbose, "v", false, "verbosely list every processed file")
|
flag.BoolVar(&opts.Verbose, "v", false, "verbosely list every processed file")
|
||||||
flag.BoolVar(&showIndexFiles, "i", false, "show index.html files in directory listings")
|
flag.BoolVar(&showIndexFiles, "i", false, "show index.html files in directory listings")
|
||||||
|
flag.StringVar(&watermarkURL, "wm", "", "watermark logo URL to display in top left corner")
|
||||||
|
|
||||||
flag.Usage = func() {
|
flag.Usage = func() {
|
||||||
fmt.Fprintf(os.Stderr, "Generate directory index files (recursive is ON, hidden files included by default).\n")
|
fmt.Fprintf(os.Stderr, "Generate directory index files (recursive is ON, hidden files included by default).\n")
|
||||||
@@ -398,9 +402,10 @@ func main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set dry run and show index files flags
|
// Set dry run, show index files, and watermark URL
|
||||||
opts.DryRun = dryRun
|
opts.DryRun = dryRun
|
||||||
opts.ShowIndexFiles = showIndexFiles
|
opts.ShowIndexFiles = showIndexFiles
|
||||||
|
opts.WatermarkURL = watermarkURL
|
||||||
|
|
||||||
if s3URL != "" {
|
if s3URL != "" {
|
||||||
// Parse S3 URL
|
// Parse S3 URL
|
||||||
|
|||||||
@@ -168,6 +168,7 @@ type Options struct {
|
|||||||
Verbose bool
|
Verbose bool
|
||||||
DryRun bool
|
DryRun bool
|
||||||
ShowIndexFiles bool
|
ShowIndexFiles bool
|
||||||
|
WatermarkURL string
|
||||||
}
|
}
|
||||||
|
|
||||||
type FileEntry struct {
|
type FileEntry struct {
|
||||||
@@ -211,17 +212,19 @@ func ProcessDir(topDir string, opts *Options) error {
|
|||||||
})
|
})
|
||||||
|
|
||||||
templateData := struct {
|
templateData := struct {
|
||||||
DirName string
|
DirName string
|
||||||
Entries []FileEntry
|
Entries []FileEntry
|
||||||
DirAppend bool
|
DirAppend bool
|
||||||
OutputFile string
|
OutputFile string
|
||||||
IsRoot bool
|
IsRoot bool
|
||||||
|
WatermarkURL string
|
||||||
}{
|
}{
|
||||||
DirName: dirName,
|
DirName: dirName,
|
||||||
Entries: entries,
|
Entries: entries,
|
||||||
DirAppend: opts.DirAppend,
|
DirAppend: opts.DirAppend,
|
||||||
OutputFile: opts.OutputFile,
|
OutputFile: opts.OutputFile,
|
||||||
IsRoot: false, // Local filesystem always shows parent directory
|
IsRoot: false, // Local filesystem always shows parent directory
|
||||||
|
WatermarkURL: opts.WatermarkURL,
|
||||||
}
|
}
|
||||||
|
|
||||||
if opts.DryRun {
|
if opts.DryRun {
|
||||||
@@ -467,6 +470,15 @@ const htmlTemplateString = `<!DOCTYPE html>
|
|||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
color: #999;
|
color: #999;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.watermark {
|
||||||
|
height: 24px;
|
||||||
|
width: auto;
|
||||||
|
margin-right: 8px;
|
||||||
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
|
||||||
h1 a {
|
h1 a {
|
||||||
@@ -943,7 +955,7 @@ const htmlTemplateString = `<!DOCTYPE html>
|
|||||||
</defs>
|
</defs>
|
||||||
</svg>
|
</svg>
|
||||||
<header>
|
<header>
|
||||||
<h1>{{.DirName}}</h1>
|
<h1>{{if .WatermarkURL}}<img src="{{.WatermarkURL}}" class="watermark" alt="Logo">{{end}}{{.DirName}}</h1>
|
||||||
</header>
|
</header>
|
||||||
<main>
|
<main>
|
||||||
<div class="listing">
|
<div class="listing">
|
||||||
|
|||||||
@@ -97,17 +97,19 @@ func TestHTMLTemplate(t *testing.T) {
|
|||||||
|
|
||||||
// Test template execution with sample data
|
// Test template execution with sample data
|
||||||
data := struct {
|
data := struct {
|
||||||
DirName string
|
DirName string
|
||||||
Entries []FileEntry
|
Entries []FileEntry
|
||||||
DirAppend bool
|
DirAppend bool
|
||||||
OutputFile string
|
OutputFile string
|
||||||
IsRoot bool
|
IsRoot bool
|
||||||
|
WatermarkURL string
|
||||||
}{
|
}{
|
||||||
DirName: "test-dir",
|
DirName: "test-dir",
|
||||||
Entries: []FileEntry{},
|
Entries: []FileEntry{},
|
||||||
DirAppend: false,
|
DirAppend: false,
|
||||||
OutputFile: "index.html",
|
OutputFile: "index.html",
|
||||||
IsRoot: false,
|
IsRoot: false,
|
||||||
|
WatermarkURL: "",
|
||||||
}
|
}
|
||||||
|
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
@@ -159,17 +161,19 @@ func TestHTMLTemplateWithEntries(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
data := struct {
|
data := struct {
|
||||||
DirName string
|
DirName string
|
||||||
Entries []FileEntry
|
Entries []FileEntry
|
||||||
DirAppend bool
|
DirAppend bool
|
||||||
OutputFile string
|
OutputFile string
|
||||||
IsRoot bool
|
IsRoot bool
|
||||||
|
WatermarkURL string
|
||||||
}{
|
}{
|
||||||
DirName: "test-dir",
|
DirName: "test-dir",
|
||||||
Entries: entries,
|
Entries: entries,
|
||||||
DirAppend: false,
|
DirAppend: false,
|
||||||
OutputFile: "index.html",
|
OutputFile: "index.html",
|
||||||
IsRoot: false,
|
IsRoot: false,
|
||||||
|
WatermarkURL: "",
|
||||||
}
|
}
|
||||||
|
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
@@ -196,6 +200,62 @@ func TestHTMLTemplateWithEntries(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestHTMLTemplateWithWatermark(t *testing.T) {
|
||||||
|
tmpl := GetHTMLTemplate()
|
||||||
|
if tmpl == nil {
|
||||||
|
t.Fatal("GetHTMLTemplate() returned nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test template execution with watermark
|
||||||
|
data := struct {
|
||||||
|
DirName string
|
||||||
|
Entries []FileEntry
|
||||||
|
DirAppend bool
|
||||||
|
OutputFile string
|
||||||
|
IsRoot bool
|
||||||
|
WatermarkURL string
|
||||||
|
}{
|
||||||
|
DirName: "test-dir",
|
||||||
|
Entries: []FileEntry{},
|
||||||
|
DirAppend: false,
|
||||||
|
OutputFile: "index.html",
|
||||||
|
IsRoot: false,
|
||||||
|
WatermarkURL: "https://example.com/logo.svg",
|
||||||
|
}
|
||||||
|
|
||||||
|
var buf bytes.Buffer
|
||||||
|
err := tmpl.Execute(&buf, data)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Template execution with watermark failed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
output := buf.String()
|
||||||
|
|
||||||
|
// Check that watermark image is included
|
||||||
|
if !bytes.Contains([]byte(output), []byte(`src="https://example.com/logo.svg"`)) {
|
||||||
|
t.Error("Template output should contain watermark image URL")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !bytes.Contains([]byte(output), []byte(`class="watermark"`)) {
|
||||||
|
t.Error("Template output should contain watermark CSS class")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test without watermark
|
||||||
|
data.WatermarkURL = ""
|
||||||
|
buf.Reset()
|
||||||
|
err = tmpl.Execute(&buf, data)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Template execution without watermark failed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
outputNoWatermark := buf.String()
|
||||||
|
|
||||||
|
// Check that watermark image is NOT included when URL is empty
|
||||||
|
if bytes.Contains([]byte(outputNoWatermark), []byte(`class="watermark"`)) {
|
||||||
|
t.Error("Template output should not contain watermark when URL is empty")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestReadDirEntries(t *testing.T) {
|
func TestReadDirEntries(t *testing.T) {
|
||||||
// Create a temporary directory with test files
|
// Create a temporary directory with test files
|
||||||
tempDir := t.TempDir()
|
tempDir := t.TempDir()
|
||||||
|
|||||||
Reference in New Issue
Block a user