From d4ab39551542495dce07748c46b4b507a3f480e9 Mon Sep 17 00:00:00 2001 From: James Mills Date: Wed, 5 Oct 2022 00:19:23 +0000 Subject: [PATCH] Refactor out the use of rice in favor of embed (#2) Co-authored-by: James Mills Reviewed-on: https://git.mills.io/prologic/spyda/pulls/2 --- .dockerignore | 2 - .gitignore | 6 +- Makefile | 8 +- go.mod | 10 +- go.sum | 40 +------ internal/handlers.go | 64 ----------- internal/page_handlers.go | 170 ++++++++++++++++++++++++++++++ internal/server.go | 16 +-- internal/static/css/spyda.min.css | 1 - internal/static/js/spyda.min.js | 36 ------- internal/static/static.go | 36 +++++++ internal/templates.go | 37 ++++--- internal/templates/templates.go | 22 ++++ 13 files changed, 270 insertions(+), 178 deletions(-) create mode 100644 internal/page_handlers.go delete mode 100644 internal/static/css/spyda.min.css delete mode 100644 internal/static/js/spyda.min.js create mode 100644 internal/static/static.go create mode 100644 internal/templates/templates.go diff --git a/.dockerignore b/.dockerignore index c4b9809..ef71ba9 100644 --- a/.dockerignore +++ b/.dockerignore @@ -13,5 +13,3 @@ Dockerfile /cmd/spyda/spyda /data/cache - -/internal/rice-box.go diff --git a/.gitignore b/.gitignore index 614b62e..69d8a30 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,7 @@ *~ *.db *.bak -*.oog +*.log **/.DS_Store @@ -9,4 +9,6 @@ /spyda /cmd/spyda/spyda -internal/rice-box.go \ No newline at end of file + +/internal/static/css/spyda.min.css +/internal/static/js/spyda.min.js diff --git a/Makefile b/Makefile index e960635..09ab22a 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,6 @@ COMMIT=$(shell git rev-parse --short HEAD || echo "$COMMIT") all: build deps: - @go install github.com/GeertJohan/go.rice/rice@latest @go install github.com/tdewolff/minify/cmd/minify@latest dev : DEBUG=1 @@ -26,12 +25,9 @@ build: server generate: @if [ x"$(DEBUG)" = x"1" ]; then \ echo 'Running in debug mode...'; \ - rm -f -v ./internal/rice-box.go; \ else \ - minify -o ./internal/static/css/spyda.min.css ./internal/static/css/[0-9]*-*.css; \ - minify -o ./internal/static/js/spyda.min.js ./internal/static/js/[0-9]*-*.js; \ - rm -f ./internal/rice-box.go; \ - rice -i ./internal embed-go; \ + minify -b -o ./internal/static/css/spyda.min.css ./internal/static/css/[0-9]*-*.css; \ + minify -b -o ./internal/static/js/spyda.min.js ./internal/static/js/[0-9]*-*.js; \ fi install: build diff --git a/go.mod b/go.mod index 95686a0..c0950b0 100644 --- a/go.mod +++ b/go.mod @@ -1,25 +1,22 @@ module git.mills.io/prologic/spyda -go 1.14 +go 1.16 require ( git.mills.io/prologic/bitcask v1.0.2 git.mills.io/prologic/observe v0.0.0-20210712230028-fc31c7aa2bd1 - github.com/GeertJohan/go.rice v1.0.2 github.com/Masterminds/goutils v1.1.1 // indirect github.com/Masterminds/semver v1.5.0 // indirect github.com/Masterminds/sprig v2.22.0+incompatible github.com/NYTimes/gziphandler v1.1.1 github.com/PuerkitoBio/goquery v1.6.1 // indirect github.com/RoaringBitmap/roaring v0.5.5 // indirect - github.com/akavel/rsrc v0.10.2 // indirect github.com/andreadipersio/securecookie v0.0.0-20131119095127-e3c3b33544ec github.com/antchfx/xmlquery v1.3.3 // indirect github.com/antchfx/xpath v1.1.11 // indirect github.com/apex/log v1.9.0 github.com/blevesearch/bleve/v2 v2.0.1 github.com/creasty/defaults v1.5.1 - github.com/daaku/go.zipexe v1.0.1 // indirect github.com/dgrijalva/jwt-go v3.2.0+incompatible github.com/dustin/go-humanize v1.0.0 github.com/elithrar/simple-scrypt v1.3.0 @@ -36,7 +33,6 @@ require ( github.com/huandu/xstrings v1.3.2 // indirect github.com/imdario/mergo v0.3.11 // indirect github.com/james4k/fmatter v0.0.0-20150827042251-377c8ea6259d - github.com/jessevdk/go-flags v1.5.0 // indirect github.com/julienschmidt/httprouter v1.3.0 github.com/justinas/nosurf v1.1.1 github.com/mitchellh/copystructure v1.1.1 // indirect @@ -46,15 +42,13 @@ require ( github.com/rainycape/unidecode v0.0.0-20150907023854-cb7f23ec59be // indirect github.com/renstrom/shortuuid v3.0.0+incompatible github.com/robfig/cron v1.2.0 + github.com/sasha-s/go-deadlock v0.3.1 github.com/sirupsen/logrus v1.8.1 github.com/spf13/pflag v1.0.5 github.com/steambap/captcha v1.3.1 github.com/stretchr/testify v1.7.0 - github.com/tdewolff/minify/v2 v2.12.0 // indirect - github.com/tdewolff/parse/v2 v2.6.2 // indirect github.com/tinylib/msgp v1.1.5 // indirect github.com/unrolled/logger v0.0.0-20201216141554-31a3694fe979 - github.com/valyala/fasttemplate v1.2.1 // indirect github.com/vcraescu/go-paginator v1.0.0 github.com/wblakecaldwell/profiler v0.0.0-20150908040756-6111ef1313a1 github.com/willf/bitset v1.1.11 // indirect diff --git a/go.sum b/go.sum index 481c557..f4723cf 100644 --- a/go.sum +++ b/go.sum @@ -44,10 +44,6 @@ git.mills.io/prologic/observe v0.0.0-20210712230028-fc31c7aa2bd1 h1:e6ZyAOFGLZJZ git.mills.io/prologic/observe v0.0.0-20210712230028-fc31c7aa2bd1/go.mod h1:/rNXqsTHGrilgNJYH/8wsIRDScyxXUhpbSdNbBatAKY= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/GeertJohan/go.incremental v1.0.0 h1:7AH+pY1XUgQE4Y1HcXYaMqAI0m9yrFqo/jt0CW30vsg= -github.com/GeertJohan/go.incremental v1.0.0/go.mod h1:6fAjUhbVuX1KcMD3c8TEgVUqmo4seqhv0i0kdATSkM0= -github.com/GeertJohan/go.rice v1.0.2 h1:PtRw+Tg3oa3HYwiDBZyvOJ8LdIyf6lAovJJtr7YOAYk= -github.com/GeertJohan/go.rice v1.0.2/go.mod h1:af5vUNlDNkCjOZeSGFgIJxDje9qdjsO6hshx0gTmZt4= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= @@ -74,9 +70,6 @@ github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/ github.com/abcum/lcp v0.0.0-20201209214815-7a3f3840be81 h1:uHogIJ9bXH75ZYrXnVShHIyywFiUZ7OOabwd9Sfd8rw= github.com/abcum/lcp v0.0.0-20201209214815-7a3f3840be81/go.mod h1:6ZvnjTZX1LNo1oLpfaJK8h+MXqHxcBFBIwkgsv+xlv0= github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= -github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c= -github.com/akavel/rsrc v0.10.2 h1:Zxm8V5eI1hW4gGaYsJQUhxpjkENuG91ki8B4zCrvEsw= -github.com/akavel/rsrc v0.10.2/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= @@ -154,7 +147,6 @@ github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cheekybits/is v0.0.0-20150225183255-68e9c0620927/go.mod h1:h/aW8ynjgkuj+NQRlZcDbAbM1ORAbXjXX77sX7T289U= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= @@ -185,9 +177,6 @@ github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsr github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creasty/defaults v1.5.1 h1:j8WexcS3d/t4ZmllX4GEkl4wIB/trOr035ajcLHCISM= github.com/creasty/defaults v1.5.1/go.mod h1:FPZ+Y0WNrbqOVw+c6av63eyHUAl6pMHZwqLPvXUZGfY= -github.com/daaku/go.zipexe v1.0.0/go.mod h1:z8IiR6TsVLEYKwXAoE/I+8ys/sDkgTzSL0CLnGVd57E= -github.com/daaku/go.zipexe v1.0.1 h1:wV4zMsDOI2SZ2m7Tdz1Ps96Zrx+TzaK15VbUaGozw0M= -github.com/daaku/go.zipexe v1.0.1/go.mod h1:5xWogtqlYnfBXkSB1o9xysukNP9GTvaNkqzUZbt3Bw8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -195,8 +184,6 @@ github.com/denisenkom/go-mssqldb v0.9.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27N github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= -github.com/djherbis/atime v1.1.0 h1:rgwVbP/5by8BvvjBNrbh64Qz33idKT3pSnMSJsxhi0g= -github.com/djherbis/atime v1.1.0/go.mod h1:28OF6Y8s3NQWwacXc5eZTsEsiMzp7LF8MbXE+XJPdBE= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= @@ -222,8 +209,6 @@ github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVB github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= -github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= github.com/gabstv/merger v1.0.1 h1:e6y87GkAX9XSNPZNCMvYf90ZNcr2PzbtvHN3pZZOQt0= github.com/gabstv/merger v1.0.1/go.mod h1:oQKCbAX4P6q0jk4s9Is144NojOE/HggFPb5qjPNZjq8= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= @@ -407,9 +392,6 @@ github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod github.com/james4k/fmatter v0.0.0-20150827042251-377c8ea6259d h1:+j8+Mdui1SE9TchF4Oxne37OWOYaLG91xFzLWehKPqE= github.com/james4k/fmatter v0.0.0-20150827042251-377c8ea6259d/go.mod h1:lxdGBh4Mr76rBen37GEal03CF0eF1qF5DSk2qfrrdo0= github.com/jawher/mow.cli v1.1.0/go.mod h1:aNaQlc7ozF3vw6IJ2dHjp2ZFiA4ozMIYY6PyuRJwlUg= -github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/jessevdk/go-flags v1.5.0 h1:1jKYvbxEjfUl0fmqTCOfonvskHHXMjBySTLW4y9LFvc= -github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= github.com/jinzhu/gorm v1.9.2 h1:lCvgEaqe/HVE+tjAR2mt4HbbHAZsQOv3XAZiEZV37iw= github.com/jinzhu/gorm v1.9.2/go.mod h1:Vla75njaFJ8clLU1W44h34PjIkijhjHIYnZxMqCdxqo= github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= @@ -456,8 +438,6 @@ github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0U github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= -github.com/matryer/try v0.0.0-20161228173917-9ac251b645a2 h1:JAEbJn3j/FrhdWA9jW8B5ajsLIjeuEHLi8xE4fk997o= -github.com/matryer/try v0.0.0-20161228173917-9ac251b645a2/go.mod h1:0KeJpeMD6o+O4hW7qJOT7vyQPKrWmj26uf5wMc/IiIs= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= @@ -505,8 +485,6 @@ github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzE github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= -github.com/nkovacs/streamquote v1.0.0 h1:PmVIV08Zlx2lZK5fFZlMZ04eHcDTIFJCv/5/0twVUow= -github.com/nkovacs/streamquote v1.0.0/go.mod h1:BN+NaZ2CmdKqUuTUXUEm9j95B2TRbpOWpxbJYzzgUsc= github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= @@ -532,6 +510,8 @@ github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtP github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= +github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 h1:q2e307iGHPdTGp0hoxKjt1H5pDo6utceo3dQVK3I5XQ= +github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o= github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= github.com/philhofer/fwd v1.1.1 h1:GdGcTjf5RNAxwS4QLsiMzJYj5KEvPJD3Abr261yRQXQ= github.com/philhofer/fwd v1.1.1/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= @@ -602,6 +582,8 @@ github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca h1:NugYot0LIVPxTvN8n+Kvkn6TrbMyxQiuvKdEwFdR9vI= github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca/go.mod h1:uugorj2VCxiV1x+LzaIdVa9b4S4qGAcH6cbhh4qVxOU= github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= +github.com/sasha-s/go-deadlock v0.3.1 h1:sqv7fDNShgjcaxkO0JNcOAlr8B9+cV5Ey/OB71efZx0= +github.com/sasha-s/go-deadlock v0.3.1/go.mod h1:F73l+cr82YSh10GxyRI6qZiCgK64VaZjwesgfQ1/iLM= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= @@ -661,13 +643,6 @@ github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5Cc github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= -github.com/tdewolff/minify/v2 v2.12.0 h1:ZyvMKeciyR3vzJrK/oHyBcSmpttQ/V+ah7qOqTZclaU= -github.com/tdewolff/minify/v2 v2.12.0/go.mod h1:8mvf+KglD7XurfvvFZDUYvVURy6bA/r0oTvmakXMnyg= -github.com/tdewolff/parse/v2 v2.6.1/go.mod h1:WzaJpRSbwq++EIQHYIRTpbYKNA3gn9it1Ik++q4zyho= -github.com/tdewolff/parse/v2 v2.6.2 h1:RDExtQ7ThRGSucatK0nri3p+HD/tSreYh1IDtDDAS/I= -github.com/tdewolff/parse/v2 v2.6.2/go.mod h1:woz0cgbLwFdtbjJu8PIKxhW05KplTFQkOdX78o+Jgrs= -github.com/tdewolff/test v1.0.6/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE= -github.com/tdewolff/test v1.0.7/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE= github.com/temoto/robotstxt v1.1.1 h1:Gh8RCs8ouX3hRSxxK7B1mO5RFByQ4CmJZDwgom++JaA= github.com/temoto/robotstxt v1.1.1/go.mod h1:+1AmkuG3IYkh1kv0d2qEB9Le88ehNO0zwOr3ujewlOo= github.com/tidwall/btree v0.4.2/go.mod h1:huei1BkDWJ3/sLXmO+bsCNELL+Bp2Kks9OLyQFkzvA8= @@ -692,11 +667,6 @@ github.com/unrolled/logger v0.0.0-20201216141554-31a3694fe979 h1:47+K4wN0S8L3fUw github.com/unrolled/logger v0.0.0-20201216141554-31a3694fe979/go.mod h1:X5DBNY1yIVkuLwJP3BXlCoQCa5mGg7hPJPIA0Blwc44= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= -github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= -github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= -github.com/valyala/fasttemplate v1.2.1 h1:TVEnxayobAdVkhQfrfes2IzOB6o+z4roRkPF52WA1u4= -github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= github.com/vcraescu/go-paginator v1.0.0 h1:ilNmRhlgG8N44LuxfGoPI2u8guXMA6gUqaPGA5BmRFs= github.com/vcraescu/go-paginator v1.0.0/go.mod h1:caZCjjt2qcA1O2aDzW7lwAcK4Rxw3LNvdEVF/ONxZWw= github.com/wblakecaldwell/profiler v0.0.0-20150908040756-6111ef1313a1 h1:Dz/PRieZRmOhDfOlkVpY1LYYIfNoTJjlDirAlagOr0s= @@ -934,9 +904,7 @@ golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007 h1:gG67DSER+11cZvqIMb8S8bt0vZtiN6xWYARwirrOSfE= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220829200755-d48e67d00261 h1:v6hYoSR9T5oet+pMXwUWkbiVqx/63mlHjefrHmxwfeY= golang.org/x/sys v0.0.0-20220829200755-d48e67d00261/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= diff --git a/internal/handlers.go b/internal/handlers.go index 37f3518..4d89611 100644 --- a/internal/handlers.go +++ b/internal/handlers.go @@ -10,11 +10,6 @@ import ( "strings" "time" - rice "github.com/GeertJohan/go.rice" - "github.com/gomarkdown/markdown" - "github.com/gomarkdown/markdown/html" - "github.com/gomarkdown/markdown/parser" - "github.com/james4k/fmatter" "github.com/julienschmidt/httprouter" log "github.com/sirupsen/logrus" "github.com/vcraescu/go-paginator" @@ -37,65 +32,6 @@ func (s *Server) NotFoundHandler(w http.ResponseWriter, r *http.Request) { s.render("404", w, ctx) } -type FrontMatter struct { - Title string -} - -// PageHandler ... -func (s *Server) PageHandler(name string) httprouter.Handle { - box := rice.MustFindBox("pages") - mdTpl := box.MustString(fmt.Sprintf("%s.md", name)) - - return func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { - ctx := NewContext(s.config, s.db, r) - - md, err := RenderString(mdTpl, ctx) - if err != nil { - log.WithError(err).Errorf("error rendering page %s", name) - ctx.Error = true - ctx.Message = "Error loading help page! Please contact support." - s.render("error", w, ctx) - return - } - - var frontmatter FrontMatter - content, err := fmatter.Read([]byte(md), &frontmatter) - if err != nil { - log.WithError(err).Error("error parsing front matter") - ctx.Error = true - ctx.Message = "Error loading page! Please contact support." - s.render("error", w, ctx) - return - } - - extensions := parser.CommonExtensions | parser.AutoHeadingIDs - p := parser.NewWithExtensions(extensions) - - htmlFlags := html.CommonFlags - opts := html.RendererOptions{ - Flags: htmlFlags, - Generator: "", - } - renderer := html.NewRenderer(opts) - - html := markdown.ToHTML(content, p, renderer) - - var title string - - if frontmatter.Title != "" { - title = frontmatter.Title - } else { - title = strings.Title(name) - } - ctx.Title = title - - ctx.Page = name - ctx.Content = template.HTML(html) - - s.render("page", w, ctx) - } -} - // IndexHandler ... func (s *Server) IndexHandler() httprouter.Handle { return func(w http.ResponseWriter, r *http.Request, p httprouter.Params) { diff --git a/internal/page_handlers.go b/internal/page_handlers.go new file mode 100644 index 0000000..05bd055 --- /dev/null +++ b/internal/page_handlers.go @@ -0,0 +1,170 @@ +// Copyright 2020-present Yarn.social +// SPDX-License-Identifier: AGPL-3.0-or-later + +package internal + +import ( + "embed" + "fmt" + "html/template" + "net/http" + "os" + "path/filepath" + "strings" + "time" + + "github.com/gomarkdown/markdown" + "github.com/gomarkdown/markdown/html" + "github.com/gomarkdown/markdown/parser" + "github.com/james4k/fmatter" + "github.com/julienschmidt/httprouter" + sync "github.com/sasha-s/go-deadlock" + log "github.com/sirupsen/logrus" +) + +const pagesDir = "pages" + +//go:embed pages/*.md +var builtinPages embed.FS + +type FrontMatter struct { + Title string + Description string +} + +type Page struct { + Content string + LastModified time.Time +} + +// PageHandler ... +func (s *Server) PageHandler(name string) httprouter.Handle { + pagesBaseDir := filepath.Join(s.config.Data, pagesDir) + + pageMutex := &sync.RWMutex{} + pageCache := make(map[string]*Page) + + getPage := func(name string) (*Page, error) { + fn := filepath.Join(pagesBaseDir, fmt.Sprintf("%s.md", name)) + + pageMutex.RLock() + page, isCached := pageCache[name] + pageMutex.RUnlock() + + if isCached && FileExists(fn) { + if fileInfo, err := os.Stat(fn); err == nil { + if fileInfo.ModTime().After(page.LastModified) { + data, err := os.ReadFile(fn) + if err != nil { + log.WithError(err).Warnf("error reading page %s", name) + return page, nil + } + page.Content = string(data) + page.LastModified = fileInfo.ModTime() + + pageMutex.Lock() + pageCache[name] = page + pageMutex.Unlock() + + return page, nil + } + } + } + + page = &Page{} + + if FileExists(fn) { + fileInfo, err := os.Stat(fn) + if err != nil { + log.WithError(err).Errorf("error getting page stats") + return nil, err + } + page.LastModified = fileInfo.ModTime() + + data, err := os.ReadFile(fn) + if err != nil { + log.WithError(err).Errorf("error reading page %s", name) + return nil, err + } + page.Content = string(data) + } else { + fn := filepath.Join(pagesDir, fmt.Sprintf("%s.md", name)) + data, err := builtinPages.ReadFile(fn) + if err != nil { + log.WithError(err).Errorf("error reading custom page %s", name) + return nil, err + } + page.Content = string(data) + } + + pageMutex.Lock() + pageCache[name] = page + pageMutex.Unlock() + + return page, nil + } + + return func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { + ctx := NewContext(s.config, s.db, r) + + page, err := getPage(name) + if err != nil { + if os.IsNotExist(err) { + ctx.Error = true + ctx.Message = "Page Not Found" + s.render("404", w, ctx) + return + } + ctx.Error = true + ctx.Message = "Error reading page" + s.render("message", w, ctx) + return + } + + markdownContent, err := RenderHTML(page.Content, ctx) + if err != nil { + log.WithError(err).Errorf("error rendering page %s", name) + ctx.Error = true + ctx.Message = "Error rendering page" + s.render("error", w, ctx) + return + } + + var frontmatter FrontMatter + content, err := fmatter.Read([]byte(markdownContent), &frontmatter) + if err != nil { + log.WithError(err).Error("error parsing front matter") + ctx.Error = true + ctx.Message = "Error loading page" + s.render("error", w, ctx) + return + } + + extensions := parser.CommonExtensions | parser.AutoHeadingIDs + p := parser.NewWithExtensions(extensions) + + htmlFlags := html.CommonFlags + opts := html.RendererOptions{ + Flags: htmlFlags, + Generator: "", + } + renderer := html.NewRenderer(opts) + + html := markdown.ToHTML(content, p, renderer) + + var title string + + if frontmatter.Title != "" { + title = frontmatter.Title + } else { + title = strings.Title(name) + } + ctx.Title = title + ctx.Meta.Description = frontmatter.Description + + ctx.Page = name + ctx.Content = template.HTML(html) + + s.render("page", w, ctx) + } +} diff --git a/internal/server.go b/internal/server.go index e8ebb7b..e93bafd 100644 --- a/internal/server.go +++ b/internal/server.go @@ -10,11 +10,10 @@ import ( "syscall" "time" - rice "github.com/GeertJohan/go.rice" + "git.mills.io/prologic/observe" "github.com/NYTimes/gziphandler" "github.com/gabstv/merger" "github.com/justinas/nosurf" - "git.mills.io/prologic/observe" "github.com/robfig/cron" log "github.com/sirupsen/logrus" "github.com/unrolled/logger" @@ -23,6 +22,7 @@ import ( "git.mills.io/prologic/spyda/internal/auth" "git.mills.io/prologic/spyda/internal/passwords" "git.mills.io/prologic/spyda/internal/session" + "git.mills.io/prologic/spyda/internal/static" ) var ( @@ -284,12 +284,12 @@ func (s *Server) initRoutes() { s.router.ServeFiles("/img/*filepath", http.Dir("./internal/static/img")) s.router.ServeFiles("/js/*filepath", http.Dir("./internal/static/js")) } else { - cssBox := rice.MustFindBox("static/css").HTTPBox() - imgBox := rice.MustFindBox("static/img").HTTPBox() - jsBox := rice.MustFindBox("static/js").HTTPBox() - s.router.ServeFilesWithCacheControl("/css/:commit/*filepath", cssBox) - s.router.ServeFilesWithCacheControl("/img/:commit/*filepath", imgBox) - s.router.ServeFilesWithCacheControl("/js/:commit/*filepath", jsBox) + cssFS := static.GetSubFilesystem("css") + imgFS := static.GetSubFilesystem("img") + jsFS := static.GetSubFilesystem("js") + s.router.ServeFilesWithCacheControl("/css/:commit/*filepath", cssFS) + s.router.ServeFilesWithCacheControl("/img/:commit/*filepath", imgFS) + s.router.ServeFilesWithCacheControl("/js/:commit/*filepath", jsFS) } s.router.NotFound = http.HandlerFunc(s.NotFoundHandler) diff --git a/internal/static/css/spyda.min.css b/internal/static/css/spyda.min.css deleted file mode 100644 index 63d2e74..0000000 --- a/internal/static/css/spyda.min.css +++ /dev/null @@ -1 +0,0 @@ -@charset "UTF-8";@keyframes anim-nova-toggle{from{max-height:0}to{max-height:500px}}*{font-family:oswald,sans-serif,monospace,segoe ui emoji;margin:0;padding:0}*:root{background:#000;color:#a9a9a9}address,area,article,aside,audio,blockquote,datalist,dl,details,fieldset,figure,form,input,iframe,meter,nav,ol,optgroup,option,output,p,pre,progress,ruby,section{margin-bottom:1rem}.container{position:relative;width:100%;max-width:960px;margin:0 auto;padding:0 20px;box-sizing:border-box}@media(min-width:400px){.container{width:85%;padding:0}}@media(min-width:550px){.container{width:80%}}.row .col{width:100%;float:left;box-sizing:border-box}@media(min-width:550px){.row .col{margin-left:4%}.row .col:first-child,.row .col:first-child{margin-left:0}}@media(min-width:550px){.row .one{width:4.66666666667%}.row .two{width:13.3333333333%}.row .three{width:22%}.row .four{width:30.6666666667%}.row .five{width:39.3333333333%}.row .six{width:48%}.row .seven{width:56.6666666667%}.row .eight{width:65.3333333333%}.row .nine{width:74%}.row .ten{width:82.6666666667%}.row .eleven{width:91.3333333333%}.row .twelve{width:100%;margin-left:0}.row .fill-one{margin-left:8.66666666667%}.row .fill-two{margin-left:17.3333333333%}.row .fill-three{margin-left:26%}.row .fill-four{margin-left:34.6666666667%}.row .fill-five{margin-left:43.3333333333%}.row .fill-six{margin-left:52%}.row .fill-seven{margin-left:60.6666666667%}.row .fill-eight{margin-left:69.3333333333%}.row .fill-nine{margin-left:78%}.row .fill-ten{margin-left:86.6666666667%}.row .fill-eleven{margin-left:95.3333333333%}}blockquote{padding:1.5rem;background:#111;border-left:5px solid #222}blockquote *:last-child{padding-bottom:0;margin-bottom:0}fieldset{margin-top:1rem;padding:2rem;border:1px solid #222;border-radius:4px}input{font-family:oswald,-apple-system,BlinkMacSystemFont,segoe ui,Roboto,Oxygen,Ubuntu,Cantarell,open sans,helvetica neue,sans-serif,apple color emoji,segoe ui emoji,segoe ui symbol,comic mono;padding:6px 12px;margin-bottom:.5rem;background:#111;color:#eee;border:1px solid #222;border-radius:4px;box-shadow:none;box-sizing:border-box}img{margin-bottom:1rem;max-width:100%}ol{padding-left:2rem}ol ul{margin-bottom:0}ol ol{margin-bottom:0}pre{font-family:Consolas,monaco,ubuntu mono,liberation mono,courier new,Courier,monospace;background:#111;border:1px solid #222;border-radius:4px;padding:3px 6px;font-size:.9em;padding:1rem 1.4rem;max-width:100%;overflow:auto}pre code{background:inherit;font-size:inherit;color:inherit;border:0;padding:0;margin:0}table{margin-bottom:1rem;border-collapse:collapse;width:100%}table caption{font-weight:700;margin-bottom:.5rem}textarea{margin-bottom:1rem;max-width:100%;padding:6px 12px;margin-bottom:.5rem;background:#111;color:#eee;border:1px solid #222;border-radius:4px;box-shadow:none;box-sizing:border-box}ul{margin-bottom:1rem;padding-left:2rem}ul ul{margin-bottom:0}ul ol{margin-bottom:0}video{margin-bottom:1rem}html{font-family:oswald,-apple-system,BlinkMacSystemFont,segoe ui,Roboto,Oxygen,Ubuntu,Cantarell,open sans,helvetica neue,sans-serif,apple color emoji,segoe ui emoji,segoe ui symbol,comic mono}select{font-family:oswald,-apple-system,BlinkMacSystemFont,segoe ui,Roboto,Oxygen,Ubuntu,Cantarell,open sans,helvetica neue,sans-serif,apple color emoji,segoe ui emoji,segoe ui symbol,comic mono;padding:6px 12px;margin-bottom:.5rem;background:#111;color:#eee;border:1px solid #222;border-radius:4px;box-shadow:none;box-sizing:border-box}button{font-family:oswald,-apple-system,BlinkMacSystemFont,segoe ui,Roboto,Oxygen,Ubuntu,Cantarell,open sans,helvetica neue,sans-serif,apple color emoji,segoe ui emoji,segoe ui symbol,comic mono;font-size:1rem;display:inline-block;padding:6px 12px;text-align:center;text-decoration:none;white-space:nowrap;background:#fff;color:#000;border:0;border-radius:4px;box-sizing:border-box;cursor:pointer;color:#000}button:focus{background:#fff}button:enabled:hover{background:#fff}body{margin:0 auto;padding:2rem;border-radius:6px;overflow-x:hidden;word-break:break-word;overflow-wrap:break-word;color:#eee;font-size:1.03rem;line-height:1.5}body::selection{background:#fff;color:#fff}h1{line-height:1;color:#fff;padding-top:.875rem;padding-bottom:2px;margin-bottom:8px;border-bottom:1px solid #111;font-size:2.25rem}h2{line-height:1;color:#fff;padding-top:.875rem;padding-bottom:2px;margin-bottom:8px;border-bottom:1px solid #111;font-size:1.85rem}h3{line-height:1;color:#fff;padding-top:.875rem;color:#fff;padding-bottom:2px;margin-bottom:8px;border-bottom:1px solid #111;font-size:1.55rem}h4{line-height:1;color:#fff;padding-top:.875rem;margin-bottom:.3rem;font-size:1.25rem}h5{line-height:1;color:#fff;padding-top:.875rem;margin-bottom:.3rem;font-size:1rem}h6{line-height:1;color:#fff;padding-top:.875rem;margin-bottom:.3rem;font-size:.875rem}a{color:#fff}a:hover{color:#fff}a button{font-size:1rem;display:inline-block;padding:6px 12px;text-align:center;text-decoration:none;white-space:nowrap;background:#fff;color:#000;border:0;border-radius:4px;box-sizing:border-box;cursor:pointer;color:#000}a button[disabled]{cursor:default;opacity:.5;cursor:not-allowed}abbr{cursor:help}abbr:hover{cursor:help}header{background:#111;border-bottom:1px solid #222;padding:2rem 1.5rem;margin:-2rem calc(0px - (50vw - 50%))2rem;padding-left:calc(50vw - 50%);padding-right:calc(50vw - 50%)}header h1{padding-bottom:0;border-bottom:0}header h2{padding-bottom:0;border-bottom:0}header h3{padding-bottom:0;border-bottom:0}header>*:first-child{margin-top:0;padding-top:0}header>*:last-child{margin-bottom:0}input[type=submit]{font-size:1rem;display:inline-block;padding:6px 12px;text-align:center;text-decoration:none;white-space:nowrap;background:#fff;color:#000;border:0;border-radius:4px;box-sizing:border-box;cursor:pointer;color:#000}input[type=submit]:focus{background:#fff}input[type=submit]:enabled:hover{background:#fff}input[type=reset]{font-size:1rem;display:inline-block;padding:6px 12px;text-align:center;text-decoration:none;white-space:nowrap;background:#fff;color:#000;border:0;border-radius:4px;box-sizing:border-box;cursor:pointer;color:#000}input[type=reset]:focus{background:#fff}input[type=reset]:enabled:hover{background:#fff}input[type=button]{font-size:1rem;display:inline-block;padding:6px 12px;text-align:center;text-decoration:none;white-space:nowrap;background:#fff;color:#000;border:0;border-radius:4px;box-sizing:border-box;cursor:pointer;color:#000}input[type=button]:focus{background:#fff}input[type=button]:enabled:hover{background:#fff}button[disabled]{cursor:default;opacity:.5;cursor:not-allowed}input[type=submit][disabled]{cursor:default;opacity:.5;cursor:not-allowed}input[type=reset][disabled]{cursor:default;opacity:.5;cursor:not-allowed}input[type=button][disabled]{cursor:default;opacity:.5;cursor:not-allowed}.button:focus{background:#fff}.button:enabled:hover{background:#fff}code{font-family:Consolas,monaco,ubuntu mono,liberation mono,courier new,Courier,monospace;background:#111;border:1px solid #222;border-radius:4px;padding:3px 6px;font-size:.9em}code pre{display:inline;background:inherit;font-size:inherit;color:inherit;border:0;padding:0;margin:0}kbd{font-family:Consolas,monaco,ubuntu mono,liberation mono,courier new,Courier,monospace;background:#111;border:1px solid #222;border-radius:4px;padding:3px 6px;font-size:.9em;border-bottom:3px solid #222}samp{font-family:Consolas,monaco,ubuntu mono,liberation mono,courier new,Courier,monospace;background:#111;border:1px solid #222;border-radius:4px;padding:3px 6px;font-size:.9em}.nova-menu-button{padding:.6rem 1rem;background:#111;border:1px solid #222;border-radius:4px;display:block;position:relative;text-align:center}.nova-menu-button summary::marker{content:''!important;display:none!important}@media(min-width:550px){.nova-menu-button{display:none}}.nova-menu-list{display:none;position:relative;text-align:center;padding-left:0;overflow:hidden}.nova-menu-list li{display:block;position:relative}@media(min-width:550px){.nova-menu-list{display:block;text-align:left}.nova-menu-list li{display:inline-block;position:relative;margin:auto 12px}}.nova-menu-button[open]+.nova-menu-list{display:block;max-height:0;padding-bottom:15px;background:#111;border:1px solid #222;border-radius:4px;animation-name:anim-nova-toggle;animation-duration:1s;animation-fill-mode:forwards}dt{font-weight:700}dd::before{content:'→ '}hr{border:0;border-bottom:1px solid #222;margin:1rem auto}legend{padding:auto .5rem}td{border:1px solid #222;text-align:left;padding:.5rem}th{border:1px solid #222;text-align:left;padding:.5rem;background:#111}tr:nth-child(even){background:#111}li{margin-top:.4rem}mark{padding:3px 6px;background:#fff;color:#fff}footer{text-align:center}.container:after,.row:after{content:"";display:table;clear:both}.full-width{width:100%;box-sizing:border-box}.nova-brand-logo{display:block;position:relative;text-align:center}.nova-brand-logo img{width:85%}@media(min-width:550px){.nova-brand-logo{width:120px}} \ No newline at end of file diff --git a/internal/static/js/spyda.min.js b/internal/static/js/spyda.min.js deleted file mode 100644 index 2261113..0000000 --- a/internal/static/js/spyda.min.js +++ /dev/null @@ -1,36 +0,0 @@ -var u=function(parameter,context){if(!(this instanceof u)){return new u(parameter,context);} -if(parameter instanceof u){return parameter;} -if(typeof parameter==='string'){parameter=this.select(parameter,context);} -if(parameter&¶meter.nodeName){parameter=[parameter];} -this.nodes=this.slice(parameter);};u.prototype={get length(){return this.nodes.length;}};u.prototype.nodes=[];u.prototype.addClass=function(){return this.eacharg(arguments,function(el,name){el.classList.add(name);});};u.prototype.adjacent=function(html,data,callback){if(typeof data==='number'){if(data===0){data=[];}else{data=new Array(data).join().split(',').map(Number.call,Number);}} -return this.each(function(node,j){var fragment=document.createDocumentFragment();u(data||{}).map(function(el,i){var part=(typeof html==='function')?html.call(this,el,i,node,j):html;if(typeof part==='string'){return this.generate(part);} -return u(part);}).each(function(n){this.isInPage(n)?fragment.appendChild(u(n).clone().first()):fragment.appendChild(n);});callback.call(this,node,fragment);});};u.prototype.after=function(html,data){return this.adjacent(html,data,function(node,fragment){node.parentNode.insertBefore(fragment,node.nextSibling);});};u.prototype.append=function(html,data){return this.adjacent(html,data,function(node,fragment){node.appendChild(fragment);});};u.prototype.args=function(args,node,i){if(typeof args==='function'){args=args(node,i);} -if(typeof args!=='string'){args=this.slice(args).map(this.str(node,i));} -return args.toString().split(/[\s,]+/).filter(function(e){return e.length;});};u.prototype.array=function(callback){callback=callback;var self=this;return this.nodes.reduce(function(list,node,i){var val;if(callback){val=callback.call(self,node,i);if(!val)val=false;if(typeof val==='string')val=u(val);if(val instanceof u)val=val.nodes;}else{val=node.innerHTML;} -return list.concat(val!==false?val:[]);},[]);};u.prototype.attr=function(name,value,data){data=data?'data-':'';return this.pairs(name,value,function(node,name){return node.getAttribute(data+name);},function(node,name,value){node.setAttribute(data+name,value);});};u.prototype.before=function(html,data){return this.adjacent(html,data,function(node,fragment){node.parentNode.insertBefore(fragment,node);});};u.prototype.children=function(selector){return this.map(function(node){return this.slice(node.children);}).filter(selector);};u.prototype.clone=function(){return this.map(function(node,i){var clone=node.cloneNode(true);var dest=this.getAll(clone);this.getAll(node).each(function(src,i){for(var key in this.mirror){if(this.mirror[key]){this.mirror[key](src,dest.nodes[i]);}}});return clone;});};u.prototype.getAll=function getAll(context){return u([context].concat(u('*',context).nodes));};u.prototype.mirror={};u.prototype.mirror.events=function(src,dest){if(!src._e)return;for(var type in src._e){src._e[type].forEach(function(ref){u(dest).on(type,ref.callback);});}};u.prototype.mirror.select=function(src,dest){if(u(src).is('select')){dest.value=src.value;}};u.prototype.mirror.textarea=function(src,dest){if(u(src).is('textarea')){dest.value=src.value;}};u.prototype.closest=function(selector){return this.map(function(node){do{if(u(node).is(selector)){return node;}}while((node=node.parentNode)&&node!==document);});};u.prototype.data=function(name,value){return this.attr(name,value,true);};u.prototype.each=function(callback){this.nodes.forEach(callback.bind(this));return this;};u.prototype.eacharg=function(args,callback){return this.each(function(node,i){this.args(args,node,i).forEach(function(arg){callback.call(this,node,arg);},this);});};u.prototype.empty=function(){return this.each(function(node){while(node.firstChild){node.removeChild(node.firstChild);}});};u.prototype.filter=function(selector){var callback=function(node){node.matches=node.matches||node.msMatchesSelector||node.webkitMatchesSelector;return node.matches(selector||'*');};if(typeof selector==='function')callback=selector;if(selector instanceof u){callback=function(node){return(selector.nodes).indexOf(node)!==-1;};} -return u(this.nodes.filter(callback));};u.prototype.find=function(selector){return this.map(function(node){return u(selector||'*',node);});};u.prototype.first=function(){return this.nodes[0]||false;};u.prototype.generate=function(html){if(/^\s* ]/.test(html)){return u(document.createElement('table')).html(html).children().children().nodes;}else if(/^\s* ]/.test(html)){return u(document.createElement('table')).html(html).children().children().children().nodes;}else if(/^\s*0;};u.prototype.isInPage=function isInPage(node){return(node===document.body)?false:document.body.contains(node);};u.prototype.last=function(){return this.nodes[this.length-1]||false;};u.prototype.map=function(callback){return callback?u(this.array(callback)).unique():this;};u.prototype.not=function(filter){return this.filter(function(node){return!u(node).is(filter||true);});};u.prototype.off=function(events,cb,cb2){var cb_filter_off=(cb==null&&cb2==null);var sel=null;var cb_to_be_removed=cb;if(typeof cb==='string'){sel=cb;cb_to_be_removed=cb2;} -return this.eacharg(events,function(node,event){u(node._e?node._e[event]:[]).each(function(ref){if(cb_filter_off||(ref.orig_callback===cb_to_be_removed&&ref.selector===sel)){node.removeEventListener(event,ref.callback);}});});};u.prototype.on=function(events,cb,cb2){var sel=null;var orig_callback=cb;if(typeof cb==='string'){sel=cb;orig_callback=cb2;cb=function(e){var args=arguments;var targetFound=false;u(e.currentTarget).find(sel).each(function(target){if(target===e.target||target.contains(e.target)){targetFound=true;try{Object.defineProperty(e,'currentTarget',{get:function(){return target;}});}catch(err){} -cb2.apply(target,args);}});if(!targetFound&&e.currentTarget===e.target){cb2.apply(e.target,args);}};} -var callback=function(e){return cb.apply(this,[e].concat(e.detail||[]));};return this.eacharg(events,function(node,event){node.addEventListener(event,callback);node._e=node._e||{};node._e[event]=node._e[event]||[];node._e[event].push({callback:callback,orig_callback:orig_callback,selector:sel});});};u.prototype.pairs=function(name,value,get,set){if(typeof value!=='undefined'){var nm=name;name={};name[nm]=value;} -if(typeof name==='object'){return this.each(function(node){for(var key in name){set(node,key,name[key]);}});} -return this.length?get(this.first(),name):'';};u.prototype.param=function(obj){return Object.keys(obj).map(function(key){return this.uri(key)+'='+this.uri(obj[key]);}.bind(this)).join('&');};u.prototype.parent=function(selector){return this.map(function(node){return node.parentNode;}).filter(selector);};u.prototype.prepend=function(html,data){return this.adjacent(html,data,function(node,fragment){node.insertBefore(fragment,node.firstChild);});};u.prototype.remove=function(){return this.each(function(node){if(node.parentNode){node.parentNode.removeChild(node);}});};u.prototype.removeClass=function(){return this.eacharg(arguments,function(el,name){el.classList.remove(name);});};u.prototype.replace=function(html,data){var nodes=[];this.adjacent(html,data,function(node,fragment){nodes=nodes.concat(this.slice(fragment.children));node.parentNode.replaceChild(fragment,node);});return u(nodes);};u.prototype.scroll=function(){this.first().scrollIntoView({behavior:'smooth'});return this;};u.prototype.select=function(parameter,context){parameter=parameter.replace(/^\s*/,'').replace(/\s*$/,'');if(/^0){client.timeout=options.timeout;client.ontimeout=function(){options.error('timeout','timeout',client);};} -client.open(options.type,options.url,options.async);for(var i in options.headers){if(options.headers.hasOwnProperty(i)){client.setRequestHeader(i,options.headers[i]);}} -client.send(options.data);client.onreadystatechange=function(){if(this.readyState==4&&((this.status>=200&&this.status<300)||this.status==304)){var data=this.responseText;var contentType=this.getResponseHeader('Content-Type');if(contentType&&contentType.match(/json/)){data=JSON.parse(this.responseText);} -options.success(data,this.statusText,this);}else if(this.readyState==4){options.error(this.status,this.statusText,this);}};if(options.async==false){if(client.readyState==4&&((client.status>=200&&client.status<300)||client.status==304)){options.success(client.responseText,client);}else if(client.readyState==4){options.error(client.status,client.statusText,client);}} -return client;};var _ajax=function(type,url,data,callback){if(typeof data==="function"){callback=data;data=undefined;} -return Twix.ajax({url:url,data:data,type:type,success:callback});};Twix.get=function(url,data,callback){return _ajax("GET",url,data,callback);};Twix.head=function(url,data,callback){return _ajax("HEAD",url,data,callback);};Twix.post=function(url,data,callback){return _ajax("POST",url,data,callback);};Twix.patch=function(url,data,callback){return _ajax("PATCH",url,data,callback);};Twix.put=function(url,data,callback){return _ajax("PUT",url,data,callback);};Twix.delete=function(url,data,callback){return _ajax("DELETE",url,data,callback);};Twix.options=function(url,data,callback){return _ajax("OPTIONS",url,data,callback);};return Twix;})();__=Twix;u("#burgerMenu").on("click",function(e){e.preventDefault();if(u("#mainNav").hasClass("responsive")){u("#mainNav").removeClass("responsive");}else{u("#mainNav").addClass("responsive");}}); \ No newline at end of file diff --git a/internal/static/static.go b/internal/static/static.go new file mode 100644 index 0000000..2dac6cf --- /dev/null +++ b/internal/static/static.go @@ -0,0 +1,36 @@ +package static + +import ( + "embed" + "io/fs" + "log" + "net/http" +) + +//go:embed css/*.css +//go:embed img/*.png img/*.svg +//go:embed js/*.js +var files embed.FS + +// MustGetFile returns the contents of a file from static as bytes. +func MustGetFile(name string) []byte { + b, err := files.ReadFile(name) + if err != nil { + panic(err) + } + return b +} + +// GetFilesystem returns a http.FileSystem for the static files. +func GetFilesystem() http.FileSystem { + return http.FS(files) +} + +// GetSubFilesystem returns a http.FileSystem for the static sub-files. +func GetSubFilesystem(name string) http.FileSystem { + fsys, err := fs.Sub(files, name) + if err != nil { + log.Fatalf("error loading sub-filesystem for %q: %s", name, err) + } + return http.FS(fsys) +} diff --git a/internal/templates.go b/internal/templates.go index 532dfd6..c77cc26 100644 --- a/internal/templates.go +++ b/internal/templates.go @@ -5,15 +5,16 @@ import ( "fmt" "html/template" "io" - "os" + "io/fs" "path/filepath" "strings" "sync" - rice "github.com/GeertJohan/go.rice" "github.com/Masterminds/sprig" humanize "github.com/dustin/go-humanize" log "github.com/sirupsen/logrus" + + "git.mills.io/prologic/spyda/internal/templates" ) const ( @@ -57,20 +58,14 @@ func (m *TemplateManager) LoadTemplates() error { m.Lock() defer m.Unlock() - box, err := rice.FindBox("templates") - if err != nil { - log.WithError(err).Errorf("error finding templates") - return fmt.Errorf("error finding templates: %w", err) - } - - err = box.Walk("", func(path string, info os.FileInfo, err error) error { + err := fs.WalkDir(templates.FS(), ".", func(path string, d fs.DirEntry, err error) error { if err != nil { - log.WithError(err).Error("error talking templates") + log.WithError(err).Error("error walking templates") return fmt.Errorf("error walking templates: %w", err) } - fname := info.Name() - if !info.IsDir() && fname != baseTemplate { + fname := d.Name() + if !d.IsDir() && fname != baseTemplate { // Skip _partials.html and also editor swap files, to improve the development // cycle. Editors often add suffixes to their swap files, e.g "~" or ".swp" // (Vim) and those files are not parsable as templates, causing panics. @@ -82,9 +77,9 @@ func (m *TemplateManager) LoadTemplates() error { t := template.New(name).Option("missingkey=zero") t.Funcs(m.funcMap) - template.Must(t.Parse(box.MustString(fname))) - template.Must(t.Parse(box.MustString(partialsTemplate))) - template.Must(t.Parse(box.MustString(baseTemplate))) + template.Must(t.Parse(templates.MustGetTemplate(fname))) + template.Must(t.Parse(templates.MustGetTemplate(partialsTemplate))) + template.Must(t.Parse(templates.MustGetTemplate(baseTemplate))) m.templates[name] = t } @@ -136,3 +131,15 @@ func (m *TemplateManager) Exec(name string, ctx *Context) (io.WriterTo, error) { return buf, nil } + +// RenderHTML ... +func RenderHTML(tpl string, ctx *Context) (string, error) { + t := template.Must(template.New("tpl").Parse(tpl)) + buf := bytes.NewBuffer([]byte{}) + err := t.Execute(buf, ctx) + if err != nil { + return "", err + } + + return buf.String(), nil +} diff --git a/internal/templates/templates.go b/internal/templates/templates.go new file mode 100644 index 0000000..ab620f3 --- /dev/null +++ b/internal/templates/templates.go @@ -0,0 +1,22 @@ +package templates + +import ( + "embed" + "io/fs" +) + +//go:embed *.html +var templates embed.FS + +// MustGetTemplate returns a template string with the given name. +func MustGetTemplate(name string) string { + b, err := templates.ReadFile(name) + if err != nil { + panic(err) + } + return string(b) +} + +func FS() fs.FS { + return templates +}