Skip to content

Commit f0eea03

Browse files
delaneyjbencroker
andauthored
Make title dynamic in site (#277)
* Make title dynamic in site Fixes #263 * Update meta tags --------- Co-authored-by: Ben Croker <[email protected]>
1 parent 63482a9 commit f0eea03

File tree

9 files changed

+76
-49
lines changed

9 files changed

+76
-49
lines changed

code/go/site/routes_bundler.templ

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import (
1010
)
1111

1212
templ PageBundler(r *http.Request, manifest PluginManifest, store *BundlerStore) {
13-
@Page() {
13+
@Page("Bundler", "Bundle only the plugins you need to reduce the size of Datastar even further.") {
1414
@header(r)
1515
<div data-store={ templ.JSONString(store) } class="p-8 flex flex-col gap-4">
1616
<div>

code/go/site/routes_essays.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import (
1212

1313
func setupEssays(ctx context.Context, router chi.Router) error {
1414

15-
mdElementRenderers, _, err := markdownRenders(ctx, "essays")
15+
mdDataset, err := markdownRenders(ctx, "essays")
1616
if err != nil {
1717
return err
1818
}
@@ -65,7 +65,7 @@ func setupEssays(ctx context.Context, router chi.Router) error {
6565

6666
essaysRouter.Get("/{name}", func(w http.ResponseWriter, r *http.Request) {
6767
name := chi.URLParam(r, "name")
68-
contents, ok := mdElementRenderers[name]
68+
mdData, ok := mdDataset[name]
6969
if !ok {
7070
http.Error(w, "not found", http.StatusNotFound)
7171
return
@@ -81,7 +81,7 @@ func setupEssays(ctx context.Context, router chi.Router) error {
8181
}
8282
}
8383

84-
SidebarPage(r, sidebarGroups, currentLink, contents).Render(r.Context(), w)
84+
SidebarPage(r, sidebarGroups, currentLink, mdData.Title, mdData.Description, mdData.Contents).Render(r.Context(), w)
8585
})
8686
})
8787

code/go/site/routes_examples.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ var (
2020
)
2121

2222
func setupExamples(ctx context.Context, router chi.Router, store sessions.Store, ns *embeddednats.Server) (err error) {
23-
mdElementRenderers, _, err := markdownRenders(ctx, "examples")
23+
mdDataset, err := markdownRenders(ctx, "examples")
2424
if err != nil {
2525
return err
2626
}
@@ -134,7 +134,7 @@ func setupExamples(ctx context.Context, router chi.Router, store sessions.Store,
134134
examplesRouter.Get("/{name}", func(w http.ResponseWriter, r *http.Request) {
135135
ctx := r.Context()
136136
name := chi.URLParam(r, "name")
137-
contents, ok := mdElementRenderers[name]
137+
mdData, ok := mdDataset[name]
138138
if !ok {
139139
http.Error(w, "not found", http.StatusNotFound)
140140
return
@@ -150,7 +150,7 @@ func setupExamples(ctx context.Context, router chi.Router, store sessions.Store,
150150
}
151151
}
152152

153-
SidebarPage(r, sidebarGroups, currentLink, contents).Render(ctx, w)
153+
SidebarPage(r, sidebarGroups, currentLink, mdData.Title, mdData.Description, mdData.Contents).Render(ctx, w)
154154
})
155155

156156
if err := errors.Join(

code/go/site/routes_guide.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import (
1111
)
1212

1313
func setupGuide(ctx context.Context, router chi.Router) error {
14-
mdElementRenderers, _, err := markdownRenders(ctx, "guide")
14+
mdDataset, err := markdownRenders(ctx, "guide")
1515
if err != nil {
1616
return err
1717
}
@@ -56,7 +56,7 @@ func setupGuide(ctx context.Context, router chi.Router) error {
5656

5757
essaysRouter.Get("/{name}", func(w http.ResponseWriter, r *http.Request) {
5858
name := chi.URLParam(r, "name")
59-
contents, ok := mdElementRenderers[name]
59+
mdData, ok := mdDataset[name]
6060
if !ok {
6161
http.Error(w, "not found", http.StatusNotFound)
6262
return
@@ -72,7 +72,7 @@ func setupGuide(ctx context.Context, router chi.Router) error {
7272
}
7373
}
7474

75-
SidebarPage(r, sidebarGroups, currentLink, contents).Render(r.Context(), w)
75+
SidebarPage(r, sidebarGroups, currentLink, mdData.Title, mdData.Description, mdData.Contents).Render(r.Context(), w)
7676
})
7777
})
7878

code/go/site/routes_home.templ

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,10 @@ templ Home() {
1111
{{
1212
cdnText := `<script type="module" src="https://cdn.jsdelivr.net/gh/starfederation/datastar/bundles/datastar.js"></script>`
1313
}}
14-
@Page() {
14+
@Page(
15+
"A real-time hypermedia framework",
16+
"Datastar helps you build real-time web applications with the simplicity of server-side rendering and the power of a full-stack SPA framework.",
17+
) {
1518
<div class="flex flex-col w-full min-h-screen bg-base-200 md:bg-gradient-to-br md:items-center from-base-300 to-base-100">
1619
<div class="flex flex-col items-stretch gap-7 p-4 md:pt-8 md:max-w-3xl max-w-none">
1720
<div class="flex flex-col items-center gap-7">

code/go/site/routes_memes.templ

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ package site
33
import "net/http"
44

55
templ PageMemes(r *http.Request, memes ...string) {
6-
@Page() {
6+
@Page("Hot fresh memes", "The most wasted of all days is one without laughter.") {
77
@header(r)
88
<div class="flex flex-col gap-4 p-8">
99
<div class="text-4xl font-bold text-center">Memes</div>

code/go/site/routes_reference.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import (
1111
)
1212

1313
func setupReferenceRoutes(ctx context.Context, router chi.Router) error {
14-
mdElementRenderers, _, err := markdownRenders(ctx, "reference")
14+
mdDataset, err := markdownRenders(ctx, "reference")
1515
if err != nil {
1616
return err
1717
}
@@ -62,7 +62,7 @@ func setupReferenceRoutes(ctx context.Context, router chi.Router) error {
6262

6363
essaysRouter.Get("/{name}", func(w http.ResponseWriter, r *http.Request) {
6464
name := chi.URLParam(r, "name")
65-
contents, ok := mdElementRenderers[name]
65+
mdData, ok := mdDataset[name]
6666
if !ok {
6767
http.Error(w, "not found", http.StatusNotFound)
6868
return
@@ -78,7 +78,7 @@ func setupReferenceRoutes(ctx context.Context, router chi.Router) error {
7878
}
7979
}
8080

81-
SidebarPage(r, sidebarGroups, currentLink, contents).Render(r.Context(), w)
81+
SidebarPage(r, sidebarGroups, currentLink, mdData.Title, mdData.Description, mdData.Contents).Render(r.Context(), w)
8282
})
8383
})
8484

code/go/site/shared.templ

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,32 +8,33 @@ import (
88
"strings"
99
)
1010

11-
templ Page() {
11+
templ Page(title, description string) {
1212
<!DOCTYPE html>
1313
<html lang="en">
1414
<head>
15-
<title>Datastar – A real-time hypermedia framework</title>
15+
<title>{ title }</title>
16+
<meta name="description" content={ description }/>
1617
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
1718
<link href={ staticPath("css/site.css") } rel="stylesheet" type="text/css"/>
1819
<link rel="preconnect" href="https://fonts.googleapis.com"/>
1920
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin/>
2021
<link href="https://fonts.googleapis.com/css2?family=Fira+Code:[email protected]&family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&family=Orbitron:[email protected]&display=swap" rel="stylesheet"/>
2122
<link rel="apple-touch-icon" sizes="180x180" href={ staticPath("favicon/apple-touch-icon.png") }/>
22-
<link rel="icon" type="image/png" sizes="32x32" href={ staticPath("favicon/favicon-32x32.png") }/>
23-
<link rel="icon" type="image/png" sizes="16x16" href={ staticPath("favicon/favicon-16x16.png") }/>
24-
<link rel="manifest" href={ staticPath("favicon/site.webmanifest") }/>
25-
<meta property="og:title" content="Datastar"/>
26-
<meta property="og:description" content="A real-time hypermedia framework."/>
27-
<meta property="og:image" content={ staticAbsolutePath("images/rocket.webp") }/>
28-
<meta property="og:url" content="https://data-star.dev/"/>
29-
<meta property="og:type" content="website"/>
30-
<meta property="og:site_name" content="Datastar"/>
31-
<meta name="twitter:card" content="summary">
32-
<meta name="twitter:title" content="Datastar">
33-
<meta name="twitter:description" content="A real-time hypermedia framework.">
34-
<meta name="twitter:image" content={ staticAbsolutePath("images/rocket.webp") }>
35-
<meta name="twitter:site" content="@DelaneyGillilan">
36-
<meta name="twitter:creator" content="@DelaneyGillilan">
23+
<link rel="icon" type="image/png" sizes="32x32" href={ staticPath("favicon/favicon-32x32.png") }/>
24+
<link rel="icon" type="image/png" sizes="16x16" href={ staticPath("favicon/favicon-16x16.png") }/>
25+
<link rel="manifest" href={ staticPath("favicon/site.webmanifest") }/>
26+
<meta property="og:title" content={ title }/>
27+
<meta property="og:description" content={ description }/>
28+
<meta property="og:image" content={ staticAbsolutePath("images/rocket.webp") }/>
29+
<meta property="og:url" content="https://data-star.dev/"/>
30+
<meta property="og:type" content="website"/>
31+
<meta property="og:site_name" content="Datastar"/>
32+
<meta name="twitter:card" content="summary"/>
33+
<meta name="twitter:title" content={ title }/>
34+
<meta name="twitter:description" content={ description }/>
35+
<meta name="twitter:image" content={ staticAbsolutePath("images/rocket.webp") }/>
36+
<meta name="twitter:site" content="@DelaneyGillilan"/>
37+
<meta name="twitter:creator" content="@DelaneyGillilan"/>
3738
<script src="https://code.iconify.design/iconify-icon/2.1.0/iconify-icon.min.js"></script>
3839
<script type="module" src={ staticPath("js/datastar.js") }></script>
3940
<style>
@@ -149,8 +150,11 @@ type SidebarGroup struct {
149150
Links []*SidebarLink
150151
}
151152

152-
templ SidebarPage(r *http.Request, sidebarGroups []*SidebarGroup, current *SidebarLink, contents string) {
153-
@Page() {
153+
templ SidebarPage(
154+
r *http.Request, sidebarGroups []*SidebarGroup, current *SidebarLink,
155+
title, description, contents string,
156+
) {
157+
@Page(title, description) {
154158
@highlightCSS
155159
<div class="drawer">
156160
<input id="sidebar-drawer" type="checkbox" class="drawer-toggle"/>

code/go/site/shared_partials.go

Lines changed: 35 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -46,20 +46,28 @@ type CodeSnippetBlock struct {
4646
Snippets []CodeSnippet
4747
}
4848

49-
func markdownRenders(ctx context.Context, staticMdPath string) (mdElementRenderers map[string]string, mdAnchors map[string][]string, err error) {
49+
type MarkdownData struct {
50+
Anchors []string
51+
Title string
52+
Description string
53+
Contents string
54+
}
55+
type MarkdownDataset map[string]*MarkdownData
56+
57+
func markdownRenders(ctx context.Context, staticMdPath string) (MarkdownDataset, error) {
5058
if mdRenderer == nil {
5159
htmlFormatter := html.New(html.WithClasses(true), html.TabWidth(2))
5260
if htmlFormatter == nil {
53-
return nil, nil, fmt.Errorf("couldn't create html formatter")
61+
return nil, fmt.Errorf("couldn't create html formatter")
5462
}
5563
styleName := "nord"
5664
highlightStyle := styles.Get(styleName)
5765
if highlightStyle == nil {
58-
return nil, nil, fmt.Errorf("couldn't find style %s", styleName)
66+
return nil, fmt.Errorf("couldn't find style %s", styleName)
5967
}
6068
highlightCSSBuffer := &bytes.Buffer{}
6169
if err := htmlFormatter.WriteCSS(highlightCSSBuffer, highlightStyle); err != nil {
62-
return nil, nil, fmt.Errorf("error writing highlight css: %w", err)
70+
return nil, fmt.Errorf("error writing highlight css: %w", err)
6371
}
6472
highlightCSS = templ.ComponentFunc(func(ctx context.Context, w io.Writer) error {
6573
_, err := io.WriteString(w, fmt.Sprintf(`<style>%s</style>`, highlightCSSBuffer.String()))
@@ -124,7 +132,7 @@ func markdownRenders(ctx context.Context, staticMdPath string) (mdElementRendere
124132
mdDir := "static/md/" + staticMdPath
125133
docs, err := staticFS.ReadDir(mdDir)
126134
if err != nil {
127-
return nil, nil, fmt.Errorf("error reading docs dir: %w", err)
135+
return nil, fmt.Errorf("error reading docs dir: %w", err)
128136
}
129137

130138
// regExpImg := regexp.MustCompile(`(?P<whole>!\[[^\]]+]\((?P<path>[^)]+)\))`)
@@ -133,14 +141,16 @@ func markdownRenders(ctx context.Context, staticMdPath string) (mdElementRendere
133141
codeSnippets := regexp.MustCompile(`!!!CODE_SNIPPET:(?<basePath>[^!]*)!!!`)
134142
// Icon or mascot from https://icones.js.org/collection/vscode-icons
135143

136-
mdElementRenderers = map[string]string{}
137-
mdAnchors = map[string][]string{}
144+
res := MarkdownDataset{}
145+
146+
titleTrimmer := regexp.MustCompile(`^#+\s*`)
147+
138148
for _, de := range docs {
139149
fullPath := mdDir + "/" + de.Name()
140150

141151
b, err := staticFS.ReadFile(fullPath)
142152
if err != nil {
143-
return nil, nil, fmt.Errorf("error reading doc %s: %w", de.Name(), err)
153+
return nil, fmt.Errorf("error reading doc %s: %w", de.Name(), err)
144154
}
145155

146156
// Package version
@@ -155,10 +165,10 @@ func markdownRenders(ctx context.Context, staticMdPath string) (mdElementRendere
155165
baseDir := filepath.Dir(fullWithTestExtension)
156166
fileEntries, err := staticFS.ReadDir(baseDir)
157167
if err != nil {
158-
return nil, nil, fmt.Errorf("error reading code snippet dir %s: %w", baseDir, err)
168+
return nil, fmt.Errorf("error reading code snippet dir %s: %w", baseDir, err)
159169
}
160170
if len(fileEntries) == 0 {
161-
return nil, nil, fmt.Errorf("no files found in code snippet dir %s", baseDir)
171+
return nil, fmt.Errorf("no files found in code snippet dir %s", baseDir)
162172
}
163173

164174
snippetBlock := CodeSnippetBlock{
@@ -178,15 +188,15 @@ func markdownRenders(ctx context.Context, staticMdPath string) (mdElementRendere
178188

179189
codeSnippetRaw, err := staticFS.ReadFile(fileFullPath)
180190
if err != nil {
181-
return nil, nil, fmt.Errorf("error reading code snippet %s: %w", fileFullPath, err)
191+
return nil, fmt.Errorf("error reading code snippet %s: %w", fileFullPath, err)
182192
}
183193
codeSnippet := string(codeSnippetRaw)
184194

185195
buf := bytebufferpool.Get()
186196
defer bytebufferpool.Put(buf)
187197

188198
if err := htmlHighlight(buf, codeSnippet, ext, ""); err != nil {
189-
return nil, nil, fmt.Errorf("error highlighting code snippet %s: %w", fileFullPath, err)
199+
return nil, fmt.Errorf("error highlighting code snippet %s: %w", fileFullPath, err)
190200
}
191201

192202
icon := ""
@@ -220,11 +230,16 @@ func markdownRenders(ctx context.Context, staticMdPath string) (mdElementRendere
220230
b = bytes.ReplaceAll(b, fullMatch, buf.Bytes())
221231
}
222232

233+
title := ""
234+
223235
// Get all anchors
224236
anchors := []string{}
225237
lines := strings.Split(string(b), "\n")
226238
for _, line := range lines {
227239
if strings.HasPrefix(line, "#") {
240+
if title == "" {
241+
title = titleTrimmer.ReplaceAllString(line, "")
242+
}
228243
parts := strings.Split(line, " ")
229244
anchor := strings.Join(parts[1:], " ")
230245
anchors = append(anchors, anchor)
@@ -236,11 +251,16 @@ func markdownRenders(ctx context.Context, staticMdPath string) (mdElementRendere
236251
renderedHTML := string(markdown.Render(doc, mdRenderer()))
237252

238253
name := de.Name()[0 : len(de.Name())-3]
239-
mdElementRenderers[name] = renderedHTML
240-
mdAnchors[name] = anchors
254+
255+
res[name] = &MarkdownData{
256+
Anchors: anchors,
257+
Title: title,
258+
Description: "",
259+
Contents: renderedHTML,
260+
}
241261
}
242262

243-
return mdElementRenderers, mdAnchors, nil
263+
return res, nil
244264
}
245265

246266
func KVPairsAttrs(kvPairs ...string) templ.Attributes {

0 commit comments

Comments
 (0)