summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulien Dessaux2024-03-25 13:58:48 +0100
committerJulien Dessaux2024-03-25 13:58:48 +0100
commit4c9b51b8c6b2ebeea0481d219df89ed4fec1e360 (patch)
tree4fadf1fb8dc7de8de571d828ecf61014826d9e9e
parentchore(dictionary): go mod init and initial dictionary (diff)
downloadods-4c9b51b8c6b2ebeea0481d219df89ed4fec1e360.tar.gz
ods-4c9b51b8c6b2ebeea0481d219df89ed4fec1e360.tar.bz2
ods-4c9b51b8c6b2ebeea0481d219df89ed4fec1e360.zip
feat(ods): implement basic ods functionality
-rw-r--r--index.html29
-rw-r--r--main.go75
-rw-r--r--static/favicon.svg97
-rw-r--r--static/index4.css57
4 files changed, 258 insertions, 0 deletions
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..f98fd30
--- /dev/null
+++ b/index.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <link rel="icon" href="/static/favicon.svg">
+
+ <link rel="stylesheet" type="text/css" href="/static/index4.css" media="all">
+ <title>ODS</title>
+ </head>
+ <body>
+ <main>
+ <form action="/" method="post">
+ <input class="fullwidth" type="text" placeholder="Entrez un mot" id="query" name="query" value="{{ .Query }}" minlength="2" maxlength="32" onfocus="this.select()" required autofocus/>
+ <div class=".btn-group">
+ <input type="submit" value="Valider"/>
+ {{ if .HasQuery }}
+ <input type="submit" formmethod="GET" value="Effacer"/>
+ {{ end }}
+ </div>
+ </form>
+ <p>
+ {{ if .HasQuery }}
+ <a href="https://dictionnaire.lerobert.com/definition/{{ .Query }}">{{ .Query }}</a> est un mot <span class="{{ if .Invalid }}invalid">IN{{ else }}valid">{{ end }}VALIDE</span> au scrabble.
+ {{ end }}
+ </p>
+ </main>
+ </body>
+</html>
diff --git a/main.go b/main.go
new file mode 100644
index 0000000..3afc7cc
--- /dev/null
+++ b/main.go
@@ -0,0 +1,75 @@
+package main
+
+import (
+ "embed"
+ "html/template"
+ "log/slog"
+ "net/http"
+ "strings"
+)
+
+// Variables to customise the search behaviour
+const (
+ listenStr = "0.0.0.0:8090"
+)
+
+//go:embed ods.txt
+var ods string
+
+//go:embed index.html
+var templatesFS embed.FS
+
+//go:embed static/*
+var static embed.FS
+
+// html templates
+var indexTemplate = template.Must(template.New("index").ParseFS(templatesFS, "index.html"))
+
+type IndexData struct {
+ HasQuery bool
+ Query string
+ Invalid bool
+}
+
+func getIndex() http.Handler {
+ data := IndexData{
+ HasQuery: false,
+ Query: "",
+ Invalid: true,
+ }
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Cache-Control", "no-store, no-cache")
+ indexTemplate.ExecuteTemplate(w, "index.html", data)
+ })
+}
+
+func postIndex() http.Handler {
+ words := strings.Split(ods,"\n")
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ data := IndexData{
+ HasQuery: true,
+ Query: r.FormValue("query"),
+ Invalid: true,
+ }
+ query := strings.ToUpper(data.Query)
+ for _, w := range words {
+ if w == query {
+ data.Invalid = false
+ break
+ }
+ }
+ w.Header().Set("Cache-Control", "no-store, no-cache")
+ indexTemplate.ExecuteTemplate(w, "index.html", data)
+ })
+}
+
+// The main function
+func main() {
+ http.Handle("GET /static/", http.FileServer(http.FS(static)))
+ http.Handle("GET /", getIndex())
+ http.Handle("POST /", postIndex())
+ slog.Info("listening", "addr", listenStr)
+ if err := http.ListenAndServe(listenStr, nil); err != nil && err != http.ErrServerClosed {
+ slog.Error("error listening and serving", "error", err)
+ }
+}
diff --git a/static/favicon.svg b/static/favicon.svg
new file mode 100644
index 0000000..971d573
--- /dev/null
+++ b/static/favicon.svg
@@ -0,0 +1,97 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ width="180"
+ height="180"
+ viewBox="0 0 180 180"
+ version="1.1"
+ id="svg5"
+ inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)"
+ sodipodi:docname="favicon.svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg">
+ <sodipodi:namedview
+ id="namedview7"
+ pagecolor="#ffffff"
+ bordercolor="#000000"
+ borderopacity="0.25"
+ inkscape:showpageshadow="2"
+ inkscape:pageopacity="0.0"
+ inkscape:pagecheckerboard="0"
+ inkscape:deskcolor="#d1d1d1"
+ inkscape:document-units="px"
+ showgrid="false"
+ inkscape:zoom="1.3984437"
+ inkscape:cx="93.675563"
+ inkscape:cy="74.010846"
+ inkscape:window-width="1362"
+ inkscape:window-height="717"
+ inkscape:window-x="0"
+ inkscape:window-y="49"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="layer1" />
+ <defs
+ id="defs2">
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3622">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop3618" />
+ <stop
+ style="stop-color:#000000;stop-opacity:0;"
+ offset="1"
+ id="stop3620" />
+ </linearGradient>
+ <rect
+ x="21.339478"
+ y="33.460999"
+ width="232.05208"
+ height="284.04139"
+ id="rect3591" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3622"
+ id="linearGradient3624"
+ x1="19.339844"
+ y1="108.185"
+ x2="103.28756"
+ y2="108.185"
+ gradientUnits="userSpaceOnUse" />
+ </defs>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1">
+ <rect
+ style="fill:#fee797;stroke-width:8;fill-opacity:1;stroke:#000000;stroke-opacity:1;stroke-dasharray:none;stroke-linejoin:round;stroke-linecap:round"
+ id="rect113"
+ width="180"
+ height="180"
+ x="0"
+ y="0" />
+ <text
+ xml:space="preserve"
+ id="text3589"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:186.667px;font-family:monospace;-inkscape-font-specification:'monospace, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;white-space:pre;shape-inside:url(#rect3591);fill:#000000;stroke:#000000;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1;fill-opacity:1"
+ transform="translate(-0.935125,-48.075078)"><tspan
+ x="21.339844"
+ y="199.55305"
+ id="tspan7040">A</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:53.3333px;font-family:monospace;-inkscape-font-specification:'monospace, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+ x="138.96565"
+ y="149.52071"
+ id="text3732"><tspan
+ sodipodi:role="line"
+ id="tspan3730"
+ x="138.96565"
+ y="149.52071">1</tspan></text>
+ </g>
+</svg>
diff --git a/static/index4.css b/static/index4.css
new file mode 100644
index 0000000..34637fe
--- /dev/null
+++ b/static/index4.css
@@ -0,0 +1,57 @@
+* {
+ box-sizing: border-box;
+ scrollbar-gutter: stable both-edges;
+}
+
+body {
+ background: #009E60;
+ display: grid;
+ grid-template-rows: auto 1fr auto;
+ font-family: -apple-system, BlinkMacSystemFont,
+ "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell",
+ "Fira Sans", "Droid Sans", "Helvetica Neue",
+ sans-serif;
+ font-feature-settings: "kern" 1;
+ font-kerning: normal;
+}
+
+form {
+ align-items: center;
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: start;
+}
+
+input,.btn-group {
+ margin-top: 1em;
+ margin-right: 1.5em;
+}
+
+main {
+ background: #F6F7EB;
+ padding-left: 1em;
+ padding-right: 1em;
+}
+
+@media only screen and (min-width: 48rem) {
+ body {
+ max-width:48rem;
+ margin-left: auto;
+ margin-right: auto;
+ }
+}
+
+span {
+ font-weight: bold;
+ padding-bottom: 0.1em;
+ padding-left: 0.5em;
+ padding-right: 0.5em;
+ padding-top: 0.1em;
+}
+.valid {
+ background: #009E60;
+ color: #F6F7EB;
+}
+.invalid {
+ background: #E94F37;
+}