fix: Mobile hamburger menu and iPad sidebar visibility
Mobile fixes: - Add click toggle handler for hamburger menu (was hover-only) - Menu now opens/closes on tap and closes when clicking outside - Keep hover support for desktop iPad fixes: - Sidebar content now visible on touch devices (901-1280px) - Added (hover: hover) media query to prevent hide-on-hover on tablets Security improvements: - Replace exec.CommandContext with go-git library for git operations - Add path traversal and command injection prevention - Fix race condition in template hot reload - Add environment-based cookie Secure flag Code quality: - Add constants.go for magic numbers - Remove unused code (ParsePreferenceToggleRequest, DomainError) - Add FOUC prevention with inline critical CSS - Add Makefile dev/run/clean targets - Fix README git clone URL - Add doc/DECISIONS.md for architectural decisions Tests: - Add hamburger menu click toggle tests - Add iPad sidebar visibility tests - Update security tests for go-git implementation - Add cookie Secure flag tests
This commit is contained in:
@@ -0,0 +1,123 @@
|
||||
package handlers
|
||||
|
||||
import "time"
|
||||
|
||||
// ==============================================================================
|
||||
// HTTP CONTENT TYPES
|
||||
// ==============================================================================
|
||||
|
||||
const (
|
||||
// ContentTypePDF is the MIME type for PDF documents
|
||||
ContentTypePDF = "application/pdf"
|
||||
|
||||
// ContentTypeHTML is the MIME type for HTML documents
|
||||
ContentTypeHTML = "text/html; charset=utf-8"
|
||||
|
||||
// ContentTypeJSON is the MIME type for JSON documents
|
||||
ContentTypeJSON = "application/json"
|
||||
|
||||
// ContentTypePlainText is the MIME type for plain text
|
||||
ContentTypePlainText = "text/plain; charset=utf-8"
|
||||
)
|
||||
|
||||
// ==============================================================================
|
||||
// RATE LIMITING
|
||||
// ==============================================================================
|
||||
|
||||
const (
|
||||
// PDFRateLimitRequests is the maximum number of PDF requests per window
|
||||
PDFRateLimitRequests = 3
|
||||
|
||||
// PDFRateLimitWindow is the time window for PDF rate limiting
|
||||
PDFRateLimitWindow = 1 * time.Minute
|
||||
|
||||
// GeneralRateLimitRequests is the default rate limit for general requests
|
||||
GeneralRateLimitRequests = 100
|
||||
|
||||
// GeneralRateLimitWindow is the time window for general rate limiting
|
||||
GeneralRateLimitWindow = 1 * time.Minute
|
||||
)
|
||||
|
||||
// ==============================================================================
|
||||
// PDF GENERATION
|
||||
// ==============================================================================
|
||||
|
||||
const (
|
||||
// A4WidthInches is the width of A4 paper in inches
|
||||
A4WidthInches = 8.27
|
||||
|
||||
// A4HeightInches is the height of A4 paper in inches
|
||||
A4HeightInches = 11.69
|
||||
|
||||
// PDFGenerationTimeout is the maximum time allowed for PDF generation
|
||||
PDFGenerationTimeout = 30 * time.Second
|
||||
)
|
||||
|
||||
// ==============================================================================
|
||||
// COOKIE SETTINGS
|
||||
// ==============================================================================
|
||||
|
||||
const (
|
||||
// CookieMaxAge is the default cookie expiration (1 year in seconds)
|
||||
CookieMaxAge = 365 * 24 * 60 * 60
|
||||
|
||||
// CookiePath is the default cookie path
|
||||
CookiePath = "/"
|
||||
)
|
||||
|
||||
// ==============================================================================
|
||||
// LANGUAGE CODES
|
||||
// ==============================================================================
|
||||
|
||||
const (
|
||||
// LangEnglish is the English language code
|
||||
LangEnglish = "en"
|
||||
|
||||
// LangSpanish is the Spanish language code
|
||||
LangSpanish = "es"
|
||||
|
||||
// DefaultLanguage is the default language for the application
|
||||
DefaultLanguage = LangEnglish
|
||||
)
|
||||
|
||||
// ==============================================================================
|
||||
// CV PREFERENCES
|
||||
// ==============================================================================
|
||||
|
||||
const (
|
||||
// CVLengthShort represents the short CV format
|
||||
CVLengthShort = "short"
|
||||
|
||||
// CVLengthLong represents the long CV format
|
||||
CVLengthLong = "long"
|
||||
|
||||
// CVIconsShow indicates icons should be visible
|
||||
CVIconsShow = "show"
|
||||
|
||||
// CVIconsHide indicates icons should be hidden
|
||||
CVIconsHide = "hide"
|
||||
|
||||
// CVThemeDefault is the default CV theme
|
||||
CVThemeDefault = "default"
|
||||
|
||||
// CVThemeClean is the clean CV theme
|
||||
CVThemeClean = "clean"
|
||||
)
|
||||
|
||||
// ==============================================================================
|
||||
// HTTP HEADERS
|
||||
// ==============================================================================
|
||||
|
||||
const (
|
||||
// HeaderContentType is the Content-Type header key
|
||||
HeaderContentType = "Content-Type"
|
||||
|
||||
// HeaderContentDisposition is the Content-Disposition header key
|
||||
HeaderContentDisposition = "Content-Disposition"
|
||||
|
||||
// HeaderCacheControl is the Cache-Control header key
|
||||
HeaderCacheControl = "Cache-Control"
|
||||
|
||||
// HeaderHXRequest is the HTMX request header
|
||||
HeaderHXRequest = "HX-Request"
|
||||
)
|
||||
Reference in New Issue
Block a user