An experimental IndieWeb site built in Go.

add post page styles, extract sidebar layout

+2 -2
handlers/routes.go
··· 18 18 panic(result.Error) 19 19 } 20 20 21 - layouts.RenderDefault("", pages.Home(posts)).ServeHTTP(w, r) 21 + layouts.RenderWithSidebar("", pages.Home(posts)).ServeHTTP(w, r) 22 22 } 23 23 24 24 func ServePostPage(w http.ResponseWriter, r *http.Request) { ··· 32 32 return 33 33 } 34 34 35 - layouts.RenderDefault(string(post.MicroformatType), pages.Post(post)).ServeHTTP(w, r) 35 + layouts.RenderWithSidebar(string(post.MicroformatType), pages.Post(post)).ServeHTTP(w, r) 36 36 }
+21
html/components/head.templ
··· 1 + package components 2 + 3 + import "github.com/puregarlic/space/storage" 4 + 5 + templ Head(title string) { 6 + <head> 7 + if len(title) > 0 { 8 + <title>{ title } | puregarlic dot space</title> 9 + } else { 10 + <title>puregarlic dot space</title> 11 + } 12 + <meta name="viewport" content="width=device-width, initial-scale=1"/> 13 + <link rel="preconnect" href="https://fonts.googleapis.com"/> 14 + <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin/> 15 + <link href="https://fonts.googleapis.com/css2?family=Recursive:slnt,wght,CASL,CRSV,MONO@-15..0,300..1000,0..1,0..1,0..1&display=swap" rel="stylesheet"/> 16 + for _, rel := range storage.GetRels() { 17 + <link rel={ rel.Name } href={ rel.HREF }/> 18 + } 19 + <link rel="stylesheet" href="/static/styles.css"/> 20 + </head> 21 + }
+101
html/components/head_templ.go
··· 1 + // Code generated by templ - DO NOT EDIT. 2 + 3 + // templ: version: v0.2.747 4 + package components 5 + 6 + //lint:file-ignore SA4006 This context is only used if a nested component is present. 7 + 8 + import "github.com/a-h/templ" 9 + import templruntime "github.com/a-h/templ/runtime" 10 + 11 + import "github.com/puregarlic/space/storage" 12 + 13 + func Head(title string) templ.Component { 14 + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { 15 + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context 16 + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) 17 + if !templ_7745c5c3_IsBuffer { 18 + defer func() { 19 + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) 20 + if templ_7745c5c3_Err == nil { 21 + templ_7745c5c3_Err = templ_7745c5c3_BufErr 22 + } 23 + }() 24 + } 25 + ctx = templ.InitializeContext(ctx) 26 + templ_7745c5c3_Var1 := templ.GetChildren(ctx) 27 + if templ_7745c5c3_Var1 == nil { 28 + templ_7745c5c3_Var1 = templ.NopComponent 29 + } 30 + ctx = templ.ClearChildren(ctx) 31 + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 1) 32 + if templ_7745c5c3_Err != nil { 33 + return templ_7745c5c3_Err 34 + } 35 + if len(title) > 0 { 36 + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 2) 37 + if templ_7745c5c3_Err != nil { 38 + return templ_7745c5c3_Err 39 + } 40 + var templ_7745c5c3_Var2 string 41 + templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(title) 42 + if templ_7745c5c3_Err != nil { 43 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `html/components/head.templ`, Line: 8, Col: 17} 44 + } 45 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2)) 46 + if templ_7745c5c3_Err != nil { 47 + return templ_7745c5c3_Err 48 + } 49 + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 3) 50 + if templ_7745c5c3_Err != nil { 51 + return templ_7745c5c3_Err 52 + } 53 + } else { 54 + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 4) 55 + if templ_7745c5c3_Err != nil { 56 + return templ_7745c5c3_Err 57 + } 58 + } 59 + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 5) 60 + if templ_7745c5c3_Err != nil { 61 + return templ_7745c5c3_Err 62 + } 63 + for _, rel := range storage.GetRels() { 64 + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 6) 65 + if templ_7745c5c3_Err != nil { 66 + return templ_7745c5c3_Err 67 + } 68 + var templ_7745c5c3_Var3 string 69 + templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(rel.Name) 70 + if templ_7745c5c3_Err != nil { 71 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `html/components/head.templ`, Line: 17, Col: 23} 72 + } 73 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) 74 + if templ_7745c5c3_Err != nil { 75 + return templ_7745c5c3_Err 76 + } 77 + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 7) 78 + if templ_7745c5c3_Err != nil { 79 + return templ_7745c5c3_Err 80 + } 81 + var templ_7745c5c3_Var4 string 82 + templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(rel.HREF) 83 + if templ_7745c5c3_Err != nil { 84 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `html/components/head.templ`, Line: 17, Col: 41} 85 + } 86 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) 87 + if templ_7745c5c3_Err != nil { 88 + return templ_7745c5c3_Err 89 + } 90 + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 8) 91 + if templ_7745c5c3_Err != nil { 92 + return templ_7745c5c3_Err 93 + } 94 + } 95 + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 9) 96 + if templ_7745c5c3_Err != nil { 97 + return templ_7745c5c3_Err 98 + } 99 + return templ_7745c5c3_Err 100 + }) 101 + }
+4 -6
html/components/posts/note.templ
··· 1 1 package posts 2 2 3 - import ( 4 - "github.com/puregarlic/space/models" 5 - ) 3 + import "github.com/puregarlic/space/models" 6 4 7 5 templ Note(post *models.Post) { 8 - <div class="bg-surface p-4"> 9 - {GetPostJSONProperty(post, "content")[0]} 10 - </div> 6 + <div class="bg-surface p-4 first:rounded-t last:rounded-b border-2 border-overlay"> 7 + { GetPostJSONProperty(post, "content")[0] } 8 + </div> 11 9 }
+4 -6
html/components/posts/note_templ.go
··· 8 8 import "github.com/a-h/templ" 9 9 import templruntime "github.com/a-h/templ/runtime" 10 10 11 - import ( 12 - "github.com/puregarlic/space/models" 13 - ) 11 + import "github.com/puregarlic/space/models" 14 12 15 13 func Note(post *models.Post) templ.Component { 16 14 return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { ··· 30 28 templ_7745c5c3_Var1 = templ.NopComponent 31 29 } 32 30 ctx = templ.ClearChildren(ctx) 33 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"bg-surface p-4\">") 31 + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 1) 34 32 if templ_7745c5c3_Err != nil { 35 33 return templ_7745c5c3_Err 36 34 } 37 35 var templ_7745c5c3_Var2 string 38 36 templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(GetPostJSONProperty(post, "content")[0]) 39 37 if templ_7745c5c3_Err != nil { 40 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `html/components/posts/note.templ`, Line: 9, Col: 43} 38 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `html/components/posts/note.templ`, Line: 7, Col: 43} 41 39 } 42 40 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2)) 43 41 if templ_7745c5c3_Err != nil { 44 42 return templ_7745c5c3_Err 45 43 } 46 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>") 44 + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 2) 47 45 if templ_7745c5c3_Err != nil { 48 46 return templ_7745c5c3_Err 49 47 }
+13 -15
html/components/posts/photo.templ
··· 1 1 package posts 2 2 3 - import ( 4 - "github.com/puregarlic/space/models" 5 - ) 3 + import "github.com/puregarlic/space/models" 6 4 7 5 templ Photo(post *models.Post) { 8 - <div class="bg-base"> 9 - for index, photo := range GetPostJSONProperty(post, "photo") { 10 - <figure class="relative group"> 11 - <img class="w-full" src={photo} /> 12 - <figcaption 13 - class="p-4 absolute inset-x-0 bottom-0 opacity-100 group-hover:opacity-0 bg-surface/70 backdrop-blur transition" 14 - > 15 - {GetPostJSONProperty(post, "content")[index]} 16 - </figcaption> 17 - </figure> 18 - } 19 - </div> 6 + <div class="bg-base"> 7 + for index, photo := range GetPostJSONProperty(post, "photo") { 8 + <figure class="relative group last:rounded-b"> 9 + <img class="w-full border-x-2 border-overlay group-first:rounded-t group-first:border-t-2" src={ photo }/> 10 + <figcaption 11 + class="p-4 bg-surface group-last:rounded-b group-last:border-b-2 group-last:border-x-2 group-last:border-overlay" 12 + > 13 + { GetPostJSONProperty(post, "content")[index] } 14 + </figcaption> 15 + </figure> 16 + } 17 + </div> 20 18 }
+8 -10
html/components/posts/photo_templ.go
··· 8 8 import "github.com/a-h/templ" 9 9 import templruntime "github.com/a-h/templ/runtime" 10 10 11 - import ( 12 - "github.com/puregarlic/space/models" 13 - ) 11 + import "github.com/puregarlic/space/models" 14 12 15 13 func Photo(post *models.Post) templ.Component { 16 14 return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { ··· 30 28 templ_7745c5c3_Var1 = templ.NopComponent 31 29 } 32 30 ctx = templ.ClearChildren(ctx) 33 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"bg-base\">") 31 + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 1) 34 32 if templ_7745c5c3_Err != nil { 35 33 return templ_7745c5c3_Err 36 34 } 37 35 for index, photo := range GetPostJSONProperty(post, "photo") { 38 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<figure class=\"relative group\"><img class=\"w-full\" src=\"") 36 + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 2) 39 37 if templ_7745c5c3_Err != nil { 40 38 return templ_7745c5c3_Err 41 39 } 42 40 var templ_7745c5c3_Var2 string 43 41 templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(photo) 44 42 if templ_7745c5c3_Err != nil { 45 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `html/components/posts/photo.templ`, Line: 11, Col: 35} 43 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `html/components/posts/photo.templ`, Line: 9, Col: 106} 46 44 } 47 45 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2)) 48 46 if templ_7745c5c3_Err != nil { 49 47 return templ_7745c5c3_Err 50 48 } 51 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"><figcaption class=\"p-4 absolute inset-x-0 bottom-0 opacity-100 group-hover:opacity-0 bg-surface/70 backdrop-blur transition\">") 49 + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 3) 52 50 if templ_7745c5c3_Err != nil { 53 51 return templ_7745c5c3_Err 54 52 } 55 53 var templ_7745c5c3_Var3 string 56 54 templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(GetPostJSONProperty(post, "content")[index]) 57 55 if templ_7745c5c3_Err != nil { 58 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `html/components/posts/photo.templ`, Line: 15, Col: 52} 56 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `html/components/posts/photo.templ`, Line: 13, Col: 50} 59 57 } 60 58 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) 61 59 if templ_7745c5c3_Err != nil { 62 60 return templ_7745c5c3_Err 63 61 } 64 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</figcaption></figure>") 62 + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 4) 65 63 if templ_7745c5c3_Err != nil { 66 64 return templ_7745c5c3_Err 67 65 } 68 66 } 69 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>") 67 + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 5) 70 68 if templ_7745c5c3_Err != nil { 71 69 return templ_7745c5c3_Err 72 70 }
+66 -50
html/components/posts/post.templ
··· 1 1 package posts 2 2 3 3 import ( 4 - "fmt" 5 4 "encoding/json" 6 - 7 - "github.com/puregarlic/space/models" 5 + "fmt" 8 6 9 - "github.com/samber/lo" 7 + "github.com/puregarlic/space/models" 8 + "github.com/samber/lo" 10 9 "go.hacdias.com/indielib/microformats" 11 10 ) 12 11 13 12 var ImplementedPostTypes = []microformats.Type{ 14 - microformats.TypeNote, 15 - microformats.TypePhoto, 13 + microformats.TypeNote, 14 + microformats.TypePhoto, 16 15 } 17 16 18 17 func GetPostJSONProperty(post *models.Post, name string) []string { 19 - var tmp map[string]any 20 - if err := json.Unmarshal(post.Properties, &tmp); err != nil { 21 - panic(err) 22 - } 18 + var tmp map[string]any 19 + if err := json.Unmarshal(post.Properties, &tmp); err != nil { 20 + panic(err) 21 + } 23 22 24 - prop, ok := tmp[name] 25 - if !ok { 26 - return []string{""} 27 - } 23 + prop, ok := tmp[name] 24 + if !ok { 25 + return []string{""} 26 + } 28 27 29 - var out []string 30 - for _, val := range prop.([]any) { 31 - out = append(out, val.(string)) 32 - } 28 + var out []string 29 + for _, val := range prop.([]any) { 30 + out = append(out, val.(string)) 31 + } 33 32 34 - return out 33 + return out 35 34 } 36 35 37 36 func formatPostTypeName(mfType microformats.Type) string { 38 - has := lo.ContainsBy(ImplementedPostTypes, func(postType microformats.Type) bool { 39 - return postType == mfType 40 - }) 37 + has := lo.ContainsBy(ImplementedPostTypes, func(postType microformats.Type) bool { 38 + return postType == mfType 39 + }) 41 40 42 - if has { 43 - return string(mfType) 44 - } else { 45 - return fmt.Sprintf("oops! (%s)", string(mfType)) 46 - } 41 + if has { 42 + return string(mfType) 43 + } else { 44 + return fmt.Sprintf("%s (oops!)", string(mfType)) 45 + } 47 46 } 48 47 49 48 templ PostFeedHeader(post *models.Post) { 50 - <div class="px-3 py-2 bg-base text-xs text-subtle/50 group-hover:text-subtle/100 flex justify-between transition"> 51 - <p>{ formatPostTypeName(post.MicroformatType) }</p> 52 - <a 53 - class="hover:underline hover:text-iris flex gap-1" 54 - target="_blank" 55 - rel="noopener noreferrer" 56 - href={ templ.URL("/posts/" + post.ID.String()) } 57 - > 58 - { post.CreatedAt.Format("01/02/2006 at 3:04 PM") } 59 - <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="currentColor" class="size-4 -mt-px"> 60 - <path d="M6.22 8.72a.75.75 0 0 0 1.06 1.06l5.22-5.22v1.69a.75.75 0 0 0 1.5 0v-3.5a.75.75 0 0 0-.75-.75h-3.5a.75.75 0 0 0 0 1.5h1.69L6.22 8.72Z" /> 61 - <path d="M3.5 6.75c0-.69.56-1.25 1.25-1.25H7A.75.75 0 0 0 7 4H4.75A2.75 2.75 0 0 0 2 6.75v4.5A2.75 2.75 0 0 0 4.75 14h4.5A2.75 2.75 0 0 0 12 11.25V9a.75.75 0 0 0-1.5 0v2.25c0 .69-.56 1.25-1.25 1.25h-4.5c-.69 0-1.25-.56-1.25-1.25v-4.5Z" /> 62 - </svg> 63 - </a> 64 - </div> 49 + <div class="px-3 py-2 bg-surface text-xs text-muted flex items-center justify-between rounded-t border-2 border-b-0 border-overlay"> 50 + <p>{ post.Timestamp() }</p> 51 + <p class="flex gap-1.5"> 52 + { formatPostTypeName(post.MicroformatType) } 53 + <span class="text-muted/40">&#8226;</span> 54 + <a 55 + class="hover:underline hover:text-iris flex items-center gap-1 transition" 56 + target="_blank" 57 + rel="noopener noreferrer" 58 + href={ templ.URL("/posts/" + post.ID.String()) } 59 + > 60 + open 61 + <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="currentColor" class="size-4 -mt-px"> 62 + <path d="M6.22 8.72a.75.75 0 0 0 1.06 1.06l5.22-5.22v1.69a.75.75 0 0 0 1.5 0v-3.5a.75.75 0 0 0-.75-.75h-3.5a.75.75 0 0 0 0 1.5h1.69L6.22 8.72Z"></path> 63 + <path d="M3.5 6.75c0-.69.56-1.25 1.25-1.25H7A.75.75 0 0 0 7 4H4.75A2.75 2.75 0 0 0 2 6.75v4.5A2.75 2.75 0 0 0 4.75 14h4.5A2.75 2.75 0 0 0 12 11.25V9a.75.75 0 0 0-1.5 0v2.25c0 .69-.56 1.25-1.25 1.25h-4.5c-.69 0-1.25-.56-1.25-1.25v-4.5Z"></path> 64 + </svg> 65 + </a> 66 + </p> 67 + </div> 68 + } 69 + 70 + templ PostDetails(post *models.Post) { 71 + <dl class="grid md:grid-cols-2 gap-4"> 72 + <div> 73 + <dt class="mb-1 text-sm text-muted">Posted At</dt> 74 + <dd class="text-subtle">{ post.Timestamp() }</dd> 75 + </div> 76 + <div> 77 + <dt class="mb-1 text-sm text-muted">Post Type</dt> 78 + <dd class="text-subtle">{ string(post.MicroformatType) }</dd> 79 + </div> 80 + </dl> 65 81 } 66 82 67 83 templ PostContent(post *models.Post) { 68 - switch post.MicroformatType { 69 - case microformats.TypePhoto: 70 - @Photo(post) 71 - case microformats.TypeNote: 72 - @Note(post) 73 - default: 74 - @Unsupported(post) 75 - } 84 + switch post.MicroformatType { 85 + case microformats.TypePhoto: 86 + @Photo(post) 87 + case microformats.TypeNote: 88 + @Note(post) 89 + default: 90 + @Unsupported(post) 91 + } 76 92 }
+67 -16
html/components/posts/post_templ.go
··· 13 13 "fmt" 14 14 15 15 "github.com/puregarlic/space/models" 16 - 17 16 "github.com/samber/lo" 18 17 "go.hacdias.com/indielib/microformats" 19 18 ) ··· 50 49 if has { 51 50 return string(mfType) 52 51 } else { 53 - return fmt.Sprintf("oops! (%s)", string(mfType)) 52 + return fmt.Sprintf("%s (oops!)", string(mfType)) 54 53 } 55 54 } 56 55 ··· 72 71 templ_7745c5c3_Var1 = templ.NopComponent 73 72 } 74 73 ctx = templ.ClearChildren(ctx) 75 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"px-3 py-2 bg-base text-xs text-subtle/50 group-hover:text-subtle/100 flex justify-between transition\"><p>") 74 + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 1) 76 75 if templ_7745c5c3_Err != nil { 77 76 return templ_7745c5c3_Err 78 77 } 79 78 var templ_7745c5c3_Var2 string 80 - templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(formatPostTypeName(post.MicroformatType)) 79 + templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(post.Timestamp()) 81 80 if templ_7745c5c3_Err != nil { 82 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `html/components/posts/post.templ`, Line: 51, Col: 49} 81 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `html/components/posts/post.templ`, Line: 50, Col: 23} 83 82 } 84 83 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2)) 85 84 if templ_7745c5c3_Err != nil { 86 85 return templ_7745c5c3_Err 87 86 } 88 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</p><a class=\"hover:underline hover:text-iris flex gap-1\" target=\"_blank\" rel=\"noopener noreferrer\" href=\"") 87 + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 2) 89 88 if templ_7745c5c3_Err != nil { 90 89 return templ_7745c5c3_Err 91 90 } 92 - var templ_7745c5c3_Var3 templ.SafeURL = templ.URL("/posts/" + post.ID.String()) 93 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var3))) 91 + var templ_7745c5c3_Var3 string 92 + templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(formatPostTypeName(post.MicroformatType)) 94 93 if templ_7745c5c3_Err != nil { 95 - return templ_7745c5c3_Err 94 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `html/components/posts/post.templ`, Line: 52, Col: 45} 96 95 } 97 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">") 96 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) 98 97 if templ_7745c5c3_Err != nil { 99 98 return templ_7745c5c3_Err 100 99 } 101 - var templ_7745c5c3_Var4 string 102 - templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(post.CreatedAt.Format("01/02/2006 at 3:04 PM")) 100 + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 3) 103 101 if templ_7745c5c3_Err != nil { 104 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `html/components/posts/post.templ`, Line: 58, Col: 53} 102 + return templ_7745c5c3_Err 105 103 } 106 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) 104 + var templ_7745c5c3_Var4 templ.SafeURL = templ.URL("/posts/" + post.ID.String()) 105 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var4))) 107 106 if templ_7745c5c3_Err != nil { 108 107 return templ_7745c5c3_Err 109 108 } 110 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 16 16\" fill=\"currentColor\" class=\"size-4 -mt-px\"><path d=\"M6.22 8.72a.75.75 0 0 0 1.06 1.06l5.22-5.22v1.69a.75.75 0 0 0 1.5 0v-3.5a.75.75 0 0 0-.75-.75h-3.5a.75.75 0 0 0 0 1.5h1.69L6.22 8.72Z\"></path> <path d=\"M3.5 6.75c0-.69.56-1.25 1.25-1.25H7A.75.75 0 0 0 7 4H4.75A2.75 2.75 0 0 0 2 6.75v4.5A2.75 2.75 0 0 0 4.75 14h4.5A2.75 2.75 0 0 0 12 11.25V9a.75.75 0 0 0-1.5 0v2.25c0 .69-.56 1.25-1.25 1.25h-4.5c-.69 0-1.25-.56-1.25-1.25v-4.5Z\"></path></svg></a></div>") 109 + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 4) 111 110 if templ_7745c5c3_Err != nil { 112 111 return templ_7745c5c3_Err 113 112 } ··· 115 114 }) 116 115 } 117 116 118 - func PostContent(post *models.Post) templ.Component { 117 + func PostDetails(post *models.Post) templ.Component { 119 118 return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { 120 119 templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context 121 120 templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) ··· 131 130 templ_7745c5c3_Var5 := templ.GetChildren(ctx) 132 131 if templ_7745c5c3_Var5 == nil { 133 132 templ_7745c5c3_Var5 = templ.NopComponent 133 + } 134 + ctx = templ.ClearChildren(ctx) 135 + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 5) 136 + if templ_7745c5c3_Err != nil { 137 + return templ_7745c5c3_Err 138 + } 139 + var templ_7745c5c3_Var6 string 140 + templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(post.Timestamp()) 141 + if templ_7745c5c3_Err != nil { 142 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `html/components/posts/post.templ`, Line: 74, Col: 45} 143 + } 144 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6)) 145 + if templ_7745c5c3_Err != nil { 146 + return templ_7745c5c3_Err 147 + } 148 + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 6) 149 + if templ_7745c5c3_Err != nil { 150 + return templ_7745c5c3_Err 151 + } 152 + var templ_7745c5c3_Var7 string 153 + templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(string(post.MicroformatType)) 154 + if templ_7745c5c3_Err != nil { 155 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `html/components/posts/post.templ`, Line: 78, Col: 57} 156 + } 157 + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7)) 158 + if templ_7745c5c3_Err != nil { 159 + return templ_7745c5c3_Err 160 + } 161 + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 7) 162 + if templ_7745c5c3_Err != nil { 163 + return templ_7745c5c3_Err 164 + } 165 + return templ_7745c5c3_Err 166 + }) 167 + } 168 + 169 + func PostContent(post *models.Post) templ.Component { 170 + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { 171 + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context 172 + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) 173 + if !templ_7745c5c3_IsBuffer { 174 + defer func() { 175 + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) 176 + if templ_7745c5c3_Err == nil { 177 + templ_7745c5c3_Err = templ_7745c5c3_BufErr 178 + } 179 + }() 180 + } 181 + ctx = templ.InitializeContext(ctx) 182 + templ_7745c5c3_Var8 := templ.GetChildren(ctx) 183 + if templ_7745c5c3_Var8 == nil { 184 + templ_7745c5c3_Var8 = templ.NopComponent 134 185 } 135 186 ctx = templ.ClearChildren(ctx) 136 187 switch post.MicroformatType {
+29 -30
html/components/posts/unsupported.templ
··· 1 1 package posts 2 2 3 3 import ( 4 - "bytes" 5 - "encoding/json" 4 + "bytes" 5 + "encoding/json" 6 6 7 - "github.com/puregarlic/space/models" 8 - 9 - "github.com/alecthomas/chroma/v2/formatters/html" 10 - "github.com/alecthomas/chroma/v2/styles" 11 - "github.com/alecthomas/chroma/v2/lexers" 7 + "github.com/alecthomas/chroma/v2/formatters/html" 8 + "github.com/alecthomas/chroma/v2/lexers" 9 + "github.com/alecthomas/chroma/v2/styles" 10 + "github.com/puregarlic/space/models" 12 11 ) 13 12 14 13 var style = styles.Get("rose-pine") ··· 18 17 var dedupeSyntaxStyles = templ.NewOnceHandle() 19 18 20 19 func renderPostAsJSON(post *models.Post) string { 21 - contents, err := json.MarshalIndent(post.Properties, "", " ") 22 - if err != nil { 23 - panic(err) 24 - } 20 + contents, err := json.MarshalIndent(post.Properties, "", " ") 21 + if err != nil { 22 + panic(err) 23 + } 25 24 26 - iterator, err := lexer.Tokenise(nil, string(contents)) 25 + iterator, err := lexer.Tokenise(nil, string(contents)) 27 26 28 - var buf bytes.Buffer 29 - formatter.Format(&buf, style, iterator) 27 + var buf bytes.Buffer 28 + formatter.Format(&buf, style, iterator) 30 29 31 - return buf.String() 30 + return buf.String() 32 31 } 33 32 34 33 func generateSyntaxClassNames() string { 35 - var buf bytes.Buffer 36 - if err := formatter.WriteCSS(&buf, style); err != nil { 37 - panic(err) 38 - } 39 - 40 - return "<style>"+buf.String()+"</style>" 34 + var buf bytes.Buffer 35 + if err := formatter.WriteCSS(&buf, style); err != nil { 36 + panic(err) 37 + } 38 + 39 + return "<style>" + buf.String() + "</style>" 41 40 } 42 41 43 42 templ syntaxStyleTag() { 44 - @templ.Raw(generateSyntaxClassNames()) 43 + @templ.Raw(generateSyntaxClassNames()) 45 44 } 46 45 47 46 templ Unsupported(post *models.Post) { 48 - <div 49 - class="block p-4 bg-base overflow-x-scroll min-w-0" 50 - > 51 - @dedupeSyntaxStyles.Once() { 52 - @syntaxStyleTag() 53 - } 54 - @templ.Raw(renderPostAsJSON(post)) 55 - </div> 47 + <div 48 + class="block p-4 bg-base overflow-x-scroll min-w-0 first:rounded-t last:rounded-b border-2 border-overlay" 49 + > 50 + @dedupeSyntaxStyles.Once() { 51 + @syntaxStyleTag() 52 + } 53 + @templ.Raw(renderPostAsJSON(post)) 54 + </div> 56 55 }
+3 -4
html/components/posts/unsupported_templ.go
··· 12 12 "bytes" 13 13 "encoding/json" 14 14 15 - "github.com/puregarlic/space/models" 16 - 17 15 "github.com/alecthomas/chroma/v2/formatters/html" 18 16 "github.com/alecthomas/chroma/v2/lexers" 19 17 "github.com/alecthomas/chroma/v2/styles" 18 + "github.com/puregarlic/space/models" 20 19 ) 21 20 22 21 var style = styles.Get("rose-pine") ··· 92 91 templ_7745c5c3_Var2 = templ.NopComponent 93 92 } 94 93 ctx = templ.ClearChildren(ctx) 95 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"block p-4 bg-base overflow-x-scroll min-w-0\">") 94 + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 1) 96 95 if templ_7745c5c3_Err != nil { 97 96 return templ_7745c5c3_Err 98 97 } ··· 122 121 if templ_7745c5c3_Err != nil { 123 122 return templ_7745c5c3_Err 124 123 } 125 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>") 124 + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 2) 126 125 if templ_7745c5c3_Err != nil { 127 126 return templ_7745c5c3_Err 128 127 }
+12
html/components/sidebar.templ
··· 1 + package components 2 + 3 + templ Sidebar() { 4 + <aside class="min-w-0"> 5 + <div class="w-full md:sticky md:top-8"> 6 + <h1 class="font-extrabold text-xl">puregarlic dot space</h1> 7 + <p class="font-light mt-3 text-subtle italic md:text-sm"> 8 + this space is mine, it was <a class="underline hover:text-iris" href="https://github.com/puregarlic/space">made by me</a>! 9 + </p> 10 + </div> 11 + </aside> 12 + }
+35
html/components/sidebar_templ.go
··· 1 + // Code generated by templ - DO NOT EDIT. 2 + 3 + // templ: version: v0.2.747 4 + package components 5 + 6 + //lint:file-ignore SA4006 This context is only used if a nested component is present. 7 + 8 + import "github.com/a-h/templ" 9 + import templruntime "github.com/a-h/templ/runtime" 10 + 11 + func Sidebar() templ.Component { 12 + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { 13 + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context 14 + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) 15 + if !templ_7745c5c3_IsBuffer { 16 + defer func() { 17 + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) 18 + if templ_7745c5c3_Err == nil { 19 + templ_7745c5c3_Err = templ_7745c5c3_BufErr 20 + } 21 + }() 22 + } 23 + ctx = templ.InitializeContext(ctx) 24 + templ_7745c5c3_Var1 := templ.GetChildren(ctx) 25 + if templ_7745c5c3_Var1 == nil { 26 + templ_7745c5c3_Var1 = templ.NopComponent 27 + } 28 + ctx = templ.ClearChildren(ctx) 29 + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 1) 30 + if templ_7745c5c3_Err != nil { 31 + return templ_7745c5c3_Err 32 + } 33 + return templ_7745c5c3_Err 34 + }) 35 + }
+14 -29
html/layouts/default.templ
··· 1 1 package layouts 2 2 3 - import "net/http" 4 - import "github.com/puregarlic/space/storage" 3 + import ( 4 + "github.com/puregarlic/space/html/components" 5 + "net/http" 6 + ) 5 7 6 8 func RenderDefault(title string, page templ.Component) http.Handler { 7 - rels := storage.GetRels() 8 - document := Default(title, page, rels) 9 + document := Default(title, page) 9 10 10 - return templ.Handler(document) 11 + return templ.Handler(document) 11 12 } 12 13 13 - templ Default(title string, body templ.Component, rels []*storage.RelEntry) { 14 - <!DOCTYPE html> 15 - <html> 16 - <head> 17 - if len(title) > 0 { 18 - <title>{title} | puregarlic dot space</title> 19 - } else { 20 - <title>puregarlic dot space</title> 21 - } 22 - <meta name="viewport" content="width=device-width, initial-scale=1" /> 23 - <link rel="preconnect" href="https://fonts.googleapis.com" /> 24 - <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin /> 25 - <link href="https://fonts.googleapis.com/css2?family=Recursive:slnt,wght,CASL,CRSV,MONO@-15..0,300..1000,0..1,0..1,0..1&display=swap" rel="stylesheet"> 26 - 27 - for _, rel := range rels { 28 - <link rel={ rel.Name } href={ rel.HREF } /> 29 - } 30 - 31 - <link rel="stylesheet" href="/static/styles.css" /> 32 - </head> 33 - <body class="text-text bg-base"> 34 - @body 35 - </body> 36 - </html> 14 + templ Default(title string, body templ.Component) { 15 + <!DOCTYPE html> 16 + <html> 17 + @components.Head(title) 18 + <body class="px-4 py-12 md:py-20 text-text bg-base"> 19 + @body 20 + </body> 21 + </html> 37 22 }
+10 -65
html/layouts/default_templ.go
··· 8 8 import "github.com/a-h/templ" 9 9 import templruntime "github.com/a-h/templ/runtime" 10 10 11 - import "net/http" 12 - import "github.com/puregarlic/space/storage" 11 + import ( 12 + "github.com/puregarlic/space/html/components" 13 + "net/http" 14 + ) 13 15 14 16 func RenderDefault(title string, page templ.Component) http.Handler { 15 - rels := storage.GetRels() 16 - document := Default(title, page, rels) 17 + document := Default(title, page) 17 18 18 19 return templ.Handler(document) 19 20 } 20 21 21 - func Default(title string, body templ.Component, rels []*storage.RelEntry) templ.Component { 22 + func Default(title string, body templ.Component) templ.Component { 22 23 return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { 23 24 templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context 24 25 templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) ··· 36 37 templ_7745c5c3_Var1 = templ.NopComponent 37 38 } 38 39 ctx = templ.ClearChildren(ctx) 39 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<!doctype html><html><head>") 40 + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 1) 40 41 if templ_7745c5c3_Err != nil { 41 42 return templ_7745c5c3_Err 42 43 } 43 - if len(title) > 0 { 44 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<title>") 45 - if templ_7745c5c3_Err != nil { 46 - return templ_7745c5c3_Err 47 - } 48 - var templ_7745c5c3_Var2 string 49 - templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(title) 50 - if templ_7745c5c3_Err != nil { 51 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `html/layouts/default.templ`, Line: 18, Col: 21} 52 - } 53 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2)) 54 - if templ_7745c5c3_Err != nil { 55 - return templ_7745c5c3_Err 56 - } 57 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" | puregarlic dot space</title>") 58 - if templ_7745c5c3_Err != nil { 59 - return templ_7745c5c3_Err 60 - } 61 - } else { 62 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<title>puregarlic dot space</title>") 63 - if templ_7745c5c3_Err != nil { 64 - return templ_7745c5c3_Err 65 - } 66 - } 67 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"><link rel=\"preconnect\" href=\"https://fonts.googleapis.com\"><link rel=\"preconnect\" href=\"https://fonts.gstatic.com\" crossorigin><link href=\"https://fonts.googleapis.com/css2?family=Recursive:slnt,wght,CASL,CRSV,MONO@-15..0,300..1000,0..1,0..1,0..1&amp;display=swap\" rel=\"stylesheet\">") 44 + templ_7745c5c3_Err = components.Head(title).Render(ctx, templ_7745c5c3_Buffer) 68 45 if templ_7745c5c3_Err != nil { 69 46 return templ_7745c5c3_Err 70 47 } 71 - for _, rel := range rels { 72 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<link rel=\"") 73 - if templ_7745c5c3_Err != nil { 74 - return templ_7745c5c3_Err 75 - } 76 - var templ_7745c5c3_Var3 string 77 - templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(rel.Name) 78 - if templ_7745c5c3_Err != nil { 79 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `html/layouts/default.templ`, Line: 28, Col: 28} 80 - } 81 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) 82 - if templ_7745c5c3_Err != nil { 83 - return templ_7745c5c3_Err 84 - } 85 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\" href=\"") 86 - if templ_7745c5c3_Err != nil { 87 - return templ_7745c5c3_Err 88 - } 89 - var templ_7745c5c3_Var4 string 90 - templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(rel.HREF) 91 - if templ_7745c5c3_Err != nil { 92 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `html/layouts/default.templ`, Line: 28, Col: 46} 93 - } 94 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) 95 - if templ_7745c5c3_Err != nil { 96 - return templ_7745c5c3_Err 97 - } 98 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">") 99 - if templ_7745c5c3_Err != nil { 100 - return templ_7745c5c3_Err 101 - } 102 - } 103 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<link rel=\"stylesheet\" href=\"/static/styles.css\"></head><body class=\"text-text bg-base\">") 48 + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 2) 104 49 if templ_7745c5c3_Err != nil { 105 50 return templ_7745c5c3_Err 106 51 } ··· 108 53 if templ_7745c5c3_Err != nil { 109 54 return templ_7745c5c3_Err 110 55 } 111 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</body></html>") 56 + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 3) 112 57 if templ_7745c5c3_Err != nil { 113 58 return templ_7745c5c3_Err 114 59 }
+29
html/layouts/sidebar.templ
··· 1 + package layouts 2 + 3 + import ( 4 + "github.com/puregarlic/space/html/components" 5 + "net/http" 6 + ) 7 + 8 + func RenderWithSidebar(title string, body templ.Component) http.Handler { 9 + page := WithSidebar(title, body) 10 + 11 + return templ.Handler(page) 12 + } 13 + 14 + templ WithSidebar(title string, body templ.Component) { 15 + <!DOCTYPE html> 16 + <html> 17 + @components.Head(title) 18 + <body class="px-4 py-12 md:py-20 text-text bg-base"> 19 + <div class="mx-auto max-w-screen-lg grid md:grid-cols-[1fr_2fr] gap-12 gap-16"> 20 + <aside class="min-w-0"> 21 + @components.Sidebar() 22 + </aside> 23 + <main class="min-w-0"> 24 + @body 25 + </main> 26 + </div> 27 + </body> 28 + </html> 29 + }
+70
html/layouts/sidebar_templ.go
··· 1 + // Code generated by templ - DO NOT EDIT. 2 + 3 + // templ: version: v0.2.747 4 + package layouts 5 + 6 + //lint:file-ignore SA4006 This context is only used if a nested component is present. 7 + 8 + import "github.com/a-h/templ" 9 + import templruntime "github.com/a-h/templ/runtime" 10 + 11 + import ( 12 + "github.com/puregarlic/space/html/components" 13 + "net/http" 14 + ) 15 + 16 + func RenderWithSidebar(title string, body templ.Component) http.Handler { 17 + page := WithSidebar(title, body) 18 + 19 + return templ.Handler(page) 20 + } 21 + 22 + func WithSidebar(title string, body templ.Component) templ.Component { 23 + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { 24 + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context 25 + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) 26 + if !templ_7745c5c3_IsBuffer { 27 + defer func() { 28 + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) 29 + if templ_7745c5c3_Err == nil { 30 + templ_7745c5c3_Err = templ_7745c5c3_BufErr 31 + } 32 + }() 33 + } 34 + ctx = templ.InitializeContext(ctx) 35 + templ_7745c5c3_Var1 := templ.GetChildren(ctx) 36 + if templ_7745c5c3_Var1 == nil { 37 + templ_7745c5c3_Var1 = templ.NopComponent 38 + } 39 + ctx = templ.ClearChildren(ctx) 40 + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 1) 41 + if templ_7745c5c3_Err != nil { 42 + return templ_7745c5c3_Err 43 + } 44 + templ_7745c5c3_Err = components.Head(title).Render(ctx, templ_7745c5c3_Buffer) 45 + if templ_7745c5c3_Err != nil { 46 + return templ_7745c5c3_Err 47 + } 48 + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 2) 49 + if templ_7745c5c3_Err != nil { 50 + return templ_7745c5c3_Err 51 + } 52 + templ_7745c5c3_Err = components.Sidebar().Render(ctx, templ_7745c5c3_Buffer) 53 + if templ_7745c5c3_Err != nil { 54 + return templ_7745c5c3_Err 55 + } 56 + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 3) 57 + if templ_7745c5c3_Err != nil { 58 + return templ_7745c5c3_Err 59 + } 60 + templ_7745c5c3_Err = body.Render(ctx, templ_7745c5c3_Buffer) 61 + if templ_7745c5c3_Err != nil { 62 + return templ_7745c5c3_Err 63 + } 64 + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 4) 65 + if templ_7745c5c3_Err != nil { 66 + return templ_7745c5c3_Err 67 + } 68 + return templ_7745c5c3_Err 69 + }) 70 + }
+57 -66
html/pages/auth.templ
··· 1 1 package pages 2 2 3 3 import ( 4 - "strings" 5 - "go.hacdias.com/indielib/indieauth" 4 + "go.hacdias.com/indielib/indieauth" 5 + "strings" 6 6 ) 7 7 8 - templ Auth( req *indieauth.AuthenticationRequest, app *indieauth.ApplicationMetadata, nonceId string, nonce string ) { 9 - <div class="px-4 py-12 md:py-20 mx-auto max-w-screen-sm"> 10 - <p class="text-sm font-thin italic">authorize access to</p> 11 - <h1 class="mb-8 text-3xl font-extrabold">puregarlic dot space</h1> 12 - 13 - <div class="pt-6 border border-highlightMed rounded bg-surface"> 14 - if app != nil { 15 - <div class="px-6 flex gap-6 items-center"> 16 - if len(app.Logo) > 0 { 17 - <img class="max-w-12" src={ app.Logo } /> 18 - } 19 - 20 - <div> 21 - <h2 class="font-bold text-lg">{ app.Name }</h2> 22 - 23 - if len(app.Author) > 0 { 24 - <p class="text-sm font-light">by {app.Author}</p> 25 - } 26 - </div> 27 - </div> 28 - } else { 29 - <h2 class="px-6 font-bold text-subtle">unidentified client</h2> 30 - } 31 - 32 - <div class="mt-6 grid md:grid-cols-[max-content_1fr] *:border-highlightMed"> 33 - <h3 class="px-6 pt-4 pb-2 md:py-4 border-t bg-overlay md:border-r text-subtle font-bold">Client ID</h3> 34 - <p class="px-6 pb-4 pt-1 md:py-4 md:border-t bg-overlay min-w-0 overflow-x-scroll">{ req.ClientID }</p> 35 - 36 - <h3 class="px-6 pt-4 pb-2 md:py-4 border-t md:border-b md:border-r text-subtle font-bold">Redirect URL</h3> 37 - <p class="px-6 pb-4 pt-1 md:py-4 md:border-y min-w-0 overflow-x-scroll">{ req.RedirectURI}</p> 38 - 39 - <h3 class="px-6 pt-4 pb-2 md:py-4 border-t bg-overlay md:border-r text-subtle font-bold">Scopes</h3> 40 - <ul class="px-6 pb-4 pt-1 md:py-4 bg-overlay flex flex-wrap gap-3"> 41 - for _, scope := range req.Scopes { 42 - <li class="px-2 py-1 text-sm bg-pine rounded">{ scope }</li> 43 - } 44 - </ul> 45 - </div> 46 - </div> 47 - 48 - <form method='post' action='/authorization/accept'> 49 - <input type="hidden" name="response_type" value="code"/> 50 - <input type="hidden" name="scope" value={ strings.Join(req.Scopes, " ") }/> 51 - <input type="hidden" name="redirect_uri" value={ req.RedirectURI }/> 52 - <input type="hidden" name="client_id" value={ req.ClientID }/> 53 - <input type="hidden" name="state" value={ req.State }/> 54 - <input type="hidden" name="code_challenge" value={ req.CodeChallenge }/> 55 - <input type="hidden" name="code_challenge_method" value={ req.CodeChallengeMethod }/> 56 - 57 - // CSRF protections 58 - <input type="hidden" name="nonce_id" value={ nonceId }/> 59 - <input type="hidden" name="nonce" value={ nonce }/> 60 - 61 - <button 62 - class="mt-8 px-3 py-2 flex items-center justify-center gap-2 bg-surface border border-highlightMed text-sm font-bold transition rounded hover:bg-foam hover:text-surface" 63 - id="submit" 64 - > 65 - <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="currentColor" class="size-4"> 66 - <path fill-rule="evenodd" d="M8 15A7 7 0 1 0 8 1a7 7 0 0 0 0 14Zm3.844-8.791a.75.75 0 0 0-1.188-.918l-3.7 4.79-1.649-1.833a.75.75 0 1 0-1.114 1.004l2.25 2.5a.75.75 0 0 0 1.15-.043l4.25-5.5Z" clip-rule="evenodd" /> 67 - </svg> 68 - Authorize 69 - </button> 70 - </form> 71 - </div> 8 + templ Auth(req *indieauth.AuthenticationRequest, app *indieauth.ApplicationMetadata, nonceId string, nonce string) { 9 + <main class="mx-auto max-w-screen-sm"> 10 + <p class="text-sm font-thin italic">authorize access to</p> 11 + <h1 class="mb-8 text-3xl font-extrabold">puregarlic dot space</h1> 12 + <div class="pt-6 border border-highlightMed rounded bg-surface"> 13 + if app != nil { 14 + <div class="px-6 flex gap-6 items-center"> 15 + if len(app.Logo) > 0 { 16 + <img class="max-w-12" src={ app.Logo }/> 17 + } 18 + <div> 19 + <h2 class="font-bold text-lg">{ app.Name }</h2> 20 + if len(app.Author) > 0 { 21 + <p class="text-sm font-light">by { app.Author }</p> 22 + } 23 + </div> 24 + </div> 25 + } else { 26 + <h2 class="px-6 font-bold text-subtle">unidentified client</h2> 27 + } 28 + <div class="mt-6 grid md:grid-cols-[max-content_1fr] *:border-highlightMed"> 29 + <h3 class="px-6 pt-4 pb-2 md:py-4 border-t bg-overlay md:border-r text-subtle font-bold">Client ID</h3> 30 + <p class="px-6 pb-4 pt-1 md:py-4 md:border-t bg-overlay min-w-0 overflow-x-scroll">{ req.ClientID }</p> 31 + <h3 class="px-6 pt-4 pb-2 md:py-4 border-t md:border-b md:border-r text-subtle font-bold">Redirect URL</h3> 32 + <p class="px-6 pb-4 pt-1 md:py-4 md:border-y min-w-0 overflow-x-scroll">{ req.RedirectURI }</p> 33 + <h3 class="px-6 pt-4 pb-2 md:py-4 border-t bg-overlay md:border-r text-subtle font-bold">Scopes</h3> 34 + <ul class="px-6 pb-4 pt-1 md:py-4 bg-overlay flex flex-wrap gap-3"> 35 + for _, scope := range req.Scopes { 36 + <li class="px-2 py-1 text-sm bg-pine rounded">{ scope }</li> 37 + } 38 + </ul> 39 + </div> 40 + </div> 41 + <form method="post" action="/authorization/accept"> 42 + <input type="hidden" name="response_type" value="code"/> 43 + <input type="hidden" name="scope" value={ strings.Join(req.Scopes, " ") }/> 44 + <input type="hidden" name="redirect_uri" value={ req.RedirectURI }/> 45 + <input type="hidden" name="client_id" value={ req.ClientID }/> 46 + <input type="hidden" name="state" value={ req.State }/> 47 + <input type="hidden" name="code_challenge" value={ req.CodeChallenge }/> 48 + <input type="hidden" name="code_challenge_method" value={ req.CodeChallengeMethod }/> 49 + // CSRF protections 50 + <input type="hidden" name="nonce_id" value={ nonceId }/> 51 + <input type="hidden" name="nonce" value={ nonce }/> 52 + <button 53 + class="mt-8 px-3 py-2 flex items-center justify-center gap-2 bg-surface border border-highlightMed text-sm font-bold transition rounded hover:bg-foam hover:text-surface" 54 + id="submit" 55 + > 56 + <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="currentColor" class="size-4"> 57 + <path fill-rule="evenodd" d="M8 15A7 7 0 1 0 8 1a7 7 0 0 0 0 14Zm3.844-8.791a.75.75 0 0 0-1.188-.918l-3.7 4.79-1.649-1.833a.75.75 0 1 0-1.114 1.004l2.25 2.5a.75.75 0 0 0 1.15-.043l4.25-5.5Z" clip-rule="evenodd"></path> 58 + </svg> 59 + Authorize 60 + </button> 61 + </form> 62 + </main> 72 63 }
+38 -38
html/pages/auth_templ.go
··· 31 31 templ_7745c5c3_Var1 = templ.NopComponent 32 32 } 33 33 ctx = templ.ClearChildren(ctx) 34 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"px-4 py-12 md:py-20 mx-auto max-w-screen-sm\"><p class=\"text-sm font-thin italic\">authorize access to</p><h1 class=\"mb-8 text-3xl font-extrabold\">puregarlic dot space</h1><div class=\"pt-6 border border-highlightMed rounded bg-surface\">") 34 + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 1) 35 35 if templ_7745c5c3_Err != nil { 36 36 return templ_7745c5c3_Err 37 37 } 38 38 if app != nil { 39 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"px-6 flex gap-6 items-center\">") 39 + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 2) 40 40 if templ_7745c5c3_Err != nil { 41 41 return templ_7745c5c3_Err 42 42 } 43 43 if len(app.Logo) > 0 { 44 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<img class=\"max-w-12\" src=\"") 44 + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 3) 45 45 if templ_7745c5c3_Err != nil { 46 46 return templ_7745c5c3_Err 47 47 } 48 48 var templ_7745c5c3_Var2 string 49 49 templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(app.Logo) 50 50 if templ_7745c5c3_Err != nil { 51 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `html/pages/auth.templ`, Line: 17, Col: 46} 51 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `html/pages/auth.templ`, Line: 16, Col: 42} 52 52 } 53 53 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2)) 54 54 if templ_7745c5c3_Err != nil { 55 55 return templ_7745c5c3_Err 56 56 } 57 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">") 57 + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 4) 58 58 if templ_7745c5c3_Err != nil { 59 59 return templ_7745c5c3_Err 60 60 } 61 61 } 62 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div><h2 class=\"font-bold text-lg\">") 62 + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 5) 63 63 if templ_7745c5c3_Err != nil { 64 64 return templ_7745c5c3_Err 65 65 } 66 66 var templ_7745c5c3_Var3 string 67 67 templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(app.Name) 68 68 if templ_7745c5c3_Err != nil { 69 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `html/pages/auth.templ`, Line: 21, Col: 49} 69 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `html/pages/auth.templ`, Line: 19, Col: 46} 70 70 } 71 71 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) 72 72 if templ_7745c5c3_Err != nil { 73 73 return templ_7745c5c3_Err 74 74 } 75 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</h2>") 75 + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 6) 76 76 if templ_7745c5c3_Err != nil { 77 77 return templ_7745c5c3_Err 78 78 } 79 79 if len(app.Author) > 0 { 80 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<p class=\"text-sm font-light\">by ") 80 + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 7) 81 81 if templ_7745c5c3_Err != nil { 82 82 return templ_7745c5c3_Err 83 83 } 84 84 var templ_7745c5c3_Var4 string 85 85 templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(app.Author) 86 86 if templ_7745c5c3_Err != nil { 87 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `html/pages/auth.templ`, Line: 24, Col: 56} 87 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `html/pages/auth.templ`, Line: 21, Col: 52} 88 88 } 89 89 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) 90 90 if templ_7745c5c3_Err != nil { 91 91 return templ_7745c5c3_Err 92 92 } 93 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</p>") 93 + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 8) 94 94 if templ_7745c5c3_Err != nil { 95 95 return templ_7745c5c3_Err 96 96 } 97 97 } 98 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div></div>") 98 + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 9) 99 99 if templ_7745c5c3_Err != nil { 100 100 return templ_7745c5c3_Err 101 101 } 102 102 } else { 103 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<h2 class=\"px-6 font-bold text-subtle\">unidentified client</h2>") 103 + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 10) 104 104 if templ_7745c5c3_Err != nil { 105 105 return templ_7745c5c3_Err 106 106 } 107 107 } 108 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"mt-6 grid md:grid-cols-[max-content_1fr] *:border-highlightMed\"><h3 class=\"px-6 pt-4 pb-2 md:py-4 border-t bg-overlay md:border-r text-subtle font-bold\">Client ID</h3><p class=\"px-6 pb-4 pt-1 md:py-4 md:border-t bg-overlay min-w-0 overflow-x-scroll\">") 108 + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 11) 109 109 if templ_7745c5c3_Err != nil { 110 110 return templ_7745c5c3_Err 111 111 } 112 112 var templ_7745c5c3_Var5 string 113 113 templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(req.ClientID) 114 114 if templ_7745c5c3_Err != nil { 115 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `html/pages/auth.templ`, Line: 34, Col: 103} 115 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `html/pages/auth.templ`, Line: 30, Col: 101} 116 116 } 117 117 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5)) 118 118 if templ_7745c5c3_Err != nil { 119 119 return templ_7745c5c3_Err 120 120 } 121 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</p><h3 class=\"px-6 pt-4 pb-2 md:py-4 border-t md:border-b md:border-r text-subtle font-bold\">Redirect URL</h3><p class=\"px-6 pb-4 pt-1 md:py-4 md:border-y min-w-0 overflow-x-scroll\">") 121 + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 12) 122 122 if templ_7745c5c3_Err != nil { 123 123 return templ_7745c5c3_Err 124 124 } 125 125 var templ_7745c5c3_Var6 string 126 126 templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(req.RedirectURI) 127 127 if templ_7745c5c3_Err != nil { 128 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `html/pages/auth.templ`, Line: 37, Col: 95} 128 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `html/pages/auth.templ`, Line: 32, Col: 93} 129 129 } 130 130 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6)) 131 131 if templ_7745c5c3_Err != nil { 132 132 return templ_7745c5c3_Err 133 133 } 134 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</p><h3 class=\"px-6 pt-4 pb-2 md:py-4 border-t bg-overlay md:border-r text-subtle font-bold\">Scopes</h3><ul class=\"px-6 pb-4 pt-1 md:py-4 bg-overlay flex flex-wrap gap-3\">") 134 + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 13) 135 135 if templ_7745c5c3_Err != nil { 136 136 return templ_7745c5c3_Err 137 137 } 138 138 for _, scope := range req.Scopes { 139 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<li class=\"px-2 py-1 text-sm bg-pine rounded\">") 139 + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 14) 140 140 if templ_7745c5c3_Err != nil { 141 141 return templ_7745c5c3_Err 142 142 } 143 143 var templ_7745c5c3_Var7 string 144 144 templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(scope) 145 145 if templ_7745c5c3_Err != nil { 146 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `html/pages/auth.templ`, Line: 42, Col: 63} 146 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `html/pages/auth.templ`, Line: 36, Col: 59} 147 147 } 148 148 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7)) 149 149 if templ_7745c5c3_Err != nil { 150 150 return templ_7745c5c3_Err 151 151 } 152 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</li>") 152 + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 15) 153 153 if templ_7745c5c3_Err != nil { 154 154 return templ_7745c5c3_Err 155 155 } 156 156 } 157 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</ul></div></div><form method=\"post\" action=\"/authorization/accept\"><input type=\"hidden\" name=\"response_type\" value=\"code\"> <input type=\"hidden\" name=\"scope\" value=\"") 157 + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 16) 158 158 if templ_7745c5c3_Err != nil { 159 159 return templ_7745c5c3_Err 160 160 } 161 161 var templ_7745c5c3_Var8 string 162 162 templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(strings.Join(req.Scopes, " ")) 163 163 if templ_7745c5c3_Err != nil { 164 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `html/pages/auth.templ`, Line: 50, Col: 75} 164 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `html/pages/auth.templ`, Line: 43, Col: 74} 165 165 } 166 166 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8)) 167 167 if templ_7745c5c3_Err != nil { 168 168 return templ_7745c5c3_Err 169 169 } 170 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"> <input type=\"hidden\" name=\"redirect_uri\" value=\"") 170 + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 17) 171 171 if templ_7745c5c3_Err != nil { 172 172 return templ_7745c5c3_Err 173 173 } 174 174 var templ_7745c5c3_Var9 string 175 175 templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(req.RedirectURI) 176 176 if templ_7745c5c3_Err != nil { 177 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `html/pages/auth.templ`, Line: 51, Col: 68} 177 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `html/pages/auth.templ`, Line: 44, Col: 67} 178 178 } 179 179 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9)) 180 180 if templ_7745c5c3_Err != nil { 181 181 return templ_7745c5c3_Err 182 182 } 183 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"> <input type=\"hidden\" name=\"client_id\" value=\"") 183 + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 18) 184 184 if templ_7745c5c3_Err != nil { 185 185 return templ_7745c5c3_Err 186 186 } 187 187 var templ_7745c5c3_Var10 string 188 188 templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(req.ClientID) 189 189 if templ_7745c5c3_Err != nil { 190 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `html/pages/auth.templ`, Line: 52, Col: 62} 190 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `html/pages/auth.templ`, Line: 45, Col: 61} 191 191 } 192 192 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10)) 193 193 if templ_7745c5c3_Err != nil { 194 194 return templ_7745c5c3_Err 195 195 } 196 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"> <input type=\"hidden\" name=\"state\" value=\"") 196 + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 19) 197 197 if templ_7745c5c3_Err != nil { 198 198 return templ_7745c5c3_Err 199 199 } 200 200 var templ_7745c5c3_Var11 string 201 201 templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(req.State) 202 202 if templ_7745c5c3_Err != nil { 203 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `html/pages/auth.templ`, Line: 53, Col: 55} 203 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `html/pages/auth.templ`, Line: 46, Col: 54} 204 204 } 205 205 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11)) 206 206 if templ_7745c5c3_Err != nil { 207 207 return templ_7745c5c3_Err 208 208 } 209 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"> <input type=\"hidden\" name=\"code_challenge\" value=\"") 209 + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 20) 210 210 if templ_7745c5c3_Err != nil { 211 211 return templ_7745c5c3_Err 212 212 } 213 213 var templ_7745c5c3_Var12 string 214 214 templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(req.CodeChallenge) 215 215 if templ_7745c5c3_Err != nil { 216 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `html/pages/auth.templ`, Line: 54, Col: 72} 216 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `html/pages/auth.templ`, Line: 47, Col: 71} 217 217 } 218 218 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12)) 219 219 if templ_7745c5c3_Err != nil { 220 220 return templ_7745c5c3_Err 221 221 } 222 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"> <input type=\"hidden\" name=\"code_challenge_method\" value=\"") 222 + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 21) 223 223 if templ_7745c5c3_Err != nil { 224 224 return templ_7745c5c3_Err 225 225 } 226 226 var templ_7745c5c3_Var13 string 227 227 templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(req.CodeChallengeMethod) 228 228 if templ_7745c5c3_Err != nil { 229 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `html/pages/auth.templ`, Line: 55, Col: 85} 229 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `html/pages/auth.templ`, Line: 48, Col: 84} 230 230 } 231 231 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13)) 232 232 if templ_7745c5c3_Err != nil { 233 233 return templ_7745c5c3_Err 234 234 } 235 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"><input type=\"hidden\" name=\"nonce_id\" value=\"") 235 + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 22) 236 236 if templ_7745c5c3_Err != nil { 237 237 return templ_7745c5c3_Err 238 238 } 239 239 var templ_7745c5c3_Var14 string 240 240 templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(nonceId) 241 241 if templ_7745c5c3_Err != nil { 242 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `html/pages/auth.templ`, Line: 58, Col: 56} 242 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `html/pages/auth.templ`, Line: 50, Col: 55} 243 243 } 244 244 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14)) 245 245 if templ_7745c5c3_Err != nil { 246 246 return templ_7745c5c3_Err 247 247 } 248 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"> <input type=\"hidden\" name=\"nonce\" value=\"") 248 + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 23) 249 249 if templ_7745c5c3_Err != nil { 250 250 return templ_7745c5c3_Err 251 251 } 252 252 var templ_7745c5c3_Var15 string 253 253 templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(nonce) 254 254 if templ_7745c5c3_Err != nil { 255 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `html/pages/auth.templ`, Line: 59, Col: 51} 255 + return templ.Error{Err: templ_7745c5c3_Err, FileName: `html/pages/auth.templ`, Line: 51, Col: 50} 256 256 } 257 257 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15)) 258 258 if templ_7745c5c3_Err != nil { 259 259 return templ_7745c5c3_Err 260 260 } 261 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"> <button class=\"mt-8 px-3 py-2 flex items-center justify-center gap-2 bg-surface border border-highlightMed text-sm font-bold transition rounded hover:bg-foam hover:text-surface\" id=\"submit\"><svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 16 16\" fill=\"currentColor\" class=\"size-4\"><path fill-rule=\"evenodd\" d=\"M8 15A7 7 0 1 0 8 1a7 7 0 0 0 0 14Zm3.844-8.791a.75.75 0 0 0-1.188-.918l-3.7 4.79-1.649-1.833a.75.75 0 1 0-1.114 1.004l2.25 2.5a.75.75 0 0 0 1.15-.043l4.25-5.5Z\" clip-rule=\"evenodd\"></path></svg> Authorize</button></form></div>") 261 + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 24) 262 262 if templ_7745c5c3_Err != nil { 263 263 return templ_7745c5c3_Err 264 264 }
+16 -30
html/pages/home.templ
··· 1 1 package pages 2 2 3 3 import ( 4 - "github.com/puregarlic/space/models" 5 - p "github.com/puregarlic/space/html/components/posts" 4 + p "github.com/puregarlic/space/html/components/posts" 5 + "github.com/puregarlic/space/models" 6 6 ) 7 7 8 8 templ Home(posts []*models.Post) { 9 - <div class="px-4 py-12 md:py-20 md:mx-auto md:max-w-screen-lg grid md:grid-cols-[1fr_2fr] gap-12 md:gap-16"> 10 - <aside class="min-w-0"> 11 - <div class="w-full md:sticky md:top-8"> 12 - <h1 class="font-extrabold text-xl">puregarlic dot space</h1> 13 - <p class="font-light mt-3 text-subtle italic md:text-sm"> 14 - this space is mine, it was <a class="underline hover:text-iris" href="https://github.com/puregarlic/space">made by me</a>! 15 - </p> 16 - </div> 17 - </aside> 18 - <main class="min-w-0"> 19 - <ul class="flex flex-col gap-6 md:gap-12"> 20 - if len(posts) > 0 { 21 - for _, post := range posts { 22 - <li class="flex flex-col divide-y-2 divide-highlightLow group border-2 border-highlightLow"> 23 - @p.PostContent(post) 24 - @p.PostFeedHeader(post) 25 - </li> 26 - } 27 - } else { 28 - <li class="text-muted bg-surface px-4 py-8 text-center border border-highlightLow"> 29 - intention-rich, content-poor 30 - </li> 31 - } 32 - </ul> 33 - </main> 34 - </div> 35 - 9 + <ul class="flex flex-col gap-6"> 10 + if len(posts) > 0 { 11 + for _, post := range posts { 12 + <li class="flex flex-col"> 13 + @p.PostFeedHeader(post) 14 + @p.PostContent(post) 15 + </li> 16 + } 17 + } else { 18 + <li class="text-muted bg-surface px-4 py-8 text-center border border-overlay"> 19 + intention-rich, content-poor 20 + </li> 21 + } 22 + </ul> 36 23 } 37 -
+7 -7
html/pages/home_templ.go
··· 31 31 templ_7745c5c3_Var1 = templ.NopComponent 32 32 } 33 33 ctx = templ.ClearChildren(ctx) 34 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"px-4 py-12 md:py-20 md:mx-auto md:max-w-screen-lg grid md:grid-cols-[1fr_2fr] gap-12 md:gap-16\"><aside class=\"min-w-0\"><div class=\"w-full md:sticky md:top-8\"><h1 class=\"font-extrabold text-xl\">puregarlic dot space</h1><p class=\"font-light mt-3 text-subtle italic md:text-sm\">this space is mine, it was <a class=\"underline hover:text-iris\" href=\"https://github.com/puregarlic/space\">made by me</a>!</p></div></aside><main class=\"min-w-0\"><ul class=\"flex flex-col gap-6 md:gap-12\">") 34 + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 1) 35 35 if templ_7745c5c3_Err != nil { 36 36 return templ_7745c5c3_Err 37 37 } 38 38 if len(posts) > 0 { 39 39 for _, post := range posts { 40 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<li class=\"flex flex-col divide-y-2 divide-highlightLow group border-2 border-highlightLow\">") 40 + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 2) 41 41 if templ_7745c5c3_Err != nil { 42 42 return templ_7745c5c3_Err 43 43 } 44 - templ_7745c5c3_Err = p.PostContent(post).Render(ctx, templ_7745c5c3_Buffer) 44 + templ_7745c5c3_Err = p.PostFeedHeader(post).Render(ctx, templ_7745c5c3_Buffer) 45 45 if templ_7745c5c3_Err != nil { 46 46 return templ_7745c5c3_Err 47 47 } 48 - templ_7745c5c3_Err = p.PostFeedHeader(post).Render(ctx, templ_7745c5c3_Buffer) 48 + templ_7745c5c3_Err = p.PostContent(post).Render(ctx, templ_7745c5c3_Buffer) 49 49 if templ_7745c5c3_Err != nil { 50 50 return templ_7745c5c3_Err 51 51 } 52 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</li>") 52 + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 3) 53 53 if templ_7745c5c3_Err != nil { 54 54 return templ_7745c5c3_Err 55 55 } 56 56 } 57 57 } else { 58 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<li class=\"text-muted bg-surface px-4 py-8 text-center border border-highlightLow\">intention-rich, content-poor</li>") 58 + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 4) 59 59 if templ_7745c5c3_Err != nil { 60 60 return templ_7745c5c3_Err 61 61 } 62 62 } 63 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</ul></main></div>") 63 + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 5) 64 64 if templ_7745c5c3_Err != nil { 65 65 return templ_7745c5c3_Err 66 66 }
+22 -56
html/pages/post.templ
··· 1 1 package pages 2 2 3 - import "github.com/puregarlic/space/models" 4 - import "fmt" 5 - import "encoding/json" 6 - import "reflect" 7 - 8 - func printProperty(post *models.Post, name string) string { 9 - props := make(map[string]any) 10 - if err := json.Unmarshal(post.Properties, &props); err != nil { 11 - panic(err) 12 - } 13 - 14 - if val, ok := props[name]; ok { 15 - tp := reflect.TypeOf(val) 16 - switch tp.Kind() { 17 - default: 18 - return fmt.Sprint(val) 19 - case reflect.Slice: 20 - str := "" 21 - for _, v := range val.([]any) { 22 - str = str + fmt.Sprint(v) 23 - } 24 - 25 - return str 26 - } 27 - 28 - } 29 - 30 - return "<no name provided>" 31 - } 32 - 33 - func printPost(post *models.Post) string { 34 - out, err := json.Marshal(post) 35 - 36 - if (err != nil) { 37 - panic (err) 38 - } 39 - 40 - return fmt.Sprint(string(out)) 41 - } 3 + import ( 4 + "github.com/puregarlic/space/html/components/posts" 5 + "github.com/puregarlic/space/models" 6 + ) 42 7 43 8 templ Post(post *models.Post) { 44 - <!DOCTYPE html> 45 - <html> 46 - <head> 47 - <title>Post | Micropub and IndieAuth Server Demo</title> 48 - </head> 49 - <body> 50 - <div class={ post.Type }> 51 - <h1 class="p-name">{ printProperty(post, "name") }</h1> 52 - <p class="p-content">{ printProperty(post, "content") }</p> 53 - 54 - <h3>Stored Microformats</h3> 55 - <code> 56 - <pre>{ printPost(post) }</pre> 57 - </code> 58 - </div> 59 - </body> 60 - </html> 9 + <div class="flex flex-col gap-8"> 10 + <a href="/" class="text-sm text-muted flex items-center gap-1"> 11 + <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="currentColor" class="size-4"> 12 + <path fill-rule="evenodd" d="M14 8a.75.75 0 0 1-.75.75H4.56l1.22 1.22a.75.75 0 1 1-1.06 1.06l-2.5-2.5a.75.75 0 0 1 0-1.06l2.5-2.5a.75.75 0 0 1 1.06 1.06L4.56 7.25h8.69A.75.75 0 0 1 14 8Z" clip-rule="evenodd"></path> 13 + </svg> 14 + back to home 15 + </a> 16 + <div> 17 + @posts.PostContent(post) 18 + </div> 19 + @posts.PostDetails(post) 20 + <div class="py-12 flex flex-col gap-1 items-center text-muted text-xs font-light"> 21 + interactions not implemented yet 22 + <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="currentColor" class="size-4"> 23 + <path fill-rule="evenodd" d="M15 8A7 7 0 1 1 1 8a7 7 0 0 1 14 0ZM6 8c.552 0 1-.672 1-1.5S6.552 5 6 5s-1 .672-1 1.5S5.448 8 6 8Zm5-1.5c0 .828-.448 1.5-1 1.5s-1-.672-1-1.5S9.448 5 10 5s1 .672 1 1.5Zm-6.005 5.805a.75.75 0 0 0 1.06 0 2.75 2.75 0 0 1 3.89 0 .75.75 0 0 0 1.06-1.06 4.25 4.25 0 0 0-6.01 0 .75.75 0 0 0 0 1.06Z" clip-rule="evenodd"></path> 24 + </svg> 25 + </div> 26 + </div> 61 27 }
+9 -89
html/pages/post_templ.go
··· 8 8 import "github.com/a-h/templ" 9 9 import templruntime "github.com/a-h/templ/runtime" 10 10 11 - import "github.com/puregarlic/space/models" 12 - import "fmt" 13 - import "encoding/json" 14 - import "reflect" 15 - 16 - func printProperty(post *models.Post, name string) string { 17 - props := make(map[string]any) 18 - if err := json.Unmarshal(post.Properties, &props); err != nil { 19 - panic(err) 20 - } 21 - 22 - if val, ok := props[name]; ok { 23 - tp := reflect.TypeOf(val) 24 - switch tp.Kind() { 25 - default: 26 - return fmt.Sprint(val) 27 - case reflect.Slice: 28 - str := "" 29 - for _, v := range val.([]any) { 30 - str = str + fmt.Sprint(v) 31 - } 32 - 33 - return str 34 - } 35 - 36 - } 37 - 38 - return "<no name provided>" 39 - } 40 - 41 - func printPost(post *models.Post) string { 42 - out, err := json.Marshal(post) 43 - 44 - if err != nil { 45 - panic(err) 46 - } 47 - 48 - return fmt.Sprint(string(out)) 49 - } 11 + import ( 12 + "github.com/puregarlic/space/html/components/posts" 13 + "github.com/puregarlic/space/models" 14 + ) 50 15 51 16 func Post(post *models.Post) templ.Component { 52 17 return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { ··· 66 31 templ_7745c5c3_Var1 = templ.NopComponent 67 32 } 68 33 ctx = templ.ClearChildren(ctx) 69 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<!doctype html><html><head><title>Post | Micropub and IndieAuth Server Demo</title></head><body>") 70 - if templ_7745c5c3_Err != nil { 71 - return templ_7745c5c3_Err 72 - } 73 - var templ_7745c5c3_Var2 = []any{post.Type} 74 - templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var2...) 34 + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 1) 75 35 if templ_7745c5c3_Err != nil { 76 36 return templ_7745c5c3_Err 77 37 } 78 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"") 38 + templ_7745c5c3_Err = posts.PostContent(post).Render(ctx, templ_7745c5c3_Buffer) 79 39 if templ_7745c5c3_Err != nil { 80 40 return templ_7745c5c3_Err 81 41 } 82 - var templ_7745c5c3_Var3 string 83 - templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var2).String()) 84 - if templ_7745c5c3_Err != nil { 85 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `html/pages/post.templ`, Line: 1, Col: 0} 86 - } 87 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) 42 + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 2) 88 43 if templ_7745c5c3_Err != nil { 89 44 return templ_7745c5c3_Err 90 45 } 91 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"><h1 class=\"p-name\">") 46 + templ_7745c5c3_Err = posts.PostDetails(post).Render(ctx, templ_7745c5c3_Buffer) 92 47 if templ_7745c5c3_Err != nil { 93 48 return templ_7745c5c3_Err 94 49 } 95 - var templ_7745c5c3_Var4 string 96 - templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(printProperty(post, "name")) 97 - if templ_7745c5c3_Err != nil { 98 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `html/pages/post.templ`, Line: 51, Col: 56} 99 - } 100 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) 101 - if templ_7745c5c3_Err != nil { 102 - return templ_7745c5c3_Err 103 - } 104 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</h1><p class=\"p-content\">") 105 - if templ_7745c5c3_Err != nil { 106 - return templ_7745c5c3_Err 107 - } 108 - var templ_7745c5c3_Var5 string 109 - templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(printProperty(post, "content")) 110 - if templ_7745c5c3_Err != nil { 111 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `html/pages/post.templ`, Line: 52, Col: 61} 112 - } 113 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5)) 114 - if templ_7745c5c3_Err != nil { 115 - return templ_7745c5c3_Err 116 - } 117 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</p><h3>Stored Microformats</h3><code><pre>") 118 - if templ_7745c5c3_Err != nil { 119 - return templ_7745c5c3_Err 120 - } 121 - var templ_7745c5c3_Var6 string 122 - templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(printPost(post)) 123 - if templ_7745c5c3_Err != nil { 124 - return templ.Error{Err: templ_7745c5c3_Err, FileName: `html/pages/post.templ`, Line: 56, Col: 32} 125 - } 126 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6)) 127 - if templ_7745c5c3_Err != nil { 128 - return templ_7745c5c3_Err 129 - } 130 - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</pre></code></div></body></html>") 50 + templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 3) 131 51 if templ_7745c5c3_Err != nil { 132 52 return templ_7745c5c3_Err 133 53 }
+4
models/post.go
··· 19 19 UpdatedAt time.Time 20 20 DeletedAt gorm.DeletedAt `gorm:"index"` 21 21 } 22 + 23 + func (p *Post) Timestamp() string { 24 + return p.CreatedAt.Format("01/02/2006 at 3:04 PM") 25 + }