commit 1df852e7e5492c1d366faa436d2c885c473883c9 Author: Erik Winter Date: Fri Dec 4 12:50:20 2020 +0100 initial import diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..8283089 --- /dev/null +++ b/go.mod @@ -0,0 +1,8 @@ +module git.sr.ht/~ewintr/shitty-ssg + +go 1.14 + +require ( + git.sr.ht/~ewintr/erikwinternl/shitty-ssg v0.0.0-20201204092507-5528bf33815d // indirect + git.sr.ht/~ewintr/go-kit v0.0.0-20200704112030-36275689b0ea +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..6142bd2 --- /dev/null +++ b/go.sum @@ -0,0 +1,352 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +git.sr.ht/~ewintr/erikwinternl/shitty-ssg v0.0.0-20201204092507-5528bf33815d/go.mod h1:ka/PzT9A0BNvjcUQpIM0YE1BnOR1/qr6x7XeCUyYDlw= +git.sr.ht/~ewintr/go-kit v0.0.0-20200704112030-36275689b0ea h1:YdHan+/QwjzF05Dlp40BHw5N47nWy2QZCY7aseXf2n0= +git.sr.ht/~ewintr/go-kit v0.0.0-20200704112030-36275689b0ea/go.mod h1:zrpigRr1EHuVGw7GWwvYWwfLgdAwJ110zIRAGtaicvI= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= +github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= +github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= +github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= +github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= +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= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= +github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= +github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= +github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= +github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= +github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= +github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= +github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= +github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= +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/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= +github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= +github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= +github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= +github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= +github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= +github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= +github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= +github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= +github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= +github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= +github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= +github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= +github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= +github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k= +github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= +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/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/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= +github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= +github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= +github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= +github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= +github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= +github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= +github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= +github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= +github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= +github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= +github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +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/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= +go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= +gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= +gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= +sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= diff --git a/main.go b/main.go new file mode 100644 index 0000000..edf9f78 --- /dev/null +++ b/main.go @@ -0,0 +1,51 @@ +package main + +import ( + "flag" + "log" + "os" + "path/filepath" + "strings" + + "git.sr.ht/~ewintr/shitty-ssg/site" +) + +var ( + resources = flag.String("resources", "./resources", "folder with templates and other resources") + content = flag.String("content", "./content,/projectx", "comma separated list of folders search for content") + public = flag.String("public", "./public", "target folder for generated site") +) + +func main() { + flag.Parse() + if *resources == "" || *content == "" || *public == "" { + log.Fatal("missing parameter") + } + + // initialize site + s, err := site.New(*resources) + if err != nil { + log.Fatal(err) + } + + // add content + for _, cp := range strings.Split(*content, ",") { + log.Printf("checking %s for content\n", cp) + if err := filepath.Walk(cp, func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + if !info.IsDir() && filepath.Ext(path) == ".adoc" { + s.AddFilePost(path) + } + return nil + }); err != nil { + log.Fatal(err) + } + } + + // render site + if err := s.RenderHTML(*public); err != nil { + log.Fatal(err) + } +} diff --git a/resources/about/rss.png b/resources/about/rss.png new file mode 100644 index 0000000..e047c86 Binary files /dev/null and b/resources/about/rss.png differ diff --git a/resources/font/Amiko-Bold.ttf b/resources/font/Amiko-Bold.ttf new file mode 100644 index 0000000..ce0d43b Binary files /dev/null and b/resources/font/Amiko-Bold.ttf differ diff --git a/resources/font/Amiko-Regular.ttf b/resources/font/Amiko-Regular.ttf new file mode 100644 index 0000000..33cb7f9 Binary files /dev/null and b/resources/font/Amiko-Regular.ttf differ diff --git a/resources/font/Amiko-SemiBold.ttf b/resources/font/Amiko-SemiBold.ttf new file mode 100644 index 0000000..366e073 Binary files /dev/null and b/resources/font/Amiko-SemiBold.ttf differ diff --git a/resources/font/Merriweather-Regular.otf b/resources/font/Merriweather-Regular.otf new file mode 100644 index 0000000..f8d16bd Binary files /dev/null and b/resources/font/Merriweather-Regular.otf differ diff --git a/resources/font/merriweather.regular.ttf b/resources/font/merriweather.regular.ttf new file mode 100644 index 0000000..f61c2fe Binary files /dev/null and b/resources/font/merriweather.regular.ttf differ diff --git a/resources/other/beginnenmetroken.jpg b/resources/other/beginnenmetroken.jpg new file mode 100644 index 0000000..017ae53 Binary files /dev/null and b/resources/other/beginnenmetroken.jpg differ diff --git a/resources/other/christel 39.mp3 b/resources/other/christel 39.mp3 new file mode 100644 index 0000000..4df0d26 Binary files /dev/null and b/resources/other/christel 39.mp3 differ diff --git a/resources/other/crunchy.jpeg b/resources/other/crunchy.jpeg new file mode 100644 index 0000000..96f5080 Binary files /dev/null and b/resources/other/crunchy.jpeg differ diff --git a/resources/other/lowlandswedstrijd.jpg b/resources/other/lowlandswedstrijd.jpg new file mode 100644 index 0000000..d631b1f Binary files /dev/null and b/resources/other/lowlandswedstrijd.jpg differ diff --git a/resources/other/volca testje.mp3 b/resources/other/volca testje.mp3 new file mode 100644 index 0000000..3aa1be6 Binary files /dev/null and b/resources/other/volca testje.mp3 differ diff --git a/resources/other/volca.png b/resources/other/volca.png new file mode 100644 index 0000000..0f233d0 Binary files /dev/null and b/resources/other/volca.png differ diff --git a/resources/other/werkeloos.mp3 b/resources/other/werkeloos.mp3 new file mode 100644 index 0000000..e300bd3 Binary files /dev/null and b/resources/other/werkeloos.mp3 differ diff --git a/resources/template/about.gohtml b/resources/template/about.gohtml new file mode 100644 index 0000000..7e7073a --- /dev/null +++ b/resources/template/about.gohtml @@ -0,0 +1,19 @@ + + +{{- template "head" . -}} + +{{- template "menu" -}} +
+
+

Hi,

+

As you may have guessed from the contents of this site, I am a Dutch software developer who also likes literature and music and a bunch of other things.

+

I am old enough to remember what the internet was like before platforms like Facebook, Twitter, Github, etc. came around. Everything was decentralized, everybody had their own website and it actually felt more personal and real than the “social” media of today.

+

Since I like to create things, I thought I’d make myself an old school personal website again. For my own pleasure. And for others like me. I know you are out there!

+

RSS Feeds

+

To stay updated, there is an RSS link: RSS IconRecent

+

Contact

+

I'm @ewintr@fosstodon.org on Mastodon.

+

Otherwise, you can contact me by sending me an email.

+
+
+ diff --git a/resources/template/archive.gohtml b/resources/template/archive.gohtml new file mode 100644 index 0000000..6ddc504 --- /dev/null +++ b/resources/template/archive.gohtml @@ -0,0 +1,43 @@ + + +{{- template "head" . -}} + +{{- template "menu" -}} +
+ + + +
+ diff --git a/resources/template/head.gohtml b/resources/template/head.gohtml new file mode 100644 index 0000000..235fe50 --- /dev/null +++ b/resources/template/head.gohtml @@ -0,0 +1,56 @@ +{{ define "head" }} + + {{ .Title }} - ErikWinter.nl + + + + + + + +{{ end }} diff --git a/resources/template/list.gohtml b/resources/template/list.gohtml new file mode 100644 index 0000000..b558ade --- /dev/null +++ b/resources/template/list.gohtml @@ -0,0 +1,23 @@ + + +{{- template "head" . -}} + +{{- template "menu" -}} +
+ +
+ + diff --git a/resources/template/menu.gohtml b/resources/template/menu.gohtml new file mode 100644 index 0000000..9035ecf --- /dev/null +++ b/resources/template/menu.gohtml @@ -0,0 +1,16 @@ +{{ define "menu" }} + + +{{ end }} diff --git a/resources/template/other.gohtml b/resources/template/other.gohtml new file mode 100644 index 0000000..29ba63f --- /dev/null +++ b/resources/template/other.gohtml @@ -0,0 +1,37 @@ + + +{{- template "head" . -}} + +{{- template "menu" -}} +
+
+
+

Crunchy Granola logo

+

A site 🇳🇱 full of recipes for crunchy, tasty granolas that are nothing like the mundane stuff you buy at the store. Everything made from scratch, healthy ingredients, with options for all kinds of diets like gluten-free and keto. All recipes, photos, texts and design created by my wonderful girlfriend. I -eh- also did things.

+
+
+

Volca Keys

+

Some sounds I made. Some time ago.

+ + + +
+
+

Story illustration

+

In 2015, one of my stories won the Lowlands Short Story contest. Because of that, it was featured in NRC, a Dutch national newspaper. You can read it here 🇳🇱 on their site.

+
+
+

Logo Beginnenmetroken.nl

+

A long time ago, somewhere at the start of this century, I created www.BeginnenMetRoken.nl, a satirical site that “helped” people to kickstart their smoking habit. Right in the middle of large campaings urging people to quit, it struck a nerve and went viral. Millions of pageviews, featured in several magazines. People still bring it up, twenty years later.

+

The site is gone, but it you can still view it here 🇳🇱 on Archive.org.

+
+
+
+ + diff --git a/resources/template/post.gohtml b/resources/template/post.gohtml new file mode 100644 index 0000000..6681067 --- /dev/null +++ b/resources/template/post.gohtml @@ -0,0 +1,14 @@ + + +{{- template "head" . -}} + +{{- template "menu" -}} +
+
+

{{ .Title }}

+ + {{ .Content }} +
+
+ + diff --git a/resources/template/rss.goxml b/resources/template/rss.goxml new file mode 100644 index 0000000..c05efb0 --- /dev/null +++ b/resources/template/rss.goxml @@ -0,0 +1,20 @@ + + + + ErikWinter.nl + https://erikwinter.nl/ + Activity on ErikWinter.nl + en-us + {{ .DateFormal }} + + {{- range .Posts -}} + + {{ .Title }} + {{ .Link }} + {{ .DateFormal }} + {{ .Link }} + {{ .Content }} + + {{- end -}} + + diff --git a/site/block.go b/site/block.go new file mode 100644 index 0000000..dd04b1e --- /dev/null +++ b/site/block.go @@ -0,0 +1,93 @@ +package site + +import ( + "fmt" + "html" + "strings" +) + +type BlockElement interface { + Text() string + BlockHTML() string +} + +type Paragraph []InlineElement + +func (p Paragraph) Text() string { + var text []string + for _, ie := range p { + text = append(text, ie.Text()) + } + + return strings.Join(text, " ") +} + +func (p Paragraph) BlockHTML() string { + var body string + for _, ie := range p { + body += ie.InlineHTML() + } + + return fmt.Sprintf("

%s

", body) +} + +type SubTitle string + +func (st SubTitle) Text() string { return string(st) } +func (st SubTitle) BlockHTML() string { + return fmt.Sprintf("

%s

", st) +} + +type SubSubTitle string + +func (st SubSubTitle) Text() string { return string(st) } +func (st SubSubTitle) BlockHTML() string { + return fmt.Sprintf("

%s

", st) +} + +type CodeBlock string + +func (cb CodeBlock) Text() string { return string(cb) } +func (cb CodeBlock) BlockHTML() string { + return fmt.Sprintf("
%s
", html.EscapeString(string(cb))) +} + +type ListItem []InlineElement + +func (li ListItem) Text() string { + var text []string + for _, ie := range li { + text = append(text, ie.Text()) + } + + return fmt.Sprintf("%s%s", LISTITEM_PREFIX, strings.Join(text, " ")) +} + +func (li ListItem) HTML() string { + var body string + for _, ie := range li { + body += ie.InlineHTML() + } + + return fmt.Sprintf("
  • %s
  • ", body) +} + +type List []ListItem + +func (l List) Text() string { + var items []string + for _, item := range l { + items = append(items, item.Text()) + } + + return strings.Join(items, "\n") +} + +func (l List) BlockHTML() string { + var items []string + for _, item := range l { + items = append(items, item.HTML()) + } + + return fmt.Sprintf("", strings.Join(items, "\n")) +} diff --git a/site/block_test.go b/site/block_test.go new file mode 100644 index 0000000..e61cb6e --- /dev/null +++ b/site/block_test.go @@ -0,0 +1,27 @@ +package site + +import ( + "fmt" + "testing" + + "git.sr.ht/~ewintr/go-kit/test" +) + +func TestParagraph(t *testing.T) { + p := Paragraph([]InlineElement{ + PlainText("one "), + PlainText("two "), + PlainText("three"), + }) + + exp := "

    one two three

    " + test.Equals(t, exp, p.BlockHTML()) +} + +func TestSubTitle(t *testing.T) { + text := "text" + st := SubTitle(text) + + exp := fmt.Sprintf("

    %s

    ", text) + test.Equals(t, exp, st.BlockHTML()) +} diff --git a/site/html.go b/site/html.go new file mode 100644 index 0000000..75d860b --- /dev/null +++ b/site/html.go @@ -0,0 +1,18 @@ +package site + +type HTMLPost struct { + Slug string + Title string + DateLong string + DateShort string + Content string +} + +type HTMLSummary struct { + Link string + Title string + Language Language + DateShort string + DateLong string + Summary string +} diff --git a/site/inline.go b/site/inline.go new file mode 100644 index 0000000..33e3c59 --- /dev/null +++ b/site/inline.go @@ -0,0 +1,71 @@ +package site + +import ( + "fmt" + "html" +) + +type InlineType int + +type InlineElement interface { + Text() string + InlineHTML() string +} + +type PlainText string + +func (pt PlainText) Text() string { return string(pt) } + +func (pt PlainText) InlineHTML() string { + return html.EscapeString(string(pt)) +} + +type StrongText string + +func (st StrongText) Text() string { return string(st) } + +func (st StrongText) InlineHTML() string { + return fmt.Sprintf("%s", html.EscapeString(string(st))) +} + +type EmpText string + +func (et EmpText) Text() string { return string(et) } + +func (et EmpText) InlineHTML() string { + return fmt.Sprintf("%s", html.EscapeString(string(et))) +} + +type StrongEmpText string + +func (set StrongEmpText) Text() string { return string(set) } + +func (set StrongEmpText) InlineHTML() string { + return fmt.Sprintf("%s", html.EscapeString(string(set))) +} + +type Link struct { + url string + title string +} + +func NewLink(url, title string) Link { + return Link{ + url: url, + title: title, + } +} + +func (l Link) Text() string { return l.title } + +func (l Link) InlineHTML() string { + return fmt.Sprintf("%s", l.url, html.EscapeString(l.title)) +} + +type CodeText string + +func (ct CodeText) Text() string { return string(ct) } + +func (ct CodeText) InlineHTML() string { + return fmt.Sprintf("%s", html.EscapeString(string(ct))) +} diff --git a/site/inline_test.go b/site/inline_test.go new file mode 100644 index 0000000..1d6b224 --- /dev/null +++ b/site/inline_test.go @@ -0,0 +1,41 @@ +package site_test + +import ( + "fmt" + "testing" + + "git.sr.ht/~ewintr/go-kit/test" + "git.sr.ht/~ewintr/shitty-ssg/site" +) + +func TestPlainText(t *testing.T) { + text := "text" + pt := site.PlainText(text) + + test.Equals(t, text, pt.InlineHTML()) +} + +func TestStrongText(t *testing.T) { + text := "text" + st := site.StrongText(text) + exp := fmt.Sprintf("%s", text) + + test.Equals(t, exp, st.InlineHTML()) +} + +func TestEmpText(t *testing.T) { + text := "text" + et := site.EmpText(text) + exp := fmt.Sprintf("%s", text) + + test.Equals(t, exp, et.InlineHTML()) +} + +func TestLink(t *testing.T) { + url := "http://example.com" + title := "link title" + link := site.NewLink(url, title) + exp := fmt.Sprintf("%s", url, title) + + test.Equals(t, exp, link.InlineHTML()) +} diff --git a/site/meta.go b/site/meta.go new file mode 100644 index 0000000..fc0d48b --- /dev/null +++ b/site/meta.go @@ -0,0 +1,59 @@ +package site + +const ( + KIND_NOTE = Kind("note") + KIND_STORY = Kind("story") + KIND_ARTICLE = Kind("article") + KIND_INVALID = Kind("") +) + +type Kind string + +var pluralKind = map[Kind]string{ + KIND_NOTE: "notes", + KIND_STORY: "stories", + KIND_ARTICLE: "articles", +} + +func NewKind(kind string) Kind { + switch kind { + case "note": + return KIND_NOTE + case "story": + return KIND_STORY + case "article": + return KIND_ARTICLE + default: + return KIND_INVALID + } + +} + +const ( + LANGUAGE_EN = Language("en") + LANGUAGE_NL = Language("nl") + LANGUAGE_INVALID = Language("") +) + +type Language string + +func NewLanguage(text string) Language { + switch text { + case "nl": + return LANGUAGE_NL + case "en": + fallthrough + default: + return LANGUAGE_EN + } +} + +type Tag string + +const ( + DATE_SHORT DateFormat = iota + DATE_LONG + DATE_FORMAL //Sat, 12 Sep 2020 12:32:00 +0200 +) + +type DateFormat int diff --git a/site/parser.go b/site/parser.go new file mode 100644 index 0000000..5f72090 --- /dev/null +++ b/site/parser.go @@ -0,0 +1,232 @@ +package site + +import ( + "strings" + "time" +) + +const ( + TITLE_PREFIX = "= " + SUBTITLE_PREFIX = "== " + SUBSUBTITLE_PREFIX = "=== " + PARAGRAPH_SEPARATOR = "\n\n" + LINE_SEPARATOR = "\n" + CODE_PREFIX = "----\n" + CODE_SUFFIX = "\n----" + LISTITEM_PREFIX = "* " + PARAGRAPH_CONTINUATION = "\n+\n" +) + +func NewPost(text string) Post { + post := Post{ + Language: LANGUAGE_EN, + Tags: []Tag{}, + } + + // split up blocks + var pars []string + for _, s := range strings.Split(text, PARAGRAPH_SEPARATOR) { + if s == "" { + continue + } + + pars = append(pars, s) + } + + // actually, code blocks are allowed to have empty lines + var blocks []string + var inCode bool + var currentBlock string + for _, par := range pars { + switch { + case strings.HasPrefix(par, CODE_PREFIX) && strings.HasSuffix(par, CODE_SUFFIX): + blocks = append(blocks, par) + case !inCode && strings.HasPrefix(par, CODE_PREFIX): + inCode = true + currentBlock = par + case inCode && !strings.HasSuffix(par, CODE_SUFFIX): + currentBlock += PARAGRAPH_SEPARATOR + par + case inCode && strings.HasSuffix(par, CODE_SUFFIX): + currentBlock += PARAGRAPH_SEPARATOR + par + blocks = append(blocks, currentBlock) + inCode = false + currentBlock = "" + default: + blocks = append(blocks, par) + } + } + + // interpret the blocks + for i, p := range blocks { + switch { + case i == 0 && strings.HasPrefix(p, TITLE_PREFIX): + ParseHeader(p, &post) + case strings.HasPrefix(p, SUBTITLE_PREFIX): + p = strings.TrimSpace(p) + s := strings.Split(p, SUBTITLE_PREFIX) + if len(s) == 1 || s[1] == "" { + + continue + } + post.Content = append(post.Content, SubTitle(s[1])) + case strings.HasPrefix(p, SUBSUBTITLE_PREFIX): + p = strings.TrimSpace(p) + s := strings.Split(p, SUBSUBTITLE_PREFIX) + if len(s) == 1 || s[1] == "" { + + continue + } + post.Content = append(post.Content, SubSubTitle(s[1])) + case isCodeBlock(p): + post.Content = append(post.Content, parseCodeBlock(p)) + case strings.HasPrefix(p, LISTITEM_PREFIX): + p = strings.TrimSpace(p) + var items []ListItem + for i, ti := range strings.Split(p, LISTITEM_PREFIX) { + if i > 0 { + inline := ParseInline(strings.TrimSpace(ti)) + items = append(items, ListItem(inline)) + } + } + post.Content = append(post.Content, List(items)) + + default: + p = strings.TrimSpace(p) + post.Content = append(post.Content, Paragraph(ParseInline(p))) + } + } + + return post +} + +func isCodeBlock(par string) bool { + return strings.HasPrefix(par, CODE_PREFIX) && strings.HasSuffix(par, CODE_SUFFIX) +} + +func parseCodeBlock(par string) CodeBlock { + ss := strings.Split(par, "\n") + ss = ss[1 : len(ss)-1] + content := strings.Join(ss, "\n") + + return CodeBlock(content) +} + +func ParseHeader(text string, post *Post) { + text = strings.TrimSpace(text) + lines := strings.Split(text, LINE_SEPARATOR) + for i, l := range lines { + switch { + case i == 0: + s := strings.Split(l, TITLE_PREFIX) + post.Title = s[1] + case isDate(l): + date, _ := time.Parse("2006-01-02", l) + post.Date = date + case strings.HasPrefix(l, ":kind:"): + s := strings.Split(l, ":") + post.Kind = NewKind(strings.TrimSpace(s[2])) + case strings.HasPrefix(l, ":language:"): + s := strings.Split(l, ":") + post.Language = NewLanguage(strings.TrimSpace(s[2])) + case strings.HasPrefix(l, ":tags:"): + s := strings.Split(l, ":") + t := strings.Split(s[2], ",") + for _, tag := range t { + post.Tags = append(post.Tags, Tag(strings.TrimSpace(tag))) + } + default: + post.Author = l + } + } +} + +func isDate(text string) bool { + if _, err := time.Parse("2006-01-02", text); err == nil { + return true + } + + return false +} + +func ParseInline(text string) []InlineElement { + var e []InlineElement + + ss := strings.Split(text, "") + var buffer, curWord, prevChar string + var strong, emp, code, linkTitle bool + wordStart := true + for _, s := range ss { + switch { + case (s == "_" && wordStart) || (s == "_" && emp): + e = addElement(e, buffer+curWord, strong, emp, code) + emp = !emp + buffer = "" + curWord = "" + case s == "*": + e = addElement(e, buffer+curWord, strong, emp, code) + buffer = "" + curWord = "" + strong = !strong + case s == "`": + e = addElement(e, buffer+curWord, strong, emp, code) + code = !code + buffer = "" + curWord = "" + case s == "[" && prevChar != "": + e = addElement(e, buffer, strong, emp, code) + linkTitle = true + curWord += s + case s == "]" && linkTitle: + e = addLink(e, curWord) + buffer = "" + curWord = "" + linkTitle = false + case s == " " && !linkTitle: + buffer += curWord + " " + curWord = "" + default: + curWord += s + } + prevChar = s + wordStart = false + if prevChar == " " { + wordStart = true + } + } + if len(buffer+curWord) > 0 { + e = addElement(e, buffer+curWord, false, false, false) + } + + return e +} + +func addLink(ies []InlineElement, linkText string) []InlineElement { + ss := strings.Split(linkText, "[") + if len(ss) < 2 { + ss = append(ss, "ERROR") + } + + return append(ies, Link{url: ss[0], title: ss[1]}) +} + +func addElement(ies []InlineElement, text string, strong, emp, code bool) []InlineElement { + if len(text) == 0 { + return ies + } + + var ne InlineElement + switch { + case code: + ne = CodeText(text) + case strong && emp: + ne = StrongEmpText(text) + case strong && !emp: + ne = StrongText(text) + case !strong && emp: + ne = EmpText(text) + default: + ne = PlainText(text) + } + + return append(ies, ne) +} diff --git a/site/parser_test.go b/site/parser_test.go new file mode 100644 index 0000000..224727d --- /dev/null +++ b/site/parser_test.go @@ -0,0 +1,247 @@ +package site_test + +import ( + "fmt" + "testing" + "time" + + "git.sr.ht/~ewintr/go-kit/test" + "git.sr.ht/~ewintr/shitty-ssg/site" +) + +func TestNewPost(t *testing.T) { + one := "one" + two := "two" + three := "three" + ptOne := site.PlainText(one) + ptTwo := site.PlainText(two) + ptThree := site.PlainText(three) + for _, tc := range []struct { + name string + input string + exp site.Post + }{ + { + name: "empty", + exp: site.Post{ + Tags: []site.Tag{}, + Language: site.LANGUAGE_EN, + }, + }, + { + name: "title", + input: "= Title", + exp: site.Post{ + Title: "Title", + Tags: []site.Tag{}, + Language: site.LANGUAGE_EN, + }, + }, + { + name: "header", + input: "= Title\nT. Test\n2020-10-27\n:tags:\ttag1, tag2\n:kind:\tnote\n:language:\tnl", + exp: site.Post{ + Title: "Title", + Author: "T. Test", + Kind: site.KIND_NOTE, + Language: site.LANGUAGE_NL, + Tags: []site.Tag{ + site.Tag("tag1"), + site.Tag("tag2"), + }, + Date: time.Date(2020, time.October, 27, 0, 0, 0, 0, time.UTC), + }, + }, + { + name: "paragraphs", + input: fmt.Sprintf("%s\n\n%s\n\n%s", one, two, three), + exp: site.Post{ + Tags: []site.Tag{}, + Language: site.LANGUAGE_EN, + Content: []site.BlockElement{ + site.Paragraph([]site.InlineElement{ptOne}), + site.Paragraph([]site.InlineElement{ptTwo}), + site.Paragraph([]site.InlineElement{ptThree}), + }, + }, + }, + { + name: "subtitle", + input: "== Subtitle", + exp: site.Post{ + Tags: []site.Tag{}, + Language: site.LANGUAGE_EN, + Content: []site.BlockElement{ + site.SubTitle("Subtitle"), + }, + }, + }, + { + name: "code block", + input: "----\nsome code\nmore code\n----", + exp: site.Post{ + Tags: []site.Tag{}, + Language: site.LANGUAGE_EN, + Content: []site.BlockElement{ + site.CodeBlock("some code\nmore code"), + }, + }, + }, + { + name: "code block with empty lines", + input: "----\nsome code\n\nmore code\n----", + exp: site.Post{ + Tags: []site.Tag{}, + Language: site.LANGUAGE_EN, + Content: []site.BlockElement{ + site.CodeBlock("some code\n\nmore code"), + }, + }, + }, + { + name: "list", + input: "* item 1\n* item 2\n* *item 3*\n", + exp: site.Post{ + Tags: []site.Tag{}, + Language: site.LANGUAGE_EN, + Content: []site.BlockElement{ + site.List{ + site.ListItem([]site.InlineElement{site.PlainText("item 1")}), + site.ListItem([]site.InlineElement{site.PlainText("item 2")}), + site.ListItem([]site.InlineElement{site.StrongText("item 3")}), + }, + }, + }, + }, + } { + t.Run(tc.name, func(t *testing.T) { + act := site.NewPost(tc.input) + + test.Equals(t, tc.exp, act) + }) + } +} + +func TestPostBodyHTML(t *testing.T) { + text := `= Title + +Some text. With some *strong*. And a http://example.com[link]. + +== A Sub Title + +And some more text. + ` + post := site.NewPost(text) + act := post.HTMLPost() + + exp := &site.HTMLPost{ + Slug: "title", + Title: "Title", + DateLong: "January 1, 0001", + DateShort: "0001-01-01 00:00:00", + Content: `

    Some text. With some strong. And a link.

    +

    A Sub Title

    +

    And some more text.

    +`, + } + + test.Equals(t, exp, act) + +} + +func TestParseInline(t *testing.T) { + for _, tc := range []struct { + name string + input string + exp []site.InlineElement + }{{ + name: "empty", + }, + { + name: "plain", + input: "some test text", + exp: []site.InlineElement{ + site.PlainText("some test text")}, + }, + { + name: "strong", + input: "*some strong text*", + exp: []site.InlineElement{ + site.StrongText("some strong text"), + }, + }, + { + name: "strong in plain", + input: "some *strong* text", + exp: []site.InlineElement{ + site.PlainText("some "), + site.StrongText("strong"), + site.PlainText(" text"), + }, + }, + { + name: "emphasis", + input: "_some emphasized text_", + exp: []site.InlineElement{ + site.EmpText("some emphasized text"), + }, + }, + { + name: "emphasis in plain", + input: "some _emphasized_ text", + exp: []site.InlineElement{ + site.PlainText("some "), + site.EmpText("emphasized"), + site.PlainText(" text"), + }, + }, + { + name: "emp and strong in plain", + input: "some _*special*_ text", + exp: []site.InlineElement{ + site.PlainText("some "), + site.StrongEmpText("special"), + site.PlainText(" text"), + }, + }, + { + name: "link", + input: "a link[title] somewhere", + exp: []site.InlineElement{ + site.PlainText("a "), + site.NewLink("link", "title"), + site.PlainText(" somewhere"), + }, + }, + { + name: "code", + input: "`command`", + exp: []site.InlineElement{ + site.CodeText("command"), + }, + }, + { + name: "code in plain", + input: "some `code` in text", + exp: []site.InlineElement{ + site.PlainText("some "), + site.CodeText("code"), + site.PlainText(" in text"), + }, + }, + { + name: "link with underscore", + input: "https://example.com/some_url[some url]", + exp: []site.InlineElement{ + site.NewLink("https://example.com/some_url", "some url"), + }, + }, + } { + t.Run(tc.name, func(t *testing.T) { + act := site.ParseInline(tc.input) + + test.Equals(t, tc.exp, act) + + }) + } +} diff --git a/site/post.go b/site/post.go new file mode 100644 index 0000000..ab9f5e6 --- /dev/null +++ b/site/post.go @@ -0,0 +1,125 @@ +package site + +import ( + "errors" + "fmt" + "html" + "path" + "strconv" + "strings" + "time" + + "git.sr.ht/~ewintr/go-kit/slugify" +) + +var ( + ErrInvalidPost = errors.New("invalid post") +) + +type Post struct { + Title string + Author string + Kind Kind + Language Language + Path string + Date time.Time + Tags []Tag + Content []BlockElement +} + +func (p Post) Slug() string { + return slugify.Slugify(p.Title) +} + +func (p *Post) Year() string { + return strconv.Itoa(p.Date.Year()) +} + +func (p *Post) Link() string { + return fmt.Sprintf("%s/", path.Join("/", pluralKind[p.Kind], p.Year(), p.Slug())) +} + +func (p *Post) FullLink() string { + return fmt.Sprintf("https://erikwinter.nl/%s", p.Link()) +} + +func (p *Post) HTMLSummary() *HTMLSummary { + summary := "" + if len(p.Content) > 0 { + summary = fmt.Sprintf("

    %s...

    ", truncateOnSpace(p.Content[0].Text(), 150)) + } + + return &HTMLSummary{ + Link: p.Link(), + Title: p.Title, + Language: p.Language, + DateLong: p.FormattedDate(DATE_LONG), + DateShort: p.FormattedDate(DATE_SHORT), + Summary: summary, + } +} + +func (p *Post) HTMLPost() *HTMLPost { + var content string + for _, be := range p.Content { + content += fmt.Sprintf("%s\n", be.BlockHTML()) + } + + return &HTMLPost{ + Slug: p.Slug(), + Title: html.EscapeString(p.Title), + DateLong: p.FormattedDate(DATE_LONG), + DateShort: p.FormattedDate(DATE_SHORT), + Content: content, + } +} + +func (p *Post) XMLPost() *XMLPost { + var content string + for _, be := range p.Content { + content += fmt.Sprintf("%s\n", html.EscapeString(be.BlockHTML())) + } + + return &XMLPost{ + Link: p.FullLink(), + Title: html.EscapeString(p.Title), + DateFormal: p.FormattedDate(DATE_FORMAL), + Content: content, + } +} + +func (p Post) FormattedDate(format DateFormat) string { + switch { + case format == DATE_LONG && p.Language == LANGUAGE_NL: + nlMonth := [...]string{"januari", "februari", "maart", + "april", "mei", "juni", "juli", "augustus", "september", + "oktober", "november", "december", + } + return fmt.Sprintf("%d %s %d", p.Date.Day(), nlMonth[p.Date.Month()-1], p.Date.Year()) + case format == DATE_LONG && p.Language == LANGUAGE_EN: + return p.Date.Format("January 2, 2006") + case format == DATE_FORMAL: + return p.Date.Format(time.RFC1123Z) + case format == DATE_SHORT: + fallthrough + default: + return p.Date.Format("2006-01-02 00:00:00") + } +} + +func truncateOnSpace(text string, maxChars int) string { + if len(text) <= maxChars { + return text + } + + shortText := "" + ss := strings.Split(text, " ") + for _, s := range ss { + if len(shortText+" "+s) > maxChars { + break + } + shortText += " " + s + } + + return shortText +} diff --git a/site/posts.go b/site/posts.go new file mode 100644 index 0000000..44d78d4 --- /dev/null +++ b/site/posts.go @@ -0,0 +1,113 @@ +package site + +import "sort" + +type Posts []Post + +func (p Posts) Len() int { return len(p) } +func (p Posts) Swap(i, j int) { p[i], p[j] = p[j], p[i] } +func (p Posts) Less(i, j int) bool { return p[i].Date.After(p[j].Date) } + +func (p Posts) Sort() Posts { + sort.Sort(p) + + return p +} + +func (p Posts) FilterByKind(wanted Kind) Posts { + pList := Posts{} + for _, post := range p { + if post.Kind == wanted { + pList = append(pList, post) + } + } + + return pList +} + +func (p Posts) FilterByYear(year string) Posts { + pList := Posts{} + for _, post := range p { + if post.Year() == year { + pList = append(pList, post) + } + } + + return pList +} + +func (p Posts) FilterByTag(wanted Tag) Posts { + pList := Posts{} + +POSTS: + for _, post := range p { + for _, tag := range post.Tags { + if tag == wanted { + pList = append(pList, post) + + continue POSTS + } + } + } + + return pList +} + +func (p Posts) Limit(limit int) Posts { + if len(p) <= limit { + return p + } + + return p[:limit] +} + +func (p Posts) YearList() []string { + fullList := []string{} + for _, post := range p { + fullList = append(fullList, post.Year()) + } + list := removeDuplicates(fullList) + sort.Strings(list) + + return list +} + +func (p Posts) TagList() []string { + fullList := []string{} + for _, post := range p { + for _, tag := range post.Tags { + fullList = append(fullList, string(tag)) + } + } + + list := removeDuplicates(fullList) + sort.Strings(list) + + return list +} + +func (p Posts) HTMLSummaries() []*HTMLSummary { + summaries := []*HTMLSummary{} + for _, post := range p { + summaries = append(summaries, post.HTMLSummary()) + } + + return summaries +} + +func removeDuplicates(fullList []string) []string { + list := []string{} + for _, item := range fullList { + isNew := true + for _, li := range list { + if item == li { + isNew = false + } + } + if isNew { + list = append(list, item) + } + } + + return list +} diff --git a/site/render.go b/site/render.go new file mode 100644 index 0000000..b159dec --- /dev/null +++ b/site/render.go @@ -0,0 +1,254 @@ +package site + +import ( + "fmt" + "io/ioutil" + "os" + "path" + "path/filepath" + "strings" + "text/template" + "time" +) + +const dirMode = os.ModeDir | 0755 + +func resetTarget(targetPath string) error { + if err := os.RemoveAll(targetPath); err != nil { + return err + } + + return os.Mkdir(targetPath, dirMode) +} + +func moveResources(targetPath, resourcesPath string) error { + for _, dir := range []string{"css", "font"} { + srcPath := filepath.Join(resourcesPath, dir) + destPath := filepath.Join(targetPath, dir) + if err := copyFiles(filepath.Join(srcPath, "*"), destPath); err != nil { + return err + } + } + + return nil +} + +func renderStaticPages(targetPath string, statics []*StaticPage) error { + for _, static := range statics { + destPath := filepath.Join(targetPath, static.Name) + if err := os.MkdirAll(destPath, dirMode); err != nil { + return err + } + pageFile, err := os.Create(filepath.Join(destPath, "index.html")) + if err != nil { + return err + } + defer pageFile.Close() + + data := struct { + Title string + }{ + Title: strings.Title(static.Name), + } + if err := static.Template.Execute(pageFile, data); err != nil { + return err + } + + if err := copyFiles(filepath.Join(static.SourcePath, "*"), destPath); err != nil { + return err + } + } + return nil +} + +func renderHome(targetPath string, tpl *template.Template, posts Posts) error { + data := struct { + Title string + Summaries []*HTMLSummary + }{ + Title: "Recent", + Summaries: posts.HTMLSummaries(), + } + + hPath := filepath.Join(targetPath, "index.html") + homeFile, err := os.Create(hPath) + if err != nil { + return err + } + defer homeFile.Close() + + return tpl.Execute(homeFile, data) +} + +func renderArchive(targetPath string, tpl *template.Template, title string, posts Posts) error { + archPath := filepath.Join(targetPath, "archive") + if err := os.MkdirAll(archPath, dirMode); err != nil { + return err + } + archFile, err := os.Create(filepath.Join(archPath, "index.html")) + if err != nil { + return err + } + + type link struct { + Name string + Link string + } + + tags := []link{} + for _, tag := range posts.TagList() { + tags = append(tags, link{ + Name: tag, + Link: fmt.Sprintf("%s/", path.Join("/tags", tag)), + }) + } + + yearLinks := map[Kind][]link{ + KIND_ARTICLE: {}, + KIND_NOTE: {}, + KIND_STORY: {}, + } + for kind := range yearLinks { + for _, year := range posts.FilterByKind(kind).YearList() { + yearLinks[kind] = append(yearLinks[kind], link{ + Name: year, + Link: fmt.Sprintf("%s/", path.Join("/", pluralKind[kind], year)), + }) + } + } + + data := struct { + Title string + Tags []link + ArticleYears []link + NoteYears []link + StoryYears []link + }{ + Title: title, + Tags: tags, + ArticleYears: yearLinks[KIND_ARTICLE], + NoteYears: yearLinks[KIND_NOTE], + StoryYears: yearLinks[KIND_STORY], + } + + return tpl.Execute(archFile, data) +} + +func renderListings(targetPath string, tpl *template.Template, posts Posts) error { + for _, kind := range []Kind{KIND_NOTE, KIND_STORY, KIND_ARTICLE} { + for _, year := range posts.FilterByKind(kind).YearList() { + title := fmt.Sprintf("%s in %s", strings.Title(pluralKind[kind]), year) + summaries := posts.FilterByKind(kind).FilterByYear(year).HTMLSummaries() + path := filepath.Join(targetPath, pluralKind[kind], year) + if err := renderListing(path, tpl, title, summaries); err != nil { + return err + } + } + } + + for _, tag := range posts.TagList() { + title := fmt.Sprintf("Posts Tagged with \"%s\"", tag) + summaries := posts.FilterByTag(Tag(tag)).HTMLSummaries() + path := filepath.Join(targetPath, "tags", tag) + if err := renderListing(path, tpl, title, summaries); err != nil { + return err + } + } + + return nil +} + +func renderListing(path string, tpl *template.Template, title string, summaries []*HTMLSummary) error { + data := struct { + Title string + Summaries []*HTMLSummary + }{ + Title: title, + Summaries: summaries, + } + if err := os.MkdirAll(path, dirMode); err != nil { + return err + } + lPath := filepath.Join(path, "index.html") + f, err := os.Create(lPath) + if err != nil { + return err + } + defer f.Close() + + return tpl.Execute(f, data) +} + +func renderPosts(targetPath string, tpl *template.Template, posts Posts) error { + for _, post := range posts { + data := post.HTMLPost() + if data.Slug == "" { + return ErrInvalidPost + } + + path := filepath.Join(targetPath, pluralKind[post.Kind], post.Year(), data.Slug) + if err := os.MkdirAll(path, dirMode); err != nil { + return err + } + + nPath := filepath.Join(path, "index.html") + f, err := os.Create(nPath) + if err != nil { + return err + } + defer f.Close() + + if err := tpl.Execute(f, data); err != nil { + return err + } + } + + return nil +} + +func renderRSS(targetPath string, tpl *template.Template, posts Posts) error { + rssPath := filepath.Join(targetPath, "index.xml") + rssFile, err := os.Create(rssPath) + if err != nil { + return err + } + defer rssFile.Close() + + var xmlPosts []*XMLPost + for _, p := range posts.Limit(10) { + xmlPosts = append(xmlPosts, p.XMLPost()) + } + + data := struct { + DateFormal string + Posts []*XMLPost + }{ + DateFormal: time.Now().Format(time.RFC1123Z), + Posts: xmlPosts, + } + return tpl.Execute(rssFile, data) +} + +func copyFiles(srcPattern, destPath string) error { + filePaths, err := filepath.Glob(srcPattern) + if err != nil { + return err + } + + if err := os.MkdirAll(destPath, dirMode); err != nil { + return err + } + + for _, fPath := range filePaths { + destFPath := filepath.Join(destPath, filepath.Base(fPath)) + content, err := ioutil.ReadFile(fPath) + if err != nil { + return err + } + if err := ioutil.WriteFile(destFPath, content, 0644); err != nil { + return err + } + } + + return nil +} diff --git a/site/site.go b/site/site.go new file mode 100644 index 0000000..1e0536e --- /dev/null +++ b/site/site.go @@ -0,0 +1,118 @@ +package site + +import ( + "fmt" + "io/ioutil" + "path/filepath" + "text/template" +) + +type StaticPage struct { + Name string + Template *template.Template + SourcePath string +} + +type Site struct { + resourcesPath string + templates map[string]*template.Template + posts Posts + staticPages []*StaticPage +} + +func New(resourcesPath string) (*Site, error) { + templates, err := parseTemplates(resourcesPath) + if err != nil { + return &Site{}, err + } + + staticPages := []*StaticPage{} + for _, stName := range []string{"other", "about"} { + staticPages = append(staticPages, &StaticPage{ + Name: stName, + Template: templates[stName], + SourcePath: filepath.Join(resourcesPath, stName), + }) + } + + return &Site{ + resourcesPath: resourcesPath, + templates: templates, + posts: []Post{}, + staticPages: staticPages, + }, nil +} + +func (s *Site) AddFilePost(fPath string) error { + content, err := ioutil.ReadFile(fPath) + if err != nil { + return err + } + s.posts = append(s.posts, NewPost(string(content))) + + return nil +} + +func (s *Site) AddFolderPost(kind Kind, fPath string) error { + // TODO implement + return nil +} + +func (s *Site) RenderHTML(targetPath string) error { + posts := s.posts.Sort() + + if err := resetTarget(targetPath); err != nil { + return err + } + if err := moveResources(targetPath, s.resourcesPath); err != nil { + return err + } + if err := renderStaticPages(targetPath, s.staticPages); err != nil { + return err + } + + if err := renderArchive(targetPath, s.templates["archive"], "Archive", posts); err != nil { + return err + } + + if err := renderHome(targetPath, s.templates["list"], posts.Limit(10)); err != nil { + return err + } + + if err := renderListings(targetPath, s.templates["list"], posts); err != nil { + return err + } + + if err := renderPosts(targetPath, s.templates["post"], posts); err != nil { + return err + } + + if err := renderRSS(targetPath, s.templates["rss"], posts); err != nil { + return err + } + return nil +} + +func parseTemplates(resourcesPath string) (map[string]*template.Template, error) { + templates := map[string]*template.Template{} + tPath := filepath.Join(resourcesPath, "template") + for _, tName := range []string{"post", "list", "archive", "other", "about"} { + var tFiles []string + for _, tf := range []string{tName, "head", "menu"} { + tFiles = append(tFiles, filepath.Join(tPath, fmt.Sprintf("%s.gohtml", tf))) + } + tpl, err := template.ParseFiles(tFiles...) + if err != nil { + return map[string]*template.Template{}, err + } + templates[tName] = tpl + } + + rss, err := template.ParseFiles(filepath.Join(tPath, "rss.goxml")) + if err != nil { + return map[string]*template.Template{}, err + } + templates["rss"] = rss + + return templates, nil +} diff --git a/site/xml.go b/site/xml.go new file mode 100644 index 0000000..fccda4c --- /dev/null +++ b/site/xml.go @@ -0,0 +1,8 @@ +package site + +type XMLPost struct { + Link string + Title string + DateFormal string + Content string +}