feat: search

This commit is contained in:
Evan Buss
2024-07-13 17:16:38 +00:00
parent 4f3948943a
commit 9094e780d0
8 changed files with 122 additions and 85 deletions

View File

@@ -1,7 +1,6 @@
package convert
import (
"fmt"
"os/exec"
"path/filepath"
"strings"
@@ -16,7 +15,6 @@ type KepubConverter struct {
func (kc *KepubConverter) Available() bool {
kc.availableOnce.Do(func() {
fmt.Println("TEST")
path, err := exec.LookPath("kepubify")
kc.available = err == nil && path != ""
})

View File

@@ -2,30 +2,7 @@
<nav class="navigation">
{{if .Search }}
<div class="search">
<a
href="{{.Search}}"
tabindex="-1"
hx-get="?q={{.Search}}&partial=search.html"
>
<svg
width="30"
height="30"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="size-6"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607Z"
/>
</svg>
</a>
</div>
{{template "search" .}}
{{end}}
<div class="nav-controls">
@@ -45,11 +22,13 @@
{{end}}
<div class="info">
<p>{{.Title}}</p>
{{if empty .Author | not }}
<p>{{.Author}}</p>
{{end}}
</div>
</a>
</li>
{{end}}
</ul>
{{end}}
{{end}}

View File

@@ -23,6 +23,14 @@ func parse(file ...string) *template.Template {
return template.Must(
template.New("layout.html").
Funcs(sprig.FuncMap()).
Funcs(template.FuncMap{
"getKey": func(key string, d map[string]interface{}) interface{} {
if val, ok := d[key]; ok {
return val
}
return ""
}},
).
ParseFS(files, file...),
)
}

View File

@@ -1,16 +1,14 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>{{block "title" .}}Kobo OPDS Proxy{{end}}</title>
<link rel="stylesheet" href="/static/style.css" />
<script
src="https://unpkg.com/htmx.org@2.0.0"
integrity="sha384-wS5l5IKJBvK6sPTKa2WZ1js3d947pvWXbPJ1OmWfEuxLgeHcEbjUUA5i9V5ZkpCw"
crossorigin="anonymous"
></script>
</head>
<body>
<main id="container">{{block "content" .}}{{end}}</main>
</body>
</html>
<head>
<meta charset="UTF-8" />
<title>{{block "title" .}}Kobo OPDS Proxy{{end}}</title>
<link rel="stylesheet" href="/static/style.css" />
</head>
<body>
<main id="container">{{block "content" .}}{{end}}</main>
</body>
</html>

View File

@@ -1,28 +1,23 @@
{{define "title"}}Feed Log In{{end}}
{{ define "content" }}
<main>
<h1>{{index (urlParse .ReturnURL) "query" | trimPrefix "q=" }}</h1>
<p>Log in to access this feed</p>
<div id="content">
<form method="post">
<input type="text" name="username" placeholder="Username" />
<input type="password" name="password" placeholder="Password" />
<button type="submit">Log In</button>
</form>
</div>
</main>
<h1>{{urlParse .ReturnURL | getKey "query" | trimPrefix "q=" | urlParse | getKey "host" }}</h1>
<p>Log in to access this feed.</p>
<div id="content">
<form method="post">
<input type="text" name="username" placeholder="Username" />
<input type="password" name="password" placeholder="Password" />
<button type="submit">Log In</button>
</form>
</div>
<style>
main {
margin-top: 2rem;
h1,
p {
text-align: center;
}
h1 {
font-size: 1.25rem;
}
form {
margin: 0 auto;
font-size: 1.5rem;
}
input {
@@ -35,7 +30,6 @@
}
button {
font-style: normal;
padding: 0.8rem 1rem;
margin: 1rem auto;
display: block;
@@ -43,6 +37,7 @@
color: white;
border: none;
border-radius: 2px;
width: 268px;
}
</style>
{{ end }}

View File

@@ -1,16 +1,23 @@
{{define "search-partial"}}
{{define "search"}}
<form method="get">
<form method="get" id="search-form">
<input type="hidden" name="q" value="{{.Search}}" />
<input type="search" placeholder="Search" name="search" />
<label for="search">
<svg width="30" height="30" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5"
stroke="currentColor" class="size-6">
<path stroke-linecap="round" stroke-linejoin="round"
d="m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607Z" />
</svg>
<input tabindex="-1" type="search" id="search" placeholder="Search" name="search" />
</label>
<script>
const searchInput = document.querySelector("input[name=search]");
const searchParams = new URLSearchParams(window.location.search);
if (searchParams.has("search") && !!searchInput) {
if (searchParams.has("search")) {
searchInput.value = searchParams.get("search");
}
</script>
</form>
{{end}}
{{end}}

View File

@@ -8,41 +8,47 @@
font-size: 1.25rem;
}
p {
font-size: 1rem;
}
#container {
padding: 1rem;
width: 100%;
}
#container > ul {
#container>ul {
margin-top: 75px;
list-style-type: none;
}
@media (max-width: 500px) {
#container > ul {
#container>ul {
margin-top: 125px;
}
}
#container > ul > li {
#container>ul>li {
padding: 1rem;
white-space: nowrap;
}
#container > ul > li > a > img {
#container>ul>li>a>img {
display: inline-block;
height: 75px;
margin-right: 1rem;
}
#container > ul > li > a > .info {
#container>ul>li>a>.info {
display: inline-block;
vertical-align: top;
white-space: normal;
max-width: calc(100% - 3rem - 75px);
}
.info > p:not(:first-child) {
font-size: 1rem;
.info>p:first-child {
font-weight: 500;
font-size: 1.25rem;
}
a {
@@ -51,11 +57,11 @@ a {
color: black;
}
#container > ul > li a {
#container>ul>li a {
width: 100%;
}
#container > ul > li:not(:last-child) {
#container>ul>li:not(:last-child) {
border-bottom: 1px solid rgba(0, 0, 0, 0.5);
}
@@ -69,12 +75,13 @@ a {
display: block;
height: 64px;
border-bottom: 1px solid rgba(0, 0, 0, 0.5);
}
.search {
width: 100px;
display: inline-block;
}
.search:focus {
@@ -82,19 +89,45 @@ a {
box-shadow: none;
}
.search > a {
#search-form {
display: inline-block;
height: 100%;
}
#search-form>label>input {
height: 100%;
width: 100%;
padding: 0.5rem;
font-size: 1rem;
border: none;
border-right: 1px solid rgba(0, 0, 0, 0.5);
padding-left: 3rem;
}
#search-form>label {
position: relative;
}
#search-form>label>svg {
position: absolute;
top: 25%;
left: 0.5rem;
height: 1rem;
}
.search>form {
padding-top: 1rem;
padding-left: 1rem;
display: block;
margin: auto;
}
.nav-controls {
float: right;
vertical-align: center;
}
.nav-controls > a {
.nav-controls>a {
padding: 1rem 0.5rem;
height: 100%;
font-size: 1rem;
}
@@ -102,23 +135,42 @@ a {
padding-right: 1rem;
}
*, *::before, *::after {
*,
*::before,
*::after {
box-sizing: border-box;
}
* {
margin: 0;
}
body {
line-height: 1.5;
-webkit-font-smoothing: antialiased;
/* -webkit-font-smoothing: antialiased; */
}
img, picture, video, canvas, svg {
img,
picture,
video,
canvas,
svg {
display: block;
max-width: 100%;
}
input, button, textarea, select {
input,
button,
textarea,
select {
font: inherit;
}
p, h1, h2, h3, h4, h5, h6 {
p,
h1,
h2,
h3,
h4,
h5,
h6 {
overflow-wrap: break-word;
}

View File

@@ -95,7 +95,6 @@ func handleFeed(outputDir string) http.HandlerFunc {
searchTerm := r.URL.Query().Get("search")
if searchTerm != "" {
fmt.Println("Search term", searchTerm)
queryURL = replaceSearchPlaceHolder(queryURL, searchTerm)
}
@@ -213,6 +212,7 @@ func handleAuth() http.HandlerFunc {
http.SetCookie(w, cookie)
http.Redirect(w, r, returnUrl, http.StatusFound)
return
}
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)