snippets view testing / cleanup

This commit is contained in:
maddalax 2024-10-28 10:32:50 -05:00
parent 2726c60608
commit 42febeb654
19 changed files with 442 additions and 228 deletions

View file

@ -8,3 +8,7 @@ watch_ignore: [".git", "node_modules", "dist/*"]
# files to watch for changes, supports glob patterns through https://github.com/bmatcuk/doublestar
watch_files: ["**/*.go", "**/*.css", "**/*.md"]
# files or directories to ignore when automatically registering routes for pages
# supports glob patterns through https://github.com/bmatcuk/doublestar
automatic_page_routing_ignore: ["root.go"]

View file

@ -1,71 +0,0 @@
package base
import (
"github.com/google/uuid"
"github.com/maddalax/htmgo/framework/h"
"htmgo-site/partials"
)
var Version = uuid.NewString()[0:6]
func RootPage(ctx *h.RequestContext, children ...h.Ren) *h.Element {
title := "htmgo"
description := "build simple and scalable systems with go + htmx"
return h.Html(
h.HxExtension(
h.BaseExtensions(),
),
h.Head(
h.Meta("viewport", "width=device-width, initial-scale=1"),
h.Meta("title", title),
h.Link("/public/favicon.ico", "icon"),
h.Link("/public/apple-touch-icon.png", "apple-touch-icon"),
h.Meta("charset", "utf-8"),
h.Meta("author", "htmgo"),
h.Meta("description", description),
h.Meta("og:title", title),
h.Meta("og:url", "https://htmgo.dev"),
h.Link("canonical", "https://htmgo.dev"),
h.Link("https://cdn.jsdelivr.net/npm/@docsearch/css@3", "stylesheet"),
h.Meta("og:description", description),
h.LinkWithVersion("/public/main.css", "stylesheet", Version),
h.ScriptWithVersion("/public/htmgo.js", Version),
h.Style(`
html {
scroll-behavior: smooth;
}
`),
),
h.Body(
h.Class("bg-white h-screen"),
h.Fragment(children...),
h.Script("https://cdn.jsdelivr.net/npm/@docsearch/js@3"),
h.UnsafeRawScript(`
docsearch({
insights: true,
appId: "9IO2WZA8L1",
apiKey: "d8cd8b6f8f8a0c961ce971e09dbde90a",
indexName: "htmgo",
container: "#search-container",
debug: false
});
`),
),
)
}
func PageWithNav(ctx *h.RequestContext, children ...h.Ren) *h.Element {
return RootPage(
ctx,
h.Fragment(
partials.NavBar(ctx, partials.NavBarProps{
Expanded: false,
ShowPreRelease: true,
}),
h.Div(
children...,
),
),
)
}

View file

@ -3,7 +3,6 @@ package pages
import (
"github.com/maddalax/htmgo/framework/h"
"htmgo-site/internal/dirwalk"
"htmgo-site/pages/base"
"htmgo-site/partials"
"io/fs"
)
@ -12,7 +11,7 @@ func DocsPage(ctx *h.RequestContext) *h.Page {
assets := ctx.Get("embeddedMarkdown").(fs.FS)
pages := dirwalk.WalkPages("md/docs", assets)
return h.NewPage(base.RootPage(
return RootPage(
ctx,
h.Div(
h.Class("flex h-full"),
@ -28,7 +27,7 @@ func DocsPage(ctx *h.RequestContext) *h.Page {
}),
h.Main(
h.Div(
h.Class("w-full md:hidden bg-neutral-50 overflow-y-auto"),
h.Class("w-full md:hidden bg-neutral-50 overflow-y-auto mb-4 border-b border-b-slate-300"),
partials.DocSidebar(pages),
),
h.Class("overflow-y-auto justify-center overflow-x-hidden pb-6 items-center w-full"),
@ -63,5 +62,5 @@ func DocsPage(ctx *h.RequestContext) *h.Page {
),
),
),
))
)
}

View file

@ -2,7 +2,6 @@ package pages
import (
"github.com/maddalax/htmgo/framework/h"
"htmgo-site/pages/base"
)
type Example struct {
@ -49,39 +48,37 @@ var examples = []Example{
},
{
Title: "Form With Loading State",
Github: "https://github.com/maddalax/htmgo/blob/master/htmgo-site/pages/form.go",
Demo: "/form",
Github: "https://github.com/maddalax/htmgo/blob/master/htmgo-site/partials/snippets/form.go",
Demo: "/snippets/form",
Description: "A simple form submission example with a loading state",
},
}
func ExamplesPage(ctx *h.RequestContext) *h.Page {
return h.NewPage(
base.PageWithNav(
ctx,
return PageWithNav(
ctx,
h.Div(
h.Class("flex items-center justify-center"),
h.Div(
h.Class("flex items-center justify-center"),
h.Class("w-full px-4 flex flex-col prose max-w-[95vw] md:max-w-3xl mt-6"),
h.Div(
h.Class("w-full px-4 flex flex-col prose max-w-[95vw] md:max-w-3xl mt-6"),
h.Class("flex flex-col mb-6 md:mb-0 md:flex-row justify-between items-center"),
h.Div(
h.Class("flex flex-col mb-6 md:mb-0 md:flex-row justify-between items-center"),
h.Div(
h.H1(
h.Class("text-center md:text-left"),
h.Text("htmgo examples"),
),
h.H3(
h.Class("-mt-4"),
h.TextF("example projects built with htmgo"),
),
h.H1(
h.Class("text-center md:text-left"),
h.Text("htmgo examples"),
),
h.H3(
h.Class("-mt-4"),
h.TextF("example projects built with htmgo"),
),
),
),
h.Div(
h.Class("border-b border-b-slate-200 h-1"),
h.Div(
h.Class("border-b border-b-slate-200 h-1"),
h.Div(
h.Class("mt-4"),
ExampleCards(),
),
h.Class("mt-4"),
ExampleCards(),
),
),
),

View file

@ -2,25 +2,22 @@ package pages
import (
"github.com/maddalax/htmgo/framework/h"
"htmgo-site/pages/base"
"htmgo-site/partials"
)
func HtmlToGoPage(ctx *h.RequestContext) *h.Page {
return h.NewPage(
base.PageWithNav(
ctx,
return PageWithNav(
ctx,
h.Div(
h.Class("flex flex-col h-screen items-center justify-center w-full pt-6"),
h.H3(
h.Text("Convert raw html to htmgo code"),
h.Class("text-2xl font-bold"),
),
h.Div(
h.Class("flex flex-col h-screen items-center justify-center w-full pt-6"),
h.H3(
h.Text("Convert raw html to htmgo code"),
h.Class("text-2xl font-bold"),
),
h.Div(
h.Class("h-full w-full flex gap-4 p-8"),
partials.HtmlInput(),
partials.GoOutput(""),
),
h.Class("h-full w-full flex gap-4 p-8"),
partials.HtmlInput(),
partials.GoOutput(""),
),
),
)

View file

@ -2,47 +2,44 @@ package pages
import (
"github.com/maddalax/htmgo/framework/h"
"htmgo-site/pages/base"
)
func IndexPage(ctx *h.RequestContext) *h.Page {
return h.NewPage(
base.PageWithNav(
ctx,
return PageWithNav(
ctx,
h.Div(
h.Class("flex items-center justify-center"),
h.Div(
h.Class("flex items-center justify-center"),
h.Class("w-full px-4 flex flex-col prose md:max-w-3xl mt-6 mx-auto"),
h.Div(
h.Class("w-full px-4 flex flex-col prose md:max-w-3xl mt-6 mx-auto"),
h.Class("flex flex-col mb-6 md:mb-0 md:flex-row justify-between items-center"),
h.Div(
h.Class("flex flex-col mb-6 md:mb-0 md:flex-row justify-between items-center"),
h.Div(
h.H1F(
"htmgo",
h.Class("text-center md:text-left"),
),
h.H3F(
"build simple and scalable systems with %s",
"go + htmx",
h.Class("-mt-4"),
),
h.H1F(
"htmgo",
h.Class("text-center md:text-left"),
),
h.Div(
h.Class("mt-2"),
h.A(
h.Href("/docs"),
h.Class("not-prose p-3 bg-slate-900 text-white rounded-md"),
h.Text("Get Started"),
),
h.H3F(
"build simple and scalable systems with %s",
"go + htmx",
h.Class("-mt-4"),
),
),
h.Div(
h.Class("border-b border-b-slate-200 h-1"),
h.Div(
h.Class("mt-4"),
MarkdownPage(ctx, "md/index.md", ""),
h.Class("mt-2"),
h.A(
h.Href("/docs"),
h.Class("not-prose p-3 bg-slate-900 text-white rounded-md"),
h.Text("Get Started"),
),
),
),
h.Div(
h.Class("border-b border-b-slate-200 h-1"),
h.Div(
h.Class("mt-4"),
MarkdownPage(ctx, "md/index.md", ""),
),
),
),
),
)

72
htmgo-site/pages/root.go Normal file
View file

@ -0,0 +1,72 @@
package pages
import (
"github.com/google/uuid"
"github.com/maddalax/htmgo/framework/h"
"htmgo-site/partials"
)
var Version = uuid.NewString()[0:6]
func RootPage(ctx *h.RequestContext, children ...h.Ren) *h.Page {
title := "htmgo"
description := "build simple and scalable systems with go + htmx"
return h.NewPage(
h.Html(
h.HxExtension(
h.BaseExtensions(),
),
h.Head(
h.Meta("viewport", "width=device-width, initial-scale=1"),
h.Meta("title", title),
h.Link("/public/favicon.ico", "icon"),
h.Link("/public/apple-touch-icon.png", "apple-touch-icon"),
h.Meta("charset", "utf-8"),
h.Meta("author", "htmgo"),
h.Meta("description", description),
h.Meta("og:title", title),
h.Meta("og:url", "https://htmgo.dev"),
h.Link("canonical", "https://htmgo.dev"),
h.Link("https://cdn.jsdelivr.net/npm/@docsearch/css@3", "stylesheet"),
h.Meta("og:description", description),
h.LinkWithVersion("/public/main.css", "stylesheet", Version),
h.ScriptWithVersion("/public/htmgo.js", Version),
h.Style(`
html {
scroll-behavior: smooth;
}
`),
),
h.Body(
h.Class("bg-white h-screen"),
h.Fragment(children...),
h.Script("https://cdn.jsdelivr.net/npm/@docsearch/js@3"),
h.UnsafeRawScript(`
docsearch({
insights: true,
appId: "9IO2WZA8L1",
apiKey: "d8cd8b6f8f8a0c961ce971e09dbde90a",
indexName: "htmgo",
container: "#search-container",
debug: false
});
`),
),
),
)
}
func PageWithNav(ctx *h.RequestContext, children ...h.Ren) *h.Page {
return RootPage(
ctx,
h.Fragment(
partials.NavBar(ctx, partials.NavBarProps{
Expanded: false,
ShowPreRelease: true,
}),
h.Div(
children...,
),
),
)
}

View file

@ -0,0 +1,38 @@
package snippets
import (
"fmt"
"github.com/maddalax/htmgo/framework/h"
"htmgo-site/ui"
"os"
"reflect"
"runtime"
)
func getFunctionFilePath(fn interface{}) string {
// Get the function pointer using reflection
ptr := reflect.ValueOf(fn).Pointer()
// Get the file path and line number using runtime
fnInfo := runtime.FuncForPC(ptr)
if fnInfo == nil {
return ""
}
file, _ := fnInfo.FileLine(ptr)
return file
}
func GetGithubPath(path string) string {
return fmt.Sprintf("https://github.com/maddalax/htmgo/blob/master%s", path)
}
func RenderCodeToString(partial h.PartialFunc) *h.Element {
path := getFunctionFilePath(partial)
if path == "" {
return h.Empty()
}
bytes, err := os.ReadFile(path)
if err != nil {
return h.Empty()
}
return ui.CodeSnippet(string(bytes), "border-radius: 0.5rem;")
}

View file

@ -0,0 +1,22 @@
package snippets
import "github.com/maddalax/htmgo/framework/h"
type Snippet struct {
name string
description string
sidebarName string
path string
partial h.PartialFunc
}
func SetSnippet(ctx *h.RequestContext, snippet *Snippet) {
ctx.Set("snippet", snippet)
}
func GetSnippet(ctx *h.RequestContext) *Snippet {
if ctx.Get("snippet") == nil {
return nil
}
return ctx.Get("snippet").(*Snippet)
}

View file

@ -0,0 +1,10 @@
package snippets
import (
"github.com/maddalax/htmgo/framework/h"
)
func FormExample(ctx *h.RequestContext) *h.Page {
SetSnippet(ctx, &FormWithLoadingState)
return Index(ctx)
}

View file

@ -0,0 +1,120 @@
package snippets
import (
"github.com/maddalax/htmgo/framework/h"
"htmgo-site/pages"
"htmgo-site/partials"
)
func Index(ctx *h.RequestContext) *h.Page {
snippet := GetSnippet(ctx)
return pages.RootPage(
ctx,
h.Div(
h.Class("flex h-full"),
h.Aside(
h.Class("hidden md:block md:min-w-60 text-white overflow-y-auto"),
SnippetSidebar(),
),
h.Div(
h.Class("flex flex-col flex-1 overflow-hidden"),
partials.NavBar(ctx, partials.NavBarProps{
Expanded: false,
ShowPreRelease: false,
}),
h.Main(
h.Div(
h.Class("w-full md:hidden bg-neutral-50 overflow-y-auto mb-4 border-b border-b-slate-300"),
SnippetSidebar(),
),
h.Class("overflow-y-auto justify-center overflow-x-hidden pb-6 items-center w-full"),
h.Div(
h.Class("flex flex-col mx-auto"),
h.Div(
h.Class("flex flex-col justify-center items-center md:mt-6 mx-auto"),
),
h.IfElseLazy(
snippet != nil,
func() *h.Element {
return snippetView(snippet)
},
emptyState,
),
),
),
),
),
)
}
func snippetView(snippet *Snippet) *h.Element {
return h.Div(
h.Class("flex flex-col mx-auto items-center gap-6 max-w-[90vw] md:max-w-[75vw] xl:max-w-4xl px-8"),
h.Div(
h.Class("flex flex-col gap-1 w-full"),
h.H2(
h.Text(snippet.name),
h.Class("text-2xl font-bold"),
),
h.If(
snippet.description != "",
h.P(
h.Text(snippet.description),
h.Class("text-slate-900"),
),
),
),
h.Div(
h.Class("border px-8 py-4 rounded-md shadow-sm border-slate-200 w-full"),
h.Div(
h.Get(
h.GetPartialPath(snippet.partial),
"load",
),
),
),
h.Div(
h.Class("mt-8 flex flex-col gap-2 justify-center"),
h.Div(
h.Class("flex gap-2 items-center"),
h.A(
githubLogo(),
h.Href(GetGithubPath(snippet.path)),
h.Class("font-sm text-blue-500 hover:text-blue-400"),
),
h.H3(
h.Text("Source Code"),
h.Class("text-lg font-bold"),
),
),
RenderCodeToString(snippet.partial),
),
)
}
func emptyState() *h.Element {
return h.Div(
h.Class("flex flex-col gap-2 justify-center items-center mt-8"),
h.Div(
h.Class("flex gap-2 items-center"),
h.H3(
h.Text("Choose a snippet on the sidebar to view"),
h.Class("text-lg"),
),
),
)
}
func githubLogo() *h.Element {
return h.Body(
h.Svg(
h.Attribute("xmlns", "http://www.w3.org/2000/svg"),
h.Width(24),
h.Height(24),
h.Attribute("viewBox", "0 0 24 24"),
h.Path(
h.Attribute("d", "M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"),
),
),
)
}

View file

@ -0,0 +1,31 @@
package snippets
import (
"github.com/maddalax/htmgo/framework/h"
)
func SnippetSidebar() *h.Element {
return h.Div(
h.Class("px-3 py-2 pr-6 md:min-h-screen pb-4 mb:pb-0 bg-neutral-50 border-r border-r-slate-300 overflow-y-auto"),
h.Div(
h.Div(
h.Class("mb-3"),
h.A(
h.Href("#"),
h.Text("Snippets"),
h.Class("md:mt-4 text-xl text-slate-900 font-bold"),
),
),
h.Div(
h.Class("flex flex-col gap-4"),
h.List(Snippets, func(entry Snippet, index int) *h.Element {
return h.A(
h.Href(entry.path),
h.Text(entry.sidebarName),
h.Class("text-slate-900 hover:text-rose-400"),
)
}),
),
),
)
}

View file

@ -0,0 +1,17 @@
package snippets
import (
"htmgo-site/partials/snippets"
)
var FormWithLoadingState = Snippet{
name: "Form",
description: "A simple form submission example with a loading state",
sidebarName: "Form with loading state",
path: "/snippets/form",
partial: snippets.FormExample,
}
var Snippets = []Snippet{
FormWithLoadingState,
}

View file

@ -3,24 +3,21 @@ package pages
import (
"fmt"
"github.com/maddalax/htmgo/framework/h"
"htmgo-site/pages/base"
)
func TestFormatPage(ctx *h.RequestContext) *h.Page {
return h.NewPage(
base.RootPage(
ctx,
h.Div(
h.P(
h.Class("hello"),
h.Details(
h.Summary(
h.Text("Summary"),
),
h.Text("Details"),
return RootPage(
ctx,
h.Div(
h.P(
h.Class("hello"),
h.Details(
h.Summary(
h.Text("Summary"),
),
h.Id("hi"),
h.Text("Details"),
),
h.Id("hi"),
),
),
)
@ -33,26 +30,23 @@ func notPage() int {
}
func TestOtherPage(ctx *h.RequestContext) *h.Page {
return h.NewPage(
base.RootPage(
ctx,
h.Div(
h.Id("test"),
h.Details(
h.Summary(
h.Text("Summary"),
),
h.Text("Details"),
return RootPage(
ctx,
h.Div(
h.Id("test"),
h.Details(
h.Summary(
h.Text("Summary"),
),
h.Class("flex flex-col gap-2 bg-white h-full"),
h.Id("test"),
h.Details(
h.Summary(
h.Text("Summary"),
),
h.Text("Details"),
h.Text("Details"),
),
h.Class("flex flex-col gap-2 bg-white h-full"),
h.Id("test"),
h.Details(
h.Summary(
h.Text("Summary"),
),
h.Text("Details"),
),
),
)

View file

@ -2,16 +2,14 @@ package pages
import (
"github.com/maddalax/htmgo/framework/h"
"htmgo-site/pages/base"
"htmgo-site/partials"
)
func CurrentTimePage(ctx *h.RequestContext) *h.Page {
return h.NewPage(
base.RootPage(
ctx,
h.GetPartial(
partials.CurrentTimePartial,
"load, every 1s"),
))
return RootPage(
ctx,
h.GetPartial(
partials.CurrentTimePartial,
"load, every 1s"),
)
}

View file

@ -57,7 +57,7 @@ func DocSidebar(pages []*dirwalk.Page) *h.Element {
grouped := groupByFirstPart(pages)
return h.Div(
h.Class("px-3 py-2 pr-6 min-h-screen bg-neutral-50 border-r border-r-slate-300 overflow-y-auto"),
h.Class("px-3 py-2 pr-6 md:min-h-screen pb-4 mb:pb-0 bg-neutral-50 border-r border-r-slate-300 overflow-y-auto"),
h.Div(
h.Div(
h.Class("mb-3"),

View file

@ -1,15 +0,0 @@
package partials
import (
"github.com/maddalax/htmgo/framework/h"
"time"
)
func SubmitForm(ctx *h.RequestContext) *h.Partial {
time.Sleep(time.Second * 3)
return h.NewPartial(
h.Div(
h.Text("Form submitted"),
),
)
}

View file

@ -1,42 +1,33 @@
package pages
package snippets
import (
"github.com/maddalax/htmgo/framework/h"
"github.com/maddalax/htmgo/framework/hx"
"github.com/maddalax/htmgo/framework/js"
"htmgo-site/pages/base"
"htmgo-site/partials"
"time"
)
func Form(ctx *h.RequestContext) *h.Page {
return h.NewPage(base.RootPage(
ctx,
h.Div(
h.Class("flex flex-col items-center justify-center p-4 gap-6"),
h.H2F(
"Form submission with loading state example",
h.Class("text-2xl font-bold"),
),
h.Form(
h.TriggerChildren(),
h.PostPartial(partials.SubmitForm),
h.Class("flex flex-col gap-2"),
h.LabelFor("name", "Your Name"),
h.Input(
"text",
h.Required(),
h.Class("p-4 rounded-md border border-slate-200"),
h.Name("name"),
h.Placeholder("Name"),
h.OnEvent(
hx.KeyDownEvent,
js.SubmitFormOnEnter(),
),
func FormExample(ctx *h.RequestContext) *h.Partial {
return h.NewPartial(
h.Form(
h.TriggerChildren(),
h.PostPartial(SubmitForm),
h.Class("flex flex-col gap-2 max-w-[300px] mx-auto"),
h.LabelFor("name", "Your Name"),
h.Input(
"text",
h.Required(),
h.Class("p-4 rounded-md border border-slate-200"),
h.Name("name"),
h.Placeholder("Name"),
h.OnEvent(
hx.KeyDownEvent,
js.SubmitFormOnEnter(),
),
SubmitButton(),
),
SubmitButton(),
),
))
)
}
func SubmitButton() *h.Element {
@ -68,7 +59,18 @@ func SubmitButton() *h.Element {
func Spinner(children ...h.Ren) *h.Element {
return h.Div(
h.Children(children...),
h.Class("absolute left-1 spinner spinner-border animate-spin inline-block w-6 h-6 border-4 rounded-full border-slate-200 border-t-transparent"),
h.Class("absolute left-1 spinner spinner-border animate-spin "+
"inline-block w-6 h-6 border-4 rounded-full border-slate-200 border-t-transparent"),
h.Attribute("role", "status"),
)
}
func SubmitForm(ctx *h.RequestContext) *h.Partial {
name := ctx.FormValue("name")
time.Sleep(time.Second * 2)
return h.NewPartial(
h.Div(
h.TextF("Form submitted with name: %s", name),
),
)
}

View file

@ -16,8 +16,10 @@ func FormatCode(code string, customStyles ...string) string {
lexer := lexers.Get("go")
style := styles.Get("github")
formatter := html.New(
html.WrapLongLines(true),
html.WithLineNumbers(true),
html.WithCustomCSS(map[chroma.TokenType]string{
chroma.PreWrapper: fmt.Sprintf("padding: 12px; overflow: auto; %s", strings.Join(customStyles, ";")),
chroma.PreWrapper: fmt.Sprintf("padding: 12px; overflow: auto; background-color: rgb(245, 245, 245) !important; %s", strings.Join(customStyles, ";")),
}))
iterator, err := lexer.Tokenise(nil, code)
if err != nil {
@ -27,8 +29,8 @@ func FormatCode(code string, customStyles ...string) string {
return buf.String()
}
func CodeSnippet(code string) *h.Element {
func CodeSnippet(code string, customStyles ...string) *h.Element {
return h.Div(
h.UnsafeRaw(FormatCode(code)),
h.UnsafeRaw(FormatCode(code, customStyles...)),
)
}