]> Sergey Matveev's repositories - sgblog.git/blobdiff - cmd/sgblog/main.go
telnet:// is used in practice
[sgblog.git] / cmd / sgblog / main.go
index 361189325b397257051f1609869fd2d762d29c6b..9162a88b0ffb830c468d8886830a69de9c06b7dc 100644 (file)
@@ -39,6 +39,7 @@ import (
 
        "github.com/hjson/hjson-go"
        "go.cypherpunks.ru/netstring/v2"
+       "go.stargrave.org/sgblog"
        "golang.org/x/crypto/blake2b"
        "golang.org/x/tools/blog/atom"
        "gopkg.in/src-d/go-git.v4"
@@ -48,12 +49,10 @@ import (
 
 const (
        PageEntries = 50
-       WhenFmt     = "2006-01-02 15:04:05Z07:00"
        AtomFeed    = "feed.atom"
 )
 
 var (
-       Version      = "0.2.0"
        sha1DigestRe = regexp.MustCompilePOSIX("([0-9a-f]{40,40})")
        defaultLinks = []string{}
        repo         *git.Repository
@@ -65,6 +64,7 @@ var (
                "gopher": struct{}{},
                "http":   struct{}{},
                "https":  struct{}{},
+               "telnet": struct{}{},
        }
 )
 
@@ -78,11 +78,11 @@ type Cfg struct {
        Branch  string
        Title   string
 
-       BaseURL   string
        URLPrefix string
 
-       AtomId     string
-       AtomAuthor string
+       AtomBaseURL string
+       AtomId      string
+       AtomAuthor  string
 
        CSS       string
        Webmaster string
@@ -119,12 +119,37 @@ func msgSplit(msg string) []string {
        return lines
 }
 
+func lineURLize(urlPrefix, line string) string {
+       cols := strings.Split(html.EscapeString(line), " ")
+       for i, col := range cols {
+               if u := urlParse(col); u != nil {
+                       cols[i] = makeA(col, col)
+                       continue
+               }
+               cols[i] = sha1DigestRe.ReplaceAllString(col, makeA(
+                       urlPrefix+"/$1", "$1",
+               ))
+       }
+       return strings.Join(cols, " ")
+}
+
 func getNote(tree *object.Tree, what plumbing.Hash) []byte {
        if tree == nil {
                return nil
        }
-       entry, err := tree.FindEntry(what.String())
-       if err != nil {
+       var entry *object.TreeEntry
+       var err error
+       paths := make([]string, 3)
+       paths[0] = what.String()
+       paths[1] = paths[0][:2] + "/" + paths[0][2:]
+       paths[2] = paths[1][:4+1] + "/" + paths[1][4+1:]
+       for _, p := range paths {
+               entry, err = tree.FindEntry(p)
+               if err == nil {
+                       break
+               }
+       }
+       if entry == nil {
                return nil
        }
        blob, err := repo.BlobObject(entry.Hash)
@@ -179,7 +204,7 @@ func startHTML(title string, additional []string) string {
 </head>
 <body>
 `,
-               Version, title,
+               sgblog.Version, title,
                strings.Join(append(defaultLinks, additional...), "\n   "),
        )
 }
@@ -234,11 +259,12 @@ func main() {
                panic(err)
        }
        etagHash.Write([]byte("SGBLOG"))
+       etagHash.Write([]byte(sgblog.Version))
        etagHash.Write([]byte(cfg.GitPath))
        etagHash.Write([]byte(cfg.Branch))
        etagHash.Write([]byte(cfg.Title))
-       etagHash.Write([]byte(cfg.BaseURL))
        etagHash.Write([]byte(cfg.URLPrefix))
+       etagHash.Write([]byte(cfg.AtomBaseURL))
        etagHash.Write([]byte(cfg.AtomId))
        etagHash.Write([]byte(cfg.AtomAuthor))
 
@@ -266,7 +292,7 @@ func main() {
        }
 
        defaultLinks = append(defaultLinks, `<link rel="top" href="`+cfg.URLPrefix+`/" title="top">`)
-       atomURL := cfg.BaseURL + cfg.URLPrefix + "/" + AtomFeed
+       atomURL := cfg.AtomBaseURL + cfg.URLPrefix + "/" + AtomFeed
        defaultLinks = append(defaultLinks, `<link rel="alternate" title="Atom feed" href="`+atomURL+`" type="application/atom+xml">`)
 
        repo, err = git.PlainOpen(cfg.GitPath)
@@ -355,12 +381,13 @@ func main() {
 
                var table bytes.Buffer
                table.WriteString(
-                       "<table border=1>\n<tr>" +
+                       "<table border=1>\n" +
+                               "<caption>Comments</caption>\n<tr>" +
                                "<th>N</th>" +
                                "<th>When</th>" +
                                "<th>Title</th>" +
-                               "<th size=\"5%\">L</th>" +
-                               "<th size=\"5%\">C</th>" +
+                               `<th size="5%"><a title="Lines">L</a></th>` +
+                               `<th size="5%"><a title="Comments">C</a></th>` +
                                "<th>Linked to</th></tr>\n")
                for _, entry := range entries {
                        commentN++
@@ -384,7 +411,7 @@ func main() {
                                        "<td>%s</td>"+
                                        "<td>%d</td><td>%s</td>"+
                                        "<td>%s</td></tr>\n",
-                               commentN, entry.commit.Author.When.Format(WhenFmt),
+                               commentN, entry.commit.Author.When.Format(sgblog.WhenFmt),
                                makeA(cfg.URLPrefix+"/"+entry.commit.Hash.String(), lines[0]),
                                len(lines)-2,
                                commentsValue,
@@ -403,12 +430,12 @@ func main() {
                                href = cfg.URLPrefix + "/"
                        }
                        links = append(links, `<link rel="prev" href="`+href+`" title="newer">`)
-                       refs.WriteString(makeA(href, "&nbsp;[prev]"))
+                       refs.WriteString("\n" + makeA(href, "[prev]"))
                }
                if !logEnded {
                        href = cfg.URLPrefix + "/?offset=" + strconv.Itoa(offset+PageEntries)
                        links = append(links, `<link rel="next" href="`+href+`" title="older">`)
-                       refs.WriteString(makeA(href, "&nbsp;[next]"))
+                       refs.WriteString("\n" + makeA(href, "[next]"))
                }
 
                os.Stdout.Write([]byte(startHeader(etagHash, gzipWriter != nil)))
@@ -469,7 +496,7 @@ func main() {
                                ID:    "urn:uuid:" + feedId,
                                Link: []atom.Link{{
                                        Rel:  "alternate",
-                                       Href: cfg.BaseURL + cfg.URLPrefix + "/" + commit.Hash.String(),
+                                       Href: cfg.AtomBaseURL + cfg.URLPrefix + "/" + commit.Hash.String(),
                                }},
                                Published: atom.Time(commit.Author.When),
                                Updated:   atom.Time(commit.Author.When),
@@ -514,7 +541,7 @@ func main() {
                checkETag(etagHash)
                lines := msgSplit(commit.Message)
                title := lines[0]
-               when := commit.Author.When.Format(WhenFmt)
+               when := commit.Author.When.Format(sgblog.WhenFmt)
                os.Stdout.Write([]byte(startHeader(etagHash, gzipWriter != nil)))
                links := []string{}
                var parent string
@@ -524,32 +551,23 @@ func main() {
                }
                out.Write([]byte(startHTML(fmt.Sprintf("%s (%s)", title, when), links)))
                if cfg.AboutURL != "" {
-                       out.Write([]byte(fmt.Sprintf("[%s]&nbsp;", makeA(cfg.AboutURL, "about"))))
+                       out.Write([]byte(fmt.Sprintf("[%s]\n", makeA(cfg.AboutURL, "about"))))
                }
+               out.Write([]byte(fmt.Sprintf("[%s]\n", makeA(cfg.URLPrefix+"/", "index"))))
                if parent != "" {
                        out.Write([]byte(fmt.Sprintf(
-                               "[%s]&nbsp;",
+                               "[%s]\n",
                                makeA(cfg.URLPrefix+"/"+parent, "older"),
                        )))
                }
                out.Write([]byte(fmt.Sprintf(
-                       "[<tt>%s</tt>]&nbsp;[<tt>%s</tt>]<hr/>\n<h2>%s</h2>\n<pre>\n",
+                       "[<tt><a title=\"When\">%s</a></tt>]\n"+
+                               "[<tt><a title=\"Hash\">%s</a></tt>]\n"+
+                               "<hr/>\n<h2>%s</h2>\n<pre>\n",
                        when, commit.Hash.String(), title,
                )))
                for _, line := range lines[2:] {
-                       line = html.EscapeString(line)
-                       cols := strings.Split(line, " ")
-                       for i, col := range cols {
-                               if u := urlParse(col); u != nil {
-                                       cols[i] = makeA(col, col)
-                                       continue
-                               }
-                               cols[i] = sha1DigestRe.ReplaceAllString(col, makeA(
-                                       cfg.URLPrefix+"/$1", "$1",
-                               ))
-                       }
-                       line = strings.Join(cols, " ")
-                       out.Write([]byte(line + "\n"))
+                       out.Write([]byte(lineURLize(cfg.URLPrefix, line) + "\n"))
                }
                out.Write([]byte("</pre>\n<hr/>\n"))
                if len(notesRaw) > 0 {
@@ -565,9 +583,17 @@ func main() {
                for i, comment := range parseComments(commentsRaw) {
                        out.Write([]byte(fmt.Sprintf(
                                "<dt><a name=\"comment%d\"><a href=\"#comment%d\">comment %d</a>:"+
-                                       "</dt>\n<dd><pre>\n%s\n</pre></dd>\n",
-                               i, i, i, html.EscapeString(comment),
+                                       "</dt>\n<dd><pre>\n",
+                               i, i, i,
                        )))
+                       lines = strings.Split(comment, "\n")
+                       for _, line := range lines[:3] {
+                               out.Write([]byte(line + "\n"))
+                       }
+                       for _, line := range lines[3:] {
+                               out.Write([]byte(lineURLize(cfg.URLPrefix, line) + "\n"))
+                       }
+                       out.Write([]byte("</pre></dd>\n"))
                }
                out.Write([]byte("</dl>\n"))
        } else {