generated from ElnuDev/go-project
Better template loading, word page
See https://stackoverflow.com/a/11468132
This commit is contained in:
parent
f558d7f0c1
commit
e70916c6c1
11 changed files with 236 additions and 87 deletions
58
dict/main.go
58
dict/main.go
|
@ -115,6 +115,16 @@ func Search(query string) queryResult {
|
|||
}
|
||||
}
|
||||
|
||||
func Lookup(word string) *Entry {
|
||||
for _, jmdictEntry := range dict.Entries {
|
||||
entry := ParseEntry(jmdictEntry)
|
||||
if entry.Kanji == word {
|
||||
return &entry
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type queryResult struct {
|
||||
// Fields must be capitalized
|
||||
// to be accessible in templates
|
||||
|
@ -134,9 +144,9 @@ func main() {
|
|||
fmt.Println("JMdict loaded!")
|
||||
r := mux.NewRouter()
|
||||
r.HandleFunc("/", httputils.GenerateHandler(
|
||||
"index.html",
|
||||
func(w http.ResponseWriter, r *http.Request) bool { return true },
|
||||
func(w http.ResponseWriter, r *http.Request) any { return nil },
|
||||
httputils.NewTemplateSet("index.html"),
|
||||
func(w http.ResponseWriter, r *http.Request) (string, any) { return "index.html", nil },
|
||||
[]string{http.MethodGet},
|
||||
))
|
||||
rawSearchHandler := func(w http.ResponseWriter, r *http.Request) {
|
||||
|
@ -153,13 +163,6 @@ func main() {
|
|||
r.HandleFunc("/search", rawSearchHandler)
|
||||
r.HandleFunc("/search/", rawSearchHandler)
|
||||
r.HandleFunc("/search/{query}", httputils.GenerateHandler(
|
||||
// template file
|
||||
func(w http.ResponseWriter, r *http.Request) string {
|
||||
if r.Header.Get("HX-Request") == "" {
|
||||
return "index.html"
|
||||
}
|
||||
return "search.html"
|
||||
},
|
||||
// handler whether or not to use template
|
||||
func(w http.ResponseWriter, r *http.Request) bool {
|
||||
// If Accept: applicaiton/json we'll use the template
|
||||
|
@ -177,11 +180,44 @@ func main() {
|
|||
|
||||
return false
|
||||
},
|
||||
httputils.NewTemplateSet("index.html", "search.html"),
|
||||
// template data
|
||||
func(w http.ResponseWriter, r *http.Request) any {
|
||||
func(w http.ResponseWriter, r *http.Request) (template string, data any) {
|
||||
if r.Header.Get("HX-Request") == "" {
|
||||
template = "search.html"
|
||||
} else {
|
||||
template = "search"
|
||||
}
|
||||
// Only runs if handler returns true
|
||||
query := mux.Vars(r)["query"]
|
||||
return Search(query)
|
||||
data = Search(query)
|
||||
return
|
||||
},
|
||||
[]string{http.MethodGet},
|
||||
))
|
||||
rawWordHandler := func(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Println("Redirecting raw word handler")
|
||||
http.Redirect(w, r, "/", http.StatusMovedPermanently)
|
||||
}
|
||||
r.HandleFunc("/word", rawWordHandler)
|
||||
r.HandleFunc("/word/", rawWordHandler)
|
||||
r.HandleFunc("/word/{word}", httputils.GenerateHandler(
|
||||
func(w http.ResponseWriter, r *http.Request) bool { return true },
|
||||
// Order matters
|
||||
// word.html overrided the results block in index.html
|
||||
// so should be loaded second
|
||||
httputils.NewTemplateSet("index.html", "word.html"),
|
||||
func(w http.ResponseWriter, r *http.Request) (template string, data any) {
|
||||
template = "word.html"
|
||||
query := mux.Vars(r)["word"]
|
||||
data = struct {
|
||||
Query any
|
||||
Entry *Entry
|
||||
}{
|
||||
Query: nil,
|
||||
Entry: Lookup(query),
|
||||
}
|
||||
return
|
||||
},
|
||||
[]string{http.MethodGet},
|
||||
))
|
||||
|
|
|
@ -1,18 +1,25 @@
|
|||
{{- define "index" -}}
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{{ with .Query }}{{ . }} search - {{ end }}jidict</title>
|
||||
<title>{{ block "title" . }}{{ template "sitetitle" . }}{{ end }}</title>
|
||||
<link rel="stylesheet" href="https://unpkg.com/missing.css@1.0.9/dist/missing.min.css">
|
||||
<style>
|
||||
li {
|
||||
margin-top: 0.75em;
|
||||
}
|
||||
#results .box h3 a {
|
||||
color: inherit;
|
||||
}
|
||||
#results .box h3 a:not(:hover) {
|
||||
text-decoration: none;
|
||||
}
|
||||
</style>
|
||||
<script src="https://unpkg.com/htmx.org@1.9.3"></script>
|
||||
</head>
|
||||
<body>
|
||||
<body hx-boost="true">
|
||||
<main>
|
||||
<a href="/">
|
||||
<img src="https://jichan.org/logo.svg" style="height: 4em; display: block; margin: 1em auto 1em auto">
|
||||
|
@ -20,13 +27,16 @@
|
|||
<form
|
||||
hx-get="/search"
|
||||
hx-replace-url="true"
|
||||
hx-target="#results">
|
||||
<input type="text" name="q"{{ with .Query }} value="{{ . }}"{{ end }} placeholder="辞書をサーチする" class="width:100%" autocomplete="false">
|
||||
hx-target="#results"
|
||||
hx-on::before-request="document.title = `${this.querySelector('input').value} search - jidict`">
|
||||
<input type="text" name="q" value="{{ block "value" . }}{{ end }}" placeholder="辞書をサーチする" class="width:100%" autocomplete="false" required>
|
||||
</form>
|
||||
<div id="results">
|
||||
{{ if .Count }}{{ template "search" . }}{{ end }}
|
||||
{{ block "results" . }}{{ if .Query }}{{ template "search" . }}{{ end }}{{ end }}
|
||||
</div>
|
||||
<br>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
{{- end -}}
|
||||
{{- template "index" . -}}
|
23
dict/templates/partials/entry.html
Normal file
23
dict/templates/partials/entry.html
Normal file
|
@ -0,0 +1,23 @@
|
|||
{{ define "entry" }}
|
||||
<div class="box">
|
||||
<h3>
|
||||
{{- if .Kanji -}}
|
||||
<a href="/word/{{ .Kanji }}"><ruby>{{- .Kanji -}}<rp>(</rp><rt>{{- .Reading -}}</rt><rp>)</rp></ruby></a>
|
||||
{{- else -}}
|
||||
{{- .Reading -}}
|
||||
{{- end -}}
|
||||
</h3>
|
||||
{{- $count := len .Definitions -}}
|
||||
{{ if eq $count 1 -}}
|
||||
<p>{{- template "definition" (index .Definitions 0) -}}</p>
|
||||
{{- else if ne $count 0 -}}
|
||||
<ol>
|
||||
{{- range .Definitions }}
|
||||
<li>
|
||||
{{ template "definition" . }}
|
||||
</li>
|
||||
{{- end }}
|
||||
</ol>
|
||||
{{- end }}
|
||||
</div>
|
||||
{{ end }}
|
23
dict/templates/partials/entryfull.html
Normal file
23
dict/templates/partials/entryfull.html
Normal file
|
@ -0,0 +1,23 @@
|
|||
{{ define "entryfull" }}
|
||||
<div class="box">
|
||||
<h3>
|
||||
{{- if .Kanji -}}
|
||||
<ruby>{{- .Kanji -}}<rp>(</rp><rt>{{- .Reading -}}</rt><rp>)</rp></ruby>
|
||||
{{- else -}}
|
||||
{{- .Reading -}}
|
||||
{{- end -}}
|
||||
</h3>
|
||||
{{- $count := len .Definitions -}}
|
||||
{{ if eq $count 1 -}}
|
||||
<p>{{- template "definition" (index .Definitions 0) -}}</p>
|
||||
{{- else if ne $count 0 -}}
|
||||
<ol>
|
||||
{{- range .Definitions }}
|
||||
<li>
|
||||
{{ template "definition" . }}
|
||||
</li>
|
||||
{{- end }}
|
||||
</ol>
|
||||
{{- end }}
|
||||
</div>
|
||||
{{ end }}
|
11
dict/templates/partials/search.html
Normal file
11
dict/templates/partials/search.html
Normal file
|
@ -0,0 +1,11 @@
|
|||
{{- define "search" -}}
|
||||
<p><i>{{ if .Truncated }}Truncated results, showing first {{ .Count }}{{ else }}{{ if eq .Count 0 }}No results{{ else }}{{ .Count }} result{{ if ne .Count 1}}s{{ end }}{{ end }}{{ end }}.</i></p>
|
||||
{{ range .ExactResults -}}
|
||||
{{- template "entry" . -}}
|
||||
{{- end }}
|
||||
{{ if and (ne (len .ExactResults) 0) (ne (len .OtherResults) 0) }}<hr>{{ end }}
|
||||
{{ range .OtherResults -}}
|
||||
{{ template "entry" . }}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- template "search" . -}}
|
1
dict/templates/partials/sitetitle.html
Normal file
1
dict/templates/partials/sitetitle.html
Normal file
|
@ -0,0 +1 @@
|
|||
{{ define "sitetitle" }}jidict{{ end }}
|
|
@ -1,11 +1,9 @@
|
|||
{{- define "search" -}}
|
||||
<p><i>{{ if .Truncated }}Truncated results, showing first {{ .Count }}{{ else }}{{ if eq .Count 0 }}No results{{ else }}{{ .Count }} result{{ if ne .Count 1}}s{{ end }}{{ end }}{{ end }}.</i></p>
|
||||
{{ range .ExactResults -}}
|
||||
{{- template "word" . -}}
|
||||
{{- end }}
|
||||
{{ if and (ne (len .ExactResults) 0) (ne (len .OtherResults) 0) }}<hr>{{ end }}
|
||||
{{ range .OtherResults -}}
|
||||
{{ template "word" . }}
|
||||
{{- define "title" }}{{ .Query }} search - {{ template "sitetitle" . }}{{- end -}}
|
||||
|
||||
{{- define "value" }}{{ .Query }}{{- end -}}
|
||||
|
||||
{{- define "results" -}}
|
||||
{{- template "entryfull" .Entry -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- template "search" . -}}
|
||||
|
||||
{{- template "index" . -}}
|
|
@ -1,22 +1,5 @@
|
|||
{{ define "word" }}
|
||||
<div class="box">
|
||||
<h3>
|
||||
{{- if .Kanji -}}
|
||||
<ruby>{{- .Kanji -}}<rp>(</rp><rt>{{- .Reading -}}</rt><rp>)</rp></ruby>
|
||||
{{- else -}}
|
||||
{{- .Reading -}}
|
||||
{{- end -}}
|
||||
</h3>
|
||||
{{ if le (len .Definitions) 2 -}}
|
||||
<p>{{- template "definition" (index .Definitions 0) -}}</p>
|
||||
{{- else -}}
|
||||
<ol>
|
||||
{{- range .Definitions }}
|
||||
<li>
|
||||
{{ template "definition" . }}
|
||||
</li>
|
||||
{{- end }}
|
||||
</ol>
|
||||
{{- end }}
|
||||
</div>
|
||||
{{ end }}
|
||||
{{- define "title" }}{{ .Entry.Kanji }} - {{ template "sitetitle" . }}{{- end -}}
|
||||
{{- define "results" -}}
|
||||
{{- template "entryfull" .Entry -}}
|
||||
{{- end -}}
|
||||
{{- template "index" . -}}
|
Reference in a new issue