fix github button from being glitchy
This commit is contained in:
parent
f2c4574e96
commit
ce111ec03d
11 changed files with 153 additions and 31 deletions
|
|
@ -117,6 +117,14 @@ func Href(path string) Ren {
|
|||
return Attribute("href", path)
|
||||
}
|
||||
|
||||
func Target(target string) Ren {
|
||||
return Attribute("target", target)
|
||||
}
|
||||
|
||||
func D(value string) Ren {
|
||||
return Attribute("d", value)
|
||||
}
|
||||
|
||||
func Type(name string) Ren {
|
||||
return Attribute("type", name)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,14 @@ func (node *Element) AppendChildren(children ...Ren) *Element {
|
|||
return node
|
||||
}
|
||||
|
||||
func Svg(children ...Ren) *Element {
|
||||
return Tag("svg", children...)
|
||||
}
|
||||
|
||||
func Path(children ...Ren) *Element {
|
||||
return Tag("path", children...)
|
||||
}
|
||||
|
||||
func TextF(format string, args ...interface{}) *TextContent {
|
||||
return Text(fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
|
|
|||
57
htmgo-site/internal/cache/simplecache.go
vendored
Normal file
57
htmgo-site/internal/cache/simplecache.go
vendored
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
package cache
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
type SimpleCache struct {
|
||||
data map[string]Entry
|
||||
lock sync.RWMutex
|
||||
}
|
||||
|
||||
type Entry struct {
|
||||
Value any
|
||||
Expiration time.Time
|
||||
}
|
||||
|
||||
func NewSimpleCache() *SimpleCache {
|
||||
return &SimpleCache{
|
||||
data: make(map[string]Entry),
|
||||
lock: sync.RWMutex{},
|
||||
}
|
||||
}
|
||||
|
||||
func (c *SimpleCache) Get(key string) (any, bool) {
|
||||
c.lock.RLock()
|
||||
defer c.lock.RUnlock()
|
||||
entry, ok := c.data[key]
|
||||
if !ok {
|
||||
return nil, false
|
||||
}
|
||||
if entry.Expiration.Before(time.Now()) {
|
||||
delete(c.data, key)
|
||||
return nil, false
|
||||
}
|
||||
return entry.Value, true
|
||||
}
|
||||
|
||||
func (c *SimpleCache) Set(key string, value any, expiration time.Duration) {
|
||||
c.lock.Lock()
|
||||
defer c.lock.Unlock()
|
||||
c.data[key] = Entry{
|
||||
Value: value,
|
||||
Expiration: time.Now().Add(expiration),
|
||||
}
|
||||
}
|
||||
|
||||
func GetOrSet[T any](cache *SimpleCache, key string, expiration time.Duration, cb func() (T, bool)) T {
|
||||
if val, ok := cache.Get(key); ok {
|
||||
return val.(T)
|
||||
}
|
||||
value, should := cb()
|
||||
if should {
|
||||
cache.Set(key, value, expiration)
|
||||
}
|
||||
return value
|
||||
}
|
||||
27
htmgo-site/internal/httpjson/client.go
Normal file
27
htmgo-site/internal/httpjson/client.go
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
package httpjson
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// Get sends a GET request and decodes the response JSON into a generic type T
|
||||
func Get[T any](url string) (*T, error) {
|
||||
resp, err := http.Get(url)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to make GET request: %w", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return nil, fmt.Errorf("received non-OK status code: %d", resp.StatusCode)
|
||||
}
|
||||
|
||||
var result T
|
||||
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
|
||||
return nil, fmt.Errorf("failed to decode response: %w", err)
|
||||
}
|
||||
|
||||
return &result, nil
|
||||
}
|
||||
|
|
@ -4,6 +4,7 @@ import (
|
|||
"github.com/maddalax/htmgo/framework/h"
|
||||
"github.com/maddalax/htmgo/framework/service"
|
||||
"htmgo-site/__htmgo"
|
||||
"htmgo-site/internal/cache"
|
||||
"htmgo-site/internal/markdown"
|
||||
"io/fs"
|
||||
"net/http"
|
||||
|
|
@ -15,6 +16,7 @@ func main() {
|
|||
markdownAssets := GetMarkdownAssets()
|
||||
|
||||
service.Set(locator, service.Singleton, markdown.NewRenderer)
|
||||
service.Set(locator, service.Singleton, cache.NewSimpleCache)
|
||||
|
||||
h.Start(h.AppOpts{
|
||||
ServiceLocator: locator,
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import (
|
|||
|
||||
var Version = uuid.NewString()[0:6]
|
||||
|
||||
func RootPage(children ...h.Ren) *h.Element {
|
||||
func RootPage(ctx *h.RequestContext, children ...h.Ren) *h.Element {
|
||||
title := "htmgo"
|
||||
description := "build simple and scalable systems with go + htmx"
|
||||
|
||||
|
|
@ -26,9 +26,6 @@ func RootPage(children ...h.Ren) *h.Element {
|
|||
h.Meta("og:description", description),
|
||||
h.LinkWithVersion("/public/main.css", "stylesheet", Version),
|
||||
h.ScriptWithVersion("/public/htmgo.js", Version),
|
||||
h.Raw(`
|
||||
<script src="https://buttons.github.io/buttons.js"></script>
|
||||
`),
|
||||
h.Style(`
|
||||
html {
|
||||
scroll-behavior: smooth;
|
||||
|
|
@ -37,7 +34,7 @@ func RootPage(children ...h.Ren) *h.Element {
|
|||
),
|
||||
h.Body(
|
||||
h.Class("bg-stone-50 min-h-screen overflow-x-hidden"),
|
||||
partials.NavBar(false),
|
||||
partials.NavBar(ctx, false),
|
||||
h.Fragment(children...),
|
||||
),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ func DocsPage(ctx *h.RequestContext) *h.Page {
|
|||
pages := dirwalk.WalkPages("md/docs", assets)
|
||||
|
||||
return h.NewPage(base.RootPage(
|
||||
ctx,
|
||||
h.Div(
|
||||
h.Class("flex flex-col md:flex-row gap-4 justify-center mb-12"),
|
||||
partials.DocSidebar(pages),
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ var examples = []Example{
|
|||
|
||||
func ExamplesPage(ctx *h.RequestContext) *h.Page {
|
||||
return h.NewPage(
|
||||
base.RootPage(h.Div(
|
||||
base.RootPage(ctx, h.Div(
|
||||
h.Class("flex items-center justify-center"),
|
||||
h.Div(
|
||||
h.Class("w-full px-4 flex flex-col prose max-w-[95vw] md:max-w-3xl mt-6"),
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import (
|
|||
|
||||
func IndexPage(ctx *h.RequestContext) *h.Page {
|
||||
return h.NewPage(
|
||||
base.RootPage(h.Div(
|
||||
base.RootPage(ctx, h.Div(
|
||||
h.Class("flex items-center justify-center "),
|
||||
h.Div(
|
||||
h.Class("w-full px-4 flex flex-col prose md:max-w-3xl mt-6 mx-auto"),
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import (
|
|||
func CurrentTimePage(ctx *h.RequestContext) *h.Page {
|
||||
return h.NewPage(
|
||||
base.RootPage(
|
||||
ctx,
|
||||
h.GetPartial(
|
||||
partials.CurrentTimePartial,
|
||||
"load, every 1s"),
|
||||
|
|
|
|||
|
|
@ -2,6 +2,10 @@ package partials
|
|||
|
||||
import (
|
||||
"github.com/maddalax/htmgo/framework/h"
|
||||
"github.com/maddalax/htmgo/framework/service"
|
||||
"htmgo-site/internal/cache"
|
||||
"htmgo-site/internal/httpjson"
|
||||
"time"
|
||||
)
|
||||
|
||||
type NavItem struct {
|
||||
|
|
@ -12,7 +16,7 @@ type NavItem struct {
|
|||
func ToggleNavbar(ctx *h.RequestContext) *h.Partial {
|
||||
return h.SwapManyPartial(
|
||||
ctx,
|
||||
MobileNav(h.GetQueryParam(ctx, "expanded") == "true"),
|
||||
MobileNav(ctx, h.GetQueryParam(ctx, "expanded") == "true"),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -21,26 +25,46 @@ var navItems = []NavItem{
|
|||
{Name: "Examples", Url: "/examples"},
|
||||
}
|
||||
|
||||
func Star() *h.Element {
|
||||
func Star(ctx *h.RequestContext) *h.Element {
|
||||
|
||||
return h.Div(
|
||||
h.Script("https://buttons.github.io/buttons.js"),
|
||||
h.Id("github-star"),
|
||||
h.Class("min-w-[100px]"),
|
||||
h.Raw(`
|
||||
<a
|
||||
class="github-button hidden min-w-[100px]"
|
||||
href="https://github.com/maddalax/htmgo"
|
||||
data-color-scheme="no-preference: light; light: light; dark: dark;"
|
||||
data-icon="octicon-star"
|
||||
data-size="large"
|
||||
data-show-count="true"
|
||||
aria-label="Star maddalax/htmgo on GitHub">Star</a>
|
||||
`),
|
||||
type Repo struct {
|
||||
StarCount int `json:"stargazers_count"`
|
||||
}
|
||||
|
||||
simpleCache := service.Get[cache.SimpleCache](ctx.ServiceLocator())
|
||||
count := cache.GetOrSet(simpleCache, "starCount", 10*time.Minute, func() (int, bool) {
|
||||
response, err := httpjson.Get[Repo]("https://api.github.com/repos/maddalax/htmgo")
|
||||
if err != nil {
|
||||
return 0, false
|
||||
}
|
||||
return response.StarCount, true
|
||||
})
|
||||
|
||||
return h.A(
|
||||
h.Href("https://github.com/maddalax/htmgo"),
|
||||
h.Target("_blank"),
|
||||
h.Class("inline-flex items-center rounded overflow-hidden shadow-sm"),
|
||||
h.Div(
|
||||
h.Class("flex items-center px-2 py-1 bg-gray-800 text-white text-sm font-semibold hover:bg-gray-700 transition"),
|
||||
h.Svg(
|
||||
h.Class("w-4 h-4 -mt-0.5 mr-0.5 fill-current text-white"),
|
||||
h.Attribute("xmlns", "http://www.w3.org/2000/svg"),
|
||||
h.Attribute("viewBox", "0 0 24 24"),
|
||||
h.Attribute("fill", "currentColor"),
|
||||
h.Path(
|
||||
h.D("M12 17.27l5.18 3.05-1.64-5.68 4.46-3.87-5.88-.5L12 3.5l-2.12 6.77-5.88.5 4.46 3.87-1.64 5.68L12 17.27z"),
|
||||
),
|
||||
),
|
||||
h.Text("Star"),
|
||||
),
|
||||
h.If(count > 0, h.Div(
|
||||
h.Class("flex items-center px-3 py-1 bg-black text-white text-sm font-semibold"),
|
||||
h.Pf("%d", count),
|
||||
)),
|
||||
)
|
||||
}
|
||||
|
||||
func NavBar(expanded bool) *h.Element {
|
||||
func NavBar(ctx *h.RequestContext, expanded bool) *h.Element {
|
||||
prelease := h.A(h.Class("bg-yellow-200 text-yellow-800 text-center p-2 flex items-center justify-center"),
|
||||
h.Href("https://github.com/maddalax/htmgo/issues"),
|
||||
h.Attribute("target", "_blank"),
|
||||
|
|
@ -72,10 +96,7 @@ func NavBar(expanded bool) *h.Element {
|
|||
),
|
||||
)
|
||||
}),
|
||||
h.Div(
|
||||
h.Class("ml-2 hidden md:block min-w-[99px]"),
|
||||
Star(),
|
||||
),
|
||||
Star(ctx),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
@ -84,12 +105,12 @@ func NavBar(expanded bool) *h.Element {
|
|||
return h.Div(
|
||||
h.Id("navbar"),
|
||||
prelease,
|
||||
MobileNav(expanded),
|
||||
MobileNav(ctx, expanded),
|
||||
desktopNav,
|
||||
)
|
||||
}
|
||||
|
||||
func MobileNav(expanded bool) *h.Element {
|
||||
func MobileNav(ctx *h.RequestContext, expanded bool) *h.Element {
|
||||
return h.Nav(
|
||||
h.Id("mobile-nav"),
|
||||
h.Class("block sm:hidden bg-neutral-100 border border-b-slate-300 p-4 md:p-3"),
|
||||
|
|
@ -107,7 +128,7 @@ func MobileNav(expanded bool) *h.Element {
|
|||
)),
|
||||
h.Div(
|
||||
h.Class("flex items-center gap-3"),
|
||||
h.Div(h.Class("mt-1"), Star()),
|
||||
h.Div(h.Class("mt-1"), Star(ctx)),
|
||||
h.Button(
|
||||
h.Boost(),
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue