diff --git a/cmd/files.go b/cmd/files.go
index 5e2320f..223e0c5 100644
--- a/cmd/files.go
+++ b/cmd/files.go
@@ -34,6 +34,11 @@ var (
extensions = [6]string{".jpg", ".jpeg", ".png", ".gif", ".webp", ".bmp"}
)
+type Dimensions struct {
+ Width int
+ Height int
+}
+
type Files struct {
Mutex sync.Mutex
List map[string][]string
@@ -105,21 +110,21 @@ func humanReadableSize(bytes int) string {
float64(bytes)/float64(div), "KMGTPE"[exp])
}
-func getImageDimensions(path string) (string, error) {
+func getImageDimensions(path string) (*Dimensions, error) {
file, err := os.Open(path)
if err != nil {
- return "", err
+ return &Dimensions{}, err
}
defer file.Close()
myImage, _, err := image.DecodeConfig(file)
if errors.Is(err, image.ErrFormat) {
- return "", nil
+ return &Dimensions{Width: 0, Height: 0}, nil
} else if err != nil {
- return "", err
+ return &Dimensions{}, err
}
- return fmt.Sprintf("%vx%v", myImage.Width, myImage.Height), nil
+ return &Dimensions{Width: myImage.Width, Height: myImage.Height}, nil
}
func preparePath(path string) string {
@@ -336,7 +341,7 @@ func pathIsValid(filePath string, paths []string) bool {
switch {
case Verbose && !matchesPrefix:
fmt.Printf("%v | Error: Failed to serve file outside specified path(s): %v\n",
- time.Now().Format(LOGDATE),
+ time.Now().Format(LogDate),
filePath,
)
@@ -489,7 +494,7 @@ func pickFile(args []string, filters *Filters, sort string, fileCache *[]string)
if Verbose {
fmt.Printf("%v | Scanned %v/%v files across %v directories in %v\n",
- time.Now().Format(LOGDATE),
+ time.Now().Format(LogDate),
stats.GetFilesMatched(),
stats.GetFilesTotal(),
stats.GetDirectoriesMatched(),
diff --git a/cmd/version.go b/cmd/version.go
index 651270b..35394a0 100644
--- a/cmd/version.go
+++ b/cmd/version.go
@@ -10,7 +10,7 @@ import (
"github.com/spf13/cobra"
)
-var Version = "0.23.1"
+var Version = "0.24.0"
func init() {
rootCmd.AddCommand(versionCmd)
diff --git a/cmd/web.go b/cmd/web.go
index 1f8a09a..7b71f11 100644
--- a/cmd/web.go
+++ b/cmd/web.go
@@ -17,12 +17,18 @@ import (
"strconv"
"strings"
"time"
+
+ "github.com/yosssi/gohtml"
)
const (
- LOGDATE string = "2006-01-02T15:04:05.000-07:00"
- PREFIX string = "/src"
+ LogDate string = `2006-01-02T15:04:05.000-07:00`
+ Prefix string = `/src`
RedirectStatusCode int = http.StatusSeeOther
+
+ // You may not like it, but this is what peak string generation looks like.
+ RefreshScriptTemplate string = ``
+ HtmlTemplate string = `
%v (%vx%v)%v`
)
type Filters struct {
@@ -167,7 +173,7 @@ func stripQueryParams(u string) (string, error) {
}
func generateFilePath(filePath string) string {
- htmlBody := PREFIX
+ htmlBody := Prefix
if runtime.GOOS == "windows" {
htmlBody += "/"
}
@@ -186,7 +192,7 @@ func refererToUri(referer string) string {
return "/" + parts[3]
}
-func serveHtml(w http.ResponseWriter, r *http.Request, filePath, dimensions string, filters *Filters) error {
+func serveHtml(w http.ResponseWriter, r *http.Request, filePath string, dimensions *Dimensions, filters *Filters) error {
fileName := filepath.Base(filePath)
w.Header().Add("Content-Type", "text/html")
@@ -198,43 +204,33 @@ func serveHtml(w http.ResponseWriter, r *http.Request, filePath, dimensions stri
queryParams, err := generateQueryParams(filters, r.URL.Query().Get("sort"), refreshInterval)
- htmlBody := `
-
-
- `
- htmlBody += fmt.Sprintf("%v (%v)", fileName, dimensions)
- htmlBody += `
-
-
- `
+ refreshScript := ""
if refreshInterval != "0" {
r, err := strconv.Atoi(refreshInterval)
if err != nil {
return err
}
refreshTimer := strconv.Itoa(r * 1000)
- htmlBody += `
- `
+ refreshScript = fmt.Sprintf(RefreshScriptTemplate,
+ queryParams,
+ refreshTimer)
}
- htmlBody += `
-
-`
- _, err = io.WriteString(w, htmlBody)
+ htmlBody := fmt.Sprintf(HtmlTemplate,
+ fileName,
+ dimensions.Width,
+ dimensions.Height,
+ queryParams,
+ generateFilePath(filePath),
+ dimensions.Width,
+ dimensions.Height,
+ fileName,
+ refreshScript,
+ )
+
+ formattedBody := gohtml.Format(htmlBody)
+
+ _, err = io.WriteString(w, formattedBody)
if err != nil {
return err
}
@@ -243,12 +239,12 @@ func serveHtml(w http.ResponseWriter, r *http.Request, filePath, dimensions stri
}
func serveStaticFile(w http.ResponseWriter, r *http.Request, paths []string) error {
- prefixedFilePath, err := stripQueryParams(r.URL.Path)
+ PrefixedFilePath, err := stripQueryParams(r.URL.Path)
if err != nil {
return err
}
- filePath, err := filepath.EvalSymlinks(strings.TrimPrefix(prefixedFilePath, PREFIX))
+ filePath, err := filepath.EvalSymlinks(strings.TrimPrefix(PrefixedFilePath, Prefix))
if err != nil {
return err
}
@@ -279,7 +275,7 @@ func serveStaticFile(w http.ResponseWriter, r *http.Request, paths []string) err
if Verbose {
fmt.Printf("%v | Served %v (%v) to %v in %v\n",
- startTime.Format(LOGDATE),
+ startTime.Format(LogDate),
filePath,
humanReadableSize(len(buf)),
r.RemoteAddr,
@@ -406,7 +402,7 @@ func ServePage(args []string) error {
fileCache := []string{}
http.Handle("/", serveHtmlHandler(paths, *re, &fileCache))
- http.Handle(PREFIX+"/", http.StripPrefix(PREFIX, serveStaticFileHandler(paths)))
+ http.Handle(Prefix+"/", http.StripPrefix(Prefix, serveStaticFileHandler(paths)))
http.HandleFunc("/favicon.ico", doNothing)
err = http.ListenAndServe(":"+strconv.FormatInt(int64(Port), 10), nil)
diff --git a/go.mod b/go.mod
index 675d869..5f86cc7 100644
--- a/go.mod
+++ b/go.mod
@@ -5,10 +5,12 @@ go 1.19
require (
github.com/h2non/filetype v1.1.3
github.com/spf13/cobra v1.6.1
+ github.com/yosssi/gohtml v0.0.0-20201013000340-ee4748c638f4
golang.org/x/image v0.1.0
)
require (
github.com/inconshreveable/mousetrap v1.0.1 // indirect
github.com/spf13/pflag v1.0.5 // indirect
+ golang.org/x/net v0.0.0-20220722155237-a158d28d115b // indirect
)
diff --git a/go.sum b/go.sum
index 0194ad9..90a6b9c 100644
--- a/go.sum
+++ b/go.sum
@@ -8,6 +8,8 @@ github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA=
github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
+github.com/yosssi/gohtml v0.0.0-20201013000340-ee4748c638f4 h1:0sw0nJM544SpsihWx1bkXdYLQDlzRflMgFJQ4Yih9ts=
+github.com/yosssi/gohtml v0.0.0-20201013000340-ee4748c638f4/go.mod h1:+ccdNT0xMY1dtc5XBxumbYfOUhmduiGudqaDgD2rVRE=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
@@ -16,6 +18,7 @@ golang.org/x/image v0.1.0/go.mod h1:iyPr49SD/G/TBxYVB/9RRtGUT5eNbo2u4NamWeQcD5c=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
+golang.org/x/net v0.0.0-20220722155237-a158d28d115b h1:PxfKdU9lEEDYjdIzOtC4qFWgkU2rGHdKlKowJSMN9h0=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
diff --git a/vendor/github.com/yosssi/gohtml/.gitignore b/vendor/github.com/yosssi/gohtml/.gitignore
new file mode 100644
index 0000000..8365624
--- /dev/null
+++ b/vendor/github.com/yosssi/gohtml/.gitignore
@@ -0,0 +1,23 @@
+# Compiled Object files, Static and Dynamic libs (Shared Objects)
+*.o
+*.a
+*.so
+
+# Folders
+_obj
+_test
+
+# Architecture specific extensions/prefixes
+*.[568vq]
+[568vq].out
+
+*.cgo1.go
+*.cgo2.c
+_cgo_defun.c
+_cgo_gotypes.go
+_cgo_export.*
+
+_testmain.go
+
+*.exe
+*.test
diff --git a/vendor/github.com/yosssi/gohtml/LICENSE b/vendor/github.com/yosssi/gohtml/LICENSE
new file mode 100644
index 0000000..73f313c
--- /dev/null
+++ b/vendor/github.com/yosssi/gohtml/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014 Keiji Yoshida
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
\ No newline at end of file
diff --git a/vendor/github.com/yosssi/gohtml/README.md b/vendor/github.com/yosssi/gohtml/README.md
new file mode 100644
index 0000000..34da207
--- /dev/null
+++ b/vendor/github.com/yosssi/gohtml/README.md
@@ -0,0 +1,194 @@
+# GoHTML - HTML formatter for Go
+
+[![wercker status](https://app.wercker.com/status/926cf3edc004271539be40d705d037bd/s "wercker status")](https://app.wercker.com/project/bykey/926cf3edc004271539be40d705d037bd)
+[![GoDoc](http://godoc.org/github.com/yosssi/gohtml?status.png)](http://godoc.org/github.com/yosssi/gohtml)
+
+GoHTML is an HTML formatter for [Go](http://golang.org/). You can format HTML source codes by using this package.
+
+## Install
+
+```
+go get -u github.com/yosssi/gohtml
+```
+
+## Example
+
+Example Go source code:
+
+```go
+package main
+
+import (
+ "fmt"
+
+ "github.com/yosssi/gohtml"
+)
+
+func main() {
+ h := `This is a title.`
+ fmt.Println(gohtml.Format(h))
+}
+```
+
+Output:
+
+```html
+
+
+
+
+ This is a title.
+
+
+
+
+
+
+
+
+
+```
+
+## Output Formatted HTML with Line No
+
+You can output formatted HTML source codes with line no by calling `FormatWithLineNo`:
+
+```go
+package main
+
+import (
+ "fmt"
+
+ "github.com/yosssi/gohtml"
+)
+
+func main() {
+ h := `This is a title.`
+ fmt.Println(gohtml.FormatWithLineNo(h))
+}
+```
+
+Output:
+
+```sh
+ 1
+ 2
+ 3
+ 4
+ 5 This is a title.
+ 6
+ 7
+13
+20
+21
+22
+30
+31
+32
+```
+
+## Format Go html/template Package's Template's Execute Result
+
+You can format [Go html/template package](http://golang.org/pkg/html/template/)'s template's execute result by passing `Writer` to the `tpl.Execute`:
+
+```go
+package main
+
+import (
+ "os"
+ "text/template"
+
+ "github.com/yosssi/gohtml"
+)
+
+func main() {
+
+ tpl, err := template.New("test").Parse("{{.Msg}}")
+
+ if err != nil {
+ panic(err)
+ }
+
+ data := map[string]interface{}{"Msg": "Hello!"}
+
+ err = tpl.Execute(gohtml.NewWriter(os.Stdout), data)
+
+ if err != nil {
+ panic(err)
+ }
+}
+```
+
+Output:
+
+```html
+
+
+
+
+ Hello!
+
+
+```
+
+## Docs
+
+* [GoDoc](https://godoc.org/github.com/yosssi/gohtml)
diff --git a/vendor/github.com/yosssi/gohtml/consts.go b/vendor/github.com/yosssi/gohtml/consts.go
new file mode 100644
index 0000000..625118c
--- /dev/null
+++ b/vendor/github.com/yosssi/gohtml/consts.go
@@ -0,0 +1,7 @@
+package gohtml
+
+const (
+ defaultIndentString = " "
+ startIndent = 0
+ defaultLastElement = "