mirror of
https://github.com/axzilla/templui.git
synced 2025-02-21 00:12:48 +00:00
chore: make some changes on current pr, remove unused middleware
This commit is contained in:
parent
2c0fefe972
commit
78a3cf066f
@ -1583,6 +1583,11 @@ body {
|
|||||||
background-color: rgb(234 179 8 / var(--tw-bg-opacity, 1));
|
background-color: rgb(234 179 8 / var(--tw-bg-opacity, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.bg-gray-100 {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: rgb(243 244 246 / var(--tw-bg-opacity, 1));
|
||||||
|
}
|
||||||
|
|
||||||
.bg-opacity-50 {
|
.bg-opacity-50 {
|
||||||
--tw-bg-opacity: 0.5;
|
--tw-bg-opacity: 0.5;
|
||||||
}
|
}
|
||||||
@ -2408,6 +2413,11 @@ body {
|
|||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dark\:bg-gray-700:is(.dark *) {
|
||||||
|
--tw-bg-opacity: 1;
|
||||||
|
background-color: rgb(55 65 81 / var(--tw-bg-opacity, 1));
|
||||||
|
}
|
||||||
|
|
||||||
.dark\:text-gray-200:is(.dark *) {
|
.dark\:text-gray-200:is(.dark *) {
|
||||||
--tw-text-opacity: 1;
|
--tw-text-opacity: 1;
|
||||||
color: rgb(229 231 235 / var(--tw-text-opacity, 1));
|
color: rgb(229 231 235 / var(--tw-text-opacity, 1));
|
||||||
|
@ -47,15 +47,13 @@ func main() {
|
|||||||
|
|
||||||
wrappedMux := middleware.WithURLPathValue(
|
wrappedMux := middleware.WithURLPathValue(
|
||||||
middleware.CacheControlMiddleware(
|
middleware.CacheControlMiddleware(
|
||||||
middleware.WithPreviewCheck(
|
|
||||||
mw.WithCSP(cspConfig)(mux),
|
mw.WithCSP(cspConfig)(mux),
|
||||||
),
|
),
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
mux.Handle("GET /", templ.Handler(pages.Landing()))
|
mux.Handle("GET /", templ.Handler(pages.Landing()))
|
||||||
mux.Handle("GET /docs/components", http.RedirectHandler("/docs/components/accordion", http.StatusSeeOther))
|
|
||||||
mux.Handle("GET /docs/getting-started", http.RedirectHandler("/docs/introduction", http.StatusSeeOther))
|
mux.Handle("GET /docs/getting-started", http.RedirectHandler("/docs/introduction", http.StatusSeeOther))
|
||||||
|
mux.Handle("GET /docs/components", http.RedirectHandler("/docs/components/accordion", http.StatusSeeOther))
|
||||||
mux.Handle("GET /docs/introduction", templ.Handler(pages.Introduction()))
|
mux.Handle("GET /docs/introduction", templ.Handler(pages.Introduction()))
|
||||||
mux.Handle("GET /docs/how-to-use", templ.Handler(pages.HowToUse()))
|
mux.Handle("GET /docs/how-to-use", templ.Handler(pages.HowToUse()))
|
||||||
mux.Handle("GET /docs/themes", templ.Handler(pages.Themes()))
|
mux.Handle("GET /docs/themes", templ.Handler(pages.Themes()))
|
||||||
@ -112,4 +110,3 @@ func SetupAssetsRoutes(mux *http.ServeMux) {
|
|||||||
|
|
||||||
mux.Handle("GET /assets/", http.StripPrefix("/assets/", assetHandler))
|
mux.Handle("GET /assets/", http.StripPrefix("/assets/", assetHandler))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package config
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
@ -27,14 +26,3 @@ func LoadConfig() {
|
|||||||
GoEnv: os.Getenv("GO_ENV"),
|
GoEnv: os.Getenv("GO_ENV"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type contextKey string
|
|
||||||
|
|
||||||
var PreviewContextKey = contextKey("preview")
|
|
||||||
|
|
||||||
func IsPreview(ctx context.Context) bool {
|
|
||||||
if preview, ok := ctx.Value(PreviewContextKey).(bool); ok {
|
|
||||||
return preview
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
7
internal/ctxkeys/ctxkeys.go
Normal file
7
internal/ctxkeys/ctxkeys.go
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
package ctxkeys
|
||||||
|
|
||||||
|
type contextKey string
|
||||||
|
|
||||||
|
const (
|
||||||
|
URLPathValue = contextKey("url_path_value")
|
||||||
|
)
|
@ -3,26 +3,15 @@ package middleware
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/axzilla/templui/internal/config"
|
"github.com/axzilla/templui/internal/ctxkeys"
|
||||||
"github.com/axzilla/templui/internal/utils"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func WithPreviewCheck(next http.Handler) http.Handler {
|
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
isPreview := strings.HasPrefix(r.Host, "preview.")
|
|
||||||
ctx := context.WithValue(r.Context(), config.PreviewContextKey, isPreview)
|
|
||||||
next.ServeHTTP(w, r.WithContext(ctx))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func CacheControlMiddleware(next http.Handler) http.Handler {
|
func CacheControlMiddleware(next http.Handler) http.Handler {
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Cache-Control", "max-age=0, must-revalidate, no-cache, no-store, private")
|
w.Header().Set("Cache-Control", "max-age=0, must-revalidate, no-cache, no-store, private")
|
||||||
w.Header().Set("Pragma", "no-cache")
|
w.Header().Set("Pragma", "no-cache")
|
||||||
w.Header().Set("Expires", "0")
|
w.Header().Set("Expires", "0")
|
||||||
|
|
||||||
next.ServeHTTP(w, r)
|
next.ServeHTTP(w, r)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -32,11 +21,9 @@ func WithURLPathValue(next http.Handler) http.Handler {
|
|||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
ctx := context.WithValue(
|
ctx := context.WithValue(
|
||||||
r.Context(),
|
r.Context(),
|
||||||
utils.CtxURLPathValueKey,
|
ctxkeys.URLPathValue,
|
||||||
r.URL.Path,
|
r.URL.Path,
|
||||||
)
|
)
|
||||||
|
|
||||||
next.ServeHTTP(w, r.WithContext(ctx))
|
next.ServeHTTP(w, r.WithContext(ctx))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,6 @@ package layouts
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/axzilla/templui/internal/config"
|
"github.com/axzilla/templui/internal/config"
|
||||||
"github.com/axzilla/templui/internal/ui/modules"
|
|
||||||
"github.com/axzilla/templui/pkg/helpers"
|
"github.com/axzilla/templui/pkg/helpers"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -74,9 +73,6 @@ templ BaseLayout() {
|
|||||||
>
|
>
|
||||||
<div class="flex flex-col min-h-screen">
|
<div class="flex flex-col min-h-screen">
|
||||||
{ children... }
|
{ children... }
|
||||||
if config.IsPreview(ctx) {
|
|
||||||
@modules.PreviewIndicator()
|
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -3,9 +3,9 @@ package modules
|
|||||||
import (
|
import (
|
||||||
"github.com/axzilla/templui/internal/shared"
|
"github.com/axzilla/templui/internal/shared"
|
||||||
wrappedicons "github.com/axzilla/templui/internal/ui/icons"
|
wrappedicons "github.com/axzilla/templui/internal/ui/icons"
|
||||||
"github.com/axzilla/templui/internal/utils"
|
|
||||||
"github.com/axzilla/templui/pkg/components"
|
"github.com/axzilla/templui/pkg/components"
|
||||||
"github.com/axzilla/templui/pkg/icons"
|
"github.com/axzilla/templui/pkg/icons"
|
||||||
|
"github.com/axzilla/templui/internal/ctxkeys"
|
||||||
)
|
)
|
||||||
|
|
||||||
templ Navbar() {
|
templ Navbar() {
|
||||||
@ -51,19 +51,17 @@ templ NavbarMobileMenu() {
|
|||||||
<ul class="mt-2 space-y-1">
|
<ul class="mt-2 space-y-1">
|
||||||
for _, link := range section.Links {
|
for _, link := range section.Links {
|
||||||
<li>
|
<li>
|
||||||
if link.Href == ctx.Value(utils.CtxURLPathValueKey) {
|
if link.Href == ctx.Value(ctxkeys.URLPathValue) {
|
||||||
<a
|
<a
|
||||||
href={ templ.SafeURL(link.Href) }
|
href={ templ.SafeURL(link.Href) }
|
||||||
class={ "text-sm flex items-center px-4 py-2 rounded-md text-gray-700 dark:text-gray-200",
|
class={ "text-sm flex items-center px-4 py-2 rounded-md text-gray-700 dark:text-gray-200 bg-gray-100 dark:bg-gray-700" }
|
||||||
"bg-gray-100 dark:bg-gray-700" }
|
|
||||||
>
|
>
|
||||||
<span>{ link.Text }</span>
|
<span>{ link.Text }</span>
|
||||||
</a>
|
</a>
|
||||||
} else {
|
} else {
|
||||||
<a
|
<a
|
||||||
href={ templ.SafeURL(link.Href) }
|
href={ templ.SafeURL(link.Href) }
|
||||||
class={ "text-sm flex items-center px-4 py-2 rounded-md text-gray-700 dark:text-gray-200",
|
class={ "text-sm flex items-center px-4 py-2 rounded-md text-gray-700 dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-gray-700" }
|
||||||
"hover:bg-gray-100 dark:hover:bg-gray-700" }
|
|
||||||
>
|
>
|
||||||
<span>{ link.Text }</span>
|
<span>{ link.Text }</span>
|
||||||
</a>
|
</a>
|
||||||
@ -79,9 +77,7 @@ templ NavbarMobileMenu() {
|
|||||||
class="mr-2 lg:hidden p-2 rounded-md text-gray-400 hover:text-gray-500 hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-indigo-500"
|
class="mr-2 lg:hidden p-2 rounded-md text-gray-400 hover:text-gray-500 hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-indigo-500"
|
||||||
>
|
>
|
||||||
@icons.SquareLibrary(icons.IconProps{})
|
@icons.SquareLibrary(icons.IconProps{})
|
||||||
// @Icon(IconProps{Name: "square-library"})
|
|
||||||
</button>
|
</button>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,36 +0,0 @@
|
|||||||
package modules
|
|
||||||
|
|
||||||
import "github.com/axzilla/templui/pkg/icons"
|
|
||||||
|
|
||||||
templ PreviewIndicator() {
|
|
||||||
<div
|
|
||||||
class="fixed bottom-4 left-4 z-50"
|
|
||||||
x-data="{ expanded: false }"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="relative bg-purple-500 text-white rounded-lg shadow-lg overflow-hidden"
|
|
||||||
@mouseenter="expanded = true"
|
|
||||||
@mouseleave="expanded = false"
|
|
||||||
>
|
|
||||||
// Base layout - always visible
|
|
||||||
<div class="flex items-center h-9 px-3">
|
|
||||||
<div class="flex items-center gap-2">
|
|
||||||
@icons.Sparkles(icons.IconProps{Size: "16", Class: "animate-pulse"})
|
|
||||||
<span class="text-sm font-medium">Preview Mode</span>
|
|
||||||
</div>
|
|
||||||
// Extra content - slides in/out
|
|
||||||
<div
|
|
||||||
class="flex items-center gap-3 overflow-hidden transition-all duration-300 ease-in-out"
|
|
||||||
:class="expanded ? 'ml-3 max-w-[200px] opacity-100' : 'max-w-0 opacity-0'"
|
|
||||||
>
|
|
||||||
<div class="border-l pl-3 whitespace-nowrap">
|
|
||||||
<a href="https://templui.io" class="text-sm hover:underline flex items-center gap-1">
|
|
||||||
Production Site
|
|
||||||
@icons.ArrowRight(icons.IconProps{Size: "14"})
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
@ -1,7 +1,7 @@
|
|||||||
package modules
|
package modules
|
||||||
|
|
||||||
import "github.com/axzilla/templui/internal/shared"
|
import "github.com/axzilla/templui/internal/shared"
|
||||||
import "github.com/axzilla/templui/internal/utils"
|
import "github.com/axzilla/templui/internal/ctxkeys"
|
||||||
|
|
||||||
templ Sidebar() {
|
templ Sidebar() {
|
||||||
<aside class="h-full">
|
<aside class="h-full">
|
||||||
@ -14,7 +14,7 @@ templ Sidebar() {
|
|||||||
<ul class="mt-2 space-y-1">
|
<ul class="mt-2 space-y-1">
|
||||||
for _, link := range section.Links {
|
for _, link := range section.Links {
|
||||||
<li>
|
<li>
|
||||||
if link.Href == ctx.Value(utils.CtxURLPathValueKey) {
|
if link.Href == ctx.Value(ctxkeys.URLPathValue) {
|
||||||
<a href={ templ.SafeURL(link.Href) } class="text-sm flex items-center px-4 py-2 rounded-md text-gray-700 dark:text-gray-200 bg-gray-100 dark:bg-gray-700">
|
<a href={ templ.SafeURL(link.Href) } class="text-sm flex items-center px-4 py-2 rounded-md text-gray-700 dark:text-gray-200 bg-gray-100 dark:bg-gray-700">
|
||||||
<span>{ link.Text }</span>
|
<span>{ link.Text }</span>
|
||||||
</a>
|
</a>
|
||||||
@ -33,4 +33,3 @@ templ Sidebar() {
|
|||||||
</div>
|
</div>
|
||||||
</aside>
|
</aside>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,26 +3,14 @@ package utils
|
|||||||
import (
|
import (
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
|
"fmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
type CtxKey string
|
func GenerateNonce() (string, error) {
|
||||||
|
|
||||||
const CtxURLPathValueKey = CtxKey("url_value")
|
|
||||||
|
|
||||||
func GenerateNonce() string {
|
|
||||||
try := 0
|
|
||||||
Retry:
|
|
||||||
try++
|
|
||||||
|
|
||||||
nonceBytes := make([]byte, 16)
|
nonceBytes := make([]byte, 16)
|
||||||
_, err := rand.Read(nonceBytes)
|
_, err := rand.Read(nonceBytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if try < 2 {
|
return "", fmt.Errorf("failed to generate nonce: %w", err)
|
||||||
goto Retry
|
|
||||||
}
|
}
|
||||||
|
return base64.StdEncoding.EncodeToString(nonceBytes), nil
|
||||||
return ""
|
|
||||||
}
|
|
||||||
return base64.StdEncoding.EncodeToString(nonceBytes)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ package middleware
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@ -16,7 +17,13 @@ type CSPConfig struct {
|
|||||||
func WithCSP(config CSPConfig) func(http.Handler) http.Handler {
|
func WithCSP(config CSPConfig) func(http.Handler) http.Handler {
|
||||||
return func(next http.Handler) http.Handler {
|
return func(next http.Handler) http.Handler {
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
nonce := utils.GenerateNonce()
|
nonce, err := utils.GenerateNonce()
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("failed to generate nonce: %v", err)
|
||||||
|
w.Header().Set("Content-Security-Policy", "script-src 'self'")
|
||||||
|
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Combine all script sources
|
// Combine all script sources
|
||||||
scriptSources := append(
|
scriptSources := append(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user