templ generate, add markdown syntax highlighting, fix stuff

This commit is contained in:
2025-08-17 14:15:46 +00:00
parent 59d82ae563
commit 749d68cdeb
23 changed files with 1106 additions and 135 deletions

3
go.mod
View File

@@ -5,15 +5,18 @@ go 1.25.0
require ( require (
github.com/a-h/parse v0.0.0-20250122154542-74294addb73e // indirect github.com/a-h/parse v0.0.0-20250122154542-74294addb73e // indirect
github.com/a-h/templ v0.3.943 // indirect github.com/a-h/templ v0.3.943 // indirect
github.com/alecthomas/chroma/v2 v2.2.0 // indirect
github.com/andybalholm/brotli v1.1.0 // indirect github.com/andybalholm/brotli v1.1.0 // indirect
github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect
github.com/cli/browser v1.3.0 // indirect github.com/cli/browser v1.3.0 // indirect
github.com/dlclark/regexp2 v1.7.0 // indirect
github.com/fatih/color v1.16.0 // indirect github.com/fatih/color v1.16.0 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-isatty v0.0.20 // indirect
github.com/natefinch/atomic v1.0.1 // indirect github.com/natefinch/atomic v1.0.1 // indirect
github.com/yuin/goldmark v1.7.13 // indirect github.com/yuin/goldmark v1.7.13 // indirect
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc // indirect
golang.org/x/mod v0.26.0 // indirect golang.org/x/mod v0.26.0 // indirect
golang.org/x/net v0.42.0 // indirect golang.org/x/net v0.42.0 // indirect
golang.org/x/sync v0.16.0 // indirect golang.org/x/sync v0.16.0 // indirect

16
go.sum
View File

@@ -2,12 +2,20 @@ github.com/a-h/parse v0.0.0-20250122154542-74294addb73e h1:HjVbSQHy+dnlS6C3XajZ6
github.com/a-h/parse v0.0.0-20250122154542-74294addb73e/go.mod h1:3mnrkvGpurZ4ZrTDbYU84xhwXW2TjTKShSwjRi2ihfQ= github.com/a-h/parse v0.0.0-20250122154542-74294addb73e/go.mod h1:3mnrkvGpurZ4ZrTDbYU84xhwXW2TjTKShSwjRi2ihfQ=
github.com/a-h/templ v0.3.943 h1:o+mT/4yqhZ33F3ootBiHwaY4HM5EVaOJfIshvd5UNTY= github.com/a-h/templ v0.3.943 h1:o+mT/4yqhZ33F3ootBiHwaY4HM5EVaOJfIshvd5UNTY=
github.com/a-h/templ v0.3.943/go.mod h1:oCZcnKRf5jjsGpf2yELzQfodLphd2mwecwG4Crk5HBo= github.com/a-h/templ v0.3.943/go.mod h1:oCZcnKRf5jjsGpf2yELzQfodLphd2mwecwG4Crk5HBo=
github.com/alecthomas/chroma/v2 v2.2.0 h1:Aten8jfQwUqEdadVFFjNyjx7HTexhKP0XuqBG67mRDY=
github.com/alecthomas/chroma/v2 v2.2.0/go.mod h1:vf4zrexSH54oEjJ7EdB65tGNHmH3pGZmVkgTP5RHvAs=
github.com/alecthomas/repr v0.0.0-20220113201626-b1b626ac65ae/go.mod h1:2kn6fqh/zIyPLmm3ugklbEi5hg5wS435eygvNfaDQL8=
github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M=
github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY=
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/cli/browser v1.3.0 h1:LejqCrpWr+1pRqmEPDGnTZOjsMe7sehifLynZJuqJpo= github.com/cli/browser v1.3.0 h1:LejqCrpWr+1pRqmEPDGnTZOjsMe7sehifLynZJuqJpo=
github.com/cli/browser v1.3.0/go.mod h1:HH8s+fOAxjhQoBUAsKuPCbqUuxZDhQ2/aD+SzsEfBTk= github.com/cli/browser v1.3.0/go.mod h1:HH8s+fOAxjhQoBUAsKuPCbqUuxZDhQ2/aD+SzsEfBTk=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
github.com/dlclark/regexp2 v1.7.0 h1:7lJfhqlPssTb1WQx4yvTHN0uElPEv52sbaECrAQxjAo=
github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
@@ -19,8 +27,14 @@ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWE
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/natefinch/atomic v1.0.1 h1:ZPYKxkqQOx3KZ+RsbnP/YsgvxWQPGxjC0oBt2AhwV0A= github.com/natefinch/atomic v1.0.1 h1:ZPYKxkqQOx3KZ+RsbnP/YsgvxWQPGxjC0oBt2AhwV0A=
github.com/natefinch/atomic v1.0.1/go.mod h1:N/D/ELrljoqDyT3rZrsUmtsuzvHkeB/wWjHV22AZRbM= github.com/natefinch/atomic v1.0.1/go.mod h1:N/D/ELrljoqDyT3rZrsUmtsuzvHkeB/wWjHV22AZRbM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/yuin/goldmark v1.4.15/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yuin/goldmark v1.7.13 h1:GPddIs617DnBLFFVJFgpo1aBfe/4xcvMc3SB5t/D0pA= github.com/yuin/goldmark v1.7.13 h1:GPddIs617DnBLFFVJFgpo1aBfe/4xcvMc3SB5t/D0pA=
github.com/yuin/goldmark v1.7.13/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg= github.com/yuin/goldmark v1.7.13/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg=
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc h1:+IAOyRda+RLrxa1WC7umKOZRsGq4QrFFMYApOeHzQwQ=
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc/go.mod h1:ovIvrum6DQJA4QsJSovrkC4saKHQVs7TvcaeO8AIl5I=
golang.org/x/mod v0.26.0 h1:EGMPT//Ezu+ylkCijjPc+f4Aih7sZvaAr+O3EHBxvZg= golang.org/x/mod v0.26.0 h1:EGMPT//Ezu+ylkCijjPc+f4Aih7sZvaAr+O3EHBxvZg=
golang.org/x/mod v0.26.0/go.mod h1:/j6NAhSk8iQ723BGAUyoAcn7SlD7s15Dp9Nd/SfeaFQ= golang.org/x/mod v0.26.0/go.mod h1:/j6NAhSk8iQ723BGAUyoAcn7SlD7s15Dp9Nd/SfeaFQ=
golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs= golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs=
@@ -33,3 +47,5 @@ golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/tools v0.35.0 h1:mBffYraMEf7aa0sB+NuKnuCy8qI/9Bughn8dC2Gu5r0= golang.org/x/tools v0.35.0 h1:mBffYraMEf7aa0sB+NuKnuCy8qI/9Bughn8dC2Gu5r0=
golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw= golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

19
main.go
View File

@@ -8,6 +8,7 @@ import (
"strings" "strings"
"git.valxntine.dev/valxntine/blog/models" "git.valxntine.dev/valxntine/blog/models"
"git.valxntine.dev/valxntine/blog/templates"
) )
func main() { func main() {
@@ -51,7 +52,7 @@ func handleHome(w http.ResponseWriter, r *http.Request) {
d := models.Data{ d := models.Data{
Title: "~/valxntine/blog", Title: "~/valxntine/blog",
Subtitle: "Thought from the Forge", Subtitle: "Thoughts from the Forge",
Posts: posts, Posts: posts,
CurrentPage: page, CurrentPage: page,
TotalPages: total, TotalPages: total,
@@ -100,18 +101,10 @@ func handlePost(w http.ResponseWriter, r *http.Request) {
} }
w.Header().Set("Content-Type", "text/html") w.Header().Set("Content-Type", "text/html")
// err := templates.Layout(post.Title + " - ~/valxntine/blog") { err := templates.PostPageFull(*post).Render(r.Context(), w)
// @templates.Header("~/valxntine/blog", "Thoughts from the Forge") if err != nil {
// @templates.Nav() http.Error(w, err.Error(), http.StatusInternalServerError)
// <main> }
// @templates.PostDetail(*post)
// </main>
// @templates.Footer()
// }.Render(r.Context(), w)
// if err != nil {
// http.Error(w, err.Error(), http.StatusInternalServerError)
// }
// }
} }
func handleTag(w http.ResponseWriter, r *http.Request) { func handleTag(w http.ResponseWriter, r *http.Request) {

View File

@@ -10,7 +10,9 @@ import (
"time" "time"
"git.valxntine.dev/valxntine/blog/models" "git.valxntine.dev/valxntine/blog/models"
chromahtml "github.com/alecthomas/chroma/v2/formatters/html"
"github.com/yuin/goldmark" "github.com/yuin/goldmark"
highlighting "github.com/yuin/goldmark-highlighting/v2"
"github.com/yuin/goldmark/extension" "github.com/yuin/goldmark/extension"
"github.com/yuin/goldmark/parser" "github.com/yuin/goldmark/parser"
"github.com/yuin/goldmark/renderer/html" "github.com/yuin/goldmark/renderer/html"
@@ -41,6 +43,13 @@ var md = goldmark.New(
extension.Strikethrough, extension.Strikethrough,
extension.Linkify, extension.Linkify,
extension.TaskList, extension.TaskList,
highlighting.NewHighlighting(
highlighting.WithStyle("monokai"),
highlighting.WithFormatOptions(
chromahtml.WithLineNumbers(true),
// chromahtml.WithClasses(true),
),
),
), ),
goldmark.WithParserOptions( goldmark.WithParserOptions(
parser.WithAutoHeadingID(), parser.WithAutoHeadingID(),

View File

@@ -5,8 +5,6 @@ excerpt: "The Hammer Strikes..."
draft: false draft: false
--- ---
# Hello, Forge
Welcome. Welcome.
This is my home. This is my home.

View File

@@ -400,3 +400,315 @@ a[href^="/tags/"]:hover {
transition: opacity 0.2s ease; transition: opacity 0.2s ease;
} }
/* Add to your existing CSS */
/* Syntax Highlighting */
.chroma {
background-color: #f8f8f8;
border: 1px solid #e2e8f0;
border-radius: 6px;
padding: 16px;
overflow-x: auto;
margin: 16px 0;
font-family: 'SF Mono', 'Monaco', 'Inconsolata', 'Roboto Mono', 'Consolas', 'Courier New', monospace;
font-size: 14px;
line-height: 1.4;
}
/* Line numbers */
.chroma .lnt {
color: #999;
margin-right: 16px;
user-select: none;
}
.chroma .hl {
background-color: #ffffcc;
display: block;
width: 100%;
}
/* Syntax highlighting colors (GitHub style) */
.chroma .c { color: #6a737d; } /* Comment */
.chroma .err { color: #cb2431; } /* Error */
.chroma .k { color: #d73a49; } /* Keyword */
.chroma .l { color: #032f62; } /* Literal */
.chroma .n { color: #24292e; } /* Name */
.chroma .o { color: #d73a49; } /* Operator */
.chroma .p { color: #24292e; } /* Punctuation */
.chroma .cm { color: #6a737d; } /* Comment.Multiline */
.chroma .cp { color: #d73a49; } /* Comment.Preproc */
.chroma .c1 { color: #6a737d; } /* Comment.Single */
.chroma .cs { color: #6a737d; } /* Comment.Special */
.chroma .gd { color: #cb2431; } /* Generic.Deleted */
.chroma .ge { font-style: italic; } /* Generic.Emph */
.chroma .gi { color: #28a745; } /* Generic.Inserted */
.chroma .gs { font-weight: bold; } /* Generic.Strong */
.chroma .gu { color: #6f42c1; } /* Generic.Subheading */
.chroma .kc { color: #005cc5; } /* Keyword.Constant */
.chroma .kd { color: #d73a49; } /* Keyword.Declaration */
.chroma .kn { color: #d73a49; } /* Keyword.Namespace */
.chroma .kp { color: #d73a49; } /* Keyword.Pseudo */
.chroma .kr { color: #d73a49; } /* Keyword.Reserved */
.chroma .kt { color: #d73a49; } /* Keyword.Type */
.chroma .ld { color: #032f62; } /* Literal.Date */
.chroma .m { color: #005cc5; } /* Literal.Number */
.chroma .s { color: #032f62; } /* Literal.String */
.chroma .na { color: #24292e; } /* Name.Attribute */
.chroma .nb { color: #005cc5; } /* Name.Builtin */
.chroma .nc { color: #6f42c1; } /* Name.Class */
.chroma .no { color: #005cc5; } /* Name.Constant */
.chroma .nd { color: #6f42c1; } /* Name.Decorator */
.chroma .ni { color: #6f42c1; } /* Name.Entity */
.chroma .ne { color: #6f42c1; } /* Name.Exception */
.chroma .nf { color: #6f42c1; } /* Name.Function */
.chroma .nl { color: #6f42c1; } /* Name.Label */
.chroma .nn { color: #6f42c1; } /* Name.Namespace */
.chroma .nx { color: #6f42c1; } /* Name.Other */
.chroma .py { color: #24292e; } /* Name.Property */
.chroma .nt { color: #22863a; } /* Name.Tag */
.chroma .nv { color: #e36209; } /* Name.Variable */
.chroma .ow { color: #d73a49; } /* Operator.Word */
.chroma .w { color: #bbbbbb; } /* Text.Whitespace */
.chroma .mb { color: #005cc5; } /* Literal.Number.Bin */
.chroma .mf { color: #005cc5; } /* Literal.Number.Float */
.chroma .mh { color: #005cc5; } /* Literal.Number.Hex */
.chroma .mi { color: #005cc5; } /* Literal.Number.Integer */
.chroma .mo { color: #005cc5; } /* Literal.Number.Oct */
.chroma .sb { color: #032f62; } /* Literal.String.Backtick */
.chroma .sc { color: #032f62; } /* Literal.String.Char */
.chroma .sd { color: #032f62; } /* Literal.String.Doc */
.chroma .s2 { color: #032f62; } /* Literal.String.Double */
.chroma .se { color: #032f62; } /* Literal.String.Escape */
.chroma .sh { color: #032f62; } /* Literal.String.Heredoc */
.chroma .si { color: #032f62; } /* Literal.String.Interpol */
.chroma .sx { color: #032f62; } /* Literal.String.Other */
.chroma .sr { color: #032f62; } /* Literal.String.Regex */
.chroma .s1 { color: #032f62; } /* Literal.String.Single */
.chroma .ss { color: #032f62; } /* Literal.String.Symbol */
.chroma .bp { color: #005cc5; } /* Name.Builtin.Pseudo */
.chroma .vc { color: #e36209; } /* Name.Variable.Class */
.chroma .vg { color: #e36209; } /* Name.Variable.Global */
.chroma .vi { color: #e36209; } /* Name.Variable.Instance */
/* Dark mode syntax highlighting (optional) */
@media (prefers-color-scheme: dark) {
.chroma {
background-color: #0d1117;
border-color: #30363d;
color: #e6edf3;
}
.chroma .c { color: #8b949e; }
.chroma .k { color: #ff7b72; }
.chroma .s { color: #a5d6ff; }
.chroma .nb { color: #ffa657; }
.chroma .nc { color: #ffa657; }
.chroma .nf { color: #d2a8ff; }
.chroma .nt { color: #7ee787; }
.chroma .m { color: #79c0ff; }
}
/* Mobile adjustments */
@media (max-width: 600px) {
.chroma {
padding: 12px;
font-size: 13px;
}
.chroma .lnt {
margin-right: 8px;
}
}
/* HTMX Loading States */
.loading {
opacity: 0.7;
pointer-events: none;
transition: opacity 0.2s ease;
}
.loading::after {
content: '';
position: absolute;
top: 50%;
left: 50%;
width: 20px;
height: 20px;
margin: -10px 0 0 -10px;
border: 2px solid #e2e8f0;
border-top: 2px solid #3182ce;
border-radius: 50%;
animation: spin 1s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
/* Pagination Styles */
.pagination {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 32px;
padding: 20px;
background-color: #f7fafc;
border: 1px solid #e2e8f0;
border-radius: 6px;
}
.pagination a {
color: #3182ce;
text-decoration: none;
padding: 8px 16px;
border-radius: 4px;
transition: all 0.2s ease;
font-weight: 500;
}
.pagination a:hover {
background-color: #bee3f8;
text-decoration: underline;
}
.page-info {
color: #718096;
font-weight: 500;
}
/* Post Detail Styles */
.post-detail {
background-color: #ffffff;
border: 1px solid #e2e8f0;
border-radius: 6px;
padding: 32px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}
.post-detail .post-title {
font-size: 28px;
font-weight: 700;
margin-bottom: 16px;
color: #1a202c;
}
.post-detail .post-meta {
font-size: 14px;
color: #718096;
margin-bottom: 24px;
padding-bottom: 16px;
border-bottom: 1px solid #e2e8f0;
}
.post-content {
font-size: 16px;
line-height: 1.7;
color: #2d3748;
}
.post-content h2 {
font-size: 24px;
font-weight: 600;
margin: 32px 0 16px 0;
color: #1a202c;
}
.post-content h3 {
font-size: 20px;
font-weight: 600;
margin: 24px 0 12px 0;
color: #1a202c;
}
.post-content p {
margin-bottom: 16px;
}
.post-content code {
background-color: #f7fafc;
padding: 2px 6px;
border-radius: 3px;
font-size: 14px;
border: 1px solid #e2e8f0;
}
.post-content pre {
background-color: #1a202c;
color: #f7fafc;
padding: 16px;
border-radius: 6px;
overflow-x: auto;
margin: 16px 0;
}
.post-content pre code {
background: none;
border: none;
padding: 0;
color: inherit;
}
.post-footer {
margin-top: 32px;
padding-top: 24px;
border-top: 1px solid #e2e8f0;
}
.post-footer a {
color: #3182ce;
text-decoration: none;
font-weight: 500;
padding: 8px 12px;
border-radius: 4px;
transition: all 0.2s ease;
}
.post-footer a:hover {
background-color: #ebf8ff;
text-decoration: underline;
}
/* Tag Links */
a[href^="/tags/"] {
background-color: #ebf8ff;
color: #2b6cb0;
padding: 2px 6px;
border-radius: 3px;
font-size: 12px;
text-decoration: none;
font-weight: 500;
transition: all 0.2s ease;
}
a[href^="/tags/"]:hover {
background-color: #bee3f8;
text-decoration: none;
}
/* HTMX Transitions */
.htmx-settling {
opacity: 0;
}
.htmx-swapping {
opacity: 0;
transition: opacity 0.2s ease;
}
/* Mobile adjustments for new elements */
@media (max-width: 600px) {
.pagination {
flex-direction: column;
gap: 12px;
}
.post-detail {
padding: 20px;
}
.post-detail .post-title {
font-size: 24px;
}
}

View File

@@ -36,7 +36,7 @@ func Header(title, subtitle string) templ.Component {
var templ_7745c5c3_Var2 string var templ_7745c5c3_Var2 string
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(title) templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(title)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/header.templ`, Line: 5, Col: 15} return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/header.templ`, Line: 5, Col: 13}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
@@ -49,7 +49,7 @@ func Header(title, subtitle string) templ.Component {
var templ_7745c5c3_Var3 string var templ_7745c5c3_Var3 string
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(subtitle) templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(subtitle)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/header.templ`, Line: 6, Col: 36} return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/header.templ`, Line: 6, Col: 34}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {

View File

@@ -1,5 +1,7 @@
package templates package templates
import "git.valxntine.dev/valxntine/blog/models"
templ HomePage(data models.Data) { templ HomePage(data models.Data) {
@Layout(data.Title) { @Layout(data.Title) {
@Header(data.Title, data.Subtitle) @Header(data.Title, data.Subtitle)

View File

@@ -8,6 +8,8 @@ package templates
import "github.com/a-h/templ" import "github.com/a-h/templ"
import templruntime "github.com/a-h/templ/runtime" import templruntime "github.com/a-h/templ/runtime"
import "git.valxntine.dev/valxntine/blog/models"
func HomePage(data models.Data) templ.Component { func HomePage(data models.Data) templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context

View File

@@ -7,6 +7,7 @@ templ Layout(title string) {
<meta charset="UTF-8"/> <meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/> <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>{ title }</title> <title>{ title }</title>
<link rel="stylesheet" href="/static/style.css"/>
<script src="https://unpkg.com/htmx.org@1.9.6"></script> <script src="https://unpkg.com/htmx.org@1.9.6"></script>
</head> </head>
<body> <body>

View File

@@ -36,13 +36,13 @@ func Layout(title string) templ.Component {
var templ_7745c5c3_Var2 string var templ_7745c5c3_Var2 string
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(title) templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(title)
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/layout.templ`, Line: 9, Col: 18} return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/layout.templ`, Line: 9, Col: 17}
} }
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2)) _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "</title><script src=\"https://unpkg.com/htmx.org@1.9.6\"></script></head><body>") templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "</title><link rel=\"stylesheet\" href=\"/static/style.css\"><script src=\"https://unpkg.com/htmx.org@1.9.6\"></script></head><body>")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }

View File

@@ -3,9 +3,8 @@ package templates
templ Nav() { templ Nav() {
<nav class="nav"> <nav class="nav">
<a href="/" hx-get="/" hx-target="main" hx-push-url="true">home</a> <a href="/" hx-get="/" hx-target="main" hx-push-url="true">home</a>
<a href="/tags" hx-get="/tags" hx-target="main" hx-push-url="true">tags</a> // <a href="/tags" hx-get="/tags" hx-target="main" hx-push-url="true">tags</a>
<a href="/about" hx-get="/about" hx-target="main" hx-push-url="true">about</a> <a href="https://git.valxntine.dev">code</a>
<a href="/archive" hx-get="/archive" hx-target="main" hx-push-url="true">archive</a> <a href="mailto:valentine.bott@gmail.com">email</a>
<a href="mailto:valentine.bott@gmail.com">Contact Me</a>
</nav> </nav>
} }

View File

@@ -29,7 +29,7 @@ func Nav() templ.Component {
templ_7745c5c3_Var1 = templ.NopComponent templ_7745c5c3_Var1 = templ.NopComponent
} }
ctx = templ.ClearChildren(ctx) ctx = templ.ClearChildren(ctx)
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<nav class=\"nav\"><a href=\"/\" hx-get=\"/\" hx-target=\"main\" hx-push-url=\"true\">home</a> <a href=\"/tags\" hx-get=\"/tags\" hx-target=\"main\" hx-push-url=\"true\">tags</a> <a href=\"/about\" hx-get=\"/about\" hx-target=\"main\" hx-push-url=\"true\">about</a> <a href=\"/archive\" hx-get=\"/archive\" hx-target=\"main\" hx-push-url=\"true\">archive</a> <a href=\"mailto:valentine.bott@gmail.com\">Contact Me</a></nav>") templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<nav class=\"nav\"><a href=\"/\" hx-get=\"/\" hx-target=\"main\" hx-push-url=\"true\">home</a><a href=\"https://git.valxntine.dev\">code</a> <a href=\"mailto:valentine.bott@gmail.com\">email</a></nav>")
if templ_7745c5c3_Err != nil { if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err return templ_7745c5c3_Err
} }

14
templates/pages.templ Normal file
View File

@@ -0,0 +1,14 @@
package templates
import "git.valxntine.dev/valxntine/blog/models"
templ PostPageFull(post models.Post) {
@Layout(post.Title + " - ~/valxntine/blog") {
@Header("~/valxntine/blog", "Thoughts from the Forge")
@Nav()
<main>
@PostDetail(post)
</main>
@Footer()
}
}

84
templates/pages_templ.go Normal file
View File

@@ -0,0 +1,84 @@
// Code generated by templ - DO NOT EDIT.
// templ: version: v0.3.943
package templates
//lint:file-ignore SA4006 This context is only used if a nested component is present.
import "github.com/a-h/templ"
import templruntime "github.com/a-h/templ/runtime"
import "git.valxntine.dev/valxntine/blog/models"
func PostPageFull(post models.Post) templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
return templ_7745c5c3_CtxErr
}
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
if templ_7745c5c3_Var1 == nil {
templ_7745c5c3_Var1 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Err = Header("~/valxntine/blog", "Thoughts from the Forge").Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, " ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = Nav().Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, " <main>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = PostDetail(post).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</main>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = Footer().Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return nil
})
templ_7745c5c3_Err = Layout(post.Title+" - ~/valxntine/blog").Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return nil
})
}
var _ = templruntime.GeneratedTemplate

View File

@@ -9,7 +9,7 @@ templ Pagination(currentPage, totalPages int) {
hx-get={ fmt.Sprintf("/?page=%d", currentPage-1) } hx-get={ fmt.Sprintf("/?page=%d", currentPage-1) }
hx-target="#post-list" hx-target="#post-list"
hx-swap="outerHTML"> hx-swap="outerHTML">
<- Previous Previous
</a> </a>
} }
@@ -22,7 +22,7 @@ templ Pagination(currentPage, totalPages int) {
hx-get={ fmt.Sprintf("/?page=%d", currentPage+1) } hx-get={ fmt.Sprintf("/?page=%d", currentPage+1) }
hx-target="#post-list" hx-target="#post-list"
hx-swap="outerHTML"> hx-swap="outerHTML">
Next -> Next
</a> </a>
} }
</div> </div>

View File

@@ -0,0 +1,127 @@
// Code generated by templ - DO NOT EDIT.
// templ: version: v0.3.943
package templates
//lint:file-ignore SA4006 This context is only used if a nested component is present.
import "github.com/a-h/templ"
import templruntime "github.com/a-h/templ/runtime"
import "fmt"
func Pagination(currentPage, totalPages int) templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
return templ_7745c5c3_CtxErr
}
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
if templ_7745c5c3_Var1 == nil {
templ_7745c5c3_Var1 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div class=\"pagination\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if currentPage > 1 {
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<a href=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var2 templ.SafeURL
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinURLErrs(templ.URL(fmt.Sprintf("/?page=%d", currentPage-1)))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/pagination.templ`, Line: 8, Col: 66}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "\" hx-get=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var3 string
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("/?page=%d", currentPage-1))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/pagination.templ`, Line: 9, Col: 56}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "\" hx-target=\"#post-list\" hx-swap=\"outerHTML\">← Previous</a> ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "<span class=\"page-info\">Page ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var4 string
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", currentPage))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/pagination.templ`, Line: 17, Col: 43}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "</span> ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if currentPage < totalPages {
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "<a href=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var5 templ.SafeURL
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinURLErrs(templ.URL(fmt.Sprintf("/?page=%d", currentPage+1)))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/pagination.templ`, Line: 21, Col: 66}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "\" hx-get=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var6 string
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("/?page=%d", currentPage+1))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/pagination.templ`, Line: 22, Col: 56}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "\" hx-target=\"#post-list\" hx-swap=\"outerHTML\">Next →</a>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "</div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return nil
})
}
var _ = templruntime.GeneratedTemplate

View File

@@ -1,10 +1,17 @@
package templates package templates
import (
"git.valxntine.dev/valxntine/blog/models"
"strconv"
)
templ PostDetail(post models.Post) { templ PostDetail(post models.Post) {
<article class="post-detail"> <article class="post-detail">
<h1 class="post-title">{ post.Title }</h1> <h1 class="post-title">{ post.Title }</h1>
<div class="post-meta"> <div class="post-meta">
Published: { post.PublishedAt.Format("January 2, 2006") } | Published: { post.PublishedAt.Format("January 2, 2006") }
if len(post.Tags) > 0 {
|
Tags: Tags:
for i, tag := range post.Tags { for i, tag := range post.Tags {
if i > 0 { if i > 0 {
@@ -12,17 +19,20 @@ templ PostDetail(post models.Post) {
} }
<a href={ templ.URL("/tags/" + tag) }>{ tag }</a> <a href={ templ.URL("/tags/" + tag) }>{ tag }</a>
} }
| { fmt.Sprintf("%d", post.WordCount) } words }
| { strconv.Itoa(post.WordCount) } words
</div> </div>
<div class="post-content"> <div class="post-content">
{ templ.Raw(post.Content) } @templ.Raw(post.Content)
</div> </div>
<div class="post-footer"> <div class="post-footer">
<a href="/" <a
href="/"
hx-get="/" hx-get="/"
hx-target="main" hx-target="main"
hx-push-url="true"> hx-push-url="true"
<- Back to Posts >
← Back to Posts
</a> </a>
</div> </div>
</article> </article>

140
templates/post_templ.go Normal file
View File

@@ -0,0 +1,140 @@
// Code generated by templ - DO NOT EDIT.
// templ: version: v0.3.943
package templates
//lint:file-ignore SA4006 This context is only used if a nested component is present.
import "github.com/a-h/templ"
import templruntime "github.com/a-h/templ/runtime"
import (
"git.valxntine.dev/valxntine/blog/models"
"strconv"
)
func PostDetail(post models.Post) templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
return templ_7745c5c3_CtxErr
}
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
if templ_7745c5c3_Var1 == nil {
templ_7745c5c3_Var1 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<article class=\"post-detail\"><h1 class=\"post-title\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var2 string
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(post.Title)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/post.templ`, Line: 10, Col: 37}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "</h1><div class=\"post-meta\">Published: ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var3 string
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(post.PublishedAt.Format("January 2, 2006"))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/post.templ`, Line: 12, Col: 58}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, " ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if len(post.Tags) > 0 {
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "|\t Tags: ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
for i, tag := range post.Tags {
if i > 0 {
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, ",")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, " <a href=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var4 templ.SafeURL
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinURLErrs(templ.URL("/tags/" + tag))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/post.templ`, Line: 20, Col: 40}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var5 string
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(tag)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/post.templ`, Line: 20, Col: 48}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "</a> ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "| ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var6 string
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(strconv.Itoa(post.WordCount))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/post.templ`, Line: 23, Col: 35}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, " words</div><div class=\"post-content\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templ.Raw(post.Content).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "</div><div class=\"post-footer\"><a href=\"/\" hx-get=\"/\" hx-target=\"main\" hx-push-url=\"true\">← Back to Posts</a></div></article>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return nil
})
}
var _ = templruntime.GeneratedTemplate

View File

@@ -1,6 +1,9 @@
package templates package templates
import "time" import (
"fmt"
"git.valxntine.dev/valxntine/blog/models"
)
templ PostList(posts []models.Post, page, totalPages int) { templ PostList(posts []models.Post, page, totalPages int) {
<div id="post-list"> <div id="post-list">
@@ -9,7 +12,6 @@ templ PostList(posts []models.Post, page, totalPages int) {
@PostListItem(post) @PostListItem(post)
} }
</ul> </ul>
if totalPages > 1 { if totalPages > 1 {
@Pagination(page, totalPages) @Pagination(page, totalPages)
} }
@@ -19,10 +21,12 @@ templ PostList(posts []models.Post, page, totalPages int) {
templ PostListItem(post models.Post) { templ PostListItem(post models.Post) {
<li class="blog-post"> <li class="blog-post">
<div class="post-title"> <div class="post-title">
<a href={ templ.URL("/posts/" + post.Slug) } <a
href={ templ.URL("/posts/" + post.Slug) }
hx-get={ "/posts/" + post.Slug } hx-get={ "/posts/" + post.Slug }
hx-target="main" hx-target="main"
hx-push-url="true"> hx-push-url="true"
>
{ post.Title } { post.Title }
</a> </a>
</div> </div>
@@ -33,10 +37,12 @@ templ PostListItem(post models.Post) {
if i > 0 { if i > 0 {
, ,
} }
<a href={ templ.URL("/tags/" + tag) } <a
href={ templ.URL("/tags/" + tag) }
hx-get={ "/tags/" + tag } hx-get={ "/tags/" + tag }
hx-target="main" hx-target="main"
hx-push-url="true"> hx-push-url="true"
>
{ tag } { tag }
</a> </a>
} }
@@ -46,10 +52,12 @@ templ PostListItem(post models.Post) {
{ post.Excerpt } { post.Excerpt }
</div> </div>
<div class="read-more"> <div class="read-more">
<a href={ templ.URL("/posts/" + post.Slug) } <a
href={ templ.URL("/posts/" + post.Slug) }
hx-get={ "/posts/" + post.Slug } hx-get={ "/posts/" + post.Slug }
hx-target="main" hx-target="main"
hx-push-url=true> hx-push-url="true"
>
[Read more...] [Read more...]
</a> </a>
</div> </div>

253
templates/posts_templ.go Normal file
View File

@@ -0,0 +1,253 @@
// Code generated by templ - DO NOT EDIT.
// templ: version: v0.3.943
package templates
//lint:file-ignore SA4006 This context is only used if a nested component is present.
import "github.com/a-h/templ"
import templruntime "github.com/a-h/templ/runtime"
import (
"fmt"
"git.valxntine.dev/valxntine/blog/models"
)
func PostList(posts []models.Post, page, totalPages int) templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
return templ_7745c5c3_CtxErr
}
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
if templ_7745c5c3_Var1 == nil {
templ_7745c5c3_Var1 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div id=\"post-list\"><ul class=\"blog-posts\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
for _, post := range posts {
templ_7745c5c3_Err = PostListItem(post).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "</ul>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if totalPages > 1 {
templ_7745c5c3_Err = Pagination(page, totalPages).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return nil
})
}
func PostListItem(post models.Post) templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
return templ_7745c5c3_CtxErr
}
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var2 := templ.GetChildren(ctx)
if templ_7745c5c3_Var2 == nil {
templ_7745c5c3_Var2 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "<li class=\"blog-post\"><div class=\"post-title\"><a href=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var3 templ.SafeURL
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinURLErrs(templ.URL("/posts/" + post.Slug))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/posts.templ`, Line: 25, Col: 43}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "\" hx-get=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var4 string
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs("/posts/" + post.Slug)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/posts.templ`, Line: 26, Col: 34}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "\" hx-target=\"main\" hx-push-url=\"true\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var5 string
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(post.Title)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/posts.templ`, Line: 30, Col: 16}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "</a></div><div class=\"post-meta\">Posted: ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var6 string
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(post.PublishedAt.Format("2006-01-02"))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/posts.templ`, Line: 34, Col: 50}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, " | Tags: ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
for i, tag := range post.Tags {
if i > 0 {
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, ",")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, " <a href=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var7 templ.SafeURL
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinURLErrs(templ.URL("/tags/" + tag))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/posts.templ`, Line: 41, Col: 37}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "\" hx-get=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var8 string
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs("/tags/" + tag)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/posts.templ`, Line: 42, Col: 28}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "\" hx-target=\"main\" hx-push-url=\"true\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var9 string
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(tag)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/posts.templ`, Line: 46, Col: 10}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "</a> ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "| Words: ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var10 string
templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", post.WordCount))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/posts.templ`, Line: 49, Col: 47}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "</div><div class=\"post-excerpt\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var11 string
templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(post.Excerpt)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/posts.templ`, Line: 52, Col: 17}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "</div><div class=\"read-more\"><a href=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var12 templ.SafeURL
templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinURLErrs(templ.URL("/posts/" + post.Slug))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/posts.templ`, Line: 56, Col: 43}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "\" hx-get=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var13 string
templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs("/posts/" + post.Slug)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/posts.templ`, Line: 57, Col: 34}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "\" hx-target=\"main\" hx-push-url=\"true\">[Read more...]</a></div></li>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return nil
})
}
var _ = templruntime.GeneratedTemplate