add support for ignoring specific files for automatic page/partial routing

This commit is contained in:
maddalax 2024-10-21 10:06:18 -05:00
parent 245d63c7b2
commit 635b17dd7f
7 changed files with 114 additions and 36 deletions

View file

@ -2,7 +2,9 @@ package astgen
import ( import (
"fmt" "fmt"
"github.com/maddalax/htmgo/cli/htmgo/internal/dirutil"
"github.com/maddalax/htmgo/cli/htmgo/tasks/process" "github.com/maddalax/htmgo/cli/htmgo/tasks/process"
"github.com/maddalax/htmgo/framework/h"
"go/ast" "go/ast"
"go/parser" "go/parser"
"go/token" "go/token"
@ -24,6 +26,7 @@ type Partial struct {
FuncName string FuncName string
Package string Package string
Import string Import string
Path string
} }
const GeneratedDirName = "__htmgo" const GeneratedDirName = "__htmgo"
@ -103,6 +106,7 @@ func findPublicFuncsReturningHPartial(dir string, predicate func(partial Partial
if selectorExpr.Sel.Name == "Partial" { if selectorExpr.Sel.Name == "Partial" {
p := Partial{ p := Partial{
Package: node.Name.Name, Package: node.Name.Name,
Path: sliceCommonPrefix(cwd, path),
Import: sliceCommonPrefix(cwd, strings.ReplaceAll(filepath.Dir(path), `\`, `/`)), Import: sliceCommonPrefix(cwd, strings.ReplaceAll(filepath.Dir(path), `\`, `/`)),
FuncName: funcDecl.Name.Name, FuncName: funcDecl.Name.Name,
} }
@ -254,12 +258,18 @@ func buildGetPartialFromContext(builder *CodeBuilder, partials []Partial) {
} }
func writePartialsFile() { func writePartialsFile() {
config := dirutil.GetConfig()
cwd := process.GetWorkingDir() cwd := process.GetWorkingDir()
partialPath := filepath.Join(cwd, "partials") partialPath := filepath.Join(cwd, "partials")
partials, err := findPublicFuncsReturningHPartial(partialPath, func(partial Partial) bool { partials, err := findPublicFuncsReturningHPartial(partialPath, func(partial Partial) bool {
return partial.FuncName != "GetPartialFromContext" return partial.FuncName != "GetPartialFromContext"
}) })
partials = h.Filter(partials, func(partial Partial) bool {
return !dirutil.IsGlobExclude(partial.Path, config.AutomaticPartialRoutingIgnore)
})
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
return return
@ -317,6 +327,7 @@ func formatRoute(path string) string {
} }
func writePagesFile() { func writePagesFile() {
config := dirutil.GetConfig()
builder := NewCodeBuilder(nil) builder := NewCodeBuilder(nil)
builder.AppendLine(GeneratedFileLine) builder.AppendLine(GeneratedFileLine)
@ -326,6 +337,10 @@ func writePagesFile() {
pages, _ := findPublicFuncsReturningHPage("pages") pages, _ := findPublicFuncsReturningHPage("pages")
pages = h.Filter(pages, func(page Page) bool {
return !dirutil.IsGlobExclude(page.Path, config.AutomaticPageRoutingIgnore)
})
if len(pages) > 0 { if len(pages) > 0 {
builder.AddImport(ModuleName) builder.AddImport(ModuleName)
} }

View file

@ -5,12 +5,15 @@ import (
"log/slog" "log/slog"
"os" "os"
"path" "path"
"strings"
) )
type ProjectConfig struct { type ProjectConfig struct {
Tailwind bool `yaml:"tailwind"` Tailwind bool `yaml:"tailwind"`
WatchIgnore []string `yaml:"watch_ignore"` WatchIgnore []string `yaml:"watch_ignore"`
WatchFiles []string `yaml:"watch_files"` WatchFiles []string `yaml:"watch_files"`
AutomaticPageRoutingIgnore []string `yaml:"automatic_page_routing_ignore"`
AutomaticPartialRoutingIgnore []string `yaml:"automatic_partial_routing_ignore"`
} }
func DefaultProjectConfig() *ProjectConfig { func DefaultProjectConfig() *ProjectConfig {
@ -25,7 +28,7 @@ func DefaultProjectConfig() *ProjectConfig {
} }
} }
func (cfg *ProjectConfig) EnhanceWithDefaults() *ProjectConfig { func (cfg *ProjectConfig) Enhance() *ProjectConfig {
defaultCfg := DefaultProjectConfig() defaultCfg := DefaultProjectConfig()
if len(cfg.WatchFiles) == 0 { if len(cfg.WatchFiles) == 0 {
cfg.WatchFiles = defaultCfg.WatchFiles cfg.WatchFiles = defaultCfg.WatchFiles
@ -33,6 +36,27 @@ func (cfg *ProjectConfig) EnhanceWithDefaults() *ProjectConfig {
if len(cfg.WatchIgnore) == 0 { if len(cfg.WatchIgnore) == 0 {
cfg.WatchIgnore = defaultCfg.WatchIgnore cfg.WatchIgnore = defaultCfg.WatchIgnore
} }
for i, s := range cfg.AutomaticPartialRoutingIgnore {
parts := strings.Split(s, string(os.PathSeparator))
if len(parts) == 0 {
continue
}
if parts[0] != "partials" {
cfg.AutomaticPartialRoutingIgnore[i] = path.Join("partials", s)
}
}
for i, s := range cfg.AutomaticPageRoutingIgnore {
parts := strings.Split(s, string(os.PathSeparator))
if len(parts) == 0 {
continue
}
if parts[0] != "pages" {
cfg.AutomaticPageRoutingIgnore[i] = path.Join("pages", s)
}
}
return cfg return cfg
} }
@ -50,7 +74,7 @@ func FromConfigFile(workingDir string) *ProjectConfig {
slog.Error("Error parsing config file", slog.String("file", filePath), slog.String("error", err.Error())) slog.Error("Error parsing config file", slog.String("file", filePath), slog.String("error", err.Error()))
os.Exit(1) os.Exit(1)
} }
return cfg.EnhanceWithDefaults() return cfg.Enhance()
} }
} }
} }

View file

@ -41,6 +41,38 @@ func TestShouldNotSetTailwindTrue(t *testing.T) {
assert.Equal(t, 8, len(cfg.WatchFiles)) assert.Equal(t, 8, len(cfg.WatchFiles))
} }
func TestShouldPrefixAutomaticPageRoutingIgnore(t *testing.T) {
t.Parallel()
cfg := DefaultProjectConfig()
cfg.AutomaticPageRoutingIgnore = []string{"somefile"}
cfg.Enhance()
assert.Equal(t, []string{"pages/somefile"}, cfg.AutomaticPageRoutingIgnore)
}
func TestShouldPrefixAutomaticPageRoutingIgnore_1(t *testing.T) {
t.Parallel()
cfg := DefaultProjectConfig()
cfg.AutomaticPageRoutingIgnore = []string{"pages/somefile/*"}
cfg.Enhance()
assert.Equal(t, []string{"pages/somefile/*"}, cfg.AutomaticPageRoutingIgnore)
}
func TestShouldPrefixAutomaticPartialRoutingIgnore(t *testing.T) {
t.Parallel()
cfg := DefaultProjectConfig()
cfg.AutomaticPartialRoutingIgnore = []string{"somefile/*"}
cfg.Enhance()
assert.Equal(t, []string{"partials/somefile/*"}, cfg.AutomaticPartialRoutingIgnore)
}
func TestShouldPrefixAutomaticPartialRoutingIgnore_1(t *testing.T) {
t.Parallel()
cfg := DefaultProjectConfig()
cfg.AutomaticPartialRoutingIgnore = []string{"partials/somefile/*"}
cfg.Enhance()
assert.Equal(t, []string{"partials/somefile/*"}, cfg.AutomaticPartialRoutingIgnore)
}
func writeConfigFile(t *testing.T, content string) string { func writeConfigFile(t *testing.T, content string) string {
temp := os.TempDir() temp := os.TempDir()
os.Mkdir(temp, 0755) os.Mkdir(temp, 0755)

View file

@ -30,7 +30,6 @@ func validateCommands(cmds []Command) {
panic(fmt.Sprintf("element is not allowed in lifecycle events. Got: %v", t)) panic(fmt.Sprintf("element is not allowed in lifecycle events. Got: %v", t))
default: default:
panic(fmt.Sprintf("type is not allowed in lifecycle events. Got: %v", t)) panic(fmt.Sprintf("type is not allowed in lifecycle events. Got: %v", t))
} }
} }
} }

View file

@ -8,3 +8,11 @@ watch_ignore: [".git", "node_modules", "dist/*"]
# files to watch for changes, supports glob patterns through https://github.com/bmatcuk/doublestar # files to watch for changes, supports glob patterns through https://github.com/bmatcuk/doublestar
watch_files: ["**/*.go", "**/*.css", "**/*.md"] 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"]
# files or directories to ignore when automatically registering routes for partials
# supports glob patterns through https://github.com/bmatcuk/doublestar
automatic_partial_routing_ignore: []

View file

@ -6,8 +6,7 @@ import (
) )
func IndexPage(ctx *h.RequestContext) *h.Page { func IndexPage(ctx *h.RequestContext) *h.Page {
return h.NewPage( return RootPage(
RootPage(
h.Div( h.Div(
h.Class("flex flex-col gap-4 items-center pt-24 min-h-screen bg-neutral-100"), h.Class("flex flex-col gap-4 items-center pt-24 min-h-screen bg-neutral-100"),
h.H3(h.Id("intro-text"), h.Text("hello htmgo"), h.Class("text-5xl")), h.H3(h.Id("intro-text"), h.Text("hello htmgo"), h.Class("text-5xl")),
@ -16,6 +15,5 @@ func IndexPage(ctx *h.RequestContext) *h.Page {
partials.CounterForm(0), partials.CounterForm(0),
), ),
), ),
),
) )
} }

View file

@ -4,8 +4,9 @@ import (
"github.com/maddalax/htmgo/framework/h" "github.com/maddalax/htmgo/framework/h"
) )
func RootPage(children ...h.Ren) h.Ren { func RootPage(children ...h.Ren) *h.Page {
return h.Html( return h.NewPage(
h.Html(
h.HxExtensions(h.BaseExtensions()), h.HxExtensions(h.BaseExtensions()),
h.Head( h.Head(
h.Meta("viewport", "width=device-width, initial-scale=1"), h.Meta("viewport", "width=device-width, initial-scale=1"),
@ -28,5 +29,6 @@ func RootPage(children ...h.Ren) h.Ren {
h.Fragment(children...), h.Fragment(children...),
), ),
), ),
),
) )
} }