@marcel91200 / caddy Mirror · read-only / commits / 82bebfab
Fork 0

Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS

Mirrored from https://github.com/Slazee/caddy.git

Synced Nov 14, 05:15 UTC

templates: Change functions, add front matter support, better markdown

Matthew Holt committed Dec 23, 2019 at 12:56 UTC 82bebfab8a6528f24f23dac99ce5b11efab27761
6 files changed +271 -29
go.mod
+7 -1
@@ -4,6 +4,7 @@ go 1.13
4
5 require (
6 github.com/Masterminds/sprig/v3 v3.0.0
7 + github.com/alecthomas/chroma v0.7.0
8 github.com/andybalholm/brotli v0.0.0-20190821151343-b60f0d972eeb
9 github.com/cenkalti/backoff/v3 v3.1.1 // indirect
10 github.com/dustin/go-humanize v1.0.0
@@ -14,15 +15,19 @@ require (
15 github.com/jsternberg/zap-logfmt v1.2.0
16 github.com/klauspost/compress v1.8.6
17 github.com/klauspost/cpuid v1.2.2
18 + github.com/kylelemons/godebug v1.1.0 // indirect
19 github.com/lucas-clemente/quic-go v0.14.1
20 github.com/mholt/certmagic v0.9.0
21 github.com/miekg/dns v1.1.25 // indirect
22 github.com/muhammadmuzzammil1998/jsonc v0.0.0-20190906142622-1265e9b150c6
23 + github.com/naoina/go-stringutil v0.1.0 // indirect
24 + github.com/naoina/toml v0.1.1
25 github.com/onsi/ginkgo v1.8.0 // indirect
26 github.com/onsi/gomega v1.5.0 // indirect
23 - github.com/russross/blackfriday/v2 v2.0.1
27 github.com/starlight-go/starlight v0.0.0-20181207205707-b06f321544f3
28 github.com/vulcand/oxy v1.0.0
29 + github.com/yuin/goldmark v1.1.17
30 + github.com/yuin/goldmark-highlighting v0.0.0-20191202084645-78f32c8dd6d5
31 go.starlark.net v0.0.0-20190919145610-979af19b165c
32 go.uber.org/multierr v1.2.0 // indirect
33 go.uber.org/zap v1.10.0
@@ -31,4 +36,5 @@ require (
36 golang.org/x/sys v0.0.0-20191210023423-ac6580df4449 // indirect
37 gopkg.in/natefinch/lumberjack.v2 v2.0.0
38 gopkg.in/square/go-jose.v2 v2.4.1 // indirect
39 + gopkg.in/yaml.v2 v2.2.2
40 )
go.sum
+44
@@ -17,6 +17,8 @@ github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6L
17 github.com/Azure/go-autorest/tracing v0.1.0/go.mod h1:ROEEAFwXycQw7Sn3DXNtEedEvdeRAgDr0izn4z5Ij88=
18 github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
19 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
20 +github.com/GeertJohan/go.incremental v1.0.0/go.mod h1:6fAjUhbVuX1KcMD3c8TEgVUqmo4seqhv0i0kdATSkM0=
21 +github.com/GeertJohan/go.rice v1.0.0/go.mod h1:eH6gbSOAUv07dQuZVnBmoDP8mgsM1rtixis4Tib9if0=
22 github.com/Masterminds/goutils v1.1.0 h1:zukEsf/1JZwCMgHiK3GZftabmxiCw4apj3a28RPBiVg=
23 github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
24 github.com/Masterminds/semver/v3 v3.0.1 h1:2kKm5lb7dKVrt5TYUiAavE6oFc1cFT0057UVGT+JqLk=
@@ -27,8 +29,20 @@ github.com/OpenDNS/vegadns2client v0.0.0-20180418235048-a3fa4a771d87/go.mod h1:i
29 github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
30 github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
31 github.com/akamai/AkamaiOPEN-edgegrid-golang v0.9.0/go.mod h1:zpDJeKyp9ScW4NNrbdr+Eyxvry3ilGPewKoXw3XGN1k=
32 +github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c=
33 github.com/alangpierce/go-forceexport v0.0.0-20160317203124-8f1d6941cd75 h1:3ILjVyslFbc4jl1w5TWuvvslFD/nDfR2H8tVaMVLrEY=
34 github.com/alangpierce/go-forceexport v0.0.0-20160317203124-8f1d6941cd75/go.mod h1:uAXEEpARkRhCZfEvy/y0Jcc888f9tHCc1W7/UeEtreE=
35 +github.com/alecthomas/assert v0.0.0-20170929043011-405dbfeb8e38 h1:smF2tmSOzy2Mm+0dGI2AIUHY+w0BUc+4tn40djz7+6U=
36 +github.com/alecthomas/assert v0.0.0-20170929043011-405dbfeb8e38/go.mod h1:r7bzyVFMNntcxPZXK3/+KdruV1H5KSlyVY0gc+NgInI=
37 +github.com/alecthomas/chroma v0.7.0 h1:z+0HgTUmkpRDRz0SRSdMaqOLfJV4F+N1FPDZUZIDUzw=
38 +github.com/alecthomas/chroma v0.7.0/go.mod h1:1U/PfCsTALWWYHDnsIQkxEBM0+6LLe0v8+RSVMOwxeY=
39 +github.com/alecthomas/colour v0.0.0-20160524082231-60882d9e2721 h1:JHZL0hZKJ1VENNfmXvHbgYlbUOvpzYzvy2aZU5gXVeo=
40 +github.com/alecthomas/colour v0.0.0-20160524082231-60882d9e2721/go.mod h1:QO9JBoKquHd+jz9nshCh40fOfO+JzsoXy8qTHF68zU0=
41 +github.com/alecthomas/kong v0.1.17-0.20190424132513-439c674f7ae0/go.mod h1:+inYUSluD+p4L8KdviBSgzcqEjUQOfC5fQDRFuc36lI=
42 +github.com/alecthomas/kong v0.2.1-0.20190708041108-0548c6b1afae/go.mod h1:+inYUSluD+p4L8KdviBSgzcqEjUQOfC5fQDRFuc36lI=
43 +github.com/alecthomas/kong-hcl v0.1.8-0.20190615233001-b21fea9723c8/go.mod h1:MRgZdU3vrFd05IQ89AxUZ0aYdF39BYoNFa324SodPCA=
44 +github.com/alecthomas/repr v0.0.0-20180818092828-117648cd9897 h1:p9Sln00KOTlrYkxI1zYWl1QLnEqAqEARBEYa8FQnQcY=
45 +github.com/alecthomas/repr v0.0.0-20180818092828-117648cd9897/go.mod h1:xTS7Pm1pD1mvyM075QCDSRqH6qRLXylzS24ZTpRiSzQ=
46 github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
47 github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
48 github.com/aliyun/alibaba-cloud-sdk-go v0.0.0-20190808125512-07798873deee/go.mod h1:myCDvQSzCW+wB1WAlocEru4wMGJxy+vlxHdhegi1CDQ=
@@ -54,12 +68,17 @@ github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd h1:qMd81Ts1T
68 github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
69 github.com/cpu/goacmedns v0.0.1/go.mod h1:sesf/pNnCYwUevQEQfEwY0Y3DydlQWSGZbaMElOWxok=
70 github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
71 +github.com/daaku/go.zipexe v1.0.0/go.mod h1:z8IiR6TsVLEYKwXAoE/I+8ys/sDkgTzSL0CLnGVd57E=
72 +github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964 h1:y5HC9v93H5EPKqaS1UYVg1uYah5Xf51mBfIoWehClUQ=
73 +github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964/go.mod h1:Xd9hchkHSWYkEqJwUGisez3G1QY8Ryz0sdWrLPMGjLk=
74 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
75 github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
76 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
77 github.com/decker502/dnspod-go v0.2.0/go.mod h1:qsurYu1FgxcDwfSwXJdLt4kRsBLZeosEb9uq4Sy+08g=
78 github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
79 github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8=
80 +github.com/dlclark/regexp2 v1.1.6 h1:CqB4MjHw0MFCDj+PHHjiESmHX+N7t0tJzKvC6M97BRg=
81 +github.com/dlclark/regexp2 v1.1.6/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
82 github.com/dnaeon/go-vcr v0.0.0-20180814043457-aafff18a5cc2/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
83 github.com/dnsimple/dnsimple-go v0.30.0/go.mod h1:O5TJ0/U6r7AfT8niYNlmohpLbCSG+c71tQlGr9SeGrg=
84 github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
@@ -114,8 +133,11 @@ github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5m
133 github.com/gophercloud/gophercloud v0.3.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=
134 github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
135 github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
136 +github.com/gorilla/csrf v1.6.0/go.mod h1:7tSf8kmjNYr7IWDCYhd3U8Ck34iQ/Yw5CJu7bAkHEGI=
137 +github.com/gorilla/handlers v1.4.1/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ=
138 github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
139 github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
140 +github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
141 github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
142 github.com/gravitational/trace v0.0.0-20190726142706-a535a178675f/go.mod h1:RvdOUHE4SHqR3oXlFFKnGzms8a5dugHygGw1bqDstYI=
143 github.com/grpc-ecosystem/grpc-gateway v1.8.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
@@ -123,6 +145,7 @@ github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplb
145 github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
146 github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
147 github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
148 +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
149 github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
150 github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
151 github.com/huandu/xstrings v1.2.0 h1:yPeWdRnmynF7p+lLYz0H2tthW9lqhMJrQV/U7yy4wX0=
@@ -133,6 +156,7 @@ github.com/ilibs/json5 v1.0.1/go.mod h1:kXsGuzHMPuZZTN15l0IQzy5PR8DrDhPB24tFgwpd
156 github.com/imdario/mergo v0.3.7/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
157 github.com/imdario/mergo v0.3.8 h1:CGgOkSJeqMRmt0D9XLWExdT4m4F1vd3FV3VPt+0VxkQ=
158 github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
159 +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
160 github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
161 github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
162 github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
@@ -159,6 +183,8 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN
183 github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
184 github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
185 github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
186 +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
187 +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
188 github.com/labbsr0x/bindman-dns-webhook v1.0.2/go.mod h1:p6b+VCXIR8NYKpDr8/dg1HKfQoRHCdcsROXKvmoehKA=
189 github.com/labbsr0x/goh v1.0.1/go.mod h1:8K2UhVoaWXcCU7Lxoa2omWnC8gyW8px7/lmO61c027w=
190 github.com/linode/linodego v0.10.0/go.mod h1:cziNP7pbvE3mXIPneHj0oRY8L1WtGEIKlZ8LANE4eXA=
@@ -176,7 +202,10 @@ github.com/marten-seemann/qpack v0.1.0 h1:/0M7lkda/6mus9B8u34Asqm8ZhHAAt9Ho0vniN
202 github.com/marten-seemann/qpack v0.1.0/go.mod h1:LFt1NU/Ptjip0C2CPkhimBz5CGE3WGDAUWqna+CNTrI=
203 github.com/marten-seemann/qtls v0.4.1 h1:YlT8QP3WCCvvok7MGEZkMldXbyqgr8oFg5/n8Gtbkks=
204 github.com/marten-seemann/qtls v0.4.1/go.mod h1:pxVXcHHw1pNIt8Qo0pwSYQEoZ8yYOOPXTCZLQQunvRc=
205 +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
206 github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
207 +github.com/mattn/go-isatty v0.0.4 h1:bnP0vzxcAdeI1zdubAl5PjU6zsERjGZb7raWodagDYs=
208 +github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
209 github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
210 github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
211 github.com/mattn/go-tty v0.0.0-20180219170247-931426f7535a/go.mod h1:XPvLUNfbS4fJH25nqRHfWLMa1ONC8Amw+mIA639KxkE=
@@ -202,7 +231,12 @@ github.com/muhammadmuzzammil1998/jsonc v0.0.0-20190906142622-1265e9b150c6 h1:Eaj
231 github.com/muhammadmuzzammil1998/jsonc v0.0.0-20190906142622-1265e9b150c6/go.mod h1:saF2fIVw4banK0H4+/EuqfFLpRnoy5S+ECwTOCcRcSU=
232 github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
233 github.com/namedotcom/go v0.0.0-20180403034216-08470befbe04/go.mod h1:5sN+Lt1CaY4wsPvgQH/jsuJi4XO2ssZbdsIizr4CVC8=
234 +github.com/naoina/go-stringutil v0.1.0 h1:rCUeRUHjBjGTSHl0VC00jUPLz8/F9dDzYI70Hzifhks=
235 +github.com/naoina/go-stringutil v0.1.0/go.mod h1:XJ2SJL9jCtBh+P9q5btrd/Ylo8XwT/h1USek5+NqSA0=
236 +github.com/naoina/toml v0.1.1 h1:PT/lllxVVN0gzzSqSlHEmP8MJB4MY2U7STGxiouV4X8=
237 +github.com/naoina/toml v0.1.1/go.mod h1:NBIhNtsFMo3G2szEBne+bO4gS192HuIYRqfvOWb4i1E=
238 github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms=
239 +github.com/nkovacs/streamquote v0.0.0-20170412213628-49af9bddb229/go.mod h1:0aYXnNPJ8l7uZxf45rWW1a/uME32OF0rhiYGNQ2oF2E=
240 github.com/nrdcg/auroradns v1.0.0/go.mod h1:6JPXKzIRzZzMqtTDgueIhTi6rFf1QvYE/HzqidhOhjw=
241 github.com/nrdcg/goinwx v0.6.1/go.mod h1:XPiut7enlbEdntAqalBIqcYcTEVhpv/dKWgDCX2SwKQ=
242 github.com/nrdcg/namesilo v0.2.1/go.mod h1:lwMvfQTyYq+BbjJd30ylEG4GPSS6PII0Tia4rRpRiyw=
@@ -246,6 +280,8 @@ github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0
280 github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
281 github.com/sacloud/libsacloud v1.26.1/go.mod h1:79ZwATmHLIFZIMd7sxA3LwzVy/B77uj3LDoToVTxDoQ=
282 github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
283 +github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
284 +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
285 github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
286 github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
287 github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
@@ -268,6 +304,8 @@ github.com/timewasted/linode v0.0.0-20160829202747-37e84520dcf7/go.mod h1:imsgLp
304 github.com/transip/gotransip v0.0.0-20190812104329-6d8d9179b66f/go.mod h1:i0f4R4o2HM0m3DZYQWsj6/MEowD57VzoH0v3d7igeFY=
305 github.com/uber-go/atomic v1.3.2/go.mod h1:/Ct5t2lcmbJ4OSe/waGBoaVvVqtO0bmtfVNex1PFV8g=
306 github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
307 +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
308 +github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
309 github.com/vulcand/oxy v1.0.0 h1:7vL5/pjDFzHGbtBEhmlHITUi6KLH4xXTDF33/wrdRKw=
310 github.com/vulcand/oxy v1.0.0/go.mod h1:6EXgOAl6CRa46/2ZGcDJKf3ywJUp5WtT7vSlGSkvecI=
311 github.com/vulcand/predicate v1.1.0/go.mod h1:mlccC5IRBoc2cIFmCB8ZM62I3VDb6p2GXESMHa3CnZg=
@@ -275,6 +313,11 @@ github.com/vultr/govultr v0.1.4/go.mod h1:9H008Uxr/C4vFNGLqKx232C206GL0PBHzOP080
313 github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
314 github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
315 github.com/xeipuuv/gojsonschema v1.1.0/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs=
316 +github.com/yuin/goldmark v1.1.7/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
317 +github.com/yuin/goldmark v1.1.17 h1:t7bl7JAmainKs/Uhmr1XZVkRJsgL2UwdTCtTuYL7RAY=
318 +github.com/yuin/goldmark v1.1.17/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
319 +github.com/yuin/goldmark-highlighting v0.0.0-20191202084645-78f32c8dd6d5 h1:QbH7ca1qtgZHrzvcVAEoiJIwBqrXxMOfHYfwZIniIK0=
320 +github.com/yuin/goldmark-highlighting v0.0.0-20191202084645-78f32c8dd6d5/go.mod h1:4QGn5rJFOASBa2uK4Q2h3BRTyJqRfsAucPFIipSTcaM=
321 go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
322 go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
323 go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
@@ -342,6 +385,7 @@ golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5h
385 golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
386 golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
387 golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
388 +golang.org/x/sys v0.0.0-20181128092732-4ed8d59d0b35/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
389 golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
390 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
391 golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
modules/caddyhttp/templates/frontmatter.go new
+100
@@ -0,0 +1,100 @@
1 +package templates
2 +
3 +import (
4 + "encoding/json"
5 + "fmt"
6 + "strings"
7 + "unicode"
8 +
9 + "github.com/naoina/toml"
10 + "gopkg.in/yaml.v2"
11 +)
12 +
13 +func extractFrontMatter(input string) (map[string]interface{}, string, error) {
14 + // get the bounds of the first non-empty line
15 + var firstLineStart, firstLineEnd int
16 + lineEmpty := true
17 + for i, b := range input {
18 + if b == '\n' {
19 + firstLineStart = firstLineEnd
20 + if firstLineStart > 0 {
21 + firstLineStart++ // skip newline character
22 + }
23 + firstLineEnd = i
24 + if !lineEmpty {
25 + break
26 + }
27 + continue
28 + }
29 + lineEmpty = lineEmpty && unicode.IsSpace(b)
30 + }
31 + firstLine := input[firstLineStart:firstLineEnd]
32 +
33 + // see what kind of front matter there is, if any
34 + var closingFence string
35 + var fmParser func([]byte) (map[string]interface{}, error)
36 + switch string(firstLine) {
37 + case yamlFrontMatterFenceOpen:
38 + fmParser = yamlFrontMatter
39 + closingFence = yamlFrontMatterFenceClose
40 + case tomlFrontMatterFenceOpen:
41 + fmParser = tomlFrontMatter
42 + closingFence = tomlFrontMatterFenceClose
43 + case jsonFrontMatterFenceOpen:
44 + fmParser = jsonFrontMatter
45 + closingFence = jsonFrontMatterFenceClose
46 + default:
47 + // no recognized front matter; whole document is body
48 + return nil, input, nil
49 + }
50 +
51 + // find end of front matter
52 + fmEndFenceStart := strings.Index(input[firstLineEnd:], "\n"+closingFence)
53 + if fmEndFenceStart < 0 {
54 + return nil, "", fmt.Errorf("unterminated front matter")
55 + }
56 + fmEndFenceStart += firstLineEnd + 1 // add 1 to account for newline
57 +
58 + // extract and parse front matter
59 + frontMatter := input[firstLineEnd:fmEndFenceStart]
60 + fm, err := fmParser([]byte(frontMatter))
61 + if err != nil {
62 + return nil, "", err
63 + }
64 +
65 + // the rest is the body
66 + body := input[fmEndFenceStart+len(closingFence):]
67 +
68 + return fm, body, nil
69 +}
70 +
71 +func yamlFrontMatter(input []byte) (map[string]interface{}, error) {
72 + m := make(map[string]interface{})
73 + err := yaml.Unmarshal(input, &m)
74 + return m, err
75 +}
76 +
77 +func tomlFrontMatter(input []byte) (map[string]interface{}, error) {
78 + m := make(map[string]interface{})
79 + err := toml.Unmarshal(input, &m)
80 + return m, err
81 +}
82 +
83 +func jsonFrontMatter(input []byte) (map[string]interface{}, error) {
84 + input = append([]byte{'{'}, input...)
85 + input = append(input, '}')
86 + m := make(map[string]interface{})
87 + err := json.Unmarshal(input, &m)
88 + return m, err
89 +}
90 +
91 +type parsedMarkdownDoc struct {
92 + Meta map[string]interface{} `json:"meta,omitempty"`
93 + Body string `json:"body,omitempty"`
94 +}
95 +
96 +const (
97 + yamlFrontMatterFenceOpen, yamlFrontMatterFenceClose = "---", "---"
98 + tomlFrontMatterFenceOpen, tomlFrontMatterFenceClose = "+++", "+++"
99 + jsonFrontMatterFenceOpen, jsonFrontMatterFenceClose = "{", "}"
100 +)
modules/caddyhttp/templates/templates.go
+19 -11
@@ -31,9 +31,18 @@ func init() {
31
32 // Templates is a middleware which execute response bodies as templates.
33 type Templates struct {
34 - IncludeRoot string `json:"include_root,omitempty"`
35 - MIMETypes []string `json:"mime_types,omitempty"`
36 - Delimiters []string `json:"delimiters,omitempty"`
34 + // The root path from which to load files. Required if template functions
35 + // accessing the file system are used (such as include). Default is
36 + // `{http.vars.root}` if set, or current working directory otherwise.
37 + FileRoot string `json:"file_root,omitempty"`
38 +
39 + // The MIME types for which to render templates. It is important to use
40 + // this if the route matchers do not exclude images or other binary files.
41 + // Default is text/plain, text/markdown, and text/html.
42 + MIMETypes []string `json:"mime_types,omitempty"`
43 +
44 + // The template action delimiters.
45 + Delimiters []string `json:"delimiters,omitempty"`
46 }
47
48 // CaddyModule returns the Caddy module information.
@@ -49,8 +58,8 @@ func (t *Templates) Provision(ctx caddy.Context) error {
58 if t.MIMETypes == nil {
59 t.MIMETypes = defaultMIMETypes
60 }
52 - if t.IncludeRoot == "" {
53 - t.IncludeRoot = "{http.vars.root}"
61 + if t.FileRoot == "" {
62 + t.FileRoot = "{http.vars.root}"
63 }
64 return nil
65 }
@@ -100,10 +109,9 @@ func (t *Templates) ServeHTTP(w http.ResponseWriter, r *http.Request, next caddy
109 rec.Header().Del("Last-Modified") // useless for dynamic content since it's always changing
110
111 // we don't know a way to guickly generate etag for dynamic content,
103 - // but we can convert this to a weak etag to kind of indicate that
104 - if etag := rec.Header().Get("Etag"); etag != "" {
105 - rec.Header().Set("Etag", "W/"+etag)
106 - }
112 + // and weak etags still cause browsers to rely on it even after a
113 + // refresh, so disable them until we find a better way to do this
114 + rec.Header().Del("Etag")
115
116 rec.WriteResponse()
117
@@ -113,9 +121,9 @@ func (t *Templates) ServeHTTP(w http.ResponseWriter, r *http.Request, next caddy
121 // executeTemplate executes the template contained in wb.buf and replaces it with the results.
122 func (t *Templates) executeTemplate(rr caddyhttp.ResponseRecorder, r *http.Request) error {
123 var fs http.FileSystem
116 - if t.IncludeRoot != "" {
124 + if t.FileRoot != "" {
125 repl := r.Context().Value(caddy.ReplacerCtxKey).(caddy.Replacer)
118 - fs = http.Dir(repl.ReplaceAll(t.IncludeRoot, "."))
126 + fs = http.Dir(repl.ReplaceAll(t.FileRoot, "."))
127 }
128
129 ctx := &templateContext{
modules/caddyhttp/templates/tplcontext.go
+93 -13
@@ -27,8 +27,13 @@ import (
27 "sync"
28
29 "github.com/Masterminds/sprig/v3"
30 + "github.com/alecthomas/chroma/formatters/html"
31 "github.com/caddyserver/caddy/v2/modules/caddyhttp"
31 - "github.com/russross/blackfriday/v2"
32 + "github.com/yuin/goldmark"
33 + highlighting "github.com/yuin/goldmark-highlighting"
34 + "github.com/yuin/goldmark/extension"
35 + "github.com/yuin/goldmark/parser"
36 + gmhtml "github.com/yuin/goldmark/renderer/html"
37 )
38
39 // templateContext is the templateContext with which HTTP templates are executed.
@@ -41,11 +46,18 @@ type templateContext struct {
46 config *Templates
47 }
48
44 -// Include returns the contents of filename relative to the site root.
49 +// OriginalReq returns the original, unmodified, un-rewritten request as
50 +// it originally came in over the wire.
51 +func (c templateContext) OriginalReq() http.Request {
52 + or, _ := c.Req.Context().Value(caddyhttp.OriginalRequestCtxKey).(http.Request)
53 + return or
54 +}
55 +
56 +// funcInclude returns the contents of filename relative to the site root.
57 // Note that included files are NOT escaped, so you should only include
58 // trusted files. If it is not trusted, be sure to use escaping functions
59 // in your template.
48 -func (c templateContext) Include(filename string, args ...interface{}) (template.HTML, error) {
60 +func (c templateContext) funcInclude(filename string, args ...interface{}) (template.HTML, error) {
61 if c.Root == nil {
62 return "", fmt.Errorf("root file system not specified")
63 }
@@ -75,11 +87,11 @@ func (c templateContext) Include(filename string, args ...interface{}) (template
87 return template.HTML(bodyBuf.String()), nil
88 }
89
78 -// HTTPInclude returns the body of a virtual (lightweight) request
90 +// funcHTTPInclude returns the body of a virtual (lightweight) request
91 // to the given URI on the same server. Note that included bodies
92 // are NOT escaped, so you should only include trusted resources.
93 // If it is not trusted, be sure to use escaping functions yourself.
82 -func (c templateContext) HTTPInclude(uri string) (template.HTML, error) {
94 +func (c templateContext) funcHTTPInclude(uri string) (template.HTML, error) {
95 // prevent virtual request loops by counting how many levels
96 // deep we are; and if we get too deep, return an error
97 recursionCount := 1
@@ -124,11 +136,22 @@ func (c templateContext) HTTPInclude(uri string) (template.HTML, error) {
136 }
137
138 func (c templateContext) executeTemplateInBuffer(tplName string, buf *bytes.Buffer) error {
127 - tpl := template.New(tplName).Funcs(sprig.FuncMap())
139 + tpl := template.New(tplName)
140 if len(c.config.Delimiters) == 2 {
141 tpl.Delims(c.config.Delimiters[0], c.config.Delimiters[1])
142 }
143
144 + tpl.Funcs(sprigFuncMap)
145 +
146 + tpl.Funcs(template.FuncMap{
147 + "include": c.funcInclude,
148 + "httpInclude": c.funcHTTPInclude,
149 + "stripHTML": c.funcStripHTML,
150 + "markdown": c.funcMarkdown,
151 + "splitFrontMatter": c.funcSplitFrontMatter,
152 + "listFiles": c.funcListFiles,
153 + })
154 +
155 parsedTpl, err := tpl.Parse(buf.String())
156 if err != nil {
157 return err
@@ -173,9 +196,9 @@ func (c templateContext) Host() (string, error) {
196 return host, nil
197 }
198
176 -// StripHTML returns s without HTML tags. It is fairly naive
199 +// funcStripHTML returns s without HTML tags. It is fairly naive
200 // but works with most valid HTML inputs.
178 -func (c templateContext) StripHTML(s string) string {
201 +func (c templateContext) funcStripHTML(s string) string {
202 var buf bytes.Buffer
203 var inTag, inQuotes bool
204 var tagStart int
@@ -206,15 +229,53 @@ func (c templateContext) StripHTML(s string) string {
229 return buf.String()
230 }
231
209 -// Markdown renders the markdown body as HTML. The resulting
232 +// funcMarkdown renders the markdown body as HTML. The resulting
233 // HTML is NOT escaped so that it can be rendered as HTML.
211 -func (c templateContext) Markdown(body string) template.HTML {
212 - return template.HTML(blackfriday.Run([]byte(body)))
234 +func (c templateContext) funcMarkdown(input interface{}) (template.HTML, error) {
235 + inputStr := toString(input)
236 +
237 + md := goldmark.New(
238 + goldmark.WithExtensions(
239 + extension.GFM,
240 + extension.Table,
241 + highlighting.NewHighlighting(
242 + highlighting.WithFormatOptions(
243 + html.WithClasses(true),
244 + ),
245 + ),
246 + ),
247 + goldmark.WithParserOptions(
248 + parser.WithAutoHeadingID(),
249 + ),
250 + goldmark.WithRendererOptions(
251 + gmhtml.WithHardWraps(),
252 + gmhtml.WithUnsafe(), // TODO: this is not awesome, maybe should be configurable?
253 + ),
254 + )
255 +
256 + buf := bufPool.Get().(*bytes.Buffer)
257 + buf.Reset()
258 + defer bufPool.Put(buf)
259 +
260 + md.Convert([]byte(inputStr), buf)
261 +
262 + return template.HTML(buf.String()), nil
263 +}
264 +
265 +// splitFrontMatter parses front matter out from the beginning of input,
266 +// and returns the separated key-value pairs and the body/content. input
267 +// must be a "stringy" value.
268 +func (c templateContext) funcSplitFrontMatter(input interface{}) (parsedMarkdownDoc, error) {
269 + meta, body, err := extractFrontMatter(toString(input))
270 + if err != nil {
271 + return parsedMarkdownDoc{}, err
272 + }
273 + return parsedMarkdownDoc{Meta: meta, Body: body}, nil
274 }
275
215 -// ListFiles reads and returns a slice of names from the given
276 +// funcListFiles reads and returns a slice of names from the given
277 // directory relative to the root of c.
217 -func (c templateContext) ListFiles(name string) ([]string, error) {
278 +func (c templateContext) funcListFiles(name string) ([]string, error) {
279 if c.Root == nil {
280 return nil, fmt.Errorf("root file system not specified")
281 }
@@ -273,10 +334,29 @@ func (h tplWrappedHeader) Del(field string) string {
334 return ""
335 }
336
337 +func toString(input interface{}) string {
338 + switch v := input.(type) {
339 + case string:
340 + return v
341 + case template.HTML:
342 + return string(v)
343 + case fmt.Stringer:
344 + return v.String()
345 + case error:
346 + return v.Error()
347 + default:
348 + return fmt.Sprintf("%s", input)
349 + }
350 +}
351 +
352 var bufPool = sync.Pool{
353 New: func() interface{} {
354 return new(bytes.Buffer)
355 },
356 }
357
358 +// at time of writing, sprig.FuncMap() makes a copy, thus
359 +// involves iterating the whole map, so do it just once
360 +var sprigFuncMap = sprig.FuncMap()
361 +
362 const recursionPreventionHeader = "Caddy-Templates-Include"
modules/caddyhttp/templates/tplcontext_test.go
+8 -4
@@ -31,6 +31,7 @@ package templates
31 import (
32 "bytes"
33 "fmt"
34 + "html/template"
35 "io/ioutil"
36 "net/http"
37 "os"
@@ -47,17 +48,20 @@ func TestMarkdown(t *testing.T) {
48
49 for i, test := range []struct {
50 body string
50 - expect string
51 + expect template.HTML
52 }{
53 {
54 body: "- str1\n- str2\n",
55 expect: "<ul>\n<li>str1</li>\n<li>str2</li>\n</ul>\n",
56 },
57 } {
57 - result := string(context.Markdown(test.body))
58 + result, err := context.funcMarkdown(test.body)
59 if result != test.expect {
60 t.Errorf("Test %d: expected '%s' but got '%s'", i, test.expect, result)
61 }
62 + if err != nil {
63 + t.Errorf("Test %d: got error: %v", i, result)
64 + }
65 }
66 }
67
@@ -180,7 +184,7 @@ func TestStripHTML(t *testing.T) {
184 expect: `<h1hi`,
185 },
186 } {
183 - actual := context.StripHTML(test.input)
187 + actual := context.funcStripHTML(test.input)
188 if actual != test.expect {
189 t.Errorf("Test %d: Expected %s, found %s. Input was StripHTML(%s)", i, test.expect, actual, test.input)
190 }
@@ -249,7 +253,7 @@ func TestFileListing(t *testing.T) {
253
254 // perform test
255 input := filepath.ToSlash(filepath.Join(filepath.Base(dirPath), test.inputBase))
252 - actual, err := context.ListFiles(input)
256 + actual, err := context.funcListFiles(input)
257 if err != nil {
258 if !test.shouldErr {
259 t.Errorf("Test %d: Expected no error, got: '%s'", i, err)