diff --git a/dict/main.go b/dict/main.go index 8b4328b..77755a9 100644 --- a/dict/main.go +++ b/dict/main.go @@ -6,7 +6,6 @@ import ( "log" "net/http" "os" - "strings" "foosoft.net/projects/jmdict" "git.elnu.com/ElnuDev/jichanorg/httputils" @@ -31,12 +30,7 @@ func LoadDict() error { type Entry struct { Kanji string Reading string - Definitions []Definition -} - -type Definition struct { - Definition string - PartOfSpeech []string + Definitions []string } func ParseEntry(entry jmdict.JmdictEntry) Entry { @@ -48,18 +42,11 @@ func ParseEntry(entry jmdict.JmdictEntry) Entry { if len(entry.Readings) > 0 { reading = entry.Readings[0].Reading } - var definitions []Definition - definitions = make([]Definition, len(entry.Sense)) - for i, sense := range entry.Sense { - definition := sense.Glossary[0].Content - if len(sense.Glossary) > 1 { - for _, glossary := range sense.Glossary[1:] { - definition += "; " + glossary.Content - } - } - definitions[i] = Definition{ - Definition: definition, - PartOfSpeech: sense.PartsOfSpeech, + var definitions []string + if len(entry.Sense) > 0 && len(entry.Sense[0].Glossary) > 0 { + definitions = make([]string, len(entry.Sense[0].Glossary)) + for i, glossary := range entry.Sense[0].Glossary { + definitions[i] = glossary.Content } } return Entry{ @@ -69,59 +56,25 @@ func ParseEntry(entry jmdict.JmdictEntry) Entry { } } -func Search(query string) (exactResults []Entry, otherResults []Entry, truncated bool) { - query = strings.TrimSpace(query) - exactResults = make([]Entry, 0) - otherResults = make([]Entry, 0) - count := 0 +func Search(query string) []Entry { + entries := make([]Entry, 0) for _, jmdictEntry := range dict.Entries { - exactMatch := false for _, kanji := range jmdictEntry.Kanji { if kanji.Expression == query { - exactMatch = true - goto match - } - if strings.Contains(kanji.Expression, query) { goto match } } - // TODO: Skip if query contains kanji for _, reading := range jmdictEntry.Readings { - if strings.Contains(reading.Reading, query) { + if reading.Reading == query { goto match } } continue match: entry := ParseEntry(jmdictEntry) - if exactMatch { - exactResults = append(exactResults, entry) - } else { - otherResults = append(otherResults, entry) - } - count++ - if count >= 500 { - truncated = true - break - } - } - return -} - -type searchTemplateData struct { - ExactResults []Entry - OtherResults []Entry - Truncated bool - Count int -} - -func initSearchTemplateData(exactResults []Entry, otherResults []Entry, truncated bool) searchTemplateData { - return searchTemplateData{ - ExactResults: exactResults, - OtherResults: otherResults, - Truncated: truncated, - Count: len(exactResults) + len(otherResults), + entries = append(entries, entry) } + return entries } func main() { @@ -132,34 +85,6 @@ 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 }, - []string{http.MethodGet}, - )) - redirectToHome := func(w http.ResponseWriter, r *http.Request) { - http.Redirect(w, r, "/", http.StatusPermanentRedirect) - } - r.HandleFunc("/search", redirectToHome) - r.HandleFunc("/search/", redirectToHome) - r.HandleFunc("/search/{query}", httputils.GenerateHandler( - "index.html", - func(w http.ResponseWriter, r *http.Request) bool { - return true - }, - func(w http.ResponseWriter, r *http.Request) any { - query := mux.Vars(r)["query"] - return struct { - Query string - Results searchTemplateData - }{ - Query: query, - Results: initSearchTemplateData(Search(query)), - } - }, - []string{http.MethodGet}, - )) r.HandleFunc("/api/search", httputils.GenerateHandler( "search.html", func(w http.ResponseWriter, r *http.Request) bool { @@ -169,17 +94,18 @@ func main() { w.Header().Set("Content-Type", "application/json; charset=utf-8") r.ParseMultipartForm(0) query := r.FormValue("q") - exactResults, otherResults, _ := Search(query) - jsonBytes, _ := json.Marshal(append(exactResults, otherResults...)) + entries := Search(query) + jsonBytes, _ := json.Marshal(entries) fmt.Fprint(w, string(jsonBytes)) return false }, func(w http.ResponseWriter, r *http.Request) any { r.ParseMultipartForm(0) query := r.FormValue("q") - return initSearchTemplateData(Search(query)) + entry := Search(query) + return entry }, - []string{http.MethodGet}, + []string{http.MethodGet, http.MethodPost}, )) r.Handle("/", http.FileServer(http.Dir("static"))) log.Fatal(http.ListenAndServe(":3334", r)) diff --git a/dict/templates/index.html b/dict/static/index.html similarity index 55% rename from dict/templates/index.html rename to dict/static/index.html index ca01362..cfebb64 100644 --- a/dict/templates/index.html +++ b/dict/static/index.html @@ -5,11 +5,6 @@ jidict - @@ -18,15 +13,12 @@
- +
-
- {{ with .Results }}{{ template "search" . }}{{ end }} -
+

diff --git a/dict/templates/definition.html b/dict/templates/definition.html deleted file mode 100644 index 86595c7..0000000 --- a/dict/templates/definition.html +++ /dev/null @@ -1,3 +0,0 @@ -{{- define "definition" -}} -{{ if .PartOfSpeech }}{{ .PartOfSpeech }}
{{ end }}{{ .Definition -}} -{{ end }} \ No newline at end of file diff --git a/dict/templates/search.html b/dict/templates/search.html index 90053b1..b87fb1c 100644 --- a/dict/templates/search.html +++ b/dict/templates/search.html @@ -1,11 +1,21 @@ -{{- define "search" -}} -

{{ 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 }}.

-{{- range .ExactResults -}} -{{- template "word" . -}} -{{- end }} -
-{{ range .OtherResults -}} -{{ template "word" . }} -{{- end -}} -{{- end -}} -{{- template "search" . -}} \ No newline at end of file +

{{ $count := (len .) }}{{ if eq $count 0 }}No results{{ else }}{{ $count }} result{{ if ne $count 1}}s{{ end }}{{ end }}.

+{{- range . -}} +
+

+ {{- if .Kanji -}} + {{- .Kanji -}}({{- .Reading -}}) + {{- else -}} + {{- .Reading -}} + {{- end -}} +

+ {{ if le (len .Definitions) 2 -}} +

{{- index .Definitions 0 -}}

+ {{- else -}} +
    + {{- range .Definitions }} +
  1. {{- . -}}
  2. + {{- end }} +
+ {{- end }} +
+{{ end -}} \ No newline at end of file diff --git a/dict/templates/word.html b/dict/templates/word.html deleted file mode 100644 index 40d56f8..0000000 --- a/dict/templates/word.html +++ /dev/null @@ -1,22 +0,0 @@ -{{ define "word" }} -
-

- {{- if .Kanji -}} - {{- .Kanji -}}({{- .Reading -}}) - {{- else -}} - {{- .Reading -}} - {{- end -}} -

- {{ if le (len .Definitions) 2 -}} -

{{- template "definition" (index .Definitions 0) -}}

- {{- else -}} -
    - {{- range .Definitions }} -
  1. - {{ template "definition" . }} -
  2. - {{- end }} -
- {{- end }} -
-{{ end }} \ No newline at end of file diff --git a/httputils/handler.go b/httputils/handler.go index a98c763..31bf89b 100644 --- a/httputils/handler.go +++ b/httputils/handler.go @@ -3,69 +3,23 @@ package httputils import ( "fmt" "net/http" - "os" - "path/filepath" - "strings" "text/template" - "time" ) type Handler = func(http.ResponseWriter, *http.Request) -const templateFolder = "templates" - -var templatePaths, templateModTimes, _ = getTemplates() -var templates *template.Template = template.Must(template.ParseFiles(templatePaths...)) - -func getTemplates() ([]string, map[string]time.Time, error) { - var modTimes map[string]time.Time = make(map[string]time.Time) - err := filepath.Walk(templateFolder, func(path string, info os.FileInfo, err error) error { - if err != nil { - return err - } - if !info.IsDir() && strings.HasSuffix(path, ".html") { - modTimes[path] = info.ModTime() - } - return nil - }) - paths := make([]string, len(modTimes)) - i := 0 - for path := range modTimes { - paths[i] = path - i++ - } - return paths, modTimes, err -} - -func reloadTemplateIfModified(path string) { - fileInfo, _ := os.Stat(path) - modTime := fileInfo.ModTime() - if modTime.After(templateModTimes[path]) { - fmt.Printf("Reloading template %s...\n", path) - templates.ParseFiles(path) - templateModTimes[path] = modTime - } -} - -func reloadTemplatesIfModified() { - for _, path := range templatePaths { - reloadTemplateIfModified(path) - } -} - -const reloadTemplates = true - func GenerateHandler( file string, handler func(http.ResponseWriter, *http.Request) bool, data func(http.ResponseWriter, *http.Request) any, methods []string, ) Handler { + var tmpl *template.Template + if file != "" { + tmpl = template.Must(template.ParseFiles(fmt.Sprintf("templates/%s", file))) + } return func(w http.ResponseWriter, r *http.Request) { - // All templates must be reloaded in case of dependencies - if reloadTemplates { - reloadTemplatesIfModified() - } + tmpl = template.Must(template.ParseFiles(fmt.Sprintf("templates/%s", file))) for _, method := range methods { if method == r.Method { goto ok @@ -75,9 +29,9 @@ func GenerateHandler( return ok: renderTemplate := handler(w, r) - if renderTemplate && file != "" { + if renderTemplate && tmpl != nil { w.Header().Set("Content-Type", "text/html; charset=utf-8") - templates.ExecuteTemplate(w, file, data(w, r)) + tmpl.Execute(w, data(w, r)) } } }