pico
created pr with
67.1
cmds
checkout latest patchset:
ssh pr.pico.sh print 67 | git am -3checkout any patchset in a patch request:
ssh pr.pico.sh print 67.[rev] | git am -3add changes to patch request:
git format-patch main --stdout | ssh pr.pico.sh pr add 67
Patchset
67.1
refactor(prose): unified _styles.css handler
Eric Bower
2025-05-03T17:31:22ZBREAKING CHANGE: `with_styles` is deprecated and users cannot "tweak" the default stylesheet, they will have to copy and then upload it with tweaks.
Semantic diff summary
0 added,
6 modified,
0 signature changed,
0 removed
across 1 analyzed file
(2 files skipped: unsupported file type)
+52
-60
pkg/apps/prose/api.go
#
| ... | ... | @@ -41,18 +41,17 @@ type PostItemData struct { | |
| 41 | 41 | } | |
| 42 | 42 | ||
| 43 | 43 | type BlogPageData struct { | |
| 44 | - | Site shared.SitePageData | |
| 45 | - | PageTitle string | |
| 46 | - | URL template.URL | |
| 47 | - | RSSURL template.URL | |
| 48 | - | Username string | |
| 49 | - | Readme *ReadmeTxt | |
| 50 | - | Header *HeaderTxt | |
| 51 | - | Posts []PostItemData | |
| 52 | - | HasCSS bool | |
| 53 | - | WithStyles bool | |
| 54 | - | CssURL template.URL | |
| 55 | - | HasFilter bool | |
| 44 | + | Site shared.SitePageData | |
| 45 | + | PageTitle string | |
| 46 | + | URL template.URL | |
| 47 | + | RSSURL template.URL | |
| 48 | + | Username string | |
| 49 | + | Readme *ReadmeTxt | |
| 50 | + | Header *HeaderTxt | |
| 51 | + | Posts []PostItemData | |
| 52 | + | HasCSS bool | |
| 53 | + | CssURL template.URL | |
| 54 | + | HasFilter bool | |
| 56 | 55 | } | |
| 57 | 56 | ||
| 58 | 57 | type ReadPageData struct { |
| ... | ... | @@ -90,16 +88,15 @@ type PostPageData struct { | |
| 90 | 88 | } | |
| 91 | 89 | ||
| 92 | 90 | type HeaderTxt struct { | |
| 93 | - | Title string | |
| 94 | - | Bio string | |
| 95 | - | Nav []shared.Link | |
| 96 | - | HasLinks bool | |
| 97 | - | Layout string | |
| 98 | - | Image template.URL | |
| 99 | - | ImageCard string | |
| 100 | - | Favicon template.URL | |
| 101 | - | WithStyles bool | |
| 102 | - | Domain string | |
| 91 | + | Title string | |
| 92 | + | Bio string | |
| 93 | + | Nav []shared.Link | |
| 94 | + | HasLinks bool | |
| 95 | + | Layout string | |
| 96 | + | Image template.URL | |
| 97 | + | ImageCard string | |
| 98 | + | Favicon template.URL | |
| 99 | + | Domain string | |
| 103 | 100 | } | |
| 104 | 101 | ||
| 105 | 102 | type ReadmeTxt struct { |
| ... | ... | @@ -134,15 +131,27 @@ func blogStyleHandler(w http.ResponseWriter, r *http.Request) { | |
| 134 | 131 | logger = shared.LoggerWithUser(logger, user) | |
| 135 | 132 | ||
| 136 | 133 | styles, err := dbpool.FindPostWithFilename("_styles.css", user.ID, cfg.Space) | |
| 137 | - | if err != nil { | |
| 138 | - | logger.Info("css not found") | |
| 139 | - | http.Error(w, "css not found", http.StatusNotFound) | |
| 140 | - | return | |
| 134 | + | var txt []byte | |
| 135 | + | if err == nil { | |
| 136 | + | txt = []byte(styles.Text) | |
| 137 | + | logger.Info("custom css found") | |
| 138 | + | } else { | |
| 139 | + | fp := cfg.StaticPath(fmt.Sprintf("public/%s", "smol.css")) | |
| 140 | + | if user.CreatedAt.After(time.Date(2025, 5, 3, 0, 0, 0, 0, time.Local)) { | |
| 141 | + | fp = cfg.StaticPath(fmt.Sprintf("public/%s", "smol-v2.css")) | |
| 142 | + | } | |
| 143 | + | txt, err = os.ReadFile(fp) | |
| 144 | + | if err != nil { | |
| 145 | + | logger.Error("read default css file", "err", err) | |
| 146 | + | http.Error(w, "default css file not found", http.StatusInternalServerError) | |
| 147 | + | return | |
| 148 | + | } | |
| 149 | + | logger.Info("custom css not found, loading default") | |
| 141 | 150 | } | |
| 142 | 151 | ||
| 143 | 152 | w.Header().Add("Content-Type", "text/css") | |
| 144 | 153 | ||
| 145 | - | _, err = w.Write([]byte(styles.Text)) | |
| 154 | + | _, err = w.Write(txt) | |
| 146 | 155 | if err != nil { | |
| 147 | 156 | logger.Error("write to response writer", "err", err.Error()) | |
| 148 | 157 | http.Error(w, "server error", 500) |
| ... | ... | @@ -195,11 +204,10 @@ func blogHandler(w http.ResponseWriter, r *http.Request) { | |
| 195 | 204 | } | |
| 196 | 205 | ||
| 197 | 206 | headerTxt := &HeaderTxt{ | |
| 198 | - | Title: GetBlogName(username), | |
| 199 | - | Bio: "", | |
| 200 | - | Layout: "default", | |
| 201 | - | ImageCard: "summary", | |
| 202 | - | WithStyles: true, | |
| 207 | + | Title: GetBlogName(username), | |
| 208 | + | Bio: "", | |
| 209 | + | Layout: "default", | |
| 210 | + | ImageCard: "summary", | |
| 203 | 211 | } | |
| 204 | 212 | readmeTxt := &ReadmeTxt{} | |
| 205 | 213 |
| ... | ... | @@ -213,7 +221,6 @@ func blogHandler(w http.ResponseWriter, r *http.Request) { | |
| 213 | 221 | headerTxt.Layout = parsedText.Layout | |
| 214 | 222 | headerTxt.Image = template.URL(parsedText.Image) | |
| 215 | 223 | headerTxt.ImageCard = parsedText.ImageCard | |
| 216 | - | headerTxt.WithStyles = parsedText.WithStyles | |
| 217 | 224 | headerTxt.Favicon = template.URL(parsedText.Favicon) | |
| 218 | 225 | if parsedText.Title != "" { | |
| 219 | 226 | headerTxt.Title = parsedText.Title |
| ... | ... | @@ -263,18 +270,17 @@ func blogHandler(w http.ResponseWriter, r *http.Request) { | |
| 263 | 270 | } | |
| 264 | 271 | ||
| 265 | 272 | data := BlogPageData{ | |
| 266 | - | Site: *cfg.GetSiteData(), | |
| 267 | - | PageTitle: headerTxt.Title, | |
| 268 | - | URL: template.URL(cfg.FullBlogURL(curl, username)), | |
| 269 | - | RSSURL: template.URL(cfg.RssBlogURL(curl, username, tag)), | |
| 270 | - | Readme: readmeTxt, | |
| 271 | - | Header: headerTxt, | |
| 272 | - | Username: username, | |
| 273 | - | Posts: postCollection, | |
| 274 | - | HasCSS: hasCSS, | |
| 275 | - | CssURL: template.URL(cfg.CssURL(username)), | |
| 276 | - | HasFilter: tag != "", | |
| 277 | - | WithStyles: headerTxt.WithStyles, | |
| 273 | + | Site: *cfg.GetSiteData(), | |
| 274 | + | PageTitle: headerTxt.Title, | |
| 275 | + | URL: template.URL(cfg.FullBlogURL(curl, username)), | |
| 276 | + | RSSURL: template.URL(cfg.RssBlogURL(curl, username, tag)), | |
| 277 | + | Readme: readmeTxt, | |
| 278 | + | Header: headerTxt, | |
| 279 | + | Username: username, | |
| 280 | + | Posts: postCollection, | |
| 281 | + | HasCSS: hasCSS, | |
| 282 | + | CssURL: template.URL(cfg.CssURL(username)), | |
| 283 | + | HasFilter: tag != "", | |
| 278 | 284 | } | |
| 279 | 285 | ||
| 280 | 286 | err = ts.Execute(w, data) |
| ... | ... | @@ -357,17 +363,8 @@ func postHandler(w http.ResponseWriter, r *http.Request) { | |
| 357 | 363 | favicon := "" | |
| 358 | 364 | ogImage := "" | |
| 359 | 365 | ogImageCard := "" | |
| 360 | - | hasCSS := false | |
| 361 | - | withStyles := true | |
| 362 | 366 | var data PostPageData | |
| 363 | 367 | ||
| 364 | - | css, err := dbpool.FindPostWithFilename("_styles.css", user.ID, cfg.Space) | |
| 365 | - | if err == nil { | |
| 366 | - | if len(css.Text) > 0 { | |
| 367 | - | hasCSS = true | |
| 368 | - | } | |
| 369 | - | } | |
| 370 | - | ||
| 371 | 368 | footer, err := dbpool.FindPostWithFilename("_footer.md", user.ID, cfg.Space) | |
| 372 | 369 | var footerHTML template.HTML | |
| 373 | 370 | if err == nil { |
| ... | ... | @@ -388,7 +385,6 @@ func postHandler(w http.ResponseWriter, r *http.Request) { | |
| 388 | 385 | if readmeParsed.MetaData.Title != "" { | |
| 389 | 386 | blogName = readmeParsed.MetaData.Title | |
| 390 | 387 | } | |
| 391 | - | withStyles = readmeParsed.WithStyles | |
| 392 | 388 | ogImage = readmeParsed.Image | |
| 393 | 389 | ogImageCard = readmeParsed.ImageCard | |
| 394 | 390 | favicon = readmeParsed.Favicon |
| ... | ... | @@ -429,7 +425,6 @@ func postHandler(w http.ResponseWriter, r *http.Request) { | |
| 429 | 425 | Username: username, | |
| 430 | 426 | BlogName: blogName, | |
| 431 | 427 | Contents: template.HTML(parsedText.Html), | |
| 432 | - | HasCSS: hasCSS, | |
| 433 | 428 | CssURL: template.URL(cfg.CssURL(username)), | |
| 434 | 429 | Tags: parsedText.Tags, | |
| 435 | 430 | Image: template.URL(ogImage), |
| ... | ... | @@ -473,7 +467,6 @@ func postHandler(w http.ResponseWriter, r *http.Request) { | |
| 473 | 467 | PublishAtISO: time.Now().Format(time.RFC3339), | |
| 474 | 468 | Username: username, | |
| 475 | 469 | BlogName: blogName, | |
| 476 | - | HasCSS: hasCSS, | |
| 477 | 470 | CssURL: template.URL(cfg.CssURL(username)), | |
| 478 | 471 | Image: template.URL(ogImage), | |
| 479 | 472 | ImageCard: ogImageCard, |
+1
-5
pkg/apps/prose/html/blog.page.tmpl
#
| ... | ... | @@ -41,12 +41,8 @@ | |
| 41 | 41 | {{if .Header.Bio}}<meta property="twitter:description" content="{{.Header.Bio}}">{{end}} | |
| 42 | 42 | ||
| 43 | 43 | <link rel="alternate" href="{{.RSSURL}}" type="application/rss+xml" title="RSS feed for {{.Header.Title}}" /> | |
| 44 | - | {{if .WithStyles}} | |
| 45 | - | <link rel="stylesheet" href="/smol.css" /> | |
| 46 | - | {{else}} | |
| 47 | - | {{end}} | |
| 48 | 44 | <link rel="stylesheet" href="/syntax.css" /> | |
| 49 | - | {{if .HasCSS}}<link rel="stylesheet" href="{{.CssURL}}" />{{end}} | |
| 45 | + | <link rel="stylesheet" href="{{.CssURL}}" /> | |
| 50 | 46 | {{end}} | |
| 51 | 47 | ||
| 52 | 48 | {{define "attrs"}}id="blog" class="layout-{{.Header.Layout}}"{{end}} |
+1
-5
pkg/apps/prose/html/post.page.tmpl
#
| ... | ... | @@ -41,11 +41,7 @@ | |
| 41 | 41 | {{if .Description}}<meta property="twitter:description" content="{{.Description}}">{{end}} | |
| 42 | 42 | ||
| 43 | 43 | <link rel="stylesheet" href="/syntax.css" /> | |
| 44 | - | {{if .WithStyles}} | |
| 45 | - | <link rel="stylesheet" href="/smol.css" /> | |
| 46 | - | {{else}} | |
| 47 | - | {{end}} | |
| 48 | - | {{if .HasCSS}}<link rel="stylesheet" href="{{.CssURL}}" />{{end}} | |
| 44 | + | <link rel="stylesheet" href="{{.CssURL}}" /> | |
| 49 | 45 | {{end}} | |
| 50 | 46 | ||
| 51 | 47 | {{define "attrs"}}id="post" class="{{.Slug}}"{{end}} |