- commit
- bc3e29b
- parent
- bb90d2e
- author
- Eric Bower
- date
- 2022-11-07 21:18:41 +0000 UTC
feat(lists): layout support Introduced parity with prose for different layouts. Right now we support "default" and "aside".
20 files changed,
+280,
-68
M
smol.css
+28,
-0
1@@ -324,6 +324,22 @@ figure {
2 flex: 1;
3 }
4
5+.layout-aside {
6+ max-width: 50rem;
7+}
8+
9+.layout-aside aside {
10+ width: 200px;
11+}
12+
13+.layout-aside img {
14+ border-radius: 5px;
15+}
16+
17+#readme {
18+ display: none;
19+}
20+
21 @media only screen and (max-width: 600px) {
22 body {
23 padding: 1rem;
24@@ -332,4 +348,16 @@ figure {
25 header {
26 margin: 0;
27 }
28+
29+ .layout-aside main {
30+ flex-direction: column;
31+ }
32+
33+ aside {
34+ display: none;
35+ }
36+
37+ #readme {
38+ display: block;
39+ }
40 }
+9,
-0
1@@ -77,6 +77,7 @@ type HeaderTxt struct {
2 Title string
3 Bio string
4 Nav []*ListItem
5+ Layout string
6 HasItems bool
7 }
8
9@@ -140,6 +141,8 @@ func blogHandler(w http.ResponseWriter, r *http.Request) {
10 curl := shared.CreateURLFromRequest(cfg, r)
11
12 ts, err := shared.RenderTemplate(cfg, []string{
13+ cfg.StaticPath("html/blog-default.partial.tmpl"),
14+ cfg.StaticPath("html/blog-aside.partial.tmpl"),
15 cfg.StaticPath("html/blog.page.tmpl"),
16 cfg.StaticPath("html/list.partial.tmpl"),
17 })
18@@ -165,6 +168,10 @@ func blogHandler(w http.ResponseWriter, r *http.Request) {
19 headerTxt.Bio = parsedText.MetaData.Description
20 }
21
22+ if parsedText.MetaData.Layout != "" {
23+ headerTxt.Layout = parsedText.MetaData.Layout
24+ }
25+
26 headerTxt.Nav = parsedText.Items
27 if len(headerTxt.Nav) > 0 {
28 headerTxt.HasItems = true
29@@ -388,6 +395,8 @@ func transparencyHandler(w http.ResponseWriter, r *http.Request) {
30 cfg.StaticPath("html/footer.partial.tmpl"),
31 cfg.StaticPath("html/marketing-footer.partial.tmpl"),
32 cfg.StaticPath("html/base.layout.tmpl"),
33+ cfg.StaticPath("html/base-aside.layout.tmpl"),
34+ cfg.StaticPath("html/base-default.layout.tmpl"),
35 )
36
37 if err != nil {
+1,
-1
1@@ -13,6 +13,6 @@
2
3 <link rel="stylesheet" href="/main.css" />
4 </head>
5- <body>{{template "body" .}}</body>
6+ <body {{template "attrs" .}}>{{template "body" .}}</body>
7 </html>
8 {{end}}
+65,
-0
1@@ -0,0 +1,65 @@
2+{{define "blog-aside"}}
3+<main class="flex">
4+ <section class="flex-1 mr">
5+ <div>
6+ <h1 class="text-2xl font-bold">{{.Header.Title}}</h1>
7+ {{if .Header.Bio}}<span>{{.Header.Bio}}</span>{{end}}
8+ </div>
9+
10+ <div id="readme">
11+ {{if .Readme.HasItems}}
12+ <section>
13+ <article>
14+ {{template "list" .Readme}}
15+ </article>
16+ <hr />
17+ </section>
18+ {{end}}
19+
20+ <div>
21+ {{range .Header.Nav}}
22+ {{if .IsURL}}
23+ <a href="{{.URL}}" class="text-lg">{{.Value}}</a> |
24+ {{end}}
25+ {{end}}
26+ <a href="{{.RSSURL}}" class="text-lg">rss</a>
27+ </div>
28+ <hr />
29+ </div>
30+
31+ {{if .HasFilter}}
32+ <a href={{.URL}}>clear filters</a>
33+ {{end}}
34+
35+ <div class="posts">
36+ {{range .Posts}}
37+ <article class="my">
38+ <div class="flex items-center">
39+ <time datetime="{{.PublishAtISO}}" class="font-italic text-sm post-date">{{.PublishAt}}</time>
40+ <div class="font-bold flex-1"><a href="{{.URL}}">{{.Title}}</a></div>
41+ </div>
42+ </article>
43+ {{end}}
44+ </div>
45+ </section>
46+
47+ <aside>
48+ {{if .Readme.HasItems}}
49+ <section>
50+ <article>
51+ {{template "list" .Readme}}
52+ </article>
53+ </section>
54+ {{end}}
55+
56+ <nav>
57+ {{range .Header.Nav}}
58+ {{if .IsURL}}
59+ <a href="{{.URL}}" class="text-lg">{{.Value}}</a> ยท
60+ {{end}}
61+ {{end}}
62+ <a href="{{.RSSURL}}" class="text-lg">rss</a>
63+ </nav>
64+ </aside>
65+</main>
66+{{end}}
+39,
-0
1@@ -0,0 +1,39 @@
2+{{define "blog-default"}}
3+<header class="text-center">
4+ <h1 class="text-2xl font-bold">{{.Header.Title}}</h1>
5+ {{if .Header.Bio}}<p class="text-lg">{{.Header.Bio}}</p>{{end}}
6+ <nav>
7+ {{range .Header.Nav}}
8+ {{if .IsURL}}
9+ <a href="{{.URL}}" class="text-lg">{{.Value}}</a> |
10+ {{end}}
11+ {{end}}
12+ <a href="{{.RSSURL}}" class="text-lg">rss</a>
13+ </nav>
14+ <hr />
15+</header>
16+<main>
17+ {{if .Readme.HasItems}}
18+ <section>
19+ <article>
20+ {{template "list" .Readme}}
21+ </article>
22+ <hr />
23+ </section>
24+ {{end}}
25+
26+ <section class="posts">
27+ {{if .HasFilter}}
28+ <a href="{{.URL}}">clear filters</a>
29+ {{end}}
30+ {{range .Posts}}
31+ <article class="my">
32+ <div class="flex items-center">
33+ <time datetime="{{.UpdatedAtISO}}" class="font-italic text-sm post-date">{{.UpdatedTimeAgo}}</time>
34+ <div class="font-bold flex-1"><a href="{{.URL}}">{{.Title}}</a></div>
35+ </div>
36+ </article>
37+ {{end}}
38+ </section>
39+</main>
40+{{end}}
+8,
-36
1@@ -23,43 +23,15 @@
2 <meta name="twitter:image:src" content="https://{{.Site.Domain}}/card.png" />
3 {{end}}
4
5+{{define "attrs"}}id="blog" class="layout-{{.Header.Layout}}"{{end}}
6+
7 {{define "body"}}
8-<header class="text-center">
9- <h1 class="text-2xl font-bold">{{.Header.Title}}</h1>
10- {{if .Header.Bio}}<p class="text-lg">{{.Header.Bio}}</p>{{end}}
11- <nav>
12- {{range .Header.Nav}}
13- {{if .IsURL}}
14- <a href="{{.URL}}" class="text-lg">{{.Value}}</a> |
15- {{end}}
16- {{end}}
17- <a href="{{.RSSURL}}" class="text-lg">rss</a>
18- </nav>
19- <hr />
20-</header>
21-<main>
22- {{if .Readme.HasItems}}
23- <section>
24- <article>
25- {{template "list" .Readme}}
26- </article>
27- <hr />
28- </section>
29- {{end}}
30
31- <section class="posts">
32- {{if .HasFilter}}
33- <a href="{{.URL}}">clear filters</a>
34- {{end}}
35- {{range .Posts}}
36- <article class="my">
37- <div class="flex items-center">
38- <time datetime="{{.UpdatedAtISO}}" class="font-italic text-sm post-date">{{.UpdatedTimeAgo}}</time>
39- <div class="font-bold flex-1"><a href="{{.URL}}">{{.Title}}</a></div>
40- </div>
41- </article>
42- {{end}}
43- </section>
44-</main>
45+{{if eq .Header.Layout "aside"}}
46+ {{template "blog-aside" .}}
47+{{else}}
48+ {{template "blog-default" .}}
49+{{end}}
50+
51 {{template "footer" .}}
52 {{end}}
+2,
-0
1@@ -6,6 +6,8 @@
2 <meta name="description" content="questions and answers" />
3 {{end}}
4
5+{{define "attrs"}}{{end}}
6+
7 {{define "body"}}
8 <header>
9 <h1 class="text-2xl">Need help?</h1>
+2,
-0
1@@ -24,6 +24,8 @@
2 <meta property="og:image" content="https://{{.Site.Domain}}/card.png" />
3 {{end}}
4
5+{{define "attrs"}}{{end}}
6+
7 {{define "body"}}
8 <header class="text-center">
9 <h1 class="text-2xl font-bold">{{.Site.Domain}}</h1>
+2,
-0
1@@ -23,6 +23,8 @@
2 <meta name="twitter:image:src" content="https://{{.Site.Domain}}/card.png" />
3 {{end}}
4
5+{{define "attrs"}}{{end}}
6+
7 {{define "body"}}
8 <header>
9 <h1 class="text-2xl font-bold">{{.Title}}</h1>
+2,
-0
1@@ -6,6 +6,8 @@
2 <meta name="description" content="{{.Site.Domain}} privacy policy" />
3 {{end}}
4
5+{{define "attrs"}}{{end}}
6+
7 {{define "body"}}
8 <header>
9 <h1 class="text-2xl">Privacy</h1>
+2,
-0
1@@ -6,6 +6,8 @@
2 <meta name="description" content="discover interesting lists" />
3 {{end}}
4
5+{{define "attrs"}}{{end}}
6+
7 {{define "body"}}
8 <header class="text-center">
9 <h1 class="text-2xl font-bold">read</h1>
+2,
-0
1@@ -6,6 +6,8 @@
2 <meta name="description" content="a specification for lists" />
3 {{end}}
4
5+{{define "attrs"}}{{end}}
6+
7 {{define "body"}}
8 <header>
9 <h1 class="text-2xl">Plain text list</h1>
+2,
-0
1@@ -6,6 +6,8 @@
2 <meta name="description" content="full transparency of analytics and cost at {{.Site.Domain}}" />
3 {{end}}
4
5+{{define "attrs"}}{{end}}
6+
7 {{define "body"}}
8 <header>
9 <h1 class="text-2xl">Transparency</h1>
+4,
-0
1@@ -35,6 +35,7 @@ type MetaData struct {
2 PublishAt *time.Time
3 Title string
4 Description string
5+ Layout string
6 Tags []string
7 ListType string // https://developer.mozilla.org/en-US/docs/Web/CSS/list-style-type
8 }
9@@ -101,6 +102,8 @@ func TokenToMetaField(meta *MetaData, token *SplitToken) {
10 for _, tag := range tags {
11 meta.Tags = append(meta.Tags, strings.TrimSpace(tag))
12 }
13+ } else if token.Key == "layout" {
14+ meta.Layout = token.Value
15 }
16 }
17
18@@ -179,6 +182,7 @@ func ParseText(text string) *ParsedText {
19 meta := MetaData{
20 ListType: "disc",
21 Tags: []string{},
22+ Layout: "default",
23 }
24 pre := false
25 skip := false
+28,
-0
1@@ -324,6 +324,22 @@ figure {
2 flex: 1;
3 }
4
5+.layout-aside {
6+ max-width: 50rem;
7+}
8+
9+.layout-aside aside {
10+ width: 200px;
11+}
12+
13+.layout-aside img {
14+ border-radius: 5px;
15+}
16+
17+#readme {
18+ display: none;
19+}
20+
21 @media only screen and (max-width: 600px) {
22 body {
23 padding: 1rem;
24@@ -332,4 +348,16 @@ figure {
25 header {
26 margin: 0;
27 }
28+
29+ .layout-aside main {
30+ flex-direction: column;
31+ }
32+
33+ aside {
34+ display: none;
35+ }
36+
37+ #readme {
38+ display: block;
39+ }
40 }
+28,
-0
1@@ -324,6 +324,22 @@ figure {
2 flex: 1;
3 }
4
5+.layout-aside {
6+ max-width: 50rem;
7+}
8+
9+.layout-aside aside {
10+ width: 200px;
11+}
12+
13+.layout-aside img {
14+ border-radius: 5px;
15+}
16+
17+#readme {
18+ display: none;
19+}
20+
21 @media only screen and (max-width: 600px) {
22 body {
23 padding: 1rem;
24@@ -332,4 +348,16 @@ figure {
25 header {
26 margin: 0;
27 }
28+
29+ .layout-aside main {
30+ flex-direction: column;
31+ }
32+
33+ aside {
34+ display: none;
35+ }
36+
37+ #readme {
38+ display: block;
39+ }
40 }
+0,
-1
1@@ -463,7 +463,6 @@ func transparencyHandler(w http.ResponseWriter, r *http.Request) {
2
3 ts, err := template.ParseFiles(
4 cfg.StaticPath("html/transparency.page.tmpl"),
5- cfg.StaticPath("html/base.layout.tmpl"),
6 cfg.StaticPath("html/footer.partial.tmpl"),
7 cfg.StaticPath("html/marketing-footer.partial.tmpl"),
8 cfg.StaticPath("html/base.layout.tmpl"),
+28,
-0
1@@ -324,6 +324,22 @@ figure {
2 flex: 1;
3 }
4
5+.layout-aside {
6+ max-width: 50rem;
7+}
8+
9+.layout-aside aside {
10+ width: 200px;
11+}
12+
13+.layout-aside img {
14+ border-radius: 5px;
15+}
16+
17+#readme {
18+ display: none;
19+}
20+
21 @media only screen and (max-width: 600px) {
22 body {
23 padding: 1rem;
24@@ -332,4 +348,16 @@ figure {
25 header {
26 margin: 0;
27 }
28+
29+ .layout-aside main {
30+ flex-direction: column;
31+ }
32+
33+ aside {
34+ display: none;
35+ }
36+
37+ #readme {
38+ display: block;
39+ }
40 }
+0,
-30
1@@ -33,33 +33,3 @@ table {
2 font-weight: bold;
3 padding: 0.6rem 0 0 0;
4 }
5-
6-.layout-aside {
7- max-width: 50rem;
8-}
9-
10-.layout-aside aside {
11- width: 200px;
12-}
13-
14-.layout-aside img {
15- border-radius: 5px;
16-}
17-
18-#readme {
19- display: none;
20-}
21-
22-@media only screen and (max-width: 600px) {
23- .layout-aside main {
24- flex-direction: column;
25- }
26-
27- #readme {
28- display: block;
29- }
30-
31- aside {
32- display: none;
33- }
34-}
M
smol.css
+28,
-0
1@@ -324,6 +324,22 @@ figure {
2 flex: 1;
3 }
4
5+.layout-aside {
6+ max-width: 50rem;
7+}
8+
9+.layout-aside aside {
10+ width: 200px;
11+}
12+
13+.layout-aside img {
14+ border-radius: 5px;
15+}
16+
17+#readme {
18+ display: none;
19+}
20+
21 @media only screen and (max-width: 600px) {
22 body {
23 padding: 1rem;
24@@ -332,4 +348,16 @@ figure {
25 header {
26 margin: 0;
27 }
28+
29+ .layout-aside main {
30+ flex-direction: column;
31+ }
32+
33+ aside {
34+ display: none;
35+ }
36+
37+ #readme {
38+ display: block;
39+ }
40 }