]> Sergey Matveev's repositories - sgblog.git/commitdiff
Images support v0.28.0
authorSergey Matveev <stargrave@stargrave.org>
Fri, 28 Jul 2023 18:26:56 +0000 (21:26 +0300)
committerSergey Matveev <stargrave@stargrave.org>
Fri, 28 Jul 2023 18:52:24 +0000 (21:52 +0300)
README.texi
cmd/sgblog/http-entry.tmpl
cmd/sgblog/http.go
cmd/sgblog/img.go [new file with mode: 0644]
cmd/sgblog/main.go
comment.rec [new file with mode: 0644]
common.go

index 18b8335f207633a8b9423a6a232826c730c71c77..ffe270463db19e0f5984cae609f8d7737e326e28 100644 (file)
@@ -30,6 +30,7 @@ Its main competitive features:
     interface for working as
     @url{https://en.wikipedia.org/wiki/Gopher_(protocol), Gopher} server
 @item Topics (tags/categories) support
+@item Images linking support
 @item Supports on the fly generation of
     @url{https://en.wikipedia.org/wiki/Atom_(feed), Atom} feeds
     for posts, comments and per-post comments
@@ -115,6 +116,19 @@ To reset incorrectly added topic:
 $ git update-ref refs/notes/topics refs/notes/topics^
 @end example
 
+@node Images
+@unnumbered Images
+
+You can link any number of image files with your post. You need to put
+them in a directory (@code{ImgPath} configuration file's option) which
+path is equal to your post's hash, with two subdirectory levels. For
+example directory for post @code{3e12180dd2b6fb3b44c77c365d355d5a3796a43f}
+will be @code{ImgPath/3e/12/180dd2b6fb3b44c77c365d355d5a3796a43f}.
+Filenames are lexically sorted. Filename without an extension will be
+image's alternative text. Currently only @file{.jxl} and @file{.webp}
+are recognized. @code{ImgDomain} configuration file's option will be
+used to construct URL to @code{//ImgDomain/3e/12/180dd2b6fb3b44c77c365d355d5a3796a43f}.
+
 @node Installation
 @unnumbered Installation
 
@@ -258,6 +272,10 @@ optional fields:
   TopicsNotesRef: refs/notes/topics
   # Optional file for topics state caching
   TopicsCachePath: /path/to/sgblog-topics-cache.gob
+
+  # If set, then images are searched in XX/YY/ZZZ...ZZZ directory
+  ImgPath: /path/to/directory/with/images
+  ImgDomain: img.blog.example.com
 @}
 @end example
 
index 240617a97a6246e01cb568f8ad4398461bd8bfd2..efff427b3954a939cc3d5186bb4aa4cddf120df9 100644 (file)
 {{end}}</pre>
 <hr/>{{end}}
 
+<ol>{{range $idx, $img := .Imgs}}
+<li><img alt="{{$img.Alt}}" src="//{{$.Cfg.ImgDomain}}/{{$img.Path}}" /></li>
+{{end}}</ol>
+
 {{if .Cfg.CommentsEmail}}[<a href="mailto:{{.Cfg.CommentsEmail}}?subject={{.TitleEscaped}}">{{$.T.Get "leave a comment"}}</a>]{{end}}
 
 <dl>{{range $idx, $comment := .Comments}}
index fd5f7b448ec88bcdb7dc8a15d5b51e01a5575b5a..50bb1a882f841715f2d0dee1be079243ef67e858 100644 (file)
@@ -484,13 +484,22 @@ func serveHTTP() {
                                htmlized = append(htmlized, lineURLize(cfg.AtomBaseURL+cfg.URLPrefix, l))
                        }
                        htmlized = append(htmlized, "</pre>")
+                       links := []atom.Link{{
+                               Rel:  "alternate",
+                               Href: cfg.AtomBaseURL + cfg.URLPrefix + "/" + commit.Hash.String(),
+                       }}
+                       for _, img := range listImgs(cfg, commit.Hash) {
+                               links = append(links, atom.Link{
+                                       Rel:    "enclosure",
+                                       Href:   "http://" + cfg.ImgDomain + "/" + img.Path,
+                                       Type:   img.Typ,
+                                       Length: uint(img.Size),
+                               })
+                       }
                        feed.Entry = append(feed.Entry, &atom.Entry{
-                               Title: lines[0],
-                               ID:    "urn:uuid:" + bytes2uuid(commit.Hash[:]),
-                               Link: []atom.Link{{
-                                       Rel:  "alternate",
-                                       Href: cfg.AtomBaseURL + cfg.URLPrefix + "/" + commit.Hash.String(),
-                               }},
+                               Title:     lines[0],
+                               ID:        "urn:uuid:" + bytes2uuid(commit.Hash[:]),
+                               Link:      links,
                                Published: atom.Time(commit.Author.When),
                                Updated:   atom.Time(commit.Author.When),
                                Summary:   &atom.Text{Type: "text", Body: lines[0]},
@@ -742,6 +751,7 @@ func serveHTTP() {
                        NoteLines       []string
                        Comments        []CommentEntry
                        Topics          []string
+                       Imgs            []Img
                }{
                        T:               localizer,
                        Version:         sgblog.Version,
@@ -756,6 +766,7 @@ func serveHTTP() {
                        NoteLines:       notesLines,
                        Comments:        comments,
                        Topics:          sgblog.ParseTopics(topicsRaw),
+                       Imgs:            listImgs(cfg, commit.Hash),
                })
                if err != nil {
                        makeErr(err, http.StatusInternalServerError)
diff --git a/cmd/sgblog/img.go b/cmd/sgblog/img.go
new file mode 100644 (file)
index 0000000..7f97d98
--- /dev/null
@@ -0,0 +1,55 @@
+package main
+
+import (
+       "log"
+       "os"
+       "path"
+       "strings"
+
+       "github.com/go-git/go-git/v5/plumbing"
+)
+
+type Img struct {
+       Path string
+       Alt  string
+       Size int64
+       Typ  string
+}
+
+var ImgTypes = map[string]string{
+       ".jxl":  "image/jxl",
+       ".webp": "image/webp",
+}
+
+func listImgs(cfg *Cfg, what plumbing.Hash) (out []Img) {
+       if cfg.ImgPath == "" {
+               return nil
+       }
+       w := what.String()
+       sub := path.Join(w[:2], w[2:4], w[4:])
+       ents, err := os.ReadDir(path.Join(cfg.ImgPath, sub))
+       if err != nil {
+               return nil
+       }
+       out = make([]Img, 0, len(ents))
+       for _, ent := range ents {
+               name := ent.Name()
+               ext := path.Ext(name)
+               info, err := ent.Info()
+               if err != nil {
+                       log.Println("imgs: Info():", err)
+                       continue
+               }
+               typ := ImgTypes[ext]
+               if typ == "" {
+                       typ = "application/octet-stream"
+               }
+               out = append(out, Img{
+                       Path: path.Join(sub, ent.Name()),
+                       Alt:  strings.TrimSuffix(name, ext),
+                       Size: info.Size(),
+                       Typ:  typ,
+               })
+       }
+       return
+}
index 6cd1efd17b7a35a7bb12f4faa16ffdee120bbb14..a7613021a61eb2491f66af3af73682fdb85a0885 100644 (file)
@@ -81,6 +81,9 @@ type Cfg struct {
        TopicsCachePath string
 
        GopherDomain string
+
+       ImgPath   string
+       ImgDomain string
 }
 
 func msgSplit(msg string) []string {
diff --git a/comment.rec b/comment.rec
new file mode 100644 (file)
index 0000000..b5337a0
--- /dev/null
@@ -0,0 +1,4 @@
+%rec: Comment
+%doc: SGBlog's comment
+%mandatory: From Date Body
+%type: Date date
index 9c4843b7ea81a18811f61b6b9b8e273f523867b3..e3c092d435b30266d087b4c3347cf8c5053b7ddd 100644 (file)
--- a/common.go
+++ b/common.go
@@ -15,7 +15,7 @@ import (
 )
 
 const (
-       Version = "0.27.3"
+       Version = "0.28.0"
        WhenFmt = "2006-01-02 15:04:05Z07:00"
 )