detached b1ebd30

New structure and embedding ok

commit
b1ebd301f7ef87cd55f96ca7add691d1a074d3f7
author
bnema · · 2023-09-12 17:30 UTC
parent
69d1ee6
signature
unsigned
54 files · +2128 -991

this diff is incomplete: 2 files are too large to show. the totals above count everything; clone the repository to read the rest.

M .gitignore +1 -0
@@ -7,3 +7,4 @@ logs/error.log
77 logs/http.log
88 logs/docker.log
99 gordon.yml
10+bun.lockb
@@ -7,3 +7,4 @@ logs/error.log
7 logs/http.log7 logs/http.log
8 logs/docker.log8 logs/docker.log
9 gordon.yml9 gordon.yml
10+bun.lockb
A cmd/main.go +10 -0
@@ -0,0 +1,10 @@
1+package main
2+
3+import (
4+ "github.com/bnema/gordon/internal/app"
5+)
6+
7+func main() {
8+ a := app.NewApp()
9+ a.Start()
10+}
@@ -0,0 +1,10 @@
1+package main
2+
3+import (
4+ "github.com/bnema/gordon/internal/app"
5+)
6+
7+func main() {
8+ a := app.NewApp()
9+ a.Start()
10+}
A go.mod +21 -0
@@ -0,0 +1,21 @@
1+module github.com/bnema/gordon
2+
3+go 1.21.1
4+
5+require (
6+ github.com/PuerkitoBio/goquery v1.8.1
7+ github.com/labstack/echo/v4 v4.11.1
8+)
9+
10+require (
11+ github.com/andybalholm/cascadia v1.3.1 // indirect
12+ github.com/labstack/gommon v0.4.0 // indirect
13+ github.com/mattn/go-colorable v0.1.13 // indirect
14+ github.com/mattn/go-isatty v0.0.19 // indirect
15+ github.com/valyala/bytebufferpool v1.0.0 // indirect
16+ github.com/valyala/fasttemplate v1.2.2 // indirect
17+ golang.org/x/crypto v0.11.0 // indirect
18+ golang.org/x/net v0.12.0 // indirect
19+ golang.org/x/sys v0.10.0 // indirect
20+ golang.org/x/text v0.11.0 // indirect
21+)
@@ -0,0 +1,21 @@
1+module github.com/bnema/gordon
2+
3+go 1.21.1
4+
5+require (
6+ github.com/PuerkitoBio/goquery v1.8.1
7+ github.com/labstack/echo/v4 v4.11.1
8+)
9+
10+require (
11+ github.com/andybalholm/cascadia v1.3.1 // indirect
12+ github.com/labstack/gommon v0.4.0 // indirect
13+ github.com/mattn/go-colorable v0.1.13 // indirect
14+ github.com/mattn/go-isatty v0.0.19 // indirect
15+ github.com/valyala/bytebufferpool v1.0.0 // indirect
16+ github.com/valyala/fasttemplate v1.2.2 // indirect
17+ golang.org/x/crypto v0.11.0 // indirect
18+ golang.org/x/net v0.12.0 // indirect
19+ golang.org/x/sys v0.10.0 // indirect
20+ golang.org/x/text v0.11.0 // indirect
21+)
A go.sum +77 -0 generated file: collapsed
A internal/app/app.go +61 -0
@@ -0,0 +1,61 @@
1+package app
2+
3+import (
4+ "fmt"
5+ "io/fs"
6+
7+ "github.com/bnema/gordon/internal/gotemplate"
8+ "github.com/bnema/gordon/internal/webui"
9+)
10+
11+const (
12+ BuildVersion = "0.0.2"
13+ BuildDir = "tmp"
14+)
15+
16+type App struct {
17+ TemplateFS fs.FS
18+ PublicFS fs.FS
19+ BuildVersion string
20+ BuildDir string
21+}
22+
23+func (*App) GetTemplateFS() fs.FS {
24+ return gotemplate.TemplateFS
25+}
26+
27+func (*App) GetPublicFS() fs.FS {
28+ return webui.PublicFS
29+}
30+
31+func (*App) GetBuildVersion() string {
32+ return BuildVersion
33+}
34+
35+func (*App) GetBuildDir() string {
36+ return BuildDir
37+}
38+
39+func NewApp() *App {
40+ return &App{
41+ TemplateFS: gotemplate.TemplateFS,
42+ PublicFS: webui.PublicFS,
43+ BuildVersion: BuildVersion,
44+ BuildDir: BuildDir,
45+ }
46+}
47+
48+func (a *App) Start() {
49+ fmt.Println("Starting app")
50+
51+ // LS in the template directory
52+ entries, err := fs.ReadDir(a.TemplateFS, ".") // List the root directory
53+ if err != nil {
54+ fmt.Println("Error reading directory:", err)
55+ return
56+ }
57+
58+ for _, entry := range entries {
59+ fmt.Println(entry.Name())
60+ }
61+}
@@ -0,0 +1,61 @@
1+package app
2+
3+import (
4+ "fmt"
5+ "io/fs"
6+
7+ "github.com/bnema/gordon/internal/gotemplate"
8+ "github.com/bnema/gordon/internal/webui"
9+)
10+
11+const (
12+ BuildVersion = "0.0.2"
13+ BuildDir = "tmp"
14+)
15+
16+type App struct {
17+ TemplateFS fs.FS
18+ PublicFS fs.FS
19+ BuildVersion string
20+ BuildDir string
21+}
22+
23+func (*App) GetTemplateFS() fs.FS {
24+ return gotemplate.TemplateFS
25+}
26+
27+func (*App) GetPublicFS() fs.FS {
28+ return webui.PublicFS
29+}
30+
31+func (*App) GetBuildVersion() string {
32+ return BuildVersion
33+}
34+
35+func (*App) GetBuildDir() string {
36+ return BuildDir
37+}
38+
39+func NewApp() *App {
40+ return &App{
41+ TemplateFS: gotemplate.TemplateFS,
42+ PublicFS: webui.PublicFS,
43+ BuildVersion: BuildVersion,
44+ BuildDir: BuildDir,
45+ }
46+}
47+
48+func (a *App) Start() {
49+ fmt.Println("Starting app")
50+
51+ // LS in the template directory
52+ entries, err := fs.ReadDir(a.TemplateFS, ".") // List the root directory
53+ if err != nil {
54+ fmt.Println("Error reading directory:", err)
55+ return
56+ }
57+
58+ for _, entry := range entries {
59+ fmt.Println(entry.Name())
60+ }
61+}
A internal/gotemplate/embed.go +13 -0
@@ -0,0 +1,13 @@
1+package gotemplate
2+
3+import (
4+ "embed"
5+
6+ "github.com/labstack/echo/v4"
7+)
8+
9+// Embedding templates directories
10+
11+//go:embed models/*
12+var template embed.FS
13+var TemplateFS = echo.MustSubFS(template, "models")
@@ -0,0 +1,13 @@
1+package gotemplate
2+
3+import (
4+ "embed"
5+
6+ "github.com/labstack/echo/v4"
7+)
8+
9+// Embedding templates directories
10+
11+//go:embed models/*
12+var template embed.FS
13+var TemplateFS = echo.MustSubFS(template, "models")
A internal/gotemplate/models/html/admin/dashboard.gohtml +9 -0
@@ -0,0 +1,9 @@
1+<div id="dashboard">
2+ <h1
3+ class="text-5xl fw100 animate-bounce-alt animate-count-infinite animate-duration-1s"
4+ >
5+ Hello World from dashboard.html
6+ </h1>
7+ <!-- We load Chart.js here to avoid loading it in every page end when all the rest is loaded -->
8+ <script src="libs/chart.js"></script>
9+</div>
@@ -0,0 +1,9 @@
1+<div id="dashboard">
2+ <h1
3+ class="text-5xl fw100 animate-bounce-alt animate-count-infinite animate-duration-1s"
4+ >
5+ Hello World from dashboard.html
6+ </h1>
7+ <!-- We load Chart.js here to avoid loading it in every page end when all the rest is loaded -->
8+ <script src="libs/chart.js"></script>
9+</div>
A internal/gotemplate/models/html/admin/index.gohtml +124 -0
@@ -0,0 +1,124 @@
1+<!-- @format -->
2+
3+<!DOCTYPE html>
4+<html lang="en">
5+ <head>
6+ <meta charset="UTF-8" />
7+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
8+ <title>{{ .header.meta.title }}</title>
9+ <meta name="description" content="{{ .Header.Meta.Description }}" />
10+ <meta name="keywords" content="{{ .Header.Meta.Keywords }}" />
11+ <!-- Custom CSS + Tailwind -->
12+ <link rel="stylesheet" href="/assets/css/tailwind.css" />
13+ <!-- Iconoir -->
14+ <link rel="stylesheet" href="/libs/iconoir.css" />
15+ <!-- Alpine -->
16+ <script src="/libs/alpine.min.js"></script>
17+ <!-- HTMX min js -->
18+ <script src="/libs/htmx.min.js"></script>
19+ <!-- HTMX SSE -->
20+ <script src="/libs/htmx-sse.js"></script>
21+ <!-- Custom JS from assets/js -->
22+ <script src="assets/js/custom.js"></script>
23+ </head>
24+ <body class="IBMPlexSans bg-zinc-200 md:p-8 flex">
25+ <!-- Left Menu -->
26+ <div class="w-1/5 flex flex-col space-evenly">
27+ <!-- Logo -->
28+ <div id="logo-mascot-leftnav" class="flex justify-center p-4">
29+ <div class="circle-shadow flex justify-center w-100">
30+ <img
31+ src="/assets/imgs/gordon-mascot-hq-trsp.png"
32+ alt="logo"
33+ class="sm:h-24 h-32 xl:h-48"
34+ />
35+ </div>
36+ </div>
37+ <!-- Site Name + Version -->
38+ <div
39+ class="p-4 flex flex-col bg-gordonmascot-lblue rounded-lg shadow space-y-4"
40+ >
41+ <div class="w-full flex justify-center">
42+ <h1
43+ class="gordon-title text-2xl lg:text-4xl xl:text-5xl text-gordonmascot-hblue tracking-tighter"
44+ >
45+ Gordon
46+ </h1>
47+ <span class="gordon-v-subtitle text-gordonmascot-mblue text-sm"
48+ >v0.0.1</span
49+ >
50+ </div>
51+ <!--(Navigation) -->
52+ <div id="menu-leftnav" class="w-full">
53+ <ul
54+ class="flex flex-col md:space-y-6 md:py-8 font-semibold text-gray-100 text-lg md:text-2xl md:pl-4"
55+ >
56+ <li class="flex items-center">
57+ <i class="iconoir-dashboard-speed mr-2 md:text-3xl"></i>
58+ <a href="index.html">Dashboard</a>
59+ </li>
60+ <li class="flex items-center">
61+ <i class="iconoir-server mr-2 md:text-3xl"></i>
62+ <a href="#manager">Manager</a>
63+ </li>
64+ <li class="flex items-center">
65+ <i class="iconoir-community mr-2 md:text-3xl"></i>
66+ <a href="#users">Users</a>
67+ </li>
68+ <li class="flex items-center">
69+ <i class="iconoir-database-settings mr-2 md:text-3xl"></i>
70+ <a href="#gordon-settings">Settings</a>
71+ </li>
72+ </ul>
73+ </div>
74+
75+ <div class="w-full h-24 bg-gordonmascot-mblue rounded-lg"></div>
76+ <!-- Mock menu item -->
77+ </div>
78+ </div>
79+
80+ <!-- Main Content including the navbar -->
81+ <div class="flex-1 flex flex-col md:pt-10 space-y-4 ml-4">
82+ <!-- Search Nav within the main content -->
83+ <div class="mb-4 flex justify-end">
84+ <div class="w-72 h-10 bg-gray-300 rounded-lg">
85+ <!-- Search input with iconir search -->
86+ <div class="flex justify-between items-center h-full px-2">
87+ <input
88+ type="text"
89+ class="w-full h-full bg-transparent outline-none"
90+ placeholder="Search"
91+ />
92+ <i class="iconoir-search"></i>
93+ </div>
94+ </div>
95+ <!-- Mock search or other element -->
96+ </div>
97+
98+ <!-- Cards section -->
99+ <div class="flex space-x-4 flex-grow">
100+ <!-- Main Card on the Left -->
101+ <div class="w-4/6 bg-white p-4 rounded-md shadow mb-4">
102+ <div class="w-full rounded-sm bg-gray-300"></div>
103+ <!-- Mock main card -->
104+ </div>
105+
106+ <!-- Two Cards on the Right -->
107+ <div class="w-2/6 flex flex-col flex-justify-start">
108+ <div class="bg-white p-4 rounded-md shadow mb-4">
109+ <div class="w-full h-44 rounded-sm bg-gray-300"></div>
110+ <!-- Mock card -->
111+ </div>
112+ <div class="bg-white p-4 rounded-md shadow mb-4">
113+ <div class="w-full h-44 rounded-sm bg-gray-300"></div>
114+ <!-- Mock card -->
115+ </div>
116+ <div class="bg-white p-4 rounded-md shadow mb-4">
117+ <div class="w-full h-44 rounded-sm bg-gray-300"></div>
118+ <!-- Mock card -->
119+ </div>
120+ </div>
121+ </div>
122+ </div>
123+ </body>
124+</html>
@@ -0,0 +1,124 @@
1+<!-- @format -->
2+
3+<!DOCTYPE html>
4+<html lang="en">
5+ <head>
6+ <meta charset="UTF-8" />
7+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
8+ <title>{{ .header.meta.title }}</title>
9+ <meta name="description" content="{{ .Header.Meta.Description }}" />
10+ <meta name="keywords" content="{{ .Header.Meta.Keywords }}" />
11+ <!-- Custom CSS + Tailwind -->
12+ <link rel="stylesheet" href="/assets/css/tailwind.css" />
13+ <!-- Iconoir -->
14+ <link rel="stylesheet" href="/libs/iconoir.css" />
15+ <!-- Alpine -->
16+ <script src="/libs/alpine.min.js"></script>
17+ <!-- HTMX min js -->
18+ <script src="/libs/htmx.min.js"></script>
19+ <!-- HTMX SSE -->
20+ <script src="/libs/htmx-sse.js"></script>
21+ <!-- Custom JS from assets/js -->
22+ <script src="assets/js/custom.js"></script>
23+ </head>
24+ <body class="IBMPlexSans bg-zinc-200 md:p-8 flex">
25+ <!-- Left Menu -->
26+ <div class="w-1/5 flex flex-col space-evenly">
27+ <!-- Logo -->
28+ <div id="logo-mascot-leftnav" class="flex justify-center p-4">
29+ <div class="circle-shadow flex justify-center w-100">
30+ <img
31+ src="/assets/imgs/gordon-mascot-hq-trsp.png"
32+ alt="logo"
33+ class="sm:h-24 h-32 xl:h-48"
34+ />
35+ </div>
36+ </div>
37+ <!-- Site Name + Version -->
38+ <div
39+ class="p-4 flex flex-col bg-gordonmascot-lblue rounded-lg shadow space-y-4"
40+ >
41+ <div class="w-full flex justify-center">
42+ <h1
43+ class="gordon-title text-2xl lg:text-4xl xl:text-5xl text-gordonmascot-hblue tracking-tighter"
44+ >
45+ Gordon
46+ </h1>
47+ <span class="gordon-v-subtitle text-gordonmascot-mblue text-sm"
48+ >v0.0.1</span
49+ >
50+ </div>
51+ <!--(Navigation) -->
52+ <div id="menu-leftnav" class="w-full">
53+ <ul
54+ class="flex flex-col md:space-y-6 md:py-8 font-semibold text-gray-100 text-lg md:text-2xl md:pl-4"
55+ >
56+ <li class="flex items-center">
57+ <i class="iconoir-dashboard-speed mr-2 md:text-3xl"></i>
58+ <a href="index.html">Dashboard</a>
59+ </li>
60+ <li class="flex items-center">
61+ <i class="iconoir-server mr-2 md:text-3xl"></i>
62+ <a href="#manager">Manager</a>
63+ </li>
64+ <li class="flex items-center">
65+ <i class="iconoir-community mr-2 md:text-3xl"></i>
66+ <a href="#users">Users</a>
67+ </li>
68+ <li class="flex items-center">
69+ <i class="iconoir-database-settings mr-2 md:text-3xl"></i>
70+ <a href="#gordon-settings">Settings</a>
71+ </li>
72+ </ul>
73+ </div>
74+
75+ <div class="w-full h-24 bg-gordonmascot-mblue rounded-lg"></div>
76+ <!-- Mock menu item -->
77+ </div>
78+ </div>
79+
80+ <!-- Main Content including the navbar -->
81+ <div class="flex-1 flex flex-col md:pt-10 space-y-4 ml-4">
82+ <!-- Search Nav within the main content -->
83+ <div class="mb-4 flex justify-end">
84+ <div class="w-72 h-10 bg-gray-300 rounded-lg">
85+ <!-- Search input with iconir search -->
86+ <div class="flex justify-between items-center h-full px-2">
87+ <input
88+ type="text"
89+ class="w-full h-full bg-transparent outline-none"
90+ placeholder="Search"
91+ />
92+ <i class="iconoir-search"></i>
93+ </div>
94+ </div>
95+ <!-- Mock search or other element -->
96+ </div>
97+
98+ <!-- Cards section -->
99+ <div class="flex space-x-4 flex-grow">
100+ <!-- Main Card on the Left -->
101+ <div class="w-4/6 bg-white p-4 rounded-md shadow mb-4">
102+ <div class="w-full rounded-sm bg-gray-300"></div>
103+ <!-- Mock main card -->
104+ </div>
105+
106+ <!-- Two Cards on the Right -->
107+ <div class="w-2/6 flex flex-col flex-justify-start">
108+ <div class="bg-white p-4 rounded-md shadow mb-4">
109+ <div class="w-full h-44 rounded-sm bg-gray-300"></div>
110+ <!-- Mock card -->
111+ </div>
112+ <div class="bg-white p-4 rounded-md shadow mb-4">
113+ <div class="w-full h-44 rounded-sm bg-gray-300"></div>
114+ <!-- Mock card -->
115+ </div>
116+ <div class="bg-white p-4 rounded-md shadow mb-4">
117+ <div class="w-full h-44 rounded-sm bg-gray-300"></div>
118+ <!-- Mock card -->
119+ </div>
120+ </div>
121+ </div>
122+ </div>
123+ </body>
124+</html>
A internal/gotemplate/models/html/admin/install.gohtml +137 -0
@@ -0,0 +1,137 @@
1+<!DOCTYPE html>
2+<html lang="en">
3+ <head>
4+ <meta charset="UTF-8" />
5+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6+ <title>{{ .header.meta.title }}</title>
7+ <meta name="description" content="{{ .Header.Meta.Description }}" />
8+ <meta name="keywords" content="{{ .Header.Meta.Keywords }}" />
9+ <!-- Custom CSS + Tailwind -->
10+ <link rel="stylesheet" href="/assets/css/tailwind.css" />
11+ <!-- Iconoir -->
12+ <link rel="stylesheet" href="/libs/iconoir.css" />
13+ <!-- Alpine -->
14+ <script src="/libs/alpine.min.js"></script>
15+ <!-- HTMX min js -->
16+ <script src="/libs/htmx.min.js"></script>
17+ <!-- HTMX SSE -->
18+ <script src="/libs/htmx-sse.js"></script>
19+ <!-- Custom JS from assets/js -->
20+ <script src="/assets/js/custom.js"></script>
21+ </head>
22+
23+ <body
24+ class="IBMPlexSans bg-zinc-200 md:p-8 flex flex-col items-center"
25+ hx-boost="true"
26+ >
27+ <!-- Logo and Title -->
28+ <div
29+ id="logo-mascot"
30+ class="flex flex-col justify-center items-center p-4 mb-4"
31+ >
32+ <div class="circle-shadow flex justify-center w-100">
33+ <img
34+ src="/assets/imgs/gordon-mascot-hq-trsp.png"
35+ alt="logo"
36+ class="sm:h-24 h-32 xl:h-48"
37+ />
38+ </div>
39+ <div class="flex justify-center mt-4">
40+ <h1
41+ class="gordon-title text-2xl lg:text-4xl xl:text-5xl text-gordonmascot-hblue tracking-tighter"
42+ >
43+ Gordon
44+ </h1>
45+ <span class="gordon-v-subtitle text-gordonmascot-mblue text-sm ml-2"
46+ >v0.0.1</span
47+ >
48+ </div>
49+ </div>
50+
51+ <!-- Main Content -->
52+ <div class="bg-white p-4 rounded-md shadow mb-4 w-2/3">
53+ <!-- Install Traefik -->
54+ <div id="install-traefik">
55+ <div class="flex flex-col items-center">
56+ <h2 class="text-2xl font-semibold text-gray-800">
57+ 1 - Install Traefik
58+ </h2>
59+ <!-- Dual view left : install procedure / right : SSE log installation -->
60+ <div class="flex flex-col md:flex-row justify-items-center w-full">
61+ <!-- Left -->
62+ <div class="w-full md:w-1/2 p-4">
63+ <form
64+ id="install-traefik-form"
65+ action="/admin/install/traefik"
66+ method="POST"
67+ hx-post="/admin/install/traefik"
68+ hx-swap="outerHTML"
69+ >
70+ <h2 class="">1.1 - Set your top domain name</h2>
71+ <input
72+ type="text"
73+ name="topdomain"
74+ id="topdomain"
75+ class="w-full py-2 px-4 my-2 border border-gray-300 rounded-md"
76+ placeholder="example.com"
77+ />
78+ <h2>1.2 - Set your admin email (a reachable one)</h2>
79+ <input
80+ type="text"
81+ name="adminemail"
82+ id="adminemail"
83+ class="w-full p-2 border border-gray-300 rounded-md"
84+ placeholder="admin@example.com"
85+ />
86+ <button
87+ type="submit"
88+ class="w-full p-2 bg-gordonmascot-hblue text-slate-100 rounded-md mt-4"
89+ >
90+ Save & Install Traefik
91+ </button>
92+ </form>
93+ </div>
94+ <!-- Right -->
95+ <div class="w-full md:w-1/2 p-4 text-slate-100">
96+ <div
97+ class="flex flex-col items-center bg-gordonmascot-hblue rounded-md"
98+ >
99+ <div class="w-full h-64 overflow-y-scroll-auto p-4">
100+ <div
101+ class="flex flex-col space-y-2"
102+ hx-ext="sse"
103+ sse-connect="/admin/install/traefik/sse"
104+ >
105+ <!-- One item -->
106+ <div class="flex flex-row items-center">
107+ <span class="">[INFO]</span>
108+ <span class="">Traefik installed</span>
109+ </div>
110+ <!-- One item -->
111+ <div class="flex flex-row items-center">
112+ <span class="">[INFO]</span>
113+ <span class="ml-2">Traefik started</span>
114+ </div>
115+ <!-- One item -->
116+ <div class="flex flex-row items-center">
117+ <span class="">[INFO]</span>
118+ <span class="ml-2"
119+ >Traefik configuration file created</span
120+ >
121+ </div>
122+ <!-- One item -->
123+ <div class="flex flex-row items-center">
124+ <span class="">[INFO]</span>
125+ <span class="">Traefik configuration file updated</span>
126+ </div>
127+ </div>
128+ </div>
129+ </div>
130+ </div>
131+ </div>
132+ </div>
133+ </div>
134+ <!-- End Install Traefik -->
135+ </div>
136+ </body>
137+</html>
@@ -0,0 +1,137 @@
1+<!DOCTYPE html>
2+<html lang="en">
3+ <head>
4+ <meta charset="UTF-8" />
5+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6+ <title>{{ .header.meta.title }}</title>
7+ <meta name="description" content="{{ .Header.Meta.Description }}" />
8+ <meta name="keywords" content="{{ .Header.Meta.Keywords }}" />
9+ <!-- Custom CSS + Tailwind -->
10+ <link rel="stylesheet" href="/assets/css/tailwind.css" />
11+ <!-- Iconoir -->
12+ <link rel="stylesheet" href="/libs/iconoir.css" />
13+ <!-- Alpine -->
14+ <script src="/libs/alpine.min.js"></script>
15+ <!-- HTMX min js -->
16+ <script src="/libs/htmx.min.js"></script>
17+ <!-- HTMX SSE -->
18+ <script src="/libs/htmx-sse.js"></script>
19+ <!-- Custom JS from assets/js -->
20+ <script src="/assets/js/custom.js"></script>
21+ </head>
22+
23+ <body
24+ class="IBMPlexSans bg-zinc-200 md:p-8 flex flex-col items-center"
25+ hx-boost="true"
26+ >
27+ <!-- Logo and Title -->
28+ <div
29+ id="logo-mascot"
30+ class="flex flex-col justify-center items-center p-4 mb-4"
31+ >
32+ <div class="circle-shadow flex justify-center w-100">
33+ <img
34+ src="/assets/imgs/gordon-mascot-hq-trsp.png"
35+ alt="logo"
36+ class="sm:h-24 h-32 xl:h-48"
37+ />
38+ </div>
39+ <div class="flex justify-center mt-4">
40+ <h1
41+ class="gordon-title text-2xl lg:text-4xl xl:text-5xl text-gordonmascot-hblue tracking-tighter"
42+ >
43+ Gordon
44+ </h1>
45+ <span class="gordon-v-subtitle text-gordonmascot-mblue text-sm ml-2"
46+ >v0.0.1</span
47+ >
48+ </div>
49+ </div>
50+
51+ <!-- Main Content -->
52+ <div class="bg-white p-4 rounded-md shadow mb-4 w-2/3">
53+ <!-- Install Traefik -->
54+ <div id="install-traefik">
55+ <div class="flex flex-col items-center">
56+ <h2 class="text-2xl font-semibold text-gray-800">
57+ 1 - Install Traefik
58+ </h2>
59+ <!-- Dual view left : install procedure / right : SSE log installation -->
60+ <div class="flex flex-col md:flex-row justify-items-center w-full">
61+ <!-- Left -->
62+ <div class="w-full md:w-1/2 p-4">
63+ <form
64+ id="install-traefik-form"
65+ action="/admin/install/traefik"
66+ method="POST"
67+ hx-post="/admin/install/traefik"
68+ hx-swap="outerHTML"
69+ >
70+ <h2 class="">1.1 - Set your top domain name</h2>
71+ <input
72+ type="text"
73+ name="topdomain"
74+ id="topdomain"
75+ class="w-full py-2 px-4 my-2 border border-gray-300 rounded-md"
76+ placeholder="example.com"
77+ />
78+ <h2>1.2 - Set your admin email (a reachable one)</h2>
79+ <input
80+ type="text"
81+ name="adminemail"
82+ id="adminemail"
83+ class="w-full p-2 border border-gray-300 rounded-md"
84+ placeholder="admin@example.com"
85+ />
86+ <button
87+ type="submit"
88+ class="w-full p-2 bg-gordonmascot-hblue text-slate-100 rounded-md mt-4"
89+ >
90+ Save & Install Traefik
91+ </button>
92+ </form>
93+ </div>
94+ <!-- Right -->
95+ <div class="w-full md:w-1/2 p-4 text-slate-100">
96+ <div
97+ class="flex flex-col items-center bg-gordonmascot-hblue rounded-md"
98+ >
99+ <div class="w-full h-64 overflow-y-scroll-auto p-4">
100+ <div
101+ class="flex flex-col space-y-2"
102+ hx-ext="sse"
103+ sse-connect="/admin/install/traefik/sse"
104+ >
105+ <!-- One item -->
106+ <div class="flex flex-row items-center">
107+ <span class="">[INFO]</span>
108+ <span class="">Traefik installed</span>
109+ </div>
110+ <!-- One item -->
111+ <div class="flex flex-row items-center">
112+ <span class="">[INFO]</span>
113+ <span class="ml-2">Traefik started</span>
114+ </div>
115+ <!-- One item -->
116+ <div class="flex flex-row items-center">
117+ <span class="">[INFO]</span>
118+ <span class="ml-2"
119+ >Traefik configuration file created</span
120+ >
121+ </div>
122+ <!-- One item -->
123+ <div class="flex flex-row items-center">
124+ <span class="">[INFO]</span>
125+ <span class="">Traefik configuration file updated</span>
126+ </div>
127+ </div>
128+ </div>
129+ </div>
130+ </div>
131+ </div>
132+ </div>
133+ </div>
134+ <!-- End Install Traefik -->
135+ </div>
136+ </body>
137+</html>
A internal/gotemplate/models/html/admin/manager.gohtml +0 -0

no textual change.

A internal/gotemplate/models/html/admin/user.gohtml +0 -0

no textual change.

A internal/gotemplate/models/html/fragments/components.gohtml +33 -0
@@ -0,0 +1,33 @@
1+<!-- @format -->
2+
3+<div id="header">
4+ <h1
5+ class="text-5xl fw100 animate-bounce-alt animate-count-infinite animate-duration-1s"
6+ >
7+ {{ .body.header.helloworld }}
8+ </h1>
9+</div>
10+
11+<div id="hello">
12+ <h1
13+ class="text-5xl fw100 animate-bounce-alt animate-count-infinite animate-duration-1s"
14+ >
15+ {{ .body.div.hello }}
16+ </h1>
17+</div>
18+<div
19+ id="header"
20+ hx-get="/htmx"
21+ hx-headers='{"HX-Fragment": "header"}'
22+ hx-trigger="load"
23+ hx-swap="outerHTML"
24+></div>
25+
26+<!-- App Fragment -->
27+<div
28+ id="app"
29+ hx-get="/htmx"
30+ hx-headers='{"HX-Fragment": "hello"}'
31+ hx-trigger="load"
32+ hx-swap="outerHTML"
33+></div>
@@ -0,0 +1,33 @@
1+<!-- @format -->
2+
3+<div id="header">
4+ <h1
5+ class="text-5xl fw100 animate-bounce-alt animate-count-infinite animate-duration-1s"
6+ >
7+ {{ .body.header.helloworld }}
8+ </h1>
9+</div>
10+
11+<div id="hello">
12+ <h1
13+ class="text-5xl fw100 animate-bounce-alt animate-count-infinite animate-duration-1s"
14+ >
15+ {{ .body.div.hello }}
16+ </h1>
17+</div>
18+<div
19+ id="header"
20+ hx-get="/htmx"
21+ hx-headers='{"HX-Fragment": "header"}'
22+ hx-trigger="load"
23+ hx-swap="outerHTML"
24+></div>
25+
26+<!-- App Fragment -->
27+<div
28+ id="app"
29+ hx-get="/htmx"
30+ hx-headers='{"HX-Fragment": "hello"}'
31+ hx-trigger="load"
32+ hx-swap="outerHTML"
33+></div>
A internal/gotemplate/models/html/strings.yml +23 -0
@@ -0,0 +1,23 @@
1+en:
2+ header:
3+ meta:
4+ title: Gordon - Admin Dashboard
5+ description: Admin dashboard for Gordon
6+ keywords: gordon, admin, dashboard
7+ body:
8+ header:
9+ helloworld: Hello World!
10+ div:
11+ hello: Hello component loaded from a template!
12+
13+fr:
14+ header:
15+ meta:
16+ title: Gordon - Tableau de bord administrateur
17+ description: Tableau de bord administrateur pour Gordon
18+ keywords: gordon, admin, dashboard
19+ body:
20+ header:
21+ helloworld: Bonjour le monde!
22+ div:
23+ hello: Composant de salut chargé à partir d'un modèle!
@@ -0,0 +1,23 @@
1+en:
2+ header:
3+ meta:
4+ title: Gordon - Admin Dashboard
5+ description: Admin dashboard for Gordon
6+ keywords: gordon, admin, dashboard
7+ body:
8+ header:
9+ helloworld: Hello World!
10+ div:
11+ hello: Hello component loaded from a template!
12+
13+fr:
14+ header:
15+ meta:
16+ title: Gordon - Tableau de bord administrateur
17+ description: Tableau de bord administrateur pour Gordon
18+ keywords: gordon, admin, dashboard
19+ body:
20+ header:
21+ helloworld: Bonjour le monde!
22+ div:
23+ hello: Composant de salut chargé à partir d'un modèle!
A internal/gotemplate/models/txt/test.txt +0 -0

no textual change.

A internal/httpserve/handler/adminroutes.go +5 -0
@@ -0,0 +1,5 @@
1+package handlers
2+
3+import ()
4+
5+
@@ -0,0 +1,5 @@
1+package handlers
2+
3+import ()
4+
5+
A internal/httpserve/handler/htmx.go +0 -0

no textual change.

A internal/httpserve/handler/static.go +0 -0

no textual change.

A internal/httpserve/middleware/detectcolorscheme.go +0 -0

no textual change.

A internal/httpserve/middleware/detectlang.go +0 -0

no textual change.

A internal/httpserve/middleware/secure.go +0 -0

no textual change.

A internal/httpserve/middleware/tmp/build-errors.log +1 -0
@@ -0,0 +1,1 @@
1+exit status 1⏎̸
@@ -0,0 +1,1 @@
1+exit status 1⏎̸
A internal/httpserve/router.go +0 -0

no textual change.

A internal/webui/embed.go +14 -0
@@ -0,0 +1,14 @@
1+package webui
2+
3+import (
4+ "embed"
5+
6+ "github.com/labstack/echo/v4"
7+)
8+
9+// Embedding the public directory
10+//
11+//go:embed public/*
12+var public embed.FS
13+
14+var PublicFS = echo.MustSubFS(public, "internal/webui/public")
@@ -0,0 +1,14 @@
1+package webui
2+
3+import (
4+ "embed"
5+
6+ "github.com/labstack/echo/v4"
7+)
8+
9+// Embedding the public directory
10+//
11+//go:embed public/*
12+var public embed.FS
13+
14+var PublicFS = echo.MustSubFS(public, "internal/webui/public")
A internal/webui/public/404.gohtml +12 -0
@@ -0,0 +1,12 @@
1+<!DOCTYPE html>
2+<html lang="en">
3+ <head>
4+ <meta charset="UTF-8" />
5+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6+ <title>Error 404</title>
7+ </head>
8+ <body>
9+ <h1>Error 404</h1>
10+ <p>Page not found</p>
11+ </body>
12+</html>
@@ -0,0 +1,12 @@
1+<!DOCTYPE html>
2+<html lang="en">
3+ <head>
4+ <meta charset="UTF-8" />
5+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6+ <title>Error 404</title>
7+ </head>
8+ <body>
9+ <h1>Error 404</h1>
10+ <p>Page not found</p>
11+ </body>
12+</html>
A internal/webui/public/500.gohtml +12 -0
@@ -0,0 +1,12 @@
1+<!DOCTYPE html>
2+<html lang="en">
3+ <head>
4+ <meta charset="UTF-8" />
5+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6+ <title>Error 500</title>
7+ </head>
8+ <body>
9+ <h1>500 Internal Server Error</h1>
10+ <p>Something went really wrong o/</p>
11+ </body>
12+</html>
@@ -0,0 +1,12 @@
1+<!DOCTYPE html>
2+<html lang="en">
3+ <head>
4+ <meta charset="UTF-8" />
5+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6+ <title>Error 500</title>
7+ </head>
8+ <body>
9+ <h1>500 Internal Server Error</h1>
10+ <p>Something went really wrong o/</p>
11+ </body>
12+</html>
A internal/webui/public/android-chrome-192x192.png +0 -0 binary file: no text diff

binary file: no text diff

A internal/webui/public/android-chrome-512x512.png +0 -0 binary file: no text diff

binary file: no text diff

A internal/webui/public/apple-touch-icon.png +0 -0 binary file: no text diff

binary file: no text diff

A internal/webui/public/assets/css/custom.css +116 -0
@@ -0,0 +1,116 @@
1+/**
2+ * Path: internal/ui/public/assets/css/custom.css
3+ *
4+ * @format
5+ */
6+
7+/* Embeded path : assets/css/cutsom.css */
8+
9+@tailwind base;
10+@tailwind components;
11+@tailwind utilities;
12+
13+/* Import IBM Plex Fonts */
14+@font-face {
15+ font-family: "IBMPlexSans-Bold";
16+ src: url("/assets/fonts/IBMPlex/IBMPlexSans-Bold.woff2") format("woff2");
17+ font-weight: bold;
18+ font-style: normal;
19+}
20+
21+@font-face {
22+ font-family: "IBMPlexSans-Regular";
23+ src: url("/assets/fonts/IBMPlex/IBMPlexSans-Regular.woff2") format("woff2");
24+ font-weight: normal;
25+ font-style: normal;
26+}
27+
28+/* Import Jetbrains Mono Nerd Font */
29+@font-face {
30+ font-family: "JetBrainsMono-Nerd-Font-Regular";
31+ src: url("/assets/fonts/JetBrainsMonoNerd/JetBrainsMonoNerdFontMono-Regular.woff2")
32+ format("woff2");
33+ font-weight: normal;
34+ font-style: normal;
35+}
36+
37+@font-face {
38+ font-family: "LilitaOne-Regular";
39+ src: url("/assets/fonts/LilitaOne/LilitaOne-Regular.ttf") format("truetype");
40+ font-weight: normal;
41+ font-style: normal;
42+}
43+
44+.fade-me-out.htmx-swapping {
45+ opacity: 0;
46+ transition: opacity 1s ease-out;
47+}
48+
49+/* View transition */
50+@keyframes fade-in {
51+ from {
52+ opacity: 0;
53+ }
54+}
55+
56+@keyframes fade-out {
57+ to {
58+ opacity: 0;
59+ }
60+}
61+
62+@keyframes slide-from-right {
63+ from {
64+ transform: translateX(90px);
65+ }
66+}
67+
68+@keyframes slide-to-left {
69+ to {
70+ transform: translateX(-90px);
71+ }
72+}
73+
74+.slide-it {
75+ view-transition-name: slide-it;
76+}
77+
78+::view-transition-old(slide-it) {
79+ animation: 180ms cubic-bezier(0.4, 0, 1, 1) both fade-out,
80+ 600ms cubic-bezier(0.4, 0, 0.2, 1) both slide-to-left;
81+}
82+::view-transition-new(slide-it) {
83+ animation: 420ms cubic-bezier(0, 0, 0.2, 1) 90ms both fade-in,
84+ 600ms cubic-bezier(0.4, 0, 0.2, 1) both slide-from-right;
85+}
86+
87+.gordon-title {
88+ font-family: "LilitaOne-Regular", sans-serif;
89+
90+}
91+
92+.IBMPlexSans {
93+ font-family: "IBMPlexSans-Regular", sans-serif;
94+}
95+
96+.circle-shadow {
97+ width: 100%;
98+ position: relative;
99+}
100+
101+.circle-shadow::after {
102+ position: absolute;
103+ width: 50%;
104+ height: 0.4rem;
105+ margin: auto;
106+ background: rgba(0, 0, 0, 0.1);
107+ border-radius: 50%;
108+ z-index: -1;
109+ bottom: 2%;
110+ content: "";
111+ box-shadow: 0 0 1px 0.3rem rgba(0, 0, 0, 0.1);
112+}
113+
114+.iconoir {
115+ margin-right: 8px;
116+}
@@ -0,0 +1,116 @@
1+/**
2+ * Path: internal/ui/public/assets/css/custom.css
3+ *
4+ * @format
5+ */
6+
7+/* Embeded path : assets/css/cutsom.css */
8+
9+@tailwind base;
10+@tailwind components;
11+@tailwind utilities;
12+
13+/* Import IBM Plex Fonts */
14+@font-face {
15+ font-family: "IBMPlexSans-Bold";
16+ src: url("/assets/fonts/IBMPlex/IBMPlexSans-Bold.woff2") format("woff2");
17+ font-weight: bold;
18+ font-style: normal;
19+}
20+
21+@font-face {
22+ font-family: "IBMPlexSans-Regular";
23+ src: url("/assets/fonts/IBMPlex/IBMPlexSans-Regular.woff2") format("woff2");
24+ font-weight: normal;
25+ font-style: normal;
26+}
27+
28+/* Import Jetbrains Mono Nerd Font */
29+@font-face {
30+ font-family: "JetBrainsMono-Nerd-Font-Regular";
31+ src: url("/assets/fonts/JetBrainsMonoNerd/JetBrainsMonoNerdFontMono-Regular.woff2")
32+ format("woff2");
33+ font-weight: normal;
34+ font-style: normal;
35+}
36+
37+@font-face {
38+ font-family: "LilitaOne-Regular";
39+ src: url("/assets/fonts/LilitaOne/LilitaOne-Regular.ttf") format("truetype");
40+ font-weight: normal;
41+ font-style: normal;
42+}
43+
44+.fade-me-out.htmx-swapping {
45+ opacity: 0;
46+ transition: opacity 1s ease-out;
47+}
48+
49+/* View transition */
50+@keyframes fade-in {
51+ from {
52+ opacity: 0;
53+ }
54+}
55+
56+@keyframes fade-out {
57+ to {
58+ opacity: 0;
59+ }
60+}
61+
62+@keyframes slide-from-right {
63+ from {
64+ transform: translateX(90px);
65+ }
66+}
67+
68+@keyframes slide-to-left {
69+ to {
70+ transform: translateX(-90px);
71+ }
72+}
73+
74+.slide-it {
75+ view-transition-name: slide-it;
76+}
77+
78+::view-transition-old(slide-it) {
79+ animation: 180ms cubic-bezier(0.4, 0, 1, 1) both fade-out,
80+ 600ms cubic-bezier(0.4, 0, 0.2, 1) both slide-to-left;
81+}
82+::view-transition-new(slide-it) {
83+ animation: 420ms cubic-bezier(0, 0, 0.2, 1) 90ms both fade-in,
84+ 600ms cubic-bezier(0.4, 0, 0.2, 1) both slide-from-right;
85+}
86+
87+.gordon-title {
88+ font-family: "LilitaOne-Regular", sans-serif;
89+
90+}
91+
92+.IBMPlexSans {
93+ font-family: "IBMPlexSans-Regular", sans-serif;
94+}
95+
96+.circle-shadow {
97+ width: 100%;
98+ position: relative;
99+}
100+
101+.circle-shadow::after {
102+ position: absolute;
103+ width: 50%;
104+ height: 0.4rem;
105+ margin: auto;
106+ background: rgba(0, 0, 0, 0.1);
107+ border-radius: 50%;
108+ z-index: -1;
109+ bottom: 2%;
110+ content: "";
111+ box-shadow: 0 0 1px 0.3rem rgba(0, 0, 0, 0.1);
112+}
113+
114+.iconoir {
115+ margin-right: 8px;
116+}
A internal/webui/public/assets/css/tailwind.css +1046 -0
@@ -0,0 +1,1046 @@
1+/**
2+ * Path: internal/ui/public/assets/css/custom.css
3+ *
4+ * @format
5+ */
6+
7+/* Embeded path : assets/css/cutsom.css */
8+
9+/*! tailwindcss v3.3.3 | MIT License | https://tailwindcss.com
10+ */
11+
12+/*
13+1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4)
14+2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116)
15+*/
16+
17+*,
18+::before,
19+::after {
20+ box-sizing: border-box;
21+ /* 1 */
22+ border-width: 0;
23+ /* 2 */
24+ border-style: solid;
25+ /* 2 */
26+ border-color: #e5e7eb;
27+ /* 2 */
28+}
29+
30+::before,
31+::after {
32+ --tw-content: '';
33+}
34+
35+/*
36+1. Use a consistent sensible line-height in all browsers.
37+2. Prevent adjustments of font size after orientation changes in iOS.
38+3. Use a more readable tab size.
39+4. Use the user's configured `sans` font-family by default.
40+5. Use the user's configured `sans` font-feature-settings by default.
41+6. Use the user's configured `sans` font-variation-settings by default.
42+*/
43+
44+html {
45+ line-height: 1.5;
46+ /* 1 */
47+ -webkit-text-size-adjust: 100%;
48+ /* 2 */
49+ -moz-tab-size: 4;
50+ /* 3 */
51+ -o-tab-size: 4;
52+ tab-size: 4;
53+ /* 3 */
54+ font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
55+ /* 4 */
56+ font-feature-settings: normal;
57+ /* 5 */
58+ font-variation-settings: normal;
59+ /* 6 */
60+}
61+
62+/*
63+1. Remove the margin in all browsers.
64+2. Inherit line-height from `html` so users can set them as a class directly on the `html` element.
65+*/
66+
67+body {
68+ margin: 0;
69+ /* 1 */
70+ line-height: inherit;
71+ /* 2 */
72+}
73+
74+/*
75+1. Add the correct height in Firefox.
76+2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655)
77+3. Ensure horizontal rules are visible by default.
78+*/
79+
80+hr {
81+ height: 0;
82+ /* 1 */
83+ color: inherit;
84+ /* 2 */
85+ border-top-width: 1px;
86+ /* 3 */
87+}
88+
89+/*
90+Add the correct text decoration in Chrome, Edge, and Safari.
91+*/
92+
93+abbr:where([title]) {
94+ -webkit-text-decoration: underline dotted;
95+ text-decoration: underline dotted;
96+}
97+
98+/*
99+Remove the default font size and weight for headings.
100+*/
101+
102+h1,
103+h2,
104+h3,
105+h4,
106+h5,
107+h6 {
108+ font-size: inherit;
109+ font-weight: inherit;
110+}
111+
112+/*
113+Reset links to optimize for opt-in styling instead of opt-out.
114+*/
115+
116+a {
117+ color: inherit;
118+ text-decoration: inherit;
119+}
120+
121+/*
122+Add the correct font weight in Edge and Safari.
123+*/
124+
125+b,
126+strong {
127+ font-weight: bolder;
128+}
129+
130+/*
131+1. Use the user's configured `mono` font family by default.
132+2. Correct the odd `em` font sizing in all browsers.
133+*/
134+
135+code,
136+kbd,
137+samp,
138+pre {
139+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
140+ /* 1 */
141+ font-size: 1em;
142+ /* 2 */
143+}
144+
145+/*
146+Add the correct font size in all browsers.
147+*/
148+
149+small {
150+ font-size: 80%;
151+}
152+
153+/*
154+Prevent `sub` and `sup` elements from affecting the line height in all browsers.
155+*/
156+
157+sub,
158+sup {
159+ font-size: 75%;
160+ line-height: 0;
161+ position: relative;
162+ vertical-align: baseline;
163+}
164+
165+sub {
166+ bottom: -0.25em;
167+}
168+
169+sup {
170+ top: -0.5em;
171+}
172+
173+/*
174+1. Remove text indentation from table contents in Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=999088, https://bugs.webkit.org/show_bug.cgi?id=201297)
175+2. Correct table border color inheritance in all Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=935729, https://bugs.webkit.org/show_bug.cgi?id=195016)
176+3. Remove gaps between table borders by default.
177+*/
178+
179+table {
180+ text-indent: 0;
181+ /* 1 */
182+ border-color: inherit;
183+ /* 2 */
184+ border-collapse: collapse;
185+ /* 3 */
186+}
187+
188+/*
189+1. Change the font styles in all browsers.
190+2. Remove the margin in Firefox and Safari.
191+3. Remove default padding in all browsers.
192+*/
193+
194+button,
195+input,
196+optgroup,
197+select,
198+textarea {
199+ font-family: inherit;
200+ /* 1 */
201+ font-feature-settings: inherit;
202+ /* 1 */
203+ font-variation-settings: inherit;
204+ /* 1 */
205+ font-size: 100%;
206+ /* 1 */
207+ font-weight: inherit;
208+ /* 1 */
209+ line-height: inherit;
210+ /* 1 */
211+ color: inherit;
212+ /* 1 */
213+ margin: 0;
214+ /* 2 */
215+ padding: 0;
216+ /* 3 */
217+}
218+
219+/*
220+Remove the inheritance of text transform in Edge and Firefox.
221+*/
222+
223+button,
224+select {
225+ text-transform: none;
226+}
227+
228+/*
229+1. Correct the inability to style clickable types in iOS and Safari.
230+2. Remove default button styles.
231+*/
232+
233+button,
234+[type='button'],
235+[type='reset'],
236+[type='submit'] {
237+ -webkit-appearance: button;
238+ /* 1 */
239+ background-color: transparent;
240+ /* 2 */
241+ background-image: none;
242+ /* 2 */
243+}
244+
245+/*
246+Use the modern Firefox focus style for all focusable elements.
247+*/
248+
249+:-moz-focusring {
250+ outline: auto;
251+}
252+
253+/*
254+Remove the additional `:invalid` styles in Firefox. (https://github.com/mozilla/gecko-dev/blob/2f9eacd9d3d995c937b4251a5557d95d494c9be1/layout/style/res/forms.css#L728-L737)
255+*/
256+
257+:-moz-ui-invalid {
258+ box-shadow: none;
259+}
260+
261+/*
262+Add the correct vertical alignment in Chrome and Firefox.
263+*/
264+
265+progress {
266+ vertical-align: baseline;
267+}
268+
269+/*
270+Correct the cursor style of increment and decrement buttons in Safari.
271+*/
272+
273+::-webkit-inner-spin-button,
274+::-webkit-outer-spin-button {
275+ height: auto;
276+}
277+
278+/*
279+1. Correct the odd appearance in Chrome and Safari.
280+2. Correct the outline style in Safari.
281+*/
282+
283+[type='search'] {
284+ -webkit-appearance: textfield;
285+ /* 1 */
286+ outline-offset: -2px;
287+ /* 2 */
288+}
289+
290+/*
291+Remove the inner padding in Chrome and Safari on macOS.
292+*/
293+
294+::-webkit-search-decoration {
295+ -webkit-appearance: none;
296+}
297+
298+/*
299+1. Correct the inability to style clickable types in iOS and Safari.
300+2. Change font properties to `inherit` in Safari.
301+*/
302+
303+::-webkit-file-upload-button {
304+ -webkit-appearance: button;
305+ /* 1 */
306+ font: inherit;
307+ /* 2 */
308+}
309+
310+/*
311+Add the correct display in Chrome and Safari.
312+*/
313+
314+summary {
315+ display: list-item;
316+}
317+
318+/*
319+Removes the default spacing and border for appropriate elements.
320+*/
321+
322+blockquote,
323+dl,
324+dd,
325+h1,
326+h2,
327+h3,
328+h4,
329+h5,
330+h6,
331+hr,
332+figure,
333+p,
334+pre {
335+ margin: 0;
336+}
337+
338+fieldset {
339+ margin: 0;
340+ padding: 0;
341+}
342+
343+legend {
344+ padding: 0;
345+}
346+
347+ol,
348+ul,
349+menu {
350+ list-style: none;
351+ margin: 0;
352+ padding: 0;
353+}
354+
355+/*
356+Reset default styling for dialogs.
357+*/
358+
359+dialog {
360+ padding: 0;
361+}
362+
363+/*
364+Prevent resizing textareas horizontally by default.
365+*/
366+
367+textarea {
368+ resize: vertical;
369+}
370+
371+/*
372+1. Reset the default placeholder opacity in Firefox. (https://github.com/tailwindlabs/tailwindcss/issues/3300)
373+2. Set the default placeholder color to the user's configured gray 400 color.
374+*/
375+
376+input::-moz-placeholder, textarea::-moz-placeholder {
377+ opacity: 1;
378+ /* 1 */
379+ color: #9ca3af;
380+ /* 2 */
381+}
382+
383+input::placeholder,
384+textarea::placeholder {
385+ opacity: 1;
386+ /* 1 */
387+ color: #9ca3af;
388+ /* 2 */
389+}
390+
391+/*
392+Set the default cursor for buttons.
393+*/
394+
395+button,
396+[role="button"] {
397+ cursor: pointer;
398+}
399+
400+/*
401+Make sure disabled buttons don't get the pointer cursor.
402+*/
403+
404+:disabled {
405+ cursor: default;
406+}
407+
408+/*
409+1. Make replaced elements `display: block` by default. (https://github.com/mozdevs/cssremedy/issues/14)
410+2. Add `vertical-align: middle` to align replaced elements more sensibly by default. (https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210)
411+ This can trigger a poorly considered lint error in some tools but is included by design.
412+*/
413+
414+img,
415+svg,
416+video,
417+canvas,
418+audio,
419+iframe,
420+embed,
421+object {
422+ display: block;
423+ /* 1 */
424+ vertical-align: middle;
425+ /* 2 */
426+}
427+
428+/*
429+Constrain images and videos to the parent width and preserve their intrinsic aspect ratio. (https://github.com/mozdevs/cssremedy/issues/14)
430+*/
431+
432+img,
433+video {
434+ max-width: 100%;
435+ height: auto;
436+}
437+
438+/* Make elements with the HTML hidden attribute stay hidden by default */
439+
440+[hidden] {
441+ display: none;
442+}
443+
444+*, ::before, ::after {
445+ --tw-border-spacing-x: 0;
446+ --tw-border-spacing-y: 0;
447+ --tw-translate-x: 0;
448+ --tw-translate-y: 0;
449+ --tw-rotate: 0;
450+ --tw-skew-x: 0;
451+ --tw-skew-y: 0;
452+ --tw-scale-x: 1;
453+ --tw-scale-y: 1;
454+ --tw-pan-x: ;
455+ --tw-pan-y: ;
456+ --tw-pinch-zoom: ;
457+ --tw-scroll-snap-strictness: proximity;
458+ --tw-gradient-from-position: ;
459+ --tw-gradient-via-position: ;
460+ --tw-gradient-to-position: ;
461+ --tw-ordinal: ;
462+ --tw-slashed-zero: ;
463+ --tw-numeric-figure: ;
464+ --tw-numeric-spacing: ;
465+ --tw-numeric-fraction: ;
466+ --tw-ring-inset: ;
467+ --tw-ring-offset-width: 0px;
468+ --tw-ring-offset-color: #fff;
469+ --tw-ring-color: rgb(59 130 246 / 0.5);
470+ --tw-ring-offset-shadow: 0 0 #0000;
471+ --tw-ring-shadow: 0 0 #0000;
472+ --tw-shadow: 0 0 #0000;
473+ --tw-shadow-colored: 0 0 #0000;
474+ --tw-blur: ;
475+ --tw-brightness: ;
476+ --tw-contrast: ;
477+ --tw-grayscale: ;
478+ --tw-hue-rotate: ;
479+ --tw-invert: ;
480+ --tw-saturate: ;
481+ --tw-sepia: ;
482+ --tw-drop-shadow: ;
483+ --tw-backdrop-blur: ;
484+ --tw-backdrop-brightness: ;
485+ --tw-backdrop-contrast: ;
486+ --tw-backdrop-grayscale: ;
487+ --tw-backdrop-hue-rotate: ;
488+ --tw-backdrop-invert: ;
489+ --tw-backdrop-opacity: ;
490+ --tw-backdrop-saturate: ;
491+ --tw-backdrop-sepia: ;
492+}
493+
494+::backdrop {
495+ --tw-border-spacing-x: 0;
496+ --tw-border-spacing-y: 0;
497+ --tw-translate-x: 0;
498+ --tw-translate-y: 0;
499+ --tw-rotate: 0;
500+ --tw-skew-x: 0;
501+ --tw-skew-y: 0;
502+ --tw-scale-x: 1;
503+ --tw-scale-y: 1;
504+ --tw-pan-x: ;
505+ --tw-pan-y: ;
506+ --tw-pinch-zoom: ;
507+ --tw-scroll-snap-strictness: proximity;
508+ --tw-gradient-from-position: ;
509+ --tw-gradient-via-position: ;
510+ --tw-gradient-to-position: ;
511+ --tw-ordinal: ;
512+ --tw-slashed-zero: ;
513+ --tw-numeric-figure: ;
514+ --tw-numeric-spacing: ;
515+ --tw-numeric-fraction: ;
516+ --tw-ring-inset: ;
517+ --tw-ring-offset-width: 0px;
518+ --tw-ring-offset-color: #fff;
519+ --tw-ring-color: rgb(59 130 246 / 0.5);
520+ --tw-ring-offset-shadow: 0 0 #0000;
521+ --tw-ring-shadow: 0 0 #0000;
522+ --tw-shadow: 0 0 #0000;
523+ --tw-shadow-colored: 0 0 #0000;
524+ --tw-blur: ;
525+ --tw-brightness: ;
526+ --tw-contrast: ;
527+ --tw-grayscale: ;
528+ --tw-hue-rotate: ;
529+ --tw-invert: ;
530+ --tw-saturate: ;
531+ --tw-sepia: ;
532+ --tw-drop-shadow: ;
533+ --tw-backdrop-blur: ;
534+ --tw-backdrop-brightness: ;
535+ --tw-backdrop-contrast: ;
536+ --tw-backdrop-grayscale: ;
537+ --tw-backdrop-hue-rotate: ;
538+ --tw-backdrop-invert: ;
539+ --tw-backdrop-opacity: ;
540+ --tw-backdrop-saturate: ;
541+ --tw-backdrop-sepia: ;
542+}
543+
544+.my-2 {
545+ margin-top: 0.5rem;
546+ margin-bottom: 0.5rem;
547+}
548+
549+.mb-4 {
550+ margin-bottom: 1rem;
551+}
552+
553+.ml-2 {
554+ margin-left: 0.5rem;
555+}
556+
557+.ml-4 {
558+ margin-left: 1rem;
559+}
560+
561+.mr-2 {
562+ margin-right: 0.5rem;
563+}
564+
565+.mt-4 {
566+ margin-top: 1rem;
567+}
568+
569+.flex {
570+ display: flex;
571+}
572+
573+.h-10 {
574+ height: 2.5rem;
575+}
576+
577+.h-24 {
578+ height: 6rem;
579+}
580+
581+.h-32 {
582+ height: 8rem;
583+}
584+
585+.h-44 {
586+ height: 11rem;
587+}
588+
589+.h-64 {
590+ height: 16rem;
591+}
592+
593+.h-full {
594+ height: 100%;
595+}
596+
597+.w-1\/5 {
598+ width: 20%;
599+}
600+
601+.w-2\/6 {
602+ width: 33.333333%;
603+}
604+
605+.w-4\/6 {
606+ width: 66.666667%;
607+}
608+
609+.w-72 {
610+ width: 18rem;
611+}
612+
613+.w-full {
614+ width: 100%;
615+}
616+
617+.w-2\/3 {
618+ width: 66.666667%;
619+}
620+
621+.w-screen {
622+ width: 100vw;
623+}
624+
625+.w-96 {
626+ width: 24rem;
627+}
628+
629+.flex-1 {
630+ flex: 1 1 0%;
631+}
632+
633+.flex-grow {
634+ flex-grow: 1;
635+}
636+
637+.flex-row {
638+ flex-direction: row;
639+}
640+
641+.flex-col {
642+ flex-direction: column;
643+}
644+
645+.items-center {
646+ align-items: center;
647+}
648+
649+.justify-end {
650+ justify-content: flex-end;
651+}
652+
653+.justify-center {
654+ justify-content: center;
655+}
656+
657+.justify-between {
658+ justify-content: space-between;
659+}
660+
661+.justify-items-center {
662+ justify-items: center;
663+}
664+
665+.space-x-4 > :not([hidden]) ~ :not([hidden]) {
666+ --tw-space-x-reverse: 0;
667+ margin-right: calc(1rem * var(--tw-space-x-reverse));
668+ margin-left: calc(1rem * calc(1 - var(--tw-space-x-reverse)));
669+}
670+
671+.space-y-2 > :not([hidden]) ~ :not([hidden]) {
672+ --tw-space-y-reverse: 0;
673+ margin-top: calc(0.5rem * calc(1 - var(--tw-space-y-reverse)));
674+ margin-bottom: calc(0.5rem * var(--tw-space-y-reverse));
675+}
676+
677+.space-y-4 > :not([hidden]) ~ :not([hidden]) {
678+ --tw-space-y-reverse: 0;
679+ margin-top: calc(1rem * calc(1 - var(--tw-space-y-reverse)));
680+ margin-bottom: calc(1rem * var(--tw-space-y-reverse));
681+}
682+
683+.space-x-3 > :not([hidden]) ~ :not([hidden]) {
684+ --tw-space-x-reverse: 0;
685+ margin-right: calc(0.75rem * var(--tw-space-x-reverse));
686+ margin-left: calc(0.75rem * calc(1 - var(--tw-space-x-reverse)));
687+}
688+
689+.space-y-3 > :not([hidden]) ~ :not([hidden]) {
690+ --tw-space-y-reverse: 0;
691+ margin-top: calc(0.75rem * calc(1 - var(--tw-space-y-reverse)));
692+ margin-bottom: calc(0.75rem * var(--tw-space-y-reverse));
693+}
694+
695+.overflow-y-scroll {
696+ overflow-y: scroll;
697+}
698+
699+.rounded-lg {
700+ border-radius: 0.5rem;
701+}
702+
703+.rounded-md {
704+ border-radius: 0.375rem;
705+}
706+
707+.rounded-sm {
708+ border-radius: 0.125rem;
709+}
710+
711+.border {
712+ border-width: 1px;
713+}
714+
715+.border-gray-300 {
716+ --tw-border-opacity: 1;
717+ border-color: rgb(209 213 219 / var(--tw-border-opacity));
718+}
719+
720+.bg-gordonmascot-lblue {
721+ --tw-bg-opacity: 1;
722+ background-color: rgb(0 123 192 / var(--tw-bg-opacity));
723+}
724+
725+.bg-gordonmascot-mblue {
726+ --tw-bg-opacity: 1;
727+ background-color: rgb(0 82 147 / var(--tw-bg-opacity));
728+}
729+
730+.bg-gray-300 {
731+ --tw-bg-opacity: 1;
732+ background-color: rgb(209 213 219 / var(--tw-bg-opacity));
733+}
734+
735+.bg-transparent {
736+ background-color: transparent;
737+}
738+
739+.bg-white {
740+ --tw-bg-opacity: 1;
741+ background-color: rgb(255 255 255 / var(--tw-bg-opacity));
742+}
743+
744+.bg-zinc-200 {
745+ --tw-bg-opacity: 1;
746+ background-color: rgb(228 228 231 / var(--tw-bg-opacity));
747+}
748+
749+.bg-gordonmascot-hblue {
750+ --tw-bg-opacity: 1;
751+ background-color: rgb(1 30 92 / var(--tw-bg-opacity));
752+}
753+
754+.bg-zinc-400 {
755+ --tw-bg-opacity: 1;
756+ background-color: rgb(161 161 170 / var(--tw-bg-opacity));
757+}
758+
759+.p-4 {
760+ padding: 1rem;
761+}
762+
763+.p-2 {
764+ padding: 0.5rem;
765+}
766+
767+.px-2 {
768+ padding-left: 0.5rem;
769+ padding-right: 0.5rem;
770+}
771+
772+.px-6 {
773+ padding-left: 1.5rem;
774+ padding-right: 1.5rem;
775+}
776+
777+.py-2 {
778+ padding-top: 0.5rem;
779+ padding-bottom: 0.5rem;
780+}
781+
782+.px-4 {
783+ padding-left: 1rem;
784+ padding-right: 1rem;
785+}
786+
787+.text-2xl {
788+ font-size: 1.5rem;
789+ line-height: 2rem;
790+}
791+
792+.text-5xl {
793+ font-size: 3rem;
794+ line-height: 1;
795+}
796+
797+.text-lg {
798+ font-size: 1.125rem;
799+ line-height: 1.75rem;
800+}
801+
802+.text-sm {
803+ font-size: 0.875rem;
804+ line-height: 1.25rem;
805+}
806+
807+.text-xl {
808+ font-size: 1.25rem;
809+ line-height: 1.75rem;
810+}
811+
812+.font-semibold {
813+ font-weight: 600;
814+}
815+
816+.tracking-tighter {
817+ letter-spacing: -0.05em;
818+}
819+
820+.text-gordonmascot-hblue {
821+ --tw-text-opacity: 1;
822+ color: rgb(1 30 92 / var(--tw-text-opacity));
823+}
824+
825+.text-gordonmascot-mblue {
826+ --tw-text-opacity: 1;
827+ color: rgb(0 82 147 / var(--tw-text-opacity));
828+}
829+
830+.text-gray-100 {
831+ --tw-text-opacity: 1;
832+ color: rgb(243 244 246 / var(--tw-text-opacity));
833+}
834+
835+.text-gray-800 {
836+ --tw-text-opacity: 1;
837+ color: rgb(31 41 55 / var(--tw-text-opacity));
838+}
839+
840+.text-slate-400 {
841+ --tw-text-opacity: 1;
842+ color: rgb(148 163 184 / var(--tw-text-opacity));
843+}
844+
845+.text-slate-100 {
846+ --tw-text-opacity: 1;
847+ color: rgb(241 245 249 / var(--tw-text-opacity));
848+}
849+
850+.shadow {
851+ --tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
852+ --tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);
853+ box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
854+}
855+
856+.outline-none {
857+ outline: 2px solid transparent;
858+ outline-offset: 2px;
859+}
860+
861+/* Import IBM Plex Fonts */
862+
863+@font-face {
864+ font-family: "IBMPlexSans-Bold";
865+
866+ src: url("/assets/fonts/IBMPlex/IBMPlexSans-Bold.woff2") format("woff2");
867+
868+ font-weight: bold;
869+
870+ font-style: normal;
871+}
872+
873+@font-face {
874+ font-family: "IBMPlexSans-Regular";
875+
876+ src: url("/assets/fonts/IBMPlex/IBMPlexSans-Regular.woff2") format("woff2");
877+
878+ font-weight: normal;
879+
880+ font-style: normal;
881+}
882+
883+/* Import Jetbrains Mono Nerd Font */
884+
885+@font-face {
886+ font-family: "JetBrainsMono-Nerd-Font-Regular";
887+
888+ src: url("/assets/fonts/JetBrainsMonoNerd/JetBrainsMonoNerdFontMono-Regular.woff2")
889+ format("woff2");
890+
891+ font-weight: normal;
892+
893+ font-style: normal;
894+}
895+
896+@font-face {
897+ font-family: "LilitaOne-Regular";
898+
899+ src: url("/assets/fonts/LilitaOne/LilitaOne-Regular.ttf") format("truetype");
900+
901+ font-weight: normal;
902+
903+ font-style: normal;
904+}
905+
906+.fade-me-out.htmx-swapping {
907+ opacity: 0;
908+ transition: opacity 1s ease-out;
909+}
910+
911+/* View transition */
912+
913+@keyframes fade-in {
914+ from {
915+ opacity: 0;
916+ }
917+}
918+
919+@keyframes fade-out {
920+ to {
921+ opacity: 0;
922+ }
923+}
924+
925+@keyframes slide-from-right {
926+ from {
927+ transform: translateX(90px);
928+ }
929+}
930+
931+@keyframes slide-to-left {
932+ to {
933+ transform: translateX(-90px);
934+ }
935+}
936+
937+.slide-it {
938+ view-transition-name: slide-it;
939+}
940+
941+::view-transition-old(slide-it) {
942+ animation: 180ms cubic-bezier(0.4, 0, 1, 1) both fade-out,
943+ 600ms cubic-bezier(0.4, 0, 0.2, 1) both slide-to-left;
944+}
945+
946+::view-transition-new(slide-it) {
947+ animation: 420ms cubic-bezier(0, 0, 0.2, 1) 90ms both fade-in,
948+ 600ms cubic-bezier(0.4, 0, 0.2, 1) both slide-from-right;
949+}
950+
951+.gordon-title {
952+ font-family: "LilitaOne-Regular", sans-serif;
953+}
954+
955+.IBMPlexSans {
956+ font-family: "IBMPlexSans-Regular", sans-serif;
957+}
958+
959+.circle-shadow {
960+ width: 100%;
961+ position: relative;
962+}
963+
964+.circle-shadow::after {
965+ position: absolute;
966+ width: 50%;
967+ height: 0.4rem;
968+ margin: auto;
969+ background: rgba(0, 0, 0, 0.1);
970+ border-radius: 50%;
971+ z-index: -1;
972+ bottom: 2%;
973+ content: "";
974+ box-shadow: 0 0 1px 0.3rem rgba(0, 0, 0, 0.1);
975+}
976+
977+.iconoir {
978+ margin-right: 8px;
979+}
980+
981+@media (min-width: 640px) {
982+ .sm\:h-24 {
983+ height: 6rem;
984+ }
985+}
986+
987+@media (min-width: 768px) {
988+ .md\:w-1\/2 {
989+ width: 50%;
990+ }
991+
992+ .md\:flex-row {
993+ flex-direction: row;
994+ }
995+
996+ .md\:space-y-6 > :not([hidden]) ~ :not([hidden]) {
997+ --tw-space-y-reverse: 0;
998+ margin-top: calc(1.5rem * calc(1 - var(--tw-space-y-reverse)));
999+ margin-bottom: calc(1.5rem * var(--tw-space-y-reverse));
1000+ }
1001+
1002+ .md\:p-8 {
1003+ padding: 2rem;
1004+ }
1005+
1006+ .md\:py-8 {
1007+ padding-top: 2rem;
1008+ padding-bottom: 2rem;
1009+ }
1010+
1011+ .md\:pl-4 {
1012+ padding-left: 1rem;
1013+ }
1014+
1015+ .md\:pt-10 {
1016+ padding-top: 2.5rem;
1017+ }
1018+
1019+ .md\:text-2xl {
1020+ font-size: 1.5rem;
1021+ line-height: 2rem;
1022+ }
1023+
1024+ .md\:text-3xl {
1025+ font-size: 1.875rem;
1026+ line-height: 2.25rem;
1027+ }
1028+}
1029+
1030+@media (min-width: 1024px) {
1031+ .lg\:text-4xl {
1032+ font-size: 2.25rem;
1033+ line-height: 2.5rem;
1034+ }
1035+}
1036+
1037+@media (min-width: 1280px) {
1038+ .xl\:h-48 {
1039+ height: 12rem;
1040+ }
1041+
1042+ .xl\:text-5xl {
1043+ font-size: 3rem;
1044+ line-height: 1;
1045+ }
1046+}
@@ -0,0 +1,1046 @@
1+/**
2+ * Path: internal/ui/public/assets/css/custom.css
3+ *
4+ * @format
5+ */
6+
7+/* Embeded path : assets/css/cutsom.css */
8+
9+/*! tailwindcss v3.3.3 | MIT License | https://tailwindcss.com
10+ */
11+
12+/*
13+1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4)
14+2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116)
15+*/
16+
17+*,
18+::before,
19+::after {
20+ box-sizing: border-box;
21+ /* 1 */
22+ border-width: 0;
23+ /* 2 */
24+ border-style: solid;
25+ /* 2 */
26+ border-color: #e5e7eb;
27+ /* 2 */
28+}
29+
30+::before,
31+::after {
32+ --tw-content: '';
33+}
34+
35+/*
36+1. Use a consistent sensible line-height in all browsers.
37+2. Prevent adjustments of font size after orientation changes in iOS.
38+3. Use a more readable tab size.
39+4. Use the user's configured `sans` font-family by default.
40+5. Use the user's configured `sans` font-feature-settings by default.
41+6. Use the user's configured `sans` font-variation-settings by default.
42+*/
43+
44+html {
45+ line-height: 1.5;
46+ /* 1 */
47+ -webkit-text-size-adjust: 100%;
48+ /* 2 */
49+ -moz-tab-size: 4;
50+ /* 3 */
51+ -o-tab-size: 4;
52+ tab-size: 4;
53+ /* 3 */
54+ font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
55+ /* 4 */
56+ font-feature-settings: normal;
57+ /* 5 */
58+ font-variation-settings: normal;
59+ /* 6 */
60+}
61+
62+/*
63+1. Remove the margin in all browsers.
64+2. Inherit line-height from `html` so users can set them as a class directly on the `html` element.
65+*/
66+
67+body {
68+ margin: 0;
69+ /* 1 */
70+ line-height: inherit;
71+ /* 2 */
72+}
73+
74+/*
75+1. Add the correct height in Firefox.
76+2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655)
77+3. Ensure horizontal rules are visible by default.
78+*/
79+
80+hr {
81+ height: 0;
82+ /* 1 */
83+ color: inherit;
84+ /* 2 */
85+ border-top-width: 1px;
86+ /* 3 */
87+}
88+
89+/*
90+Add the correct text decoration in Chrome, Edge, and Safari.
91+*/
92+
93+abbr:where([title]) {
94+ -webkit-text-decoration: underline dotted;
95+ text-decoration: underline dotted;
96+}
97+
98+/*
99+Remove the default font size and weight for headings.
100+*/
101+
102+h1,
103+h2,
104+h3,
105+h4,
106+h5,
107+h6 {
108+ font-size: inherit;
109+ font-weight: inherit;
110+}
111+
112+/*
113+Reset links to optimize for opt-in styling instead of opt-out.
114+*/
115+
116+a {
117+ color: inherit;
118+ text-decoration: inherit;
119+}
120+
121+/*
122+Add the correct font weight in Edge and Safari.
123+*/
124+
125+b,
126+strong {
127+ font-weight: bolder;
128+}
129+
130+/*
131+1. Use the user's configured `mono` font family by default.
132+2. Correct the odd `em` font sizing in all browsers.
133+*/
134+
135+code,
136+kbd,
137+samp,
138+pre {
139+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
140+ /* 1 */
141+ font-size: 1em;
142+ /* 2 */
143+}
144+
145+/*
146+Add the correct font size in all browsers.
147+*/
148+
149+small {
150+ font-size: 80%;
151+}
152+
153+/*
154+Prevent `sub` and `sup` elements from affecting the line height in all browsers.
155+*/
156+
157+sub,
158+sup {
159+ font-size: 75%;
160+ line-height: 0;
161+ position: relative;
162+ vertical-align: baseline;
163+}
164+
165+sub {
166+ bottom: -0.25em;
167+}
168+
169+sup {
170+ top: -0.5em;
171+}
172+
173+/*
174+1. Remove text indentation from table contents in Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=999088, https://bugs.webkit.org/show_bug.cgi?id=201297)
175+2. Correct table border color inheritance in all Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=935729, https://bugs.webkit.org/show_bug.cgi?id=195016)
176+3. Remove gaps between table borders by default.
177+*/
178+
179+table {
180+ text-indent: 0;
181+ /* 1 */
182+ border-color: inherit;
183+ /* 2 */
184+ border-collapse: collapse;
185+ /* 3 */
186+}
187+
188+/*
189+1. Change the font styles in all browsers.
190+2. Remove the margin in Firefox and Safari.
191+3. Remove default padding in all browsers.
192+*/
193+
194+button,
195+input,
196+optgroup,
197+select,
198+textarea {
199+ font-family: inherit;
200+ /* 1 */
201+ font-feature-settings: inherit;
202+ /* 1 */
203+ font-variation-settings: inherit;
204+ /* 1 */
205+ font-size: 100%;
206+ /* 1 */
207+ font-weight: inherit;
208+ /* 1 */
209+ line-height: inherit;
210+ /* 1 */
211+ color: inherit;
212+ /* 1 */
213+ margin: 0;
214+ /* 2 */
215+ padding: 0;
216+ /* 3 */
217+}
218+
219+/*
220+Remove the inheritance of text transform in Edge and Firefox.
221+*/
222+
223+button,
224+select {
225+ text-transform: none;
226+}
227+
228+/*
229+1. Correct the inability to style clickable types in iOS and Safari.
230+2. Remove default button styles.
231+*/
232+
233+button,
234+[type='button'],
235+[type='reset'],
236+[type='submit'] {
237+ -webkit-appearance: button;
238+ /* 1 */
239+ background-color: transparent;
240+ /* 2 */
241+ background-image: none;
242+ /* 2 */
243+}
244+
245+/*
246+Use the modern Firefox focus style for all focusable elements.
247+*/
248+
249+:-moz-focusring {
250+ outline: auto;
251+}
252+
253+/*
254+Remove the additional `:invalid` styles in Firefox. (https://github.com/mozilla/gecko-dev/blob/2f9eacd9d3d995c937b4251a5557d95d494c9be1/layout/style/res/forms.css#L728-L737)
255+*/
256+
257+:-moz-ui-invalid {
258+ box-shadow: none;
259+}
260+
261+/*
262+Add the correct vertical alignment in Chrome and Firefox.
263+*/
264+
265+progress {
266+ vertical-align: baseline;
267+}
268+
269+/*
270+Correct the cursor style of increment and decrement buttons in Safari.
271+*/
272+
273+::-webkit-inner-spin-button,
274+::-webkit-outer-spin-button {
275+ height: auto;
276+}
277+
278+/*
279+1. Correct the odd appearance in Chrome and Safari.
280+2. Correct the outline style in Safari.
281+*/
282+
283+[type='search'] {
284+ -webkit-appearance: textfield;
285+ /* 1 */
286+ outline-offset: -2px;
287+ /* 2 */
288+}
289+
290+/*
291+Remove the inner padding in Chrome and Safari on macOS.
292+*/
293+
294+::-webkit-search-decoration {
295+ -webkit-appearance: none;
296+}
297+
298+/*
299+1. Correct the inability to style clickable types in iOS and Safari.
300+2. Change font properties to `inherit` in Safari.
301+*/
302+
303+::-webkit-file-upload-button {
304+ -webkit-appearance: button;
305+ /* 1 */
306+ font: inherit;
307+ /* 2 */
308+}
309+
310+/*
311+Add the correct display in Chrome and Safari.
312+*/
313+
314+summary {
315+ display: list-item;
316+}
317+
318+/*
319+Removes the default spacing and border for appropriate elements.
320+*/
321+
322+blockquote,
323+dl,
324+dd,
325+h1,
326+h2,
327+h3,
328+h4,
329+h5,
330+h6,
331+hr,
332+figure,
333+p,
334+pre {
335+ margin: 0;
336+}
337+
338+fieldset {
339+ margin: 0;
340+ padding: 0;
341+}
342+
343+legend {
344+ padding: 0;
345+}
346+
347+ol,
348+ul,
349+menu {
350+ list-style: none;
351+ margin: 0;
352+ padding: 0;
353+}
354+
355+/*
356+Reset default styling for dialogs.
357+*/
358+
359+dialog {
360+ padding: 0;
361+}
362+
363+/*
364+Prevent resizing textareas horizontally by default.
365+*/
366+
367+textarea {
368+ resize: vertical;
369+}
370+
371+/*
372+1. Reset the default placeholder opacity in Firefox. (https://github.com/tailwindlabs/tailwindcss/issues/3300)
373+2. Set the default placeholder color to the user's configured gray 400 color.
374+*/
375+
376+input::-moz-placeholder, textarea::-moz-placeholder {
377+ opacity: 1;
378+ /* 1 */
379+ color: #9ca3af;
380+ /* 2 */
381+}
382+
383+input::placeholder,
384+textarea::placeholder {
385+ opacity: 1;
386+ /* 1 */
387+ color: #9ca3af;
388+ /* 2 */
389+}
390+
391+/*
392+Set the default cursor for buttons.
393+*/
394+
395+button,
396+[role="button"] {
397+ cursor: pointer;
398+}
399+
400+/*
401+Make sure disabled buttons don't get the pointer cursor.
402+*/
403+
404+:disabled {
405+ cursor: default;
406+}
407+
408+/*
409+1. Make replaced elements `display: block` by default. (https://github.com/mozdevs/cssremedy/issues/14)
410+2. Add `vertical-align: middle` to align replaced elements more sensibly by default. (https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210)
411+ This can trigger a poorly considered lint error in some tools but is included by design.
412+*/
413+
414+img,
415+svg,
416+video,
417+canvas,
418+audio,
419+iframe,
420+embed,
421+object {
422+ display: block;
423+ /* 1 */
424+ vertical-align: middle;
425+ /* 2 */
426+}
427+
428+/*
429+Constrain images and videos to the parent width and preserve their intrinsic aspect ratio. (https://github.com/mozdevs/cssremedy/issues/14)
430+*/
431+
432+img,
433+video {
434+ max-width: 100%;
435+ height: auto;
436+}
437+
438+/* Make elements with the HTML hidden attribute stay hidden by default */
439+
440+[hidden] {
441+ display: none;
442+}
443+
444+*, ::before, ::after {
445+ --tw-border-spacing-x: 0;
446+ --tw-border-spacing-y: 0;
447+ --tw-translate-x: 0;
448+ --tw-translate-y: 0;
449+ --tw-rotate: 0;
450+ --tw-skew-x: 0;
451+ --tw-skew-y: 0;
452+ --tw-scale-x: 1;
453+ --tw-scale-y: 1;
454+ --tw-pan-x: ;
455+ --tw-pan-y: ;
456+ --tw-pinch-zoom: ;
457+ --tw-scroll-snap-strictness: proximity;
458+ --tw-gradient-from-position: ;
459+ --tw-gradient-via-position: ;
460+ --tw-gradient-to-position: ;
461+ --tw-ordinal: ;
462+ --tw-slashed-zero: ;
463+ --tw-numeric-figure: ;
464+ --tw-numeric-spacing: ;
465+ --tw-numeric-fraction: ;
466+ --tw-ring-inset: ;
467+ --tw-ring-offset-width: 0px;
468+ --tw-ring-offset-color: #fff;
469+ --tw-ring-color: rgb(59 130 246 / 0.5);
470+ --tw-ring-offset-shadow: 0 0 #0000;
471+ --tw-ring-shadow: 0 0 #0000;
472+ --tw-shadow: 0 0 #0000;
473+ --tw-shadow-colored: 0 0 #0000;
474+ --tw-blur: ;
475+ --tw-brightness: ;
476+ --tw-contrast: ;
477+ --tw-grayscale: ;
478+ --tw-hue-rotate: ;
479+ --tw-invert: ;
480+ --tw-saturate: ;
481+ --tw-sepia: ;
482+ --tw-drop-shadow: ;
483+ --tw-backdrop-blur: ;
484+ --tw-backdrop-brightness: ;
485+ --tw-backdrop-contrast: ;
486+ --tw-backdrop-grayscale: ;
487+ --tw-backdrop-hue-rotate: ;
488+ --tw-backdrop-invert: ;
489+ --tw-backdrop-opacity: ;
490+ --tw-backdrop-saturate: ;
491+ --tw-backdrop-sepia: ;
492+}
493+
494+::backdrop {
495+ --tw-border-spacing-x: 0;
496+ --tw-border-spacing-y: 0;
497+ --tw-translate-x: 0;
498+ --tw-translate-y: 0;
499+ --tw-rotate: 0;
500+ --tw-skew-x: 0;
501+ --tw-skew-y: 0;
502+ --tw-scale-x: 1;
503+ --tw-scale-y: 1;
504+ --tw-pan-x: ;
505+ --tw-pan-y: ;
506+ --tw-pinch-zoom: ;
507+ --tw-scroll-snap-strictness: proximity;
508+ --tw-gradient-from-position: ;
509+ --tw-gradient-via-position: ;
510+ --tw-gradient-to-position: ;
511+ --tw-ordinal: ;
512+ --tw-slashed-zero: ;
513+ --tw-numeric-figure: ;
514+ --tw-numeric-spacing: ;
515+ --tw-numeric-fraction: ;
516+ --tw-ring-inset: ;
517+ --tw-ring-offset-width: 0px;
518+ --tw-ring-offset-color: #fff;
519+ --tw-ring-color: rgb(59 130 246 / 0.5);
520+ --tw-ring-offset-shadow: 0 0 #0000;
521+ --tw-ring-shadow: 0 0 #0000;
522+ --tw-shadow: 0 0 #0000;
523+ --tw-shadow-colored: 0 0 #0000;
524+ --tw-blur: ;
525+ --tw-brightness: ;
526+ --tw-contrast: ;
527+ --tw-grayscale: ;
528+ --tw-hue-rotate: ;
529+ --tw-invert: ;
530+ --tw-saturate: ;
531+ --tw-sepia: ;
532+ --tw-drop-shadow: ;
533+ --tw-backdrop-blur: ;
534+ --tw-backdrop-brightness: ;
535+ --tw-backdrop-contrast: ;
536+ --tw-backdrop-grayscale: ;
537+ --tw-backdrop-hue-rotate: ;
538+ --tw-backdrop-invert: ;
539+ --tw-backdrop-opacity: ;
540+ --tw-backdrop-saturate: ;
541+ --tw-backdrop-sepia: ;
542+}
543+
544+.my-2 {
545+ margin-top: 0.5rem;
546+ margin-bottom: 0.5rem;
547+}
548+
549+.mb-4 {
550+ margin-bottom: 1rem;
551+}
552+
553+.ml-2 {
554+ margin-left: 0.5rem;
555+}
556+
557+.ml-4 {
558+ margin-left: 1rem;
559+}
560+
561+.mr-2 {
562+ margin-right: 0.5rem;
563+}
564+
565+.mt-4 {
566+ margin-top: 1rem;
567+}
568+
569+.flex {
570+ display: flex;
571+}
572+
573+.h-10 {
574+ height: 2.5rem;
575+}
576+
577+.h-24 {
578+ height: 6rem;
579+}
580+
581+.h-32 {
582+ height: 8rem;
583+}
584+
585+.h-44 {
586+ height: 11rem;
587+}
588+
589+.h-64 {
590+ height: 16rem;
591+}
592+
593+.h-full {
594+ height: 100%;
595+}
596+
597+.w-1\/5 {
598+ width: 20%;
599+}
600+
601+.w-2\/6 {
602+ width: 33.333333%;
603+}
604+
605+.w-4\/6 {
606+ width: 66.666667%;
607+}
608+
609+.w-72 {
610+ width: 18rem;
611+}
612+
613+.w-full {
614+ width: 100%;
615+}
616+
617+.w-2\/3 {
618+ width: 66.666667%;
619+}
620+
621+.w-screen {
622+ width: 100vw;
623+}
624+
625+.w-96 {
626+ width: 24rem;
627+}
628+
629+.flex-1 {
630+ flex: 1 1 0%;
631+}
632+
633+.flex-grow {
634+ flex-grow: 1;
635+}
636+
637+.flex-row {
638+ flex-direction: row;
639+}
640+
641+.flex-col {
642+ flex-direction: column;
643+}
644+
645+.items-center {
646+ align-items: center;
647+}
648+
649+.justify-end {
650+ justify-content: flex-end;
651+}
652+
653+.justify-center {
654+ justify-content: center;
655+}
656+
657+.justify-between {
658+ justify-content: space-between;
659+}
660+
661+.justify-items-center {
662+ justify-items: center;
663+}
664+
665+.space-x-4 > :not([hidden]) ~ :not([hidden]) {
666+ --tw-space-x-reverse: 0;
667+ margin-right: calc(1rem * var(--tw-space-x-reverse));
668+ margin-left: calc(1rem * calc(1 - var(--tw-space-x-reverse)));
669+}
670+
671+.space-y-2 > :not([hidden]) ~ :not([hidden]) {
672+ --tw-space-y-reverse: 0;
673+ margin-top: calc(0.5rem * calc(1 - var(--tw-space-y-reverse)));
674+ margin-bottom: calc(0.5rem * var(--tw-space-y-reverse));
675+}
676+
677+.space-y-4 > :not([hidden]) ~ :not([hidden]) {
678+ --tw-space-y-reverse: 0;
679+ margin-top: calc(1rem * calc(1 - var(--tw-space-y-reverse)));
680+ margin-bottom: calc(1rem * var(--tw-space-y-reverse));
681+}
682+
683+.space-x-3 > :not([hidden]) ~ :not([hidden]) {
684+ --tw-space-x-reverse: 0;
685+ margin-right: calc(0.75rem * var(--tw-space-x-reverse));
686+ margin-left: calc(0.75rem * calc(1 - var(--tw-space-x-reverse)));
687+}
688+
689+.space-y-3 > :not([hidden]) ~ :not([hidden]) {
690+ --tw-space-y-reverse: 0;
691+ margin-top: calc(0.75rem * calc(1 - var(--tw-space-y-reverse)));
692+ margin-bottom: calc(0.75rem * var(--tw-space-y-reverse));
693+}
694+
695+.overflow-y-scroll {
696+ overflow-y: scroll;
697+}
698+
699+.rounded-lg {
700+ border-radius: 0.5rem;
701+}
702+
703+.rounded-md {
704+ border-radius: 0.375rem;
705+}
706+
707+.rounded-sm {
708+ border-radius: 0.125rem;
709+}
710+
711+.border {
712+ border-width: 1px;
713+}
714+
715+.border-gray-300 {
716+ --tw-border-opacity: 1;
717+ border-color: rgb(209 213 219 / var(--tw-border-opacity));
718+}
719+
720+.bg-gordonmascot-lblue {
721+ --tw-bg-opacity: 1;
722+ background-color: rgb(0 123 192 / var(--tw-bg-opacity));
723+}
724+
725+.bg-gordonmascot-mblue {
726+ --tw-bg-opacity: 1;
727+ background-color: rgb(0 82 147 / var(--tw-bg-opacity));
728+}
729+
730+.bg-gray-300 {
731+ --tw-bg-opacity: 1;
732+ background-color: rgb(209 213 219 / var(--tw-bg-opacity));
733+}
734+
735+.bg-transparent {
736+ background-color: transparent;
737+}
738+
739+.bg-white {
740+ --tw-bg-opacity: 1;
741+ background-color: rgb(255 255 255 / var(--tw-bg-opacity));
742+}
743+
744+.bg-zinc-200 {
745+ --tw-bg-opacity: 1;
746+ background-color: rgb(228 228 231 / var(--tw-bg-opacity));
747+}
748+
749+.bg-gordonmascot-hblue {
750+ --tw-bg-opacity: 1;
751+ background-color: rgb(1 30 92 / var(--tw-bg-opacity));
752+}
753+
754+.bg-zinc-400 {
755+ --tw-bg-opacity: 1;
756+ background-color: rgb(161 161 170 / var(--tw-bg-opacity));
757+}
758+
759+.p-4 {
760+ padding: 1rem;
761+}
762+
763+.p-2 {
764+ padding: 0.5rem;
765+}
766+
767+.px-2 {
768+ padding-left: 0.5rem;
769+ padding-right: 0.5rem;
770+}
771+
772+.px-6 {
773+ padding-left: 1.5rem;
774+ padding-right: 1.5rem;
775+}
776+
777+.py-2 {
778+ padding-top: 0.5rem;
779+ padding-bottom: 0.5rem;
780+}
781+
782+.px-4 {
783+ padding-left: 1rem;
784+ padding-right: 1rem;
785+}
786+
787+.text-2xl {
788+ font-size: 1.5rem;
789+ line-height: 2rem;
790+}
791+
792+.text-5xl {
793+ font-size: 3rem;
794+ line-height: 1;
795+}
796+
797+.text-lg {
798+ font-size: 1.125rem;
799+ line-height: 1.75rem;
800+}
801+
802+.text-sm {
803+ font-size: 0.875rem;
804+ line-height: 1.25rem;
805+}
806+
807+.text-xl {
808+ font-size: 1.25rem;
809+ line-height: 1.75rem;
810+}
811+
812+.font-semibold {
813+ font-weight: 600;
814+}
815+
816+.tracking-tighter {
817+ letter-spacing: -0.05em;
818+}
819+
820+.text-gordonmascot-hblue {
821+ --tw-text-opacity: 1;
822+ color: rgb(1 30 92 / var(--tw-text-opacity));
823+}
824+
825+.text-gordonmascot-mblue {
826+ --tw-text-opacity: 1;
827+ color: rgb(0 82 147 / var(--tw-text-opacity));
828+}
829+
830+.text-gray-100 {
831+ --tw-text-opacity: 1;
832+ color: rgb(243 244 246 / var(--tw-text-opacity));
833+}
834+
835+.text-gray-800 {
836+ --tw-text-opacity: 1;
837+ color: rgb(31 41 55 / var(--tw-text-opacity));
838+}
839+
840+.text-slate-400 {
841+ --tw-text-opacity: 1;
842+ color: rgb(148 163 184 / var(--tw-text-opacity));
843+}
844+
845+.text-slate-100 {
846+ --tw-text-opacity: 1;
847+ color: rgb(241 245 249 / var(--tw-text-opacity));
848+}
849+
850+.shadow {
851+ --tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
852+ --tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);
853+ box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
854+}
855+
856+.outline-none {
857+ outline: 2px solid transparent;
858+ outline-offset: 2px;
859+}
860+
861+/* Import IBM Plex Fonts */
862+
863+@font-face {
864+ font-family: "IBMPlexSans-Bold";
865+
866+ src: url("/assets/fonts/IBMPlex/IBMPlexSans-Bold.woff2") format("woff2");
867+
868+ font-weight: bold;
869+
870+ font-style: normal;
871+}
872+
873+@font-face {
874+ font-family: "IBMPlexSans-Regular";
875+
876+ src: url("/assets/fonts/IBMPlex/IBMPlexSans-Regular.woff2") format("woff2");
877+
878+ font-weight: normal;
879+
880+ font-style: normal;
881+}
882+
883+/* Import Jetbrains Mono Nerd Font */
884+
885+@font-face {
886+ font-family: "JetBrainsMono-Nerd-Font-Regular";
887+
888+ src: url("/assets/fonts/JetBrainsMonoNerd/JetBrainsMonoNerdFontMono-Regular.woff2")
889+ format("woff2");
890+
891+ font-weight: normal;
892+
893+ font-style: normal;
894+}
895+
896+@font-face {
897+ font-family: "LilitaOne-Regular";
898+
899+ src: url("/assets/fonts/LilitaOne/LilitaOne-Regular.ttf") format("truetype");
900+
901+ font-weight: normal;
902+
903+ font-style: normal;
904+}
905+
906+.fade-me-out.htmx-swapping {
907+ opacity: 0;
908+ transition: opacity 1s ease-out;
909+}
910+
911+/* View transition */
912+
913+@keyframes fade-in {
914+ from {
915+ opacity: 0;
916+ }
917+}
918+
919+@keyframes fade-out {
920+ to {
921+ opacity: 0;
922+ }
923+}
924+
925+@keyframes slide-from-right {
926+ from {
927+ transform: translateX(90px);
928+ }
929+}
930+
931+@keyframes slide-to-left {
932+ to {
933+ transform: translateX(-90px);
934+ }
935+}
936+
937+.slide-it {
938+ view-transition-name: slide-it;
939+}
940+
941+::view-transition-old(slide-it) {
942+ animation: 180ms cubic-bezier(0.4, 0, 1, 1) both fade-out,
943+ 600ms cubic-bezier(0.4, 0, 0.2, 1) both slide-to-left;
944+}
945+
946+::view-transition-new(slide-it) {
947+ animation: 420ms cubic-bezier(0, 0, 0.2, 1) 90ms both fade-in,
948+ 600ms cubic-bezier(0.4, 0, 0.2, 1) both slide-from-right;
949+}
950+
951+.gordon-title {
952+ font-family: "LilitaOne-Regular", sans-serif;
953+}
954+
955+.IBMPlexSans {
956+ font-family: "IBMPlexSans-Regular", sans-serif;
957+}
958+
959+.circle-shadow {
960+ width: 100%;
961+ position: relative;
962+}
963+
964+.circle-shadow::after {
965+ position: absolute;
966+ width: 50%;
967+ height: 0.4rem;
968+ margin: auto;
969+ background: rgba(0, 0, 0, 0.1);
970+ border-radius: 50%;
971+ z-index: -1;
972+ bottom: 2%;
973+ content: "";
974+ box-shadow: 0 0 1px 0.3rem rgba(0, 0, 0, 0.1);
975+}
976+
977+.iconoir {
978+ margin-right: 8px;
979+}
980+
981+@media (min-width: 640px) {
982+ .sm\:h-24 {
983+ height: 6rem;
984+ }
985+}
986+
987+@media (min-width: 768px) {
988+ .md\:w-1\/2 {
989+ width: 50%;
990+ }
991+
992+ .md\:flex-row {
993+ flex-direction: row;
994+ }
995+
996+ .md\:space-y-6 > :not([hidden]) ~ :not([hidden]) {
997+ --tw-space-y-reverse: 0;
998+ margin-top: calc(1.5rem * calc(1 - var(--tw-space-y-reverse)));
999+ margin-bottom: calc(1.5rem * var(--tw-space-y-reverse));
1000+ }
1001+
1002+ .md\:p-8 {
1003+ padding: 2rem;
1004+ }
1005+
1006+ .md\:py-8 {
1007+ padding-top: 2rem;
1008+ padding-bottom: 2rem;
1009+ }
1010+
1011+ .md\:pl-4 {
1012+ padding-left: 1rem;
1013+ }
1014+
1015+ .md\:pt-10 {
1016+ padding-top: 2.5rem;
1017+ }
1018+
1019+ .md\:text-2xl {
1020+ font-size: 1.5rem;
1021+ line-height: 2rem;
1022+ }
1023+
1024+ .md\:text-3xl {
1025+ font-size: 1.875rem;
1026+ line-height: 2.25rem;
1027+ }
1028+}
1029+
1030+@media (min-width: 1024px) {
1031+ .lg\:text-4xl {
1032+ font-size: 2.25rem;
1033+ line-height: 2.5rem;
1034+ }
1035+}
1036+
1037+@media (min-width: 1280px) {
1038+ .xl\:h-48 {
1039+ height: 12rem;
1040+ }
1041+
1042+ .xl\:text-5xl {
1043+ font-size: 3rem;
1044+ line-height: 1;
1045+ }
1046+}
A internal/webui/public/assets/fonts/IBMPlex/IBMPlexSans-Bold.woff2 +0 -0 binary file: no text diff

binary file: no text diff

A internal/webui/public/assets/fonts/IBMPlex/IBMPlexSans-Light.woff2 +0 -0 binary file: no text diff

binary file: no text diff

A internal/webui/public/assets/fonts/IBMPlex/IBMPlexSans-Medium.woff2 +0 -0 binary file: no text diff

binary file: no text diff

A internal/webui/public/assets/fonts/IBMPlex/IBMPlexSans-Regular.woff2 +0 -0 binary file: no text diff

binary file: no text diff

A internal/webui/public/assets/fonts/IBMPlex/IBMPlexSans-Thin.woff2 +0 -0 binary file: no text diff

binary file: no text diff

A internal/webui/public/assets/fonts/JetBrainsMonoNerd/JetBrainsMonoNerdFont-Bold.woff2 +0 -0 binary file: no text diff

binary file: no text diff

A internal/webui/public/assets/fonts/JetBrainsMonoNerd/JetBrainsMonoNerdFont-Regular.woff2 +0 -0 binary file: no text diff

binary file: no text diff

A internal/webui/public/assets/fonts/JetBrainsMonoNerd/JetBrainsMonoNerdFontMono-Regular.ttf +0 -0 binary file: no text diff

binary file: no text diff

A internal/webui/public/assets/fonts/LilitaOne/LilitaOne-Regular.ttf +0 -0 binary file: no text diff

binary file: no text diff

A internal/webui/public/assets/fonts/LilitaOne/LilitaOne-Regular.woff2 +0 -0 binary file: no text diff

binary file: no text diff

A internal/webui/public/assets/imgs/gordon-mascot-hq-trsp.png +0 -0 binary file: no text diff

binary file: no text diff

A internal/webui/public/assets/imgs/gordon-mascot-mq-trsp.png +0 -0 binary file: no text diff

binary file: no text diff

A internal/webui/public/assets/imgs/gordon-mascot.png +0 -0 binary file: no text diff

binary file: no text diff

A internal/webui/public/favicon-16x16.png +0 -0 binary file: no text diff

binary file: no text diff

A internal/webui/public/favicon-32x32.png +0 -0 binary file: no text diff

binary file: no text diff

A internal/webui/public/favicon.ico +0 -0 binary file: no text diff

binary file: no text diff

A internal/webui/public/libs/alpine.min.js +5 -0 generated file: collapsed
A internal/webui/public/libs/chart.js +20 -0 too large to show in the browser

too large to show in the browser view raw

A internal/webui/public/libs/htmx-sse.js +322 -0
@@ -0,0 +1,322 @@
1+/*
2+Server Sent Events Extension
3+============================
4+This extension adds support for Server Sent Events to htmx. See /www/extensions/sse.md for usage instructions.
5+
6+*/
7+
8+(function(){
9+
10+ /** @type {import("../htmx").HtmxInternalApi} */
11+ var api;
12+
13+ htmx.defineExtension("sse", {
14+
15+ /**
16+ * Init saves the provided reference to the internal HTMX API.
17+ *
18+ * @param {import("../htmx").HtmxInternalApi} api
19+ * @returns void
20+ */
21+ init: function(apiRef) {
22+ // store a reference to the internal API.
23+ api = apiRef;
24+
25+ // set a function in the public API for creating new EventSource objects
26+ if (htmx.createEventSource == undefined) {
27+ htmx.createEventSource = createEventSource;
28+ }
29+ },
30+
31+ /**
32+ * onEvent handles all events passed to this extension.
33+ *
34+ * @param {string} name
35+ * @param {Event} evt
36+ * @returns void
37+ */
38+ onEvent: function(name, evt) {
39+
40+ switch (name) {
41+
42+ // Try to remove remove an EventSource when elements are removed
43+ case "htmx:beforeCleanupElement":
44+ var internalData = api.getInternalData(evt.target)
45+ if (internalData.sseEventSource) {
46+ internalData.sseEventSource.close();
47+ }
48+ return;
49+
50+ // Try to create EventSources when elements are processed
51+ case "htmx:afterProcessNode":
52+ createEventSourceOnElement(evt.target);
53+ }
54+ }
55+ });
56+
57+ ///////////////////////////////////////////////
58+ // HELPER FUNCTIONS
59+ ///////////////////////////////////////////////
60+
61+
62+ /**
63+ * createEventSource is the default method for creating new EventSource objects.
64+ * it is hoisted into htmx.config.createEventSource to be overridden by the user, if needed.
65+ *
66+ * @param {string} url
67+ * @returns EventSource
68+ */
69+ function createEventSource(url) {
70+ return new EventSource(url, {withCredentials:true});
71+ }
72+
73+ function splitOnWhitespace(trigger) {
74+ return trigger.trim().split(/\s+/);
75+ }
76+
77+ function getLegacySSEURL(elt) {
78+ var legacySSEValue = api.getAttributeValue(elt, "hx-sse");
79+ if (legacySSEValue) {
80+ var values = splitOnWhitespace(legacySSEValue);
81+ for (var i = 0; i < values.length; i++) {
82+ var value = values[i].split(/:(.+)/);
83+ if (value[0] === "connect") {
84+ return value[1];
85+ }
86+ }
87+ }
88+ }
89+
90+ function getLegacySSESwaps(elt) {
91+ var legacySSEValue = api.getAttributeValue(elt, "hx-sse");
92+ var returnArr = [];
93+ if (legacySSEValue) {
94+ var values = splitOnWhitespace(legacySSEValue);
95+ for (var i = 0; i < values.length; i++) {
96+ var value = values[i].split(/:(.+)/);
97+ if (value[0] === "swap") {
98+ returnArr.push(value[1]);
99+ }
100+ }
101+ }
102+ return returnArr;
103+ }
104+
105+ /**
106+ * createEventSourceOnElement creates a new EventSource connection on the provided element.
107+ * If a usable EventSource already exists, then it is returned. If not, then a new EventSource
108+ * is created and stored in the element's internalData.
109+ * @param {HTMLElement} elt
110+ * @param {number} retryCount
111+ * @returns {EventSource | null}
112+ */
113+ function createEventSourceOnElement(elt, retryCount) {
114+
115+ if (elt == null) {
116+ return null;
117+ }
118+
119+ var internalData = api.getInternalData(elt);
120+
121+ // get URL from element's attribute
122+ var sseURL = api.getAttributeValue(elt, "sse-connect");
123+
124+
125+ if (sseURL == undefined) {
126+ var legacyURL = getLegacySSEURL(elt)
127+ if (legacyURL) {
128+ sseURL = legacyURL;
129+ } else {
130+ return null;
131+ }
132+ }
133+
134+ // Connect to the EventSource
135+ var source = htmx.createEventSource(sseURL);
136+ internalData.sseEventSource = source;
137+
138+ // Create event handlers
139+ source.onerror = function (err) {
140+
141+ // Log an error event
142+ api.triggerErrorEvent(elt, "htmx:sseError", {error:err, source:source});
143+
144+ // If parent no longer exists in the document, then clean up this EventSource
145+ if (maybeCloseSSESource(elt)) {
146+ return;
147+ }
148+
149+ // Otherwise, try to reconnect the EventSource
150+ if (source.readyState === EventSource.CLOSED) {
151+ retryCount = retryCount || 0;
152+ var timeout = Math.random() * (2 ^ retryCount) * 500;
153+ window.setTimeout(function() {
154+ createEventSourceOnElement(elt, Math.min(7, retryCount+1));
155+ }, timeout);
156+ }
157+ };
158+
159+ source.onopen = function (evt) {
160+ api.triggerEvent(elt, "htmx:sseOpen", {source: source});
161+ }
162+
163+ // Add message handlers for every `sse-swap` attribute
164+ queryAttributeOnThisOrChildren(elt, "sse-swap").forEach(function(child) {
165+
166+ var sseSwapAttr = api.getAttributeValue(child, "sse-swap");
167+ if (sseSwapAttr) {
168+ var sseEventNames = sseSwapAttr.split(",");
169+ } else {
170+ var sseEventNames = getLegacySSESwaps(child);
171+ }
172+
173+ for (var i = 0 ; i < sseEventNames.length ; i++) {
174+ var sseEventName = sseEventNames[i].trim();
175+ var listener = function(event) {
176+
177+ // If the parent is missing then close SSE and remove listener
178+ if (maybeCloseSSESource(elt)) {
179+ source.removeEventListener(sseEventName, listener);
180+ return;
181+ }
182+
183+ // swap the response into the DOM and trigger a notification
184+ swap(child, event.data);
185+ api.triggerEvent(elt, "htmx:sseMessage", event);
186+ };
187+
188+ // Register the new listener
189+ api.getInternalData(elt).sseEventListener = listener;
190+ source.addEventListener(sseEventName, listener);
191+ }
192+ });
193+
194+ // Add message handlers for every `hx-trigger="sse:*"` attribute
195+ queryAttributeOnThisOrChildren(elt, "hx-trigger").forEach(function(child) {
196+
197+ var sseEventName = api.getAttributeValue(child, "hx-trigger");
198+ if (sseEventName == null) {
199+ return;
200+ }
201+
202+ // Only process hx-triggers for events with the "sse:" prefix
203+ if (sseEventName.slice(0, 4) != "sse:") {
204+ return;
205+ }
206+
207+ var listener = function(event) {
208+
209+ // If parent is missing, then close SSE and remove listener
210+ if (maybeCloseSSESource(elt)) {
211+ source.removeEventListener(sseEventName, listener);
212+ return;
213+ }
214+
215+ // Trigger events to be handled by the rest of htmx
216+ htmx.trigger(child, sseEventName, event);
217+ htmx.trigger(child, "htmx:sseMessage", event);
218+ }
219+
220+ // Register the new listener
221+ api.getInternalData(elt).sseEventListener = listener;
222+ source.addEventListener(sseEventName.slice(4), listener);
223+ });
224+ }
225+
226+ /**
227+ * maybeCloseSSESource confirms that the parent element still exists.
228+ * If not, then any associated SSE source is closed and the function returns true.
229+ *
230+ * @param {HTMLElement} elt
231+ * @returns boolean
232+ */
233+ function maybeCloseSSESource(elt) {
234+ if (!api.bodyContains(elt)) {
235+ var source = api.getInternalData(elt).sseEventSource;
236+ if (source != undefined) {
237+ source.close();
238+ // source = null
239+ return true;
240+ }
241+ }
242+ return false;
243+ }
244+
245+ /**
246+ * queryAttributeOnThisOrChildren returns all nodes that contain the requested attributeName, INCLUDING THE PROVIDED ROOT ELEMENT.
247+ *
248+ * @param {HTMLElement} elt
249+ * @param {string} attributeName
250+ */
251+ function queryAttributeOnThisOrChildren(elt, attributeName) {
252+
253+ var result = [];
254+
255+ // If the parent element also contains the requested attribute, then add it to the results too.
256+ if (api.hasAttribute(elt, attributeName) || api.hasAttribute(elt, "hx-sse")) {
257+ result.push(elt);
258+ }
259+
260+ // Search all child nodes that match the requested attribute
261+ elt.querySelectorAll("[" + attributeName + "], [data-" + attributeName + "], [hx-sse], [data-hx-sse]").forEach(function(node) {
262+ result.push(node);
263+ });
264+
265+ return result;
266+ }
267+
268+ /**
269+ * @param {HTMLElement} elt
270+ * @param {string} content
271+ */
272+ function swap(elt, content) {
273+
274+ api.withExtensions(elt, function(extension) {
275+ content = extension.transformResponse(content, null, elt);
276+ });
277+
278+ var swapSpec = api.getSwapSpecification(elt);
279+ var target = api.getTarget(elt);
280+ var settleInfo = api.makeSettleInfo(elt);
281+
282+ api.selectAndSwap(swapSpec.swapStyle, target, elt, content, settleInfo);
283+
284+ settleInfo.elts.forEach(function (elt) {
285+ if (elt.classList) {
286+ elt.classList.add(htmx.config.settlingClass);
287+ }
288+ api.triggerEvent(elt, 'htmx:beforeSettle');
289+ });
290+
291+ // Handle settle tasks (with delay if requested)
292+ if (swapSpec.settleDelay > 0) {
293+ setTimeout(doSettle(settleInfo), swapSpec.settleDelay);
294+ } else {
295+ doSettle(settleInfo)();
296+ }
297+ }
298+
299+ /**
300+ * doSettle mirrors much of the functionality in htmx that
301+ * settles elements after their content has been swapped.
302+ * TODO: this should be published by htmx, and not duplicated here
303+ * @param {import("../htmx").HtmxSettleInfo} settleInfo
304+ * @returns () => void
305+ */
306+ function doSettle(settleInfo) {
307+
308+ return function() {
309+ settleInfo.tasks.forEach(function (task) {
310+ task.call();
311+ });
312+
313+ settleInfo.elts.forEach(function (elt) {
314+ if (elt.classList) {
315+ elt.classList.remove(htmx.config.settlingClass);
316+ }
317+ api.triggerEvent(elt, 'htmx:afterSettle');
318+ });
319+ }
320+ }
321+
322+})();⏎̸
@@ -0,0 +1,322 @@
1+/*
2+Server Sent Events Extension
3+============================
4+This extension adds support for Server Sent Events to htmx. See /www/extensions/sse.md for usage instructions.
5+
6+*/
7+
8+(function(){
9+
10+ /** @type {import("../htmx").HtmxInternalApi} */
11+ var api;
12+
13+ htmx.defineExtension("sse", {
14+
15+ /**
16+ * Init saves the provided reference to the internal HTMX API.
17+ *
18+ * @param {import("../htmx").HtmxInternalApi} api
19+ * @returns void
20+ */
21+ init: function(apiRef) {
22+ // store a reference to the internal API.
23+ api = apiRef;
24+
25+ // set a function in the public API for creating new EventSource objects
26+ if (htmx.createEventSource == undefined) {
27+ htmx.createEventSource = createEventSource;
28+ }
29+ },
30+
31+ /**
32+ * onEvent handles all events passed to this extension.
33+ *
34+ * @param {string} name
35+ * @param {Event} evt
36+ * @returns void
37+ */
38+ onEvent: function(name, evt) {
39+
40+ switch (name) {
41+
42+ // Try to remove remove an EventSource when elements are removed
43+ case "htmx:beforeCleanupElement":
44+ var internalData = api.getInternalData(evt.target)
45+ if (internalData.sseEventSource) {
46+ internalData.sseEventSource.close();
47+ }
48+ return;
49+
50+ // Try to create EventSources when elements are processed
51+ case "htmx:afterProcessNode":
52+ createEventSourceOnElement(evt.target);
53+ }
54+ }
55+ });
56+
57+ ///////////////////////////////////////////////
58+ // HELPER FUNCTIONS
59+ ///////////////////////////////////////////////
60+
61+
62+ /**
63+ * createEventSource is the default method for creating new EventSource objects.
64+ * it is hoisted into htmx.config.createEventSource to be overridden by the user, if needed.
65+ *
66+ * @param {string} url
67+ * @returns EventSource
68+ */
69+ function createEventSource(url) {
70+ return new EventSource(url, {withCredentials:true});
71+ }
72+
73+ function splitOnWhitespace(trigger) {
74+ return trigger.trim().split(/\s+/);
75+ }
76+
77+ function getLegacySSEURL(elt) {
78+ var legacySSEValue = api.getAttributeValue(elt, "hx-sse");
79+ if (legacySSEValue) {
80+ var values = splitOnWhitespace(legacySSEValue);
81+ for (var i = 0; i < values.length; i++) {
82+ var value = values[i].split(/:(.+)/);
83+ if (value[0] === "connect") {
84+ return value[1];
85+ }
86+ }
87+ }
88+ }
89+
90+ function getLegacySSESwaps(elt) {
91+ var legacySSEValue = api.getAttributeValue(elt, "hx-sse");
92+ var returnArr = [];
93+ if (legacySSEValue) {
94+ var values = splitOnWhitespace(legacySSEValue);
95+ for (var i = 0; i < values.length; i++) {
96+ var value = values[i].split(/:(.+)/);
97+ if (value[0] === "swap") {
98+ returnArr.push(value[1]);
99+ }
100+ }
101+ }
102+ return returnArr;
103+ }
104+
105+ /**
106+ * createEventSourceOnElement creates a new EventSource connection on the provided element.
107+ * If a usable EventSource already exists, then it is returned. If not, then a new EventSource
108+ * is created and stored in the element's internalData.
109+ * @param {HTMLElement} elt
110+ * @param {number} retryCount
111+ * @returns {EventSource | null}
112+ */
113+ function createEventSourceOnElement(elt, retryCount) {
114+
115+ if (elt == null) {
116+ return null;
117+ }
118+
119+ var internalData = api.getInternalData(elt);
120+
121+ // get URL from element's attribute
122+ var sseURL = api.getAttributeValue(elt, "sse-connect");
123+
124+
125+ if (sseURL == undefined) {
126+ var legacyURL = getLegacySSEURL(elt)
127+ if (legacyURL) {
128+ sseURL = legacyURL;
129+ } else {
130+ return null;
131+ }
132+ }
133+
134+ // Connect to the EventSource
135+ var source = htmx.createEventSource(sseURL);
136+ internalData.sseEventSource = source;
137+
138+ // Create event handlers
139+ source.onerror = function (err) {
140+
141+ // Log an error event
142+ api.triggerErrorEvent(elt, "htmx:sseError", {error:err, source:source});
143+
144+ // If parent no longer exists in the document, then clean up this EventSource
145+ if (maybeCloseSSESource(elt)) {
146+ return;
147+ }
148+
149+ // Otherwise, try to reconnect the EventSource
150+ if (source.readyState === EventSource.CLOSED) {
151+ retryCount = retryCount || 0;
152+ var timeout = Math.random() * (2 ^ retryCount) * 500;
153+ window.setTimeout(function() {
154+ createEventSourceOnElement(elt, Math.min(7, retryCount+1));
155+ }, timeout);
156+ }
157+ };
158+
159+ source.onopen = function (evt) {
160+ api.triggerEvent(elt, "htmx:sseOpen", {source: source});
161+ }
162+
163+ // Add message handlers for every `sse-swap` attribute
164+ queryAttributeOnThisOrChildren(elt, "sse-swap").forEach(function(child) {
165+
166+ var sseSwapAttr = api.getAttributeValue(child, "sse-swap");
167+ if (sseSwapAttr) {
168+ var sseEventNames = sseSwapAttr.split(",");
169+ } else {
170+ var sseEventNames = getLegacySSESwaps(child);
171+ }
172+
173+ for (var i = 0 ; i < sseEventNames.length ; i++) {
174+ var sseEventName = sseEventNames[i].trim();
175+ var listener = function(event) {
176+
177+ // If the parent is missing then close SSE and remove listener
178+ if (maybeCloseSSESource(elt)) {
179+ source.removeEventListener(sseEventName, listener);
180+ return;
181+ }
182+
183+ // swap the response into the DOM and trigger a notification
184+ swap(child, event.data);
185+ api.triggerEvent(elt, "htmx:sseMessage", event);
186+ };
187+
188+ // Register the new listener
189+ api.getInternalData(elt).sseEventListener = listener;
190+ source.addEventListener(sseEventName, listener);
191+ }
192+ });
193+
194+ // Add message handlers for every `hx-trigger="sse:*"` attribute
195+ queryAttributeOnThisOrChildren(elt, "hx-trigger").forEach(function(child) {
196+
197+ var sseEventName = api.getAttributeValue(child, "hx-trigger");
198+ if (sseEventName == null) {
199+ return;
200+ }
201+
202+ // Only process hx-triggers for events with the "sse:" prefix
203+ if (sseEventName.slice(0, 4) != "sse:") {
204+ return;
205+ }
206+
207+ var listener = function(event) {
208+
209+ // If parent is missing, then close SSE and remove listener
210+ if (maybeCloseSSESource(elt)) {
211+ source.removeEventListener(sseEventName, listener);
212+ return;
213+ }
214+
215+ // Trigger events to be handled by the rest of htmx
216+ htmx.trigger(child, sseEventName, event);
217+ htmx.trigger(child, "htmx:sseMessage", event);
218+ }
219+
220+ // Register the new listener
221+ api.getInternalData(elt).sseEventListener = listener;
222+ source.addEventListener(sseEventName.slice(4), listener);
223+ });
224+ }
225+
226+ /**
227+ * maybeCloseSSESource confirms that the parent element still exists.
228+ * If not, then any associated SSE source is closed and the function returns true.
229+ *
230+ * @param {HTMLElement} elt
231+ * @returns boolean
232+ */
233+ function maybeCloseSSESource(elt) {
234+ if (!api.bodyContains(elt)) {
235+ var source = api.getInternalData(elt).sseEventSource;
236+ if (source != undefined) {
237+ source.close();
238+ // source = null
239+ return true;
240+ }
241+ }
242+ return false;
243+ }
244+
245+ /**
246+ * queryAttributeOnThisOrChildren returns all nodes that contain the requested attributeName, INCLUDING THE PROVIDED ROOT ELEMENT.
247+ *
248+ * @param {HTMLElement} elt
249+ * @param {string} attributeName
250+ */
251+ function queryAttributeOnThisOrChildren(elt, attributeName) {
252+
253+ var result = [];
254+
255+ // If the parent element also contains the requested attribute, then add it to the results too.
256+ if (api.hasAttribute(elt, attributeName) || api.hasAttribute(elt, "hx-sse")) {
257+ result.push(elt);
258+ }
259+
260+ // Search all child nodes that match the requested attribute
261+ elt.querySelectorAll("[" + attributeName + "], [data-" + attributeName + "], [hx-sse], [data-hx-sse]").forEach(function(node) {
262+ result.push(node);
263+ });
264+
265+ return result;
266+ }
267+
268+ /**
269+ * @param {HTMLElement} elt
270+ * @param {string} content
271+ */
272+ function swap(elt, content) {
273+
274+ api.withExtensions(elt, function(extension) {
275+ content = extension.transformResponse(content, null, elt);
276+ });
277+
278+ var swapSpec = api.getSwapSpecification(elt);
279+ var target = api.getTarget(elt);
280+ var settleInfo = api.makeSettleInfo(elt);
281+
282+ api.selectAndSwap(swapSpec.swapStyle, target, elt, content, settleInfo);
283+
284+ settleInfo.elts.forEach(function (elt) {
285+ if (elt.classList) {
286+ elt.classList.add(htmx.config.settlingClass);
287+ }
288+ api.triggerEvent(elt, 'htmx:beforeSettle');
289+ });
290+
291+ // Handle settle tasks (with delay if requested)
292+ if (swapSpec.settleDelay > 0) {
293+ setTimeout(doSettle(settleInfo), swapSpec.settleDelay);
294+ } else {
295+ doSettle(settleInfo)();
296+ }
297+ }
298+
299+ /**
300+ * doSettle mirrors much of the functionality in htmx that
301+ * settles elements after their content has been swapped.
302+ * TODO: this should be published by htmx, and not duplicated here
303+ * @param {import("../htmx").HtmxSettleInfo} settleInfo
304+ * @returns () => void
305+ */
306+ function doSettle(settleInfo) {
307+
308+ return function() {
309+ settleInfo.tasks.forEach(function (task) {
310+ task.call();
311+ });
312+
313+ settleInfo.elts.forEach(function (elt) {
314+ if (elt.classList) {
315+ elt.classList.remove(htmx.config.settlingClass);
316+ }
317+ api.triggerEvent(elt, 'htmx:afterSettle');
318+ });
319+ }
320+ }
321+
322+})();⏎̸
A internal/webui/public/libs/htmx.min.js +1 -0 generated file: collapsed
A internal/webui/public/libs/iconoir.css +22 -0 too large to show in the browser

too large to show in the browser view raw

A internal/webui/public/site.webmanifest +1 -0
@@ -0,0 +1,1 @@
1+{"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}⏎̸
@@ -0,0 +1,1 @@
1+{"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}⏎̸
D package-lock.json +0 -991
@@ -1,991 +0,0 @@
1-{
2- "name": "gordon-echo",
3- "lockfileVersion": 3,
4- "requires": true,
5- "packages": {
6- "": {
7- "devDependencies": {
8- "@catppuccin/tailwindcss": "^0.1.6",
9- "tailwindcss": "^3.3.3"
10- }
11- },
12- "node_modules/@alloc/quick-lru": {
13- "version": "5.2.0",
14- "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz",
15- "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==",
16- "dev": true,
17- "engines": {
18- "node": ">=10"
19- },
20- "funding": {
21- "url": "https://github.com/sponsors/sindresorhus"
22- }
23- },
24- "node_modules/@catppuccin/tailwindcss": {
25- "version": "0.1.6",
26- "resolved": "https://registry.npmjs.org/@catppuccin/tailwindcss/-/tailwindcss-0.1.6.tgz",
27- "integrity": "sha512-V+Y0AwZ5SSyvOVAcDl7Ng30xy+m82OKnEJ+9+kcZZ7lRyXuZrAb2GScdq9XR3v+ggt8qiZ/G4TvaC9cJ88AAXA==",
28- "dev": true,
29- "peerDependencies": {
30- "tailwindcss": ">=3.0.0"
31- }
32- },
33- "node_modules/@jridgewell/gen-mapping": {
34- "version": "0.3.3",
35- "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz",
36- "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==",
37- "dev": true,
38- "dependencies": {
39- "@jridgewell/set-array": "^1.0.1",
40- "@jridgewell/sourcemap-codec": "^1.4.10",
41- "@jridgewell/trace-mapping": "^0.3.9"
42- },
43- "engines": {
44- "node": ">=6.0.0"
45- }
46- },
47- "node_modules/@jridgewell/resolve-uri": {
48- "version": "3.1.1",
49- "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz",
50- "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==",
51- "dev": true,
52- "engines": {
53- "node": ">=6.0.0"
54- }
55- },
56- "node_modules/@jridgewell/set-array": {
57- "version": "1.1.2",
58- "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz",
59- "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==",
60- "dev": true,
61- "engines": {
62- "node": ">=6.0.0"
63- }
64- },
65- "node_modules/@jridgewell/sourcemap-codec": {
66- "version": "1.4.15",
67- "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
68- "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==",
69- "dev": true
70- },
71- "node_modules/@jridgewell/trace-mapping": {
72- "version": "0.3.19",
73- "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz",
74- "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==",
75- "dev": true,
76- "dependencies": {
77- "@jridgewell/resolve-uri": "^3.1.0",
78- "@jridgewell/sourcemap-codec": "^1.4.14"
79- }
80- },
81- "node_modules/@nodelib/fs.scandir": {
82- "version": "2.1.5",
83- "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
84- "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
85- "dev": true,
86- "dependencies": {
87- "@nodelib/fs.stat": "2.0.5",
88- "run-parallel": "^1.1.9"
89- },
90- "engines": {
91- "node": ">= 8"
92- }
93- },
94- "node_modules/@nodelib/fs.stat": {
95- "version": "2.0.5",
96- "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
97- "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
98- "dev": true,
99- "engines": {
100- "node": ">= 8"
101- }
102- },
103- "node_modules/@nodelib/fs.walk": {
104- "version": "1.2.8",
105- "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
106- "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
107- "dev": true,
108- "dependencies": {
109- "@nodelib/fs.scandir": "2.1.5",
110- "fastq": "^1.6.0"
111- },
112- "engines": {
113- "node": ">= 8"
114- }
115- },
116- "node_modules/any-promise": {
117- "version": "1.3.0",
118- "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
119- "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==",
120- "dev": true
121- },
122- "node_modules/anymatch": {
123- "version": "3.1.3",
124- "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
125- "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
126- "dev": true,
127- "dependencies": {
128- "normalize-path": "^3.0.0",
129- "picomatch": "^2.0.4"
130- },
131- "engines": {
132- "node": ">= 8"
133- }
134- },
135- "node_modules/arg": {
136- "version": "5.0.2",
137- "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz",
138- "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==",
139- "dev": true
140- },
141- "node_modules/balanced-match": {
142- "version": "1.0.2",
143- "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
144- "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
145- "dev": true
146- },
147- "node_modules/binary-extensions": {
148- "version": "2.2.0",
149- "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
150- "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
151- "dev": true,
152- "engines": {
153- "node": ">=8"
154- }
155- },
156- "node_modules/brace-expansion": {
157- "version": "1.1.11",
158- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
159- "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
160- "dev": true,
161- "dependencies": {
162- "balanced-match": "^1.0.0",
163- "concat-map": "0.0.1"
164- }
165- },
166- "node_modules/braces": {
167- "version": "3.0.2",
168- "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
169- "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
170- "dev": true,
171- "dependencies": {
172- "fill-range": "^7.0.1"
173- },
174- "engines": {
175- "node": ">=8"
176- }
177- },
178- "node_modules/camelcase-css": {
179- "version": "2.0.1",
180- "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz",
181- "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==",
182- "dev": true,
183- "engines": {
184- "node": ">= 6"
185- }
186- },
187- "node_modules/chokidar": {
188- "version": "3.5.3",
189- "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
190- "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
191- "dev": true,
192- "funding": [
193- {
194- "type": "individual",
195- "url": "https://paulmillr.com/funding/"
196- }
197- ],
198- "dependencies": {
199- "anymatch": "~3.1.2",
200- "braces": "~3.0.2",
201- "glob-parent": "~5.1.2",
202- "is-binary-path": "~2.1.0",
203- "is-glob": "~4.0.1",
204- "normalize-path": "~3.0.0",
205- "readdirp": "~3.6.0"
206- },
207- "engines": {
208- "node": ">= 8.10.0"
209- },
210- "optionalDependencies": {
211- "fsevents": "~2.3.2"
212- }
213- },
214- "node_modules/chokidar/node_modules/glob-parent": {
215- "version": "5.1.2",
216- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
217- "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
218- "dev": true,
219- "dependencies": {
220- "is-glob": "^4.0.1"
221- },
222- "engines": {
223- "node": ">= 6"
224- }
225- },
226- "node_modules/commander": {
227- "version": "4.1.1",
228- "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
229- "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==",
230- "dev": true,
231- "engines": {
232- "node": ">= 6"
233- }
234- },
235- "node_modules/concat-map": {
236- "version": "0.0.1",
237- "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
238- "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
239- "dev": true
240- },
241- "node_modules/cssesc": {
242- "version": "3.0.0",
243- "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
244- "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
245- "dev": true,
246- "bin": {
247- "cssesc": "bin/cssesc"
248- },
249- "engines": {
250- "node": ">=4"
251- }
252- },
253- "node_modules/didyoumean": {
254- "version": "1.2.2",
255- "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz",
256- "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==",
257- "dev": true
258- },
259- "node_modules/dlv": {
260- "version": "1.1.3",
261- "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz",
262- "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==",
263- "dev": true
264- },
265- "node_modules/fast-glob": {
266- "version": "3.3.1",
267- "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz",
268- "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==",
269- "dev": true,
270- "dependencies": {
271- "@nodelib/fs.stat": "^2.0.2",
272- "@nodelib/fs.walk": "^1.2.3",
273- "glob-parent": "^5.1.2",
274- "merge2": "^1.3.0",
275- "micromatch": "^4.0.4"
276- },
277- "engines": {
278- "node": ">=8.6.0"
279- }
280- },
281- "node_modules/fast-glob/node_modules/glob-parent": {
282- "version": "5.1.2",
283- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
284- "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
285- "dev": true,
286- "dependencies": {
287- "is-glob": "^4.0.1"
288- },
289- "engines": {
290- "node": ">= 6"
291- }
292- },
293- "node_modules/fastq": {
294- "version": "1.15.0",
295- "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz",
296- "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==",
297- "dev": true,
298- "dependencies": {
299- "reusify": "^1.0.4"
300- }
301- },
302- "node_modules/fill-range": {
303- "version": "7.0.1",
304- "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
305- "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
306- "dev": true,
307- "dependencies": {
308- "to-regex-range": "^5.0.1"
309- },
310- "engines": {
311- "node": ">=8"
312- }
313- },
314- "node_modules/fs.realpath": {
315- "version": "1.0.0",
316- "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
317- "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
318- "dev": true
319- },
320- "node_modules/fsevents": {
321- "version": "2.3.3",
322- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
323- "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
324- "dev": true,
325- "hasInstallScript": true,
326- "optional": true,
327- "os": [
328- "darwin"
329- ],
330- "engines": {
331- "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
332- }
333- },
334- "node_modules/function-bind": {
335- "version": "1.1.1",
336- "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
337- "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
338- "dev": true
339- },
340- "node_modules/glob": {
341- "version": "7.1.6",
342- "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
343- "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
344- "dev": true,
345- "dependencies": {
346- "fs.realpath": "^1.0.0",
347- "inflight": "^1.0.4",
348- "inherits": "2",
349- "minimatch": "^3.0.4",
350- "once": "^1.3.0",
351- "path-is-absolute": "^1.0.0"
352- },
353- "engines": {
354- "node": "*"
355- },
356- "funding": {
357- "url": "https://github.com/sponsors/isaacs"
358- }
359- },
360- "node_modules/glob-parent": {
361- "version": "6.0.2",
362- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
363- "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
364- "dev": true,
365- "dependencies": {
366- "is-glob": "^4.0.3"
367- },
368- "engines": {
369- "node": ">=10.13.0"
370- }
371- },
372- "node_modules/has": {
373- "version": "1.0.3",
374- "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
375- "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
376- "dev": true,
377- "dependencies": {
378- "function-bind": "^1.1.1"
379- },
380- "engines": {
381- "node": ">= 0.4.0"
382- }
383- },
384- "node_modules/inflight": {
385- "version": "1.0.6",
386- "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
387- "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
388- "dev": true,
389- "dependencies": {
390- "once": "^1.3.0",
391- "wrappy": "1"
392- }
393- },
394- "node_modules/inherits": {
395- "version": "2.0.4",
396- "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
397- "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
398- "dev": true
399- },
400- "node_modules/is-binary-path": {
401- "version": "2.1.0",
402- "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
403- "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
404- "dev": true,
405- "dependencies": {
406- "binary-extensions": "^2.0.0"
407- },
408- "engines": {
409- "node": ">=8"
410- }
411- },
412- "node_modules/is-core-module": {
413- "version": "2.13.0",
414- "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz",
415- "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==",
416- "dev": true,
417- "dependencies": {
418- "has": "^1.0.3"
419- },
420- "funding": {
421- "url": "https://github.com/sponsors/ljharb"
422- }
423- },
424- "node_modules/is-extglob": {
425- "version": "2.1.1",
426- "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
427- "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
428- "dev": true,
429- "engines": {
430- "node": ">=0.10.0"
431- }
432- },
433- "node_modules/is-glob": {
434- "version": "4.0.3",
435- "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
436- "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
437- "dev": true,
438- "dependencies": {
439- "is-extglob": "^2.1.1"
440- },
441- "engines": {
442- "node": ">=0.10.0"
443- }
444- },
445- "node_modules/is-number": {
446- "version": "7.0.0",
447- "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
448- "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
449- "dev": true,
450- "engines": {
451- "node": ">=0.12.0"
452- }
453- },
454- "node_modules/jiti": {
455- "version": "1.19.3",
456- "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.19.3.tgz",
457- "integrity": "sha512-5eEbBDQT/jF1xg6l36P+mWGGoH9Spuy0PCdSr2dtWRDGC6ph/w9ZCL4lmESW8f8F7MwT3XKescfP0wnZWAKL9w==",
458- "dev": true,
459- "bin": {
460- "jiti": "bin/jiti.js"
461- }
462- },
463- "node_modules/lilconfig": {
464- "version": "2.1.0",
465- "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz",
466- "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==",
467- "dev": true,
468- "engines": {
469- "node": ">=10"
470- }
471- },
472- "node_modules/lines-and-columns": {
473- "version": "1.2.4",
474- "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
475- "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
476- "dev": true
477- },
478- "node_modules/merge2": {
479- "version": "1.4.1",
480- "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
481- "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
482- "dev": true,
483- "engines": {
484- "node": ">= 8"
485- }
486- },
487- "node_modules/micromatch": {
488- "version": "4.0.5",
489- "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
490- "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
491- "dev": true,
492- "dependencies": {
493- "braces": "^3.0.2",
494- "picomatch": "^2.3.1"
495- },
496- "engines": {
497- "node": ">=8.6"
498- }
499- },
500- "node_modules/minimatch": {
501- "version": "3.1.2",
502- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
503- "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
504- "dev": true,
505- "dependencies": {
506- "brace-expansion": "^1.1.7"
507- },
508- "engines": {
509- "node": "*"
510- }
511- },
512- "node_modules/mz": {
513- "version": "2.7.0",
514- "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
515- "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==",
516- "dev": true,
517- "dependencies": {
518- "any-promise": "^1.0.0",
519- "object-assign": "^4.0.1",
520- "thenify-all": "^1.0.0"
521- }
522- },
523- "node_modules/nanoid": {
524- "version": "3.3.6",
525- "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz",
526- "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==",
527- "dev": true,
528- "funding": [
529- {
530- "type": "github",
531- "url": "https://github.com/sponsors/ai"
532- }
533- ],
534- "bin": {
535- "nanoid": "bin/nanoid.cjs"
536- },
537- "engines": {
538- "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
539- }
540- },
541- "node_modules/normalize-path": {
542- "version": "3.0.0",
543- "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
544- "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
545- "dev": true,
546- "engines": {
547- "node": ">=0.10.0"
548- }
549- },
550- "node_modules/object-assign": {
551- "version": "4.1.1",
552- "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
553- "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
554- "dev": true,
555- "engines": {
556- "node": ">=0.10.0"
557- }
558- },
559- "node_modules/object-hash": {
560- "version": "3.0.0",
561- "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz",
562- "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==",
563- "dev": true,
564- "engines": {
565- "node": ">= 6"
566- }
567- },
568- "node_modules/once": {
569- "version": "1.4.0",
570- "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
571- "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
572- "dev": true,
573- "dependencies": {
574- "wrappy": "1"
575- }
576- },
577- "node_modules/path-is-absolute": {
578- "version": "1.0.1",
579- "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
580- "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
581- "dev": true,
582- "engines": {
583- "node": ">=0.10.0"
584- }
585- },
586- "node_modules/path-parse": {
587- "version": "1.0.7",
588- "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
589- "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
590- "dev": true
591- },
592- "node_modules/picocolors": {
593- "version": "1.0.0",
594- "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
595- "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
596- "dev": true
597- },
598- "node_modules/picomatch": {
599- "version": "2.3.1",
600- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
601- "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
602- "dev": true,
603- "engines": {
604- "node": ">=8.6"
605- },
606- "funding": {
607- "url": "https://github.com/sponsors/jonschlinkert"
608- }
609- },
610- "node_modules/pify": {
611- "version": "2.3.0",
612- "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
613- "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==",
614- "dev": true,
615- "engines": {
616- "node": ">=0.10.0"
617- }
618- },
619- "node_modules/pirates": {
620- "version": "4.0.6",
621- "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz",
622- "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==",
623- "dev": true,
624- "engines": {
625- "node": ">= 6"
626- }
627- },
628- "node_modules/postcss": {
629- "version": "8.4.29",
630- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.29.tgz",
631- "integrity": "sha512-cbI+jaqIeu/VGqXEarWkRCCffhjgXc0qjBtXpqJhTBohMUjUQnbBr0xqX3vEKudc4iviTewcJo5ajcec5+wdJw==",
632- "dev": true,
633- "funding": [
634- {
635- "type": "opencollective",
636- "url": "https://opencollective.com/postcss/"
637- },
638- {
639- "type": "tidelift",
640- "url": "https://tidelift.com/funding/github/npm/postcss"
641- },
642- {
643- "type": "github",
644- "url": "https://github.com/sponsors/ai"
645- }
646- ],
647- "dependencies": {
648- "nanoid": "^3.3.6",
649- "picocolors": "^1.0.0",
650- "source-map-js": "^1.0.2"
651- },
652- "engines": {
653- "node": "^10 || ^12 || >=14"
654- }
655- },
656- "node_modules/postcss-import": {
657- "version": "15.1.0",
658- "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz",
659- "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==",
660- "dev": true,
661- "dependencies": {
662- "postcss-value-parser": "^4.0.0",
663- "read-cache": "^1.0.0",
664- "resolve": "^1.1.7"
665- },
666- "engines": {
667- "node": ">=14.0.0"
668- },
669- "peerDependencies": {
670- "postcss": "^8.0.0"
671- }
672- },
673- "node_modules/postcss-js": {
674- "version": "4.0.1",
675- "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz",
676- "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==",
677- "dev": true,
678- "dependencies": {
679- "camelcase-css": "^2.0.1"
680- },
681- "engines": {
682- "node": "^12 || ^14 || >= 16"
683- },
684- "funding": {
685- "type": "opencollective",
686- "url": "https://opencollective.com/postcss/"
687- },
688- "peerDependencies": {
689- "postcss": "^8.4.21"
690- }
691- },
692- "node_modules/postcss-load-config": {
693- "version": "4.0.1",
694- "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.1.tgz",
695- "integrity": "sha512-vEJIc8RdiBRu3oRAI0ymerOn+7rPuMvRXslTvZUKZonDHFIczxztIyJ1urxM1x9JXEikvpWWTUUqal5j/8QgvA==",
696- "dev": true,
697- "dependencies": {
698- "lilconfig": "^2.0.5",
699- "yaml": "^2.1.1"
700- },
701- "engines": {
702- "node": ">= 14"
703- },
704- "funding": {
705- "type": "opencollective",
706- "url": "https://opencollective.com/postcss/"
707- },
708- "peerDependencies": {
709- "postcss": ">=8.0.9",
710- "ts-node": ">=9.0.0"
711- },
712- "peerDependenciesMeta": {
713- "postcss": {
714- "optional": true
715- },
716- "ts-node": {
717- "optional": true
718- }
719- }
720- },
721- "node_modules/postcss-nested": {
722- "version": "6.0.1",
723- "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.1.tgz",
724- "integrity": "sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==",
725- "dev": true,
726- "dependencies": {
727- "postcss-selector-parser": "^6.0.11"
728- },
729- "engines": {
730- "node": ">=12.0"
731- },
732- "funding": {
733- "type": "opencollective",
734- "url": "https://opencollective.com/postcss/"
735- },
736- "peerDependencies": {
737- "postcss": "^8.2.14"
738- }
739- },
740- "node_modules/postcss-selector-parser": {
741- "version": "6.0.13",
742- "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz",
743- "integrity": "sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==",
744- "dev": true,
745- "dependencies": {
746- "cssesc": "^3.0.0",
747- "util-deprecate": "^1.0.2"
748- },
749- "engines": {
750- "node": ">=4"
751- }
752- },
753- "node_modules/postcss-value-parser": {
754- "version": "4.2.0",
755- "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
756- "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
757- "dev": true
758- },
759- "node_modules/queue-microtask": {
760- "version": "1.2.3",
761- "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
762- "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
763- "dev": true,
764- "funding": [
765- {
766- "type": "github",
767- "url": "https://github.com/sponsors/feross"
768- },
769- {
770- "type": "patreon",
771- "url": "https://www.patreon.com/feross"
772- },
773- {
774- "type": "consulting",
775- "url": "https://feross.org/support"
776- }
777- ]
778- },
779- "node_modules/read-cache": {
780- "version": "1.0.0",
781- "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
782- "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==",
783- "dev": true,
784- "dependencies": {
785- "pify": "^2.3.0"
786- }
787- },
788- "node_modules/readdirp": {
789- "version": "3.6.0",
790- "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
791- "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
792- "dev": true,
793- "dependencies": {
794- "picomatch": "^2.2.1"
795- },
796- "engines": {
797- "node": ">=8.10.0"
798- }
799- },
800- "node_modules/resolve": {
801- "version": "1.22.4",
802- "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.4.tgz",
803- "integrity": "sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg==",
804- "dev": true,
805- "dependencies": {
806- "is-core-module": "^2.13.0",
807- "path-parse": "^1.0.7",
808- "supports-preserve-symlinks-flag": "^1.0.0"
809- },
810- "bin": {
811- "resolve": "bin/resolve"
812- },
813- "funding": {
814- "url": "https://github.com/sponsors/ljharb"
815- }
816- },
817- "node_modules/reusify": {
818- "version": "1.0.4",
819- "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
820- "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
821- "dev": true,
822- "engines": {
823- "iojs": ">=1.0.0",
824- "node": ">=0.10.0"
825- }
826- },
827- "node_modules/run-parallel": {
828- "version": "1.2.0",
829- "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
830- "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
831- "dev": true,
832- "funding": [
833- {
834- "type": "github",
835- "url": "https://github.com/sponsors/feross"
836- },
837- {
838- "type": "patreon",
839- "url": "https://www.patreon.com/feross"
840- },
841- {
842- "type": "consulting",
843- "url": "https://feross.org/support"
844- }
845- ],
846- "dependencies": {
847- "queue-microtask": "^1.2.2"
848- }
849- },
850- "node_modules/source-map-js": {
851- "version": "1.0.2",
852- "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
853- "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
854- "dev": true,
855- "engines": {
856- "node": ">=0.10.0"
857- }
858- },
859- "node_modules/sucrase": {
860- "version": "3.34.0",
861- "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.34.0.tgz",
862- "integrity": "sha512-70/LQEZ07TEcxiU2dz51FKaE6hCTWC6vr7FOk3Gr0U60C3shtAN+H+BFr9XlYe5xqf3RA8nrc+VIwzCfnxuXJw==",
863- "dev": true,
864- "dependencies": {
865- "@jridgewell/gen-mapping": "^0.3.2",
866- "commander": "^4.0.0",
867- "glob": "7.1.6",
868- "lines-and-columns": "^1.1.6",
869- "mz": "^2.7.0",
870- "pirates": "^4.0.1",
871- "ts-interface-checker": "^0.1.9"
872- },
873- "bin": {
874- "sucrase": "bin/sucrase",
875- "sucrase-node": "bin/sucrase-node"
876- },
877- "engines": {
878- "node": ">=8"
879- }
880- },
881- "node_modules/supports-preserve-symlinks-flag": {
882- "version": "1.0.0",
883- "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
884- "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
885- "dev": true,
886- "engines": {
887- "node": ">= 0.4"
888- },
889- "funding": {
890- "url": "https://github.com/sponsors/ljharb"
891- }
892- },
893- "node_modules/tailwindcss": {
894- "version": "3.3.3",
895- "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.3.3.tgz",
896- "integrity": "sha512-A0KgSkef7eE4Mf+nKJ83i75TMyq8HqY3qmFIJSWy8bNt0v1lG7jUcpGpoTFxAwYcWOphcTBLPPJg+bDfhDf52w==",
897- "dev": true,
898- "dependencies": {
899- "@alloc/quick-lru": "^5.2.0",
900- "arg": "^5.0.2",
901- "chokidar": "^3.5.3",
902- "didyoumean": "^1.2.2",
903- "dlv": "^1.1.3",
904- "fast-glob": "^3.2.12",
905- "glob-parent": "^6.0.2",
906- "is-glob": "^4.0.3",
907- "jiti": "^1.18.2",
908- "lilconfig": "^2.1.0",
909- "micromatch": "^4.0.5",
910- "normalize-path": "^3.0.0",
911- "object-hash": "^3.0.0",
912- "picocolors": "^1.0.0",
913- "postcss": "^8.4.23",
914- "postcss-import": "^15.1.0",
915- "postcss-js": "^4.0.1",
916- "postcss-load-config": "^4.0.1",
917- "postcss-nested": "^6.0.1",
918- "postcss-selector-parser": "^6.0.11",
919- "resolve": "^1.22.2",
920- "sucrase": "^3.32.0"
921- },
922- "bin": {
923- "tailwind": "lib/cli.js",
924- "tailwindcss": "lib/cli.js"
925- },
926- "engines": {
927- "node": ">=14.0.0"
928- }
929- },
930- "node_modules/thenify": {
931- "version": "3.3.1",
932- "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz",
933- "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==",
934- "dev": true,
935- "dependencies": {
936- "any-promise": "^1.0.0"
937- }
938- },
939- "node_modules/thenify-all": {
940- "version": "1.6.0",
941- "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz",
942- "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==",
943- "dev": true,
944- "dependencies": {
945- "thenify": ">= 3.1.0 < 4"
946- },
947- "engines": {
948- "node": ">=0.8"
949- }
950- },
951- "node_modules/to-regex-range": {
952- "version": "5.0.1",
953- "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
954- "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
955- "dev": true,
956- "dependencies": {
957- "is-number": "^7.0.0"
958- },
959- "engines": {
960- "node": ">=8.0"
961- }
962- },
963- "node_modules/ts-interface-checker": {
964- "version": "0.1.13",
965- "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
966- "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==",
967- "dev": true
968- },
969- "node_modules/util-deprecate": {
970- "version": "1.0.2",
971- "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
972- "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
973- "dev": true
974- },
975- "node_modules/wrappy": {
976- "version": "1.0.2",
977- "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
978- "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
979- "dev": true
980- },
981- "node_modules/yaml": {
982- "version": "2.3.2",
983- "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.2.tgz",
984- "integrity": "sha512-N/lyzTPaJasoDmfV7YTrYCI0G/3ivm/9wdG0aHuheKowWQwGTsK0Eoiw6utmzAnI6pkJa0DUVygvp3spqqEKXg==",
985- "dev": true,
986- "engines": {
987- "node": ">= 14"
988- }
989- }
990- }
991-}
@@ -1,991 +0,0 @@
1-{
2- "name": "gordon-echo",
3- "lockfileVersion": 3,
4- "requires": true,
5- "packages": {
6- "": {
7- "devDependencies": {
8- "@catppuccin/tailwindcss": "^0.1.6",
9- "tailwindcss": "^3.3.3"
10- }
11- },
12- "node_modules/@alloc/quick-lru": {
13- "version": "5.2.0",
14- "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz",
15- "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==",
16- "dev": true,
17- "engines": {
18- "node": ">=10"
19- },
20- "funding": {
21- "url": "https://github.com/sponsors/sindresorhus"
22- }
23- },
24- "node_modules/@catppuccin/tailwindcss": {
25- "version": "0.1.6",
26- "resolved": "https://registry.npmjs.org/@catppuccin/tailwindcss/-/tailwindcss-0.1.6.tgz",
27- "integrity": "sha512-V+Y0AwZ5SSyvOVAcDl7Ng30xy+m82OKnEJ+9+kcZZ7lRyXuZrAb2GScdq9XR3v+ggt8qiZ/G4TvaC9cJ88AAXA==",
28- "dev": true,
29- "peerDependencies": {
30- "tailwindcss": ">=3.0.0"
31- }
32- },
33- "node_modules/@jridgewell/gen-mapping": {
34- "version": "0.3.3",
35- "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz",
36- "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==",
37- "dev": true,
38- "dependencies": {
39- "@jridgewell/set-array": "^1.0.1",
40- "@jridgewell/sourcemap-codec": "^1.4.10",
41- "@jridgewell/trace-mapping": "^0.3.9"
42- },
43- "engines": {
44- "node": ">=6.0.0"
45- }
46- },
47- "node_modules/@jridgewell/resolve-uri": {
48- "version": "3.1.1",
49- "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz",
50- "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==",
51- "dev": true,
52- "engines": {
53- "node": ">=6.0.0"
54- }
55- },
56- "node_modules/@jridgewell/set-array": {
57- "version": "1.1.2",
58- "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz",
59- "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==",
60- "dev": true,
61- "engines": {
62- "node": ">=6.0.0"
63- }
64- },
65- "node_modules/@jridgewell/sourcemap-codec": {
66- "version": "1.4.15",
67- "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
68- "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==",
69- "dev": true
70- },
71- "node_modules/@jridgewell/trace-mapping": {
72- "version": "0.3.19",
73- "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz",
74- "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==",
75- "dev": true,
76- "dependencies": {
77- "@jridgewell/resolve-uri": "^3.1.0",
78- "@jridgewell/sourcemap-codec": "^1.4.14"
79- }
80- },
81- "node_modules/@nodelib/fs.scandir": {
82- "version": "2.1.5",
83- "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
84- "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
85- "dev": true,
86- "dependencies": {
87- "@nodelib/fs.stat": "2.0.5",
88- "run-parallel": "^1.1.9"
89- },
90- "engines": {
91- "node": ">= 8"
92- }
93- },
94- "node_modules/@nodelib/fs.stat": {
95- "version": "2.0.5",
96- "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
97- "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
98- "dev": true,
99- "engines": {
100- "node": ">= 8"
101- }
102- },
103- "node_modules/@nodelib/fs.walk": {
104- "version": "1.2.8",
105- "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
106- "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
107- "dev": true,
108- "dependencies": {
109- "@nodelib/fs.scandir": "2.1.5",
110- "fastq": "^1.6.0"
111- },
112- "engines": {
113- "node": ">= 8"
114- }
115- },
116- "node_modules/any-promise": {
117- "version": "1.3.0",
118- "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
119- "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==",
120- "dev": true
121- },
122- "node_modules/anymatch": {
123- "version": "3.1.3",
124- "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
125- "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
126- "dev": true,
127- "dependencies": {
128- "normalize-path": "^3.0.0",
129- "picomatch": "^2.0.4"
130- },
131- "engines": {
132- "node": ">= 8"
133- }
134- },
135- "node_modules/arg": {
136- "version": "5.0.2",
137- "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz",
138- "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==",
139- "dev": true
140- },
141- "node_modules/balanced-match": {
142- "version": "1.0.2",
143- "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
144- "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
145- "dev": true
146- },
147- "node_modules/binary-extensions": {
148- "version": "2.2.0",
149- "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
150- "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
151- "dev": true,
152- "engines": {
153- "node": ">=8"
154- }
155- },
156- "node_modules/brace-expansion": {
157- "version": "1.1.11",
158- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
159- "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
160- "dev": true,
161- "dependencies": {
162- "balanced-match": "^1.0.0",
163- "concat-map": "0.0.1"
164- }
165- },
166- "node_modules/braces": {
167- "version": "3.0.2",
168- "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
169- "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
170- "dev": true,
171- "dependencies": {
172- "fill-range": "^7.0.1"
173- },
174- "engines": {
175- "node": ">=8"
176- }
177- },
178- "node_modules/camelcase-css": {
179- "version": "2.0.1",
180- "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz",
181- "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==",
182- "dev": true,
183- "engines": {
184- "node": ">= 6"
185- }
186- },
187- "node_modules/chokidar": {
188- "version": "3.5.3",
189- "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
190- "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
191- "dev": true,
192- "funding": [
193- {
194- "type": "individual",
195- "url": "https://paulmillr.com/funding/"
196- }
197- ],
198- "dependencies": {
199- "anymatch": "~3.1.2",
200- "braces": "~3.0.2",
201- "glob-parent": "~5.1.2",
202- "is-binary-path": "~2.1.0",
203- "is-glob": "~4.0.1",
204- "normalize-path": "~3.0.0",
205- "readdirp": "~3.6.0"
206- },
207- "engines": {
208- "node": ">= 8.10.0"
209- },
210- "optionalDependencies": {
211- "fsevents": "~2.3.2"
212- }
213- },
214- "node_modules/chokidar/node_modules/glob-parent": {
215- "version": "5.1.2",
216- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
217- "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
218- "dev": true,
219- "dependencies": {
220- "is-glob": "^4.0.1"
221- },
222- "engines": {
223- "node": ">= 6"
224- }
225- },
226- "node_modules/commander": {
227- "version": "4.1.1",
228- "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
229- "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==",
230- "dev": true,
231- "engines": {
232- "node": ">= 6"
233- }
234- },
235- "node_modules/concat-map": {
236- "version": "0.0.1",
237- "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
238- "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
239- "dev": true
240- },
241- "node_modules/cssesc": {
242- "version": "3.0.0",
243- "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
244- "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
245- "dev": true,
246- "bin": {
247- "cssesc": "bin/cssesc"
248- },
249- "engines": {
250- "node": ">=4"
251- }
252- },
253- "node_modules/didyoumean": {
254- "version": "1.2.2",
255- "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz",
256- "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==",
257- "dev": true
258- },
259- "node_modules/dlv": {
260- "version": "1.1.3",
261- "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz",
262- "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==",
263- "dev": true
264- },
265- "node_modules/fast-glob": {
266- "version": "3.3.1",
267- "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz",
268- "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==",
269- "dev": true,
270- "dependencies": {
271- "@nodelib/fs.stat": "^2.0.2",
272- "@nodelib/fs.walk": "^1.2.3",
273- "glob-parent": "^5.1.2",
274- "merge2": "^1.3.0",
275- "micromatch": "^4.0.4"
276- },
277- "engines": {
278- "node": ">=8.6.0"
279- }
280- },
281- "node_modules/fast-glob/node_modules/glob-parent": {
282- "version": "5.1.2",
283- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
284- "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
285- "dev": true,
286- "dependencies": {
287- "is-glob": "^4.0.1"
288- },
289- "engines": {
290- "node": ">= 6"
291- }
292- },
293- "node_modules/fastq": {
294- "version": "1.15.0",
295- "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz",
296- "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==",
297- "dev": true,
298- "dependencies": {
299- "reusify": "^1.0.4"
300- }
301- },
302- "node_modules/fill-range": {
303- "version": "7.0.1",
304- "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
305- "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
306- "dev": true,
307- "dependencies": {
308- "to-regex-range": "^5.0.1"
309- },
310- "engines": {
311- "node": ">=8"
312- }
313- },
314- "node_modules/fs.realpath": {
315- "version": "1.0.0",
316- "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
317- "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
318- "dev": true
319- },
320- "node_modules/fsevents": {
321- "version": "2.3.3",
322- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
323- "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
324- "dev": true,
325- "hasInstallScript": true,
326- "optional": true,
327- "os": [
328- "darwin"
329- ],
330- "engines": {
331- "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
332- }
333- },
334- "node_modules/function-bind": {
335- "version": "1.1.1",
336- "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
337- "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
338- "dev": true
339- },
340- "node_modules/glob": {
341- "version": "7.1.6",
342- "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
343- "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
344- "dev": true,
345- "dependencies": {
346- "fs.realpath": "^1.0.0",
347- "inflight": "^1.0.4",
348- "inherits": "2",
349- "minimatch": "^3.0.4",
350- "once": "^1.3.0",
351- "path-is-absolute": "^1.0.0"
352- },
353- "engines": {
354- "node": "*"
355- },
356- "funding": {
357- "url": "https://github.com/sponsors/isaacs"
358- }
359- },
360- "node_modules/glob-parent": {
361- "version": "6.0.2",
362- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
363- "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
364- "dev": true,
365- "dependencies": {
366- "is-glob": "^4.0.3"
367- },
368- "engines": {
369- "node": ">=10.13.0"
370- }
371- },
372- "node_modules/has": {
373- "version": "1.0.3",
374- "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
375- "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
376- "dev": true,
377- "dependencies": {
378- "function-bind": "^1.1.1"
379- },
380- "engines": {
381- "node": ">= 0.4.0"
382- }
383- },
384- "node_modules/inflight": {
385- "version": "1.0.6",
386- "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
387- "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
388- "dev": true,
389- "dependencies": {
390- "once": "^1.3.0",
391- "wrappy": "1"
392- }
393- },
394- "node_modules/inherits": {
395- "version": "2.0.4",
396- "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
397- "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
398- "dev": true
399- },
400- "node_modules/is-binary-path": {
401- "version": "2.1.0",
402- "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
403- "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
404- "dev": true,
405- "dependencies": {
406- "binary-extensions": "^2.0.0"
407- },
408- "engines": {
409- "node": ">=8"
410- }
411- },
412- "node_modules/is-core-module": {
413- "version": "2.13.0",
414- "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz",
415- "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==",
416- "dev": true,
417- "dependencies": {
418- "has": "^1.0.3"
419- },
420- "funding": {
421- "url": "https://github.com/sponsors/ljharb"
422- }
423- },
424- "node_modules/is-extglob": {
425- "version": "2.1.1",
426- "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
427- "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
428- "dev": true,
429- "engines": {
430- "node": ">=0.10.0"
431- }
432- },
433- "node_modules/is-glob": {
434- "version": "4.0.3",
435- "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
436- "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
437- "dev": true,
438- "dependencies": {
439- "is-extglob": "^2.1.1"
440- },
441- "engines": {
442- "node": ">=0.10.0"
443- }
444- },
445- "node_modules/is-number": {
446- "version": "7.0.0",
447- "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
448- "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
449- "dev": true,
450- "engines": {
451- "node": ">=0.12.0"
452- }
453- },
454- "node_modules/jiti": {
455- "version": "1.19.3",
456- "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.19.3.tgz",
457- "integrity": "sha512-5eEbBDQT/jF1xg6l36P+mWGGoH9Spuy0PCdSr2dtWRDGC6ph/w9ZCL4lmESW8f8F7MwT3XKescfP0wnZWAKL9w==",
458- "dev": true,
459- "bin": {
460- "jiti": "bin/jiti.js"
461- }
462- },
463- "node_modules/lilconfig": {
464- "version": "2.1.0",
465- "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz",
466- "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==",
467- "dev": true,
468- "engines": {
469- "node": ">=10"
470- }
471- },
472- "node_modules/lines-and-columns": {
473- "version": "1.2.4",
474- "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
475- "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
476- "dev": true
477- },
478- "node_modules/merge2": {
479- "version": "1.4.1",
480- "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
481- "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
482- "dev": true,
483- "engines": {
484- "node": ">= 8"
485- }
486- },
487- "node_modules/micromatch": {
488- "version": "4.0.5",
489- "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
490- "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
491- "dev": true,
492- "dependencies": {
493- "braces": "^3.0.2",
494- "picomatch": "^2.3.1"
495- },
496- "engines": {
497- "node": ">=8.6"
498- }
499- },
500- "node_modules/minimatch": {
501- "version": "3.1.2",
502- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
503- "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
504- "dev": true,
505- "dependencies": {
506- "brace-expansion": "^1.1.7"
507- },
508- "engines": {
509- "node": "*"
510- }
511- },
512- "node_modules/mz": {
513- "version": "2.7.0",
514- "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
515- "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==",
516- "dev": true,
517- "dependencies": {
518- "any-promise": "^1.0.0",
519- "object-assign": "^4.0.1",
520- "thenify-all": "^1.0.0"
521- }
522- },
523- "node_modules/nanoid": {
524- "version": "3.3.6",
525- "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz",
526- "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==",
527- "dev": true,
528- "funding": [
529- {
530- "type": "github",
531- "url": "https://github.com/sponsors/ai"
532- }
533- ],
534- "bin": {
535- "nanoid": "bin/nanoid.cjs"
536- },
537- "engines": {
538- "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
539- }
540- },
541- "node_modules/normalize-path": {
542- "version": "3.0.0",
543- "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
544- "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
545- "dev": true,
546- "engines": {
547- "node": ">=0.10.0"
548- }
549- },
550- "node_modules/object-assign": {
551- "version": "4.1.1",
552- "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
553- "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
554- "dev": true,
555- "engines": {
556- "node": ">=0.10.0"
557- }
558- },
559- "node_modules/object-hash": {
560- "version": "3.0.0",
561- "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz",
562- "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==",
563- "dev": true,
564- "engines": {
565- "node": ">= 6"
566- }
567- },
568- "node_modules/once": {
569- "version": "1.4.0",
570- "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
571- "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
572- "dev": true,
573- "dependencies": {
574- "wrappy": "1"
575- }
576- },
577- "node_modules/path-is-absolute": {
578- "version": "1.0.1",
579- "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
580- "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
581- "dev": true,
582- "engines": {
583- "node": ">=0.10.0"
584- }
585- },
586- "node_modules/path-parse": {
587- "version": "1.0.7",
588- "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
589- "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
590- "dev": true
591- },
592- "node_modules/picocolors": {
593- "version": "1.0.0",
594- "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
595- "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
596- "dev": true
597- },
598- "node_modules/picomatch": {
599- "version": "2.3.1",
600- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
601- "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
602- "dev": true,
603- "engines": {
604- "node": ">=8.6"
605- },
606- "funding": {
607- "url": "https://github.com/sponsors/jonschlinkert"
608- }
609- },
610- "node_modules/pify": {
611- "version": "2.3.0",
612- "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
613- "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==",
614- "dev": true,
615- "engines": {
616- "node": ">=0.10.0"
617- }
618- },
619- "node_modules/pirates": {
620- "version": "4.0.6",
621- "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz",
622- "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==",
623- "dev": true,
624- "engines": {
625- "node": ">= 6"
626- }
627- },
628- "node_modules/postcss": {
629- "version": "8.4.29",
630- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.29.tgz",
631- "integrity": "sha512-cbI+jaqIeu/VGqXEarWkRCCffhjgXc0qjBtXpqJhTBohMUjUQnbBr0xqX3vEKudc4iviTewcJo5ajcec5+wdJw==",
632- "dev": true,
633- "funding": [
634- {
635- "type": "opencollective",
636- "url": "https://opencollective.com/postcss/"
637- },
638- {
639- "type": "tidelift",
640- "url": "https://tidelift.com/funding/github/npm/postcss"
641- },
642- {
643- "type": "github",
644- "url": "https://github.com/sponsors/ai"
645- }
646- ],
647- "dependencies": {
648- "nanoid": "^3.3.6",
649- "picocolors": "^1.0.0",
650- "source-map-js": "^1.0.2"
651- },
652- "engines": {
653- "node": "^10 || ^12 || >=14"
654- }
655- },
656- "node_modules/postcss-import": {
657- "version": "15.1.0",
658- "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz",
659- "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==",
660- "dev": true,
661- "dependencies": {
662- "postcss-value-parser": "^4.0.0",
663- "read-cache": "^1.0.0",
664- "resolve": "^1.1.7"
665- },
666- "engines": {
667- "node": ">=14.0.0"
668- },
669- "peerDependencies": {
670- "postcss": "^8.0.0"
671- }
672- },
673- "node_modules/postcss-js": {
674- "version": "4.0.1",
675- "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz",
676- "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==",
677- "dev": true,
678- "dependencies": {
679- "camelcase-css": "^2.0.1"
680- },
681- "engines": {
682- "node": "^12 || ^14 || >= 16"
683- },
684- "funding": {
685- "type": "opencollective",
686- "url": "https://opencollective.com/postcss/"
687- },
688- "peerDependencies": {
689- "postcss": "^8.4.21"
690- }
691- },
692- "node_modules/postcss-load-config": {
693- "version": "4.0.1",
694- "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.1.tgz",
695- "integrity": "sha512-vEJIc8RdiBRu3oRAI0ymerOn+7rPuMvRXslTvZUKZonDHFIczxztIyJ1urxM1x9JXEikvpWWTUUqal5j/8QgvA==",
696- "dev": true,
697- "dependencies": {
698- "lilconfig": "^2.0.5",
699- "yaml": "^2.1.1"
700- },
701- "engines": {
702- "node": ">= 14"
703- },
704- "funding": {
705- "type": "opencollective",
706- "url": "https://opencollective.com/postcss/"
707- },
708- "peerDependencies": {
709- "postcss": ">=8.0.9",
710- "ts-node": ">=9.0.0"
711- },
712- "peerDependenciesMeta": {
713- "postcss": {
714- "optional": true
715- },
716- "ts-node": {
717- "optional": true
718- }
719- }
720- },
721- "node_modules/postcss-nested": {
722- "version": "6.0.1",
723- "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.1.tgz",
724- "integrity": "sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==",
725- "dev": true,
726- "dependencies": {
727- "postcss-selector-parser": "^6.0.11"
728- },
729- "engines": {
730- "node": ">=12.0"
731- },
732- "funding": {
733- "type": "opencollective",
734- "url": "https://opencollective.com/postcss/"
735- },
736- "peerDependencies": {
737- "postcss": "^8.2.14"
738- }
739- },
740- "node_modules/postcss-selector-parser": {
741- "version": "6.0.13",
742- "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz",
743- "integrity": "sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==",
744- "dev": true,
745- "dependencies": {
746- "cssesc": "^3.0.0",
747- "util-deprecate": "^1.0.2"
748- },
749- "engines": {
750- "node": ">=4"
751- }
752- },
753- "node_modules/postcss-value-parser": {
754- "version": "4.2.0",
755- "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
756- "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
757- "dev": true
758- },
759- "node_modules/queue-microtask": {
760- "version": "1.2.3",
761- "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
762- "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
763- "dev": true,
764- "funding": [
765- {
766- "type": "github",
767- "url": "https://github.com/sponsors/feross"
768- },
769- {
770- "type": "patreon",
771- "url": "https://www.patreon.com/feross"
772- },
773- {
774- "type": "consulting",
775- "url": "https://feross.org/support"
776- }
777- ]
778- },
779- "node_modules/read-cache": {
780- "version": "1.0.0",
781- "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
782- "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==",
783- "dev": true,
784- "dependencies": {
785- "pify": "^2.3.0"
786- }
787- },
788- "node_modules/readdirp": {
789- "version": "3.6.0",
790- "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
791- "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
792- "dev": true,
793- "dependencies": {
794- "picomatch": "^2.2.1"
795- },
796- "engines": {
797- "node": ">=8.10.0"
798- }
799- },
800- "node_modules/resolve": {
801- "version": "1.22.4",
802- "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.4.tgz",
803- "integrity": "sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg==",
804- "dev": true,
805- "dependencies": {
806- "is-core-module": "^2.13.0",
807- "path-parse": "^1.0.7",
808- "supports-preserve-symlinks-flag": "^1.0.0"
809- },
810- "bin": {
811- "resolve": "bin/resolve"
812- },
813- "funding": {
814- "url": "https://github.com/sponsors/ljharb"
815- }
816- },
817- "node_modules/reusify": {
818- "version": "1.0.4",
819- "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
820- "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
821- "dev": true,
822- "engines": {
823- "iojs": ">=1.0.0",
824- "node": ">=0.10.0"
825- }
826- },
827- "node_modules/run-parallel": {
828- "version": "1.2.0",
829- "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
830- "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
831- "dev": true,
832- "funding": [
833- {
834- "type": "github",
835- "url": "https://github.com/sponsors/feross"
836- },
837- {
838- "type": "patreon",
839- "url": "https://www.patreon.com/feross"
840- },
841- {
842- "type": "consulting",
843- "url": "https://feross.org/support"
844- }
845- ],
846- "dependencies": {
847- "queue-microtask": "^1.2.2"
848- }
849- },
850- "node_modules/source-map-js": {
851- "version": "1.0.2",
852- "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
853- "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
854- "dev": true,
855- "engines": {
856- "node": ">=0.10.0"
857- }
858- },
859- "node_modules/sucrase": {
860- "version": "3.34.0",
861- "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.34.0.tgz",
862- "integrity": "sha512-70/LQEZ07TEcxiU2dz51FKaE6hCTWC6vr7FOk3Gr0U60C3shtAN+H+BFr9XlYe5xqf3RA8nrc+VIwzCfnxuXJw==",
863- "dev": true,
864- "dependencies": {
865- "@jridgewell/gen-mapping": "^0.3.2",
866- "commander": "^4.0.0",
867- "glob": "7.1.6",
868- "lines-and-columns": "^1.1.6",
869- "mz": "^2.7.0",
870- "pirates": "^4.0.1",
871- "ts-interface-checker": "^0.1.9"
872- },
873- "bin": {
874- "sucrase": "bin/sucrase",
875- "sucrase-node": "bin/sucrase-node"
876- },
877- "engines": {
878- "node": ">=8"
879- }
880- },
881- "node_modules/supports-preserve-symlinks-flag": {
882- "version": "1.0.0",
883- "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
884- "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
885- "dev": true,
886- "engines": {
887- "node": ">= 0.4"
888- },
889- "funding": {
890- "url": "https://github.com/sponsors/ljharb"
891- }
892- },
893- "node_modules/tailwindcss": {
894- "version": "3.3.3",
895- "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.3.3.tgz",
896- "integrity": "sha512-A0KgSkef7eE4Mf+nKJ83i75TMyq8HqY3qmFIJSWy8bNt0v1lG7jUcpGpoTFxAwYcWOphcTBLPPJg+bDfhDf52w==",
897- "dev": true,
898- "dependencies": {
899- "@alloc/quick-lru": "^5.2.0",
900- "arg": "^5.0.2",
901- "chokidar": "^3.5.3",
902- "didyoumean": "^1.2.2",
903- "dlv": "^1.1.3",
904- "fast-glob": "^3.2.12",
905- "glob-parent": "^6.0.2",
906- "is-glob": "^4.0.3",
907- "jiti": "^1.18.2",
908- "lilconfig": "^2.1.0",
909- "micromatch": "^4.0.5",
910- "normalize-path": "^3.0.0",
911- "object-hash": "^3.0.0",
912- "picocolors": "^1.0.0",
913- "postcss": "^8.4.23",
914- "postcss-import": "^15.1.0",
915- "postcss-js": "^4.0.1",
916- "postcss-load-config": "^4.0.1",
917- "postcss-nested": "^6.0.1",
918- "postcss-selector-parser": "^6.0.11",
919- "resolve": "^1.22.2",
920- "sucrase": "^3.32.0"
921- },
922- "bin": {
923- "tailwind": "lib/cli.js",
924- "tailwindcss": "lib/cli.js"
925- },
926- "engines": {
927- "node": ">=14.0.0"
928- }
929- },
930- "node_modules/thenify": {
931- "version": "3.3.1",
932- "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz",
933- "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==",
934- "dev": true,
935- "dependencies": {
936- "any-promise": "^1.0.0"
937- }
938- },
939- "node_modules/thenify-all": {
940- "version": "1.6.0",
941- "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz",
942- "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==",
943- "dev": true,
944- "dependencies": {
945- "thenify": ">= 3.1.0 < 4"
946- },
947- "engines": {
948- "node": ">=0.8"
949- }
950- },
951- "node_modules/to-regex-range": {
952- "version": "5.0.1",
953- "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
954- "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
955- "dev": true,
956- "dependencies": {
957- "is-number": "^7.0.0"
958- },
959- "engines": {
960- "node": ">=8.0"
961- }
962- },
963- "node_modules/ts-interface-checker": {
964- "version": "0.1.13",
965- "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
966- "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==",
967- "dev": true
968- },
969- "node_modules/util-deprecate": {
970- "version": "1.0.2",
971- "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
972- "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
973- "dev": true
974- },
975- "node_modules/wrappy": {
976- "version": "1.0.2",
977- "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
978- "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
979- "dev": true
980- },
981- "node_modules/yaml": {
982- "version": "2.3.2",
983- "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.2.tgz",
984- "integrity": "sha512-N/lyzTPaJasoDmfV7YTrYCI0G/3ivm/9wdG0aHuheKowWQwGTsK0Eoiw6utmzAnI6pkJa0DUVygvp3spqqEKXg==",
985- "dev": true,
986- "engines": {
987- "node": ">= 14"
988- }
989- }
990- }
991-}
A pkg/utils/htmx/htmlfragments.go +42 -0
@@ -0,0 +1,42 @@
1+package htmx
2+
3+import (
4+ "bytes"
5+
6+ "github.com/PuerkitoBio/goquery"
7+
8+)
9+
10+// GetHTMLFragmentByID returns the HTML fragment with the specified id
11+func GetHTMLFragmentByID(id string, data interface{}, a *app.App, ac *app.Config) (string, error) {
12+ // 1. Render the template
13+ renderer, err := templating.GetHTMLRenderer("components.gohtml", ac.GetTemplateFS(), a)
14+ if err != nil {
15+ return "", err
16+ }
17+
18+ renderedHTML, err := renderer.Render(data, a)
19+ if err != nil {
20+ return "", err
21+ }
22+
23+ // 2. Parse the rendered HTML with goquery
24+ doc, err := goquery.NewDocumentFromReader(bytes.NewReader([]byte(renderedHTML)))
25+ if err != nil {
26+ return "", err
27+ }
28+
29+ // 3. Find the div with the specified id
30+ fragmentContent, err := doc.Find("#" + id).Html()
31+ if err != nil {
32+ return "", err
33+ }
34+
35+ if fragmentcontent == "" {
36+ return "", err
37+ }
38+
39+ return fragmentContent, nil
40+}
41+
42+
@@ -0,0 +1,42 @@
1+package htmx
2+
3+import (
4+ "bytes"
5+
6+ "github.com/PuerkitoBio/goquery"
7+
8+)
9+
10+// GetHTMLFragmentByID returns the HTML fragment with the specified id
11+func GetHTMLFragmentByID(id string, data interface{}, a *app.App, ac *app.Config) (string, error) {
12+ // 1. Render the template
13+ renderer, err := templating.GetHTMLRenderer("components.gohtml", ac.GetTemplateFS(), a)
14+ if err != nil {
15+ return "", err
16+ }
17+
18+ renderedHTML, err := renderer.Render(data, a)
19+ if err != nil {
20+ return "", err
21+ }
22+
23+ // 2. Parse the rendered HTML with goquery
24+ doc, err := goquery.NewDocumentFromReader(bytes.NewReader([]byte(renderedHTML)))
25+ if err != nil {
26+ return "", err
27+ }
28+
29+ // 3. Find the div with the specified id
30+ fragmentContent, err := doc.Find("#" + id).Html()
31+ if err != nil {
32+ return "", err
33+ }
34+
35+ if fragmentcontent == "" {
36+ return "", err
37+ }
38+
39+ return fragmentContent, nil
40+}
41+
42+

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 7

Tags 106

↑↓ moveenter openesc close