diff --git a/cmd/root.go b/cmd/root.go index 0a04b4e..4561b21 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -12,7 +12,7 @@ import ( ) const ( - ReleaseVersion string = "0.73.1" + ReleaseVersion string = "0.74.0" ) var ( diff --git a/cmd/web.go b/cmd/web.go index 93ca041..03e02c0 100644 --- a/cmd/web.go +++ b/cmd/web.go @@ -313,27 +313,27 @@ func ServePage(args []string) error { formats := &types.Types{ Extensions: make(map[string]string), - MimeTypes: make(map[string]*types.Type), + MimeTypes: make(map[string]types.Type), } if Audio || All { - formats.Add(types.RegisterAudio()) + formats.Add(types.Audio{}) } if Flash || All { - formats.Add(types.RegisterFlash()) + formats.Add(types.Flash{}) } if Images || All { - formats.Add(types.RegisterImages()) + formats.Add(types.Images{}) } if Text || All { - formats.Add(types.RegisterText()) + formats.Add(types.Text{}) } if Videos || All { - formats.Add(types.RegisterVideos()) + formats.Add(types.Video{}) } paths, err := normalizePaths(args, formats) diff --git a/types/audio.go b/types/audio.go index bfe6671..8b3fdd2 100644 --- a/types/audio.go +++ b/types/audio.go @@ -9,41 +9,48 @@ import ( "strings" ) -func RegisterAudio() *Type { - return &Type{ - Css: func() string { - var css strings.Builder +type Audio struct{} - css.WriteString(`html,body{margin:0;padding:0;height:100%;}`) - css.WriteString(`a{color:inherit;display:block;height:100%;width:100%;text-decoration:none;}`) +func (t Audio) Css() string { + var css strings.Builder - return css.String() - }, - Title: func(queryParams, fileUri, filePath, fileName, mime string) string { - return fmt.Sprintf(`%s`, fileName) - }, - Body: func(queryParams, fileUri, filePath, fileName, mime string) string { - return fmt.Sprintf(``, - queryParams, - fileUri, - mime, - fileName) - }, - Extensions: map[string]string{ - `.mp3`: `audio/mpeg`, - `.ogg`: `audio/ogg`, - `.oga`: `audio/ogg`, - }, - MimeTypes: []string{ - `application/ogg`, - `audio/mp3`, - `audio/mpeg`, - `audio/mpeg3`, - `audio/ogg`, - `audio/x-mpeg-3`, - }, - Validate: func(filePath string) bool { - return true - }, + css.WriteString(`html,body{margin:0;padding:0;height:100%;}`) + css.WriteString(`a{color:inherit;display:block;height:100%;width:100%;text-decoration:none;}`) + + return css.String() +} + +func (t Audio) Title(queryParams, fileUri, filePath, fileName, mime string) string { + return fmt.Sprintf(`%s`, fileName) +} + +func (t Audio) Body(queryParams, fileUri, filePath, fileName, mime string) string { + return fmt.Sprintf(``, + queryParams, + fileUri, + mime, + fileName) +} + +func (t Audio) Extensions() map[string]string { + return map[string]string{ + `.mp3`: `audio/mpeg`, + `.ogg`: `audio/ogg`, + `.oga`: `audio/ogg`, } } + +func (t Audio) MimeTypes() []string { + return []string{ + `application/ogg`, + `audio/mp3`, + `audio/mpeg`, + `audio/mpeg3`, + `audio/ogg`, + `audio/x-mpeg-3`, + } +} + +func (t Audio) Validate(filePath string) bool { + return true +} diff --git a/types/flash.go b/types/flash.go index ca38ecc..31a2eaa 100644 --- a/types/flash.go +++ b/types/flash.go @@ -9,35 +9,42 @@ import ( "strings" ) -func RegisterFlash() *Type { - return &Type{ - Css: func() string { - var css strings.Builder +type Flash struct{} - css.WriteString(`html,body{margin:0;padding:0;height:100%;}`) - css.WriteString(`a{color:inherit;display:block;height:100%;width:100%;text-decoration:none;}`) +func (t Flash) Css() string { + var css strings.Builder - return css.String() - }, - Title: func(queryParams, fileUri, filePath, fileName, mime string) string { - return fmt.Sprintf(`%s`, fileName) - }, - Body: func(queryParams, fileUri, filePath, fileName, mime string) string { - var html strings.Builder + css.WriteString(`html,body{margin:0;padding:0;height:100%;}`) + css.WriteString(`a{color:inherit;display:block;height:100%;width:100%;text-decoration:none;}`) - html.WriteString(fmt.Sprintf(``, fileUri)) - html.WriteString(fmt.Sprintf(`
`, queryParams)) + return css.String() +} - return html.String() - }, - Extensions: map[string]string{ - `.swf`: `application/x-shockwave-flash`, - }, - MimeTypes: []string{ - `application/x-shockwave-flash`, - }, - Validate: func(filePath string) bool { - return true - }, +func (t Flash) Title(queryParams, fileUri, filePath, fileName, mime string) string { + return fmt.Sprintf(`%s`, fileName) +} + +func (t Flash) Body(queryParams, fileUri, filePath, fileName, mime string) string { + var html strings.Builder + + html.WriteString(fmt.Sprintf(``, fileUri)) + html.WriteString(fmt.Sprintf(`
`, queryParams)) + + return html.String() +} + +func (t Flash) Extensions() map[string]string { + return map[string]string{ + `.swf`: `application/x-shockwave-flash`, } } + +func (t Flash) MimeTypes() []string { + return []string{ + `application/x-shockwave-flash`, + } +} + +func (t Flash) Validate(filePath string) bool { + return true +} diff --git a/types/images.go b/types/images.go index 9f75870..8ee0041 100644 --- a/types/images.go +++ b/types/images.go @@ -23,71 +23,78 @@ type Dimensions struct { Height int } -func RegisterImages() *Type { - return &Type{ - Css: func() string { - var css strings.Builder +type Images struct{} - css.WriteString(`html,body{margin:0;padding:0;height:100%;}`) - css.WriteString(`a{color:inherit;display:block;height:100%;width:100%;text-decoration:none;}`) - css.WriteString(`img{margin:auto;display:block;max-width:97%;max-height:97%;`) - css.WriteString(`object-fit:scale-down;position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);}`) +func (t Images) Css() string { + var css strings.Builder - return css.String() - }, - Title: func(queryParams, fileUri, filePath, fileName, mime string) string { - dimensions, err := ImageDimensions(filePath) - if err != nil { - fmt.Println(err) - } + css.WriteString(`html,body{margin:0;padding:0;height:100%;}`) + css.WriteString(`a{color:inherit;display:block;height:100%;width:100%;text-decoration:none;}`) + css.WriteString(`img{margin:auto;display:block;max-width:97%;max-height:97%;`) + css.WriteString(`object-fit:scale-down;position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);}`) - return fmt.Sprintf(`%s (%dx%d)`, - fileName, - dimensions.Width, - dimensions.Height) - }, - Body: func(queryParams, fileUri, filePath, fileName, mime string) string { - dimensions, err := ImageDimensions(filePath) - if err != nil { - fmt.Println(err) - } + return css.String() +} - return fmt.Sprintf(`Roulette selected: %s`, - queryParams, - fileUri, - dimensions.Width, - dimensions.Height, - mime, - fileName) - }, - Extensions: map[string]string{ - `.apng`: `image/apng`, - `.avif`: `image/avif`, - `.bmp`: `image/bmp`, - `.gif`: `image/gif`, - `.jpg`: `image/jpeg`, - `.jpeg`: `image/jpeg`, - `.jfif`: `image/jpeg`, - `.pjp`: `image/jpeg`, - `.pjpeg`: `image/jpeg`, - `.png`: `image/png`, - `.svg`: `image/svg+xml`, - `.webp`: `image/webp`, - }, - MimeTypes: []string{ - `image/apng`, - `image/avif`, - `image/bmp`, - `image/gif`, - `image/jpeg`, - `image/png`, - `image/svg+xml`, - `image/webp`, - }, - Validate: func(filePath string) bool { - return true - }, +func (t Images) Title(queryParams, fileUri, filePath, fileName, mime string) string { + dimensions, err := ImageDimensions(filePath) + if err != nil { + fmt.Println(err) } + + return fmt.Sprintf(`%s (%dx%d)`, + fileName, + dimensions.Width, + dimensions.Height) +} + +func (t Images) Body(queryParams, fileUri, filePath, fileName, mime string) string { + dimensions, err := ImageDimensions(filePath) + if err != nil { + fmt.Println(err) + } + + return fmt.Sprintf(`Roulette selected: %s`, + queryParams, + fileUri, + dimensions.Width, + dimensions.Height, + mime, + fileName) +} + +func (t Images) Extensions() map[string]string { + return map[string]string{ + `.apng`: `image/apng`, + `.avif`: `image/avif`, + `.bmp`: `image/bmp`, + `.gif`: `image/gif`, + `.jpg`: `image/jpeg`, + `.jpeg`: `image/jpeg`, + `.jfif`: `image/jpeg`, + `.pjp`: `image/jpeg`, + `.pjpeg`: `image/jpeg`, + `.png`: `image/png`, + `.svg`: `image/svg+xml`, + `.webp`: `image/webp`, + } +} + +func (t Images) MimeTypes() []string { + return []string{ + `image/apng`, + `image/avif`, + `image/bmp`, + `image/gif`, + `image/jpeg`, + `image/png`, + `image/svg+xml`, + `image/webp`, + } +} + +func (t Images) Validate(filePath string) bool { + return true } func ImageDimensions(path string) (*Dimensions, error) { diff --git a/types/text.go b/types/text.go index 75b6e9c..e5c3fec 100644 --- a/types/text.go +++ b/types/text.go @@ -12,64 +12,71 @@ import ( "unicode/utf8" ) -func RegisterText() *Type { - return &Type{ - Css: func() string { - var css strings.Builder +type Text struct{} - css.WriteString(`html,body{margin:0;padding:0;height:100%;}`) - css.WriteString(`a{color:inherit;display:block;height:100%;width:100%;text-decoration:none;overflow:hidden;}`) - css.WriteString(`textarea{border:none;caret-color:transparent;outline:none;margin:.5rem;`) - css.WriteString(`height:99%;width:99%;white-space:pre;overflow:auto;}`) +func (t Text) Css() string { + var css strings.Builder - return css.String() - }, - Title: func(queryParams, fileUri, filePath, fileName, mime string) string { - return fmt.Sprintf(`%s`, fileName) - }, - Body: func(queryParams, fileUri, filePath, fileName, mime string) string { - body, err := os.ReadFile(filePath) - if err != nil { - body = []byte{} - } + css.WriteString(`html,body{margin:0;padding:0;height:100%;}`) + css.WriteString(`a{color:inherit;display:block;height:100%;width:100%;text-decoration:none;overflow:hidden;}`) + css.WriteString(`textarea{border:none;caret-color:transparent;outline:none;margin:.5rem;`) + css.WriteString(`height:99%;width:99%;white-space:pre;overflow:auto;}`) - return fmt.Sprintf(``, - queryParams, - body) - }, - Extensions: map[string]string{ - `.css`: `text/css`, - `.csv`: `text/csv`, - `.html`: `text/html`, - `.js`: `text/javascript`, - `.json`: `application/json`, - `.md`: `text/markdown`, - `.txt`: `text/plain`, - `.xml`: `application/xml`, - }, - MimeTypes: []string{ - `application/json`, - `application/xml`, - `text/css`, - `text/csv`, - `text/javascript`, - `text/plain`, - `text/plain; charset=utf-8`, - }, - Validate: func(path string) bool { - file, err := os.Open(path) - switch { - case errors.Is(err, os.ErrNotExist): - return false - case err != nil: - return false - } - defer file.Close() + return css.String() +} - head := make([]byte, 512) - file.Read(head) +func (t Text) Title(queryParams, fileUri, filePath, fileName, mime string) string { + return fmt.Sprintf(`%s`, fileName) +} - return utf8.Valid(head) - }, +func (t Text) Body(queryParams, fileUri, filePath, fileName, mime string) string { + body, err := os.ReadFile(filePath) + if err != nil { + body = []byte{} + } + + return fmt.Sprintf(``, + queryParams, + body) +} + +func (t Text) Extensions() map[string]string { + return map[string]string{ + `.css`: `text/css`, + `.csv`: `text/csv`, + `.html`: `text/html`, + `.js`: `text/javascript`, + `.json`: `application/json`, + `.md`: `text/markdown`, + `.txt`: `text/plain`, + `.xml`: `application/xml`, } } + +func (t Text) MimeTypes() []string { + return []string{ + `application/json`, + `application/xml`, + `text/css`, + `text/csv`, + `text/javascript`, + `text/plain`, + `text/plain; charset=utf-8`, + } +} + +func (t Text) Validate(filePath string) bool { + file, err := os.Open(filePath) + switch { + case errors.Is(err, os.ErrNotExist): + return false + case err != nil: + return false + } + defer file.Close() + + head := make([]byte, 512) + file.Read(head) + + return utf8.Valid(head) +} diff --git a/types/types.go b/types/types.go index bad02b4..5e3e3da 100644 --- a/types/types.go +++ b/types/types.go @@ -11,29 +11,29 @@ import ( "path/filepath" ) -type Type struct { - Css func() string - Title func(queryParams, fileUri, filePath, fileName, mime string) string - Body func(queryParams, fileUri, filePath, fileName, mime string) string - Extensions map[string]string - MimeTypes []string - Validate func(filePath string) bool +type Type interface { + Css() string + Title(queryParams, fileUri, filePath, fileName, mime string) string + Body(queryParams, fileUri, filePath, fileName, mime string) string + Extensions() map[string]string + MimeTypes() []string + Validate(filePath string) bool } type Types struct { Extensions map[string]string - MimeTypes map[string]*Type + MimeTypes map[string]Type } -func (s *Types) Add(t *Type) { - for k, v := range t.Extensions { +func (s *Types) Add(t Type) { + for k, v := range t.Extensions() { _, exists := s.Extensions[k] if !exists { s.Extensions[k] = v } } - for _, v := range t.MimeTypes { + for _, v := range t.MimeTypes() { _, exists := s.Extensions[v] if !exists { s.MimeTypes[v] = t @@ -41,7 +41,7 @@ func (s *Types) Add(t *Type) { } } -func FileType(path string, registeredFormats *Types) (bool, *Type, string, error) { +func FileType(path string, registeredFormats *Types) (bool, Type, string, error) { file, err := os.Open(path) switch { case errors.Is(err, os.ErrNotExist): diff --git a/types/video.go b/types/video.go index c27c155..b870f54 100644 --- a/types/video.go +++ b/types/video.go @@ -9,41 +9,48 @@ import ( "strings" ) -func RegisterVideos() *Type { - return &Type{ - Css: func() string { - var css strings.Builder +type Video struct{} - css.WriteString(`html,body{margin:0;padding:0;height:100%;}`) - css.WriteString(`a{color:inherit;display:block;height:100%;width:100%;text-decoration:none;}`) - css.WriteString(`video{margin:auto;display:block;max-width:97%;max-height:97%;`) - css.WriteString(`object-fit:scale-down;position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);}`) +func (t Video) Css() string { + var css strings.Builder - return css.String() - }, - Title: func(queryParams, fileUri, filePath, fileName, mime string) string { - return fmt.Sprintf(`%s`, fileName) - }, - Body: func(queryParams, fileUri, filePath, fileName, mime string) string { - return fmt.Sprintf(``, - queryParams, - fileUri, - mime, - fileName) - }, - Extensions: map[string]string{ - `.mp4`: `video/mp4`, - `.ogm`: `video/ogg`, - `.ogv`: `video/ogg`, - `.webm`: `video/webm`, - }, - MimeTypes: []string{ - `video/mp4`, - `video/ogg`, - `video/webm`, - }, - Validate: func(filePath string) bool { - return true - }, + css.WriteString(`html,body{margin:0;padding:0;height:100%;}`) + css.WriteString(`a{color:inherit;display:block;height:100%;width:100%;text-decoration:none;}`) + css.WriteString(`video{margin:auto;display:block;max-width:97%;max-height:97%;`) + css.WriteString(`object-fit:scale-down;position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);}`) + + return css.String() +} + +func (t Video) Title(queryParams, fileUri, filePath, fileName, mime string) string { + return fmt.Sprintf(`%s`, fileName) +} + +func (t Video) Body(queryParams, fileUri, filePath, fileName, mime string) string { + return fmt.Sprintf(``, + queryParams, + fileUri, + mime, + fileName) +} + +func (t Video) Extensions() map[string]string { + return map[string]string{ + `.mp4`: `video/mp4`, + `.ogm`: `video/ogg`, + `.ogv`: `video/ogg`, + `.webm`: `video/webm`, } } + +func (t Video) MimeTypes() []string { + return []string{ + `video/mp4`, + `video/ogg`, + `video/webm`, + } +} + +func (t Video) Validate(filePath string) bool { + return true +}