pico

created pr with 15.1 on 2024-08-01T14:25:45Z · by c8ef7d19
added 15.2 on 2024-08-01T15:29:59Z · by c8ef7d19
1: 866976a = 1: 866976a feat(prose): live journal
-: ------- > 2: b82b2f7 chore: diff in post
cmds
checkout latest patchset:
ssh pr.pico.sh print 15 | git am -3
checkout any patchset in a patch request:
ssh pr.pico.sh print 15.[rev] | git am -3
add changes to patch request:
git format-patch main --stdout | ssh pr.pico.sh pr add 15

Patchset 15.2 on 2024-08-01T15:29:59Z · commit 866976a

+1 -0 db/db.go #
......@@ -32,6 +32,7 @@ type User struct {
3232 type PostData struct {
3333 ImgPath string `json:"img_path"`
3434 LastDigest *time.Time `json:"last_digest"`
35+ Diff string `json:"diff"`
3536 }
3637
3738 // Make the Attrs struct implement the driver.Valuer interface. This method
+1 -0 go.mod #
......@@ -37,6 +37,7 @@ require (
3737 github.com/picosh/tunkit v0.0.0-20240709033345-8315d4f3cd0e
3838 github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06
3939 github.com/sendgrid/sendgrid-go v3.14.0+incompatible
40+ github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3
4041 github.com/simplesurance/go-ip-anonymizer v0.0.0-20200429124537-35a880f8e87d
4142 github.com/x-way/crawlerdetect v0.2.21
4243 github.com/yuin/goldmark v1.7.1
+8 -0 go.sum #
......@@ -158,8 +158,11 @@ github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuV
158158 github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
159159 github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8=
160160 github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
161+github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
161162 github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
162163 github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
164+github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
165+github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
163166 github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
164167 github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
165168 github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
......@@ -265,6 +268,8 @@ github.com/sendgrid/rest v2.6.9+incompatible h1:1EyIcsNdn9KIisLW50MKwmSRSK+ekuei
265268 github.com/sendgrid/rest v2.6.9+incompatible/go.mod h1:kXX7q3jZtJXK5c5qK83bSGMdV6tsOE70KbHoqJls4lE=
266269 github.com/sendgrid/sendgrid-go v3.14.0+incompatible h1:KDSasSTktAqMJCYClHVE94Fcif2i7P7wzISv1sU6DUA=
267270 github.com/sendgrid/sendgrid-go v3.14.0+incompatible/go.mod h1:QRQt+LX/NmgVEvmdRw0VT/QgUn499+iza2FnDca9fg8=
271+github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8=
272+github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
268273 github.com/shirou/gopsutil/v3 v3.24.5 h1:i0t8kL+kQTvpAYToeuiVk3TgDeKOFioZO3Ztz/iZ9pI=
269274 github.com/shirou/gopsutil/v3 v3.24.5/go.mod h1:bsoOS1aStSs9ErQ1WWfxllSeS1K5D+U30r2NfcubMVk=
270275 github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM=
......@@ -276,6 +281,7 @@ github.com/simplesurance/go-ip-anonymizer v0.0.0-20200429124537-35a880f8e87d/go.
276281 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
277282 github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
278283 github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
284+github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
279285 github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
280286 github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
281287 github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
......@@ -393,10 +399,12 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T
393399 google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg=
394400 google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
395401 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
402+gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
396403 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
397404 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
398405 gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
399406 gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
407+gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
400408 gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
401409 gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
402410 gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
+24 -24 prose/api.go #
......@@ -160,7 +160,7 @@ func blogHandler(w http.ResponseWriter, r *http.Request) {
160160 }
161161
162162 tag := r.URL.Query().Get("tag")
163- pager := &db.Pager{Num: 1000, Page: 0}
163+ pager := &db.Pager{Num: 250, Page: 0}
164164 var posts []*db.Post
165165 var p *db.Paginate[*db.Post]
166166 if tag == "" {
......@@ -170,6 +170,13 @@ func blogHandler(w http.ResponseWriter, r *http.Request) {
170170 }
171171 posts = p.Data
172172
173+ byUpdated := strings.Contains(r.URL.Path, "live")
174+ if byUpdated {
175+ slices.SortFunc(posts, func(a *db.Post, b *db.Post) int {
176+ return b.UpdatedAt.Compare(*a.UpdatedAt)
177+ })
178+ }
179+
173180 if err != nil {
174181 logger.Error(err.Error())
175182 http.Error(w, "could not fetch posts for blog", http.StatusInternalServerError)
......@@ -653,6 +660,13 @@ func rssBlogHandler(w http.ResponseWriter, r *http.Request) {
653660 curl := shared.CreateURLFromRequest(cfg, r)
654661 blogUrl := cfg.FullBlogURL(curl, username)
655662
663+ byUpdated := strings.Contains(r.URL.Path, "live")
664+ if byUpdated {
665+ slices.SortFunc(posts, func(a *db.Post, b *db.Post) int {
666+ return b.UpdatedAt.Compare(*a.UpdatedAt)
667+ })
668+ }
669+
656670 feed := &feeds.Feed{
657671 Id: blogUrl,
658672 Title: headerTxt.Title,
......@@ -691,12 +705,18 @@ func rssBlogHandler(w http.ResponseWriter, r *http.Request) {
691705 }
692706
693707 realUrl := cfg.FullPostURL(curl, post.Username, post.Slug)
708+ feedId := realUrl
709+
710+ if byUpdated {
711+ feedId = fmt.Sprintf("%s:%s", realUrl, post.UpdatedAt.Format(time.RFC3339))
712+ }
694713
695714 item := &feeds.Item{
696- Id: realUrl,
715+ Id: feedId,
697716 Title: shared.FilenameToTitle(post.Filename, post.Title),
698717 Link: &feeds.Link{Href: realUrl},
699718 Content: tpl.String(),
719+ Updated: *post.UpdatedAt,
700720 Created: *post.CreatedAt,
701721 Description: post.Description,
702722 }
......@@ -849,36 +869,16 @@ func createMainRoutes(staticRoutes []shared.Route) []shared.Route {
849869 staticRoutes...,
850870 )
851871
852- routes = append(
853- routes,
854- shared.NewRoute("GET", "/rss", rssHandler),
855- shared.NewRoute("GET", "/rss.xml", rssHandler),
856- shared.NewRoute("GET", "/atom.xml", rssHandler),
857- shared.NewRoute("GET", "/feed.xml", rssHandler),
858-
859- shared.NewRoute("GET", "/([^/]+)", blogHandler),
860- shared.NewRoute("GET", "/([^/]+)/rss", rssBlogHandler),
861- shared.NewRoute("GET", "/([^/]+)/rss.xml", rssBlogHandler),
862- shared.NewRoute("GET", "/([^/]+)/atom.xml", rssBlogHandler),
863- shared.NewRoute("GET", "/([^/]+)/atom", rssBlogHandler),
864- shared.NewRoute("GET", "/([^/]+)/blog/index.xml", rssBlogHandler),
865- shared.NewRoute("GET", "/([^/]+)/feed.xml", rssBlogHandler),
866- shared.NewRoute("GET", "/([^/]+)/_styles.css", blogStyleHandler),
867- shared.NewRoute("GET", "/raw/([^/]+)/(.+)", postRawHandler),
868- shared.NewRoute("GET", "/([^/]+)/(.+)/(.+)", imgs.ImgRequest),
869- shared.NewRoute("GET", "/([^/]+)/(.+.(?:jpg|jpeg|png|gif|webp|svg))$", imgs.ImgRequest),
870- shared.NewRoute("GET", "/([^/]+)/i", imgs.ImgsListHandler),
871- shared.NewRoute("GET", "/([^/]+)/(.+)", postHandler),
872- )
873-
874872 return routes
875873 }
876874
877875 func createSubdomainRoutes(staticRoutes []shared.Route) []shared.Route {
878876 routes := []shared.Route{
879877 shared.NewRoute("GET", "/", blogHandler),
878+ shared.NewRoute("GET", "/live", blogHandler),
880879 shared.NewRoute("GET", "/_styles.css", blogStyleHandler),
881880 shared.NewRoute("GET", "/rss", rssBlogHandler),
881+ shared.NewRoute("GET", "/live/rss", rssBlogHandler),
882882 shared.NewRoute("GET", "/rss.xml", rssBlogHandler),
883883 shared.NewRoute("GET", "/atom.xml", rssBlogHandler),
884884 shared.NewRoute("GET", "/feed.xml", rssBlogHandler),
+5 -0 prose/scp_hooks.go #
......@@ -10,6 +10,7 @@ import (
1010 "github.com/picosh/pico/db"
1111 "github.com/picosh/pico/filehandlers"
1212 "github.com/picosh/pico/shared"
13+ "github.com/sergi/go-diff/diffmatchpatch"
1314 )
1415
1516 type MarkdownHooks struct {
......@@ -62,6 +63,10 @@ func (p *MarkdownHooks) FileMeta(s ssh.Session, data *filehandlers.PostMetaData)
6263 data.Tags = parsedText.Tags
6364 data.Description = parsedText.Description
6465
66+ dmp := diffmatchpatch.New()
67+ diffs := dmp.DiffMain(data.Cur.Text, data.Text, false)
68+ data.Data.Diff = dmp.DiffPrettyText(diffs)
69+
6570 if parsedText.PublishAt != nil && !parsedText.PublishAt.IsZero() {
6671 data.PublishAt = parsedText.MetaData.PublishAt
6772 }
Back to top