Compare commits
3 commits
master
...
gen-code-f
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
274df0534b | ||
|
|
d544be6f04 | ||
|
|
50bc55e9ca |
8 changed files with 136 additions and 26 deletions
|
|
@ -9,10 +9,12 @@ import (
|
|||
"go/parser"
|
||||
"go/token"
|
||||
"golang.org/x/mod/modfile"
|
||||
"io/fs"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"slices"
|
||||
"strings"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
type Page struct {
|
||||
|
|
@ -37,6 +39,32 @@ const ModuleName = "github.com/maddalax/htmgo/framework/h"
|
|||
var PackageName = fmt.Sprintf("package %s", GeneratedDirName)
|
||||
var GeneratedFileLine = fmt.Sprintf("// Package %s THIS FILE IS GENERATED. DO NOT EDIT.", GeneratedDirName)
|
||||
|
||||
func toPascaleCase(input string) string {
|
||||
words := strings.Split(input, "_")
|
||||
for i := range words {
|
||||
words[i] = strings.Title(strings.ToLower(words[i]))
|
||||
}
|
||||
return strings.Join(words, "")
|
||||
}
|
||||
|
||||
func isValidGoVariableName(name string) bool {
|
||||
// Variable name must not be empty
|
||||
if name == "" {
|
||||
return false
|
||||
}
|
||||
// First character must be a letter or underscore
|
||||
if !unicode.IsLetter(rune(name[0])) && name[0] != '_' {
|
||||
return false
|
||||
}
|
||||
// Remaining characters must be letters, digits, or underscores
|
||||
for _, char := range name[1:] {
|
||||
if !unicode.IsLetter(char) && !unicode.IsDigit(char) && char != '_' {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func normalizePath(path string) string {
|
||||
return strings.ReplaceAll(path, `\`, "/")
|
||||
}
|
||||
|
|
@ -390,6 +418,63 @@ func writePagesFile() {
|
|||
})
|
||||
}
|
||||
|
||||
func writeAssetsFile() {
|
||||
cwd := process.GetWorkingDir()
|
||||
config := dirutil.GetConfig()
|
||||
distAssets := filepath.Join(cwd, "assets", "dist")
|
||||
hasAssets := false
|
||||
|
||||
builder := strings.Builder{}
|
||||
|
||||
builder.WriteString(`package assets`)
|
||||
builder.WriteString("\n")
|
||||
|
||||
filepath.WalkDir(distAssets, func(path string, d fs.DirEntry, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if d.IsDir() {
|
||||
return nil
|
||||
}
|
||||
|
||||
if strings.HasPrefix(d.Name(), ".") {
|
||||
return nil
|
||||
}
|
||||
|
||||
path = strings.ReplaceAll(path, distAssets, "")
|
||||
httpUrl := fmt.Sprintf("%s%s", config.PublicAssetPath, path)
|
||||
|
||||
path = normalizePath(path)
|
||||
path = strings.ReplaceAll(path, "/", "_")
|
||||
path = strings.ReplaceAll(path, "//", "_")
|
||||
|
||||
name := strings.ReplaceAll(path, ".", "_")
|
||||
name = strings.ReplaceAll(name, "-", "_")
|
||||
|
||||
name = toPascaleCase(name)
|
||||
|
||||
if isValidGoVariableName(name) {
|
||||
builder.WriteString(fmt.Sprintf(`const %s = "%s"`, name, httpUrl))
|
||||
builder.WriteString("\n")
|
||||
hasAssets = true
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
builder.WriteString("\n")
|
||||
|
||||
str := builder.String()
|
||||
|
||||
if hasAssets {
|
||||
WriteFile(filepath.Join(GeneratedDirName, "assets", "assets-generated.go"), func(content *ast.File) string {
|
||||
return str
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func GetModuleName() string {
|
||||
wd := process.GetWorkingDir()
|
||||
modPath := filepath.Join(wd, "go.mod")
|
||||
|
|
@ -411,6 +496,7 @@ func GenAst(flags ...process.RunFlag) error {
|
|||
}
|
||||
writePartialsFile()
|
||||
writePagesFile()
|
||||
writeAssetsFile()
|
||||
|
||||
WriteFile("__htmgo/setup-generated.go", func(content *ast.File) string {
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ type ProjectConfig struct {
|
|||
WatchFiles []string `yaml:"watch_files"`
|
||||
AutomaticPageRoutingIgnore []string `yaml:"automatic_page_routing_ignore"`
|
||||
AutomaticPartialRoutingIgnore []string `yaml:"automatic_partial_routing_ignore"`
|
||||
PublicAssetPath string `yaml:"public_asset_path"`
|
||||
}
|
||||
|
||||
func DefaultProjectConfig() *ProjectConfig {
|
||||
|
|
@ -25,6 +26,7 @@ func DefaultProjectConfig() *ProjectConfig {
|
|||
WatchFiles: []string{
|
||||
"**/*.go", "**/*.html", "**/*.css", "**/*.js", "**/*.json", "**/*.yaml", "**/*.yml", "**/*.md",
|
||||
},
|
||||
PublicAssetPath: "/public",
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -57,9 +59,22 @@ func (cfg *ProjectConfig) Enhance() *ProjectConfig {
|
|||
}
|
||||
}
|
||||
|
||||
if cfg.PublicAssetPath == "" {
|
||||
cfg.PublicAssetPath = "/public"
|
||||
}
|
||||
|
||||
return cfg
|
||||
}
|
||||
|
||||
func Get() *ProjectConfig {
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return DefaultProjectConfig()
|
||||
}
|
||||
config := FromConfigFile(cwd)
|
||||
return config
|
||||
}
|
||||
|
||||
func FromConfigFile(workingDir string) *ProjectConfig {
|
||||
defaultCfg := DefaultProjectConfig()
|
||||
names := []string{"htmgo.yaml", "htmgo.yml", "_htmgo.yaml", "_htmgo.yml"}
|
||||
|
|
|
|||
|
|
@ -73,6 +73,21 @@ func TestShouldPrefixAutomaticPartialRoutingIgnore_1(t *testing.T) {
|
|||
assert.Equal(t, []string{"partials/somefile/*"}, cfg.AutomaticPartialRoutingIgnore)
|
||||
}
|
||||
|
||||
func TestPublicAssetPath(t *testing.T) {
|
||||
t.Parallel()
|
||||
cfg := DefaultProjectConfig()
|
||||
assert.Equal(t, "/public", cfg.PublicAssetPath)
|
||||
|
||||
cfg.PublicAssetPath = "/assets"
|
||||
assert.Equal(t, "/assets", cfg.PublicAssetPath)
|
||||
}
|
||||
|
||||
func TestConfigGet(t *testing.T) {
|
||||
t.Parallel()
|
||||
cfg := Get()
|
||||
assert.Equal(t, "/public", cfg.PublicAssetPath)
|
||||
}
|
||||
|
||||
func writeConfigFile(t *testing.T, content string) string {
|
||||
temp := os.TempDir()
|
||||
os.Mkdir(temp, 0755)
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package base
|
|||
import (
|
||||
"github.com/google/uuid"
|
||||
"github.com/maddalax/htmgo/framework/h"
|
||||
"htmgo-site/__htmgo/assets"
|
||||
"htmgo-site/partials"
|
||||
)
|
||||
|
||||
|
|
@ -43,8 +44,8 @@ func ConfigurableRootPage(ctx *h.RequestContext, props RootPageProps) *h.Page {
|
|||
h.Title(
|
||||
h.Text(title),
|
||||
),
|
||||
h.Link("/public/favicon.ico", "icon"),
|
||||
h.Link("/public/apple-touch-icon.png", "apple-touch-icon"),
|
||||
h.Link(assets.FaviconIco, "icon"),
|
||||
h.Link(assets.AppleTouchIconPng, "apple-touch-icon"),
|
||||
h.Meta("charset", "utf-8"),
|
||||
h.Meta("author", "htmgo"),
|
||||
h.Meta("description", description),
|
||||
|
|
@ -53,8 +54,8 @@ func ConfigurableRootPage(ctx *h.RequestContext, props RootPageProps) *h.Page {
|
|||
h.Link("canonical", canonical),
|
||||
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.LinkWithVersion(assets.MainCss, "stylesheet", Version),
|
||||
h.ScriptWithVersion(assets.HtmgoJs, Version),
|
||||
h.Style(`
|
||||
html {
|
||||
scroll-behavior: smooth;
|
||||
|
|
|
|||
|
|
@ -61,20 +61,3 @@ h.JoinExtensions(
|
|||
h.HxExtension("my-extension"),
|
||||
)
|
||||
`
|
||||
|
||||
const htmxExtensions = `
|
||||
h.HxOnLoad
|
||||
h.HxOnAfterSwap
|
||||
h.OnClick
|
||||
h.OnSubmit
|
||||
h.HxBeforeSseMessage
|
||||
h.HxAfterSseMessage
|
||||
h.OnClick
|
||||
h.OnSubmit
|
||||
h.HxOnSseError
|
||||
h.HxOnSseClose
|
||||
h.HxOnSseConnecting
|
||||
h.HxOnSseOpen
|
||||
h.HxAfterRequest
|
||||
h.HxOnMutationError
|
||||
`
|
||||
|
|
|
|||
|
|
@ -16,3 +16,6 @@ automatic_page_routing_ignore: ["root.go"]
|
|||
# files or directories to ignore when automatically registering routes for partials
|
||||
# supports glob patterns through https://github.com/bmatcuk/doublestar
|
||||
automatic_partial_routing_ignore: []
|
||||
|
||||
# url path of where the public assets are located
|
||||
public_asset_path: "/public"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/maddalax/htmgo/framework/config"
|
||||
"github.com/maddalax/htmgo/framework/h"
|
||||
"github.com/maddalax/htmgo/framework/service"
|
||||
"io/fs"
|
||||
|
|
@ -10,6 +12,7 @@ import (
|
|||
|
||||
func main() {
|
||||
locator := service.NewLocator()
|
||||
cfg := config.Get()
|
||||
|
||||
h.Start(h.AppOpts{
|
||||
ServiceLocator: locator,
|
||||
|
|
@ -23,7 +26,10 @@ func main() {
|
|||
|
||||
http.FileServerFS(sub)
|
||||
|
||||
app.Router.Handle("/public/*", http.StripPrefix("/public", http.FileServerFS(sub)))
|
||||
// change this in htmgo.yml (public_asset_path)
|
||||
app.Router.Handle(fmt.Sprintf("%s/*", cfg.PublicAssetPath),
|
||||
http.StripPrefix(cfg.PublicAssetPath, http.FileServerFS(sub)))
|
||||
|
||||
__htmgo.Register(app.Router)
|
||||
},
|
||||
})
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package pages
|
|||
|
||||
import (
|
||||
"github.com/maddalax/htmgo/framework/h"
|
||||
"starter-template/__htmgo/assets"
|
||||
)
|
||||
|
||||
func RootPage(children ...h.Ren) *h.Page {
|
||||
|
|
@ -20,8 +21,8 @@ func RootPage(children ...h.Ren) *h.Page {
|
|||
h.Text(title),
|
||||
),
|
||||
h.Meta("viewport", "width=device-width, initial-scale=1"),
|
||||
h.Link("/public/favicon.ico", "icon"),
|
||||
h.Link("/public/apple-touch-icon.png", "apple-touch-icon"),
|
||||
h.Link(assets.FaviconIco, "icon"),
|
||||
h.Link(assets.AppleTouchIconPng, "apple-touch-icon"),
|
||||
h.Meta("title", title),
|
||||
h.Meta("charset", "utf-8"),
|
||||
h.Meta("author", author),
|
||||
|
|
@ -30,8 +31,8 @@ func RootPage(children ...h.Ren) *h.Page {
|
|||
h.Meta("og:url", url),
|
||||
h.Link("canonical", url),
|
||||
h.Meta("og:description", description),
|
||||
h.Link("/public/main.css", "stylesheet"),
|
||||
h.Script("/public/htmgo.js"),
|
||||
h.Link(assets.MainCss, "stylesheet"),
|
||||
h.Script(assets.HtmgoJs),
|
||||
),
|
||||
h.Body(
|
||||
h.Div(
|
||||
|
|
|
|||
Loading…
Reference in a new issue