diff --git a/frontend/.air.toml b/frontend/.air.toml new file mode 100644 index 0000000000..32a47c140c --- /dev/null +++ b/frontend/.air.toml @@ -0,0 +1,44 @@ +root = "." +testdata_dir = "testdata" +tmp_dir = "tmp" + +[build] + args_bin = [] + bin = "./tmp/main" + cmd = "go build -o ./tmp/main ./cmd/server" + delay = 2000 + exclude_dir = ["assets", "tmp", "vendor", "testdata", "node_modules", ".git", "bin", "public", "db", "scripts", "astro_freedevtools", "frontend", "search-index", "man-pages-stuff", "docs", "md", "nginx", "fdtdb-cli"] + exclude_file = [] + exclude_regex = ["_test.go"] + exclude_unchanged = false + follow_symlink = false + full_bin = "" + include_dir = [] + include_ext = ["go"] + include_file = [] + kill_delay = "0s" + log = "build-errors.log" + poll = false + poll_interval = 0 + rerun = false + rerun_delay = 500 + send_interrupt = false + stop_on_error = false + +[color] + app = "" + build = "yellow" + main = "magenta" + runner = "green" + watcher = "cyan" + +[log] + main_only = false + time = false + +[misc] + clean_on_exit = false + +[screen] + clear_on_rebuild = false + keep_scroll = true diff --git a/frontend/.cursor/rules/border-hover-stylings-for-ui.mdc b/frontend/.cursor/rules/border-hover-stylings-for-ui.mdc new file mode 100644 index 0000000000..25254ce8fd --- /dev/null +++ b/frontend/.cursor/rules/border-hover-stylings-for-ui.mdc @@ -0,0 +1,10 @@ +--- +alwaysApply: true +--- +Always use `border-fdt-yellow-dark` for light mode and `border-yellow-700` for dark mode when applying hover or focus border colors. + +**Colors:** +- Light mode: `border-fdt-yellow-dark` (#b6b000) +- Dark mode: `dark:border-yellow-700` () + +Apply this consistently across all search inputs, buttons, and interactive elements. diff --git a/frontend/cmd/server/routes.go b/frontend/cmd/server/routes.go index 4af72159a2..69c87c66a0 100644 --- a/frontend/cmd/server/routes.go +++ b/frontend/cmd/server/routes.go @@ -1,6 +1,8 @@ package main import ( + "bytes" + "encoding/json" "log" "net/http" "net/http/pprof" @@ -9,6 +11,7 @@ import ( "path/filepath" "strconv" "strings" + "time" "fdt-templ/components/pages" cheatsheets_pages "fdt-templ/components/pages/cheatsheets" @@ -105,6 +108,66 @@ func matchCategoryPagination(path string) (category string, page int, ok bool) { return "", 0, false } +// fetchVSXExtensionInstallCount fetches the install count from Open VSX API +func fetchVSXExtensionInstallCount() int { + client := &http.Client{ + Timeout: 5 * time.Second, + } + + requestBody := map[string]interface{}{ + "filters": []map[string]interface{}{ + { + "criteria": []map[string]interface{}{ + { + "filterType": 7, + "value": "hexmos.freedevtools", + }, + }, + }, + }, + "flags": 914, + } + + jsonData, err := json.Marshal(requestBody) + if err != nil { + log.Printf("Error marshaling VSX API request: %v", err) + return 0 + } + + resp, err := client.Post("https://open-vsx.org/vscode/gallery/extensionquery", "application/json", bytes.NewBuffer(jsonData)) + if err != nil { + log.Printf("Error fetching VSX extension data: %v", err) + return 0 + } + defer resp.Body.Close() + + var result struct { + Results []struct { + Extensions []struct { + Statistics []struct { + StatisticName string `json:"statisticName"` + Value float64 `json:"value"` + } `json:"statistics"` + } `json:"extensions"` + } `json:"results"` + } + + if err := json.NewDecoder(resp.Body).Decode(&result); err != nil { + log.Printf("Error decoding VSX API response: %v", err) + return 0 + } + + if len(result.Results) > 0 && len(result.Results[0].Extensions) > 0 { + for _, stat := range result.Results[0].Extensions[0].Statistics { + if stat.StatisticName == "install" { + return int(stat.Value) + } + } + } + + return 0 +} + // Cheatsheets route matching functions are now in cheatsheets_routes.go func setupRoutes(mux *http.ServeMux, svgIconsDB *svg_icons.DB, manPagesDB *man_pages.DB, emojisDB *emojis.DB, mcpDB *mcp.DB, pngIconsDB *png_icons.DB, cheatsheetsDB *cheatsheets.DB, tldrDB *tldr.DB, installerpediaDB *installerpedia.DB, toolsConfig *tools.Config, fdtPgDB *bookmarks.DB) { @@ -192,6 +255,13 @@ func setupRoutes(mux *http.ServeMux, svgIconsDB *svg_icons.DB, manPagesDB *man_p handler.ServeHTTP(w, r) }) + // VS Code Extension page + mux.HandleFunc(basePath+"/vs-code-extension/", func(w http.ResponseWriter, r *http.Request) { + installCount := fetchVSXExtensionInstallCount() + handler := templ.Handler(static_pages.VSCodeExtension(installCount)) + handler.ServeHTTP(w, r) + }) + // Pro page mux.HandleFunc(basePath+"/pro/", func(w http.ResponseWriter, r *http.Request) { handler := templ.Handler(pro_pages.Pro()) diff --git a/frontend/components/breadcrumb.templ b/frontend/components/breadcrumb.templ index a300a3ee9e..31265732a3 100644 --- a/frontend/components/breadcrumb.templ +++ b/frontend/components/breadcrumb.templ @@ -6,7 +6,7 @@ type BreadcrumbItem struct { } templ Breadcrumb(items []BreadcrumbItem) { -