fix build step
This commit is contained in:
parent
08337c9e8a
commit
8c51c5227e
14 changed files with 168 additions and 115 deletions
67
cli/htmgo/internal/dirutil/dir.go
Normal file
67
cli/htmgo/internal/dirutil/dir.go
Normal file
|
|
@ -0,0 +1,67 @@
|
||||||
|
package dirutil
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"log/slog"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
)
|
||||||
|
|
||||||
|
func CopyDir(srcDir, dstDir string, predicate func(path string, exists bool) bool) error {
|
||||||
|
// Walk the source directory tree.
|
||||||
|
return filepath.Walk(srcDir, func(srcPath string, info os.FileInfo, err error) error {
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// Construct the corresponding destination path.
|
||||||
|
relPath, err := filepath.Rel(srcDir, srcPath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
dstPath := filepath.Join(dstDir, relPath)
|
||||||
|
if info.IsDir() {
|
||||||
|
// If it's a directory, create the corresponding directory in the destination.
|
||||||
|
err := os.MkdirAll(dstPath, 0700)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to create directory: %v", err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
exists := true
|
||||||
|
if _, err := os.Stat(dstPath); errors.Is(err, os.ErrNotExist) {
|
||||||
|
exists = false
|
||||||
|
}
|
||||||
|
if predicate(srcPath, exists) {
|
||||||
|
err := CopyFile(srcPath, dstPath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If it's a file, copy the file.
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func CopyFile(src, dst string) error {
|
||||||
|
slog.Debug("copying file", slog.String("src", src), slog.String("dst", dst))
|
||||||
|
// Open the source file for reading.
|
||||||
|
srcFile, err := os.Open(src)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to open source file: %v", err)
|
||||||
|
}
|
||||||
|
defer srcFile.Close()
|
||||||
|
// Create the destination file.
|
||||||
|
dstFile, err := os.Create(dst)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to create destination file: %v", err)
|
||||||
|
}
|
||||||
|
defer dstFile.Close()
|
||||||
|
// Copy the content from srcFile to dstFile.
|
||||||
|
_, err = io.Copy(dstFile, srcFile)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to copy file contents: %v", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
@ -2,14 +2,13 @@ package copyassets
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/maddalax/htmgo/cli/htmgo/internal/dirutil"
|
||||||
"github.com/maddalax/htmgo/cli/htmgo/tasks/module"
|
"github.com/maddalax/htmgo/cli/htmgo/tasks/module"
|
||||||
"github.com/maddalax/htmgo/cli/htmgo/tasks/process"
|
"github.com/maddalax/htmgo/cli/htmgo/tasks/process"
|
||||||
"golang.org/x/mod/modfile"
|
"golang.org/x/mod/modfile"
|
||||||
"io"
|
|
||||||
"log"
|
"log"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -36,60 +35,6 @@ func getModuleVersion(modulePath string) (string, error) {
|
||||||
return "", fmt.Errorf("module %s not found in go.mod", modulePath)
|
return "", fmt.Errorf("module %s not found in go.mod", modulePath)
|
||||||
}
|
}
|
||||||
|
|
||||||
func copyFile(src, dst string) error {
|
|
||||||
// Open the source file for reading.
|
|
||||||
srcFile, err := os.Open(src)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to open source file: %v", err)
|
|
||||||
}
|
|
||||||
defer srcFile.Close()
|
|
||||||
// Create the destination file.
|
|
||||||
dstFile, err := os.Create(dst)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to create destination file: %v", err)
|
|
||||||
}
|
|
||||||
defer dstFile.Close()
|
|
||||||
// Copy the content from srcFile to dstFile.
|
|
||||||
_, err = io.Copy(dstFile, srcFile)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to copy file contents: %v", err)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// copyDir copies a directory recursively from src to dst.
|
|
||||||
func copyDir(srcDir, dstDir string, skip func(path string) bool) error {
|
|
||||||
// Walk the source directory tree.
|
|
||||||
return filepath.Walk(srcDir, func(srcPath string, info os.FileInfo, err error) error {
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// Construct the corresponding destination path.
|
|
||||||
relPath, err := filepath.Rel(srcDir, srcPath)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
dstPath := filepath.Join(dstDir, relPath)
|
|
||||||
if info.IsDir() {
|
|
||||||
// If it's a directory, create the corresponding directory in the destination.
|
|
||||||
err := os.MkdirAll(dstPath, 0700)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to create directory: %v", err)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if skip != nil && skip(srcPath) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
// If it's a file, copy the file.
|
|
||||||
err := copyFile(srcPath, dstPath)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func CopyAssets() {
|
func CopyAssets() {
|
||||||
moduleName := "github.com/maddalax/htmgo/framework"
|
moduleName := "github.com/maddalax/htmgo/framework"
|
||||||
modulePath := module.GetDependencyPath(moduleName)
|
modulePath := module.GetDependencyPath(moduleName)
|
||||||
|
|
@ -119,14 +64,14 @@ func CopyAssets() {
|
||||||
destDirDist := fmt.Sprintf("%s/dist", destDir)
|
destDirDist := fmt.Sprintf("%s/dist", destDir)
|
||||||
destDirCss := fmt.Sprintf("%s/css", destDir)
|
destDirCss := fmt.Sprintf("%s/css", destDir)
|
||||||
|
|
||||||
err := copyDir(assetDistDir, destDirDist, func(path string) bool {
|
err := dirutil.CopyDir(assetDistDir, destDirDist, func(path string, exists bool) bool {
|
||||||
return false
|
return true
|
||||||
})
|
})
|
||||||
err = copyDir(assetCssDir, destDirCss, func(path string) bool {
|
err = dirutil.CopyDir(assetCssDir, destDirCss, func(path string, exists bool) bool {
|
||||||
if strings.HasSuffix(path, "tailwind.config.js") {
|
if exists {
|
||||||
return true
|
return false
|
||||||
}
|
}
|
||||||
return false
|
return true
|
||||||
})
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,9 @@ var workingDir string
|
||||||
var commands = make([]CmdWithFlags, 0)
|
var commands = make([]CmdWithFlags, 0)
|
||||||
|
|
||||||
func AppendRunning(cmd *exec.Cmd, flags ...RunFlag) {
|
func AppendRunning(cmd *exec.Cmd, flags ...RunFlag) {
|
||||||
slog.Debug("running", slog.String("command", strings.Join(cmd.Args, " ")))
|
slog.Debug("running", slog.String("command", strings.Join(cmd.Args, " ")),
|
||||||
|
slog.String("dir", cmd.Dir),
|
||||||
|
slog.String("cwd", GetWorkingDir()))
|
||||||
commands = append(commands, CmdWithFlags{flags: flags, cmd: cmd})
|
commands = append(commands, CmdWithFlags{flags: flags, cmd: cmd})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,18 @@ func Build() {
|
||||||
astgen.GenAst(process.ExitOnError)
|
astgen.GenAst(process.ExitOnError)
|
||||||
css.GenerateCss(process.ExitOnError)
|
css.GenerateCss(process.ExitOnError)
|
||||||
process.RunOrExit("rm -rf ./dist")
|
process.RunOrExit("rm -rf ./dist")
|
||||||
process.RunOrExit("mkdir -p ./dist/assets/dist")
|
process.RunOrExit("mkdir -p ./dist")
|
||||||
process.RunOrExit("cp -r ./assets/dist/* ./dist/assets/dist/")
|
|
||||||
process.RunOrExit("go build -o \"./dist\" .")
|
//process.RunOrExit("mkdir -p ./dist/assets/dist")
|
||||||
|
|
||||||
|
//dirutil.CopyDir(
|
||||||
|
// "./assets/dist",
|
||||||
|
// "./dist/assets/dist",
|
||||||
|
// func(path string, exists bool) bool {
|
||||||
|
// return true
|
||||||
|
// },
|
||||||
|
//)
|
||||||
|
|
||||||
|
process.RunOrExit("go build -o ./dist .")
|
||||||
process.RunOrExit("echo \"Build successful\"")
|
process.RunOrExit("echo \"Build successful\"")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,10 @@ func Start(opts AppOpts) {
|
||||||
|
|
||||||
func (a App) start() {
|
func (a App) start() {
|
||||||
|
|
||||||
|
if a.Opts.Register != nil {
|
||||||
|
a.Opts.Register(a.Echo)
|
||||||
|
}
|
||||||
|
|
||||||
a.Echo.Use(func(next echo.HandlerFunc) echo.HandlerFunc {
|
a.Echo.Use(func(next echo.HandlerFunc) echo.HandlerFunc {
|
||||||
return func(c echo.Context) error {
|
return func(c echo.Context) error {
|
||||||
cc := &RequestContext{
|
cc := &RequestContext{
|
||||||
|
|
@ -59,10 +63,6 @@ func (a App) start() {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
if a.Opts.Register != nil {
|
|
||||||
a.Opts.Register(a.Echo)
|
|
||||||
}
|
|
||||||
|
|
||||||
if a.Opts.LiveReload {
|
if a.Opts.LiveReload {
|
||||||
AddLiveReloadHandler("/dev/livereload", a.Echo)
|
AddLiveReloadHandler("/dev/livereload", a.Echo)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,8 @@ package dirwalk
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/maddalax/htmgo/framework/h"
|
"github.com/maddalax/htmgo/framework/h"
|
||||||
|
"io/fs"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -13,14 +13,14 @@ type Page struct {
|
||||||
Parts []string
|
Parts []string
|
||||||
}
|
}
|
||||||
|
|
||||||
func WalkPages(dir string) []Page {
|
func WalkPages(dir string, system fs.FS) []Page {
|
||||||
pages := make([]Page, 0)
|
pages := make([]Page, 0)
|
||||||
filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
|
fs.WalkDir(system, dir, func(path string, d fs.DirEntry, err error) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
name := info.Name()
|
name := d.Name()
|
||||||
if !info.IsDir() && (strings.HasSuffix(name, ".md") || strings.HasSuffix(name, ".go")) {
|
if !d.IsDir() && (strings.HasSuffix(name, ".md") || strings.HasSuffix(name, ".go")) {
|
||||||
fullPath := strings.Replace(path, dir, "", 1)
|
fullPath := strings.Replace(path, dir, "", 1)
|
||||||
fullPath = strings.TrimSuffix(fullPath, ".md")
|
fullPath = strings.TrimSuffix(fullPath, ".md")
|
||||||
pages = append(pages, Page{
|
pages = append(pages, Page{
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import (
|
||||||
"github.com/yuin/goldmark/parser"
|
"github.com/yuin/goldmark/parser"
|
||||||
"github.com/yuin/goldmark/renderer/html"
|
"github.com/yuin/goldmark/renderer/html"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"io/fs"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Renderer struct {
|
type Renderer struct {
|
||||||
|
|
@ -19,15 +19,13 @@ func NewRenderer() *Renderer {
|
||||||
return &Renderer{cache: make(map[string]string)}
|
return &Renderer{cache: make(map[string]string)}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Renderer) RenderFile(source string) string {
|
func (r *Renderer) RenderFile(source string, system fs.FS) string {
|
||||||
if val, ok := r.cache[source]; ok {
|
if val, ok := r.cache[source]; ok {
|
||||||
return val
|
return val
|
||||||
}
|
}
|
||||||
|
|
||||||
o, err := os.Open(source)
|
o, err := system.Open(source)
|
||||||
defer func(o *os.File) {
|
defer o.Close()
|
||||||
_ = o.Close()
|
|
||||||
}(o)
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ""
|
return ""
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"embed"
|
||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
"github.com/maddalax/htmgo/framework/h"
|
"github.com/maddalax/htmgo/framework/h"
|
||||||
"github.com/maddalax/htmgo/framework/htmgo/service"
|
"github.com/maddalax/htmgo/framework/htmgo/service"
|
||||||
|
|
@ -8,21 +9,42 @@ import (
|
||||||
"htmgo-site/internal/markdown"
|
"htmgo-site/internal/markdown"
|
||||||
"htmgo-site/pages"
|
"htmgo-site/pages"
|
||||||
"htmgo-site/partials/load"
|
"htmgo-site/partials/load"
|
||||||
|
"io/fs"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
//go:embed assets/dist/*
|
||||||
|
var StaticAssets embed.FS
|
||||||
|
|
||||||
|
//go:embed md/*
|
||||||
|
var MarkdownAssets embed.FS
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
locator := service.NewLocator()
|
locator := service.NewLocator()
|
||||||
|
|
||||||
service.Set(locator, service.Singleton, markdown.NewRenderer)
|
service.Set(locator, service.Singleton, markdown.NewRenderer)
|
||||||
|
|
||||||
|
sub, err := fs.Sub(StaticAssets, "assets/dist")
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
h.Start(h.AppOpts{
|
h.Start(h.AppOpts{
|
||||||
ServiceLocator: locator,
|
ServiceLocator: locator,
|
||||||
LiveReload: true,
|
LiveReload: true,
|
||||||
Register: func(e *echo.Echo) {
|
Register: func(e *echo.Echo) {
|
||||||
e.Static("/public", "./assets/dist")
|
e.StaticFS("/public", sub)
|
||||||
|
|
||||||
|
e.Use(func(next echo.HandlerFunc) echo.HandlerFunc {
|
||||||
|
return func(c echo.Context) error {
|
||||||
|
c.Set("embeddedMarkdown", &MarkdownAssets)
|
||||||
|
return next(c)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
load.RegisterPartials(e)
|
load.RegisterPartials(e)
|
||||||
pages.RegisterPages(e)
|
pages.RegisterPages(e)
|
||||||
pages.RegisterMarkdown(e, "md", func(ctx echo.Context, path string) error {
|
pages.RegisterMarkdown(e, "md", MarkdownAssets, func(ctx echo.Context, path string) error {
|
||||||
return pages.MarkdownHandler(ctx.(*h.RequestContext), path)
|
return pages.MarkdownHandler(ctx.(*h.RequestContext), path)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
|
||||||
1
htmgo-site/md/examples.md
Normal file
1
htmgo-site/md/examples.md
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
Coming soon
|
||||||
|
|
@ -6,8 +6,6 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
**introduction:**
|
**introduction:**
|
||||||
|
|
||||||
htmgo is a lightweight pure go way to build interactive websites / web applications using go & htmx.
|
htmgo is a lightweight pure go way to build interactive websites / web applications using go & htmx.
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,15 @@
|
||||||
package pages
|
package pages
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"embed"
|
||||||
"github.com/maddalax/htmgo/framework/h"
|
"github.com/maddalax/htmgo/framework/h"
|
||||||
"htmgo-site/internal/dirwalk"
|
"htmgo-site/internal/dirwalk"
|
||||||
"htmgo-site/pages/base"
|
"htmgo-site/pages/base"
|
||||||
)
|
)
|
||||||
|
|
||||||
func DocsPage(ctx *h.RequestContext) *h.Page {
|
func DocsPage(ctx *h.RequestContext) *h.Page {
|
||||||
pages := dirwalk.WalkPages("md/docs")
|
assets := ctx.Get("embeddedMarkdown").(*embed.FS)
|
||||||
|
pages := dirwalk.WalkPages("md/docs", assets)
|
||||||
|
|
||||||
return h.NewPage(base.RootPage(
|
return h.NewPage(base.RootPage(
|
||||||
h.Div(
|
h.Div(
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package pages
|
package pages
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"embed"
|
||||||
"github.com/maddalax/htmgo/framework/h"
|
"github.com/maddalax/htmgo/framework/h"
|
||||||
"github.com/maddalax/htmgo/framework/htmgo/service"
|
"github.com/maddalax/htmgo/framework/htmgo/service"
|
||||||
"htmgo-site/internal/markdown"
|
"htmgo-site/internal/markdown"
|
||||||
|
|
@ -24,11 +25,12 @@ func MarkdownPage(ctx *h.RequestContext, path string) *h.Element {
|
||||||
}
|
}
|
||||||
|
|
||||||
func MarkdownContent(ctx *h.RequestContext, path string) *h.Element {
|
func MarkdownContent(ctx *h.RequestContext, path string) *h.Element {
|
||||||
|
embeddedMd := ctx.Get("embeddedMarkdown").(*embed.FS)
|
||||||
renderer := service.Get[markdown.Renderer](ctx.ServiceLocator())
|
renderer := service.Get[markdown.Renderer](ctx.ServiceLocator())
|
||||||
return h.Div(
|
return h.Div(
|
||||||
h.Article(
|
h.Article(
|
||||||
h.Class("prose max-w-sm pt-3 p-4 md:p-4 md:max-w-2xl prose-code:text-black"),
|
h.Class("prose max-w-sm pt-3 p-4 md:p-4 md:max-w-2xl prose-code:text-black"),
|
||||||
h.Raw(renderer.RenderFile(path)),
|
h.Raw(renderer.RenderFile(path, embeddedMd)),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,11 @@ package pages
|
||||||
import (
|
import (
|
||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
"htmgo-site/internal/dirwalk"
|
"htmgo-site/internal/dirwalk"
|
||||||
|
"io/fs"
|
||||||
)
|
)
|
||||||
|
|
||||||
func RegisterMarkdown(app *echo.Echo, dir string, handler func(ctx echo.Context, path string) error) {
|
func RegisterMarkdown(app *echo.Echo, dir string, system fs.FS, handler func(ctx echo.Context, path string) error) {
|
||||||
for _, page := range dirwalk.WalkPages(dir) {
|
for _, page := range dirwalk.WalkPages(dir, system) {
|
||||||
app.GET(page.RoutePath, func(ctx echo.Context) error {
|
app.GET(page.RoutePath, func(ctx echo.Context) error {
|
||||||
return handler(ctx, page.FilePath)
|
return handler(ctx, page.FilePath)
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -25,34 +25,39 @@ func NavBar() *h.Element {
|
||||||
{Name: "Examples", Url: "/examples"},
|
{Name: "Examples", Url: "/examples"},
|
||||||
}
|
}
|
||||||
|
|
||||||
return h.Nav(
|
prelease := h.Div(h.Class("bg-yellow-200 text-yellow-800 text-center p-2"),
|
||||||
h.Class("bg-neutral-100 border border-b-slate-300 p-4 md:p-3"),
|
h.Text("This is a prerelease version and generally should not be used at this time. Watch on github for the stable release!"),
|
||||||
h.Div(
|
)
|
||||||
h.Class("max-w-[95%] md:max-w-prose mx-auto"),
|
|
||||||
|
return h.Div(
|
||||||
|
prelease,
|
||||||
|
h.Nav(
|
||||||
|
h.Class("bg-neutral-100 border border-b-slate-300 p-4 md:p-3"),
|
||||||
h.Div(
|
h.Div(
|
||||||
h.Class("flex justify-between items-center"),
|
h.Class("max-w-[95%] md:max-w-prose mx-auto"),
|
||||||
h.Div(
|
h.Div(
|
||||||
h.Class("flex items-center"),
|
h.Class("flex justify-between items-center"),
|
||||||
h.A(
|
h.Div(
|
||||||
h.Boost(),
|
h.Class("flex items-center"),
|
||||||
h.Class("text-2xl"),
|
h.A(
|
||||||
h.Href("/"),
|
h.Class("text-2xl"),
|
||||||
h.Text("htmgo"),
|
h.Href("/"),
|
||||||
)),
|
h.Text("htmgo (prerelease)"),
|
||||||
h.Div(
|
)),
|
||||||
h.Class("flex gap-4 items-center"),
|
h.Div(
|
||||||
h.List(navItems, func(item NavItem, index int) *h.Element {
|
h.Class("flex gap-4 items-center"),
|
||||||
return h.Div(
|
h.List(navItems, func(item NavItem, index int) *h.Element {
|
||||||
h.Class("flex items-center"),
|
return h.Div(
|
||||||
h.A(
|
h.Class("flex items-center"),
|
||||||
h.Boost(),
|
h.A(
|
||||||
h.Class(""),
|
h.Class(""),
|
||||||
h.Href(item.Url),
|
h.Href(item.Url),
|
||||||
h.Text(item.Name),
|
h.Text(item.Name),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
h.Div(h.Class("ml-2"), star),
|
h.Div(h.Class("ml-2"), star),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue