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
$ 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
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
{{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}}
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]},
NoteLines []string
Comments []CommentEntry
Topics []string
+ Imgs []Img
}{
T: localizer,
Version: sgblog.Version,
NoteLines: notesLines,
Comments: comments,
Topics: sgblog.ParseTopics(topicsRaw),
+ Imgs: listImgs(cfg, commit.Hash),
})
if err != nil {
makeErr(err, http.StatusInternalServerError)
--- /dev/null
+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
+}
TopicsCachePath string
GopherDomain string
+
+ ImgPath string
+ ImgDomain string
}
func msgSplit(msg string) []string {
--- /dev/null
+%rec: Comment
+%doc: SGBlog's comment
+%mandatory: From Date Body
+%type: Date date
)
const (
- Version = "0.27.3"
+ Version = "0.28.0"
WhenFmt = "2006-01-02 15:04:05Z07:00"
)