Init
This commit is contained in:
71
pages/blog.go
Normal file
71
pages/blog.go
Normal file
@ -0,0 +1,71 @@
|
||||
package pages
|
||||
|
||||
import (
|
||||
"io/fs"
|
||||
"log"
|
||||
"net/http"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
contentfs "atri.dad/content"
|
||||
"atri.dad/lib"
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
type BlogProps struct {
|
||||
Posts []lib.CardLink
|
||||
}
|
||||
|
||||
func Blog(c echo.Context) error {
|
||||
var posts []lib.CardLink
|
||||
|
||||
files, err := fs.ReadDir(contentfs.FS, ".")
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
http.Error(c.Response().Writer, "There was an issue finding posts!", http.StatusInternalServerError)
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, file := range files {
|
||||
if !file.IsDir() && strings.HasSuffix(file.Name(), ".md") {
|
||||
frontMatter, err := lib.ExtractFrontMatter(file, contentfs.FS)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
http.Error(c.Response().Writer, "There was an issue rendering the posts!", http.StatusInternalServerError)
|
||||
return nil
|
||||
}
|
||||
|
||||
frontMatter.Href = "post/" + strings.TrimSuffix(file.Name(), ".md")
|
||||
frontMatter.Internal = true
|
||||
|
||||
posts = append(posts, frontMatter)
|
||||
}
|
||||
}
|
||||
|
||||
const layout = "January 2 2006"
|
||||
|
||||
sort.Slice(posts, func(i, j int) bool {
|
||||
iDate, err := time.Parse(layout, posts[i].Date)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
jDate, err := time.Parse(layout, posts[j].Date)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
return iDate.Before(jDate)
|
||||
})
|
||||
|
||||
props := BlogProps{
|
||||
Posts: posts,
|
||||
}
|
||||
|
||||
// Specify the partials used by this page
|
||||
partials := []string{"header", "navitems", "cardlinks"}
|
||||
|
||||
// Render the template
|
||||
return lib.RenderTemplate(c.Response().Writer, "base", partials, props)
|
||||
}
|
22
pages/example.go
Normal file
22
pages/example.go
Normal file
@ -0,0 +1,22 @@
|
||||
package pages
|
||||
|
||||
import (
|
||||
"atri.dad/lib"
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
type ExampleProps struct {
|
||||
ExamplePropText string
|
||||
}
|
||||
|
||||
func Example(c echo.Context) error {
|
||||
props := ExampleProps{
|
||||
ExamplePropText: "EXAMPLE TEXT HERE",
|
||||
}
|
||||
|
||||
// Specify the partials used by this page
|
||||
partials := []string{"header", "navitems"}
|
||||
|
||||
// Render the template
|
||||
return lib.RenderTemplate(c.Response().Writer, "base", partials, props)
|
||||
}
|
143
pages/home.go
Normal file
143
pages/home.go
Normal file
File diff suppressed because one or more lines are too long
78
pages/post.go
Normal file
78
pages/post.go
Normal file
@ -0,0 +1,78 @@
|
||||
package pages
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"html/template"
|
||||
"io/fs"
|
||||
"net/http"
|
||||
|
||||
contentfs "atri.dad/content"
|
||||
"atri.dad/lib"
|
||||
chromahtml "github.com/alecthomas/chroma/v2/formatters/html"
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/yuin/goldmark"
|
||||
highlighting "github.com/yuin/goldmark-highlighting/v2"
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
type PostProps struct {
|
||||
Content template.HTML
|
||||
Name string
|
||||
Date string
|
||||
Tags []string
|
||||
}
|
||||
|
||||
func Post(c echo.Context) error {
|
||||
postName := c.Param("post")
|
||||
|
||||
filePath := postName + ".md"
|
||||
|
||||
md, err := fs.ReadFile(contentfs.FS, filePath)
|
||||
if err != nil {
|
||||
println(err.Error())
|
||||
http.Error(c.Response().Writer, "This post does not exist!", http.StatusNotFound)
|
||||
return nil
|
||||
}
|
||||
|
||||
frontmatterBytes, content, err := lib.SplitFrontmatter(md)
|
||||
if err != nil {
|
||||
http.Error(c.Response().Writer, "There was an issue rendering this post!", http.StatusInternalServerError)
|
||||
return nil
|
||||
}
|
||||
|
||||
var frontmatter lib.FrontMatter
|
||||
if err := yaml.Unmarshal(frontmatterBytes, &frontmatter); err != nil {
|
||||
http.Error(c.Response().Writer, "There was an issue rendering this post!", http.StatusInternalServerError)
|
||||
return nil
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
markdown := goldmark.New(
|
||||
goldmark.WithExtensions(
|
||||
highlighting.NewHighlighting(
|
||||
highlighting.WithStyle("fruity"),
|
||||
highlighting.WithFormatOptions(
|
||||
chromahtml.WithLineNumbers(true),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
if err := markdown.Convert(content, &buf); err != nil {
|
||||
http.Error(c.Response().Writer, "There was an issue rendering this post!", http.StatusInternalServerError)
|
||||
return nil
|
||||
}
|
||||
|
||||
props := PostProps{
|
||||
Content: template.HTML(buf.String()),
|
||||
Name: frontmatter.Name,
|
||||
Date: frontmatter.Date,
|
||||
Tags: frontmatter.Tags,
|
||||
}
|
||||
|
||||
// Specify the partials used by this page
|
||||
partials := []string{"header", "navitems"}
|
||||
|
||||
// Render the template
|
||||
return lib.RenderTemplate(c.Response().Writer, "post", partials, props)
|
||||
}
|
73
pages/projects.go
Normal file
73
pages/projects.go
Normal file
@ -0,0 +1,73 @@
|
||||
package pages
|
||||
|
||||
import (
|
||||
"atri.dad/lib"
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
type ProjectProps struct {
|
||||
Projects []lib.CardLink
|
||||
}
|
||||
|
||||
func Projects(c echo.Context) error {
|
||||
projects := []lib.CardLink{
|
||||
{
|
||||
Name: "Sprint Padawan",
|
||||
Description: "A scrum poker tool that helps agile teams plan their sprints in real-time.",
|
||||
Tags: []string{"react", "remix.js", "product"},
|
||||
Href: "https://sprintpadawan.dev",
|
||||
},
|
||||
{
|
||||
Name: "Atash",
|
||||
Description: "The 🔥hottest🔥 full-stack Remix template!",
|
||||
Tags: []string{"react", "remix.js", "template"},
|
||||
Href: "http://atash.atri.dad",
|
||||
},
|
||||
{
|
||||
Name: "Darius TS",
|
||||
Description: "🚀 A Web Application Template Powered by HTMX + Elysia + Tailwind 🚀",
|
||||
Tags: []string{"typescript", "htmx", "template"},
|
||||
Href: "https://ts.darius.atri.dad",
|
||||
},
|
||||
{
|
||||
Name: "Darius Go",
|
||||
Description: "🚀 A Web Application Template Powered by HTMX + Go Fiber + Tailwind 🚀",
|
||||
Tags: []string{"golang", "htmx", "template"},
|
||||
Href: "https://go.darius.atri.dad",
|
||||
},
|
||||
{
|
||||
Name: "Himbot",
|
||||
Description: "A discord bot written in Go. Loosly named after my username online (HimbothySwaggins).",
|
||||
Tags: []string{"golang", "bot"},
|
||||
Href: "https://github.com/atridadl/HimBot",
|
||||
},
|
||||
{
|
||||
Name: "Commodore",
|
||||
Description: "Helpful Nightbot Helpers for Twitch",
|
||||
Tags: []string{"react", "remix.js", "template"},
|
||||
Href: "https://commodore.atri.dad",
|
||||
},
|
||||
{
|
||||
Name: "loadr",
|
||||
Description: "A lightweight REST load testing tool with robust support for different verbs, token auth, and performance reports.",
|
||||
Tags: []string{"golang", "cli"},
|
||||
Href: "https://github.com/atridadl/loadr",
|
||||
},
|
||||
{
|
||||
Name: "GOTH Stack",
|
||||
Description: "A template using Go + Templates + HTMX",
|
||||
Tags: []string{"golang", "htmx", "template"},
|
||||
Href: "https://github.com/atridadl/goth.stack",
|
||||
},
|
||||
}
|
||||
|
||||
props := ProjectProps{
|
||||
Projects: projects,
|
||||
}
|
||||
|
||||
// Specify the partials used by this page
|
||||
partials := []string{"header", "navitems", "cardlinks"}
|
||||
|
||||
// Render the template
|
||||
return lib.RenderTemplate(c.Response().Writer, "base", partials, props)
|
||||
}
|
54
pages/rss.go
Normal file
54
pages/rss.go
Normal file
@ -0,0 +1,54 @@
|
||||
package pages
|
||||
|
||||
import (
|
||||
"io/fs"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
contentfs "atri.dad/content"
|
||||
"atri.dad/lib"
|
||||
"github.com/gorilla/feeds"
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
func RSSFeedHandler(c echo.Context) error {
|
||||
files, err := fs.ReadDir(contentfs.FS, ".")
|
||||
|
||||
protocol := "http"
|
||||
if c.Request().TLS != nil {
|
||||
protocol = "https"
|
||||
}
|
||||
|
||||
feed := &feeds.Feed{
|
||||
Title: "Atridad Lahiji's Blog",
|
||||
Link: &feeds.Link{Href: protocol + "://" + c.Request().Host + "/api/rss"},
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
http.Error(c.Response().Writer, "There was an issue finding posts!", http.StatusInternalServerError)
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, file := range files {
|
||||
if !file.IsDir() && strings.HasSuffix(file.Name(), ".md") {
|
||||
|
||||
frontMatter, err := lib.ExtractFrontMatter(file, contentfs.FS)
|
||||
if err != nil {
|
||||
http.Error(c.Response().Writer, "There was an issue rendering the posts!", http.StatusInternalServerError)
|
||||
return nil
|
||||
}
|
||||
|
||||
date, _ := time.Parse("January 2 2006", frontMatter.Date)
|
||||
|
||||
feed.Add(&feeds.Item{
|
||||
Title: frontMatter.Name,
|
||||
Link: &feeds.Link{Href: protocol + "://" + c.Request().Host + "/post/" + strings.TrimSuffix(file.Name(), ".md")},
|
||||
Created: date,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
rss, _ := feed.ToRss()
|
||||
return c.Blob(http.StatusOK, "application/rss+xml", []byte(rss))
|
||||
}
|
14
pages/ssedemo.go
Normal file
14
pages/ssedemo.go
Normal file
@ -0,0 +1,14 @@
|
||||
package pages
|
||||
|
||||
import (
|
||||
"atri.dad/lib"
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
func SSEDemo(c echo.Context) error {
|
||||
// Specify the partials used by this page
|
||||
partials := []string{"header", "navitems"}
|
||||
|
||||
// Render the template
|
||||
return lib.RenderTemplate(c.Response().Writer, "base", partials, nil)
|
||||
}
|
39
pages/talks.go
Normal file
39
pages/talks.go
Normal file
@ -0,0 +1,39 @@
|
||||
package pages
|
||||
|
||||
import (
|
||||
"atri.dad/lib"
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
type TalkProps struct {
|
||||
Talks []lib.CardLink
|
||||
}
|
||||
|
||||
func Talks(c echo.Context) error {
|
||||
talks := []lib.CardLink{
|
||||
{
|
||||
Name: "How to ship less JavaScript",
|
||||
Description: "A talk on building websites while being mindful of the JavaScript we ship. Presented at the Dev Edmonton July 2023 JS/Ruby/Python Meetup",
|
||||
Href: "https://github.com/atridadl/devedmonton-july-2023",
|
||||
Tags: []string{"astro", "ssr"},
|
||||
Date: "July 06, 2023",
|
||||
},
|
||||
{
|
||||
Name: "Hypermedia as the engine of application state - an Introduction",
|
||||
Description: "A talk on building reactive websites using tools like HTMX instead of JSON + JS. Will be presented at the Dev Edmonton Fabruary 2024 JS/Ruby/Python Meetup",
|
||||
Href: lib.GeneratePublicURL("hypermedia_talk_atridad.pdf"),
|
||||
Tags: []string{"golang", "htmx", "ssr"},
|
||||
Date: "February 01, 2024",
|
||||
},
|
||||
}
|
||||
|
||||
props := TalkProps{
|
||||
Talks: talks,
|
||||
}
|
||||
|
||||
// Specify the partials used by this page
|
||||
partials := []string{"header", "navitems", "cardlinks"}
|
||||
|
||||
// Render the template
|
||||
return lib.RenderTemplate(c.Response().Writer, "base", partials, props)
|
||||
}
|
22
pages/templates/blog.html
Normal file
22
pages/templates/blog.html
Normal file
@ -0,0 +1,22 @@
|
||||
{{define "title"}}
|
||||
Atridad Lahiji // Blog
|
||||
{{end}}
|
||||
|
||||
{{define "headercontent"}}
|
||||
Atridad Lahiji // Blog
|
||||
{{end}}
|
||||
|
||||
{{define "head"}}
|
||||
<link rel="stylesheet" href="/public/css/styles.blog.css" />
|
||||
{{end}}
|
||||
|
||||
{{define "main"}}
|
||||
<section class="flex flex-row flex-wrap gap-2 justify-center align-middle">
|
||||
{{range .Posts}}
|
||||
{{template "cardlinks" .}}
|
||||
{{end}}
|
||||
</section>
|
||||
{{end}}
|
||||
|
||||
{{define "foot"}}
|
||||
{{end}}
|
26
pages/templates/example.html
Normal file
26
pages/templates/example.html
Normal file
@ -0,0 +1,26 @@
|
||||
{{define "title"}}
|
||||
Atridad Lahiji // [SOMEPAGE]
|
||||
{{end}}
|
||||
|
||||
{{define "headercontent"}}
|
||||
Atridad Lahiji // [SOMEPAGE]
|
||||
{{end}}
|
||||
|
||||
{{define "head"}}
|
||||
<link rel="stylesheet" href="/public/css/styles.[SOMEPAGE].css" />
|
||||
{{end}}
|
||||
|
||||
{{define "main"}}
|
||||
<h1 class="text-4xl font-extrabold text-white sm:text-8xl">
|
||||
New <span
|
||||
class="bg-gradient-to-r from-pink-500 to-blue-500 bg-clip-text text-transparent"
|
||||
>Page</span
|
||||
>
|
||||
</h1>
|
||||
{{end}}
|
||||
|
||||
{{define "foot"}}
|
||||
<script src="/public/js/htmx.base.js"></script>
|
||||
<script src="/public/js/htmx.sse.js"></script>
|
||||
<script src="/public/js/hyperscript.js"></script>
|
||||
{{end}}
|
102
pages/templates/home.html
Normal file
102
pages/templates/home.html
Normal file
@ -0,0 +1,102 @@
|
||||
{{define "title"}}
|
||||
Atridad Lahiji // Root
|
||||
{{end}}
|
||||
|
||||
{{define "headercontent"}}
|
||||
Atridad Lahiji // Root
|
||||
{{end}}
|
||||
|
||||
{{define "head"}}
|
||||
<link rel="stylesheet" href="/public/css/styles.home.css" />
|
||||
{{end}}
|
||||
|
||||
{{define "main"}}
|
||||
<h1 class="text-4xl font-extrabold text-white sm:text-8xl">
|
||||
Hi, I'm <span
|
||||
class="bg-gradient-to-r from-pink-500 to-blue-500 bg-clip-text text-transparent"
|
||||
>Atridad</span
|
||||
>
|
||||
</h1>
|
||||
|
||||
<h2 class="text-2xl font-extrabold tracking-tight text-white sm:text-[2rem]">
|
||||
I'm a full stack developer who builds cool things for the web.
|
||||
</h2>
|
||||
|
||||
<span>
|
||||
<h2 class="mb-2 text-xl text-white sm:text-[1.5rem]">Places I exist:</h2>
|
||||
<div
|
||||
class="flex flex-row flex-wrap items-center justify-center gap-4 text-center"
|
||||
>
|
||||
{{range .Socials}}
|
||||
{{if eq .Name "Spotify"}}
|
||||
<div class="indicator indicator-top indicator-end">
|
||||
<div hx-ext="sse" sse-connect="/api/sse?channel=spotify" sse-swap="message">
|
||||
<span class="link link-hover link-success" hx-get="/api/nowplaying" hx-trigger="load" hx-swap="self">
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<a class="fill-white hover:fill-pink-500"
|
||||
href={{.Href}} target="_blank" rel="me" aria-label={{.Name}}>
|
||||
{{.Icon}}
|
||||
</a>
|
||||
</div>
|
||||
{{else}}
|
||||
<a class="fill-white hover:fill-pink-500"
|
||||
href={{.Href}} target="_blank" rel="me" aria-label={{.Name}}>
|
||||
{{.Icon}}
|
||||
</a>
|
||||
{{end}}
|
||||
{{end}}
|
||||
</div>
|
||||
</span>
|
||||
|
||||
|
||||
<span>
|
||||
<h2 class="mb-2 text-xl text-white sm:text-[1.5rem]">Stuff I Use:</h2>
|
||||
<div
|
||||
class="flex flex-row flex-wrap items-center justify-center gap-4 text-center"
|
||||
>
|
||||
{{range .Tech}}
|
||||
<a class="fill-white hover:fill-pink-500"
|
||||
href={{.Href}} target="_blank" rel="me" aria-label={{.Name}}>
|
||||
{{.Icon}}
|
||||
</a>
|
||||
{{end}}
|
||||
</div>
|
||||
</span>
|
||||
|
||||
<div class="flex flex-row flex-wrap gap-2">
|
||||
<a
|
||||
class="btn btn-primary btn-outline btn-md lg:btn-lg"
|
||||
href={{.ContractLink}}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
Contract Me
|
||||
</a>
|
||||
|
||||
<a
|
||||
class="btn btn-primary btn-outline btn-md lg:btn-lg"
|
||||
href={{.ResumeURL}}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
Resumé
|
||||
</a>
|
||||
|
||||
<a
|
||||
class="btn btn-primary btn-outline btn-md lg:btn-lg"
|
||||
href={{.SupportLink}}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
Support 🩵
|
||||
</a>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
{{define "foot"}}
|
||||
<script src="/public/js/htmx.base.js"></script>
|
||||
<script src="/public/js/htmx.sse.js"></script>
|
||||
<script src="/public/js/hyperscript.js"></script>
|
||||
{{end}}
|
22
pages/templates/layouts/base.html
Normal file
22
pages/templates/layouts/base.html
Normal file
@ -0,0 +1,22 @@
|
||||
{{define "base"}}
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" data-theme="night">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<link rel="icon" href="/public/favicon.ico" />
|
||||
<title>{{template "title" .}}</title>
|
||||
<meta name="description" content="Just here for the vibes...">
|
||||
{{template "head" .}}
|
||||
</head>
|
||||
|
||||
<body class="block h-[100%]">
|
||||
{{template "header" .}}
|
||||
|
||||
<main class="container flex flex-col items-center justify-center gap-3 sm:gap-6 p-4 text-center mx-auto min-h-[calc(100%-64px)]">
|
||||
{{template "main" .}}
|
||||
</main>
|
||||
{{template "foot" .}}
|
||||
</body>
|
||||
</html>
|
||||
{{end}}
|
58
pages/templates/layouts/post.html
Normal file
58
pages/templates/layouts/post.html
Normal file
@ -0,0 +1,58 @@
|
||||
{{define "post"}}
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" data-theme="night">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<link rel="icon" href="/public/favicon.ico" />
|
||||
<title>{{.Name}}</title>
|
||||
<meta name="description" content="Just here for the vibes...">
|
||||
{{template "head" .}}
|
||||
</head>
|
||||
|
||||
<body class="block h-[100%]">
|
||||
{{template "header" .}}
|
||||
|
||||
<main class="prose prose-invert mx-auto p-4">
|
||||
<article>
|
||||
<h1 class="title">{{.Name}}</h1>
|
||||
<div class="flex flex-row flex-wrap gap-4">
|
||||
{{if .Date}}
|
||||
<p>
|
||||
<div class="flex flex-row flex-wrap items-center gap-1 text-md">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-clock-4"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg>
|
||||
{{.Date}}
|
||||
</div>
|
||||
</p>
|
||||
{{end}}
|
||||
|
||||
{{if .Tags}}
|
||||
<div class="flex flex-row flex-wrap text-center items-center justify-center gap-1">
|
||||
{{range .Tags}}
|
||||
<div class="badge badge-accent">#{{.}}</div>
|
||||
{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
<div id="svgContainer" style="display: none;">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-check-circle"><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/><path d="m9 11 3 3L22 4"/></svg>
|
||||
</div>
|
||||
|
||||
<button id="copyButton" aria-label="Copy Link to Post" hx-get="/api/post/copy" hx-swap="innerHTML" hx-trigger="click delay:3s" _='on click put #svgContainer.innerHTML into me.innerHTML then call navigator.clipboard.writeText(window.location.href)'>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-copy"><rect width="14" height="14" x="8" y="8" rx="2" ry="2"/><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"/></svg>
|
||||
</button>
|
||||
|
||||
<a href="/blog" class="btn btn-primary btn-outline">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-undo-2"><path d="M9 14 4 9l5-5"/><path d="M4 9h10.5a5.5 5.5 0 0 1 5.5 5.5v0a5.5 5.5 0 0 1-5.5 5.5H11"/></svg>
|
||||
Back
|
||||
</a>
|
||||
</div>
|
||||
<hr />
|
||||
{{template "main" .}}
|
||||
|
||||
</article>
|
||||
</main>
|
||||
{{template "foot" .}}
|
||||
</body>
|
||||
</html>
|
||||
{{end}}
|
45
pages/templates/partials/cardlinks.html
Normal file
45
pages/templates/partials/cardlinks.html
Normal file
@ -0,0 +1,45 @@
|
||||
{{define "cardlinks"}}
|
||||
<div class="card card-compact w-64 bg-secondary shadow-xl">
|
||||
<div class="card-body text-base-100 flex flex-col">
|
||||
<h2 class="card-title text-base-100">{{.Name}}</h2>
|
||||
|
||||
{{if .Description}}
|
||||
<p>{{.Description}}</p>
|
||||
{{end}}
|
||||
|
||||
{{if .Date}}
|
||||
<p>
|
||||
<div class="flex flex-row flex-wrap items-center gap-1 text-md">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-clock-4"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg>
|
||||
{{.Date}}
|
||||
</div>
|
||||
</p>
|
||||
{{end}}
|
||||
|
||||
{{if .Tags}}
|
||||
<div class="flex flex-row flex-wrap text-center items-center justify-center gap-1">
|
||||
{{range .Tags}}
|
||||
<div class="badge badge-accent">#{{.}}</div>
|
||||
{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
{{if .Href}}
|
||||
<div class="card-actions justify-end">
|
||||
<a
|
||||
role="button"
|
||||
href={{.Href}}
|
||||
aria-label={{.Name}}
|
||||
class="btn btn-circle btn-base-100 text-primary hover:btn-accent hover:text-neutral"
|
||||
>
|
||||
{{if eq true .Internal}}
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-arrow-right"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
|
||||
{{else}}
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-link"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg>
|
||||
{{end}}
|
||||
</a>
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
4
pages/templates/partials/global.html
Normal file
4
pages/templates/partials/global.html
Normal file
@ -0,0 +1,4 @@
|
||||
|
||||
{{define "header"}}
|
||||
<div class="fill-green-500 tooltip tooltip-top badge badge-success"></div>
|
||||
{{end}}
|
20
pages/templates/partials/header.html
Normal file
20
pages/templates/partials/header.html
Normal file
@ -0,0 +1,20 @@
|
||||
{{define "header"}}
|
||||
<header class="navbar bg-base-100">
|
||||
<div class="navbar-start">
|
||||
<a class="btn btn-ghost normal-case text-lg sm:text-xl text-white" href="/">{{template "headercontent".}}</a>
|
||||
</div>
|
||||
<div class="navbar-end z-50">
|
||||
<div class="dropdown dropdown-end">
|
||||
<label tabindex="0" class="btn btn-sm btn-ghost text-white">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-menu"><line x1="4" x2="20" y1="12" y2="12"/><line x1="4" x2="20" y1="6" y2="6"/><line x1="4" x2="20" y1="18" y2="18"/></svg>
|
||||
</label>
|
||||
<ul
|
||||
tabindex="0"
|
||||
class="menu menu-compact dropdown-content gap-2 mt-3 p-2 shadow bg-base-100 rounded-box"
|
||||
>
|
||||
{{template "navitems" .}}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
{{end}}
|
27
pages/templates/partials/navitems.html
Normal file
27
pages/templates/partials/navitems.html
Normal file
@ -0,0 +1,27 @@
|
||||
{{define "navitems"}}
|
||||
<li>
|
||||
<a class="no-underline" href="/">
|
||||
Home
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="no-underline" href="/projects">
|
||||
Projects
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="no-underline" href="/talks">
|
||||
Talks
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="no-underline" href="/blog">
|
||||
Blog
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="no-underline" href="https://stats.uptimerobot.com/PoGQ9Cv9M2" target="_blank" rel="noreferrer">
|
||||
Status
|
||||
</a>
|
||||
</li>
|
||||
{{end}}
|
20
pages/templates/post.html
Normal file
20
pages/templates/post.html
Normal file
@ -0,0 +1,20 @@
|
||||
{{define "title"}}
|
||||
Atridad Lahiji // Post
|
||||
{{end}}
|
||||
|
||||
{{define "headercontent"}}
|
||||
Atridad Lahiji // Post
|
||||
{{end}}
|
||||
|
||||
{{define "head"}}
|
||||
<link rel="stylesheet" href="/public/css/styles.post.css" />
|
||||
{{end}}
|
||||
|
||||
{{define "main"}}
|
||||
{{.Content}}
|
||||
{{end}}
|
||||
|
||||
{{define "foot"}}
|
||||
<script src="/public/js/htmx.base.js"></script>
|
||||
<script src="/public/js/hyperscript.js"></script>
|
||||
{{end}}
|
22
pages/templates/projects.html
Normal file
22
pages/templates/projects.html
Normal file
@ -0,0 +1,22 @@
|
||||
{{define "title"}}
|
||||
Atridad Lahiji // Projects
|
||||
{{end}}
|
||||
|
||||
{{define "headercontent"}}
|
||||
Atridad Lahiji // Projects
|
||||
{{end}}
|
||||
|
||||
{{define "head"}}
|
||||
<link rel="stylesheet" href="/public/css/styles.projects.css" />
|
||||
{{end}}
|
||||
|
||||
{{define "main"}}
|
||||
<section class="flex flex-row flex-wrap gap-2 justify-center align-middle">
|
||||
{{range .Projects}}
|
||||
{{template "cardlinks" .}}
|
||||
{{end}}
|
||||
</section>
|
||||
{{end}}
|
||||
|
||||
{{define "foot"}}
|
||||
{{end}}
|
33
pages/templates/ssedemo.html
Normal file
33
pages/templates/ssedemo.html
Normal file
@ -0,0 +1,33 @@
|
||||
{{define "title"}}Atridad Lahiji // SSE{{end}}
|
||||
|
||||
{{define "headercontent"}}
|
||||
Atridad Lahiji // SSE <div class="badge badge-accent">BETA</div>
|
||||
{{end}}
|
||||
|
||||
{{define "head"}}
|
||||
<link rel="stylesheet" href="/public/css/styles.ssedemo.css" />
|
||||
{{end}}
|
||||
|
||||
{{define "main"}}
|
||||
<h1 class="text-4xl">Server Sent Events</h1>
|
||||
<h2 class="text-xl">This page demonstrates the use of the <a href="https://htmx.org/extensions/sse/">HTMX SSE Extention</a> to receive Server Sent Events on the "default" channel.</h2>
|
||||
<p class="text-lg">Any events received on the "default" channel will appear below:</p>
|
||||
<div hx-ext="sse" sse-connect="/api/sse" sse-swap="message">
|
||||
Waiting for SSE Message...
|
||||
</div>
|
||||
|
||||
<p class="text-lg">Here you can send messages on the default channel:</p>
|
||||
<form hx-post="/api/sendsse" hx-trigger="submit" hx-swap="none" class="flex-col flex gap-2">
|
||||
<div class="label">
|
||||
<span class="label-text">Message</span>
|
||||
</div>
|
||||
<input type="text" name="message" value="Hello world!" placeholder="Enter your message here" class="input input-bordered input-primary w-full max-w-xs" />
|
||||
|
||||
<button type="submit" class="btn btn-primary">Send Event</button>
|
||||
</form>
|
||||
{{end}}
|
||||
|
||||
{{define "foot"}}
|
||||
<script src="/public/js/htmx.base.js"></script>
|
||||
<script src="/public/js/htmx.sse.js"></script>
|
||||
{{end}}
|
22
pages/templates/talks.html
Normal file
22
pages/templates/talks.html
Normal file
@ -0,0 +1,22 @@
|
||||
{{define "title"}}
|
||||
Atridad Lahiji // Talks
|
||||
{{end}}
|
||||
|
||||
{{define "headercontent"}}
|
||||
Atridad Lahiji // Talks
|
||||
{{end}}
|
||||
|
||||
{{define "head"}}
|
||||
<link rel="stylesheet" href="/public/css/styles.talks.css" />
|
||||
{{end}}
|
||||
|
||||
{{define "main"}}
|
||||
<section class="flex flex-row flex-wrap gap-2 justify-center align-middle">
|
||||
{{range .Talks}}
|
||||
{{template "cardlinks" .}}
|
||||
{{end}}
|
||||
</section>
|
||||
{{end}}
|
||||
|
||||
{{define "foot"}}
|
||||
{{end}}
|
6
pages/templates/templatesfs.go
Normal file
6
pages/templates/templatesfs.go
Normal file
@ -0,0 +1,6 @@
|
||||
package templatefs
|
||||
|
||||
import "embed"
|
||||
|
||||
//go:embed *
|
||||
var FS embed.FS
|
Reference in New Issue
Block a user