mirror of
https://github.com/gohugoio/hugo.git
synced 2026-09-01 19:22:38 +00:00
Compare commits
635 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 12b844daf0 | |||
| b502b9d8cc | |||
| 781a1539cc | |||
| af85eb62b4 | |||
| 882b2b61fc | |||
| 00e2fe077a | |||
| ccb8300d38 | |||
| 214dbdfb6f | |||
| 729be8074b | |||
| 6cee0dfe53 | |||
| 8be3934b59 | |||
| fbb25014e1 | |||
| bf5e59958d | |||
| 86543d6a50 | |||
| 3b47805fdd | |||
| e6ae32a0ba | |||
| 5103935ae8 | |||
| 95386544e8 | |||
| 7b99fb9f1c | |||
| d531d17b3b | |||
| 9266bf9d4c | |||
| 873a6f1885 | |||
| f503d76a3b | |||
| 93643860c9 | |||
| db46bcf82d | |||
| 66d4850b89 | |||
| 715ff1f874 | |||
| c17ad675e8 | |||
| d8717cd4c7 | |||
| 2d08a296a2 | |||
| a9e551a100 | |||
| 2aafb24766 | |||
| 4bd5ce7ef3 | |||
| 0f78dd06a4 | |||
| 714594a8b7 | |||
| dce70fb7c5 | |||
| c84079baa9 | |||
| a30023f5cb | |||
| 1f26420d39 | |||
| ff54b6bddc | |||
| 629e1439e8 | |||
| 26aa06a3db | |||
| 52a0cea65d | |||
| 8ca586a6e5 | |||
| e797a94d97 | |||
| 21cf464c1f | |||
| fb5cac704e | |||
| 63311a14d2 | |||
| 0f8f51414d | |||
| 39408925fd | |||
| 00d632153a | |||
| f1da5a15a3 | |||
| d5ab7f087d | |||
| 55dd533bf7 | |||
| b82cd82f11 | |||
| 204c3a9e32 | |||
| fe901b8119 | |||
| b39689393c | |||
| bef5048580 | |||
| 49a104309d | |||
| 5be0448635 | |||
| 1f55cb767d | |||
| 8aaec644a9 | |||
| 55c53ae9be | |||
| e28d9aa42c | |||
| 46b4607828 | |||
| 2c2ce33a39 | |||
| adc0572d29 | |||
| 0907a5c1c2 | |||
| 3d9c4f513b | |||
| 250ebc1db5 | |||
| b37d959408 | |||
| 4e00bb7fdd | |||
| fdcfccedcb | |||
| 213ea74929 | |||
| 08a10e5d14 | |||
| 9fa71c945e | |||
| d25d89e653 | |||
| 8969701967 | |||
| 69d92dc49c | |||
| d74452cfe8 | |||
| 978951cf52 | |||
| 4aff2b6e74 | |||
| 2342df4d2d | |||
| 828427ef52 | |||
| ce624cc7d3 | |||
| 8930e259d7 | |||
| 710300cb76 | |||
| 93cab620d7 | |||
| 19de4476d8 | |||
| 37e378773f | |||
| b5b41c4468 | |||
| bde807bd1e | |||
| 612f6e3afe | |||
| 50d11138f3 | |||
| e0c2e79820 | |||
| 87203139c3 | |||
| a91c2705c7 | |||
| 99412bfe45 | |||
| 421a46947a | |||
| 0a40cb43ea | |||
| d460159a5f | |||
| 8b49c3a175 | |||
| bcd32f1086 | |||
| 62fe640d09 | |||
| fbb78b89df | |||
| 6c560288a6 | |||
| 89b85aede1 | |||
| 4113693ac1 | |||
| f41f728222 | |||
| 8ddc7a5cde | |||
| f63ee6567d | |||
| 1a965e5d2f | |||
| baa414ae41 | |||
| cdf32f08c7 | |||
| 98e333b35c | |||
| a00962134a | |||
| a119ef693f | |||
| 1f9e8dcc60 | |||
| ebd636e4d5 | |||
| 4d1989d59c | |||
| a59525b05b | |||
| 3954160a21 | |||
| 93c5774dd7 | |||
| 77d2fe7866 | |||
| 405c2f6899 | |||
| 58d4c25e50 | |||
| 38661c17bb | |||
| 42fbded105 | |||
| 10287263f5 | |||
| 27e88154af | |||
| f1c29b017b | |||
| 93b3b13867 | |||
| e92ce83d5e | |||
| 4c427f6aaa | |||
| e682fcc622 | |||
| b6ea492b7a | |||
| 6e2f2dd8d3 | |||
| 94b5be67fc | |||
| c7646551be | |||
| af72db806f | |||
| e951d65771 | |||
| 2bcbf10400 | |||
| 1e4d082cf5 | |||
| 1d70aa9826 | |||
| 6fc7337aac | |||
| ddaf694183 | |||
| a28fbca6dc | |||
| 544f0a6394 | |||
| 5794a265b4 | |||
| ebf677a583 | |||
| 58d9cbd31b | |||
| 7d39990497 | |||
| 9b2028626e | |||
| c99761555c | |||
| 9b080dc625 | |||
| 231c0a7e09 | |||
| 5575ed4469 | |||
| 42f4ce15a9 | |||
| cff2f31334 | |||
| f9e41f6497 | |||
| 8f2ab5f498 | |||
| cce49997a4 | |||
| 3dd949d956 | |||
| a40d1f6ed2 | |||
| 635b3bb4eb | |||
| 08c0de5cc3 | |||
| 1cf2f3dc4f | |||
| 5f095c27ea | |||
| f604076de1 | |||
| f69df916df | |||
| 690b0f8ff5 | |||
| e2b067f050 | |||
| 0e2260421e | |||
| 4714085a10 | |||
| 55f90a3a0d | |||
| ee5aa84f2a | |||
| 4a3463463f | |||
| b958c0c109 | |||
| fc77b6303c | |||
| a432c90aee | |||
| 9aee8ace4e | |||
| 744dccbea4 | |||
| 8a49c0b3b8 | |||
| a3bf118eaa | |||
| 6561557367 | |||
| 0ab23eb5a8 | |||
| eefa0703cb | |||
| c5373efcf0 | |||
| 8f95172c7a | |||
| 4b637ac041 | |||
| de7c32a1a8 | |||
| 154e18ddb9 | |||
| 565a78b110 | |||
| 355736ec35 | |||
| 93a447c5dd | |||
| eaf75a18ec | |||
| 8d0917af0a | |||
| 718c0e1414 | |||
| d6957c192d | |||
| a695202ff5 | |||
| fea4fd86a3 | |||
| 656f818867 | |||
| f0f69d03c5 | |||
| 8fbec59930 | |||
| e55399f50b | |||
| 5ad2f17693 | |||
| 162d3a586d | |||
| fd5109b6d8 | |||
| 88d8111093 | |||
| 4ac60e4ca2 | |||
| b332d93e39 | |||
| b096a10fe9 | |||
| 24be139cb7 | |||
| 3e0f1ad7f5 | |||
| 0bd0593a77 | |||
| c6e4aff1ce | |||
| c0f491ab6c | |||
| 67746f36dd | |||
| 7f6430d84d | |||
| 0e87b18b66 | |||
| e98f885b8a | |||
| 6498d73c08 | |||
| b5b6e81c02 | |||
| 90d3fbf1da | |||
| 5f3ad1c319 | |||
| 8cd3ea565a | |||
| 7935541087 | |||
| d6818f2381 | |||
| 592e055f12 | |||
| ab692e73de | |||
| 7cdc244a72 | |||
| b5e32eb609 | |||
| 66ec6305f6 | |||
| 1cf29200b4 | |||
| 8ccee6717c | |||
| 86a97dbd18 | |||
| 5e2e62d97f | |||
| 8ac1fcd0ce | |||
| 0ed3beec80 | |||
| 077005e514 | |||
| efc0e05c4e | |||
| 6d2ea0f7d7 | |||
| 45c7452668 | |||
| e765b43e2b | |||
| 3b67759495 | |||
| 5fad8a9d06 | |||
| 9ec00725b7 | |||
| cfd3af8e69 | |||
| 4c6fec56f1 | |||
| dac0d4a69d | |||
| 03ec2b3397 | |||
| 18f5f3c14c | |||
| 308678aa7f | |||
| e73a35dea5 | |||
| c9731b2c2a | |||
| 9ebbf1b054 | |||
| 2874fc75ce | |||
| 9e69a92e85 | |||
| 9a8b65d8d7 | |||
| 7b2e1b0be9 | |||
| e975a07fb0 | |||
| 7ad721fd78 | |||
| 5714531f34 | |||
| 3c405f5172 | |||
| 9580872459 | |||
| af99a59021 | |||
| 260b55ea56 | |||
| 8f09e5f6bc | |||
| c4a1165587 | |||
| e77bb13c20 | |||
| e6e1aca3f4 | |||
| f3b4a0e99e | |||
| 0dd6890ed5 | |||
| 6650fae7ad | |||
| b31da911b5 | |||
| 1425587193 | |||
| a883948c4f | |||
| bc36d468ab | |||
| 7da1b65968 | |||
| 868f89d5c6 | |||
| 04d80e6e87 | |||
| 0802f79e66 | |||
| 10ff2f31a6 | |||
| f8d555cca5 | |||
| c9aee467d3 | |||
| d6e8b86f66 | |||
| a098081c4a | |||
| 5d7eeeadf0 | |||
| 8b5b558bb5 | |||
| 27610ddd01 | |||
| 6b29bccfee | |||
| 28fdd71c29 | |||
| fe8462b205 | |||
| d122260de7 | |||
| a037b855dd | |||
| 7eb71ee064 | |||
| c97dae40d9 | |||
| 0aeadfd02d | |||
| 5c5efa03d2 | |||
| 73c1c7b69d | |||
| f911b107ef | |||
| 05949c9038 | |||
| d5036c3ab5 | |||
| af1f9ecf91 | |||
| 42a4f6f9cb | |||
| 79b34c2f1e | |||
| 3c6b16d5a2 | |||
| 87b3cd4655 | |||
| 5989c4d464 | |||
| af55ec7661 | |||
| f2fbf0b2ea | |||
| 4923273688 | |||
| 930a3df1b7 | |||
| e49a2b83ad | |||
| 9a0aa5fdbe | |||
| 0aaf3c56a5 | |||
| ee4a33b14f | |||
| 09c88e84d1 | |||
| 24c1770288 | |||
| b7ed67d425 | |||
| 3cd97951f1 | |||
| ee75e2999b | |||
| 15b64d51da | |||
| 148fedd227 | |||
| ec01c3a7f0 | |||
| 5761b93c96 | |||
| 87188496fb | |||
| 0c4701f0ef | |||
| d851d6b98f | |||
| 8bcc08e3b0 | |||
| dbb83f925a | |||
| 4aaed87dd9 | |||
| c7dbee2321 | |||
| 29d3778ba1 | |||
| 1b2be5e878 | |||
| baa29f6534 | |||
| c7c6b47ba8 | |||
| 08fa2b1124 | |||
| 6178238a0b | |||
| df95383914 | |||
| a49bf8707b | |||
| d76e5f36b4 | |||
| ad8cea87f3 | |||
| 4c2abe0015 | |||
| 6bf010fed4 | |||
| c8fff9501d | |||
| 3ec5fc3504 | |||
| f091fc23ed | |||
| 03122e51fa | |||
| e5200ddaa4 | |||
| a8244658f7 | |||
| 50c64415aa | |||
| 348834d017 | |||
| 254cd89c8e | |||
| 10de077164 | |||
| 3bb52bf7bf | |||
| d3d2c63dd9 | |||
| c4989c39f1 | |||
| 9262c5b32f | |||
| 2bea9d0ca1 | |||
| 1b92c8b713 | |||
| 17b21e0af1 | |||
| 7f68e3199e | |||
| 2ed75f3462 | |||
| 9d9ec1ddd9 | |||
| 9f0b02b898 | |||
| a159feffb2 | |||
| d07ff9d221 | |||
| f1b1df5058 | |||
| 559b4007f7 | |||
| 5e191ccf4c | |||
| d3cd68e656 | |||
| 68f4cd829e | |||
| 3fa7bc9c53 | |||
| 3518de1057 | |||
| 7c48ad57a9 | |||
| 0e75f6e7b1 | |||
| 6eddb3e587 | |||
| 6e03c96a20 | |||
| 4382a8a6a0 | |||
| 9dfb9c1445 | |||
| c2ffdfab63 | |||
| a99661031a | |||
| 491d406881 | |||
| d8923eb676 | |||
| d6093aba4d | |||
| 638cc806d6 | |||
| ec3dc32511 | |||
| b156ef2712 | |||
| 042f8fca03 | |||
| 431d597442 | |||
| ede452d34e | |||
| 62efcdfed4 | |||
| 4b9493cb03 | |||
| 5d0748ce51 | |||
| 63e2a46f63 | |||
| 2f2ea42c09 | |||
| 5f443bd45b | |||
| f039e3be9e | |||
| ddc8cc0082 | |||
| 0e44f75ebd | |||
| 690961ba02 | |||
| fe41bd61bb | |||
| 48120ccfd2 | |||
| 560ed6e686 | |||
| 45b9d7223a | |||
| a2a8a651f7 | |||
| 4bfa189031 | |||
| a2ec372a03 | |||
| c950699907 | |||
| 6c5ef71368 | |||
| c7b8c45d12 | |||
| e52e2a70e5 | |||
| ea165bf9e7 | |||
| 22c89dcb6c | |||
| d0e2a1fa14 | |||
| 5a94e4cfb9 | |||
| f4779b25bc | |||
| 8203fc5923 | |||
| 7acec3c639 | |||
| 74ea81b885 | |||
| 577522bd45 | |||
| 23f5b9ac4e | |||
| 1279ca201a | |||
| 9671162a22 | |||
| 3669015f56 | |||
| a0e3ff1645 | |||
| cc15864744 | |||
| b7a672fd22 | |||
| 972649c684 | |||
| afb3334ed8 | |||
| c266cd2d86 | |||
| 0b91053c9f | |||
| 396276aafa | |||
| 072cd00305 | |||
| 0a99168220 | |||
| 28198ce982 | |||
| a1741f192c | |||
| c9c889c198 | |||
| eb572c8a18 | |||
| 8d5132229f | |||
| 0eb76b0863 | |||
| a8a8249f67 | |||
| 3631fd2f0e | |||
| e37e3dcc04 | |||
| 6dd57f7a11 | |||
| eaabecf586 | |||
| e21fdbae8d | |||
| e9921ae4b2 | |||
| 950d1aa1b3 | |||
| c1425a166d | |||
| 831bfd36aa | |||
| 4d679627ec | |||
| e117b1b2c7 | |||
| 9e6b5eb98e | |||
| 0f109faefb | |||
| 6278393540 | |||
| 87acf292e5 | |||
| 13972d6c83 | |||
| 91968f3b1f | |||
| 7934db9169 | |||
| 9e52477d94 | |||
| c7535b9c25 | |||
| eb27c47fc5 | |||
| df1ff57d1a | |||
| 2cbdd65330 | |||
| 4e77c8717b | |||
| d3fb196067 | |||
| 2320c5682c | |||
| 41857d036d | |||
| 75d855c086 | |||
| 86e8dd62f0 | |||
| a3af4fe46e | |||
| 2a6b26a7a5 | |||
| fe9fd0acf4 | |||
| 7e0fa13faa | |||
| 3d4e99ed50 | |||
| 02b120d1bd | |||
| 6809ea1e7c | |||
| a0b3d9db16 | |||
| 2ea242d5fe | |||
| 99fbc75e7a | |||
| 9416fdd334 | |||
| b2e3748a4e | |||
| 6d2281c8ea | |||
| e096917f87 | |||
| 13ca0b4c95 | |||
| 3dade5de09 | |||
| b360f9b30e | |||
| bdc02edfa8 | |||
| 4493e8ed9f | |||
| 07ab7ae3d2 | |||
| ed847ed93d | |||
| 10c13f5d79 | |||
| ade207635e | |||
| 0946630715 | |||
| 9421690281 | |||
| d3abb93cc7 | |||
| b7aa230458 | |||
| edfb9d5565 | |||
| 53d07fb409 | |||
| 04a4a193a9 | |||
| 4b3ca38b2e | |||
| 77cbe4d60b | |||
| c507e2717d | |||
| 93ca7c9e95 | |||
| e34af6ee30 | |||
| 691156c5ba | |||
| a988d3cf36 | |||
| 2ded3bf30f | |||
| 234273a5b5 | |||
| 5cc8b58907 | |||
| 298ebc37c2 | |||
| 2618cfbeaa | |||
| 25bfa7e12f | |||
| 7a5cc3cfd7 | |||
| 962443ade8 | |||
| a89fb86cdf | |||
| f404603340 | |||
| d11f37d97c | |||
| 3e5ad4aeeb | |||
| 9c97949513 | |||
| 7fd88fb199 | |||
| faba90ab96 | |||
| 2af2ff3c1f | |||
| dae6a4539f | |||
| 19aff029b1 | |||
| c71e1b106e | |||
| 0ada405912 | |||
| c2f692266d | |||
| 24512fa82b | |||
| 7241253c22 | |||
| 1e79900860 | |||
| 72cffed89b | |||
| feeb93d4f1 | |||
| 95ad3ad2fa | |||
| 91c569c7e5 | |||
| 99fd7c684f | |||
| d949c34af1 | |||
| 7dc9458167 | |||
| 940c5d8bae | |||
| 3ac1b9fe33 | |||
| dc61d3b6b3 | |||
| 3818d6967a | |||
| 85c7578313 | |||
| 92ba7219dc | |||
| 1d7b960614 | |||
| db33a33e61 | |||
| d6000a208c | |||
| 4ea4359ac1 | |||
| bc06135c96 | |||
| 45e3ed517a | |||
| 24a286791f | |||
| 56c5eadc38 | |||
| 3d058a936f | |||
| 3286b24fce | |||
| 2989c38245 | |||
| 9c19ef0f87 | |||
| 9f20e648b9 | |||
| c60c41e051 | |||
| 01ee525f47 | |||
| 1b46d2cfee | |||
| fff6617c69 | |||
| 0dad69325d | |||
| 001dd01ee2 | |||
| e856f24129 | |||
| 49a840be83 | |||
| e3e5600b81 | |||
| 19b6fdf2b1 | |||
| b8057b4989 | |||
| 2127203ae3 | |||
| cb63e87f8d | |||
| c344b1901f | |||
| 2ac9817eae | |||
| 4352156a27 | |||
| 52976da0ec | |||
| 6fb4f048e1 | |||
| be39ae5e11 | |||
| 2ece1b325b | |||
| 433c03616b | |||
| 0d330b0d5d | |||
| 6a51216c6a | |||
| 5834efd5fd | |||
| f79877cbb7 | |||
| a60ec06383 | |||
| 09a0af94f5 | |||
| 6e0f326b9d | |||
| 695be00c07 | |||
| cabc6b3186 | |||
| 707d3cf137 | |||
| 7d072fbbe6 | |||
| 02d6f5320f | |||
| 73c1e271f7 | |||
| 6374d82b82 | |||
| e9e4fd90e4 | |||
| a18b9e72c4 | |||
| 95a473e7ec | |||
| 211d20a3c7 | |||
| 164d0fb6a7 | |||
| 8a63e092fa | |||
| 83b4c40566 | |||
| c22b7ff8d9 | |||
| 8489608012 | |||
| bcb3ef7413 | |||
| 862f09babe | |||
| 6affd31b3e | |||
| 88b5bbd532 | |||
| d1b89f5c7c | |||
| 17f851780c | |||
| e78dd3cd48 | |||
| 7d991ed89c | |||
| 3e4fbbaae4 | |||
| 99e5fc63c2 | |||
| 63d3c4ce25 | |||
| bc060ee1c9 | |||
| b0e86dcde0 | |||
| d055862a41 | |||
| 8b0c3b9b27 | |||
| 34c87421b8 | |||
| 29caaddce6 | |||
| 661d64c46a | |||
| 4e5b4ac504 | |||
| 6b8422bb35 | |||
| f25f837339 | |||
| 441476b6c5 | |||
| ec34ed0520 | |||
| a4fc20a12b | |||
| e7ff094d63 | |||
| b2687ab1f7 | |||
| 4845a13c9e | |||
| 1881f60a16 | |||
| 1eb079543f | |||
| 1e313ced3f | |||
| 8b410347a6 |
+4
-1
@@ -12,4 +12,7 @@ cover.out
|
||||
*~
|
||||
vendor/*/
|
||||
*.bench
|
||||
coverage*.out
|
||||
coverage*.out
|
||||
|
||||
GoBuilds
|
||||
dist
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
[submodule "docs"]
|
||||
path = docs
|
||||
url = https://github.com/gohugoio/hugoDocs.git
|
||||
ignore = dirty
|
||||
+6
-9
@@ -1,8 +1,8 @@
|
||||
language: go
|
||||
sudo: required
|
||||
go:
|
||||
- 1.6.3
|
||||
- 1.7.3
|
||||
- 1.7.6
|
||||
- 1.8.3
|
||||
- tip
|
||||
os:
|
||||
- linux
|
||||
@@ -12,13 +12,10 @@ matrix:
|
||||
- go: tip
|
||||
fast_finish: true
|
||||
install:
|
||||
- make govendor
|
||||
- make vendor
|
||||
script:
|
||||
- make check
|
||||
- go build -race
|
||||
- ./hugo -s docs/
|
||||
- ./hugo --renderToMemory -s docs/
|
||||
- make hugo-race check
|
||||
before_install:
|
||||
# gem install must be run with sudo on OSX
|
||||
- sudo gem install asciidoctor | gem install asciidoctor
|
||||
# gem install must be run with sudo on OSX
|
||||
- sudo gem install asciidoctor | gem install asciidoctor
|
||||
- sudo pip install docutils
|
||||
|
||||
+38
-29
@@ -5,9 +5,7 @@ organization, tutorials, blog posts, bug reports, issues, feature requests,
|
||||
feature implementations, pull requests, answering questions on the forum,
|
||||
helping to manage issues, etc.
|
||||
|
||||
The Hugo community and maintainers are very active and helpful, and the project benefits greatly from this activity. We created a [step by step guide](https://gohugo.io/tutorials/how-to-contribute-to-hugo/) if you're unfamiliar with GitHub or contributing to open source projects in general.
|
||||
|
||||
[](https://waffle.io/spf13/hugo/metrics)
|
||||
The Hugo community and maintainers are [very active](https://github.com/gohugoio/hugo/pulse/monthly) and helpful, and the project benefits greatly from this activity. We created a [step by step guide](https://gohugo.io/tutorials/how-to-contribute-to-hugo/) if you're unfamiliar with GitHub or contributing to open source projects in general.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
@@ -16,20 +14,22 @@ The Hugo community and maintainers are very active and helpful, and the project
|
||||
* [Submitting Patches](#submitting-patches)
|
||||
* [Code Contribution Guidelines](#code-contribution-guidelines)
|
||||
* [Git Commit Message Guidelines](#git-commit-message-guidelines)
|
||||
* [Vendored Dependencies](#vendored-dependencies)
|
||||
* [Fetching the Sources From GitHub](#fetching-the-sources-from-github)
|
||||
* [Using Git Remotes](#using-git-remotes)
|
||||
* [Build Hugo with Your Changes](#build-hugo-with-your-changes)
|
||||
* [Add Compile Information to Hugo](#add-compile-information-to-hugo)
|
||||
* [Updating the Hugo Sources](#updating-the-hugo-sources)
|
||||
|
||||
## Asking Support Questions
|
||||
|
||||
We have an active [discussion forum](http://discuss.gohugo.io) where users and developers can ask questions.
|
||||
Please don't use the Github issue tracker to ask questions.
|
||||
We have an active [discussion forum](https://discuss.gohugo.io) where users and developers can ask questions.
|
||||
Please don't use the GitHub issue tracker to ask questions.
|
||||
|
||||
## Reporting Issues
|
||||
|
||||
If you believe you have found a defect in Hugo or its documentation, use
|
||||
the Github [issue tracker](https://github.com/spf13/hugo/issues) to report the problem to the Hugo maintainers.
|
||||
If you're not sure if it's a bug or not, start by asking in the [discussion forum](http://discuss.gohugo.io).
|
||||
the GitHub [issue tracker](https://github.com/gohugoio/hugo/issues) to report the problem to the Hugo maintainers.
|
||||
If you're not sure if it's a bug or not, start by asking in the [discussion forum](https://discuss.gohugo.io).
|
||||
When reporting the issue, please provide the version of Hugo in use (`hugo version`) and your operating system.
|
||||
|
||||
## Submitting Patches
|
||||
@@ -48,12 +48,12 @@ To make the contribution process as seamless as possible, we ask for the followi
|
||||
|
||||
* Go ahead and fork the project and make your changes. We encourage pull requests to allow for review and discussion of code changes.
|
||||
* When you’re ready to create a pull request, be sure to:
|
||||
* Sign the [CLA](https://cla-assistant.io/spf13/hugo).
|
||||
* Sign the [CLA](https://cla-assistant.io/gohugoio/hugo).
|
||||
* Have test cases for the new code. If you have questions about how to do this, please ask in your pull request.
|
||||
* Run `go fmt`.
|
||||
* Add documentation if you are adding new features or changing functionality. The docs site lives in `/docs`.
|
||||
* Squash your commits into a single commit. `git rebase -i`. It’s okay to force update your pull request with `git push -f`.
|
||||
* Make sure `go test ./...` passes, and `go build` completes. [Travis CI](https://travis-ci.org/spf13/hugo) (Linux and OS X) and [AppVeyor](https://ci.appveyor.com/project/spf13/hugo/branch/master) (Windows) will catch most things that are missing.
|
||||
* Ensure that `make check` succeeds. [Travis CI](https://travis-ci.org/gohugoio/hugo) (Linux and macOS) and [AppVeyor](https://ci.appveyor.com/project/gohugoio/hugo/branch/master) (Windows) will fail the build if `make check` fails.
|
||||
* Follow the **Git Commit Message Guidelines** below.
|
||||
|
||||
### Git Commit Message Guidelines
|
||||
@@ -84,22 +84,31 @@ new default function more useful for Hugo users.
|
||||
Fixes #1949
|
||||
```
|
||||
|
||||
### Vendored Dependencies
|
||||
|
||||
Hugo uses [govendor](https://github.com/kardianos/govendor) to vendor dependencies, but we don't commit the vendored packages themselves to the Hugo git repository.
|
||||
Therefore, a simple `go get` is not supported since `go get` is not vendor-aware.
|
||||
You **must use govendor** to fetch and manage Hugo's dependencies.
|
||||
|
||||
### Fetch the Sources From GitHub
|
||||
|
||||
```
|
||||
go get github.com/kardianos/govendor
|
||||
govendor get github.com/gohugoio/hugo
|
||||
```
|
||||
|
||||
### Using Git Remotes
|
||||
|
||||
Due to the way Go handles package imports, the best approach for working on a
|
||||
Hugo fork is to use Git Remotes. Here's a simple walk-through for getting
|
||||
started:
|
||||
|
||||
1. Get the latest Hugo sources:
|
||||
|
||||
```
|
||||
go get -u -t github.com/spf13/hugo/...
|
||||
```
|
||||
1. Fetch the Hugo sources as described above.
|
||||
|
||||
1. Change to the Hugo source directory:
|
||||
|
||||
```
|
||||
cd $GOPATH/src/github.com/spf13/hugo
|
||||
cd $HOME/go/src/github.com/gohugoio/hugo
|
||||
```
|
||||
|
||||
1. Create a new branch for your changes (the branch name is arbitrary):
|
||||
@@ -114,7 +123,7 @@ started:
|
||||
git commit -a -v
|
||||
```
|
||||
|
||||
1. Fork Hugo in Github.
|
||||
1. Fork Hugo in GitHub.
|
||||
|
||||
1. Add your fork as a new remote (the remote name, "fork" in this example, is arbitrary):
|
||||
|
||||
@@ -133,20 +142,20 @@ started:
|
||||
### Build Hugo with Your Changes
|
||||
|
||||
```bash
|
||||
cd $GOPATH/src/github.com/spf13/hugo
|
||||
go build
|
||||
mv hugo /usr/local/bin/
|
||||
cd $HOME/go/src/github.com/gohugoio/hugo
|
||||
make hugo
|
||||
# or to install in $HOME/go/bin:
|
||||
make install
|
||||
```
|
||||
|
||||
### Add Compile Information to Hugo
|
||||
### Updating the Hugo Sources
|
||||
|
||||
To add compile information to Hugo, replace the `go build` command with the following *(replace `/path/to/hugo` with the actual path)*:
|
||||
If you want to stay in sync with the Hugo repository, you can easily pull down
|
||||
the source changes, but you'll need to keep the vendored packages up-to-date as
|
||||
well.
|
||||
|
||||
go build -ldflags "-X /path/to/hugo/hugolib.CommitHash=`git rev-parse --short HEAD 2>/dev/null` -X github.com/spf13/hugo/hugolib.BuildDate=`date +%FT%T%z`"
|
||||
|
||||
This will result in `hugo version` output that looks similar to:
|
||||
|
||||
Hugo Static Site Generator v0.13-DEV-8042E77 buildDate: 2014-12-25T03:25:57-07:00
|
||||
|
||||
Alternatively, just run `make` — all the “magic” above is already in the `Makefile`. :wink:
|
||||
```
|
||||
git pull
|
||||
make vendor
|
||||
```
|
||||
|
||||
|
||||
+8
-42
@@ -1,49 +1,15 @@
|
||||
FROM golang:1.6.2
|
||||
MAINTAINER Sven Dowideit <SvenDowideit@home.org.au>
|
||||
FROM golang:1.8-alpine
|
||||
|
||||
ENV GOPATH /go
|
||||
ENV USER root
|
||||
|
||||
RUN apk update && apk add git make
|
||||
|
||||
# pre-install known dependencies before the source, so we don't redownload them whenever the source changes
|
||||
RUN go get github.com/stretchr/testify/assert \
|
||||
&& go get github.com/kyokomi/emoji \
|
||||
&& go get github.com/bep/inflect \
|
||||
&& go get github.com/BurntSushi/toml \
|
||||
&& go get github.com/PuerkitoBio/purell \
|
||||
&& go get github.com/PuerkitoBio/urlesc \
|
||||
&& go get github.com/dchest/cssmin \
|
||||
&& go get github.com/eknkc/amber \
|
||||
&& go get github.com/gorilla/websocket \
|
||||
&& go get github.com/kardianos/osext \
|
||||
&& go get github.com/miekg/mmark \
|
||||
&& go get github.com/mitchellh/mapstructure \
|
||||
&& go get github.com/russross/blackfriday \
|
||||
&& go get github.com/shurcooL/sanitized_anchor_name \
|
||||
&& go get github.com/spf13/afero \
|
||||
&& go get github.com/spf13/cast \
|
||||
&& go get github.com/spf13/jwalterweatherman \
|
||||
&& go get github.com/spf13/cobra \
|
||||
&& go get github.com/cpuguy83/go-md2man \
|
||||
&& go get github.com/inconshreveable/mousetrap \
|
||||
&& go get github.com/spf13/pflag \
|
||||
&& go get github.com/spf13/fsync \
|
||||
&& go get github.com/spf13/viper \
|
||||
&& go get github.com/kr/pretty \
|
||||
&& go get github.com/kr/text \
|
||||
&& go get github.com/magiconair/properties \
|
||||
&& go get golang.org/x/text/transform \
|
||||
&& go get golang.org/x/text/unicode/norm \
|
||||
&& go get github.com/yosssi/ace \
|
||||
&& go get github.com/spf13/nitro \
|
||||
&& go get github.com/fortytw2/leaktest \
|
||||
&& go get github.com/fsnotify/fsnotify
|
||||
RUN go get github.com/kardianos/govendor \
|
||||
&& govendor get github.com/gohugoio/hugo
|
||||
|
||||
COPY . /go/src/github.com/spf13/hugo
|
||||
RUN go get -d -v github.com/spf13/hugo
|
||||
RUN go install github.com/spf13/hugo
|
||||
|
||||
WORKDIR /go/src/github.com/spf13/hugo
|
||||
RUN go get -d -v
|
||||
RUN go build -o hugo main.go
|
||||
RUN go test github.com/spf13/hugo/...
|
||||
COPY . $GOPATH/src/github.com/gohugoio/hugo
|
||||
|
||||
RUN cd $GOPATH/src/github.com/gohugoio/hugo \
|
||||
&& make install test
|
||||
|
||||
@@ -1,83 +1,83 @@
|
||||
# A Self-Documenting Makefile: http://marmelab.com/blog/2016/02/29/auto-documented-makefile.html
|
||||
|
||||
# Adds build information from git repo
|
||||
#
|
||||
# as suggested by tatsushid in
|
||||
# https://github.com/spf13/hugo/issues/540
|
||||
PACKAGE = github.com/gohugoio/hugo
|
||||
COMMIT_HASH = `git rev-parse --short HEAD 2>/dev/null`
|
||||
BUILD_DATE = `date +%FT%T%z`
|
||||
LDFLAGS = -ldflags "-X ${PACKAGE}/hugolib.CommitHash=${COMMIT_HASH} -X ${PACKAGE}/hugolib.BuildDate=${BUILD_DATE}"
|
||||
NOGI_LDFLAGS = -ldflags "-X ${PACKAGE}/hugolib.BuildDate=${BUILD_DATE}"
|
||||
|
||||
COMMIT_HASH=`git rev-parse --short HEAD 2>/dev/null`
|
||||
BUILD_DATE=`date +%FT%T%z`
|
||||
LDFLAGS=-ldflags "-X github.com/spf13/hugo/hugolib.CommitHash=${COMMIT_HASH} -X github.com/spf13/hugo/hugolib.BuildDate=${BUILD_DATE}"
|
||||
PACKAGES = $(shell govendor list -no-status +local | sed 's/github.com.spf13.hugo/./')
|
||||
.PHONY: vendor docker check fmt lint test test-race vet test-cover-html help
|
||||
.DEFAULT_GOAL := help
|
||||
|
||||
all: gitinfo
|
||||
vendor: ## Install govendor and sync Hugo's vendored dependencies
|
||||
go get github.com/kardianos/govendor
|
||||
govendor sync ${PACKAGE}
|
||||
|
||||
install: install-gitinfo
|
||||
hugo: vendor ## Build hugo binary
|
||||
go build ${LDFLAGS} ${PACKAGE}
|
||||
|
||||
help:
|
||||
echo ${COMMIT_HASH}
|
||||
echo ${BUILD_DATE}
|
||||
hugo-race: vendor ## Build hugo binary with race detector enabled
|
||||
go build -race ${LDFLAGS} ${PACKAGE}
|
||||
|
||||
gitinfo:
|
||||
go build ${LDFLAGS} -o hugo main.go
|
||||
install: vendor ## Install hugo binary
|
||||
go install ${LDFLAGS} ${PACKAGE}
|
||||
|
||||
install-gitinfo:
|
||||
go install ${LDFLAGS} ./...
|
||||
hugo-no-gitinfo: LDFLAGS = ${NOGI_LDFLAGS}
|
||||
hugo-no-gitinfo: vendor hugo ## Build hugo without git info
|
||||
|
||||
no-git-info:
|
||||
go build -o hugo main.go
|
||||
|
||||
docker:
|
||||
docker: ## Build hugo Docker container
|
||||
docker build -t hugo .
|
||||
docker rm -f hugo-build || true
|
||||
docker run --name hugo-build hugo ls /go/bin
|
||||
docker cp hugo-build:/go/bin/hugo .
|
||||
docker rm hugo-build
|
||||
|
||||
govendor:
|
||||
go get -u github.com/kardianos/govendor
|
||||
go install github.com/kardianos/govendor
|
||||
govendor sync github.com/spf13/hugo
|
||||
govendor: vendor # Deprecated: use "vendor" target
|
||||
get: vendor # Deprecated: use "vendor"
|
||||
gitinfo: hugo # Deprecated: use "hugo" target
|
||||
install-gitinfo: install # Deprecated: use "install" target
|
||||
no-git-info: hugo-no-gitinfo # Deprecated: use "hugo-no-gitinfo" target
|
||||
|
||||
check: fmt vet test test-race
|
||||
check: test-race test386 fmt vet ## Run tests and linters
|
||||
|
||||
cyclo:
|
||||
@for d in `govendor list -no-status +local | sed 's/github.com.spf13.hugo/./'` ; do \
|
||||
if [ "`gocyclo -over 20 $$d | tee /dev/stderr`" ]; then \
|
||||
echo "^ cyclomatic complexity exceeds 20, refactor the code!" && echo && exit 1; \
|
||||
fi \
|
||||
done
|
||||
test386: ## Run tests in 32-bit mode
|
||||
GOARCH=386 govendor test +local
|
||||
|
||||
fmt:
|
||||
@for d in `govendor list -no-status +local | sed 's/github.com.spf13.hugo/./'` ; do \
|
||||
test: ## Run tests
|
||||
govendor test +local
|
||||
|
||||
test-race: ## Run tests with race detector
|
||||
govendor test -race +local
|
||||
|
||||
fmt: ## Run gofmt linter
|
||||
@for d in `govendor list -no-status +local | sed 's/github.com.gohugoio.hugo/./'` ; do \
|
||||
if [ "`gofmt -l $$d/*.go | tee /dev/stderr`" ]; then \
|
||||
echo "^ improperly formatted go files" && echo && exit 1; \
|
||||
fi \
|
||||
done
|
||||
|
||||
lint:
|
||||
@for d in `govendor list -no-status +local | sed 's/github.com.spf13.hugo/./'` ; do \
|
||||
lint: ## Run golint linter
|
||||
@for d in `govendor list -no-status +local | sed 's/github.com.gohugoio.hugo/./'` ; do \
|
||||
if [ "`golint $$d | tee /dev/stderr`" ]; then \
|
||||
echo "^ golint errors!" && echo && exit 1; \
|
||||
fi \
|
||||
done
|
||||
|
||||
get:
|
||||
go get -v -t ./...
|
||||
|
||||
test:
|
||||
govendor test +local
|
||||
|
||||
test-race:
|
||||
govendor test -race +local
|
||||
|
||||
vet:
|
||||
vet: ## Run go vet linter
|
||||
@if [ "`govendor vet +local | tee /dev/stderr`" ]; then \
|
||||
echo "^ go vet errors!" && echo && exit 1; \
|
||||
fi
|
||||
|
||||
test-cover-html:
|
||||
test-cover-html: PACKAGES = $(shell govendor list -no-status +local | sed 's/github.com.gohugoio.hugo/./')
|
||||
test-cover-html: ## Generate test coverage report
|
||||
echo "mode: count" > coverage-all.out
|
||||
$(foreach pkg,$(PACKAGES),\
|
||||
govendor test -coverprofile=coverage.out -covermode=count $(pkg);\
|
||||
tail -n +2 coverage.out >> coverage-all.out;)
|
||||
go tool cover -html=coverage-all.out
|
||||
go tool cover -html=coverage-all.out
|
||||
|
||||
check-vendor: ## Verify that vendored packages match git HEAD
|
||||
@git diff-index --quiet HEAD vendor/ || (echo "check-vendor target failed: vendored packages out of sync" && echo && git diff vendor/ && exit 1)
|
||||
|
||||
help:
|
||||
@grep -E '^[a-zA-Z0-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||

|
||||

|
||||
|
||||
A Fast and Flexible Static Site Generator built with love by [spf13](http://spf13.com/) and [friends](https://github.com/spf13/hugo/graphs/contributors) in [Go][].
|
||||
A Fast and Flexible Static Site Generator built with love by [spf13](http://spf13.com/) and [friends](https://github.com/gohugoio/hugo/graphs/contributors) in [Go][].
|
||||
|
||||
[Website](https://gohugo.io) |
|
||||
[Forum](https://discuss.gohugo.io) |
|
||||
[Developer Chat (no support)](https://gitter.im/spf13/hugo) |
|
||||
[Developer Chat (no support)](https://gitter.im/gohugoio/hugo) |
|
||||
[Documentation](https://gohugo.io/overview/introduction/) |
|
||||
[Installation Guide](https://gohugo.io/overview/installing/) |
|
||||
[Contribution Guide](CONTRIBUTING.md) |
|
||||
[Twitter](http://twitter.com/spf13)
|
||||
[Twitter](http://twitter.com/gohugoio)
|
||||
|
||||
[](https://godoc.org/github.com/spf13/hugo)
|
||||
[](https://travis-ci.org/spf13/hugo)
|
||||
[](https://ci.appveyor.com/project/spf13/hugo/branch/master)
|
||||
[](https://gitter.im/spf13/hugo?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
[](https://goreportcard.com/report/github.com/spf13/hugo)
|
||||
[](https://godoc.org/github.com/gohugoio/hugo)
|
||||
[](https://travis-ci.org/gohugoio/hugo)
|
||||
[](https://ci.appveyor.com/project/bep/hugo/branch/master)
|
||||
[](https://gitter.im/spf13/hugo?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
[](https://goreportcard.com/report/github.com/gohugoio/hugo)
|
||||
|
||||
## Overview
|
||||
|
||||
@@ -33,7 +33,7 @@ Hugo is designed to work well for any kind of website including blogs, tumbles a
|
||||
|
||||
#### Supported Architectures
|
||||
|
||||
Currently, we provide pre-built Hugo binaries for Windows, Linux, FreeBSD, NetBSD and OS X (Darwin) for x64, i386 and ARM architectures.
|
||||
Currently, we provide pre-built Hugo binaries for Windows, Linux, FreeBSD, NetBSD and macOS (Darwin) and [Android](https://gist.github.com/bep/a0d8a26cf6b4f8bc992729b8e50b480b) for x64, i386 and ARM architectures.
|
||||
|
||||
Hugo may also be compiled from source wherever the Go compiler tool chain can run, e.g. for other operating systems including DragonFly BSD, OpenBSD, Plan 9 and Solaris.
|
||||
|
||||
@@ -44,7 +44,7 @@ Hugo may also be compiled from source wherever the Go compiler tool chain can ru
|
||||
If you want to use Hugo as your site generator, simply install the Hugo binaries.
|
||||
The Hugo binaries have no external dependencies.
|
||||
|
||||
To contribute to the Hugo source code or documentation, you should [fork the Hugo GitHub project](https://github.com/spf13/hugo#fork-destination-box) and clone it to your local machine.
|
||||
To contribute to the Hugo source code or documentation, you should [fork the Hugo GitHub project](https://github.com/gohugoio/hugo#fork-destination-box) and clone it to your local machine.
|
||||
|
||||
Finally, you can install the Hugo source code with `go`, build the binaries yourself, and run Hugo that way.
|
||||
Building the binaries is an easy task for an experienced `go` getter.
|
||||
@@ -57,13 +57,13 @@ Use the [installation instructions in the Hugo documentation](https://gohugo.io/
|
||||
|
||||
Add Hugo and its package dependencies to your go `src` directory.
|
||||
|
||||
go get -v github.com/spf13/hugo
|
||||
go get -v github.com/gohugoio/hugo
|
||||
|
||||
Once the `get` completes, you should find your new `hugo` (or `hugo.exe`) executable sitting inside `$GOPATH/bin/`.
|
||||
|
||||
To update Hugo’s dependencies, use `go get` with the `-u` option.
|
||||
|
||||
go get -u -v github.com/spf13/hugo
|
||||
go get -u -v github.com/gohugoio/hugo
|
||||
|
||||
## Contributing to Hugo
|
||||
|
||||
@@ -74,19 +74,17 @@ organization, tutorials, blog posts, bug reports, issues, feature requests,
|
||||
feature implementations, pull requests, answering questions on the forum,
|
||||
helping to manage issues, etc.
|
||||
|
||||
The Hugo community and maintainers are very active and helpful, and the project benefits greatly from this activity.
|
||||
|
||||
[](https://waffle.io/spf13/hugo/metrics)
|
||||
The Hugo community and maintainers are [very active](https://github.com/gohugoio/hugo/pulse/monthly) and helpful, and the project benefits greatly from this activity.
|
||||
|
||||
### Asking Support Questions
|
||||
|
||||
We have an active [discussion forum](http://discuss.gohugo.io) where users and developers can ask questions.
|
||||
Please don't use the Github issue tracker to ask questions.
|
||||
Please don't use the GitHub issue tracker to ask questions.
|
||||
|
||||
### Reporting Issues
|
||||
|
||||
If you believe you have found a defect in Hugo or its documentation, use
|
||||
the Github issue tracker to report the problem to the Hugo maintainers.
|
||||
the GitHub issue tracker to report the problem to the Hugo maintainers.
|
||||
If you're not sure if it's a bug or not, start by asking in the [discussion forum](http://discuss.gohugo.io).
|
||||
When reporting the issue, please provide the version of Hugo in use (`hugo version`).
|
||||
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
init:
|
||||
- copy c:\MinGW\bin\mingw32-make.exe c:\MinGW\bin\make.exe
|
||||
- set PATH=%PATH%;C:\MinGW\bin;%GOPATH%\bin
|
||||
- go version
|
||||
- go env
|
||||
|
||||
# clones and cd's to path
|
||||
clone_folder: C:\GOPATH\src\github.com\gohugoio\hugo
|
||||
|
||||
install:
|
||||
- gem install asciidoctor
|
||||
- pip install docutils
|
||||
|
||||
build_script:
|
||||
- make hugo-race check
|
||||
Executable
+9
@@ -0,0 +1,9 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Send in a regexp mathing the benchmarks you want to run, i.e. './benchSite.sh "YAML"'.
|
||||
# Note the quotes, which will be needed for more complex expressions.
|
||||
# The above will run all variations, but only for front matter YAML.
|
||||
|
||||
echo "Running with BenchmarkSiteBuilding/${1}"
|
||||
|
||||
go test -run="NONE" -bench="BenchmarkSiteBuilding/${1}$" -test.benchmem=true ./hugolib -memprofile mem.prof -cpuprofile cpu.prof
|
||||
Vendored
+80
@@ -0,0 +1,80 @@
|
||||
// Copyright 2017-present The Hugo Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package cache
|
||||
|
||||
import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
// Partition represents a cache partition where Load is the callback
|
||||
// for when the partition is needed.
|
||||
type Partition struct {
|
||||
Key string
|
||||
Load func() (map[string]interface{}, error)
|
||||
}
|
||||
|
||||
type lazyPartition struct {
|
||||
initSync sync.Once
|
||||
cache map[string]interface{}
|
||||
load func() (map[string]interface{}, error)
|
||||
}
|
||||
|
||||
func (l *lazyPartition) init() error {
|
||||
var err error
|
||||
l.initSync.Do(func() {
|
||||
var c map[string]interface{}
|
||||
c, err = l.load()
|
||||
l.cache = c
|
||||
})
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// PartitionedLazyCache is a lazily loaded cache paritioned by a supplied string key.
|
||||
type PartitionedLazyCache struct {
|
||||
partitions map[string]*lazyPartition
|
||||
}
|
||||
|
||||
// NewPartitionedLazyCache creates a new NewPartitionedLazyCache with the supplied
|
||||
// partitions.
|
||||
func NewPartitionedLazyCache(partitions ...Partition) *PartitionedLazyCache {
|
||||
lazyPartitions := make(map[string]*lazyPartition, len(partitions))
|
||||
for _, partition := range partitions {
|
||||
lazyPartitions[partition.Key] = &lazyPartition{load: partition.Load}
|
||||
}
|
||||
cache := &PartitionedLazyCache{partitions: lazyPartitions}
|
||||
|
||||
return cache
|
||||
}
|
||||
|
||||
// Get initializes the partition if not already done so, then looks up the given
|
||||
// key in the given partition, returns nil if no value found.
|
||||
func (c *PartitionedLazyCache) Get(partition, key string) (interface{}, error) {
|
||||
p, found := c.partitions[partition]
|
||||
|
||||
if !found {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
if err := p.init(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if v, found := p.cache[key]; found {
|
||||
return v, nil
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
|
||||
}
|
||||
Vendored
+92
@@ -0,0 +1,92 @@
|
||||
// Copyright 2017-present The Hugo Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package cache
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestNewPartitionedLazyCache(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := require.New(t)
|
||||
|
||||
p1 := Partition{
|
||||
Key: "p1",
|
||||
Load: func() (map[string]interface{}, error) {
|
||||
return map[string]interface{}{
|
||||
"p1_1": "p1v1",
|
||||
"p1_2": "p1v2",
|
||||
"p1_nil": nil,
|
||||
}, nil
|
||||
},
|
||||
}
|
||||
|
||||
p2 := Partition{
|
||||
Key: "p2",
|
||||
Load: func() (map[string]interface{}, error) {
|
||||
return map[string]interface{}{
|
||||
"p2_1": "p2v1",
|
||||
"p2_2": "p2v2",
|
||||
"p2_3": "p2v3",
|
||||
}, nil
|
||||
},
|
||||
}
|
||||
|
||||
cache := NewPartitionedLazyCache(p1, p2)
|
||||
|
||||
v, err := cache.Get("p1", "p1_1")
|
||||
assert.NoError(err)
|
||||
assert.Equal("p1v1", v)
|
||||
|
||||
v, err = cache.Get("p1", "p2_1")
|
||||
assert.NoError(err)
|
||||
assert.Nil(v)
|
||||
|
||||
v, err = cache.Get("p1", "p1_nil")
|
||||
assert.NoError(err)
|
||||
assert.Nil(v)
|
||||
|
||||
v, err = cache.Get("p2", "p2_3")
|
||||
assert.NoError(err)
|
||||
assert.Equal("p2v3", v)
|
||||
|
||||
v, err = cache.Get("doesnotexist", "p1_1")
|
||||
assert.NoError(err)
|
||||
assert.Nil(v)
|
||||
|
||||
v, err = cache.Get("p1", "doesnotexist")
|
||||
assert.NoError(err)
|
||||
assert.Nil(v)
|
||||
|
||||
errorP := Partition{
|
||||
Key: "p3",
|
||||
Load: func() (map[string]interface{}, error) {
|
||||
return nil, errors.New("Failed")
|
||||
},
|
||||
}
|
||||
|
||||
cache = NewPartitionedLazyCache(errorP)
|
||||
|
||||
v, err = cache.Get("p1", "doesnotexist")
|
||||
assert.NoError(err)
|
||||
assert.Nil(v)
|
||||
|
||||
_, err = cache.Get("p3", "doesnotexist")
|
||||
assert.Error(err)
|
||||
|
||||
}
|
||||
@@ -48,8 +48,13 @@ func init() {
|
||||
}
|
||||
|
||||
func benchmark(cmd *cobra.Command, args []string) error {
|
||||
var err error
|
||||
if err = InitializeConfig(benchmarkCmd); err != nil {
|
||||
cfg, err := InitializeConfig(benchmarkCmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c, err := newCommandeer(cfg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -79,7 +84,7 @@ func benchmark(cmd *cobra.Command, args []string) error {
|
||||
|
||||
t := time.Now()
|
||||
for i := 0; i < benchmarkTimes; i++ {
|
||||
if err = resetAndbuildSites(false); err != nil {
|
||||
if err = c.resetAndBuildSites(false); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
// Copyright 2017 The Hugo Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package commands
|
||||
|
||||
import (
|
||||
"github.com/gohugoio/hugo/deps"
|
||||
"github.com/gohugoio/hugo/helpers"
|
||||
"github.com/gohugoio/hugo/hugofs"
|
||||
)
|
||||
|
||||
type commandeer struct {
|
||||
*deps.DepsCfg
|
||||
pathSpec *helpers.PathSpec
|
||||
configured bool
|
||||
}
|
||||
|
||||
func (c *commandeer) Set(key string, value interface{}) {
|
||||
if c.configured {
|
||||
panic("commandeer cannot be changed")
|
||||
}
|
||||
c.Cfg.Set(key, value)
|
||||
}
|
||||
|
||||
// PathSpec lazily creates a new PathSpec, as all the paths must
|
||||
// be configured before it is created.
|
||||
func (c *commandeer) PathSpec() *helpers.PathSpec {
|
||||
c.configured = true
|
||||
return c.pathSpec
|
||||
}
|
||||
|
||||
func (c *commandeer) initFs(fs *hugofs.Fs) error {
|
||||
c.DepsCfg.Fs = fs
|
||||
ps, err := helpers.NewPathSpec(fs, c.Cfg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c.pathSpec = ps
|
||||
return nil
|
||||
}
|
||||
|
||||
func newCommandeer(cfg *deps.DepsCfg) (*commandeer, error) {
|
||||
l := cfg.Language
|
||||
if l == nil {
|
||||
l = helpers.NewDefaultLanguage(cfg.Cfg)
|
||||
}
|
||||
ps, err := helpers.NewPathSpec(cfg.Fs, l)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &commandeer{DepsCfg: cfg, pathSpec: ps}, nil
|
||||
}
|
||||
+19
-22
@@ -19,13 +19,10 @@ import (
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/gohugoio/hugo/hugolib"
|
||||
"github.com/gohugoio/hugo/parser"
|
||||
"github.com/spf13/cast"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/hugo/helpers"
|
||||
"github.com/spf13/hugo/hugolib"
|
||||
"github.com/spf13/hugo/parser"
|
||||
jww "github.com/spf13/jwalterweatherman"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
var outputDir string
|
||||
@@ -80,13 +77,13 @@ func init() {
|
||||
convertCmd.PersistentFlags().SetAnnotation("source", cobra.BashCompSubdirsInDir, []string{})
|
||||
}
|
||||
|
||||
func convertContents(mark rune) (err error) {
|
||||
if err := InitializeConfig(); err != nil {
|
||||
func convertContents(mark rune) error {
|
||||
cfg, err := InitializeConfig()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
h, err := hugolib.NewHugoSitesFromConfiguration()
|
||||
|
||||
h, err := hugolib.NewHugoSites(*cfg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -104,42 +101,42 @@ func convertContents(mark rune) (err error) {
|
||||
return errors.New("No source files found")
|
||||
}
|
||||
|
||||
contentDir := helpers.AbsPathify(viper.GetString("contentDir"))
|
||||
jww.FEEDBACK.Println("processing", len(site.Source.Files()), "content files")
|
||||
contentDir := site.PathSpec.AbsPathify(site.Cfg.GetString("contentDir"))
|
||||
site.Log.FEEDBACK.Println("processing", len(site.Source.Files()), "content files")
|
||||
for _, file := range site.Source.Files() {
|
||||
jww.INFO.Println("Attempting to convert", file.LogicalName())
|
||||
page, err := hugolib.NewPage(file.LogicalName())
|
||||
site.Log.INFO.Println("Attempting to convert", file.LogicalName())
|
||||
page, err := site.NewPage(file.LogicalName())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
psr, err := parser.ReadFrom(file.Contents)
|
||||
if err != nil {
|
||||
jww.ERROR.Println("Error processing file:", file.Path())
|
||||
site.Log.ERROR.Println("Error processing file:", file.Path())
|
||||
return err
|
||||
}
|
||||
metadata, err := psr.Metadata()
|
||||
if err != nil {
|
||||
jww.ERROR.Println("Error processing file:", file.Path())
|
||||
site.Log.ERROR.Println("Error processing file:", file.Path())
|
||||
return err
|
||||
}
|
||||
|
||||
// better handling of dates in formats that don't have support for them
|
||||
if mark == parser.FormatToLeadRune("json") || mark == parser.FormatToLeadRune("yaml") || mark == parser.FormatToLeadRune("toml") {
|
||||
newmetadata := cast.ToStringMap(metadata)
|
||||
for k, v := range newmetadata {
|
||||
newMetadata := cast.ToStringMap(metadata)
|
||||
for k, v := range newMetadata {
|
||||
switch vv := v.(type) {
|
||||
case time.Time:
|
||||
newmetadata[k] = vv.Format(time.RFC3339)
|
||||
newMetadata[k] = vv.Format(time.RFC3339)
|
||||
}
|
||||
}
|
||||
metadata = newmetadata
|
||||
metadata = newMetadata
|
||||
}
|
||||
|
||||
page.SetDir(filepath.Join(contentDir, file.Dir()))
|
||||
page.SetSourceContent(psr.Content())
|
||||
if err = page.SetSourceMetaData(metadata, mark); err != nil {
|
||||
jww.ERROR.Printf("Failed to set source metadata for file %q: %s. For more info see For more info see https://github.com/spf13/hugo/issues/2458", page.FullFilePath(), err)
|
||||
site.Log.ERROR.Printf("Failed to set source metadata for file %q: %s. For more info see For more info see https://github.com/gohugoio/hugo/issues/2458", page.FullFilePath(), err)
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -153,9 +150,9 @@ func convertContents(mark rune) (err error) {
|
||||
return fmt.Errorf("Failed to save file %q: %s", page.FullFilePath(), err)
|
||||
}
|
||||
} else {
|
||||
jww.FEEDBACK.Println("Unsafe operation not allowed, use --unsafe or set a different output path")
|
||||
site.Log.FEEDBACK.Println("Unsafe operation not allowed, use --unsafe or set a different output path")
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -62,8 +62,8 @@ or just source them in directly:
|
||||
}
|
||||
|
||||
func init() {
|
||||
genautocompleteCmd.PersistentFlags().StringVarP(&autocompleteTarget, "completionfile", "", "/etc/bash_completion.d/hugo.sh", "Autocompletion file")
|
||||
genautocompleteCmd.PersistentFlags().StringVarP(&autocompleteType, "type", "", "bash", "Autocompletion type (currently only bash supported)")
|
||||
genautocompleteCmd.PersistentFlags().StringVarP(&autocompleteTarget, "completionfile", "", "/etc/bash_completion.d/hugo.sh", "autocompletion file")
|
||||
genautocompleteCmd.PersistentFlags().StringVarP(&autocompleteType, "type", "", "bash", "autocompletion type (currently only bash supported)")
|
||||
|
||||
// For bash-completion
|
||||
genautocompleteCmd.PersistentFlags().SetAnnotation("completionfile", cobra.BashCompFilenameExt, []string{})
|
||||
|
||||
+6
-4
@@ -20,10 +20,10 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gohugoio/hugo/helpers"
|
||||
"github.com/gohugoio/hugo/hugofs"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/cobra/doc"
|
||||
"github.com/spf13/hugo/helpers"
|
||||
"github.com/spf13/hugo/hugofs"
|
||||
jww "github.com/spf13/jwalterweatherman"
|
||||
)
|
||||
|
||||
@@ -51,9 +51,11 @@ for rendering in Hugo.`,
|
||||
if !strings.HasSuffix(gendocdir, helpers.FilePathSeparator) {
|
||||
gendocdir += helpers.FilePathSeparator
|
||||
}
|
||||
if found, _ := helpers.Exists(gendocdir, hugofs.Os()); !found {
|
||||
if found, _ := helpers.Exists(gendocdir, hugofs.Os); !found {
|
||||
jww.FEEDBACK.Println("Directory", gendocdir, "does not exist, creating...")
|
||||
hugofs.Os().MkdirAll(gendocdir, 0777)
|
||||
if err := hugofs.Os.MkdirAll(gendocdir, 0777); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
now := time.Now().Format(time.RFC3339)
|
||||
prepender := func(filename string) string {
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
// Copyright 2017-present The Hugo Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package commands
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/gohugoio/hugo/docshelper"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
type genDocsHelper struct {
|
||||
target string
|
||||
cmd *cobra.Command
|
||||
}
|
||||
|
||||
func createGenDocsHelper() *genDocsHelper {
|
||||
g := &genDocsHelper{
|
||||
cmd: &cobra.Command{
|
||||
Use: "docshelper",
|
||||
Short: "Generate some data files for the Hugo docs.",
|
||||
Hidden: true,
|
||||
},
|
||||
}
|
||||
|
||||
g.cmd.RunE = func(cmd *cobra.Command, args []string) error {
|
||||
return g.generate()
|
||||
}
|
||||
|
||||
// Note that ./docs is a submodule, and writing to that would be suboptimal.
|
||||
// Let us assume that the default is a sibling project.
|
||||
g.cmd.PersistentFlags().StringVarP(&g.target, "dir", "", "../hugoDocs/data", "data dir")
|
||||
|
||||
return g
|
||||
}
|
||||
|
||||
func (g *genDocsHelper) generate() error {
|
||||
fmt.Println("Generate docs data to", g.target)
|
||||
|
||||
targetFile := filepath.Join(g.target, "docs.json")
|
||||
|
||||
f, err := os.Create(targetFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
enc := json.NewEncoder(f)
|
||||
enc.SetIndent("", " ")
|
||||
|
||||
if err := enc.Encode(docshelper.DocProviders); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Println("Done!")
|
||||
return nil
|
||||
|
||||
}
|
||||
+7
-5
@@ -17,10 +17,10 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/gohugoio/hugo/helpers"
|
||||
"github.com/gohugoio/hugo/hugofs"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/cobra/doc"
|
||||
"github.com/spf13/hugo/helpers"
|
||||
"github.com/spf13/hugo/hugofs"
|
||||
jww "github.com/spf13/jwalterweatherman"
|
||||
)
|
||||
|
||||
@@ -36,14 +36,16 @@ in the "man" directory under the current directory.`,
|
||||
header := &doc.GenManHeader{
|
||||
Section: "1",
|
||||
Manual: "Hugo Manual",
|
||||
Source: fmt.Sprintf("Hugo %s", helpers.HugoVersion()),
|
||||
Source: fmt.Sprintf("Hugo %s", helpers.CurrentHugoVersion),
|
||||
}
|
||||
if !strings.HasSuffix(genmandir, helpers.FilePathSeparator) {
|
||||
genmandir += helpers.FilePathSeparator
|
||||
}
|
||||
if found, _ := helpers.Exists(genmandir, hugofs.Os()); !found {
|
||||
if found, _ := helpers.Exists(genmandir, hugofs.Os); !found {
|
||||
jww.FEEDBACK.Println("Directory", genmandir, "does not exist, creating...")
|
||||
hugofs.Os().MkdirAll(genmandir, 0777)
|
||||
if err := hugofs.Os.MkdirAll(genmandir, 0777); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
cmd.Root().DisableAutoGenTag = true
|
||||
|
||||
|
||||
+337
-254
File diff suppressed because it is too large
Load Diff
+79
-33
@@ -25,12 +25,13 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gohugoio/hugo/helpers"
|
||||
"github.com/gohugoio/hugo/hugofs"
|
||||
"github.com/gohugoio/hugo/hugolib"
|
||||
"github.com/gohugoio/hugo/parser"
|
||||
"github.com/spf13/afero"
|
||||
"github.com/spf13/cast"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/hugo/helpers"
|
||||
"github.com/spf13/hugo/hugofs"
|
||||
"github.com/spf13/hugo/hugolib"
|
||||
"github.com/spf13/hugo/parser"
|
||||
jww "github.com/spf13/jwalterweatherman"
|
||||
)
|
||||
|
||||
@@ -57,12 +58,10 @@ Import from Jekyll requires two paths, e.g. ` + "`hugo import jekyll jekyll_root
|
||||
}
|
||||
|
||||
func init() {
|
||||
importJekyllCmd.Flags().Bool("force", false, "Allow import into non-empty target directory")
|
||||
importJekyllCmd.Flags().Bool("force", false, "allow import into non-empty target directory")
|
||||
}
|
||||
|
||||
func importFromJekyll(cmd *cobra.Command, args []string) error {
|
||||
jww.SetLogThreshold(jww.LevelTrace)
|
||||
jww.SetStdoutThreshold(jww.LevelWarn)
|
||||
|
||||
if len(args) < 2 {
|
||||
return newUserError(`Import from Jekyll requires two paths, e.g. ` + "`hugo import jekyll jekyll_root_path target_path`.")
|
||||
@@ -85,8 +84,9 @@ func importFromJekyll(cmd *cobra.Command, args []string) error {
|
||||
}
|
||||
|
||||
forceImport, _ := cmd.Flags().GetBool("force")
|
||||
if err := createSiteFromJekyll(jekyllRoot, targetDir, forceImport); err != nil {
|
||||
return newUserError(err)
|
||||
site, err := createSiteFromJekyll(jekyllRoot, targetDir, forceImport)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
jww.FEEDBACK.Println("Importing...")
|
||||
@@ -120,10 +120,10 @@ func importFromJekyll(cmd *cobra.Command, args []string) error {
|
||||
}
|
||||
|
||||
fileCount++
|
||||
return convertJekyllPost(path, relPath, targetDir, draft)
|
||||
return convertJekyllPost(site, path, relPath, targetDir, draft)
|
||||
}
|
||||
|
||||
err = helpers.SymbolicWalk(hugofs.Os(), jekyllRoot, callback)
|
||||
err = helpers.SymbolicWalk(hugofs.Os, jekyllRoot, callback)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -137,21 +137,27 @@ func importFromJekyll(cmd *cobra.Command, args []string) error {
|
||||
}
|
||||
|
||||
// TODO: Consider calling doNewSite() instead?
|
||||
func createSiteFromJekyll(jekyllRoot, targetDir string, force bool) error {
|
||||
fs := hugofs.Source()
|
||||
func createSiteFromJekyll(jekyllRoot, targetDir string, force bool) (*hugolib.Site, error) {
|
||||
s, err := hugolib.NewSiteDefaultLang()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
fs := s.Fs.Source
|
||||
|
||||
if exists, _ := helpers.Exists(targetDir, fs); exists {
|
||||
if isDir, _ := helpers.IsDir(targetDir, fs); !isDir {
|
||||
return errors.New("Target path \"" + targetDir + "\" already exists but not a directory")
|
||||
return nil, errors.New("Target path \"" + targetDir + "\" already exists but not a directory")
|
||||
}
|
||||
|
||||
isEmpty, _ := helpers.IsEmpty(targetDir, fs)
|
||||
|
||||
if !isEmpty && !force {
|
||||
return errors.New("Target path \"" + targetDir + "\" already exists and is not empty")
|
||||
return nil, errors.New("Target path \"" + targetDir + "\" already exists and is not empty")
|
||||
}
|
||||
}
|
||||
|
||||
jekyllConfig := loadJekyllConfig(jekyllRoot)
|
||||
jekyllConfig := loadJekyllConfig(fs, jekyllRoot)
|
||||
|
||||
// Crude test to make sure at least one of _drafts/ and _posts/ exists
|
||||
// and is not empty.
|
||||
@@ -168,7 +174,7 @@ func createSiteFromJekyll(jekyllRoot, targetDir string, force bool) error {
|
||||
}
|
||||
}
|
||||
if !hasPostsOrDrafts {
|
||||
return errors.New("Your Jekyll root contains neither posts nor drafts, aborting.")
|
||||
return nil, errors.New("Your Jekyll root contains neither posts nor drafts, aborting.")
|
||||
}
|
||||
|
||||
mkdir(targetDir, "layouts")
|
||||
@@ -178,15 +184,14 @@ func createSiteFromJekyll(jekyllRoot, targetDir string, force bool) error {
|
||||
mkdir(targetDir, "data")
|
||||
mkdir(targetDir, "themes")
|
||||
|
||||
createConfigFromJekyll(targetDir, "yaml", jekyllConfig)
|
||||
createConfigFromJekyll(fs, targetDir, "yaml", jekyllConfig)
|
||||
|
||||
copyJekyllFilesAndFolders(jekyllRoot, filepath.Join(targetDir, "static"))
|
||||
|
||||
return nil
|
||||
return s, nil
|
||||
}
|
||||
|
||||
func loadJekyllConfig(jekyllRoot string) map[string]interface{} {
|
||||
fs := hugofs.Source()
|
||||
func loadJekyllConfig(fs afero.Fs, jekyllRoot string) map[string]interface{} {
|
||||
path := filepath.Join(jekyllRoot, "_config.yml")
|
||||
|
||||
exists, err := helpers.Exists(path, fs)
|
||||
@@ -218,7 +223,7 @@ func loadJekyllConfig(jekyllRoot string) map[string]interface{} {
|
||||
return c.(map[string]interface{})
|
||||
}
|
||||
|
||||
func createConfigFromJekyll(inpath string, kind string, jekyllConfig map[string]interface{}) (err error) {
|
||||
func createConfigFromJekyll(fs afero.Fs, inpath string, kind string, jekyllConfig map[string]interface{}) (err error) {
|
||||
title := "My New Hugo Site"
|
||||
baseURL := "http://example.org/"
|
||||
|
||||
@@ -246,17 +251,13 @@ func createConfigFromJekyll(inpath string, kind string, jekyllConfig map[string]
|
||||
}
|
||||
kind = parser.FormatSanitize(kind)
|
||||
|
||||
by, err := parser.InterfaceToConfig(in, parser.FormatToLeadRune(kind))
|
||||
var buf bytes.Buffer
|
||||
err = parser.InterfaceToConfig(in, parser.FormatToLeadRune(kind), &buf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = helpers.WriteToDisk(filepath.Join(inpath, "config."+kind), bytes.NewReader(by), hugofs.Source())
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return nil
|
||||
return helpers.WriteToDisk(filepath.Join(inpath, "config."+kind), &buf, fs)
|
||||
}
|
||||
|
||||
func copyFile(source string, dest string) error {
|
||||
@@ -371,7 +372,7 @@ func parseJekyllFilename(filename string) (time.Time, string, error) {
|
||||
return time.Now(), "", errors.New("filename not match")
|
||||
}
|
||||
|
||||
postDate, err := time.Parse("2006-01-02", r[0][1])
|
||||
postDate, err := time.Parse("2006-1-2", r[0][1])
|
||||
if err != nil {
|
||||
return time.Now(), "", err
|
||||
}
|
||||
@@ -381,7 +382,7 @@ func parseJekyllFilename(filename string) (time.Time, string, error) {
|
||||
return postDate, postName, nil
|
||||
}
|
||||
|
||||
func convertJekyllPost(path, relPath, targetDir string, draft bool) error {
|
||||
func convertJekyllPost(s *hugolib.Site, path, relPath, targetDir string, draft bool) error {
|
||||
jww.TRACE.Println("Converting", path)
|
||||
|
||||
filename := filepath.Base(path)
|
||||
@@ -424,7 +425,7 @@ func convertJekyllPost(path, relPath, targetDir string, draft bool) error {
|
||||
jww.TRACE.Println(newmetadata)
|
||||
content := convertJekyllContent(newmetadata, string(psr.Content()))
|
||||
|
||||
page, err := hugolib.NewPage(filename)
|
||||
page, err := s.NewPage(filename)
|
||||
if err != nil {
|
||||
jww.ERROR.Println("New page error", filename)
|
||||
return err
|
||||
@@ -517,7 +518,7 @@ func convertJekyllContent(m interface{}, content string) string {
|
||||
re *regexp.Regexp
|
||||
replace string
|
||||
}{
|
||||
{regexp.MustCompile("<!-- more -->"), "<!--more-->"},
|
||||
{regexp.MustCompile("(?i)<!-- more -->"), "<!--more-->"},
|
||||
{regexp.MustCompile(`\{%\s*raw\s*%\}\s*(.*?)\s*\{%\s*endraw\s*%\}`), "$1"},
|
||||
{regexp.MustCompile(`{%\s*highlight\s*(.*?)\s*%}`), "{{< highlight $1 >}}"},
|
||||
{regexp.MustCompile(`{%\s*endhighlight\s*%}`), "{{< / highlight >}}"},
|
||||
@@ -527,5 +528,50 @@ func convertJekyllContent(m interface{}, content string) string {
|
||||
content = replace.re.ReplaceAllString(content, replace.replace)
|
||||
}
|
||||
|
||||
replaceListFunc := []struct {
|
||||
re *regexp.Regexp
|
||||
replace func(string) string
|
||||
}{
|
||||
// Octopress image tag: http://octopress.org/docs/plugins/image-tag/
|
||||
{regexp.MustCompile(`{%\s+img\s*(.*?)\s*%}`), replaceImageTag},
|
||||
}
|
||||
|
||||
for _, replace := range replaceListFunc {
|
||||
content = replace.re.ReplaceAllStringFunc(content, replace.replace)
|
||||
}
|
||||
|
||||
return content
|
||||
}
|
||||
|
||||
func replaceImageTag(match string) string {
|
||||
r := regexp.MustCompile(`{%\s+img\s*(\p{L}*)\s+([\S]*/[\S]+)\s+(\d*)\s*(\d*)\s*(.*?)\s*%}`)
|
||||
result := bytes.NewBufferString("{{< figure ")
|
||||
parts := r.FindStringSubmatch(match)
|
||||
// Index 0 is the entire string, ignore
|
||||
replaceOptionalPart(result, "class", parts[1])
|
||||
replaceOptionalPart(result, "src", parts[2])
|
||||
replaceOptionalPart(result, "width", parts[3])
|
||||
replaceOptionalPart(result, "height", parts[4])
|
||||
// title + alt
|
||||
part := parts[5]
|
||||
if len(part) > 0 {
|
||||
splits := strings.Split(part, "'")
|
||||
lenSplits := len(splits)
|
||||
if lenSplits == 1 {
|
||||
replaceOptionalPart(result, "title", splits[0])
|
||||
} else if lenSplits == 3 {
|
||||
replaceOptionalPart(result, "title", splits[1])
|
||||
} else if lenSplits == 5 {
|
||||
replaceOptionalPart(result, "title", splits[1])
|
||||
replaceOptionalPart(result, "alt", splits[3])
|
||||
}
|
||||
}
|
||||
result.WriteString(">}}")
|
||||
return result.String()
|
||||
|
||||
}
|
||||
func replaceOptionalPart(buffer *bytes.Buffer, partName string, part string) {
|
||||
if len(part) > 0 {
|
||||
buffer.WriteString(partName + "=\"" + part + "\" ")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,6 +88,8 @@ func TestConvertJekyllContent(t *testing.T) {
|
||||
}{
|
||||
{map[interface{}]interface{}{},
|
||||
`Test content\n<!-- more -->\npart2 content`, `Test content\n<!--more-->\npart2 content`},
|
||||
{map[interface{}]interface{}{},
|
||||
`Test content\n<!-- More -->\npart2 content`, `Test content\n<!--more-->\npart2 content`},
|
||||
{map[interface{}]interface{}{"excerpt_separator": "<!--sep-->"},
|
||||
`Test content\n<!--sep-->\npart2 content`, `Test content\n<!--more-->\npart2 content`},
|
||||
{map[interface{}]interface{}{}, "{% raw %}text{% endraw %}", "text"},
|
||||
@@ -95,6 +97,26 @@ func TestConvertJekyllContent(t *testing.T) {
|
||||
{map[interface{}]interface{}{},
|
||||
"{% highlight go %}\nvar s int\n{% endhighlight %}",
|
||||
"{{< highlight go >}}\nvar s int\n{{< / highlight >}}"},
|
||||
|
||||
// Octopress image tag
|
||||
{map[interface{}]interface{}{},
|
||||
"{% img http://placekitten.com/890/280 %}",
|
||||
"{{< figure src=\"http://placekitten.com/890/280\" >}}"},
|
||||
{map[interface{}]interface{}{},
|
||||
"{% img left http://placekitten.com/320/250 Place Kitten #2 %}",
|
||||
"{{< figure class=\"left\" src=\"http://placekitten.com/320/250\" title=\"Place Kitten #2\" >}}"},
|
||||
{map[interface{}]interface{}{},
|
||||
"{% img right http://placekitten.com/300/500 150 250 'Place Kitten #3' %}",
|
||||
"{{< figure class=\"right\" src=\"http://placekitten.com/300/500\" width=\"150\" height=\"250\" title=\"Place Kitten #3\" >}}"},
|
||||
{map[interface{}]interface{}{},
|
||||
"{% img right http://placekitten.com/300/500 150 250 'Place Kitten #4' 'An image of a very cute kitten' %}",
|
||||
"{{< figure class=\"right\" src=\"http://placekitten.com/300/500\" width=\"150\" height=\"250\" title=\"Place Kitten #4\" alt=\"An image of a very cute kitten\" >}}"},
|
||||
{map[interface{}]interface{}{},
|
||||
"{% img http://placekitten.com/300/500 150 250 'Place Kitten #4' 'An image of a very cute kitten' %}",
|
||||
"{{< figure src=\"http://placekitten.com/300/500\" width=\"150\" height=\"250\" title=\"Place Kitten #4\" alt=\"An image of a very cute kitten\" >}}"},
|
||||
{map[interface{}]interface{}{},
|
||||
"{% img right /placekitten/300/500 'Place Kitten #4' 'An image of a very cute kitten' %}",
|
||||
"{{< figure class=\"right\" src=\"/placekitten/300/500\" title=\"Place Kitten #4\" alt=\"An image of a very cute kitten\" >}}"},
|
||||
}
|
||||
|
||||
for _, data := range testDataList {
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// +build darwin
|
||||
// Copyright 2015 The Hugo Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@@ -76,11 +75,11 @@ func tweakLimit() {
|
||||
jww.ERROR.Println("Unable to obtain rLimit", err)
|
||||
}
|
||||
if rLimit.Cur < rLimit.Max {
|
||||
rLimit.Max = 999999
|
||||
rLimit.Cur = 999999
|
||||
rLimit.Max = 64000
|
||||
rLimit.Cur = 64000
|
||||
err = syscall.Setrlimit(syscall.RLIMIT_NOFILE, &rLimit)
|
||||
if err != nil {
|
||||
jww.ERROR.Println("Unable to increase number of open files limit", err)
|
||||
jww.WARN.Println("Unable to increase number of open files limit", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+28
-11
@@ -16,10 +16,9 @@ package commands
|
||||
import (
|
||||
"path/filepath"
|
||||
|
||||
"github.com/gohugoio/hugo/hugolib"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/hugo/hugolib"
|
||||
jww "github.com/spf13/jwalterweatherman"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -45,13 +44,19 @@ var listDraftsCmd = &cobra.Command{
|
||||
Long: `List all of the drafts in your content directory.`,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
|
||||
if err := InitializeConfig(); err != nil {
|
||||
cfg, err := InitializeConfig()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
viper.Set("buildDrafts", true)
|
||||
c, err := newCommandeer(cfg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
sites, err := hugolib.NewHugoSitesFromConfiguration()
|
||||
c.Set("buildDrafts", true)
|
||||
|
||||
sites, err := hugolib.NewHugoSites(*cfg)
|
||||
|
||||
if err != nil {
|
||||
return newSystemError("Error creating sites", err)
|
||||
@@ -80,13 +85,19 @@ var listFutureCmd = &cobra.Command{
|
||||
posted in the future.`,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
|
||||
if err := InitializeConfig(); err != nil {
|
||||
cfg, err := InitializeConfig()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
viper.Set("buildFuture", true)
|
||||
c, err := newCommandeer(cfg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
sites, err := hugolib.NewHugoSitesFromConfiguration()
|
||||
c.Set("buildFuture", true)
|
||||
|
||||
sites, err := hugolib.NewHugoSites(*cfg)
|
||||
|
||||
if err != nil {
|
||||
return newSystemError("Error creating sites", err)
|
||||
@@ -115,13 +126,19 @@ var listExpiredCmd = &cobra.Command{
|
||||
expired.`,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
|
||||
if err := InitializeConfig(); err != nil {
|
||||
cfg, err := InitializeConfig()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
viper.Set("buildExpired", true)
|
||||
c, err := newCommandeer(cfg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
sites, err := hugolib.NewHugoSitesFromConfiguration()
|
||||
c.Set("buildExpired", true)
|
||||
|
||||
sites, err := hugolib.NewHugoSites(*cfg)
|
||||
|
||||
if err != nil {
|
||||
return newSystemError("Error creating sites", err)
|
||||
|
||||
@@ -29,15 +29,17 @@ var configCmd = &cobra.Command{
|
||||
}
|
||||
|
||||
func init() {
|
||||
configCmd.RunE = config
|
||||
configCmd.RunE = printConfig
|
||||
}
|
||||
|
||||
func config(cmd *cobra.Command, args []string) error {
|
||||
if err := InitializeConfig(configCmd); err != nil {
|
||||
func printConfig(cmd *cobra.Command, args []string) error {
|
||||
cfg, err := InitializeConfig(configCmd)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
allSettings := viper.AllSettings()
|
||||
allSettings := cfg.Cfg.(*viper.Viper).AllSettings()
|
||||
|
||||
var separator string
|
||||
if allSettings["metadataformat"] == "toml" {
|
||||
|
||||
+74
-54
@@ -16,16 +16,19 @@ package commands
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gohugoio/hugo/create"
|
||||
"github.com/gohugoio/hugo/helpers"
|
||||
"github.com/gohugoio/hugo/hugofs"
|
||||
"github.com/gohugoio/hugo/hugolib"
|
||||
"github.com/gohugoio/hugo/parser"
|
||||
"github.com/spf13/afero"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/hugo/create"
|
||||
"github.com/spf13/hugo/helpers"
|
||||
"github.com/spf13/hugo/hugofs"
|
||||
"github.com/spf13/hugo/parser"
|
||||
jww "github.com/spf13/jwalterweatherman"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
@@ -38,9 +41,9 @@ var (
|
||||
|
||||
func init() {
|
||||
newSiteCmd.Flags().StringVarP(&configFormat, "format", "f", "toml", "config & frontmatter format")
|
||||
newSiteCmd.Flags().Bool("force", false, "Init inside non-empty directory")
|
||||
newSiteCmd.Flags().Bool("force", false, "init inside non-empty directory")
|
||||
newCmd.Flags().StringVarP(&configFormat, "format", "f", "toml", "frontmatter format")
|
||||
newCmd.Flags().StringVarP(&contentType, "kind", "k", "", "Content type to create")
|
||||
newCmd.Flags().StringVarP(&contentType, "kind", "k", "", "content type to create")
|
||||
newCmd.PersistentFlags().StringVarP(&source, "source", "s", "", "filesystem path to read files relative from")
|
||||
newCmd.PersistentFlags().SetAnnotation("source", cobra.BashCompSubdirsInDir, []string{})
|
||||
newCmd.Flags().StringVar(&contentEditor, "editor", "", "edit new content with this editor, if provided")
|
||||
@@ -84,36 +87,49 @@ as you see fit.`,
|
||||
|
||||
// NewContent adds new content to a Hugo site.
|
||||
func NewContent(cmd *cobra.Command, args []string) error {
|
||||
if err := InitializeConfig(); err != nil {
|
||||
cfg, err := InitializeConfig()
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if flagChanged(cmd.Flags(), "format") {
|
||||
viper.Set("metaDataFormat", configFormat)
|
||||
c, err := newCommandeer(cfg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if flagChanged(cmd.Flags(), "editor") {
|
||||
viper.Set("newContentEditor", contentEditor)
|
||||
if cmd.Flags().Changed("format") {
|
||||
c.Set("metaDataFormat", configFormat)
|
||||
}
|
||||
|
||||
if cmd.Flags().Changed("editor") {
|
||||
c.Set("newContentEditor", contentEditor)
|
||||
}
|
||||
|
||||
if len(args) < 1 {
|
||||
return newUserError("path needs to be provided")
|
||||
}
|
||||
|
||||
createpath := args[0]
|
||||
createPath := args[0]
|
||||
|
||||
var kind string
|
||||
|
||||
createpath, kind = newContentPathSection(createpath)
|
||||
createPath, kind = newContentPathSection(createPath)
|
||||
|
||||
if contentType != "" {
|
||||
kind = contentType
|
||||
}
|
||||
|
||||
return create.NewContent(hugofs.Source(), kind, createpath)
|
||||
s, err := hugolib.NewSite(*cfg)
|
||||
|
||||
if err != nil {
|
||||
return newSystemError(err)
|
||||
}
|
||||
|
||||
return create.NewContent(s, kind, createPath)
|
||||
}
|
||||
|
||||
func doNewSite(basepath string, force bool) error {
|
||||
func doNewSite(fs *hugofs.Fs, basepath string, force bool) error {
|
||||
dirs := []string{
|
||||
filepath.Join(basepath, "layouts"),
|
||||
filepath.Join(basepath, "content"),
|
||||
@@ -123,12 +139,12 @@ func doNewSite(basepath string, force bool) error {
|
||||
filepath.Join(basepath, "themes"),
|
||||
}
|
||||
|
||||
if exists, _ := helpers.Exists(basepath, hugofs.Source()); exists {
|
||||
if isDir, _ := helpers.IsDir(basepath, hugofs.Source()); !isDir {
|
||||
if exists, _ := helpers.Exists(basepath, fs.Source); exists {
|
||||
if isDir, _ := helpers.IsDir(basepath, fs.Source); !isDir {
|
||||
return errors.New(basepath + " already exists but not a directory")
|
||||
}
|
||||
|
||||
isEmpty, _ := helpers.IsEmpty(basepath, hugofs.Source())
|
||||
isEmpty, _ := helpers.IsEmpty(basepath, fs.Source)
|
||||
|
||||
switch {
|
||||
case !isEmpty && !force:
|
||||
@@ -137,7 +153,7 @@ func doNewSite(basepath string, force bool) error {
|
||||
case !isEmpty && force:
|
||||
all := append(dirs, filepath.Join(basepath, "config."+configFormat))
|
||||
for _, path := range all {
|
||||
if exists, _ := helpers.Exists(path, hugofs.Source()); exists {
|
||||
if exists, _ := helpers.Exists(path, fs.Source); exists {
|
||||
return errors.New(path + " already exists")
|
||||
}
|
||||
}
|
||||
@@ -145,10 +161,12 @@ func doNewSite(basepath string, force bool) error {
|
||||
}
|
||||
|
||||
for _, dir := range dirs {
|
||||
hugofs.Source().MkdirAll(dir, 0777)
|
||||
if err := fs.Source.MkdirAll(dir, 0777); err != nil {
|
||||
return fmt.Errorf("Failed to create dir: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
createConfig(basepath, configFormat)
|
||||
createConfig(fs, basepath, configFormat)
|
||||
|
||||
jww.FEEDBACK.Printf("Congratulations! Your new Hugo site is created in %s.\n\n", basepath)
|
||||
jww.FEEDBACK.Println(nextStepsText())
|
||||
@@ -190,43 +208,49 @@ func NewSite(cmd *cobra.Command, args []string) error {
|
||||
|
||||
forceNew, _ := cmd.Flags().GetBool("force")
|
||||
|
||||
return doNewSite(createpath, forceNew)
|
||||
return doNewSite(hugofs.NewDefault(viper.New()), createpath, forceNew)
|
||||
}
|
||||
|
||||
// NewTheme creates a new Hugo theme.
|
||||
func NewTheme(cmd *cobra.Command, args []string) error {
|
||||
if err := InitializeConfig(); err != nil {
|
||||
cfg, err := InitializeConfig()
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(args) < 1 {
|
||||
|
||||
return newUserError("theme name needs to be provided")
|
||||
}
|
||||
|
||||
createpath := helpers.AbsPathify(filepath.Join(viper.GetString("themesDir"), args[0]))
|
||||
c, err := newCommandeer(cfg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
createpath := c.PathSpec().AbsPathify(filepath.Join(c.Cfg.GetString("themesDir"), args[0]))
|
||||
jww.INFO.Println("creating theme at", createpath)
|
||||
|
||||
if x, _ := helpers.Exists(createpath, hugofs.Source()); x {
|
||||
if x, _ := helpers.Exists(createpath, cfg.Fs.Source); x {
|
||||
return newUserError(createpath, "already exists")
|
||||
}
|
||||
|
||||
mkdir(createpath, "layouts", "_default")
|
||||
mkdir(createpath, "layouts", "partials")
|
||||
|
||||
touchFile(createpath, "layouts", "index.html")
|
||||
touchFile(createpath, "layouts", "404.html")
|
||||
touchFile(createpath, "layouts", "_default", "list.html")
|
||||
touchFile(createpath, "layouts", "_default", "single.html")
|
||||
touchFile(cfg.Fs.Source, createpath, "layouts", "index.html")
|
||||
touchFile(cfg.Fs.Source, createpath, "layouts", "404.html")
|
||||
touchFile(cfg.Fs.Source, createpath, "layouts", "_default", "list.html")
|
||||
touchFile(cfg.Fs.Source, createpath, "layouts", "_default", "single.html")
|
||||
|
||||
touchFile(createpath, "layouts", "partials", "header.html")
|
||||
touchFile(createpath, "layouts", "partials", "footer.html")
|
||||
touchFile(cfg.Fs.Source, createpath, "layouts", "partials", "header.html")
|
||||
touchFile(cfg.Fs.Source, createpath, "layouts", "partials", "footer.html")
|
||||
|
||||
mkdir(createpath, "archetypes")
|
||||
|
||||
archDefault := []byte("+++\n+++\n")
|
||||
|
||||
err := helpers.WriteToDisk(filepath.Join(createpath, "archetypes", "default.md"), bytes.NewReader(archDefault), hugofs.Source())
|
||||
err = helpers.WriteToDisk(filepath.Join(createpath, "archetypes", "default.md"), bytes.NewReader(archDefault), cfg.Fs.Source)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -256,12 +280,12 @@ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
`)
|
||||
|
||||
err = helpers.WriteToDisk(filepath.Join(createpath, "LICENSE.md"), bytes.NewReader(by), hugofs.Source())
|
||||
err = helpers.WriteToDisk(filepath.Join(createpath, "LICENSE.md"), bytes.NewReader(by), cfg.Fs.Source)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
createThemeMD(createpath)
|
||||
createThemeMD(cfg.Fs, createpath)
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -275,28 +299,28 @@ func mkdir(x ...string) {
|
||||
}
|
||||
}
|
||||
|
||||
func touchFile(x ...string) {
|
||||
func touchFile(fs afero.Fs, x ...string) {
|
||||
inpath := filepath.Join(x...)
|
||||
mkdir(filepath.Dir(inpath))
|
||||
err := helpers.WriteToDisk(inpath, bytes.NewReader([]byte{}), hugofs.Source())
|
||||
err := helpers.WriteToDisk(inpath, bytes.NewReader([]byte{}), fs)
|
||||
if err != nil {
|
||||
jww.FATAL.Fatalln(err)
|
||||
}
|
||||
}
|
||||
|
||||
func createThemeMD(inpath string) (err error) {
|
||||
func createThemeMD(fs *hugofs.Fs, inpath string) (err error) {
|
||||
|
||||
by := []byte(`# theme.toml template for a Hugo theme
|
||||
# See https://github.com/spf13/hugoThemes#themetoml for an example
|
||||
# See https://github.com/gohugoio/hugoThemes#themetoml for an example
|
||||
|
||||
name = "` + strings.Title(helpers.MakeTitle(filepath.Base(inpath))) + `"
|
||||
license = "MIT"
|
||||
licenselink = "https://github.com/yourname/yourtheme/blob/master/LICENSE.md"
|
||||
description = ""
|
||||
homepage = "http://siteforthistheme.com/"
|
||||
tags = ["", ""]
|
||||
features = ["", ""]
|
||||
min_version = 0.18
|
||||
tags = []
|
||||
features = []
|
||||
min_version = "0.23"
|
||||
|
||||
[author]
|
||||
name = ""
|
||||
@@ -309,7 +333,7 @@ min_version = 0.18
|
||||
repo = ""
|
||||
`)
|
||||
|
||||
err = helpers.WriteToDisk(filepath.Join(inpath, "theme.toml"), bytes.NewReader(by), hugofs.Source())
|
||||
err = helpers.WriteToDisk(filepath.Join(inpath, "theme.toml"), bytes.NewReader(by), fs.Source)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -320,7 +344,7 @@ min_version = 0.18
|
||||
func newContentPathSection(path string) (string, string) {
|
||||
// Forward slashes is used in all examples. Convert if needed.
|
||||
// Issue #1133
|
||||
createpath := strings.Replace(path, "/", helpers.FilePathSeparator, -1)
|
||||
createpath := filepath.FromSlash(path)
|
||||
var section string
|
||||
// assume the first directory is the section (kind)
|
||||
if strings.Contains(createpath[1:], helpers.FilePathSeparator) {
|
||||
@@ -330,23 +354,19 @@ func newContentPathSection(path string) (string, string) {
|
||||
return createpath, section
|
||||
}
|
||||
|
||||
func createConfig(inpath string, kind string) (err error) {
|
||||
in := map[string]interface{}{
|
||||
"baseurl": "http://example.org/",
|
||||
func createConfig(fs *hugofs.Fs, inpath string, kind string) (err error) {
|
||||
in := map[string]string{
|
||||
"baseURL": "http://example.org/",
|
||||
"title": "My New Hugo Site",
|
||||
"languageCode": "en-us",
|
||||
}
|
||||
kind = parser.FormatSanitize(kind)
|
||||
|
||||
by, err := parser.InterfaceToConfig(in, parser.FormatToLeadRune(kind))
|
||||
var buf bytes.Buffer
|
||||
err = parser.InterfaceToConfig(in, parser.FormatToLeadRune(kind), &buf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = helpers.WriteToDisk(filepath.Join(inpath, "config."+kind), bytes.NewReader(by), hugofs.Source())
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return nil
|
||||
return helpers.WriteToDisk(filepath.Join(inpath, "config."+kind), &buf, fs.Source)
|
||||
}
|
||||
|
||||
+58
-38
@@ -14,12 +14,13 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/spf13/hugo/hugofs"
|
||||
"github.com/gohugoio/hugo/hugofs"
|
||||
"github.com/spf13/viper"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// Issue #1133
|
||||
@@ -29,7 +30,8 @@ func TestNewContentPathSectionWithForwardSlashes(t *testing.T) {
|
||||
assert.Equal(t, "post", s)
|
||||
}
|
||||
|
||||
func checkNewSiteInited(basepath string, t *testing.T) {
|
||||
func checkNewSiteInited(fs *hugofs.Fs, basepath string, t *testing.T) {
|
||||
|
||||
paths := []string{
|
||||
filepath.Join(basepath, "layouts"),
|
||||
filepath.Join(basepath, "content"),
|
||||
@@ -40,63 +42,81 @@ func checkNewSiteInited(basepath string, t *testing.T) {
|
||||
}
|
||||
|
||||
for _, path := range paths {
|
||||
_, err := hugofs.Source().Stat(path)
|
||||
assert.Nil(t, err)
|
||||
_, err := fs.Source.Stat(path)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDoNewSite(t *testing.T) {
|
||||
basepath := filepath.Join(os.TempDir(), "blog")
|
||||
hugofs.InitMemFs()
|
||||
err := doNewSite(basepath, false)
|
||||
assert.Nil(t, err)
|
||||
basepath := filepath.Join("base", "blog")
|
||||
_, fs := newTestCfg()
|
||||
|
||||
checkNewSiteInited(basepath, t)
|
||||
require.NoError(t, doNewSite(fs, basepath, false))
|
||||
|
||||
checkNewSiteInited(fs, basepath, t)
|
||||
}
|
||||
|
||||
func TestDoNewSite_noerror_base_exists_but_empty(t *testing.T) {
|
||||
basepath := filepath.Join(os.TempDir(), "blog")
|
||||
hugofs.InitMemFs()
|
||||
hugofs.Source().MkdirAll(basepath, 777)
|
||||
err := doNewSite(basepath, false)
|
||||
assert.Nil(t, err)
|
||||
basepath := filepath.Join("base", "blog")
|
||||
_, fs := newTestCfg()
|
||||
|
||||
require.NoError(t, fs.Source.MkdirAll(basepath, 777))
|
||||
|
||||
require.NoError(t, doNewSite(fs, basepath, false))
|
||||
}
|
||||
|
||||
func TestDoNewSite_error_base_exists(t *testing.T) {
|
||||
basepath := filepath.Join(os.TempDir(), "blog")
|
||||
hugofs.InitMemFs()
|
||||
hugofs.Source().MkdirAll(basepath, 777)
|
||||
hugofs.Source().Create(filepath.Join(basepath, "foo"))
|
||||
basepath := filepath.Join("base", "blog")
|
||||
_, fs := newTestCfg()
|
||||
|
||||
require.NoError(t, fs.Source.MkdirAll(basepath, 777))
|
||||
_, err := fs.Source.Create(filepath.Join(basepath, "foo"))
|
||||
require.NoError(t, err)
|
||||
// Since the directory already exists and isn't empty, expect an error
|
||||
err := doNewSite(basepath, false)
|
||||
assert.NotNil(t, err)
|
||||
require.Error(t, doNewSite(fs, basepath, false))
|
||||
|
||||
}
|
||||
|
||||
func TestDoNewSite_force_empty_dir(t *testing.T) {
|
||||
basepath := filepath.Join(os.TempDir(), "blog")
|
||||
hugofs.InitMemFs()
|
||||
hugofs.Source().MkdirAll(basepath, 777)
|
||||
err := doNewSite(basepath, true)
|
||||
assert.Nil(t, err)
|
||||
basepath := filepath.Join("base", "blog")
|
||||
_, fs := newTestCfg()
|
||||
|
||||
checkNewSiteInited(basepath, t)
|
||||
require.NoError(t, fs.Source.MkdirAll(basepath, 777))
|
||||
|
||||
require.NoError(t, doNewSite(fs, basepath, true))
|
||||
|
||||
checkNewSiteInited(fs, basepath, t)
|
||||
}
|
||||
|
||||
func TestDoNewSite_error_force_dir_inside_exists(t *testing.T) {
|
||||
basepath := filepath.Join(os.TempDir(), "blog")
|
||||
basepath := filepath.Join("base", "blog")
|
||||
_, fs := newTestCfg()
|
||||
|
||||
contentPath := filepath.Join(basepath, "content")
|
||||
hugofs.InitMemFs()
|
||||
hugofs.Source().MkdirAll(contentPath, 777)
|
||||
err := doNewSite(basepath, true)
|
||||
assert.NotNil(t, err)
|
||||
|
||||
require.NoError(t, fs.Source.MkdirAll(contentPath, 777))
|
||||
require.Error(t, doNewSite(fs, basepath, true))
|
||||
}
|
||||
|
||||
func TestDoNewSite_error_force_config_inside_exists(t *testing.T) {
|
||||
basepath := filepath.Join(os.TempDir(), "blog")
|
||||
basepath := filepath.Join("base", "blog")
|
||||
_, fs := newTestCfg()
|
||||
|
||||
configPath := filepath.Join(basepath, "config.toml")
|
||||
hugofs.InitMemFs()
|
||||
hugofs.Source().MkdirAll(basepath, 777)
|
||||
hugofs.Source().Create(configPath)
|
||||
err := doNewSite(basepath, true)
|
||||
assert.NotNil(t, err)
|
||||
require.NoError(t, fs.Source.MkdirAll(basepath, 777))
|
||||
_, err := fs.Source.Create(configPath)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Error(t, doNewSite(fs, basepath, true))
|
||||
}
|
||||
|
||||
func newTestCfg() (*viper.Viper, *hugofs.Fs) {
|
||||
|
||||
v := viper.New()
|
||||
fs := hugofs.NewMem(v)
|
||||
|
||||
v.SetFs(fs.Source)
|
||||
|
||||
return v, fs
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
// +build release
|
||||
|
||||
// Copyright 2017-present The Hugo Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package commands
|
||||
|
||||
import (
|
||||
"github.com/gohugoio/hugo/releaser"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func init() {
|
||||
HugoCmd.AddCommand(createReleaser().cmd)
|
||||
}
|
||||
|
||||
type releaseCommandeer struct {
|
||||
cmd *cobra.Command
|
||||
|
||||
// Will be zero for main releases.
|
||||
patchLevel int
|
||||
|
||||
skipPublish bool
|
||||
|
||||
step int
|
||||
}
|
||||
|
||||
func createReleaser() *releaseCommandeer {
|
||||
// Note: This is a command only meant for internal use and must be run
|
||||
// via "go run -tags release main.go release" on the actual code base that is in the release.
|
||||
r := &releaseCommandeer{
|
||||
cmd: &cobra.Command{
|
||||
Use: "release",
|
||||
Short: "Release a new version of Hugo.",
|
||||
Hidden: true,
|
||||
},
|
||||
}
|
||||
|
||||
r.cmd.RunE = func(cmd *cobra.Command, args []string) error {
|
||||
return r.release()
|
||||
}
|
||||
|
||||
r.cmd.PersistentFlags().IntVarP(&r.patchLevel, "patch", "p", 0, "patch level, defaults to 0 for main releases")
|
||||
r.cmd.PersistentFlags().IntVarP(&r.step, "step", "s", -1, "release step, defaults to -1 for all steps.")
|
||||
r.cmd.PersistentFlags().BoolVarP(&r.skipPublish, "skip-publish", "", false, "skip all publishing pipes of the release")
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *releaseCommandeer) release() error {
|
||||
return releaser.New(r.patchLevel, r.step, r.skipPublish).Run()
|
||||
}
|
||||
+36
-34
@@ -24,14 +24,11 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"mime"
|
||||
|
||||
"github.com/gohugoio/hugo/config"
|
||||
"github.com/gohugoio/hugo/helpers"
|
||||
"github.com/spf13/afero"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/hugo/helpers"
|
||||
"github.com/spf13/hugo/hugofs"
|
||||
jww "github.com/spf13/jwalterweatherman"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -43,8 +40,6 @@ var (
|
||||
serverWatch bool
|
||||
)
|
||||
|
||||
//var serverCmdV *cobra.Command
|
||||
|
||||
var serverCmd = &cobra.Command{
|
||||
Use: "server",
|
||||
Aliases: []string{"serve"},
|
||||
@@ -98,34 +93,37 @@ func init() {
|
||||
|
||||
serverCmd.RunE = server
|
||||
|
||||
mime.AddExtensionType(".json", "application/json; charset=utf-8")
|
||||
mime.AddExtensionType(".css", "text/css; charset=utf-8")
|
||||
|
||||
}
|
||||
|
||||
func server(cmd *cobra.Command, args []string) error {
|
||||
if err := InitializeConfig(serverCmd); err != nil {
|
||||
cfg, err := InitializeConfig(serverCmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if flagChanged(cmd.Flags(), "disableLiveReload") {
|
||||
viper.Set("disableLiveReload", disableLiveReload)
|
||||
c, err := newCommandeer(cfg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if cmd.Flags().Changed("disableLiveReload") {
|
||||
c.Set("disableLiveReload", disableLiveReload)
|
||||
}
|
||||
|
||||
if serverWatch {
|
||||
viper.Set("watch", true)
|
||||
c.Set("watch", true)
|
||||
}
|
||||
|
||||
if viper.GetBool("watch") {
|
||||
if c.Cfg.GetBool("watch") {
|
||||
serverWatch = true
|
||||
watchConfig()
|
||||
c.watchConfig()
|
||||
}
|
||||
|
||||
l, err := net.Listen("tcp", net.JoinHostPort(serverInterface, strconv.Itoa(serverPort)))
|
||||
if err == nil {
|
||||
l.Close()
|
||||
} else {
|
||||
if flagChanged(serverCmd.Flags(), "port") {
|
||||
if serverCmd.Flags().Changed("port") {
|
||||
// port set explicitly by user -- he/she probably meant it!
|
||||
return newSystemErrorF("Server startup failed: %s", err)
|
||||
}
|
||||
@@ -137,13 +135,13 @@ func server(cmd *cobra.Command, args []string) error {
|
||||
serverPort = sp.Port
|
||||
}
|
||||
|
||||
viper.Set("port", serverPort)
|
||||
c.Set("port", serverPort)
|
||||
|
||||
baseURL, err = fixURL(baseURL)
|
||||
baseURL, err = fixURL(c.Cfg, baseURL)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
viper.Set("baseURL", baseURL)
|
||||
c.Set("baseURL", baseURL)
|
||||
|
||||
if err := memStats(); err != nil {
|
||||
jww.ERROR.Println("memstats error:", err)
|
||||
@@ -156,19 +154,23 @@ func server(cmd *cobra.Command, args []string) error {
|
||||
|
||||
// Hugo writes the output to memory instead of the disk
|
||||
if !renderToDisk {
|
||||
hugofs.SetDestination(new(afero.MemMapFs))
|
||||
cfg.Fs.Destination = new(afero.MemMapFs)
|
||||
// Rendering to memoryFS, publish to Root regardless of publishDir.
|
||||
viper.Set("publishDir", "/")
|
||||
c.Set("publishDir", "/")
|
||||
}
|
||||
|
||||
if err := build(serverWatch); err != nil {
|
||||
if err := c.build(serverWatch); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, s := range Hugo.Sites {
|
||||
s.RegisterMediaTypes()
|
||||
}
|
||||
|
||||
// Watch runs its own server as part of the routine
|
||||
if serverWatch {
|
||||
watchDirs := getDirList()
|
||||
baseWatchDir := viper.GetString("workingDir")
|
||||
watchDirs := c.getDirList()
|
||||
baseWatchDir := c.Cfg.GetString("workingDir")
|
||||
for i, dir := range watchDirs {
|
||||
watchDirs[i], _ = helpers.GetRelativePath(dir, baseWatchDir)
|
||||
}
|
||||
@@ -176,31 +178,31 @@ func server(cmd *cobra.Command, args []string) error {
|
||||
rootWatchDirs := strings.Join(helpers.UniqueStrings(helpers.ExtractRootPaths(watchDirs)), ",")
|
||||
|
||||
jww.FEEDBACK.Printf("Watching for changes in %s%s{%s}\n", baseWatchDir, helpers.FilePathSeparator, rootWatchDirs)
|
||||
err := NewWatcher(serverPort)
|
||||
err := c.newWatcher(serverPort)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
serve(serverPort)
|
||||
c.serve(serverPort)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func serve(port int) {
|
||||
func (c *commandeer) serve(port int) {
|
||||
if renderToDisk {
|
||||
jww.FEEDBACK.Println("Serving pages from " + helpers.AbsPathify(viper.GetString("publishDir")))
|
||||
jww.FEEDBACK.Println("Serving pages from " + c.PathSpec().AbsPathify(c.Cfg.GetString("publishDir")))
|
||||
} else {
|
||||
jww.FEEDBACK.Println("Serving pages from memory")
|
||||
}
|
||||
|
||||
httpFs := afero.NewHttpFs(hugofs.Destination())
|
||||
fs := filesOnlyFs{httpFs.Dir(helpers.AbsPathify(viper.GetString("publishDir")))}
|
||||
httpFs := afero.NewHttpFs(c.Fs.Destination)
|
||||
fs := filesOnlyFs{httpFs.Dir(c.PathSpec().AbsPathify(c.Cfg.GetString("publishDir")))}
|
||||
fileserver := http.FileServer(fs)
|
||||
|
||||
// We're only interested in the path
|
||||
u, err := url.Parse(viper.GetString("baseURL"))
|
||||
u, err := url.Parse(c.Cfg.GetString("baseURL"))
|
||||
if err != nil {
|
||||
jww.ERROR.Fatalf("Invalid baseURL: %s", err)
|
||||
}
|
||||
@@ -223,10 +225,10 @@ func serve(port int) {
|
||||
|
||||
// fixURL massages the baseURL into a form needed for serving
|
||||
// all pages correctly.
|
||||
func fixURL(s string) (string, error) {
|
||||
func fixURL(cfg config.Provider, s string) (string, error) {
|
||||
useLocalhost := false
|
||||
if s == "" {
|
||||
s = viper.GetString("baseURL")
|
||||
s = cfg.GetString("baseURL")
|
||||
useLocalhost = true
|
||||
}
|
||||
|
||||
|
||||
@@ -20,8 +20,6 @@ import (
|
||||
)
|
||||
|
||||
func TestFixURL(t *testing.T) {
|
||||
defer viper.Reset()
|
||||
|
||||
type data struct {
|
||||
TestName string
|
||||
CLIBaseURL string
|
||||
@@ -44,12 +42,12 @@ func TestFixURL(t *testing.T) {
|
||||
}
|
||||
|
||||
for i, test := range tests {
|
||||
viper.Reset()
|
||||
v := viper.New()
|
||||
baseURL = test.CLIBaseURL
|
||||
viper.Set("baseURL", test.CfgBaseURL)
|
||||
v.Set("baseURL", test.CfgBaseURL)
|
||||
serverAppend = test.AppendPort
|
||||
serverPort = test.Port
|
||||
result, err := fixURL(baseURL)
|
||||
result, err := fixURL(v, baseURL)
|
||||
if err != nil {
|
||||
t.Errorf("Test #%d %s: unexpected error %s", i, test.TestName, err)
|
||||
}
|
||||
|
||||
+6
-5
@@ -19,9 +19,8 @@ import (
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/gohugoio/hugo/parser"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/hugo/hugofs"
|
||||
"github.com/spf13/hugo/parser"
|
||||
)
|
||||
|
||||
var undraftCmd = &cobra.Command{
|
||||
@@ -37,7 +36,9 @@ If the content's draft status is 'False', nothing is done.`,
|
||||
// to false and setting its publish date to now. If the specified content is
|
||||
// not a draft, it will log an error.
|
||||
func Undraft(cmd *cobra.Command, args []string) error {
|
||||
if err := InitializeConfig(); err != nil {
|
||||
cfg, err := InitializeConfig()
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -47,7 +48,7 @@ func Undraft(cmd *cobra.Command, args []string) error {
|
||||
|
||||
location := args[0]
|
||||
// open the file
|
||||
f, err := hugofs.Source().Open(location)
|
||||
f, err := cfg.Fs.Source.Open(location)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -64,7 +65,7 @@ func Undraft(cmd *cobra.Command, args []string) error {
|
||||
return newSystemErrorF("an error occurred while undrafting %q: %s", location, err)
|
||||
}
|
||||
|
||||
f, err = hugofs.Source().OpenFile(location, os.O_WRONLY|os.O_TRUNC, 0644)
|
||||
f, err = cfg.Fs.Source.OpenFile(location, os.O_WRONLY|os.O_TRUNC, 0644)
|
||||
if err != nil {
|
||||
return newSystemErrorF("%q not be undrafted due to error opening file to save changes: %q\n", location, err)
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/hugo/parser"
|
||||
"github.com/gohugoio/hugo/parser"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -46,17 +46,17 @@ func TestUndraftContent(t *testing.T) {
|
||||
{yamlDraftFM, ""},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
for i, test := range tests {
|
||||
r := bytes.NewReader([]byte(test.fm))
|
||||
p, _ := parser.ReadFrom(r)
|
||||
res, err := undraftContent(p)
|
||||
if test.expectedErr != "" {
|
||||
if err == nil {
|
||||
t.Error("Expected error, got none")
|
||||
t.Errorf("[%d] Expected error, got none", i)
|
||||
continue
|
||||
}
|
||||
if err.Error() != test.expectedErr {
|
||||
t.Errorf("Expected %q, got %q", test.expectedErr, err)
|
||||
t.Errorf("[%d] Expected %q, got %q", i, test.expectedErr, err)
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
@@ -64,19 +64,19 @@ func TestUndraftContent(t *testing.T) {
|
||||
p, _ = parser.ReadFrom(r)
|
||||
meta, err := p.Metadata()
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error %q", err)
|
||||
t.Errorf("[%d] unexpected error %q", i, err)
|
||||
continue
|
||||
}
|
||||
for k, v := range meta.(map[string]interface{}) {
|
||||
if k == "draft" {
|
||||
if v.(bool) {
|
||||
t.Errorf("Expected %q to be \"false\", got \"true\"", k)
|
||||
t.Errorf("[%d] Expected %q to be \"false\", got \"true\"", i, k)
|
||||
continue
|
||||
}
|
||||
}
|
||||
if k == "date" {
|
||||
if !strings.HasPrefix(v.(string), time.Now().Format("2006-01-02")) {
|
||||
t.Errorf("Expected %v to start with %v", v.(string), time.Now().Format("2006-01-02"))
|
||||
t.Errorf("[%d] Expected %v to start with %v", i, v.(string), time.Now().Format("2006-01-02"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+5
-4
@@ -16,13 +16,14 @@ package commands
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gohugoio/hugo/helpers"
|
||||
"github.com/gohugoio/hugo/hugolib"
|
||||
"github.com/kardianos/osext"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/hugo/helpers"
|
||||
"github.com/spf13/hugo/hugolib"
|
||||
jww "github.com/spf13/jwalterweatherman"
|
||||
)
|
||||
|
||||
@@ -43,9 +44,9 @@ func printHugoVersion() {
|
||||
formatBuildDate() // format the compile time
|
||||
}
|
||||
if hugolib.CommitHash == "" {
|
||||
jww.FEEDBACK.Printf("Hugo Static Site Generator v%s BuildDate: %s\n", helpers.HugoVersion(), hugolib.BuildDate)
|
||||
jww.FEEDBACK.Printf("Hugo Static Site Generator v%s %s/%s BuildDate: %s\n", helpers.CurrentHugoVersion, runtime.GOOS, runtime.GOARCH, hugolib.BuildDate)
|
||||
} else {
|
||||
jww.FEEDBACK.Printf("Hugo Static Site Generator v%s-%s BuildDate: %s\n", helpers.HugoVersion(), strings.ToUpper(hugolib.CommitHash), hugolib.BuildDate)
|
||||
jww.FEEDBACK.Printf("Hugo Static Site Generator v%s-%s %s/%s BuildDate: %s\n", helpers.CurrentHugoVersion, strings.ToUpper(hugolib.CommitHash), runtime.GOOS, runtime.GOARCH, hugolib.BuildDate)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
// Copyright 2017-present The Hugo Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package config
|
||||
|
||||
// Provider provides the configuration settings for Hugo.
|
||||
type Provider interface {
|
||||
GetString(key string) string
|
||||
GetInt(key string) int
|
||||
GetBool(key string) bool
|
||||
GetStringMap(key string) map[string]interface{}
|
||||
GetStringMapString(key string) map[string]string
|
||||
Get(key string) interface{}
|
||||
Set(key string, value interface{})
|
||||
IsSet(key string) bool
|
||||
}
|
||||
+23
-29
@@ -18,31 +18,29 @@ import (
|
||||
"bytes"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gohugoio/hugo/helpers"
|
||||
"github.com/gohugoio/hugo/hugolib"
|
||||
"github.com/gohugoio/hugo/parser"
|
||||
"github.com/spf13/afero"
|
||||
"github.com/spf13/cast"
|
||||
"github.com/spf13/hugo/helpers"
|
||||
"github.com/spf13/hugo/hugolib"
|
||||
"github.com/spf13/hugo/parser"
|
||||
jww "github.com/spf13/jwalterweatherman"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
// NewContent creates a new content file in the content directory based upon the
|
||||
// given kind, which is used to lookup an archetype.
|
||||
func NewContent(fs afero.Fs, kind, name string) (err error) {
|
||||
func NewContent(s *hugolib.Site, kind, name string) (err error) {
|
||||
jww.INFO.Println("attempting to create ", name, "of", kind)
|
||||
|
||||
location := FindArchetype(fs, kind)
|
||||
location := FindArchetype(s, kind)
|
||||
|
||||
var by []byte
|
||||
|
||||
if location != "" {
|
||||
by, err = afero.ReadFile(fs, location)
|
||||
by, err = afero.ReadFile(s.Fs.Source, location)
|
||||
if err != nil {
|
||||
jww.ERROR.Println(err)
|
||||
}
|
||||
@@ -62,28 +60,29 @@ func NewContent(fs afero.Fs, kind, name string) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
page, err := hugolib.NewPage(name)
|
||||
page, err := s.NewPage(name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = page.SetSourceMetaData(metadata, parser.FormatToLeadRune(viper.GetString("metaDataFormat"))); err != nil {
|
||||
if err = page.SetSourceMetaData(metadata, parser.FormatToLeadRune(s.Cfg.GetString("metaDataFormat"))); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
page.SetSourceContent(psr.Content())
|
||||
|
||||
if err = page.SafeSaveSourceAs(filepath.Join(viper.GetString("contentDir"), name)); err != nil {
|
||||
contentPath := s.PathSpec.AbsPathify(filepath.Join(s.Cfg.GetString("contentDir"), name))
|
||||
|
||||
if err = page.SafeSaveSourceAs(contentPath); err != nil {
|
||||
return
|
||||
}
|
||||
jww.FEEDBACK.Println(helpers.AbsPathify(filepath.Join(viper.GetString("contentDir"), name)), "created")
|
||||
|
||||
editor := viper.GetString("newContentEditor")
|
||||
jww.FEEDBACK.Println(contentPath, "created")
|
||||
|
||||
editor := s.Cfg.GetString("newContentEditor")
|
||||
if editor != "" {
|
||||
jww.FEEDBACK.Printf("Editing %s with %q ...\n", name, editor)
|
||||
|
||||
cmd := exec.Command(editor, helpers.AbsPathify(path.Join(viper.GetString("contentDir"), name)))
|
||||
cmd := exec.Command(editor, contentPath)
|
||||
cmd.Stdin = os.Stdin
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
@@ -138,12 +137,7 @@ func createMetadata(archetype parser.Page, name string) (map[string]interface{},
|
||||
metadata["title"] = helpers.MakeTitle(helpers.Filename(name))
|
||||
}
|
||||
|
||||
// TOD(bep) what is this?
|
||||
if x := parser.FormatSanitize(viper.GetString("metaDataFormat")); x == "json" || x == "yaml" || x == "toml" {
|
||||
metadata["date"] = date.Format(time.RFC3339)
|
||||
} else {
|
||||
metadata["date"] = date
|
||||
}
|
||||
metadata["date"] = date.Format(time.RFC3339)
|
||||
|
||||
return metadata, nil
|
||||
}
|
||||
@@ -151,13 +145,13 @@ func createMetadata(archetype parser.Page, name string) (map[string]interface{},
|
||||
// FindArchetype takes a given kind/archetype of content and returns an output
|
||||
// path for that archetype. If no archetype is found, an empty string is
|
||||
// returned.
|
||||
func FindArchetype(fs afero.Fs, kind string) (outpath string) {
|
||||
search := []string{helpers.AbsPathify(viper.GetString("archetypeDir"))}
|
||||
func FindArchetype(s *hugolib.Site, kind string) (outpath string) {
|
||||
search := []string{s.PathSpec.AbsPathify(s.Cfg.GetString("archetypeDir"))}
|
||||
|
||||
if viper.GetString("theme") != "" {
|
||||
themeDir := filepath.Join(helpers.AbsPathify(viper.GetString("themesDir")+"/"+viper.GetString("theme")), "/archetypes/")
|
||||
if _, err := fs.Stat(themeDir); os.IsNotExist(err) {
|
||||
jww.ERROR.Printf("Unable to find archetypes directory for theme %q at %q", viper.GetString("theme"), themeDir)
|
||||
if s.Cfg.GetString("theme") != "" {
|
||||
themeDir := filepath.Join(s.PathSpec.AbsPathify(s.Cfg.GetString("themesDir")+"/"+s.Cfg.GetString("theme")), "/archetypes/")
|
||||
if _, err := s.Fs.Source.Stat(themeDir); os.IsNotExist(err) {
|
||||
jww.ERROR.Printf("Unable to find archetypes directory for theme %q at %q", s.Cfg.GetString("theme"), themeDir)
|
||||
} else {
|
||||
search = append(search, themeDir)
|
||||
}
|
||||
@@ -166,7 +160,7 @@ func FindArchetype(fs afero.Fs, kind string) (outpath string) {
|
||||
for _, x := range search {
|
||||
// If the new content isn't in a subdirectory, kind == "".
|
||||
// Therefore it should be excluded otherwise `is a directory`
|
||||
// error will occur. github.com/spf13/hugo/issues/411
|
||||
// error will occur. github.com/gohugoio/hugo/issues/411
|
||||
var pathsToCheck []string
|
||||
|
||||
if kind == "" {
|
||||
@@ -177,7 +171,7 @@ func FindArchetype(fs afero.Fs, kind string) (outpath string) {
|
||||
for _, p := range pathsToCheck {
|
||||
curpath := filepath.Join(x, p)
|
||||
jww.DEBUG.Println("checking", curpath, "for archetypes")
|
||||
if exists, _ := helpers.Exists(curpath, fs); exists {
|
||||
if exists, _ := helpers.Exists(curpath, s.Fs.Source); exists {
|
||||
jww.INFO.Println("curpath: " + curpath)
|
||||
return curpath
|
||||
}
|
||||
|
||||
+45
-27
@@ -19,22 +19,24 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/gohugoio/hugo/deps"
|
||||
|
||||
"github.com/gohugoio/hugo/hugolib"
|
||||
|
||||
"fmt"
|
||||
|
||||
"github.com/gohugoio/hugo/hugofs"
|
||||
|
||||
"github.com/gohugoio/hugo/create"
|
||||
"github.com/gohugoio/hugo/helpers"
|
||||
"github.com/spf13/afero"
|
||||
"github.com/spf13/hugo/create"
|
||||
"github.com/spf13/hugo/helpers"
|
||||
"github.com/spf13/hugo/hugofs"
|
||||
"github.com/spf13/viper"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestNewContent(t *testing.T) {
|
||||
initViper()
|
||||
|
||||
err := initFs()
|
||||
if err != nil {
|
||||
t.Fatalf("initialization error: %s", err)
|
||||
}
|
||||
v := viper.New()
|
||||
initViper(v)
|
||||
|
||||
cases := []struct {
|
||||
kind string
|
||||
@@ -48,15 +50,18 @@ func TestNewContent(t *testing.T) {
|
||||
{"product", "product/sample-4.md", []string{`title = "sample 4"`}}, // empty archetype front matter
|
||||
}
|
||||
|
||||
for i, c := range cases {
|
||||
err = create.NewContent(hugofs.Source(), c.kind, c.path)
|
||||
if err != nil {
|
||||
t.Errorf("[%d] NewContent: %s", i, err)
|
||||
}
|
||||
for _, c := range cases {
|
||||
cfg, fs := newTestCfg()
|
||||
h, err := hugolib.NewHugoSites(deps.DepsCfg{Cfg: cfg, Fs: fs})
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, initFs(fs))
|
||||
|
||||
s := h.Sites[0]
|
||||
|
||||
require.NoError(t, create.NewContent(s, c.kind, c.path))
|
||||
|
||||
fname := filepath.Join("content", filepath.FromSlash(c.path))
|
||||
content := readFileFromFs(t, hugofs.Source(), fname)
|
||||
|
||||
content := readFileFromFs(t, fs.Source, fname)
|
||||
for i, v := range c.expected {
|
||||
found := strings.Contains(content, v)
|
||||
if !found {
|
||||
@@ -66,17 +71,17 @@ func TestNewContent(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func initViper() {
|
||||
viper.Reset()
|
||||
viper.Set("metaDataFormat", "toml")
|
||||
viper.Set("archetypeDir", "archetypes")
|
||||
viper.Set("contentDir", "content")
|
||||
viper.Set("themesDir", "themes")
|
||||
viper.Set("theme", "sample")
|
||||
func initViper(v *viper.Viper) {
|
||||
v.Set("metaDataFormat", "toml")
|
||||
v.Set("archetypeDir", "archetypes")
|
||||
v.Set("contentDir", "content")
|
||||
v.Set("themesDir", "themes")
|
||||
v.Set("layoutDir", "layouts")
|
||||
v.Set("i18nDir", "i18n")
|
||||
v.Set("theme", "sample")
|
||||
}
|
||||
|
||||
func initFs() error {
|
||||
hugofs.InitMemFs()
|
||||
func initFs(fs *hugofs.Fs) error {
|
||||
perm := os.FileMode(0755)
|
||||
var err error
|
||||
|
||||
@@ -87,7 +92,7 @@ func initFs() error {
|
||||
filepath.Join("themes", "sample", "archetypes"),
|
||||
}
|
||||
for _, dir := range dirs {
|
||||
err = hugofs.Source().Mkdir(dir, perm)
|
||||
err = fs.Source.Mkdir(dir, perm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -111,7 +116,7 @@ func initFs() error {
|
||||
content: "+++\ndate =\"\"\ntitle = \"Empty Date Arch title\"\ntest = \"test1\"\n+++\n",
|
||||
},
|
||||
} {
|
||||
f, err := hugofs.Source().Create(v.path)
|
||||
f, err := fs.Source.Create(v.path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -144,3 +149,16 @@ func readFileFromFs(t *testing.T, fs afero.Fs, filename string) string {
|
||||
}
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func newTestCfg() (*viper.Viper, *hugofs.Fs) {
|
||||
|
||||
v := viper.New()
|
||||
fs := hugofs.NewMem(v)
|
||||
|
||||
v.SetFs(fs.Source)
|
||||
|
||||
initViper(v)
|
||||
|
||||
return v, fs
|
||||
|
||||
}
|
||||
|
||||
Vendored
+176
@@ -0,0 +1,176 @@
|
||||
package deps
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/gohugoio/hugo/config"
|
||||
"github.com/gohugoio/hugo/helpers"
|
||||
"github.com/gohugoio/hugo/hugofs"
|
||||
"github.com/gohugoio/hugo/output"
|
||||
"github.com/gohugoio/hugo/tpl"
|
||||
jww "github.com/spf13/jwalterweatherman"
|
||||
)
|
||||
|
||||
// Deps holds dependencies used by many.
|
||||
// There will be normally be only one instance of deps in play
|
||||
// at a given time, i.e. one per Site built.
|
||||
type Deps struct {
|
||||
// The logger to use.
|
||||
Log *jww.Notepad `json:"-"`
|
||||
|
||||
// The templates to use. This will usually implement the full tpl.TemplateHandler.
|
||||
Tmpl tpl.TemplateFinder `json:"-"`
|
||||
|
||||
// The file systems to use.
|
||||
Fs *hugofs.Fs `json:"-"`
|
||||
|
||||
// The PathSpec to use
|
||||
*helpers.PathSpec `json:"-"`
|
||||
|
||||
// The ContentSpec to use
|
||||
*helpers.ContentSpec `json:"-"`
|
||||
|
||||
// The configuration to use
|
||||
Cfg config.Provider `json:"-"`
|
||||
|
||||
// The translation func to use
|
||||
Translate func(translationID string, args ...interface{}) string `json:"-"`
|
||||
|
||||
Language *helpers.Language
|
||||
|
||||
// All the output formats available for the current site.
|
||||
OutputFormatsConfig output.Formats
|
||||
|
||||
templateProvider ResourceProvider
|
||||
WithTemplate func(templ tpl.TemplateHandler) error `json:"-"`
|
||||
|
||||
translationProvider ResourceProvider
|
||||
}
|
||||
|
||||
// ResourceProvider is used to create and refresh, and clone resources needed.
|
||||
type ResourceProvider interface {
|
||||
Update(deps *Deps) error
|
||||
Clone(deps *Deps) error
|
||||
}
|
||||
|
||||
func (d *Deps) TemplateHandler() tpl.TemplateHandler {
|
||||
return d.Tmpl.(tpl.TemplateHandler)
|
||||
}
|
||||
|
||||
func (d *Deps) LoadResources() error {
|
||||
// Note that the translations need to be loaded before the templates.
|
||||
if err := d.translationProvider.Update(d); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := d.templateProvider.Update(d); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if th, ok := d.Tmpl.(tpl.TemplateHandler); ok {
|
||||
th.PrintErrors()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func New(cfg DepsCfg) (*Deps, error) {
|
||||
var (
|
||||
logger = cfg.Logger
|
||||
fs = cfg.Fs
|
||||
)
|
||||
|
||||
if cfg.TemplateProvider == nil {
|
||||
panic("Must have a TemplateProvider")
|
||||
}
|
||||
|
||||
if cfg.TranslationProvider == nil {
|
||||
panic("Must have a TranslationProvider")
|
||||
}
|
||||
|
||||
if cfg.Language == nil {
|
||||
panic("Must have a Language")
|
||||
}
|
||||
|
||||
if logger == nil {
|
||||
logger = jww.NewNotepad(jww.LevelError, jww.LevelError, os.Stdout, ioutil.Discard, "", log.Ldate|log.Ltime)
|
||||
}
|
||||
|
||||
if fs == nil {
|
||||
// Default to the production file system.
|
||||
fs = hugofs.NewDefault(cfg.Language)
|
||||
}
|
||||
|
||||
ps, err := helpers.NewPathSpec(fs, cfg.Language)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
d := &Deps{
|
||||
Fs: fs,
|
||||
Log: logger,
|
||||
templateProvider: cfg.TemplateProvider,
|
||||
translationProvider: cfg.TranslationProvider,
|
||||
WithTemplate: cfg.WithTemplate,
|
||||
PathSpec: ps,
|
||||
ContentSpec: helpers.NewContentSpec(cfg.Language),
|
||||
Cfg: cfg.Language,
|
||||
Language: cfg.Language,
|
||||
}
|
||||
|
||||
return d, nil
|
||||
}
|
||||
|
||||
// ForLanguage creates a copy of the Deps with the language dependent
|
||||
// parts switched out.
|
||||
func (d Deps) ForLanguage(l *helpers.Language) (*Deps, error) {
|
||||
var err error
|
||||
|
||||
d.PathSpec, err = helpers.NewPathSpec(d.Fs, l)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
d.ContentSpec = helpers.NewContentSpec(l)
|
||||
d.Cfg = l
|
||||
d.Language = l
|
||||
|
||||
if err := d.translationProvider.Clone(&d); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := d.templateProvider.Clone(&d); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &d, nil
|
||||
|
||||
}
|
||||
|
||||
// DepsCfg contains configuration options that can be used to configure Hugo
|
||||
// on a global level, i.e. logging etc.
|
||||
// Nil values will be given default values.
|
||||
type DepsCfg struct {
|
||||
|
||||
// The Logger to use.
|
||||
Logger *jww.Notepad
|
||||
|
||||
// The file systems to use
|
||||
Fs *hugofs.Fs
|
||||
|
||||
// The language to use.
|
||||
Language *helpers.Language
|
||||
|
||||
// The configuration to use.
|
||||
Cfg config.Provider
|
||||
|
||||
// Template handling.
|
||||
TemplateProvider ResourceProvider
|
||||
WithTemplate func(templ tpl.TemplateHandler) error
|
||||
|
||||
// i18n handling.
|
||||
TranslationProvider ResourceProvider
|
||||
}
|
||||
Submodule
+1
Submodule docs added at d9fb81b49d
@@ -1 +0,0 @@
|
||||
/.idea
|
||||
@@ -1,6 +0,0 @@
|
||||
+++
|
||||
weight = 5
|
||||
[menu]
|
||||
[menu.main]
|
||||
parent = "x"
|
||||
+++
|
||||
@@ -1,14 +0,0 @@
|
||||
---
|
||||
date: 2013-07-01T07:32:00Z
|
||||
description: ""
|
||||
license: ""
|
||||
licenseLink: ""
|
||||
sitelink: http://spf13.com/
|
||||
sourceLink: https://github.com/spf13/spf13.com
|
||||
tags:
|
||||
- personal
|
||||
- blog
|
||||
thumbnail: /img/spf13-tn.jpg
|
||||
title: spf13.com
|
||||
---
|
||||
|
||||
@@ -1,113 +0,0 @@
|
||||
title = "Hugo: A Fast and Flexible Website Generator"
|
||||
baseurl = "http://gohugo.io/"
|
||||
MetaDataFormat = "yaml"
|
||||
pluralizeListTitles = false
|
||||
enableGitInfo = true
|
||||
|
||||
[blackfriday]
|
||||
plainIDAnchors = true
|
||||
|
||||
[params]
|
||||
description = "Documentation of Hugo, a fast and flexible static site generator built with love by spf13, bep and friends in Go"
|
||||
author = "Steve Francia (spf13) and friends"
|
||||
|
||||
[taxonomies]
|
||||
tag = "tags"
|
||||
group = "groups"
|
||||
|
||||
[[menu.main]]
|
||||
name = "Download Hugo"
|
||||
pre = "<i class='fa fa-download'></i>"
|
||||
url = "https://github.com/spf13/hugo/releases"
|
||||
weight = -200
|
||||
[[menu.main]]
|
||||
name = "Site Showcase"
|
||||
pre = "<i class='fa fa-cubes'></i>"
|
||||
url = "/showcase/"
|
||||
weight = -180
|
||||
[[menu.main]]
|
||||
name = "Theme Showcase"
|
||||
pre = "<i class='fa fa-puzzle-piece'></i>"
|
||||
url = "http://themes.gohugo.io"
|
||||
weight = -170
|
||||
[[menu.main]]
|
||||
name = "Press & Articles"
|
||||
pre = "<i class='fa fa-bullhorn'></i>"
|
||||
url = "/community/press/"
|
||||
weight = -160
|
||||
[[menu.main]]
|
||||
name = "Discuss Hugo"
|
||||
pre = "<i class='fa fa-comments'></i>"
|
||||
url = "http://discuss.gohugo.io/"
|
||||
weight = -150
|
||||
[[menu.main]]
|
||||
name = "About Hugo"
|
||||
identifier = "about"
|
||||
pre = "<i class='fa fa-heart'></i>"
|
||||
weight = -110
|
||||
[[menu.main]]
|
||||
name = "Getting Started"
|
||||
identifier = "getting started"
|
||||
pre = "<i class='fa fa-road'></i>"
|
||||
weight = -100
|
||||
[[menu.main]]
|
||||
name = "Content"
|
||||
identifier = "content"
|
||||
pre = "<i class='fa fa-file-text'></i>"
|
||||
weight = -90
|
||||
[[menu.main]]
|
||||
name = "Themes"
|
||||
identifier = "themes"
|
||||
pre = "<i class='fa fa-desktop'></i>"
|
||||
weight = -85
|
||||
[[menu.main]]
|
||||
parent = "themes"
|
||||
name = "Theme Showcase"
|
||||
url = "http://themes.gohugo.io"
|
||||
weight = -170
|
||||
[[menu.main]]
|
||||
name = "Templates"
|
||||
identifier = "layout"
|
||||
pre = "<i class='fa fa-columns'></i>"
|
||||
weight = -80
|
||||
[[menu.main]]
|
||||
name = "Taxonomies"
|
||||
identifier = "taxonomy"
|
||||
pre = "<i class='fa fa-tags'></i>"
|
||||
weight = -70
|
||||
[[menu.main]]
|
||||
name = "Extras"
|
||||
identifier = "extras"
|
||||
pre = "<i class='fa fa-gift'></i>"
|
||||
weight = -60
|
||||
[[menu.main]]
|
||||
name = "Community"
|
||||
identifier = "community"
|
||||
pre = "<i class='fa fa-group'></i>"
|
||||
weight = -50
|
||||
[[menu.main]]
|
||||
parent = "community"
|
||||
name = "Discussion Forum"
|
||||
url = "http://discuss.gohugo.io"
|
||||
weight = 150
|
||||
[[menu.main]]
|
||||
name = "Tutorials"
|
||||
identifier = "tutorials"
|
||||
pre = "<i class='fa fa-book'></i>"
|
||||
weight = -40
|
||||
[[menu.main]]
|
||||
name = "Troubleshooting"
|
||||
identifier = "troubleshooting"
|
||||
pre = "<i class='fa fa-wrench'></i>"
|
||||
weight = -30
|
||||
[[menu.main]]
|
||||
name = "Tools"
|
||||
url = "/tools/"
|
||||
pre = "<i class='fa fa-cogs'></i>"
|
||||
weight = -25
|
||||
[[menu.main]]
|
||||
name = "Hugo Cmd Reference"
|
||||
identifier = "commands"
|
||||
pre = "<i class='fa fa-space-shuttle'></i>"
|
||||
weight = -20
|
||||
url = "/commands/"
|
||||
@@ -1,75 +0,0 @@
|
||||
---
|
||||
date: 2016-10-05T10:21:48+02:00
|
||||
title: "hugo"
|
||||
slug: hugo
|
||||
url: /commands/hugo/
|
||||
---
|
||||
## hugo
|
||||
|
||||
hugo builds your site
|
||||
|
||||
### Synopsis
|
||||
|
||||
|
||||
hugo is the main command, used to build your Hugo site.
|
||||
|
||||
Hugo is a Fast and Flexible Static Site Generator
|
||||
built with love by spf13 and friends in Go.
|
||||
|
||||
Complete documentation is available at http://gohugo.io/.
|
||||
|
||||
```
|
||||
hugo
|
||||
```
|
||||
|
||||
### Options
|
||||
|
||||
```
|
||||
-b, --baseURL string hostname (and path) to the root, e.g. http://spf13.com/
|
||||
-D, --buildDrafts include content marked as draft
|
||||
-E, --buildExpired include expired content
|
||||
-F, --buildFuture include content with publishdate in the future
|
||||
--cacheDir string filesystem path to cache directory. Defaults: $TMPDIR/hugo_cache/
|
||||
--canonifyURLs if true, all relative URLs will be canonicalized using baseURL
|
||||
--cleanDestinationDir Remove files from destination not found in static directories
|
||||
--config string config file (default is path/config.yaml|json|toml)
|
||||
-c, --contentDir string filesystem path to content directory
|
||||
-d, --destination string filesystem path to write files to
|
||||
--disable404 Do not render 404 page
|
||||
--disableRSS Do not build RSS files
|
||||
--disableSitemap Do not build Sitemap file
|
||||
--forceSyncStatic Copy all files when static is changed.
|
||||
--i18n-warnings Print missing translations
|
||||
--ignoreCache Ignores the cache directory
|
||||
-l, --layoutDir string filesystem path to layout directory
|
||||
--log Enable Logging
|
||||
--logFile string Log File path (if set, logging enabled automatically)
|
||||
--noChmod Don't sync permission mode of files
|
||||
--noTimes Don't sync modification time of files
|
||||
--pluralizeListTitles Pluralize titles in lists using inflect (default true)
|
||||
--preserveTaxonomyNames Preserve taxonomy names as written ("Gérard Depardieu" vs "gerard-depardieu")
|
||||
--renderToMemory render to memory (only useful for benchmark testing)
|
||||
-s, --source string filesystem path to read files relative from
|
||||
--stepAnalysis display memory and timing of different steps of the program
|
||||
-t, --theme string theme to use (located in /themes/THEMENAME/)
|
||||
--uglyURLs if true, use /filename.html instead of /filename/
|
||||
-v, --verbose verbose output
|
||||
--verboseLog verbose logging
|
||||
-w, --watch watch filesystem for changes and recreate as needed
|
||||
```
|
||||
|
||||
### SEE ALSO
|
||||
* [hugo benchmark](/commands/hugo_benchmark/) - Benchmark Hugo by building a site a number of times.
|
||||
* [hugo check](/commands/hugo_check/) - Check content in the source directory
|
||||
* [hugo config](/commands/hugo_config/) - Print the site configuration
|
||||
* [hugo convert](/commands/hugo_convert/) - Convert your content to different formats
|
||||
* [hugo env](/commands/hugo_env/) - Print Hugo version and environment info
|
||||
* [hugo gen](/commands/hugo_gen/) - A collection of several useful generators.
|
||||
* [hugo import](/commands/hugo_import/) - Import your site from others.
|
||||
* [hugo list](/commands/hugo_list/) - Listing out various types of content
|
||||
* [hugo new](/commands/hugo_new/) - Create new content for your site
|
||||
* [hugo server](/commands/hugo_server/) - A high performance webserver
|
||||
* [hugo undraft](/commands/hugo_undraft/) - Undraft changes the content's draft status from 'True' to 'False'
|
||||
* [hugo version](/commands/hugo_version/) - Print the version number of Hugo
|
||||
|
||||
###### Auto generated by spf13/cobra on 5-Oct-2016
|
||||
@@ -1,67 +0,0 @@
|
||||
---
|
||||
date: 2016-10-05T10:21:48+02:00
|
||||
title: "hugo benchmark"
|
||||
slug: hugo_benchmark
|
||||
url: /commands/hugo_benchmark/
|
||||
---
|
||||
## hugo benchmark
|
||||
|
||||
Benchmark Hugo by building a site a number of times.
|
||||
|
||||
### Synopsis
|
||||
|
||||
|
||||
Hugo can build a site many times over and analyze the running process
|
||||
creating a benchmark.
|
||||
|
||||
```
|
||||
hugo benchmark
|
||||
```
|
||||
|
||||
### Options
|
||||
|
||||
```
|
||||
-b, --baseURL string hostname (and path) to the root, e.g. http://spf13.com/
|
||||
-D, --buildDrafts include content marked as draft
|
||||
-E, --buildExpired include expired content
|
||||
-F, --buildFuture include content with publishdate in the future
|
||||
--cacheDir string filesystem path to cache directory. Defaults: $TMPDIR/hugo_cache/
|
||||
--canonifyURLs if true, all relative URLs will be canonicalized using baseURL
|
||||
--cleanDestinationDir Remove files from destination not found in static directories
|
||||
-c, --contentDir string filesystem path to content directory
|
||||
-n, --count int number of times to build the site (default 13)
|
||||
--cpuprofile string path/filename for the CPU profile file
|
||||
-d, --destination string filesystem path to write files to
|
||||
--disable404 Do not render 404 page
|
||||
--disableRSS Do not build RSS files
|
||||
--disableSitemap Do not build Sitemap file
|
||||
--forceSyncStatic Copy all files when static is changed.
|
||||
--i18n-warnings Print missing translations
|
||||
--ignoreCache Ignores the cache directory
|
||||
-l, --layoutDir string filesystem path to layout directory
|
||||
--memprofile string path/filename for the memory profile file
|
||||
--noChmod Don't sync permission mode of files
|
||||
--noTimes Don't sync modification time of files
|
||||
--pluralizeListTitles Pluralize titles in lists using inflect (default true)
|
||||
--preserveTaxonomyNames Preserve taxonomy names as written ("Gérard Depardieu" vs "gerard-depardieu")
|
||||
--renderToMemory render to memory (only useful for benchmark testing)
|
||||
-s, --source string filesystem path to read files relative from
|
||||
--stepAnalysis display memory and timing of different steps of the program
|
||||
-t, --theme string theme to use (located in /themes/THEMENAME/)
|
||||
--uglyURLs if true, use /filename.html instead of /filename/
|
||||
```
|
||||
|
||||
### Options inherited from parent commands
|
||||
|
||||
```
|
||||
--config string config file (default is path/config.yaml|json|toml)
|
||||
--log Enable Logging
|
||||
--logFile string Log File path (if set, logging enabled automatically)
|
||||
-v, --verbose verbose output
|
||||
--verboseLog verbose logging
|
||||
```
|
||||
|
||||
### SEE ALSO
|
||||
* [hugo](/commands/hugo/) - hugo builds your site
|
||||
|
||||
###### Auto generated by spf13/cobra on 5-Oct-2016
|
||||
@@ -1,63 +0,0 @@
|
||||
---
|
||||
date: 2016-10-05T10:21:48+02:00
|
||||
title: "hugo check"
|
||||
slug: hugo_check
|
||||
url: /commands/hugo_check/
|
||||
---
|
||||
## hugo check
|
||||
|
||||
Check content in the source directory
|
||||
|
||||
### Synopsis
|
||||
|
||||
|
||||
Hugo will perform some basic analysis on the content provided
|
||||
and will give feedback.
|
||||
|
||||
```
|
||||
hugo check
|
||||
```
|
||||
|
||||
### Options
|
||||
|
||||
```
|
||||
-b, --baseURL string hostname (and path) to the root, e.g. http://spf13.com/
|
||||
-D, --buildDrafts include content marked as draft
|
||||
-E, --buildExpired include expired content
|
||||
-F, --buildFuture include content with publishdate in the future
|
||||
--cacheDir string filesystem path to cache directory. Defaults: $TMPDIR/hugo_cache/
|
||||
--canonifyURLs if true, all relative URLs will be canonicalized using baseURL
|
||||
--cleanDestinationDir Remove files from destination not found in static directories
|
||||
-c, --contentDir string filesystem path to content directory
|
||||
-d, --destination string filesystem path to write files to
|
||||
--disable404 Do not render 404 page
|
||||
--disableRSS Do not build RSS files
|
||||
--disableSitemap Do not build Sitemap file
|
||||
--forceSyncStatic Copy all files when static is changed.
|
||||
--i18n-warnings Print missing translations
|
||||
--ignoreCache Ignores the cache directory
|
||||
-l, --layoutDir string filesystem path to layout directory
|
||||
--noTimes Don't sync modification time of files
|
||||
--pluralizeListTitles Pluralize titles in lists using inflect (default true)
|
||||
--preserveTaxonomyNames Preserve taxonomy names as written ("Gérard Depardieu" vs "gerard-depardieu")
|
||||
-s, --source string filesystem path to read files relative from
|
||||
--stepAnalysis display memory and timing of different steps of the program
|
||||
-t, --theme string theme to use (located in /themes/THEMENAME/)
|
||||
--uglyURLs if true, use /filename.html instead of /filename/
|
||||
```
|
||||
|
||||
### Options inherited from parent commands
|
||||
|
||||
```
|
||||
--config string config file (default is path/config.yaml|json|toml)
|
||||
--log Enable Logging
|
||||
--logFile string Log File path (if set, logging enabled automatically)
|
||||
-v, --verbose verbose output
|
||||
--verboseLog verbose logging
|
||||
```
|
||||
|
||||
### SEE ALSO
|
||||
* [hugo](/commands/hugo/) - hugo builds your site
|
||||
* [hugo check ulimit](/commands/hugo_check_ulimit/) - Check system ulimit settings
|
||||
|
||||
###### Auto generated by spf13/cobra on 5-Oct-2016
|
||||
@@ -1,34 +0,0 @@
|
||||
---
|
||||
date: 2016-10-05T10:21:48+02:00
|
||||
title: "hugo check ulimit"
|
||||
slug: hugo_check_ulimit
|
||||
url: /commands/hugo_check_ulimit/
|
||||
---
|
||||
## hugo check ulimit
|
||||
|
||||
Check system ulimit settings
|
||||
|
||||
### Synopsis
|
||||
|
||||
|
||||
Hugo will inspect the current ulimit settings on the system.
|
||||
This is primarily to ensure that Hugo can watch enough files on some OSs
|
||||
|
||||
```
|
||||
hugo check ulimit
|
||||
```
|
||||
|
||||
### Options inherited from parent commands
|
||||
|
||||
```
|
||||
--config string config file (default is path/config.yaml|json|toml)
|
||||
--log Enable Logging
|
||||
--logFile string Log File path (if set, logging enabled automatically)
|
||||
-v, --verbose verbose output
|
||||
--verboseLog verbose logging
|
||||
```
|
||||
|
||||
### SEE ALSO
|
||||
* [hugo check](/commands/hugo_check/) - Check content in the source directory
|
||||
|
||||
###### Auto generated by spf13/cobra on 5-Oct-2016
|
||||
@@ -1,33 +0,0 @@
|
||||
---
|
||||
date: 2016-10-05T10:21:48+02:00
|
||||
title: "hugo config"
|
||||
slug: hugo_config
|
||||
url: /commands/hugo_config/
|
||||
---
|
||||
## hugo config
|
||||
|
||||
Print the site configuration
|
||||
|
||||
### Synopsis
|
||||
|
||||
|
||||
Print the site configuration, both default and custom settings.
|
||||
|
||||
```
|
||||
hugo config
|
||||
```
|
||||
|
||||
### Options inherited from parent commands
|
||||
|
||||
```
|
||||
--config string config file (default is path/config.yaml|json|toml)
|
||||
--log Enable Logging
|
||||
--logFile string Log File path (if set, logging enabled automatically)
|
||||
-v, --verbose verbose output
|
||||
--verboseLog verbose logging
|
||||
```
|
||||
|
||||
### SEE ALSO
|
||||
* [hugo](/commands/hugo/) - hugo builds your site
|
||||
|
||||
###### Auto generated by spf13/cobra on 5-Oct-2016
|
||||
@@ -1,42 +0,0 @@
|
||||
---
|
||||
date: 2016-10-05T10:21:48+02:00
|
||||
title: "hugo convert"
|
||||
slug: hugo_convert
|
||||
url: /commands/hugo_convert/
|
||||
---
|
||||
## hugo convert
|
||||
|
||||
Convert your content to different formats
|
||||
|
||||
### Synopsis
|
||||
|
||||
|
||||
Convert your content (e.g. front matter) to different formats.
|
||||
|
||||
See convert's subcommands toJSON, toTOML and toYAML for more information.
|
||||
|
||||
### Options
|
||||
|
||||
```
|
||||
-o, --output string filesystem path to write files to
|
||||
-s, --source string filesystem path to read files relative from
|
||||
--unsafe enable less safe operations, please backup first
|
||||
```
|
||||
|
||||
### Options inherited from parent commands
|
||||
|
||||
```
|
||||
--config string config file (default is path/config.yaml|json|toml)
|
||||
--log Enable Logging
|
||||
--logFile string Log File path (if set, logging enabled automatically)
|
||||
-v, --verbose verbose output
|
||||
--verboseLog verbose logging
|
||||
```
|
||||
|
||||
### SEE ALSO
|
||||
* [hugo](/commands/hugo/) - hugo builds your site
|
||||
* [hugo convert toJSON](/commands/hugo_convert_tojson/) - Convert front matter to JSON
|
||||
* [hugo convert toTOML](/commands/hugo_convert_totoml/) - Convert front matter to TOML
|
||||
* [hugo convert toYAML](/commands/hugo_convert_toyaml/) - Convert front matter to YAML
|
||||
|
||||
###### Auto generated by spf13/cobra on 5-Oct-2016
|
||||
@@ -1,37 +0,0 @@
|
||||
---
|
||||
date: 2016-10-05T10:21:48+02:00
|
||||
title: "hugo convert toJSON"
|
||||
slug: hugo_convert_toJSON
|
||||
url: /commands/hugo_convert_tojson/
|
||||
---
|
||||
## hugo convert toJSON
|
||||
|
||||
Convert front matter to JSON
|
||||
|
||||
### Synopsis
|
||||
|
||||
|
||||
toJSON converts all front matter in the content directory
|
||||
to use JSON for the front matter.
|
||||
|
||||
```
|
||||
hugo convert toJSON
|
||||
```
|
||||
|
||||
### Options inherited from parent commands
|
||||
|
||||
```
|
||||
--config string config file (default is path/config.yaml|json|toml)
|
||||
--log Enable Logging
|
||||
--logFile string Log File path (if set, logging enabled automatically)
|
||||
-o, --output string filesystem path to write files to
|
||||
-s, --source string filesystem path to read files relative from
|
||||
--unsafe enable less safe operations, please backup first
|
||||
-v, --verbose verbose output
|
||||
--verboseLog verbose logging
|
||||
```
|
||||
|
||||
### SEE ALSO
|
||||
* [hugo convert](/commands/hugo_convert/) - Convert your content to different formats
|
||||
|
||||
###### Auto generated by spf13/cobra on 5-Oct-2016
|
||||
@@ -1,37 +0,0 @@
|
||||
---
|
||||
date: 2016-10-05T10:21:48+02:00
|
||||
title: "hugo convert toTOML"
|
||||
slug: hugo_convert_toTOML
|
||||
url: /commands/hugo_convert_totoml/
|
||||
---
|
||||
## hugo convert toTOML
|
||||
|
||||
Convert front matter to TOML
|
||||
|
||||
### Synopsis
|
||||
|
||||
|
||||
toTOML converts all front matter in the content directory
|
||||
to use TOML for the front matter.
|
||||
|
||||
```
|
||||
hugo convert toTOML
|
||||
```
|
||||
|
||||
### Options inherited from parent commands
|
||||
|
||||
```
|
||||
--config string config file (default is path/config.yaml|json|toml)
|
||||
--log Enable Logging
|
||||
--logFile string Log File path (if set, logging enabled automatically)
|
||||
-o, --output string filesystem path to write files to
|
||||
-s, --source string filesystem path to read files relative from
|
||||
--unsafe enable less safe operations, please backup first
|
||||
-v, --verbose verbose output
|
||||
--verboseLog verbose logging
|
||||
```
|
||||
|
||||
### SEE ALSO
|
||||
* [hugo convert](/commands/hugo_convert/) - Convert your content to different formats
|
||||
|
||||
###### Auto generated by spf13/cobra on 5-Oct-2016
|
||||
@@ -1,37 +0,0 @@
|
||||
---
|
||||
date: 2016-10-05T10:21:48+02:00
|
||||
title: "hugo convert toYAML"
|
||||
slug: hugo_convert_toYAML
|
||||
url: /commands/hugo_convert_toyaml/
|
||||
---
|
||||
## hugo convert toYAML
|
||||
|
||||
Convert front matter to YAML
|
||||
|
||||
### Synopsis
|
||||
|
||||
|
||||
toYAML converts all front matter in the content directory
|
||||
to use YAML for the front matter.
|
||||
|
||||
```
|
||||
hugo convert toYAML
|
||||
```
|
||||
|
||||
### Options inherited from parent commands
|
||||
|
||||
```
|
||||
--config string config file (default is path/config.yaml|json|toml)
|
||||
--log Enable Logging
|
||||
--logFile string Log File path (if set, logging enabled automatically)
|
||||
-o, --output string filesystem path to write files to
|
||||
-s, --source string filesystem path to read files relative from
|
||||
--unsafe enable less safe operations, please backup first
|
||||
-v, --verbose verbose output
|
||||
--verboseLog verbose logging
|
||||
```
|
||||
|
||||
### SEE ALSO
|
||||
* [hugo convert](/commands/hugo_convert/) - Convert your content to different formats
|
||||
|
||||
###### Auto generated by spf13/cobra on 5-Oct-2016
|
||||
@@ -1,33 +0,0 @@
|
||||
---
|
||||
date: 2016-10-05T10:21:48+02:00
|
||||
title: "hugo env"
|
||||
slug: hugo_env
|
||||
url: /commands/hugo_env/
|
||||
---
|
||||
## hugo env
|
||||
|
||||
Print Hugo version and environment info
|
||||
|
||||
### Synopsis
|
||||
|
||||
|
||||
Print Hugo version and environment info. This is useful in Hugo bug reports.
|
||||
|
||||
```
|
||||
hugo env
|
||||
```
|
||||
|
||||
### Options inherited from parent commands
|
||||
|
||||
```
|
||||
--config string config file (default is path/config.yaml|json|toml)
|
||||
--log Enable Logging
|
||||
--logFile string Log File path (if set, logging enabled automatically)
|
||||
-v, --verbose verbose output
|
||||
--verboseLog verbose logging
|
||||
```
|
||||
|
||||
### SEE ALSO
|
||||
* [hugo](/commands/hugo/) - hugo builds your site
|
||||
|
||||
###### Auto generated by spf13/cobra on 5-Oct-2016
|
||||
@@ -1,32 +0,0 @@
|
||||
---
|
||||
date: 2016-10-05T10:21:48+02:00
|
||||
title: "hugo gen"
|
||||
slug: hugo_gen
|
||||
url: /commands/hugo_gen/
|
||||
---
|
||||
## hugo gen
|
||||
|
||||
A collection of several useful generators.
|
||||
|
||||
### Synopsis
|
||||
|
||||
|
||||
A collection of several useful generators.
|
||||
|
||||
### Options inherited from parent commands
|
||||
|
||||
```
|
||||
--config string config file (default is path/config.yaml|json|toml)
|
||||
--log Enable Logging
|
||||
--logFile string Log File path (if set, logging enabled automatically)
|
||||
-v, --verbose verbose output
|
||||
--verboseLog verbose logging
|
||||
```
|
||||
|
||||
### SEE ALSO
|
||||
* [hugo](/commands/hugo/) - hugo builds your site
|
||||
* [hugo gen autocomplete](/commands/hugo_gen_autocomplete/) - Generate shell autocompletion script for Hugo
|
||||
* [hugo gen doc](/commands/hugo_gen_doc/) - Generate Markdown documentation for the Hugo CLI.
|
||||
* [hugo gen man](/commands/hugo_gen_man/) - Generate man pages for the Hugo CLI
|
||||
|
||||
###### Auto generated by spf13/cobra on 5-Oct-2016
|
||||
@@ -1,56 +0,0 @@
|
||||
---
|
||||
date: 2016-10-05T10:21:48+02:00
|
||||
title: "hugo gen autocomplete"
|
||||
slug: hugo_gen_autocomplete
|
||||
url: /commands/hugo_gen_autocomplete/
|
||||
---
|
||||
## hugo gen autocomplete
|
||||
|
||||
Generate shell autocompletion script for Hugo
|
||||
|
||||
### Synopsis
|
||||
|
||||
|
||||
Generates a shell autocompletion script for Hugo.
|
||||
|
||||
NOTE: The current version supports Bash only.
|
||||
This should work for *nix systems with Bash installed.
|
||||
|
||||
By default, the file is written directly to /etc/bash_completion.d
|
||||
for convenience, and the command may need superuser rights, e.g.:
|
||||
|
||||
$ sudo hugo gen autocomplete
|
||||
|
||||
Add `--completionfile=/path/to/file` flag to set alternative
|
||||
file-path and name.
|
||||
|
||||
Logout and in again to reload the completion scripts,
|
||||
or just source them in directly:
|
||||
|
||||
$ . /etc/bash_completion
|
||||
|
||||
```
|
||||
hugo gen autocomplete
|
||||
```
|
||||
|
||||
### Options
|
||||
|
||||
```
|
||||
--completionfile string Autocompletion file (default "/etc/bash_completion.d/hugo.sh")
|
||||
--type string Autocompletion type (currently only bash supported) (default "bash")
|
||||
```
|
||||
|
||||
### Options inherited from parent commands
|
||||
|
||||
```
|
||||
--config string config file (default is path/config.yaml|json|toml)
|
||||
--log Enable Logging
|
||||
--logFile string Log File path (if set, logging enabled automatically)
|
||||
-v, --verbose verbose output
|
||||
--verboseLog verbose logging
|
||||
```
|
||||
|
||||
### SEE ALSO
|
||||
* [hugo gen](/commands/hugo_gen/) - A collection of several useful generators.
|
||||
|
||||
###### Auto generated by spf13/cobra on 5-Oct-2016
|
||||
@@ -1,45 +0,0 @@
|
||||
---
|
||||
date: 2016-10-05T10:21:48+02:00
|
||||
title: "hugo gen doc"
|
||||
slug: hugo_gen_doc
|
||||
url: /commands/hugo_gen_doc/
|
||||
---
|
||||
## hugo gen doc
|
||||
|
||||
Generate Markdown documentation for the Hugo CLI.
|
||||
|
||||
### Synopsis
|
||||
|
||||
|
||||
Generate Markdown documentation for the Hugo CLI.
|
||||
|
||||
This command is, mostly, used to create up-to-date documentation
|
||||
of Hugo's command-line interface for http://gohugo.io/.
|
||||
|
||||
It creates one Markdown file per command with front matter suitable
|
||||
for rendering in Hugo.
|
||||
|
||||
```
|
||||
hugo gen doc
|
||||
```
|
||||
|
||||
### Options
|
||||
|
||||
```
|
||||
--dir string the directory to write the doc. (default "/tmp/hugodoc/")
|
||||
```
|
||||
|
||||
### Options inherited from parent commands
|
||||
|
||||
```
|
||||
--config string config file (default is path/config.yaml|json|toml)
|
||||
--log Enable Logging
|
||||
--logFile string Log File path (if set, logging enabled automatically)
|
||||
-v, --verbose verbose output
|
||||
--verboseLog verbose logging
|
||||
```
|
||||
|
||||
### SEE ALSO
|
||||
* [hugo gen](/commands/hugo_gen/) - A collection of several useful generators.
|
||||
|
||||
###### Auto generated by spf13/cobra on 5-Oct-2016
|
||||
@@ -1,41 +0,0 @@
|
||||
---
|
||||
date: 2016-10-05T10:21:48+02:00
|
||||
title: "hugo gen man"
|
||||
slug: hugo_gen_man
|
||||
url: /commands/hugo_gen_man/
|
||||
---
|
||||
## hugo gen man
|
||||
|
||||
Generate man pages for the Hugo CLI
|
||||
|
||||
### Synopsis
|
||||
|
||||
|
||||
This command automatically generates up-to-date man pages of Hugo's
|
||||
command-line interface. By default, it creates the man page files
|
||||
in the "man" directory under the current directory.
|
||||
|
||||
```
|
||||
hugo gen man
|
||||
```
|
||||
|
||||
### Options
|
||||
|
||||
```
|
||||
--dir string the directory to write the man pages. (default "man/")
|
||||
```
|
||||
|
||||
### Options inherited from parent commands
|
||||
|
||||
```
|
||||
--config string config file (default is path/config.yaml|json|toml)
|
||||
--log Enable Logging
|
||||
--logFile string Log File path (if set, logging enabled automatically)
|
||||
-v, --verbose verbose output
|
||||
--verboseLog verbose logging
|
||||
```
|
||||
|
||||
### SEE ALSO
|
||||
* [hugo gen](/commands/hugo_gen/) - A collection of several useful generators.
|
||||
|
||||
###### Auto generated by spf13/cobra on 5-Oct-2016
|
||||
@@ -1,32 +0,0 @@
|
||||
---
|
||||
date: 2016-10-05T10:21:48+02:00
|
||||
title: "hugo import"
|
||||
slug: hugo_import
|
||||
url: /commands/hugo_import/
|
||||
---
|
||||
## hugo import
|
||||
|
||||
Import your site from others.
|
||||
|
||||
### Synopsis
|
||||
|
||||
|
||||
Import your site from other web site generators like Jekyll.
|
||||
|
||||
Import requires a subcommand, e.g. `hugo import jekyll jekyll_root_path target_path`.
|
||||
|
||||
### Options inherited from parent commands
|
||||
|
||||
```
|
||||
--config string config file (default is path/config.yaml|json|toml)
|
||||
--log Enable Logging
|
||||
--logFile string Log File path (if set, logging enabled automatically)
|
||||
-v, --verbose verbose output
|
||||
--verboseLog verbose logging
|
||||
```
|
||||
|
||||
### SEE ALSO
|
||||
* [hugo](/commands/hugo/) - hugo builds your site
|
||||
* [hugo import jekyll](/commands/hugo_import_jekyll/) - hugo import from Jekyll
|
||||
|
||||
###### Auto generated by spf13/cobra on 5-Oct-2016
|
||||
@@ -1,41 +0,0 @@
|
||||
---
|
||||
date: 2016-10-05T10:21:48+02:00
|
||||
title: "hugo import jekyll"
|
||||
slug: hugo_import_jekyll
|
||||
url: /commands/hugo_import_jekyll/
|
||||
---
|
||||
## hugo import jekyll
|
||||
|
||||
hugo import from Jekyll
|
||||
|
||||
### Synopsis
|
||||
|
||||
|
||||
hugo import from Jekyll.
|
||||
|
||||
Import from Jekyll requires two paths, e.g. `hugo import jekyll jekyll_root_path target_path`.
|
||||
|
||||
```
|
||||
hugo import jekyll
|
||||
```
|
||||
|
||||
### Options
|
||||
|
||||
```
|
||||
--force Allow import into non-empty target directory
|
||||
```
|
||||
|
||||
### Options inherited from parent commands
|
||||
|
||||
```
|
||||
--config string config file (default is path/config.yaml|json|toml)
|
||||
--log Enable Logging
|
||||
--logFile string Log File path (if set, logging enabled automatically)
|
||||
-v, --verbose verbose output
|
||||
--verboseLog verbose logging
|
||||
```
|
||||
|
||||
### SEE ALSO
|
||||
* [hugo import](/commands/hugo_import/) - Import your site from others.
|
||||
|
||||
###### Auto generated by spf13/cobra on 5-Oct-2016
|
||||
@@ -1,40 +0,0 @@
|
||||
---
|
||||
date: 2016-10-05T10:21:48+02:00
|
||||
title: "hugo list"
|
||||
slug: hugo_list
|
||||
url: /commands/hugo_list/
|
||||
---
|
||||
## hugo list
|
||||
|
||||
Listing out various types of content
|
||||
|
||||
### Synopsis
|
||||
|
||||
|
||||
Listing out various types of content.
|
||||
|
||||
List requires a subcommand, e.g. `hugo list drafts`.
|
||||
|
||||
### Options
|
||||
|
||||
```
|
||||
-s, --source string filesystem path to read files relative from
|
||||
```
|
||||
|
||||
### Options inherited from parent commands
|
||||
|
||||
```
|
||||
--config string config file (default is path/config.yaml|json|toml)
|
||||
--log Enable Logging
|
||||
--logFile string Log File path (if set, logging enabled automatically)
|
||||
-v, --verbose verbose output
|
||||
--verboseLog verbose logging
|
||||
```
|
||||
|
||||
### SEE ALSO
|
||||
* [hugo](/commands/hugo/) - hugo builds your site
|
||||
* [hugo list drafts](/commands/hugo_list_drafts/) - List all drafts
|
||||
* [hugo list expired](/commands/hugo_list_expired/) - List all posts already expired
|
||||
* [hugo list future](/commands/hugo_list_future/) - List all posts dated in the future
|
||||
|
||||
###### Auto generated by spf13/cobra on 5-Oct-2016
|
||||
@@ -1,34 +0,0 @@
|
||||
---
|
||||
date: 2016-10-05T10:21:48+02:00
|
||||
title: "hugo list drafts"
|
||||
slug: hugo_list_drafts
|
||||
url: /commands/hugo_list_drafts/
|
||||
---
|
||||
## hugo list drafts
|
||||
|
||||
List all drafts
|
||||
|
||||
### Synopsis
|
||||
|
||||
|
||||
List all of the drafts in your content directory.
|
||||
|
||||
```
|
||||
hugo list drafts
|
||||
```
|
||||
|
||||
### Options inherited from parent commands
|
||||
|
||||
```
|
||||
--config string config file (default is path/config.yaml|json|toml)
|
||||
--log Enable Logging
|
||||
--logFile string Log File path (if set, logging enabled automatically)
|
||||
-s, --source string filesystem path to read files relative from
|
||||
-v, --verbose verbose output
|
||||
--verboseLog verbose logging
|
||||
```
|
||||
|
||||
### SEE ALSO
|
||||
* [hugo list](/commands/hugo_list/) - Listing out various types of content
|
||||
|
||||
###### Auto generated by spf13/cobra on 5-Oct-2016
|
||||
@@ -1,35 +0,0 @@
|
||||
---
|
||||
date: 2016-10-05T10:21:48+02:00
|
||||
title: "hugo list expired"
|
||||
slug: hugo_list_expired
|
||||
url: /commands/hugo_list_expired/
|
||||
---
|
||||
## hugo list expired
|
||||
|
||||
List all posts already expired
|
||||
|
||||
### Synopsis
|
||||
|
||||
|
||||
List all of the posts in your content directory which has already
|
||||
expired.
|
||||
|
||||
```
|
||||
hugo list expired
|
||||
```
|
||||
|
||||
### Options inherited from parent commands
|
||||
|
||||
```
|
||||
--config string config file (default is path/config.yaml|json|toml)
|
||||
--log Enable Logging
|
||||
--logFile string Log File path (if set, logging enabled automatically)
|
||||
-s, --source string filesystem path to read files relative from
|
||||
-v, --verbose verbose output
|
||||
--verboseLog verbose logging
|
||||
```
|
||||
|
||||
### SEE ALSO
|
||||
* [hugo list](/commands/hugo_list/) - Listing out various types of content
|
||||
|
||||
###### Auto generated by spf13/cobra on 5-Oct-2016
|
||||
@@ -1,35 +0,0 @@
|
||||
---
|
||||
date: 2016-10-05T10:21:48+02:00
|
||||
title: "hugo list future"
|
||||
slug: hugo_list_future
|
||||
url: /commands/hugo_list_future/
|
||||
---
|
||||
## hugo list future
|
||||
|
||||
List all posts dated in the future
|
||||
|
||||
### Synopsis
|
||||
|
||||
|
||||
List all of the posts in your content directory which will be
|
||||
posted in the future.
|
||||
|
||||
```
|
||||
hugo list future
|
||||
```
|
||||
|
||||
### Options inherited from parent commands
|
||||
|
||||
```
|
||||
--config string config file (default is path/config.yaml|json|toml)
|
||||
--log Enable Logging
|
||||
--logFile string Log File path (if set, logging enabled automatically)
|
||||
-s, --source string filesystem path to read files relative from
|
||||
-v, --verbose verbose output
|
||||
--verboseLog verbose logging
|
||||
```
|
||||
|
||||
### SEE ALSO
|
||||
* [hugo list](/commands/hugo_list/) - Listing out various types of content
|
||||
|
||||
###### Auto generated by spf13/cobra on 5-Oct-2016
|
||||
@@ -1,49 +0,0 @@
|
||||
---
|
||||
date: 2016-10-05T10:21:48+02:00
|
||||
title: "hugo new"
|
||||
slug: hugo_new
|
||||
url: /commands/hugo_new/
|
||||
---
|
||||
## hugo new
|
||||
|
||||
Create new content for your site
|
||||
|
||||
### Synopsis
|
||||
|
||||
|
||||
Create a new content file and automatically set the date and title.
|
||||
It will guess which kind of file to create based on the path provided.
|
||||
|
||||
You can also specify the kind with `-k KIND`.
|
||||
|
||||
If archetypes are provided in your theme or site, they will be used.
|
||||
|
||||
```
|
||||
hugo new [path]
|
||||
```
|
||||
|
||||
### Options
|
||||
|
||||
```
|
||||
--editor string edit new content with this editor, if provided
|
||||
-f, --format string frontmatter format (default "toml")
|
||||
-k, --kind string Content type to create
|
||||
-s, --source string filesystem path to read files relative from
|
||||
```
|
||||
|
||||
### Options inherited from parent commands
|
||||
|
||||
```
|
||||
--config string config file (default is path/config.yaml|json|toml)
|
||||
--log Enable Logging
|
||||
--logFile string Log File path (if set, logging enabled automatically)
|
||||
-v, --verbose verbose output
|
||||
--verboseLog verbose logging
|
||||
```
|
||||
|
||||
### SEE ALSO
|
||||
* [hugo](/commands/hugo/) - hugo builds your site
|
||||
* [hugo new site](/commands/hugo_new_site/) - Create a new site (skeleton)
|
||||
* [hugo new theme](/commands/hugo_new_theme/) - Create a new theme
|
||||
|
||||
###### Auto generated by spf13/cobra on 5-Oct-2016
|
||||
@@ -1,43 +0,0 @@
|
||||
---
|
||||
date: 2016-10-05T10:21:48+02:00
|
||||
title: "hugo new site"
|
||||
slug: hugo_new_site
|
||||
url: /commands/hugo_new_site/
|
||||
---
|
||||
## hugo new site
|
||||
|
||||
Create a new site (skeleton)
|
||||
|
||||
### Synopsis
|
||||
|
||||
|
||||
Create a new site in the provided directory.
|
||||
The new site will have the correct structure, but no content or theme yet.
|
||||
Use `hugo new [contentPath]` to create new content.
|
||||
|
||||
```
|
||||
hugo new site [path]
|
||||
```
|
||||
|
||||
### Options
|
||||
|
||||
```
|
||||
--force Init inside non-empty directory
|
||||
-f, --format string config & frontmatter format (default "toml")
|
||||
```
|
||||
|
||||
### Options inherited from parent commands
|
||||
|
||||
```
|
||||
--config string config file (default is path/config.yaml|json|toml)
|
||||
--log Enable Logging
|
||||
--logFile string Log File path (if set, logging enabled automatically)
|
||||
-s, --source string filesystem path to read files relative from
|
||||
-v, --verbose verbose output
|
||||
--verboseLog verbose logging
|
||||
```
|
||||
|
||||
### SEE ALSO
|
||||
* [hugo new](/commands/hugo_new/) - Create new content for your site
|
||||
|
||||
###### Auto generated by spf13/cobra on 5-Oct-2016
|
||||
@@ -1,37 +0,0 @@
|
||||
---
|
||||
date: 2016-10-05T10:21:48+02:00
|
||||
title: "hugo new theme"
|
||||
slug: hugo_new_theme
|
||||
url: /commands/hugo_new_theme/
|
||||
---
|
||||
## hugo new theme
|
||||
|
||||
Create a new theme
|
||||
|
||||
### Synopsis
|
||||
|
||||
|
||||
Create a new theme (skeleton) called [name] in the current directory.
|
||||
New theme is a skeleton. Please add content to the touched files. Add your
|
||||
name to the copyright line in the license and adjust the theme.toml file
|
||||
as you see fit.
|
||||
|
||||
```
|
||||
hugo new theme [name]
|
||||
```
|
||||
|
||||
### Options inherited from parent commands
|
||||
|
||||
```
|
||||
--config string config file (default is path/config.yaml|json|toml)
|
||||
--log Enable Logging
|
||||
--logFile string Log File path (if set, logging enabled automatically)
|
||||
-s, --source string filesystem path to read files relative from
|
||||
-v, --verbose verbose output
|
||||
--verboseLog verbose logging
|
||||
```
|
||||
|
||||
### SEE ALSO
|
||||
* [hugo new](/commands/hugo_new/) - Create new content for your site
|
||||
|
||||
###### Auto generated by spf13/cobra on 5-Oct-2016
|
||||
@@ -1,81 +0,0 @@
|
||||
---
|
||||
date: 2016-10-05T10:21:48+02:00
|
||||
title: "hugo server"
|
||||
slug: hugo_server
|
||||
url: /commands/hugo_server/
|
||||
---
|
||||
## hugo server
|
||||
|
||||
A high performance webserver
|
||||
|
||||
### Synopsis
|
||||
|
||||
|
||||
Hugo provides its own webserver which builds and serves the site.
|
||||
While hugo server is high performance, it is a webserver with limited options.
|
||||
Many run it in production, but the standard behavior is for people to use it
|
||||
in development and use a more full featured server such as Nginx or Caddy.
|
||||
|
||||
'hugo server' will avoid writing the rendered and served content to disk,
|
||||
preferring to store it in memory.
|
||||
|
||||
By default hugo will also watch your files for any changes you make and
|
||||
automatically rebuild the site. It will then live reload any open browser pages
|
||||
and push the latest content to them. As most Hugo sites are built in a fraction
|
||||
of a second, you will be able to save and see your changes nearly instantly.
|
||||
|
||||
```
|
||||
hugo server
|
||||
```
|
||||
|
||||
### Options
|
||||
|
||||
```
|
||||
--appendPort append port to baseurl (default true)
|
||||
-b, --baseURL string hostname (and path) to the root, e.g. http://spf13.com/
|
||||
--bind string interface to which the server will bind (default "127.0.0.1")
|
||||
-D, --buildDrafts include content marked as draft
|
||||
-E, --buildExpired include expired content
|
||||
-F, --buildFuture include content with publishdate in the future
|
||||
--cacheDir string filesystem path to cache directory. Defaults: $TMPDIR/hugo_cache/
|
||||
--canonifyURLs if true, all relative URLs will be canonicalized using baseURL
|
||||
--cleanDestinationDir Remove files from destination not found in static directories
|
||||
-c, --contentDir string filesystem path to content directory
|
||||
-d, --destination string filesystem path to write files to
|
||||
--disable404 Do not render 404 page
|
||||
--disableLiveReload watch without enabling live browser reload on rebuild
|
||||
--disableRSS Do not build RSS files
|
||||
--disableSitemap Do not build Sitemap file
|
||||
--forceSyncStatic Copy all files when static is changed.
|
||||
--i18n-warnings Print missing translations
|
||||
--ignoreCache Ignores the cache directory
|
||||
-l, --layoutDir string filesystem path to layout directory
|
||||
--meminterval string interval to poll memory usage (requires --memstats), valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h". (default "100ms")
|
||||
--memstats string log memory usage to this file
|
||||
--noChmod Don't sync permission mode of files
|
||||
--noTimes Don't sync modification time of files
|
||||
--pluralizeListTitles Pluralize titles in lists using inflect (default true)
|
||||
-p, --port int port on which the server will listen (default 1313)
|
||||
--preserveTaxonomyNames Preserve taxonomy names as written ("Gérard Depardieu" vs "gerard-depardieu")
|
||||
--renderToDisk render to Destination path (default is render to memory & serve from there)
|
||||
-s, --source string filesystem path to read files relative from
|
||||
--stepAnalysis display memory and timing of different steps of the program
|
||||
-t, --theme string theme to use (located in /themes/THEMENAME/)
|
||||
--uglyURLs if true, use /filename.html instead of /filename/
|
||||
-w, --watch watch filesystem for changes and recreate as needed (default true)
|
||||
```
|
||||
|
||||
### Options inherited from parent commands
|
||||
|
||||
```
|
||||
--config string config file (default is path/config.yaml|json|toml)
|
||||
--log Enable Logging
|
||||
--logFile string Log File path (if set, logging enabled automatically)
|
||||
-v, --verbose verbose output
|
||||
--verboseLog verbose logging
|
||||
```
|
||||
|
||||
### SEE ALSO
|
||||
* [hugo](/commands/hugo/) - hugo builds your site
|
||||
|
||||
###### Auto generated by spf13/cobra on 5-Oct-2016
|
||||
@@ -1,35 +0,0 @@
|
||||
---
|
||||
date: 2016-10-05T10:21:48+02:00
|
||||
title: "hugo undraft"
|
||||
slug: hugo_undraft
|
||||
url: /commands/hugo_undraft/
|
||||
---
|
||||
## hugo undraft
|
||||
|
||||
Undraft changes the content's draft status from 'True' to 'False'
|
||||
|
||||
### Synopsis
|
||||
|
||||
|
||||
Undraft changes the content's draft status from 'True' to 'False'
|
||||
and updates the date to the current date and time.
|
||||
If the content's draft status is 'False', nothing is done.
|
||||
|
||||
```
|
||||
hugo undraft path/to/content
|
||||
```
|
||||
|
||||
### Options inherited from parent commands
|
||||
|
||||
```
|
||||
--config string config file (default is path/config.yaml|json|toml)
|
||||
--log Enable Logging
|
||||
--logFile string Log File path (if set, logging enabled automatically)
|
||||
-v, --verbose verbose output
|
||||
--verboseLog verbose logging
|
||||
```
|
||||
|
||||
### SEE ALSO
|
||||
* [hugo](/commands/hugo/) - hugo builds your site
|
||||
|
||||
###### Auto generated by spf13/cobra on 5-Oct-2016
|
||||
@@ -1,33 +0,0 @@
|
||||
---
|
||||
date: 2016-10-05T10:21:48+02:00
|
||||
title: "hugo version"
|
||||
slug: hugo_version
|
||||
url: /commands/hugo_version/
|
||||
---
|
||||
## hugo version
|
||||
|
||||
Print the version number of Hugo
|
||||
|
||||
### Synopsis
|
||||
|
||||
|
||||
All software has versions. This is Hugo's.
|
||||
|
||||
```
|
||||
hugo version
|
||||
```
|
||||
|
||||
### Options inherited from parent commands
|
||||
|
||||
```
|
||||
--config string config file (default is path/config.yaml|json|toml)
|
||||
--log Enable Logging
|
||||
--logFile string Log File path (if set, logging enabled automatically)
|
||||
-v, --verbose verbose output
|
||||
--verboseLog verbose logging
|
||||
```
|
||||
|
||||
### SEE ALSO
|
||||
* [hugo](/commands/hugo/) - hugo builds your site
|
||||
|
||||
###### Auto generated by spf13/cobra on 5-Oct-2016
|
||||
@@ -1,110 +0,0 @@
|
||||
---
|
||||
aliases:
|
||||
- /doc/contributing/
|
||||
- /meta/contributing/
|
||||
lastmod: 2015-02-12
|
||||
date: 2013-07-01
|
||||
menu:
|
||||
main:
|
||||
parent: community
|
||||
next: /tutorials/automated-deployments
|
||||
prev: /community/mailing-list
|
||||
title: Contributing to Hugo
|
||||
weight: 30
|
||||
---
|
||||
|
||||
All contributions to Hugo are welcome. Whether you want to scratch an itch or simply contribute to the project, feel free to pick something from the [roadmap]({{< relref "meta/roadmap.md" >}}) or contact [spf13](http://spf13.com/) about what may make sense to do next.
|
||||
|
||||
You should fork the project and make your changes. *We encourage pull requests to discuss code changes.*
|
||||
|
||||
|
||||
When you're ready to create a pull request, be sure to:
|
||||
|
||||
* Have test cases for the new code. If you have questions about how to do it, please ask in your pull request.
|
||||
* Run `go fmt`.
|
||||
* Squash your commits into a single commit. `git rebase -i`. It's okay to force update your pull request.
|
||||
* Make sure `go test ./...` passes, and `go build` completes. Our [Travis CI loop](https://travis-ci.org/spf13/hugo) will catch most things that are missing. The exception: Windows. We run on Windows from time to time, but if you have access, please check on a Windows machine too.
|
||||
|
||||
## Contribution Overview
|
||||
|
||||
We wrote a [detailed guide]({{< relref "tutorials/how-to-contribute-to-hugo.md" >}}) for newcomers that guides you step by step to your first contribution. If you are more experienced, follow the guide below.
|
||||
|
||||
# Building from source
|
||||
|
||||
## Clone locally (for contributors):
|
||||
|
||||
git clone https://github.com/spf13/hugo
|
||||
cd hugo
|
||||
go get
|
||||
|
||||
Because Go expects all of your libraries to be found in either
|
||||
`$GOROOT` or `$GOPATH`, it's helpful to symlink the project to one
|
||||
of the following paths:
|
||||
|
||||
* `ln -s /path/to/your/hugo $GOPATH/src/github.com/spf13/hugo`
|
||||
* `ln -s /path/to/your/hugo $GOROOT/src/pkg/github.com/spf13/hugo`
|
||||
|
||||
## Running Hugo
|
||||
|
||||
cd /path/to/hugo
|
||||
go install github.com/spf13/hugo/hugo
|
||||
go run main.go
|
||||
|
||||
## Building Hugo
|
||||
|
||||
cd /path/to/hugo
|
||||
go build -o hugo main.go
|
||||
mv hugo /usr/local/bin/
|
||||
|
||||
|
||||
# Showcase additions
|
||||
|
||||
You got your new website running and it's powered by Hugo? Great. You can add your website with a few steps to the [showcase](/showcase/).
|
||||
|
||||
First, make sure that you created a [fork](https://help.github.com/articles/fork-a-repo/) of Hugo on Github and cloned your fork on your local computer. Next, create a separate branch for your additions:
|
||||
|
||||
```
|
||||
# You can choose a different descriptive branch name if you like
|
||||
git checkout -b showcase-addition
|
||||
```
|
||||
|
||||
Let's create a new document that contains some metadata of your homepage. Replace `example` in the following examples with something unique like the name of your website. Inside the terminal enter the following commands:
|
||||
|
||||
```
|
||||
cd docs
|
||||
hugo new showcase/example.md
|
||||
```
|
||||
|
||||
You should find the new file at `content/showcase/example.md`. Open it in an editor. The file should contain a frontmatter with predefined variables like below:
|
||||
|
||||
```
|
||||
---
|
||||
date: 2016-02-12T21:01:18+01:00
|
||||
description: ""
|
||||
license: ""
|
||||
licenseLink: ""
|
||||
sitelink: http://spf13.com/
|
||||
sourceLink: https://github.com/spf13/spf13.com
|
||||
tags:
|
||||
- personal
|
||||
- blog
|
||||
thumbnail: /img/spf13-tn.jpg
|
||||
title: example
|
||||
---
|
||||
```
|
||||
|
||||
Add at least values for `sitelink`, `title`, `description` and a path for `thumbnail`.
|
||||
|
||||
Furthermore, we need to create the thumbnail of your website. **It's important that the thumbnail has the required dimensions of 600px by 400px.** Give your thumbnail a name like `example-tn.png`. Save it under `docs/static/img/`.
|
||||
|
||||
Check a last time that everything works as expected. Start Hugo's built-in server in order to inspect your local copy of the showcase in the browser:
|
||||
|
||||
hugo server
|
||||
|
||||
If everything looks fine, we are ready to commit your additions. For the sake of best practices, please make sure that your commit follows our [code contribution guideline](https://github.com/spf13/hugo#code-contribution-guideline).
|
||||
|
||||
git commit -m"docs: Add example.com to the showcase"
|
||||
|
||||
Last but not least, we're ready to create a [pull request](https://github.com/spf13/hugo/compare).
|
||||
|
||||
Don't forget to accept the contributor license agreement. Click on the yellow badge in the automatically added comment in the pull request.
|
||||
@@ -1,51 +0,0 @@
|
||||
---
|
||||
lastmod: 2015-05-25
|
||||
date: 2013-07-01
|
||||
menu:
|
||||
main:
|
||||
parent: community
|
||||
next: /community/contributing
|
||||
prev: /extras/urls
|
||||
title: Mailing List
|
||||
weight: 10
|
||||
---
|
||||
|
||||
## Discussion Forum
|
||||
|
||||
Hugo has its own [discussion forum](http://discuss.gohugo.io/) powered by [Discourse](http://www.discourse.org/).
|
||||
|
||||
Please use this for all discussions, questions, etc.
|
||||
|
||||
## Mailing List
|
||||
|
||||
Hugo has two mailing lists:
|
||||
|
||||
### Announcements
|
||||
Very low traffic. Only releases will be emailed here.
|
||||
|
||||
https://groups.google.com/forum/#!forum/hugo-announce
|
||||
|
||||
### Discussion (Archive)
|
||||
|
||||
**This has been replaced with the [Hugo discussion forum](http://discuss.gohugo.io/).**
|
||||
|
||||
It is available for archival purposes.
|
||||
|
||||
https://groups.google.com/forum/#!forum/hugo-discuss
|
||||
|
||||
|
||||
## Other Resources
|
||||
|
||||
### GoNuts
|
||||
|
||||
For general Go questions or discussion please refer to the Go mailing list.
|
||||
|
||||
https://groups.google.com/forum/#!forum/golang-nuts
|
||||
|
||||
### GitHub Issues
|
||||
|
||||
https://github.com/spf13/hugo/issues
|
||||
|
||||
### Twitter
|
||||
|
||||
Hugo doesn't have its own Twitter handle, but feel free to tweet [@spf13](http://twitter.com/spf13).
|
||||
@@ -1,135 +0,0 @@
|
||||
---
|
||||
lastmod: 2016-10-10
|
||||
date: 2014-03-24T20:00:00Z
|
||||
linktitle: Press
|
||||
notoc: true
|
||||
title: Press, Blogs and Media Coverage
|
||||
weight: 20
|
||||
---
|
||||
|
||||
### Help keep this list up to date
|
||||
|
||||
Know of a post, article or tutorial on Hugo? [Add it to this list](https://github.com/spf13/hugo/edit/master/docs/content/community/press.md).
|
||||
|
||||
## Press and Articles
|
||||
|
||||
Hugo has been featured in the following Blog Posts, Press and Media.
|
||||
|
||||
|
||||
| Title | Author | Date |
|
||||
| ------ | ------ | -----: |
|
||||
| [How To Dynamically Use Google Fonts In A Hugo Website](https://stoned.io/web-development/hugo/How-To-Dynamically-Use-Google-Fonts-In-A-Hugo-Website/) | Hash Borgir | 27 Oct 2016 |
|
||||
| [Embedding Facebook In A Hugo Template](https://stoned.io/web-development/hugo/Embedding-Facebook-In-A-Hugo-Template/) | Hash Borgir | 22 Oct 2016 |
|
||||
| [通过 Gitlab-cl 将 Hugo blog 自动部署至 GitHub](https://zetaoyang.github.io/post/2016/10/17/gitlab-cl.html) <small>(Chinese, Continious integration)</small> |Zetao Yang | 17 Oct 2016 |
|
||||
| [A Step-by-Step Guide: Hugo on Netlify](https://www.netlify.com/blog/2016/09/21/a-step-by-step-guide-hugo-on-netlify/) | Eli Williamson | 21 Sep 2016 |
|
||||
| [Building our site: From Django & Wordpress to a static generator (Part I)](https://tryolabs.com/blog/2016/09/20/building-our-site-django-wordpress-to-static-part-i/) | Alan Descoins | 20 Sep 2016 |
|
||||
| [Webseitenmaschine - Statische Websites mit Hugo erzeugen](http://www.heise.de/ct/ausgabe/2016-12-Statische-Websites-mit-Hugo-erzeugen-3211704.html) <small>(German, $)</small> | Christian Helmbold | 27 May 2016 |
|
||||
| [Cómo hacer sitios web estáticos con Hugo y Go - Platzi](https://www.youtube.com/watch?v=qaXXpdiCHXE) <small>(Video tutorial)</small> | Verónica López | 6 Apr 2016 |
|
||||
| [CDNOverview: A CDN comparison site made with Hugo](https://www.cloakfusion.com/cdnoverview-cdn-comparison-site-made-hugo/) | Thijs de Zoete | 23 Feb 2016 |
|
||||
| [Hugo: A Modern WebSite Engine That Just Works](https://github.com/shekhargulati/52-technologies-in-2016/blob/master/07-hugo/README.md) | Shekhar Gulati | 14 Feb 2016 |
|
||||
| [Minify Hugo Generated HTML](http://ratson.name/blog/minify-hugo-generated-html/) | Ratson | 2 Feb 2016 |
|
||||
| [Static site generators: el futuro de las webs estáticas<br>(Hugo, Jekyll, Flask y otros)](http://sitelabs.es/static-site-generators-futuro-las-webs-estaticas/) | Eneko Sarasola | 9 Jan 2016 |
|
||||
| [Writing a Lambda Function for Hugo](https://blog.jolexa.net/post/writing-a-lambda-function-for-hugo/) | Jeremy Olexa | 1 Jan 2016 |
|
||||
| [Ein Blog mit Hugo erstellen - Tutorial](http://privat.albicker.org/blog/tags/hugo/) <small>(Deutsch/German)</small> | Bernhard Albicker | 30 Dec 2015 |
|
||||
| [How to host Hugo static website generator on AWS Lambda](http://bezdelev.com/post/hugo-aws-lambda-static-website/) | Ilya Bezdelev | 15 Dec 2015 |
|
||||
| [Migrating from Pelican to Hugo](http://www.softinio.com/post/migrating-from-pelican-to-hugo/) | Salar Rahmanian | 29 Nov 2015 |
|
||||
| [Hugo + Uberspace + Git = Hubergit — eine Anleitung (German)](https://harms-ensink.name/post/hubergit/) | Christoph Harms-Ensink | 24 Nov 2015 |
|
||||
| [Static Website Generators Reviewed: Jekyll, Middleman, Roots, Hugo](http://www.smashingmagazine.com/2015/11/static-website-generators-jekyll-middleman-roots-hugo-review/) | <div style="line-height: 100%">Mathias Biilmann Christensen</div> | 16 Nov 2015 |
|
||||
| [How To Deploy a Hugo Site to Production with Git Hooks on Ubuntu 14.04](https://www.digitalocean.com/community/tutorials/how-to-deploy-a-hugo-site-to-production-with-git-hooks-on-ubuntu-14-04) | Justin Ellingwood | 12 Nov 2015 |
|
||||
| [How To Install and Use Hugo, a Static Site Generator, on Ubuntu 14.04](https://www.digitalocean.com/community/tutorials/how-to-install-and-use-hugo-a-static-site-generator-on-ubuntu-14-04) | Justin Ellingwood | 9 Nov 2015 |
|
||||
| [Switching from Wordpress to Hugo](http://justinfx.com/2015/11/08/switching-from-wordpress-to-hugo/) | Justin Israel | 8 Nov 2015 |
|
||||
| [Hands-on Experience with Hugo as a Static Site Generator](http://usersnap.com/blog/hands-on-experience-with-hugo-static-site-generator/) | Thomas Peham | 15 Oct 2015 |
|
||||
| [Statische Webseites mit Hugo erstellen/Vortrag mit Foliensatz (deutsch)](http://sfd.koelnerlinuxtreffen.de/2015/HaraldWeidner/) | Harald Weidner | 19 Sep 2015 |
|
||||
| [Moving from WordPress to Hugo](http://abhipandey.com/2015/09/moving-to-hugo/) | Abhishek Pandey | 15 Sep 2015 |
|
||||
| [<span lang="zh-CN">通过webhook将Hugo自动部署至GitHub Pages和GitCafe Pages</span> <small>(Automated deployment)</small>](http://blog.coderzh.com/2015/09/13/use-webhook-automated-deploy-hugo/) | CoderZh | 13 Sep 2015 |
|
||||
| [<span lang="zh-CN">使用hugo搭建个人博客站点</span> <small>(Using Hugo to build a personal blog site)</small>](http://blog.coderzh.com/2015/08/29/hugo/) | CoderZh | 29 Aug 2015 |
|
||||
| [Good-Bye Wordpress, Hello Hugo!](http://blog.arminhanisch.de/2015/08/blog-migration-zu-hugo/) <small>(German)</small> | Armin Hanisch | 18 Aug 2015 |
|
||||
| [Static Site E-Commerce: Integrating Snipcart with Hugo](https://snipcart.com/blog/snipcart-hugo-integration) | Francis Tremblay | 13 Aug 2015 |
|
||||
| [Générer votre site web statique avec Hugo <small>(Generate your static site with Hugo)<small>](http://www.linux-pratique.com/?p=191) | Benoît Benedetti | 26 June 2015 |
|
||||
| [<span lang="ja">Hugo向けの新しいテーマを作った</span> <small>(I created a new theme for Hugo)<small>](http://yet.unresolved.xyz/blog/2015/06/20/making-new-theme-robust-for-hugo/) | Daisuke Tsuji | 20 June 2015 |
|
||||
| [Hugo - Gerando um site com conteúdo estático. (Portuguese Brazil)](http://blog.ffrizzo.com/posts/hugo/) | Fabiano Frizzo | 2 Jun 2015 |
|
||||
| [An Introduction to Static Site Generators](http://davidwalsh.name/introduction-static-site-generators) | Eduardo Bouças | 20 May 2015 |
|
||||
| [Hugo Still Rules](http://cheekycoder.com/2015/05/hugo-still-rules/) | Cheeky Coder | 18 May 2015 |
|
||||
| [hugo - Static Site Generator](http://gscacco.github.io/post/hugo/) | G Scaccoio | 4 May 2015 |
|
||||
| [<span lang="ja">WindowsでHugoを使う</span>](http://ureta.net/2015/05/hugo-on-windows/) | <span lang="ja">うれ太郎</span> | 1 May 2015 |
|
||||
| [<span lang="ja">Hugoのshortcodesを用いてサイトにスライドなどを埋め込む</span>](http://blog.yucchiy.com/2015/04/29/hugo-shortcode/) | Yucchiy | 29 Apr 2015 |
|
||||
| [<span lang="ja">HugoとCircleCIでGitHub PagesにBlogを公開してみたら超簡単だった</span>](http://hori-ryota.github.io/blog/create-blog-with-hugo-and-circleci/) | Hori Ryota | 17 Apr 2015 |
|
||||
| [How to build a mobile friendly website Part 2 - Ok to Go](http://jbrodriguez.io/mobile-friendly-website-2/) | Juan B. Rodriguez | 13 Apr 2015 |
|
||||
| [10 Best Static Site Generators](http://beebom.com/2015/04/best-static-site-generators) | Aniruddha Mysore | 6 Apr 2015 |
|
||||
| [Goodbye WordPress; Hello Hugo](http://willwarren.com/2015/04/05/goodbye-wordpress-hello-hugo/) | Will Warren | 5 Apr 2015 |
|
||||
| [Static Websites with Hugo on Google Cloud Storage](http://www.moxie.io/post/static-websites-with-hugo-on-google-cloud-storage/) | Moxie Input/Output | 2 Apr 2015 |
|
||||
| [De nuevo iniciando un blog](http://alvarolizama.net/blog/denuevo-iniciando-un-blog/) | Alvaro Lizama | 29 Mar 2015 |
|
||||
| [We moved our blog from Posthaven to Hugo after only three posts. Why?](http://blog.hypriot.com/post/moved-from-posthaven-to-hugo/) | Hypriot | 27 Mar 2015 |
|
||||
| [Hugo is cool](http://tnt.wicast.tk/2015/03/23/hugo-is-cool/) <small>(<span lang="zh-CN">中文</span> Chinese)</small> | wicast | 23 Mar 2015 |
|
||||
| [Top Static Site Generators in 2015](http://superdevresources.com/static-site-generators-2015/) | Kanishk Kunal | 12 Mar 2015 |
|
||||
| [Moving to Hugo](http://abiosoft.com/moving-to-hugo/) | Abiola Ibrahim | 8 Mar 2015 |
|
||||
| [<span lang="ja">Hugoで試行錯誤する</span> - log](http://deprode.net/log/logs/first/) | Deprode | 28 Feb 2015 |
|
||||
| [Migrating a blog (yes, this one!) from Wordpress to Hugo](http://justindunham.net/migrating-from-wordpress-to-hugo/) | Justin Dunham | 13 Feb 2015 |
|
||||
| [<span lang="ja">blogをoctopressからHugoに乗り換えたメモ</span>](http://blog.jigyakkuma.org/2015/02/11/hugo/) | jigyakkuma | 11 Feb 2015 |
|
||||
| [<span lang="ja">Hugoでブログをつくった</span>](http://porgy13.github.io/post/new-hugo-blog/) | porgy13 | 7 Feb 2015 |
|
||||
| [<span lang="ja">Hugoにブログを移行した</span>](http://keichi.net/post/first/) | Keichi Takahashi | 4 Feb 2015 |
|
||||
| [<span lang="zh-CN">Hugo静态网站生成器中文教程</span>](http://nanshu.wang/post/2015-01-31/) | Nanshu Wang | 31 Jan 2015 |
|
||||
| [<span lang="ja">Hugo + Github Pages + Wercker CI = ¥0(無料)<br>でコマンド 1 発(自動化)でサイト<br>・ブログを公開・運営・分析・収益化</span>](http://qiita.com/yoheimuta/items/8a619cac356bed89a4c9) | Yohei Yoshimuta | 31 Jan 2015 |
|
||||
| [Running Hugo websites on anynines](http://blog.anynines.com/running-hugo-websites-on-anynines/) | Julian Weber | 30 Jan 2015 |
|
||||
| [MiddlemanからHugoへ移行した](http://re-dzine.net/2015/01/hugo/) | Haruki Konishi | 21 Jan 2015 |
|
||||
| [WordPress から Hugo に乗り換えました](http://rakuishi.com/archives/wordpress-to-hugo/) | rakuishi | 20 Jan 2015 |
|
||||
| [HUGOを使ってサイトを立ち上げる方法](http://qiita.com/syui/items/869538099551f24acbbf) | Syui | 17 Jan 2015 |
|
||||
| [<span lang="ja">Jekyllが許されるのは小学生までだよね</span>](http://t32k.me/mol/log/hugo/) | Ishimoto Koji | 16 Jan 2015 |
|
||||
| [Getting started with Hugo](http://anthonyfok.org/post/getting-started-with-hugo/) | Anthony Fok | 12 Jan 2015 |
|
||||
| [<span lang="zh-CN">把这个博客静态化了</span> <small>(Migrate to Hugo)</small>](http://lich-eng.com/2015/01/03/migrate-to-hugo/) | Li Cheng | 3 Jan 2015 |
|
||||
| [My Hugo Experiment](http://tilde.club/~jbaty/2014/12/2014-12-31-my-hugo-experiment/) | Jack Baty | 31 Dec 2014 |
|
||||
| [Porting my blog with Hugo](http://blog.srackham.com/posts/porting-my-blog-with-hugo/) | Stuart Rackham | 30 Dec 2014 |
|
||||
| [Hugoを使ってみたときのメモ](http://machortz.github.io/posts/usinghugo/) | Machortz | 29 Dec 2014 |
|
||||
| [OctopressからHugoへ移行した](http://deeeet.com/writing/2014/12/25/hugo/) | Taichi Nakashima | 25 Dec 2014 |
|
||||
| [Hugo로 Github에 블로그 호스팅하기](http://cdpython.github.io/post/go/hugo/hugo-github/) | CD Python | 25 Dec 2014 |
|
||||
| [Migrating to Hugo From Octopress](http://nathanleclaire.com/blog/2014/12/22/migrating-to-hugo-from-octopress/) | Nathan LeClaire | 22 Dec 2014 |
|
||||
| [Dynamic Pages with GoHugo.io](http://cyrillschumacher.com/2014/12/21/dynamic-pages-with-gohugo.io/) | Cyrill Schumacher | 21 Dec 2014 |
|
||||
| [6 Static Blog Generators That Aren’t Jekyll](http://www.sitepoint.com/6-static-blog-generators-arent-jekyll/) | David Turnbull | 8 Dec 2014 |
|
||||
| [Travel Blogging Setup](http://www.stou.dk/2014/11/travel-blogging-setup/) | Rasmus Stougaard | 23 Nov 2014 |
|
||||
| [Hosting A Hugo Website Behind Nginx](http://www.bigbeeconsultants.co.uk/blog/hosting-hugo-website-behind-nginx) | Rick Beton | 20 Nov 2014 |
|
||||
| [<span lang="zh-CN">使用Hugo搭建免费个人Blog</span> <small>(How to use Hugo)</small>](http://ulricqin.com/post/how-to-use-hugo/) | Ulric Qin <span lang="zh-CN">秦晓辉</span> | 11 Nov 2014 |
|
||||
| [Built in Speed and Built for Speed by Hugo](http://cheekycoder.com/2014/10/built-for-speed-by-hugo/) | Cheeky Coder | 30 Oct 2014 |
|
||||
| [hugo, syncthing](http://fredix.ovh/2014/10/hugo-syncthing/) | Frédéric Logier | 13 Oct 2014 |
|
||||
| [Hugo para crear sitios web estáticos](http://www.webbizarro.com/noticias/1076/hugo-para-crear-sitios-web-estaticos/) | Web Bizarro | 19 Aug 2014 |
|
||||
| [Going with hugo](http://www.markuseliasson.se/article/going-with-hugo/) | Markus Eliasson | 18 Aug 2014 |
|
||||
| [Benchmarking Jekyll, Hugo and Wintersmith](http://fredrikloch.me/post/2014-08-12-Jekyll-and-its-alternatives-from-a-site-generation-point-of-view/) | Fredrik Loch | 12 Aug 2014 |
|
||||
| [Goodbye Octopress, Hello Hugo!](http://andreimihu.com/blog/2014/08/11/goodbye-octopress-hello-hugo/) | Andrei Mihu | 11 Aug 2014 |
|
||||
| [Beautiful sites for Open Source projects](http://beautifulopen.com/2014/08/09/hugo/) | Beautiful Open | 9 Aug 2014 |
|
||||
| [Hugo: Beyond the Defaults](http://npf.io/2014/08/hugo-beyond-the-defaults/) | Nate Finch | 8 Aug 2014 |
|
||||
| [First Impressions of Hugo](https://peteraba.com/blog/first-impressions-of-hugo/) | Peter Aba | 6 Aug 2014 |
|
||||
| [New Site Workflow](http://vurt.co.uk/post/new_website/) | Giles Paterson | 5 Aug 2014 |
|
||||
| [How I Learned to Stop Worrying and Love the (Static) Web](http://cognition.ca/post/about-hugo/) | Joshua McKenty | 4 Aug 2014 |
|
||||
| [Hugo - Static Site Generator](http://kenwoo.io/blog/hugo---static-site-generator/) | Kenny Woo | 3 Aug 2014 |
|
||||
| [Hugo Is Friggin' Awesome](http://npf.io/2014/08/hugo-is-awesome/) | Nate Finch | 1 Aug 2014 |
|
||||
| [<span lang="zh-CN">再次搬家</span> <small>(Move from WordPress to Hugo)</small>](http://www.chingli.com/misc/move-from-wordpress-to-hugo/) | <span lang="zh-CN">青砾</span> (chingli) | 12 July 2014 |
|
||||
| [Embedding Gists in Hugo](http://danmux.com/posts/embedded_gists/) | Dan Mull | 5 July 2014 |
|
||||
| [An Introduction To Hugo](http://www.cirrushosting.com/web-hosting-blog/an-introduction-to-hugo/) | Dan Silber | 1 July 2014 |
|
||||
| [Moving to Hugo](http://danmux.com/posts/hugo_based_blog/) | Dan Mull | 29 May 2014 |
|
||||
| [<span lang="zh-CN">开源之静态站点生成器排行榜</span><br><small>(Leaderboard of open-source static website generators)</small>](http://code.csdn.net/news/2819909) | CSDN.net | 23 May 2014 |
|
||||
| [How I deploy this site using Fabric](http://carlorat.me/quote/fabric/) | Carlo Ratam | 21 May 2014 |
|
||||
| [Finally, a satisfying and effective blog setup](http://michaelwhatcott.com/now-powered-by-hugo/) | Michael Whatcott | 20 May 2014 |
|
||||
| [Hugo from scratch](http://zackofalltrades.com/notes/2014/05/hugo-from-scratch/) | Zack Williams | 18 May 2014 |
|
||||
| [Why I switched away from Jekyll](http://www.jakejanuzelli.com/why-I-switched-away-from-jekyll/) | Jake Januzelli | 10 May 2014 |
|
||||
| [Welcome our new blog](http://blog.ninya.io/posts/welcome-our-new-blog/) | Ninya.io | 11 Apr 2014 |
|
||||
| [Mission Not Accomplished](http://johnsto.co.uk/blog/mission-not-accomplished/) | Dave Johnston | 3 Apr 2014 |
|
||||
| [Hugo - A Static Site Builder in Go](http://deepfriedcode.com/post/hugo/) | Deep Fried Code | 30 Mar 2014 |
|
||||
| [Adventures in Angular Podcast](http://devchat.tv/adventures-in-angular/003-aia-gdes) | Matias Niemela | 28 Mar 2014 |
|
||||
| [Hugo](http://bra.am/post/hugo/) | bra.am | 23 Mar 2014 |
|
||||
| [Converting Blogger To Markdown](http://trishagee.github.io/project/atom-to-hugo/) | Trisha Gee | 20 Mar 2014 |
|
||||
| [Moving to Hugo Static Web Pages](http://tepid.org/tech/hugo-web/) | Tobias Weingartner | 16 Mar 2014 |
|
||||
| [Hugo and GitHub Pages](http://spencerlyon.com/blog/2014/creating-the-site/) | Spencer Lyon | 15 Mar 2014 |
|
||||
| [New Blog Engine: Hugo](https://blog.afoolishmanifesto.com/posts/hugo/) | fREW Schmidt | 15 Mar 2014 |
|
||||
| [Hugo + gulp.js = Huggle](http://ktmud.github.io/huggle/en/intro/) ([English](http://ktmud.github.io/huggle/en/intro/), [<span lang="zh-CN">中文</span>](http://ktmud.github.io/huggle/zh/intro/)) | Jesse Yang <span lang="zh-CN">杨建超</span> | 8 Mar 2014 |
|
||||
| [Powered by Hugo](http://kieranhealy.org/blog/archives/2014/02/24/powered-by-hugo/) | Kieran Healy | 24 Feb 2014 |
|
||||
| [<span lang="ja">静的サイトを素早く構築するために<br>GoLangで作られたジェネレータHugo</span>](http://hamasyou.com/blog/2014/02/21/hugo/) | <div lang="ja" style="line-height: 1.1;">Shogo Hamada<br>濱田章吾</div> | 21 Feb 2014 |
|
||||
| [Latest Roundup of Useful Tools For Developers](http://codegeekz.com/latest-roundup-of-useful-tools-for-developers/) | CodeGeekz | 13 Feb 2014 |
|
||||
| [Hugo: Static Site Generator written in Go](http://www.braveterry.com/2014/02/06/hugo-static-site-generator-written-in-go/) | Brave Terry | 6 Feb 2014 |
|
||||
| [10 Useful HTML5 Tools for Web Designers and Developers](http://designdizzy.com/10-useful-html5-tools-for-web-designers-and-developers/) | Design Dizzy | 4 Feb 2014 |
|
||||
| [Hugo – Fast, Flexible Static Site Generator](http://cube3x.com/hugo-fast-flexible-static-site-generator/) | Joby Joseph | 18 Jan 2014 |
|
||||
| [Hugo: A new way to build static website](http://www.w3update.com/opensource/hugo-a-new-way-to-build-static-website.html) | w3update | 17 Jan 2014 |
|
||||
| [Xaprb now uses Hugo](http://xaprb.com/blog/2014/01/15/using-hugo/) | Baron Schwartz | 15 Jan 2014 |
|
||||
| [New jQuery Plugins And Resources That Web Designers Need](http://www.designyourway.net/blog/resources/new-jquery-plugins-and-resources-that-web-designers-need/) | Design Your Way | 2014 |
|
||||
| [On Blog Construction](http://alexla.sh/post/on-blog-construction/) | Alexander Lash | 27 Dec 2013 |
|
||||
| [Hugo](http://onethingwell.org/post/69070926608/hugo) | One Thing Well | 5 Dec 2013 |
|
||||
| [In Praise Of Hugo](http://sound-guru.com/blog/post/hello-world/) | sound-guru.com | 19 Oct 2013 |
|
||||
| [Hosting a blog on S3 and Cloudfront](http://www.danesparza.net/2013/07/hosting-a-blog-on-s3-and-cloudfront/) | Dan Esparza | 24 July 2013 |
|
||||
@@ -1,150 +0,0 @@
|
||||
---
|
||||
lastmod: 2016-10-01
|
||||
date: 2014-05-14T02:13:50Z
|
||||
menu:
|
||||
main:
|
||||
parent: content
|
||||
next: /content/ordering
|
||||
prev: /content/types
|
||||
title: Archetypes
|
||||
weight: 50
|
||||
toc: true
|
||||
---
|
||||
|
||||
In Hugo v0.11, we introduced the concept of a content builder. Using the CLI
|
||||
command <code>hugo new <em>[path/to/my/content]</em></code>, an author could
|
||||
create an empty content file, with the date and title automatically defined in
|
||||
the front matter of the post. While this was a welcome feature, active writers
|
||||
need more flexibility.
|
||||
|
||||
When defining a custom content type, you can use an **archetype** as a way to
|
||||
define the default metadata for a new post of that type.
|
||||
|
||||
**Archetypes** are quite literally archetypal content files with pre-configured
|
||||
[front matter](/content/front-matter). An archetype will populate each new
|
||||
content file of a given type with any default metadata you've defined whenever
|
||||
you run the `hugo new` command.
|
||||
|
||||
## Example
|
||||
|
||||
### Step 1. Creating an archetype
|
||||
|
||||
In the following example scenario, suppose we have a blog with a single content
|
||||
type (blog post). Our imaginary blog will use ‘tags’ and ‘categories’ for its
|
||||
taxonomies, so let's create an archetype file with ‘tags’ and ‘categories’
|
||||
pre-defined:
|
||||
|
||||
#### archetypes/default.md
|
||||
|
||||
```toml
|
||||
+++
|
||||
tags = ["x", "y"]
|
||||
categories = ["x", "y"]
|
||||
+++
|
||||
```
|
||||
|
||||
> __CAVEAT:__ Some editors (e.g. Sublime, Emacs) do not insert an EOL (end-of-line) character at the end of the file (i.e. EOF). If you get a [strange EOF error](/troubleshooting/strange-eof-error/) when using `hugo new`, please open each archetype file (i.e. `archetypes/*.md`) and press <kbd>Enter</kbd> to type a carriage return after the closing `+++` or `---` as necessary.
|
||||
|
||||
|
||||
### Step 2. Using the archetype
|
||||
|
||||
Now, with `archetypes/default.md` in place, let's create a new post in the `post`
|
||||
section with the `hugo new` command:
|
||||
|
||||
$ hugo new post/my-new-post.md
|
||||
|
||||
Hugo will now create the file with the following contents:
|
||||
|
||||
#### content/post/my-new-post.md
|
||||
|
||||
```toml
|
||||
+++
|
||||
title = "my new post"
|
||||
date = "2015-01-12T19:20:04-07:00"
|
||||
tags = ["x", "y"]
|
||||
categories = ["x", "y"]
|
||||
+++
|
||||
```
|
||||
|
||||
We see that the `title` and `date` variables have been added, in addition to the
|
||||
`tags` and `categories` variables which were carried over from `archetype/default.md`.
|
||||
|
||||
Congratulations! We have successfully created an archetype and used it to
|
||||
quickly scaffold out a new post. But wait, what if we want to create some content
|
||||
that isn't exactly a blog post, like a profile for a musician? Let's see how
|
||||
using **archetypes** can help us out.
|
||||
|
||||
### Creating custom archetypes
|
||||
|
||||
Previously, we had created a new content type by adding a new subfolder to the
|
||||
content directory. In this case, its name would be `content/musician`. To begin
|
||||
using a `musician` archetype for each new `musician` post, we simply need to
|
||||
create a file named after the content type called `musician.md`, and put it in
|
||||
the `archetypes` directory, similar to the one below.
|
||||
|
||||
#### archetypes/musician.md
|
||||
|
||||
```toml
|
||||
+++
|
||||
name = ""
|
||||
bio = ""
|
||||
genre = ""
|
||||
+++
|
||||
```
|
||||
|
||||
Now, let's create a new musician.
|
||||
|
||||
$ hugo new musician/mozart.md
|
||||
|
||||
This time, Hugo recognizes our custom `musician` archetype and uses it instead of
|
||||
the default one. Take a look at the new `musician/mozart.md` post. You should see
|
||||
that the generated file's front matter now includes the variables `name`, `bio`,
|
||||
and `genre`.
|
||||
|
||||
#### content/musician/mozart.md
|
||||
|
||||
```toml
|
||||
+++
|
||||
title = "mozart"
|
||||
date = "2015-08-24T13:04:37+02:00"
|
||||
name = ""
|
||||
bio = ""
|
||||
genre = ""
|
||||
+++
|
||||
```
|
||||
|
||||
## Using a different front matter format
|
||||
|
||||
By default, the front matter will be created in the TOML format
|
||||
regardless of what format the archetype is using.
|
||||
|
||||
You can specify a different default format in your site-wide config file
|
||||
(e.g. `config.toml`) using the `MetaDataFormat` directive.
|
||||
Possible values are `"toml"`, `"yaml"` and `"json"`.
|
||||
|
||||
## Which archetype is being used
|
||||
|
||||
The following rules apply when creating new content:
|
||||
|
||||
* If an archetype with a filename matching the new post's [content type](/content/types) exists, it will be used.
|
||||
* If no match is found, `archetypes/default.md` will be used.
|
||||
* If neither is present and a theme is in use, then within the theme:
|
||||
* If an archetype with a filename that matches the content type being created, it will be used.
|
||||
* If no match is found, `archetypes/default.md` will be used.
|
||||
* If no archetype files are present, then the one that ships with Hugo will be used.
|
||||
|
||||
Hugo provides a simple archetype which sets the `title` (based on the
|
||||
file name) and the `date` in RFC 3339 format based on
|
||||
[`now()`](http://golang.org/pkg/time/#Now), which returns the current time.
|
||||
|
||||
> *Note: `hugo new` does not automatically add `draft = true` when the user
|
||||
> provides an archetype. This is by design, rationale being that
|
||||
> the archetype should set its own value for all fields.
|
||||
> `title` and `date`, which are dynamic and unique for each piece of content,
|
||||
> are the sole exceptions.*
|
||||
|
||||
The content type is automatically detected based on the file path passed to the
|
||||
Hugo CLI command <code>hugo new <em>[my-content-type/post-name]</em></code>. To
|
||||
override the content type for a new post, include the `--kind` flag during creation.
|
||||
|
||||
> *Note: if you wish to use archetypes that ship with a theme, the theme MUST be specified in your `config.toml`.*
|
||||
@@ -1,91 +0,0 @@
|
||||
---
|
||||
aliases:
|
||||
- /doc/example/
|
||||
lastmod: 2015-12-23
|
||||
date: 2013-07-01
|
||||
linktitle: Example
|
||||
menu:
|
||||
main:
|
||||
parent: content
|
||||
prev: /content/multilingual
|
||||
next: /themes/overview
|
||||
notoc: true
|
||||
title: Example Content File
|
||||
weight: 70
|
||||
---
|
||||
|
||||
Some things are better shown than explained. The following is a very basic example of a content file written in [Markdown](https://help.github.com/articles/github-flavored-markdown/):
|
||||
|
||||
**mysite/content/project/nitro.md → http://mysite.com/project/nitro.html**
|
||||
|
||||
With TOML front matter:
|
||||
|
||||
<pre><code class="language-toml">+++
|
||||
date = "2013-06-21T11:27:27-04:00"
|
||||
title = "Nitro: A quick and simple profiler for Go"
|
||||
description = "Nitro is a simple profiler for your Golang applications"
|
||||
tags = [ "Development", "Go", "profiling" ]
|
||||
topics = [ "Development", "Go" ]
|
||||
slug = "nitro"
|
||||
project_url = "https://github.com/spf13/nitro"
|
||||
+++
|
||||
</code><code class="language-markdown"># Nitro
|
||||
|
||||
Quick and easy performance analyzer library for [Go](http://golang.org/).
|
||||
|
||||
## Overview
|
||||
|
||||
Nitro is a quick and easy performance analyzer library for Go.
|
||||
It is useful for comparing A/B against different drafts of functions
|
||||
or different functions.
|
||||
|
||||
## Implementing Nitro
|
||||
|
||||
Using Nitro is simple. First, use `go get` to install the latest version
|
||||
of the library.
|
||||
|
||||
$ go get github.com/spf13/nitro
|
||||
|
||||
Next, include nitro in your application.
|
||||
</code></pre>
|
||||
|
||||
You may also use the equivalent YAML front matter:
|
||||
|
||||
```yaml
|
||||
---
|
||||
lastmod: 2015-12-23
|
||||
date: "2013-06-21T11:27:27-04:00"
|
||||
title: "Nitro: A quick and simple profiler for Go"
|
||||
description: "Nitro is a simple profiler for your Go lang applications"
|
||||
tags: [ "Development", "Go", "profiling" ]
|
||||
topics: [ "Development", "Go" ]
|
||||
slug: "nitro"
|
||||
project_url: "https://github.com/spf13/nitro"
|
||||
---
|
||||
```
|
||||
|
||||
`nitro.md` would be rendered as follows:
|
||||
|
||||
> # Nitro
|
||||
>
|
||||
> Quick and easy performance analyzer library for [Go](http://golang.org/).
|
||||
>
|
||||
> ## Overview
|
||||
>
|
||||
> Nitro is a quick and easy performance analyzer library for Go.
|
||||
> It is useful for comparing A/B against different drafts of functions
|
||||
> or different functions.
|
||||
>
|
||||
> ## Implementing Nitro
|
||||
>
|
||||
> Using Nitro is simple. First, use `go get` to install the latest version
|
||||
> of the library.
|
||||
>
|
||||
> $ go get github.com/spf13/nitro
|
||||
>
|
||||
> Next, include nitro in your application.
|
||||
|
||||
The source `nitro.md` file is converted to HTML by the excellent
|
||||
[Blackfriday](https://github.com/russross/blackfriday) Markdown processor,
|
||||
which supports extended features found in the popular
|
||||
[GitHub Flavored Markdown](https://help.github.com/articles/github-flavored-markdown/).
|
||||
@@ -1,119 +0,0 @@
|
||||
---
|
||||
aliases:
|
||||
- /doc/front-matter/
|
||||
lastmod: 2015-12-23
|
||||
date: 2013-07-01
|
||||
menu:
|
||||
main:
|
||||
parent: content
|
||||
next: /content/sections
|
||||
prev: /content/organization
|
||||
title: Front Matter
|
||||
weight: 20
|
||||
toc: true
|
||||
---
|
||||
|
||||
The **front matter** is one of the features that gives Hugo its strength. It enables
|
||||
you to include the meta data of the content right with it. Hugo supports a few
|
||||
different formats, each with their own identifying tokens.
|
||||
|
||||
Supported formats:
|
||||
|
||||
* **[TOML][]**, identified by '`+++`'.
|
||||
* **[YAML][]**, identified by '`---`'.
|
||||
* **[JSON][]**, a single JSON object which is surrounded by '`{`' and '`}`', each on their own line.
|
||||
|
||||
[TOML]: https://github.com/toml-lang/toml "Tom's Obvious, Minimal Language"
|
||||
[YAML]: http://www.yaml.org/ "YAML Ain't Markup Language"
|
||||
[JSON]: http://www.json.org/ "JavaScript Object Notation"
|
||||
|
||||
## TOML Example
|
||||
|
||||
<pre><code class="language-toml">+++
|
||||
title = "spf13-vim 3.0 release and new website"
|
||||
description = "spf13-vim is a cross platform distribution of vim plugins and resources for Vim."
|
||||
tags = [ ".vimrc", "plugins", "spf13-vim", "vim" ]
|
||||
date = "2012-04-06"
|
||||
categories = [
|
||||
"Development",
|
||||
"VIM"
|
||||
]
|
||||
slug = "spf13-vim-3-0-release-and-new-website"
|
||||
+++
|
||||
</code><code class="language-markdown">Content of the file goes Here
|
||||
</code></pre>
|
||||
|
||||
## YAML Example
|
||||
|
||||
```yaml
|
||||
---
|
||||
title: "spf13-vim 3.0 release and new website"
|
||||
description: "spf13-vim is a cross platform distribution of vim plugins and resources for Vim."
|
||||
tags: [ ".vimrc", "plugins", "spf13-vim", "vim" ]
|
||||
lastmod: 2015-12-23
|
||||
date: "2012-04-06"
|
||||
categories:
|
||||
- "Development"
|
||||
- "VIM"
|
||||
slug: "spf13-vim-3-0-release-and-new-website"
|
||||
---
|
||||
|
||||
Content of the file goes Here
|
||||
```
|
||||
|
||||
## JSON Example
|
||||
|
||||
```json
|
||||
{
|
||||
"title": "spf13-vim 3.0 release and new website",
|
||||
"description": "spf13-vim is a cross platform distribution of vim plugins and resources for Vim.",
|
||||
"tags": [ ".vimrc", "plugins", "spf13-vim", "vim" ],
|
||||
"date": "2012-04-06",
|
||||
"categories": [
|
||||
"Development",
|
||||
"VIM"
|
||||
],
|
||||
"slug": "spf13-vim-3-0-release-and-new-website"
|
||||
}
|
||||
|
||||
Content of the file goes Here
|
||||
```
|
||||
|
||||
## Variables
|
||||
|
||||
There are a few predefined variables that Hugo is aware of and utilizes. The user can also create
|
||||
any variable they want. These will be placed into the `.Params` variable available to the templates.
|
||||
Field names are always normalized to lowercase (e.g. `camelCase: true` is available as `.Params.camelcase`).
|
||||
|
||||
### Required variables
|
||||
|
||||
* **title** The title for the content
|
||||
* **description** The description for the content
|
||||
* **date** The date the content will be sorted by
|
||||
* **taxonomies** These will use the field name of the plural form of the index (see tags and categories above)
|
||||
|
||||
### Optional variables
|
||||
|
||||
* **aliases** An array of one or more aliases
|
||||
(e.g. old published path of a renamed content)
|
||||
that would be created to redirect to this content.
|
||||
See [Aliases]({{< relref "extras/aliases.md" >}}) for details.
|
||||
* **draft** If true, the content will not be rendered unless `hugo` is called with `--buildDrafts`
|
||||
* **publishdate** If in the future, content will not be rendered unless `hugo` is called with `--buildFuture`
|
||||
* **expirydate** Content already expired will not be rendered unless `hugo` is called with `--buildExpired`
|
||||
* **type** The type of the content (will be derived from the directory automatically if unset)
|
||||
* **isCJKLanguage** If true, explicitly treat the content as CJKLanguage (`.Summary` and `.WordCount` can work properly in CJKLanguage)
|
||||
* **weight** Used for sorting
|
||||
* **markup** *(Experimental)* Specify `"rst"` for reStructuredText (requires
|
||||
`rst2html`) or `"md"` (default) for Markdown
|
||||
* **slug** appears as tail of the url. It can be used to change the part of the url that is based on the filename.
|
||||
* **url** The full path to the content from the web root. It makes no assumptions about the path of the content file. It also ignores any language prefixes of the multilingual feature.
|
||||
|
||||
*If neither `slug` or `url` is present, the filename will be used.*
|
||||
|
||||
## Configure Blackfriday rendering
|
||||
|
||||
It's possible to set some options for Markdown rendering in the page's front matter as an override to the site wide configuration.
|
||||
|
||||
See [Configuration]({{< ref "overview/configuration.md#configure-blackfriday-rendering" >}}) for more.
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
---
|
||||
aliases:
|
||||
- /doc/supported-formats/
|
||||
lastmod: 2016-07-22
|
||||
date: 2016-07-22
|
||||
menu:
|
||||
main:
|
||||
parent: content
|
||||
prev: /content/summaries
|
||||
next: /content/multilingual
|
||||
title: Markdown Extras
|
||||
weight: 66
|
||||
toc: false
|
||||
---
|
||||
|
||||
Hugo provides some convenient markdown extensions.
|
||||
|
||||
## Task lists
|
||||
|
||||
Hugo supports GitHub styled task lists (TODO lists) for the Blackfriday renderer (md-files). See [Blackfriday config](/overview/configuration/#configure-blackfriday-rendering) for how to turn it off.
|
||||
|
||||
Example:
|
||||
|
||||
```markdown
|
||||
- [ ] a task list item
|
||||
- [ ] list syntax required
|
||||
- [ ] incomplete
|
||||
- [x] completed
|
||||
```
|
||||
|
||||
Renders as:
|
||||
|
||||
- [ ] a task list item
|
||||
- [ ] list syntax required
|
||||
- [ ] incomplete
|
||||
- [x] completed
|
||||
|
||||
|
||||
And produces this HTML:
|
||||
|
||||
```html
|
||||
|
||||
<ul class="task-list">
|
||||
<li><input type="checkbox" disabled="" class="task-list-item"> a task list item</li>
|
||||
<li><input type="checkbox" disabled="" class="task-list-item"> list syntax required</li>
|
||||
<li><input type="checkbox" disabled="" class="task-list-item"> incomplete</li>
|
||||
<li><input type="checkbox" checked="" disabled="" class="task-list-item"> completed</li>
|
||||
</ul>
|
||||
```
|
||||
@@ -1,215 +0,0 @@
|
||||
---
|
||||
date: 2016-01-02T21:21:00Z
|
||||
menu:
|
||||
main:
|
||||
parent: content
|
||||
prev: /content/markdown-extras
|
||||
next: /content/example
|
||||
title: Multilingual Mode
|
||||
weight: 68
|
||||
toc: true
|
||||
---
|
||||
Hugo supports multiple languages side-by-side (added in `Hugo 0.17`). Define the available languages in a `Languages` section in your top-level `config.toml` (or equivalent).
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
defaultContentLanguage = "en"
|
||||
|
||||
Languages:
|
||||
en:
|
||||
weight: 1
|
||||
title: "My blog"
|
||||
params:
|
||||
linkedin: "english-link"
|
||||
fr:
|
||||
weight: 2
|
||||
title: "Mon blog"
|
||||
params:
|
||||
linkedin: "lien-francais"
|
||||
copyright: "Tout est à moi"
|
||||
|
||||
copyright: "Everything is mine"
|
||||
```
|
||||
|
||||
Anything not defined in a `[lang]:` block will fall back to the global
|
||||
value for that key (like `copyright` for the English (`en`) language in this example).
|
||||
|
||||
With the config above, all content, sitemap, RSS feeds, paginations
|
||||
and taxonomy pages will be rendered below `/` in English (your default content language), and below `/fr` in French.
|
||||
|
||||
If you want all of the languages to be put below their respective language code, enable `defaultContentLanguageInSubdir: true` in your configuration.
|
||||
|
||||
Only the obvious non-global options can be overridden per language. Examples of global options are `BaseURL`, `BuildDrafts`, etc.
|
||||
|
||||
Taxonomies and Blackfriday configuration can also be set per language, example:
|
||||
|
||||
```
|
||||
[Taxonomies]
|
||||
tag = "tags"
|
||||
|
||||
[blackfriday]
|
||||
angledQuotes = true
|
||||
hrefTargetBlank = true
|
||||
|
||||
[Languages]
|
||||
[Languages.en]
|
||||
weight = 1
|
||||
title = "English"
|
||||
[Languages.en.blackfriday]
|
||||
angledQuotes = false
|
||||
|
||||
[Languages.fr]
|
||||
weight = 2
|
||||
title = "Français"
|
||||
[Languages.fr.Taxonomies]
|
||||
plaque = "plaques"
|
||||
```
|
||||
|
||||
|
||||
### Translating your content
|
||||
|
||||
Translated articles are identified by the name of the content file.
|
||||
|
||||
Example of translated articles:
|
||||
|
||||
1. `/content/about.en.md`
|
||||
2. `/content/about.fr.md`
|
||||
|
||||
You can also have:
|
||||
|
||||
1. `/content/about.md`
|
||||
2. `/content/about.fr.md`
|
||||
|
||||
In which case the config variable `defaultContentLanguage` will be used to affect the default language `about.md`. This way, you can
|
||||
slowly start to translate your current content without having to rename everything.
|
||||
|
||||
If left unspecified, the value for `defaultContentLanguage` defaults to `en`.
|
||||
|
||||
By having the same _base file name_, the content pieces are linked together as translated pieces.
|
||||
|
||||
### Link to translated content
|
||||
|
||||
To create a list of links to translated content, use a template similar to this:
|
||||
|
||||
```
|
||||
{{ if .IsTranslated }}
|
||||
<h4>{{ i18n "translations" }}</h4>
|
||||
<ul>
|
||||
{{ range .Translations }}
|
||||
<li>
|
||||
<a href="{{ .Permalink }}">{{ .Lang }}: {{ .Title }}{{ if .IsPage }} ({{ i18n "wordCount" . }}){{ end }}</a>
|
||||
</li>
|
||||
{{ end}}
|
||||
</ul>
|
||||
{{ end }}
|
||||
```
|
||||
The above can be put in a `partial` and included in any template, be it for a content page or the home page. It will not print anything if there are no translations for a given page, or if it is -- in the case of the home page, section listing etc. -- a site with only one language.
|
||||
|
||||
The above also uses the `i18n` func, see [Translation of strings](#translation-of-strings).
|
||||
|
||||
### Translation of strings
|
||||
|
||||
Hugo uses [go-i18n](https://github.com/nicksnyder/go-i18n) to support string translations. Follow the link to find tools to manage your translation workflows.
|
||||
|
||||
Translations are collected from the `themes/[name]/i18n/` folder (built into the theme), as well as translations present in `i18n/` at the root of your project. In the `i18n`, the translations will be merged and take precedence over what is in the theme folder. Language files should be named according to RFC 5646 with names such as `en-US.yaml`, `fr.yaml`, etc.
|
||||
|
||||
From within your templates, use the `i18n` function like this:
|
||||
|
||||
```
|
||||
{{ i18n "home" }}
|
||||
```
|
||||
|
||||
This uses a definition like this one in `i18n/en-US.yaml`:
|
||||
|
||||
```
|
||||
- id: home
|
||||
translation: "Home"
|
||||
```
|
||||
|
||||
Often you will want to use to the page variables in the translations strings. To do that, pass on the "." context when calling `i18n`:
|
||||
|
||||
```
|
||||
{{ i18n "wordCount" . }}
|
||||
```
|
||||
|
||||
This uses a definition like this one in `i18n/en-US.yaml`:
|
||||
|
||||
```
|
||||
- id: wordCount
|
||||
translation: "This article has {{ .WordCount }} words."
|
||||
```
|
||||
An example of singular and plural form:
|
||||
|
||||
```
|
||||
- id: readingTime
|
||||
translation:
|
||||
one: "One minute read"
|
||||
other: "{{.Count}} minutes read"
|
||||
```
|
||||
And then in the template:
|
||||
|
||||
```
|
||||
{{ i18n "readingTime" .ReadingTime }}
|
||||
```
|
||||
To track down missing translation strings, run Hugo with the `--i18n-warnings` flag:
|
||||
|
||||
```bash
|
||||
hugo --i18n-warnings | grep i18n
|
||||
i18n|MISSING_TRANSLATION|en|wordCount
|
||||
```
|
||||
|
||||
### Menus
|
||||
|
||||
You can define your menus for each language independently. The [creation of a menu]({{< relref "extras/menus.md" >}}) works analogous to earlier versions of Hugo, except that they have to be defined in their language-specific block in the configuration file:
|
||||
|
||||
```toml
|
||||
defaultContentLanguage = "en"
|
||||
|
||||
[languages.en]
|
||||
weight = 0
|
||||
languageName = "English"
|
||||
|
||||
[[languages.en.menu.main]]
|
||||
url = "/"
|
||||
name = "Home"
|
||||
weight = 0
|
||||
|
||||
|
||||
[languages.de]
|
||||
weight = 10
|
||||
languageName = "Deutsch"
|
||||
|
||||
[[languages.de.menu.main]]
|
||||
url = "/"
|
||||
name = "Startseite"
|
||||
weight = 0
|
||||
```
|
||||
|
||||
The rendering of the main navigation works as usual. `.Site.Menus` will just contain the menu of the current language. Pay attention to the generation of the menu links. `absLangURL` takes care that you link to the correct locale of your website. Otherwise, both menu entries would link to the English version because it's the default content language that resides in the root directory.
|
||||
|
||||
```html
|
||||
<ul>
|
||||
{{- $currentPage := . -}}
|
||||
{{ range .Site.Menus.main -}}
|
||||
<li class="{{ if $currentPage.IsMenuCurrent "main" . }}active{{ end }}">
|
||||
<a href="{{ .URL | absLangURL }}">{{ .Name }}</a>
|
||||
</li>
|
||||
{{- end }}
|
||||
</ul>
|
||||
|
||||
```
|
||||
|
||||
### Missing translations
|
||||
|
||||
If a string does not have a translation for the current language, Hugo will use the value from the default language. If no default value is set, an empty string will be shown.
|
||||
|
||||
While translating a Hugo site, it can be handy to have a visual indicator of missing translations. The `EnableMissingTranslationPlaceholders` config option will flag all untranslated strings with the placeholder `[i18n] identifier`, where `identifier` is the id of the missing translation.
|
||||
|
||||
**Remember: Hugo will generate your website with these placeholders. It might not be suited for production environments.**
|
||||
|
||||
### Multilingual Themes support
|
||||
|
||||
To support Multilingual mode in your themes, some considerations must be taken for the URLs in the templates. If there are more than one language, URLs must either come from the built-in `.Permalink` or `.URL`, be constructed with `relLangURL` or `absLangURL` template funcs -- or prefixed with `{{.LanguagePrefix }}`.
|
||||
|
||||
If there are more than one language defined, the`LanguagePrefix` variable will equal `"/en"` (or whatever your `CurrentLanguage` is). If not enabled, it will be an empty string, so it is harmless for single-language sites.
|
||||
@@ -1,41 +0,0 @@
|
||||
---
|
||||
lastmod: 2015-12-23
|
||||
date: 2014-03-06
|
||||
linktitle: Ordering
|
||||
menu:
|
||||
main:
|
||||
parent: content
|
||||
next: /content/summaries
|
||||
prev: /content/archetypes
|
||||
title: Ordering Content
|
||||
weight: 60
|
||||
---
|
||||
|
||||
Hugo provides you with all the flexibility you need to organize how your content is ordered.
|
||||
|
||||
By default, content is ordered by weight, then by date with the most
|
||||
recent date first, but alternative sorting (by `title` and `linktitle`) is
|
||||
also available. The order the content would appear is specified in
|
||||
the [list template](/templates/list/).
|
||||
|
||||
_Both the `date` and `weight` fields are optional._
|
||||
|
||||
Unweighted pages appear at the end of the list. If no weights are provided (or
|
||||
if weights are the same), `date` will be used to sort. If neither is provided,
|
||||
content will be ordered based on how it's read off the disk, and no order is
|
||||
guaranteed.
|
||||
|
||||
## Assigning weight to content
|
||||
|
||||
```toml
|
||||
+++
|
||||
weight = 4
|
||||
title = "Three"
|
||||
date = "2012-04-06"
|
||||
+++
|
||||
Front Matter with Ordered Pages 3
|
||||
```
|
||||
|
||||
## Ordering Content Within Taxonomies
|
||||
|
||||
Please see the [Taxonomy Ordering Documentation](/taxonomies/ordering/).
|
||||
@@ -1,175 +0,0 @@
|
||||
---
|
||||
aliases:
|
||||
- /doc/organization/
|
||||
lastmod: 2015-09-27
|
||||
date: 2013-07-01
|
||||
linktitle: Organization
|
||||
menu:
|
||||
main:
|
||||
parent: content
|
||||
next: /content/supported-formats
|
||||
prev: /overview/source-directory
|
||||
title: Content Organization
|
||||
weight: 10
|
||||
toc: true
|
||||
---
|
||||
|
||||
Hugo uses files (see [supported formats](/content/supported-formats/)) with headers commonly called the *front matter*. Hugo
|
||||
respects the organization that you provide for your content to minimize any
|
||||
extra configuration, though this can be overridden by additional configuration
|
||||
in the front matter.
|
||||
|
||||
## Organization
|
||||
|
||||
In Hugo, the content should be arranged in the same way they are intended for
|
||||
the rendered website. Without any additional configuration, the following will
|
||||
just work. Hugo supports content nested at any level. The top level is special
|
||||
in Hugo and is used as the [section](/content/sections/).
|
||||
|
||||
.
|
||||
└── content
|
||||
└── about
|
||||
| └── index.md // <- http://1.com/about/
|
||||
├── post
|
||||
| ├── firstpost.md // <- http://1.com/post/firstpost/
|
||||
| ├── happy
|
||||
| | └── ness.md // <- http://1.com/post/happy/ness/
|
||||
| └── secondpost.md // <- http://1.com/post/secondpost/
|
||||
└── quote
|
||||
├── first.md // <- http://1.com/quote/first/
|
||||
└── second.md // <- http://1.com/quote/second/
|
||||
|
||||
**Here's the same organization run with `hugo --uglyURLs`**
|
||||
|
||||
.
|
||||
└── content
|
||||
└── about
|
||||
| └── index.md // <- http://1.com/about/
|
||||
├── post
|
||||
| ├── firstpost.md // <- http://1.com/post/firstpost.html
|
||||
| ├── happy
|
||||
| | └── ness.md // <- http://1.com/post/happy/ness.html
|
||||
| └── secondpost.md // <- http://1.com/post/secondpost.html
|
||||
└── quote
|
||||
├── first.md // <- http://1.com/quote/first.html
|
||||
└── second.md // <- http://1.com/quote/second.html
|
||||
|
||||
## Destinations
|
||||
|
||||
Hugo believes that you organize your content with a purpose. The same structure
|
||||
that works to organize your source content is used to organize the rendered
|
||||
site. As displayed above, the organization of the source content will be
|
||||
mirrored in the destination.
|
||||
|
||||
Notice that the first level `about/` page URL was created using a directory
|
||||
named "about" with a single `index.md` file inside.
|
||||
|
||||
There are times when one would need more control over their content. In these
|
||||
cases, there are a variety of things that can be specified in the front matter
|
||||
to determine the destination of a specific piece of content.
|
||||
|
||||
The following items are defined in order, latter items in the list will override
|
||||
earlier settings.
|
||||
|
||||
### filename
|
||||
This isn't in the front matter, but is the actual name of the file minus the
|
||||
extension. This will be the name of the file in the destination.
|
||||
|
||||
### slug
|
||||
Defined in the front matter, the `slug` can take the place of the filename for the
|
||||
destination.
|
||||
|
||||
### filepath
|
||||
The actual path to the file on disk. Destination will create the destination
|
||||
with the same path. Includes [section](/content/sections/).
|
||||
|
||||
### section
|
||||
`section` is determined by its location on disk and can *not* be specified in the front matter. See [section](/content/sections/).
|
||||
|
||||
### type
|
||||
`type` is also determined by its location on disk but, unlike `section`, it *can* be specified in the front matter. See [type](/content/types/).
|
||||
|
||||
### path
|
||||
`path` can be provided in the front matter. This will replace the actual
|
||||
path to the file on disk. Destination will create the destination with the same
|
||||
path. Includes [section](/content/sections/).
|
||||
|
||||
### url
|
||||
A complete URL can be provided. This will override all the above as it pertains
|
||||
to the end destination. This must be the path from the baseURL (starting with a "/").
|
||||
When a `url` is provided, it will be used exactly. Using `url` will ignore the
|
||||
`--uglyURLs` setting.
|
||||
|
||||
|
||||
## Path breakdown in Hugo
|
||||
|
||||
### Content
|
||||
|
||||
. path slug
|
||||
. ⊢-------^----⊣ ⊢------^-------⊣
|
||||
content/extras/indexes/category-example/index.html
|
||||
|
||||
|
||||
. section slug
|
||||
. ⊢--^--⊣ ⊢------^-------⊣
|
||||
content/extras/indexes/category-example/index.html
|
||||
|
||||
|
||||
. section slug
|
||||
. ⊢--^--⊣⊢--^--⊣
|
||||
content/extras/indexes/index.html
|
||||
|
||||
### Destination
|
||||
|
||||
|
||||
permalink
|
||||
⊢--------------^-------------⊣
|
||||
http://spf13.com/projects/hugo
|
||||
|
||||
|
||||
baseURL section slug
|
||||
⊢-----^--------⊣ ⊢--^---⊣ ⊢-^⊣
|
||||
http://spf13.com/projects/hugo
|
||||
|
||||
|
||||
baseURL section slug
|
||||
⊢-----^--------⊣ ⊢--^--⊣ ⊢--^--⊣
|
||||
http://spf13.com/extras/indexes/example
|
||||
|
||||
|
||||
baseURL path slug
|
||||
⊢-----^--------⊣ ⊢------^-----⊣ ⊢--^--⊣
|
||||
http://spf13.com/extras/indexes/example
|
||||
|
||||
|
||||
baseURL url
|
||||
⊢-----^--------⊣ ⊢-----^-----⊣
|
||||
http://spf13.com/projects/hugo
|
||||
|
||||
|
||||
baseURL url
|
||||
⊢-----^--------⊣ ⊢--------^-----------⊣
|
||||
http://spf13.com/extras/indexes/example
|
||||
|
||||
|
||||
|
||||
**section** = which type the content is by default
|
||||
|
||||
* based on content location
|
||||
* front matter overrides
|
||||
|
||||
**slug** = name.ext or name/
|
||||
|
||||
* based on content-name.md
|
||||
* front matter overrides
|
||||
|
||||
**path** = section + path to file excluding slug
|
||||
|
||||
* based on path to content location
|
||||
|
||||
|
||||
**url** = relative URL
|
||||
|
||||
* defined in front matter
|
||||
* overrides all the above
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
---
|
||||
lastmod: 2015-12-23
|
||||
date: 2013-07-01
|
||||
menu:
|
||||
main:
|
||||
parent: content
|
||||
next: /content/types
|
||||
notoc: true
|
||||
prev: /content/front-matter
|
||||
title: Sections
|
||||
weight: 30
|
||||
---
|
||||
|
||||
Hugo believes that you organize your content with a purpose. The same structure
|
||||
that works to organize your source content is used to organize the rendered
|
||||
site (see [Organization](/content/organization/)). Following this pattern Hugo
|
||||
uses the top level of your content organization as **the Section**.
|
||||
|
||||
The following example site uses two sections, "post" and "quote".
|
||||
|
||||
{{< nohighlight >}}.
|
||||
└── content
|
||||
├── post
|
||||
| ├── firstpost.md // <- http://1.com/post/firstpost/
|
||||
| ├── happy
|
||||
| | └── ness.md // <- http://1.com/post/happy/ness/
|
||||
| └── secondpost.md // <- http://1.com/post/secondpost/
|
||||
└── quote
|
||||
├── first.md // <- http://1.com/quote/first/
|
||||
└── second.md // <- http://1.com/quote/second/
|
||||
{{< /nohighlight >}}
|
||||
|
||||
## Section Lists
|
||||
|
||||
Hugo will automatically create pages for each section root that list all
|
||||
of the content in that section. See [List Templates](/templates/list/)
|
||||
for details on customizing the way they appear.
|
||||
|
||||
Section pages can also have a content file and frontmatter, see [Source Organization]({{< relref "overview/source-directory.md#content-for-home-page-and-other-list-pages" >}}).
|
||||
|
||||
## Sections and Types
|
||||
|
||||
By default everything created within a section will use the content type
|
||||
that matches the section name.
|
||||
|
||||
Section defined in the front matter have the same impact.
|
||||
|
||||
To change the type of a given piece of content, simply define the type
|
||||
in the front matter.
|
||||
|
||||
If a layout for a given type hasn't been provided, a default type template will
|
||||
be used instead provided it exists.
|
||||
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
---
|
||||
lastmod: 2015-01-27
|
||||
date: 2013-07-01
|
||||
menu:
|
||||
main:
|
||||
parent: content
|
||||
notoc: true
|
||||
prev: /content/ordering
|
||||
next: /content/markdown-extras
|
||||
title: Summaries
|
||||
weight: 65
|
||||
---
|
||||
|
||||
With the use of the `.Summary` [page variable](/templates/variables/), Hugo can generate summaries of content to show snippets in summary views. The summary view snippets are automatically generated by Hugo. Where a piece of content is split for the content summary depends on whether the split is Hugo-defined or user-defined.
|
||||
|
||||
Content summaries may also provide links to the original content, usually in the form of a "Read More..." link, with the help of the `.RelPermalink` or `.Permalink` variable, as well as the `.Truncated` boolean variable to determine whether such "Read More..." link is necessary.
|
||||
|
||||
## Hugo-defined: automatic summary split
|
||||
|
||||
By default, Hugo automatically takes the first 70 words of your content as its summary and stores it into the `.Summary` variable, which you may use in your templates.
|
||||
|
||||
* Pros: Automatic, no additional work on your part.
|
||||
* Cons: All HTML tags are stripped from the summary, and the first 70 words, whether they belong to a heading or to different paragraphs, are all lumped into one paragraph. Some people like it, but some people don't.
|
||||
|
||||
## User-defined: manual summary split:
|
||||
|
||||
Alternatively, you may add the <code><!--more--></code> summary divider[^1] where you want to split the article. Content prior to the summary divider will be used as that content's summary, and stored into the `.Summary` variable with all HTML formatting intact.
|
||||
|
||||
[^1]: The **summary divider** is also called "more tag", "excerpt separator", etc. in other literature.
|
||||
|
||||
* Pros: Freedom, precision, and improved rendering. All formatting is preserved.
|
||||
* Cons: Need to remember to type <code><!--more--></code> in your content file. :-)
|
||||
|
||||
Be careful to enter <code><!--more--></code> exactly, i.e. all lowercase with no whitespace, otherwise it would be treated as regular comment and ignored.
|
||||
|
||||
|
||||
## Showing Summaries
|
||||
|
||||
You can show content summaries with the following code. You could do this, for example, on a [list](/templates/list/) page.
|
||||
|
||||
{{ range first 10 .Data.Pages }}
|
||||
<div class="summary">
|
||||
<h4><a href="{{ .RelPermalink }}">{{ .Title }}</a></h4>
|
||||
{{ .Summary }}
|
||||
</div>
|
||||
{{ if .Truncated }}
|
||||
<div class="read-more-link">
|
||||
<a href="{{ .RelPermalink }}">Read More…</a>
|
||||
</div>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
||||
Note how the `.Truncated` boolean valuable may be used to hide the "Read More..." link when the content is not truncated, i.e. when the summary contains the entire article.
|
||||
@@ -1,27 +0,0 @@
|
||||
---
|
||||
aliases:
|
||||
- /doc/supported-formats/
|
||||
lastmod: 2015-08-01
|
||||
date: 2015-08-01
|
||||
menu:
|
||||
main:
|
||||
parent: content
|
||||
next: /content/front-matter
|
||||
prev: /content/organization
|
||||
title: Supported Formats
|
||||
weight: 15
|
||||
toc: true
|
||||
---
|
||||
|
||||
Since 0.14, Hugo has defined a new concept called _external helpers_. It means that you can write your content using Asciidoc[tor], or reStructuredText. If you have files with associated extensions ([details](https://github.com/spf13/hugo/blob/77c60a3440806067109347d04eb5368b65ea0fe8/helpers/general.go#L65)), then Hugo will call external commands to generate the content.
|
||||
|
||||
This means that you will have to install the associated tool on your machine to be able to use those formats.
|
||||
|
||||
For example, for Asciidoc files, Hugo will try to call __asciidoctor__ or __asciidoc__ command.
|
||||
|
||||
To use those formats, just use the standard extension and the front matter exactly as you would do with natively supported _.md_ files.
|
||||
|
||||
Notes:
|
||||
|
||||
* as these are external commands, generation performance for that content will heavily depend on the performance of those external tools.
|
||||
* this feature is still in early stage, hence feedback is even more welcome.
|
||||
@@ -1,80 +0,0 @@
|
||||
---
|
||||
lastmod: 2015-09-28
|
||||
date: 2013-07-01
|
||||
linktitle: Types
|
||||
menu:
|
||||
main:
|
||||
parent: content
|
||||
next: /content/archetypes
|
||||
prev: /content/sections
|
||||
title: Content Types
|
||||
weight: 40
|
||||
toc: true
|
||||
---
|
||||
|
||||
Hugo has full support for different types of content. A content type can have a
|
||||
unique set of meta data, template and can be automatically created by the `hugo new`
|
||||
command through using content [archetypes](/content/archetypes/).
|
||||
|
||||
A good example of when multiple types are needed is to look at [Tumblr](https://www.tumblr.com/). A piece
|
||||
of content could be a photo, quote or post, each with different meta data and
|
||||
rendered differently.
|
||||
|
||||
## Assigning a content type
|
||||
|
||||
Hugo assumes that your site will be organized into [sections](/content/sections/)
|
||||
and each section will use the corresponding type. If you are taking advantage of
|
||||
this, then each new piece of content you place into a section will automatically
|
||||
inherit the type.
|
||||
|
||||
Alternatively, you can set the type in the meta data under the key "`type`".
|
||||
|
||||
|
||||
## Creating new content of a specific type
|
||||
|
||||
Hugo has the ability to create a new content file and populate the front matter
|
||||
with the data set corresponding to that type. Hugo does this by utilizing
|
||||
[archetypes](/content/archetypes/).
|
||||
|
||||
To create a new piece of content, use:
|
||||
|
||||
hugo new relative/path/to/content.md
|
||||
|
||||
For example, if I wanted to create a new post inside the post section, I would type:
|
||||
|
||||
hugo new post/my-newest-post.md
|
||||
|
||||
|
||||
## Defining a content type
|
||||
|
||||
Creating a new content type is easy in Hugo. You simply provide the templates and archetype
|
||||
that the new type will use. You only need to define the templates, archetypes and/or views
|
||||
unique to that content type. Hugo will fall back to using the general templates and default archetype
|
||||
whenever a specific file is not present.
|
||||
|
||||
*Remember, all of the following are optional:*
|
||||
|
||||
### Create Type Directory
|
||||
Create a directory with the name of the type in `/layouts`. Type is always singular. *E.g. `/layouts/post`*.
|
||||
|
||||
### Create single template
|
||||
Create a file called `single.html` inside your directory. *E.g. `/layouts/post/single.html`*.
|
||||
|
||||
### Create list template
|
||||
Create a file called `post.html` inside the section lists template directory, `/layouts/section`. *E.g. `/layouts/section/post.html`*.
|
||||
|
||||
### Create views
|
||||
Many sites support rendering content in a few different ways, for
|
||||
instance, a single page view and a summary view to be used when
|
||||
displaying a [list of contents on a single page](/templates/list).
|
||||
Hugo makes no assumptions here about how you want to display your
|
||||
content, and will support as many different views of a content type
|
||||
as your site requires. All that is required for these additional
|
||||
views is that a template exists in each `/layouts/TYPE` directory
|
||||
with the same name.
|
||||
|
||||
### Create a corresponding archetype
|
||||
|
||||
Create a file called <code><em>type</em>.md</code> in the `/archetypes` directory. *E.g. `/archetypes/post.md`*.
|
||||
|
||||
More details about archetypes can be found at the [archetypes docs](/content/archetypes/).
|
||||
@@ -1,103 +0,0 @@
|
||||
---
|
||||
aliases:
|
||||
- /doc/redirects/
|
||||
- /doc/alias/
|
||||
- /doc/aliases/
|
||||
lastmod: 2015-12-23
|
||||
date: 2013-07-09
|
||||
menu:
|
||||
main:
|
||||
parent: extras
|
||||
next: /extras/analytics
|
||||
prev: /taxonomies/methods
|
||||
title: Aliases
|
||||
---
|
||||
|
||||
For people migrating existing published content to Hugo, there's a good chance you need a mechanism to handle redirecting old URLs.
|
||||
|
||||
Luckily, redirects can be handled easily with _aliases_ in Hugo.
|
||||
|
||||
## Example
|
||||
|
||||
Given a post on your current Hugo site, with a path of:
|
||||
|
||||
``content/posts/my-awesome-blog-post.md``
|
||||
|
||||
... you create an "aliases" section in the frontmatter of your post, and add previous paths to that.
|
||||
|
||||
### TOML frontmatter
|
||||
|
||||
```toml
|
||||
+++
|
||||
...
|
||||
aliases = [
|
||||
"/posts/my-original-url/",
|
||||
"/2010/01/01/even-earlier-url.html"
|
||||
]
|
||||
...
|
||||
+++
|
||||
```
|
||||
|
||||
### YAML frontmatter
|
||||
|
||||
```yaml
|
||||
---
|
||||
...
|
||||
aliases:
|
||||
- /posts/my-original-url/
|
||||
- /2010/01/01/even-earlier-url.html
|
||||
...
|
||||
---
|
||||
```
|
||||
|
||||
Now when you visit any of the locations specified in aliases, _assuming the same site domain_, you'll be redirected to the page they are specified on.
|
||||
|
||||
## Important Behaviors
|
||||
|
||||
1. *Hugo makes no assumptions about aliases. They also don't change based
|
||||
on your UglyURLs setting. You need to provide absolute path to your webroot
|
||||
and the complete filename or directory.*
|
||||
|
||||
2. *Aliases are rendered prior to any content and will be overwritten by
|
||||
any content with the same location.*
|
||||
|
||||
## Multilingual example
|
||||
|
||||
On [multilingual sites]({{< relref "content/multilingual.md" >}}), each translation of a post can have unique aliases. To use the same alias across multiple languages, prefix it with the language code.
|
||||
|
||||
In `/posts/my-new-post.es.md`:
|
||||
|
||||
```yaml
|
||||
---
|
||||
aliases:
|
||||
- /es/posts/my-original-post/
|
||||
---
|
||||
```
|
||||
|
||||
## How Hugo Aliases Work
|
||||
|
||||
When aliases are specified, Hugo creates a physical folder structure to match the alias entry, and, an html file specifying the canonical URL for the page, and a redirect target.
|
||||
|
||||
Assuming a baseURL of `mysite.tld`, the contents of the html file will look something like:
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>http://mysite.tld/posts/my-original-url</title>
|
||||
<link rel="canonical" href="http://mysite.tld/posts/my-original-url"/>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
|
||||
<meta http-equiv="refresh" content="0; url=http://mysite.tld/posts/my-original-url"/>
|
||||
</head>
|
||||
</html>
|
||||
```
|
||||
|
||||
The `http-equiv="refresh"` line is what performs the redirect, in 0 seconds in this case.
|
||||
|
||||
## Customizing
|
||||
|
||||
You may customize this alias page by creating an alias.html template in the
|
||||
layouts folder of your site. In this case, the data passed to the template is
|
||||
|
||||
* Permalink - the link to the page being aliased
|
||||
* Page - the Page data for the page being aliased
|
||||
@@ -1,28 +0,0 @@
|
||||
---
|
||||
date: 2016-02-06
|
||||
linktitle: Analytics
|
||||
menu:
|
||||
main:
|
||||
parent: extras
|
||||
next: /extras/builders
|
||||
prev: /extras/aliases
|
||||
title: Analytics in Hugo
|
||||
---
|
||||
|
||||
Hugo ships with prebuilt internal templates for Google Analytics tracking, including both synchronous and asynchronous tracking codes.
|
||||
|
||||
## Configuring Google Analytics
|
||||
|
||||
Provide your tracking id in your configuration file, e.g. config.yaml.
|
||||
|
||||
googleAnalytics = "UA-123-45"
|
||||
|
||||
## Example
|
||||
|
||||
Include the internal template in your templates like so:
|
||||
|
||||
{{ template "_internal/google_analytics.html" . }}
|
||||
|
||||
For async include the async template:
|
||||
|
||||
{{ template "_internal/google_analytics_async.html" . }}
|
||||
@@ -1,56 +0,0 @@
|
||||
---
|
||||
lastmod: 2015-12-24
|
||||
date: 2014-05-26
|
||||
linktitle: Builders
|
||||
menu:
|
||||
main:
|
||||
parent: extras
|
||||
next: /extras/comments
|
||||
prev: /extras/analytics
|
||||
title: Hugo Builders
|
||||
---
|
||||
|
||||
Hugo provides the functionality to quickly get a site, theme or page
|
||||
started.
|
||||
|
||||
|
||||
## New Site
|
||||
|
||||
Want to get a site built quickly?
|
||||
|
||||
{{< nohighlight >}}$ hugo new site <i>path/to/site</i>
|
||||
{{< /nohighlight >}}
|
||||
|
||||
Hugo will create all the needed directories and files to get started
|
||||
quickly.
|
||||
|
||||
Hugo will only touch the files and create the directories (in the right
|
||||
places), [configuration](/overview/configuration/) and content are up to
|
||||
you... but luckily we have builders for content (see below).
|
||||
|
||||
## New Theme
|
||||
|
||||
Want to design a new theme?
|
||||
|
||||
$ hugo new theme THEME_NAME
|
||||
|
||||
Run from your working directory, this will create a new theme with all
|
||||
the needed files in your themes directory. Hugo will provide you with a
|
||||
license and theme.toml file with most of the work done for you.
|
||||
|
||||
Follow the [Theme Creation Guide](/themes/creation/) once the builder is
|
||||
done.
|
||||
|
||||
## New Content
|
||||
|
||||
You will use this builder the most of all. Every time you want to create
|
||||
a new piece of content, the content builder will get you started right.
|
||||
|
||||
Leveraging [content archetypes](/content/archetypes/) the content builder
|
||||
will not only insert the current date and appropriate metadata, but it
|
||||
will pre-populate values based on the content type.
|
||||
|
||||
$ hugo new relative/path/to/content
|
||||
|
||||
This assumes it is being run from your working directory and the content
|
||||
path starts from your content directory. Now, Hugo watches your content directory by default and rebuilds your entire website if any change occurs.
|
||||
@@ -1,94 +0,0 @@
|
||||
---
|
||||
lastmod: 2015-08-04
|
||||
date: 2014-05-26
|
||||
linktitle: Comments
|
||||
menu:
|
||||
main:
|
||||
parent: extras
|
||||
next: /extras/crossreferences
|
||||
prev: /extras/builders
|
||||
title: Comments in Hugo
|
||||
---
|
||||
|
||||
As Hugo is a static site generator, the content produced is static and doesn’t interact with the users. The most common interaction people ask for is comment capability.
|
||||
|
||||
Hugo ships with support for [Disqus](https://disqus.com/), a third-party service that provides comment and community capabilities to website via JavaScript.
|
||||
|
||||
Your theme may already support Disqus, but even it if doesn’t, it is easy to add.
|
||||
|
||||
# Disqus Support
|
||||
|
||||
## Adding Disqus to a template
|
||||
|
||||
Hugo comes with all the code you would need to include load Disqus. Simply include the following line where you want your comments to appear:
|
||||
|
||||
{{ template "_internal/disqus.html" . }}
|
||||
|
||||
## Configuring Disqus
|
||||
|
||||
That template requires you to set a single value in your site config file, e.g. config.yaml.
|
||||
|
||||
disqusShortname = "XYW"
|
||||
|
||||
Additionally, you can optionally set the following in the front matter
|
||||
for a given piece of content:
|
||||
|
||||
* **disqus_identifier**
|
||||
* **disqus_title**
|
||||
* **disqus_url**
|
||||
|
||||
## Conditional Loading of Disqus Comments
|
||||
|
||||
Users have noticed that enabling Disqus comments when running the Hugo web server on localhost causes the creation of unwanted discussions on the associated Disqus account. In order to prevent this, a slightly tweaked partial template is required. So, rather than using the built-in `"_internal/disqus.html"` template referenced above, create a template in your `partials` folder that looks like this:
|
||||
|
||||
```html
|
||||
<div id="disqus_thread"></div>
|
||||
<script type="text/javascript">
|
||||
|
||||
(function() {
|
||||
// Don't ever inject Disqus on localhost--it creates unwanted
|
||||
// discussions from 'localhost:1313' on your Disqus account...
|
||||
if (window.location.hostname == "localhost")
|
||||
return;
|
||||
|
||||
var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
|
||||
var disqus_shortname = '{{ .Site.DisqusShortname }}';
|
||||
dsq.src = '//' + disqus_shortname + '.disqus.com/embed.js';
|
||||
(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
|
||||
})();
|
||||
</script>
|
||||
<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
|
||||
<a href="http://disqus.com/" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a>
|
||||
```
|
||||
|
||||
Notice that there is a simple `if` statement that detects when you are running on localhost and skips the initialization of the Disqus comment injection.
|
||||
|
||||
Now, reference the partial template from your page template:
|
||||
|
||||
{{ partial "disqus.html" . }}
|
||||
|
||||
|
||||
# Alternatives
|
||||
|
||||
A few alternatives exist to [Disqus](https://disqus.com/):
|
||||
|
||||
* [Discourse](http://www.discourse.org)
|
||||
* [IntenseDebate](http://intensedebate.com/)
|
||||
* [Livefyre](http://livefyre.com/)
|
||||
* [Muut](http://muut.com/)
|
||||
* [多说](http://duoshuo.com/) ([Duoshuo](http://duoshuo.com/), popular in China)
|
||||
* [isso](http://posativ.org/isso/) (Self-hosted, Python)
|
||||
* [Kaiju](https://github.com/spf13/kaiju)
|
||||
|
||||
## Kaiju
|
||||
|
||||
[Kaiju](https://github.com/spf13/kaiju) is an open-source project started by [spf13](http://spf13.com/) (Hugo’s author) to bring easy and fast real time discussions to the web.
|
||||
|
||||
Written using Go, Socket.io and MongoDB, it is very fast and easy to deploy.
|
||||
|
||||
It is in early development but shows promise. If you have interest, please help by contributing whether via a pull request, an issue or even just a tweet. Everything helps.
|
||||
|
||||
## Discourse
|
||||
|
||||
Additionally, you may recognize [Discourse](http://www.discourse.org) as the system that powers the [Hugo Discussion Forum](http://discuss.gohugo.io).
|
||||
|
||||
@@ -1,153 +0,0 @@
|
||||
---
|
||||
lastmod: 2015-12-23
|
||||
date: 2014-11-25
|
||||
menu:
|
||||
main:
|
||||
parent: extras
|
||||
next: /extras/robots-txt
|
||||
prev: /extras/comments
|
||||
title: Cross-References
|
||||
toc: true
|
||||
---
|
||||
|
||||
Hugo makes it easy to link documents together with the `ref` and `relref` shortcodes. These shortcodes are also used to safely provide links to headings inside of your content, whether across documents or within a document. The only difference between `ref` and `relref` is whether the resulting URL is absolute (`http://1.com/about/`) or relative (`/about/`).
|
||||
|
||||
## Using `ref` and `relref`
|
||||
|
||||
```django
|
||||
{{</* ref "document" */>}}
|
||||
{{</* ref "#anchor" */>}}
|
||||
{{</* ref "document#anchor" */>}}
|
||||
{{</* relref "document" */>}}
|
||||
{{</* relref "#anchor" */>}}
|
||||
{{</* relref "document#anchor" */>}}
|
||||
```
|
||||
|
||||
The single parameter to `ref` is a string with a content _document name_ (`about.md`), an in-document _anchor_ (`#who`), or both (`about.md#who`).
|
||||
|
||||
### Document Names
|
||||
|
||||
The _document name_ is the name of a document including the format extension; this may be just the filename, or the relative path from the `content/` directory. With a document `content/blog/post.md`, either format will produce the same result.
|
||||
|
||||
{{</* relref "blog/post.md" */>}} ⇒ `/blog/post/`
|
||||
{{</* relref "post.md" */>}} ⇒ `/blog/post/`
|
||||
|
||||
If you have multiple sections with the same filename, you should only use the relative path format, because the behaviour is _undefined_. So, if I also have a document `link/post.md`, the output of `ref` is unknown for `post.md`.
|
||||
|
||||
{{</* relref "blog/post.md" */>}} ⇒ `/blog/post/`
|
||||
{{</* relref "post.md" */>}} ⇒ `/blog/post/` (maybe)
|
||||
{{</* relref "post.md" */>}} ⇒ `/link/post/` (maybe)
|
||||
{{</* relref "link/post.md" */>}} ⇒ `/link/post/`
|
||||
|
||||
A relative document name must *not* begin with a slash (`/`).
|
||||
|
||||
{{</* relref "/blog/post.md" */>}} ⇒ `""`
|
||||
|
||||
### Anchors
|
||||
|
||||
When an _anchor_ is provided by itself, the current page’s unique identifier will be appended; when an _anchor_ is provided with a document name, the found page's unique identifier will be appended.
|
||||
|
||||
{{</* relref "#who" */>}} ⇒ `#who:9decaf7`
|
||||
{{</* relref "blog/post.md#who" */>}} ⇒ `/blog/post/#who:badcafe`
|
||||
|
||||
More information about document unique identifiers and headings can be found [below]({{< ref "#hugo-heading-anchors" >}}).
|
||||
|
||||
### Examples
|
||||
|
||||
* `{{</* ref "blog/post.md" */>}}` ⇒ `http://1.com/blog/post/`
|
||||
* `{{</* ref "post.md#tldr" */>}}` ⇒ `http://1.com/blog/post/#tldr:caffebad`
|
||||
* `{{</* relref "post.md" */>}}` ⇒ `/blog/post/`
|
||||
* `{{</* relref "blog/post.md#tldr" */>}}` ⇒ `/blog/post/#tldr:caffebad`
|
||||
* `{{</* ref "#tldr" */>}}` ⇒ `#tldr:badcaffe`
|
||||
* `{{</* relref "#tldr" */>}}` ⇒ `#tldr:badcaffe`
|
||||
|
||||
## Hugo Heading Anchors
|
||||
|
||||
When using Markdown document types, Hugo generates heading anchors automatically. The generated anchor for this section is `hugo-heading-anchors`. Because the heading anchors are generated automatically, Hugo takes some effort to ensure that heading anchors are unique both inside a document and across the entire site.
|
||||
|
||||
Ensuring heading uniqueness across the site is accomplished with a unique identifier for each document based on its path. Unless a document is renamed or moved between sections *in the filesystem*, the unique identifier for the document will not change: `blog/post.md` will always have a unique identifier of `81df004c333b392d34a49fd3a91ba720`.
|
||||
|
||||
`ref` and `relref` were added so you can make these reference links without having to know the document’s unique identifier. (The links in document tables of contents are automatically up-to-date with this value.)
|
||||
|
||||
{{</* relref "extras/crossreferences.md#hugo-heading-anchors" */>}}
|
||||
/extras/crossreferences/#hugo-heading-anchors:77cd9ea530577debf4ce0f28c8dca242
|
||||
|
||||
> What follows is a deeper discussion of *why* and *how* Hugo generates heading anchors. It is not necessary to know this to use `ref` and `relref`, but it may be useful in understanding how some anchors may not match your expectations.
|
||||
|
||||
### How to Generate a Heading Anchor
|
||||
|
||||
Convert the text of the heading to lowercase.
|
||||
|
||||
Hugo: A Fast & Modern Static Web Engine
|
||||
hugo: a fast & modern static web engine
|
||||
|
||||
Replace anything that isn't an ASCII letter (`a-z`) or number (`0-9`) with a dash (`-`).
|
||||
|
||||
hugo: a fast & modern static web engine
|
||||
hugo--a-fast---modern-static-web-engine
|
||||
|
||||
Get rid of extra dashes.
|
||||
|
||||
hugo--a-fast---modern-static-web-engine
|
||||
hugo-a-fast-modern-static-web-engine
|
||||
|
||||
You have just converting the text of a heading to a suitable anchor. If your document has unique heading text, all of the anchors will be unique, too.
|
||||
|
||||
#### Specifying Heading Anchors
|
||||
|
||||
You can also tell Hugo to use a particular heading anchor.
|
||||
|
||||
# Hugo: A Fast & Modern Static Web Engine {#hugo-main}
|
||||
|
||||
Hugo will use `hugo-main` as the heading anchor.
|
||||
|
||||
### What About Duplicate Heading Anchors?
|
||||
|
||||
The technique outlined above works well enough, but some documents have headings with identical text, like the [shortcodes](/extras/shortcodes/) page—there are three headings with the text "Example". You can specify heading anchors manually:
|
||||
|
||||
### Example {#example-1}
|
||||
### Example {#example-2}
|
||||
### Example {#example-3}
|
||||
|
||||
It’s easy to forget to do that all the time, and Hugo is smart enough to do it for you. It just adds `-x` to the end of each heading it has already seen.
|
||||
|
||||
* `### Example` ⇒ `example`
|
||||
* `### Example` ⇒ `example-1`
|
||||
* `### Example` ⇒ `example-2`
|
||||
|
||||
Sometimes it's a little harder, but Hugo can recover from those, too, by adding more suffixes:
|
||||
|
||||
* `# Heading` ⇒ `heading`
|
||||
* `# Heading 1` ⇒ `heading-1`
|
||||
* `# Heading` ⇒ `heading-1-1`
|
||||
* `# Heading` ⇒ `heading-1-2`
|
||||
* `# Heading 1` ⇒ `heading-2`
|
||||
|
||||
This can even affect specified heading anchors that come after a generated heading anchor.
|
||||
|
||||
* `# My Heading` ⇒ `my-heading`
|
||||
* `# My Heading {#my-heading}` ⇒ `my-heading-1`
|
||||
|
||||
> This particular collision and override is unfortunate, but unavoidable because Hugo processes each heading for collision detection as it sees it during conversion.
|
||||
|
||||
This technique works well for documents rendered on individual pages, like blog posts. What about on Hugo list pages?
|
||||
|
||||
### Unique Heading Anchors in Lists
|
||||
|
||||
Hugo converts each document from Markdown independently. it doesn’t know that `blog/post.md` has an "Example" heading that will collide with the "Example" heading in `blog/post2.md`. Even if it did know this, the addition of `blog/post3.md` should not cause the anchors for the headings in the other blog posts to change.
|
||||
|
||||
Enter the document’s unique identifier. To prevent this sort of collision on
|
||||
list pages, Hugo always appends the document's to a generated heading anchor.
|
||||
So, the "Example" heading in `blog/post.md` actually turns into
|
||||
`#example:81df004…`, and the "Example" heading in `blog/post2.md` actually
|
||||
turns into `#example:8cf1599…`. All you have to know is the heading anchor that
|
||||
was generated, not the document identifier; `ref` and `relref` take care of the
|
||||
rest for you.
|
||||
|
||||
<a href='{{</* relref "blog/post.md#example" */>}}'>Post Example</a>
|
||||
<a href='/blog/post.md#81df004…'>Post Example</a>
|
||||
|
||||
[Post Two Example]({{</* relref "blog/post2.md#example" */>}})
|
||||
<a href='/blog/post2.md#8cf1599…'>Post Two Example</a>
|
||||
|
||||
Now you know.
|
||||
@@ -1,142 +0,0 @@
|
||||
---
|
||||
aliases:
|
||||
- /doc/datadrivencontent/
|
||||
lastmod: 2016-03-03
|
||||
date: 2015-02-14
|
||||
menu:
|
||||
main:
|
||||
parent: extras
|
||||
next: /extras/gitinfo
|
||||
prev: /extras/datafiles
|
||||
title: Data-driven Content
|
||||
toc: true
|
||||
---
|
||||
|
||||
Data-driven content with a static site generator? Yes, it is possible!
|
||||
|
||||
In addition to the [data files](/extras/datafiles/) feature, we have also
|
||||
implemented the feature "Data-driven Content", which lets you load
|
||||
any [JSON](http://www.json.org/) or
|
||||
[CSV](http://en.wikipedia.org/wiki/Comma-separated_values) file
|
||||
from nearly any resource.
|
||||
|
||||
"Data-driven Content" currently consists of two functions, `getJSON`
|
||||
and `getCSV`, which are available in **all template files**.
|
||||
|
||||
## Implementation details
|
||||
|
||||
### Calling the functions with an URL
|
||||
|
||||
In any HTML template or Markdown document, call the functions like this:
|
||||
|
||||
{{ $dataJ := getJSON "url" }}
|
||||
{{ $dataC := getCSV "separator" "url" }}
|
||||
|
||||
or, if you use a prefix or postfix for the URL, the functions
|
||||
accept [variadic arguments](http://en.wikipedia.org/wiki/Variadic_function):
|
||||
|
||||
{{ $dataJ := getJSON "url prefix" "arg1" "arg2" "arg n" }}
|
||||
{{ $dataC := getCSV "separator" "url prefix" "arg1" "arg2" "arg n" }}
|
||||
|
||||
The separator for `getCSV` must be put in the first position and can only
|
||||
be one character long.
|
||||
|
||||
All passed arguments will be joined to the final URL; for example:
|
||||
|
||||
{{ $urlPre := "https://api.github.com" }}
|
||||
{{ $gistJ := getJSON $urlPre "/users/GITHUB_USERNAME/gists" }}
|
||||
|
||||
will resolve internally to:
|
||||
|
||||
{{ $gistJ := getJSON "https://api.github.com/users/GITHUB_USERNAME/gists" }}
|
||||
|
||||
Finally, you can range over an array. This example will output the
|
||||
first 5 gists for a GitHub user:
|
||||
|
||||
<ul>
|
||||
{{ $urlPre := "https://api.github.com" }}
|
||||
{{ $gistJ := getJSON $urlPre "/users/GITHUB_USERNAME/gists" }}
|
||||
{{ range first 5 $gistJ }}
|
||||
{{ if .public }}
|
||||
<li><a href="{{ .html_url }}" target="_blank">{{ .description }}</a></li>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
</ul>
|
||||
|
||||
|
||||
### Example for CSV files
|
||||
|
||||
For `getCSV`, the one-character long separator must be placed in the
|
||||
first position followed by the URL.
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Position</th>
|
||||
<th>Salary</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{ $url := "http://a-big-corp.com/finance/employee-salaries.csv" }}
|
||||
{{ $sep := "," }}
|
||||
{{ range $i, $r := getCSV $sep $url }}
|
||||
<tr>
|
||||
<td>{{ index $r 0 }}</td>
|
||||
<td>{{ index $r 1 }}</td>
|
||||
<td>{{ index $r 2 }}</td>
|
||||
</tr>
|
||||
{{ end }}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
The expression `{{index $r number}}` must be used to output the nth-column from
|
||||
the current row.
|
||||
|
||||
### Caching of URLs
|
||||
|
||||
Each downloaded URL will be cached in the default folder `$TMPDIR/hugo_cache/`.
|
||||
The variable `$TMPDIR` will be resolved to your system-dependent
|
||||
temporary directory.
|
||||
|
||||
With the command-line flag `--cacheDir`, you can specify any folder on
|
||||
your system as a caching directory.
|
||||
|
||||
You can also set `cacheDir` in the main configuration file.
|
||||
|
||||
If you don't like caching at all, you can fully disable caching with the
|
||||
command line flag `--ignoreCache`.
|
||||
|
||||
### Authentication when using REST URLs
|
||||
|
||||
Currently, you can only use those authentication methods that can
|
||||
be put into an URL. [OAuth](http://en.wikipedia.org/wiki/OAuth) or
|
||||
other authentication methods are not implemented.
|
||||
|
||||
### Loading local files
|
||||
|
||||
To load local files with the two functions `getJSON` and `getCSV`, the
|
||||
source files must reside within Hugo's working directory. The file
|
||||
extension does not matter but the content does.
|
||||
|
||||
It applies the same output logic as in the topic: *Calling the functions with an URL*.
|
||||
|
||||
## LiveReload
|
||||
|
||||
There is no chance to trigger a [LiveReload](/extras/livereload/) when
|
||||
the content of an URL changes. However, when a local JSON/CSV file changes,
|
||||
then a LiveReload will be triggered of course. Symlinks are not supported.
|
||||
|
||||
**URLs and LiveReload**: If you change any local file and the LiveReload
|
||||
is triggered, Hugo will either read the URL content from the cache or, if
|
||||
you have disabled the cache, Hugo will re-download the content.
|
||||
This can create huge traffic and you may also reach API limits quickly.
|
||||
|
||||
As downloading of content takes a while, Hugo stops processing
|
||||
your Markdown files until the content has been downloaded.
|
||||
|
||||
## Examples
|
||||
|
||||
- Photo gallery JSON powered: [https://github.com/pcdummy/hugo-lightslider-example](https://github.com/pcdummy/hugo-lightslider-example)
|
||||
- GitHub Starred Repositories [in a posts](https://github.com/SchumacherFM/blog-cs/blob/master/content%2Fposts%2Fgithub-starred.md) with the related [short code](https://github.com/SchumacherFM/blog-cs/blob/master/layouts%2Fshortcodes%2FghStarred.html).
|
||||
- More? Please tell us!
|
||||
@@ -1,106 +0,0 @@
|
||||
---
|
||||
aliases:
|
||||
- /doc/datafiles/
|
||||
lastmod: 2015-08-04
|
||||
date: 2015-01-22
|
||||
menu:
|
||||
main:
|
||||
parent: extras
|
||||
next: /extras/datadrivencontent
|
||||
prev: /extras/robots-txt
|
||||
title: Data Files
|
||||
---
|
||||
|
||||
In addition to the [built-in variables](/templates/variables/) available from Hugo, you can specify your own custom data that can be accessed via templates or shortcodes.
|
||||
|
||||
Hugo supports loading data from [YAML](http://yaml.org/), [JSON](http://www.json.org/), and [TOML](https://github.com/toml-lang/toml) files located in the `data` directory.
|
||||
|
||||
**It even works with [LiveReload](/extras/livereload/).**
|
||||
|
||||
Data Files can also be used in [themes](/themes/overview/), but note: If the same `key` is used in both the main data folder and in the theme's data folder, the main one will win. So, for theme authors, for theme specific data items that shouldn't be overridden, it can be wise to prefix the folder structure with a namespace, e.g. `mytheme/data/mytheme/somekey/...`. To check if any such duplicate exists, run hugo with the `-v` flag, e.g. `hugo -v`.
|
||||
|
||||
## The Data Folder
|
||||
|
||||
The `data` folder is where you can store additional data for Hugo to use when generating your site. Data files aren't used to generate standalone pages - rather they're meant supplemental to the content files. This feature can extend the content in case your frontmatter would grow immensely. Or perhaps your want to show a larger dataset in a template (see example below). In both cases it's a good idea to outsource the data in their own file.
|
||||
|
||||
These files must be YAML, JSON or TOML files (using either the `.yml`, `.yaml`, `.json` or `toml` extension) and the data will be accessible as a `map` in `.Site.Data`.
|
||||
|
||||
**The keys in this map will be a dot chained set of _path_, _filename_ and _key_ in file (if applicable).**
|
||||
|
||||
This is best explained with an example:
|
||||
|
||||
## Example: Jaco Pastorius' Solo Discography
|
||||
|
||||
[Jaco Pastorius](http://en.wikipedia.org/wiki/Jaco_Pastorius_discography) was a great bass player, but his solo discography is short enough to use as an example. [John Patitucci](http://en.wikipedia.org/wiki/John_Patitucci) is another bass giant.
|
||||
|
||||
The example below is a bit constructed, but it illustrates the flexibility of Data Files. It uses TOML as file format.
|
||||
|
||||
Given the files:
|
||||
|
||||
* `data/jazz/bass/jacopastorius.toml`
|
||||
* `data/jazz/bass/johnpatitucci.toml`
|
||||
|
||||
`jacopastorius.toml` contains the content below, `johnpatitucci.toml` contains a similar list:
|
||||
|
||||
```
|
||||
discography = [
|
||||
"1974 – Modern American Music … Period! The Criteria Sessions",
|
||||
"1974 – Jaco",
|
||||
"1976 - Jaco Pastorius",
|
||||
"1981 - Word of Mouth",
|
||||
"1981 - The Birthday Concert (released in 1995)",
|
||||
"1982 - Twins I & II (released in 1999)",
|
||||
"1983 - Invitation",
|
||||
"1986 - Broadway Blues (released in 1998)",
|
||||
"1986 - Honestly Solo Live (released in 1990)",
|
||||
"1986 - Live In Italy (released in 1991)",
|
||||
"1986 - Heavy'n Jazz (released in 1992)",
|
||||
"1991 - Live In New York City, Volumes 1-7.",
|
||||
"1999 - Rare Collection (compilation)",
|
||||
"2003 - Punk Jazz: The Jaco Pastorius Anthology (compilation)",
|
||||
"2007 - The Essential Jaco Pastorius (compilation)"
|
||||
]
|
||||
```
|
||||
|
||||
The list of bass players can be accessed via `.Site.Data.jazz.bass`, a single bass player by adding the filename without the suffix, e.g. `.Site.Data.jazz.bass.jacopastorius`.
|
||||
|
||||
You can now render the list of recordings for all the bass players in a template:
|
||||
|
||||
```
|
||||
{{ range $.Site.Data.jazz.bass }}
|
||||
{{ partial "artist.html" . }}
|
||||
{{ end }}
|
||||
```
|
||||
|
||||
And then in `partial/artist.html`:
|
||||
|
||||
```
|
||||
<ul>
|
||||
{{ range .discography }}
|
||||
<li>{{ . }}</li>
|
||||
{{ end }}
|
||||
</ul>
|
||||
```
|
||||
|
||||
Discover a new favourite bass player? Just add another TOML-file.
|
||||
|
||||
## Example: Accessing named values in a Data File
|
||||
|
||||
Assuming you have the following YAML structure to your `User0123.yml` Data File located directly in `data/`
|
||||
|
||||
```
|
||||
Name: User0123
|
||||
"Short Description": "He is a **jolly good** fellow."
|
||||
Achievements:
|
||||
- "Can create a Key, Value list from Data File"
|
||||
- "Learns Hugo"
|
||||
- "Reads documentation"
|
||||
```
|
||||
|
||||
To render the `Short Description` in your `layout` File following code is required.
|
||||
|
||||
```
|
||||
<div>Short Description of {{.Site.Data.User0123.Name}}: <p>{{ index .Site.Data.User0123 "Short Description" | markdownify }}</p></div>
|
||||
```
|
||||
|
||||
Note the use of the `markdownify` template function. This will send the description through the Blackfriday Markdown rendering engine.
|
||||
@@ -1,50 +0,0 @@
|
||||
---
|
||||
aliases:
|
||||
- /doc/gitinfo/
|
||||
lastmod: 2016-12-11
|
||||
date: 2016-12-11
|
||||
menu:
|
||||
main:
|
||||
parent: extras
|
||||
next: /extras/livereload
|
||||
prev: /extras/datadrivencontent
|
||||
title: GitInfo
|
||||
---
|
||||
|
||||
Hugo provides a way to integrate Git data into your site.
|
||||
|
||||
|
||||
## Prerequisites
|
||||
|
||||
1. The Hugo site must be in a Git-enabled directory.
|
||||
1. The Git executable must be installed and in your system `PATH`.
|
||||
1. Enable the GitInfo feature in Hugo by using `--enableGitInfo` on the command
|
||||
line or by setting `enableGitInfo` to `true` in your site configuration.
|
||||
|
||||
## The GitInfo Object
|
||||
|
||||
The `GitInfo` object contains the following fields:
|
||||
|
||||
AbbreviatedHash
|
||||
: abbreviated commit hash, e.g. `866cbcc`
|
||||
|
||||
AuthorName
|
||||
: author name, respecting `.mailmap`
|
||||
|
||||
AuthorEmail
|
||||
: author email address, respecting `.mailmap`
|
||||
|
||||
AuthorDate
|
||||
: the author date
|
||||
|
||||
Hash
|
||||
: commit hash, e.g. `866cbccdab588b9908887ffd3b4f2667e94090c3`
|
||||
|
||||
Subject
|
||||
: commit message subject, e.g. `tpl: Add custom index function`
|
||||
|
||||
|
||||
## Performance Considerations
|
||||
|
||||
The Git integrations should be fairly performant, but it does add some time to the build, which depends somewhat on the Git history size.
|
||||
|
||||
@@ -1,197 +0,0 @@
|
||||
---
|
||||
aliases:
|
||||
- /extras/highlight/
|
||||
lastmod: 2015-10-27
|
||||
date: 2013-07-01
|
||||
menu:
|
||||
main:
|
||||
parent: extras
|
||||
next: /extras/toc
|
||||
prev: /extras/shortcodes
|
||||
title: Syntax Highlighting
|
||||
toc: true
|
||||
---
|
||||
|
||||
Hugo provides the ability for you to highlight source code in _two different ways_ — either pre-processed server side from your content, or to defer the processing to the client side, using a JavaScript library.
|
||||
|
||||
**The advantage of server side** is that it doesn’t depend on a JavaScript library and consequently works very well when read from an RSS feed.
|
||||
|
||||
**The advantage of client side** is that it doesn’t cost anything when building your site and some of the highlighting scripts available cover more languages than Pygments does.
|
||||
|
||||
## Server-side
|
||||
|
||||
For the pre-processed approach, highlighting is performed by an external Python-based program called [Pygments](http://pygments.org/) and is triggered via an embedded Hugo shortcode (see example below). If Pygments is absent from the path, it will silently simply pass the content along unhighlighted.
|
||||
|
||||
### Pygments
|
||||
|
||||
If you have never worked with Pygments before, here is a brief primer:
|
||||
|
||||
+ Install Python from [python.org](https://www.python.org/downloads/). Version 2.7.x is already sufficient.
|
||||
+ Run `pip install Pygments` in order to install Pygments. Once installed, Pygments gives you a command `pygmentize`. Make sure it sits in your PATH, otherwise Hugo cannot find it.
|
||||
|
||||
On Debian and Ubuntu systems, you may also install Pygments by running `sudo apt-get install python3-pygments`.
|
||||
|
||||
Hugo gives you two options that you can set with the variable `pygmentsuseclasses` (default `false`) in `config.toml` (or `config.yaml`).
|
||||
|
||||
1. Color-codes for highlighting keywords are directly inserted if `pygmentsuseclasses = false` (default). See in the example below. The color-codes depend on your choice of the `pygmentsstyle` (default `"monokai"`). You can explore the different color styles on [pygments.org](http://pygments.org/) after inserting some example code.
|
||||
2. If you choose `pygmentsuseclasses = true`, Hugo includes class names in your code instead of color-codes. For class-names to be meaningful, you need to include a `.css`-file in your website representing your color-scheme. You can either generate this `.css`-files according to this [description](http://pygments.org/docs/cmdline/) or download the standard ones from the [GitHub pygments-css repository](https://github.com/richleland/pygments-css).
|
||||
|
||||
### Usage
|
||||
|
||||
Highlighting is carried out via the in-built shortcode `highlight`. `highlight` takes exactly one required parameter of language, and requires a closing shortcode. Note that `highlight` is _not_ used for client-side javascript highlighting.
|
||||
|
||||
### Example
|
||||
|
||||
```
|
||||
{{</* highlight html */>}}
|
||||
<section id="main">
|
||||
<div>
|
||||
<h1 id="title">{{ .Title }}</h1>
|
||||
{{ range .Data.Pages }}
|
||||
{{ .Render "summary"}}
|
||||
{{ end }}
|
||||
</div>
|
||||
</section>
|
||||
{{</* /highlight */>}}
|
||||
```
|
||||
|
||||
### Example Output
|
||||
|
||||
```
|
||||
<span style="color: #f92672"><section</span> <span style="color: #a6e22e">id=</span><span style="color: #e6db74">"main"</span><span style="color: #f92672">></span>
|
||||
<span style="color: #f92672"><div></span>
|
||||
<span style="color: #f92672"><h1</span> <span style="color: #a6e22e">id=</span><span style="color: #e6db74">"title"</span><span style="color: #f92672">></span>{{ .Title }}<span style="color: #f92672"></h1></span>
|
||||
{{ range .Data.Pages }}
|
||||
{{ .Render "summary"}}
|
||||
{{ end }}
|
||||
<span style="color: #f92672"></div></span>
|
||||
<span style="color: #f92672"></section></span>
|
||||
```
|
||||
|
||||
### Options
|
||||
|
||||
Options to control highlighting can be added as a quoted, comma separated key-value list as the second argument in the shortcode. The example below will highlight as language `go` with inline line numbers, with line number 2 and 3 highlighted.
|
||||
|
||||
```
|
||||
{{</* highlight go "linenos=inline,hl_lines=2 3" */>}}
|
||||
var a string
|
||||
var b string
|
||||
var c string
|
||||
var d string
|
||||
{{</* / highlight */>}}
|
||||
```
|
||||
|
||||
Supported keywords: `style`, `encoding`, `noclasses`, `hl_lines`, `linenos`. Note that `style` and `noclasses` will override the similar setting in the global config.
|
||||
|
||||
The keywords are the same you would using with Pygments from the command line, see the [Pygments doc](http://pygments.org/docs/) for more info.
|
||||
|
||||
### Code fences
|
||||
|
||||
It is also possible to add syntax highlighting with GitHub flavoured code fences. To enable this, set the `PygmentsCodeFences` to `true` in Hugo's configuration file.
|
||||
|
||||
````
|
||||
``` html
|
||||
<section id="main">
|
||||
<div>
|
||||
<h1 id="title">{{ .Title }}</h1>
|
||||
{{ range .Data.Pages }}
|
||||
{{ .Render "summary"}}
|
||||
{{ end }}
|
||||
</div>
|
||||
</section>
|
||||
```
|
||||
````
|
||||
|
||||
### Disclaimers
|
||||
|
||||
* Pygments is relatively slow and _causes a performance hit when building your site_, but Hugo has been designed to cache the results to disk.
|
||||
* The caching can be turned off by setting the `--ignoreCache` flag to `true`.
|
||||
* Languages available depends on your Pygments installation.
|
||||
|
||||
## Client-side
|
||||
|
||||
Alternatively, code highlighting can be done in client-side JavaScript.
|
||||
|
||||
Client-side syntax highlighting is very simple to add. You'll need to pick
|
||||
a library and a corresponding theme. Some popular libraries are:
|
||||
|
||||
- [Highlight.js]
|
||||
- [Prism]
|
||||
- [Rainbow]
|
||||
- [Syntax Highlighter]
|
||||
- [Google Prettify]
|
||||
|
||||
### Highlight.js example
|
||||
|
||||
This example uses the popular [Highlight.js] library, hosted by [Yandex], a popular Russian search engine.
|
||||
|
||||
In your `./layouts/partials/` (or `./layouts/chrome/`) folder, depending on your specific theme, there will be a snippet that will be included in every generated HTML page, such as `header.html` or `header.includes.html`. Simply add the css and js to initialize [Highlight.js]:
|
||||
|
||||
~~~
|
||||
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.6.0/styles/default.min.css">
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.6.0/highlight.min.js"></script>
|
||||
<script>hljs.initHighlightingOnLoad();</script>
|
||||
~~~
|
||||
|
||||
### Prism example
|
||||
|
||||
Prism is another popular highlighter library, used on some major sites. Similar to Highlight.js, you simply load `prism.css` in your `<head>` via whatever Hugo partial template is creating that part of your pages, like so:
|
||||
|
||||
```html
|
||||
...
|
||||
<link href="/css/prism.css" rel="stylesheet" />
|
||||
...
|
||||
```
|
||||
|
||||
... and add `prism.js` near the bottom of your `<body>` tag, again in whatever Hugo partial template is appropriate for your site or theme.
|
||||
|
||||
```html
|
||||
...
|
||||
<script src="/js/prism.js"></script>
|
||||
...
|
||||
</body>
|
||||
```
|
||||
|
||||
In this example, the local paths indicate that your own copy of these files are being added to the site, typically under `./static/`.
|
||||
|
||||
### Using Client-side highlighting
|
||||
|
||||
To use client-side highlighting, most of these javascript libraries expect your code to be wrapped in semantically correct `<code>` tags, with the language expressed in a class attribute on the `<code>` tag, such as `class="language-abc"`, where the `abc` is the code the highlighter script uses to represent that language.
|
||||
|
||||
The script would be looking for classes like `language-go`, `language-html`, or `language-css`. If you look at the page's source, it would be marked up like so:
|
||||
|
||||
~~~html
|
||||
<pre>
|
||||
<code class="language-css">
|
||||
body {
|
||||
font-family: "Noto Sans", sans-serif;
|
||||
}
|
||||
</code>
|
||||
</pre>
|
||||
~~~
|
||||
|
||||
The markup in your content pages (e.g. `my-css-tutorial.md`) needs to look like the following, with the name of the language to be highlighted entered directly after the first "fence", in a fenced code block:
|
||||
|
||||
<pre><code class="language-css">~~~css
|
||||
body {
|
||||
font-family: "Noto Sans", sans-serif;
|
||||
}
|
||||
~~~</code></pre>
|
||||
|
||||
When passed through the highlighter script, it would yield something like this output when viewed on your rendered page:
|
||||
|
||||
~~~css
|
||||
body {
|
||||
font-family: "Noto Sans", sans-serif;
|
||||
}
|
||||
~~~
|
||||
|
||||
Please see individual libraries' documentation for how to implement each of the JavaScript-based libraries.
|
||||
|
||||
[Prism]: http://prismjs.com
|
||||
[Highlight.js]: http://highlightjs.org/
|
||||
[Rainbow]: http://craig.is/making/rainbows
|
||||
[Syntax Highlighter]: http://alexgorbatchev.com/SyntaxHighlighter/
|
||||
[Google Prettify]: https://github.com/google/code-prettify
|
||||
[Yandex]: http://yandex.ru/
|
||||
|
||||
@@ -1,74 +0,0 @@
|
||||
---
|
||||
lastmod: 2016-08-09
|
||||
date: 2014-05-26
|
||||
menu:
|
||||
main:
|
||||
parent: extras
|
||||
next: /extras/menus
|
||||
prev: /extras/gitinfo
|
||||
title: LiveReload
|
||||
---
|
||||
|
||||
Hugo may not be the first static site generator to utilize LiveReload
|
||||
technology, but it’s the first to do it right.
|
||||
|
||||
The combination of Hugo’s insane build speed and LiveReload make
|
||||
crafting your content pure joy. Virtually instantly after you hit save
|
||||
your rebuilt content will appear in your browser.
|
||||
|
||||
## Using LiveReload
|
||||
|
||||
Hugo comes with LiveReload built in. There are no additional packages to
|
||||
install. A common way to use Hugo while developing a site is to have
|
||||
Hugo run a server and watch for changes:
|
||||
|
||||
{{< nohighlight >}}$ hugo server
|
||||
{{< /nohighlight >}}
|
||||
|
||||
This will run a full functioning web server while simultaneously
|
||||
watching your file system for additions, deletions or changes within
|
||||
your:
|
||||
|
||||
* static files
|
||||
* content
|
||||
* data files
|
||||
* layouts
|
||||
* current theme
|
||||
* configuration files
|
||||
|
||||
Whenever anything changes, Hugo will rebuild the site while continuing to serve
|
||||
the content. As soon as the build is finished, it will tell the
|
||||
browser and silently reload the page. Because most Hugo builds are so
|
||||
fast they are barely noticeable, you merely need to glance at your open
|
||||
browser and you will see the change, already there.
|
||||
|
||||
This means that keeping the site open on a second monitor (or another
|
||||
half of your current monitor) allows you to see exactly what your
|
||||
content looks like, without even leaving your text editor.
|
||||
|
||||
## Disabling Watch
|
||||
|
||||
If for some reason you don't want the Hugo server's watch functionality,
|
||||
just do:
|
||||
|
||||
{{< nohighlight >}}$ hugo server --watch=false
|
||||
{{< /nohighlight >}}
|
||||
|
||||
## Disabling LiveReload
|
||||
|
||||
LiveReload works by injecting JavaScript into the pages Hugo generates,
|
||||
which creates a connection from the browser web socket client to the
|
||||
Hugo web socket server.
|
||||
|
||||
Awesome for development, but not something you would want to do in
|
||||
production. Since many people use `hugo server` in production to
|
||||
instantly display any updated content, we’ve made it easy to disable the
|
||||
LiveReload functionality:
|
||||
|
||||
{{< nohighlight >}}$ hugo server --disableLiveReload
|
||||
{{< /nohighlight >}}
|
||||
|
||||
## Notes
|
||||
|
||||
You must have a closing `</body>` tag for LiveReload to work.
|
||||
Hugo injects the LiveReload `<script>` before this tag.
|
||||
@@ -1,57 +0,0 @@
|
||||
---
|
||||
aliases:
|
||||
- /doc/localfiles/
|
||||
lastmod: 2016-09-12
|
||||
date: 2015-06-12
|
||||
menu:
|
||||
main:
|
||||
parent: extras
|
||||
next: /extras/urls
|
||||
notoc: true
|
||||
prev: /extras/toc
|
||||
title: Traversing Local Files
|
||||
---
|
||||
## Traversing Local Files
|
||||
|
||||
Using Hugo's function `readDir`,
|
||||
you can traverse your web site's files on your server.
|
||||
## Using _readDir_
|
||||
|
||||
The `readDir` function returns an array
|
||||
of [`os.FileInfo`](https://golang.org/pkg/os/#FileInfo).
|
||||
It takes a single, string argument: a path.
|
||||
This path can be to any directory of your web site
|
||||
(as found on your server's filesystem).
|
||||
|
||||
Whether the path is absolute or relative makes no difference,
|
||||
because—at least for `readDir`—the root of your web site (typically `./public/`)
|
||||
in effect becomes both:
|
||||
|
||||
1. The filesystem root; and
|
||||
1. The current working directory.
|
||||
|
||||
## New Shortcode
|
||||
|
||||
So, let's create a new shortcode using `readDir`:
|
||||
|
||||
**layouts/shortcodes/directoryindex.html**
|
||||
```html
|
||||
{{< readfile "layouts/shortcodes/directoryindex.html" >}}
|
||||
```
|
||||
For the files in any given directory,
|
||||
this shortcode usefully lists their basenames and sizes,
|
||||
while providing links to them.
|
||||
|
||||
Already—actually—this shortcode
|
||||
has been included in this very web site.
|
||||
So, let's list some of its CSS files.
|
||||
(If you click on their names, you can reveal the contents.)
|
||||
{{< directoryindex path="/static/css" pathURL="/css" >}}
|
||||
<br />
|
||||
This is the call that rendered the above output:
|
||||
```html
|
||||
{{</* directoryindex path="/static/css" pathURL="/css" */>}}
|
||||
```
|
||||
By the way,
|
||||
regarding the pathURL argument, the initial slash `/` is important.
|
||||
Otherwise, it becomes relative to the current web page.
|
||||
@@ -1,234 +0,0 @@
|
||||
---
|
||||
lastmod: 2015-08-04
|
||||
date: 2014-05-14T02:36:37Z
|
||||
toc: true
|
||||
menu:
|
||||
main:
|
||||
parent: extras
|
||||
next: /extras/pagination
|
||||
prev: /extras/livereload
|
||||
title: Menus
|
||||
---
|
||||
|
||||
Hugo has a simple yet powerful menu system that permits content to be
|
||||
placed in menus with a good degree of control without a lot of work.
|
||||
|
||||
|
||||
*TIP:* If all you want is a simple menu for your sections, see [Section Menu for "the Lazy Blogger"]({{< relref "#section-menu-for-the-lazy-blogger" >}}).
|
||||
|
||||
Some of the features of Hugo Menus:
|
||||
|
||||
* Place content in one or many menus
|
||||
* Handle nested menus with unlimited depth
|
||||
* Create menu entries without being attached to any content
|
||||
* Distinguish active element (and active branch)
|
||||
|
||||
## What is a menu?
|
||||
|
||||
A menu is a named array of menu entries accessible on the site under
|
||||
`.Site.Menus` by name. For example, if I have a menu called `main`, I would
|
||||
access it via `.Site.Menus.main`.
|
||||
|
||||
If you make use of the [multilingual feature]({{< relref "content/multilingual.md#menus">}}) you can define menus language independent.
|
||||
|
||||
A menu entry has the following properties:
|
||||
|
||||
* **URL** string
|
||||
* **Name** string
|
||||
* **Menu** string
|
||||
* **Identifier** string
|
||||
* **Pre** template.HTML
|
||||
* **Post** template.HTML
|
||||
* **Weight** int
|
||||
* **Parent** string
|
||||
* **Children** Menu
|
||||
|
||||
And the following functions:
|
||||
|
||||
* **HasChildren** bool
|
||||
|
||||
Additionally, there are some relevant functions available on the page:
|
||||
|
||||
* **IsMenuCurrent** (menu string, menuEntry *MenuEntry ) bool
|
||||
* **HasMenuCurrent** (menu string, menuEntry *MenuEntry) bool
|
||||
|
||||
|
||||
## Adding content to menus
|
||||
|
||||
Hugo supports a couple of different methods of adding a piece of content
|
||||
to the front matter.
|
||||
|
||||
### Simple
|
||||
|
||||
If all you need to do is add an entry to a menu, the simple form works
|
||||
well.
|
||||
|
||||
**A single menu:**
|
||||
|
||||
---
|
||||
menu: "main"
|
||||
---
|
||||
|
||||
**Multiple menus:**
|
||||
|
||||
---
|
||||
menu: ["main", "footer"]
|
||||
---
|
||||
|
||||
|
||||
### Advanced
|
||||
|
||||
If more control is required, then the advanced approach gives you the
|
||||
control you want. All of the menu entry properties listed above are
|
||||
available.
|
||||
|
||||
---
|
||||
menu:
|
||||
main:
|
||||
parent: 'extras'
|
||||
weight: 20
|
||||
---
|
||||
|
||||
|
||||
## Adding (non-content) entries to a menu
|
||||
|
||||
You can also add entries to menus that aren’t attached to a piece of
|
||||
content. This takes place in the sitewide [config file](/overview/configuration/).
|
||||
|
||||
Here’s an example `config.toml`:
|
||||
|
||||
[[menu.main]]
|
||||
name = "about hugo"
|
||||
pre = "<i class='fa fa-heart'></i>"
|
||||
weight = -110
|
||||
identifier = "about"
|
||||
url = "/about/"
|
||||
[[menu.main]]
|
||||
name = "getting started"
|
||||
pre = "<i class='fa fa-road'></i>"
|
||||
weight = -100
|
||||
url = "/getting-started/"
|
||||
|
||||
And the equivalent example `config.yaml`:
|
||||
|
||||
---
|
||||
menu:
|
||||
main:
|
||||
- Name: "about hugo"
|
||||
Pre: "<i class='fa fa-heart'></i>"
|
||||
Weight: -110
|
||||
Identifier: "about"
|
||||
URL: "/about/"
|
||||
- Name: "getting started"
|
||||
Pre: "<i class='fa fa-road'></i>"
|
||||
Weight: -100
|
||||
URL: "/getting-started/"
|
||||
---
|
||||
|
||||
|
||||
**NOTE:** The URLs must be relative to the context root. If the `baseURL` is `http://example.com/mysite/`, then the URLs in the menu must not include the context root `mysite`. Using an absolute URL will overide the baseURL. If the `URL` is `http://subdomain.example.com/`, the output will be `http://subdomain.example.com`.
|
||||
|
||||
## Nesting
|
||||
|
||||
All nesting of content is done via the `parent` field.
|
||||
|
||||
The parent of an entry should be the identifier of another entry.
|
||||
Identifier should be unique (within a menu).
|
||||
|
||||
The following order is used to determine an Identifier:
|
||||
|
||||
> Name > LinkTitle > Title.
|
||||
|
||||
This means that the title will be used unless
|
||||
linktitle is present, etc. In practice Name and Identifier are never
|
||||
displayed and only used to structure relationships.
|
||||
|
||||
In this example, the top level of the menu is defined in the config file
|
||||
and all content entries are attached to one of these entries via the
|
||||
`parent` field.
|
||||
|
||||
## Rendering menus
|
||||
|
||||
Hugo makes no assumptions about how your rendered HTML will be
|
||||
structured. Instead, it provides all of the functions you will need to be
|
||||
able to build your menu however you want.
|
||||
|
||||
|
||||
The following is an example:
|
||||
|
||||
<!--sidebar start-->
|
||||
<aside>
|
||||
<div id="sidebar" class="nav-collapse">
|
||||
<!-- sidebar menu start-->
|
||||
<ul class="sidebar-menu">
|
||||
{{ $currentPage := . }}
|
||||
{{ range .Site.Menus.main }}
|
||||
{{ if .HasChildren }}
|
||||
|
||||
<li class="sub-menu{{if $currentPage.HasMenuCurrent "main" . }} active{{end}}">
|
||||
<a href="javascript:;" class="">
|
||||
{{ .Pre }}
|
||||
<span>{{ .Name }}</span>
|
||||
<span class="menu-arrow arrow_carrot-right"></span>
|
||||
</a>
|
||||
<ul class="sub">
|
||||
{{ range .Children }}
|
||||
<li{{if $currentPage.IsMenuCurrent "main" . }} class="active"{{end}}><a href="{{.URL}}"> {{ .Name }} </a> </li>
|
||||
{{ end }}
|
||||
</ul>
|
||||
{{else}}
|
||||
<li>
|
||||
<a href="{{.URL}}">
|
||||
{{ .Pre }}
|
||||
<span>{{ .Name }}</span>
|
||||
</a>
|
||||
{{end}}
|
||||
</li>
|
||||
{{end}}
|
||||
<li> <a href="https://github.com/spf13/hugo/issues" target="blank">Questions and Issues</a> </li>
|
||||
<li> <a href="#" target="blank">Edit this Page</a> </li>
|
||||
</ul>
|
||||
<!-- sidebar menu end-->
|
||||
</div>
|
||||
</aside>
|
||||
<!--sidebar end-->
|
||||
|
||||
> **Note**: use the `absLangURL` or `relLangURL` if your theme makes use of the [multilingual feature]({{< relref "content/multilingual.md" >}}). In contrast to `absURL` and `relURL` it adds the correct language prefix to the url. [Read more]({{< relref "templates/functions.md#urls" >}}).
|
||||
|
||||
## Section Menu for "the Lazy Blogger"
|
||||
|
||||
To enable this menu, add this to your site config, i.e. `config.toml`:
|
||||
|
||||
```
|
||||
SectionPagesMenu = "main"
|
||||
```
|
||||
|
||||
The menu name can be anything, but take a note of what it is.
|
||||
|
||||
This will create a menu with all the sections as menu items and all the sections' pages as "shadow-members". The _shadow_ implies that the pages isn't represented by a menu-item themselves, but this enables you to create a top-level menu like this:
|
||||
|
||||
```
|
||||
<nav class="sidebar-nav">
|
||||
{{ $currentPage := . }}
|
||||
{{ range .Site.Menus.main }}
|
||||
<a class="sidebar-nav-item{{if or ($currentPage.IsMenuCurrent "main" .) ($currentPage.HasMenuCurrent "main" .) }} active{{end}}" href="{{.URL}}">{{ .Name }}</a>
|
||||
{{ end }}
|
||||
</nav>
|
||||
|
||||
```
|
||||
|
||||
In the above, the menu item is marked as active if on the current section's list page or on a page in that section.
|
||||
|
||||
The above is all that's needed. But if you want custom menu items, e.g. changing weight or name, you can define them manually in the site config, i.e. `config.toml`:
|
||||
|
||||
```
|
||||
[[menu.main]]
|
||||
name = "This is the blog section"
|
||||
weight = -110
|
||||
identifier = "blog"
|
||||
url = "/blog/"
|
||||
|
||||
```
|
||||
|
||||
**Note** that the `identifier` must match the section name.
|
||||
|
||||
@@ -1,106 +0,0 @@
|
||||
---
|
||||
aliases:
|
||||
- /doc/pagination/
|
||||
lastmod: 2015-07-16
|
||||
date: 2014-01-01
|
||||
menu:
|
||||
main:
|
||||
parent: extras
|
||||
next: /extras/permalinks
|
||||
prev: /extras/menus
|
||||
title: Pagination
|
||||
---
|
||||
|
||||
Hugo supports pagination for the home page, sections and taxonomies. It's built to be easy use, but with loads of flexibility when needed. The real power shines when you combine it with [`where`](/templates/functions/), with its SQL-like operators, `first` and others --- you can even [order the content](/templates/list/) the way you've become used to with Hugo.
|
||||
|
||||
## Configuration
|
||||
|
||||
Pagination can be configured in the site configuration (e.g. `config.toml`):
|
||||
|
||||
* `Paginate` (default `10`) (this setting can be overridden in the template)
|
||||
* `PaginatePath` (default `page`)
|
||||
|
||||
Setting `Paginate` to a positive value will split the list pages for the home page, sections and taxonomies into chunks of that size. But note that the generation of the pagination pages for sections, taxonomies and home page is *lazy* --- the pages will not be created if not referenced by a `.Paginator` (see below).
|
||||
|
||||
`PaginatePath` is used to adapt the `URL` to the pages in the paginator (the default setting will produce URLs on the form `/page/1/`.
|
||||
|
||||
## List the pages
|
||||
|
||||
**A `.Paginator` is provided to help building a pager menu. This is currently only relevant for the templates for the home page and the list pages (sections and taxonomies).**
|
||||
|
||||
There are two ways to configure and use a `.Paginator`:
|
||||
|
||||
1. The simplest way is just to call `.Paginator.Pages` from a template. It will contain the pages for *that page* .
|
||||
2. Select a sub-set of the pages with the available template functions and ordering options, and pass the slice to `.Paginate`, e.g. `{{ range (.Paginate ( first 50 .Data.Pages.ByTitle )).Pages }}`.
|
||||
|
||||
For a given **Page**, it's one of the options above. The `.Paginator` is static and cannot change once created.
|
||||
|
||||
The global page size setting (`Paginate`) can be overridden by providing a positive integer as the last argument. The examples below will give five items per page:
|
||||
|
||||
* `{{ range (.Paginator 5).Pages }}`
|
||||
* `{{ $paginator := .Paginate (where .Data.Pages "Type" "post") 5 }}`
|
||||
|
||||
It is also possible to use the `GroupBy` functions in combination with pagination:
|
||||
|
||||
```
|
||||
{{ range (.Paginate (.Data.Pages.GroupByDate "2006")).PageGroups }}
|
||||
```
|
||||
|
||||
## Build the navigation
|
||||
|
||||
The `.Paginator` contains enough information to build a paginator interface.
|
||||
|
||||
The easiest way to add this to your pages is to include the built-in template (with `Bootstrap`-compatible styles):
|
||||
|
||||
```
|
||||
{{ template "_internal/pagination.html" . }}
|
||||
```
|
||||
|
||||
**Note:** If you use any filters or ordering functions to create your `.Paginator` **and** you want the navigation buttons to be shown before the page listing, you must create the `.Paginator` before it's used:
|
||||
|
||||
```
|
||||
{{ $paginator := .Paginate (where .Data.Pages "Type" "post") }}
|
||||
{{ template "_internal/pagination.html" . }}
|
||||
{{ range $paginator.Pages }}
|
||||
{{ .Title }}
|
||||
{{ end }}
|
||||
```
|
||||
|
||||
Without the where-filter, the above is simpler:
|
||||
|
||||
```
|
||||
{{ template "_internal/pagination.html" . }}
|
||||
{{ range .Paginator.Pages }}
|
||||
{{ .Title }}
|
||||
{{ end }}
|
||||
```
|
||||
|
||||
If you want to build custom navigation, you can do so using the `.Paginator` object:
|
||||
|
||||
* `PageNumber`: The current page's number in the pager sequence
|
||||
* `URL`: The relative URL to the current pager
|
||||
* `Pages`: The pages in the current pager
|
||||
* `NumberOfElements`: The number of elements on this page
|
||||
* `HasPrev`: Whether there are page(s) before the current
|
||||
* `Prev`: The pager for the previous page
|
||||
* `HasNext`: Whether there are page(s) after the current
|
||||
* `Next`: The pager for the next page
|
||||
* `First`: The pager for the first page
|
||||
* `Last`: The pager for the last page
|
||||
* `Pagers`: A list of pagers that can be used to build a pagination menu
|
||||
* `PageSize`: Size of each pager
|
||||
* `TotalPages`: The number of pages in the paginator
|
||||
* `TotalNumberOfElements`: The number of elements on all pages in this paginator
|
||||
|
||||
## Additional information
|
||||
|
||||
The pages are built on the following form (`BLANK` means no value):
|
||||
|
||||
```
|
||||
[SECTION/TAXONOMY/BLANK]/index.html
|
||||
[SECTION/TAXONOMY/BLANK]/page/1/index.html => redirect to [SECTION/TAXONOMY/BLANK]/index.html
|
||||
[SECTION/TAXONOMY/BLANK]/page/2/index.html
|
||||
....
|
||||
```
|
||||
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
---
|
||||
aliases:
|
||||
- /doc/permalinks/
|
||||
lastmod: 2015-01-19
|
||||
date: 2013-11-18
|
||||
menu:
|
||||
main:
|
||||
parent: extras
|
||||
next: /extras/scratch
|
||||
notoc: true
|
||||
prev: /extras/pagination
|
||||
title: Permalinks
|
||||
---
|
||||
|
||||
By default, content is laid out into the target `publishdir` (public)
|
||||
namespace matching its layout within the `contentdir` hierarchy.
|
||||
The `permalinks` site configuration option allows you to adjust this on a
|
||||
per-section basis.
|
||||
This will change where the files are written to and will change the page's
|
||||
internal "canonical" location, such that template references to
|
||||
`.RelPermalink` will honour the adjustments made as a result of the mappings
|
||||
in this option.
|
||||
|
||||
For instance, if one of your sections is called `post`, and you want to adjust
|
||||
the canonical path to be hierarchical based on the year and month, then you
|
||||
might use:
|
||||
|
||||
```yaml
|
||||
permalinks:
|
||||
post: /:year/:month/:title/
|
||||
```
|
||||
|
||||
Only the content under `post/` will be so rewritten.
|
||||
A file named `content/post/sample-entry` which contains a line
|
||||
`date: 2013-11-18T19:20:00-05:00` might end up with the rendered page
|
||||
appearing at `public/2013/11/sample-entry/index.html` and be reachable via
|
||||
the URL <http://yoursite.example.com/2013/11/sample-entry/>.
|
||||
|
||||
The following is a list of values that can be used in a permalink definition.
|
||||
All references to time are dependent on the content's date.
|
||||
|
||||
* **:year** the 4-digit year
|
||||
* **:month** the 2-digit month
|
||||
* **:monthname** the name of the month
|
||||
* **:day** the 2-digit day
|
||||
* **:weekday** the 1-digit day of the week (Sunday = 0)
|
||||
* **:weekdayname** the name of the day of the week
|
||||
* **:yearday** the 1- to 3-digit day of the year
|
||||
* **:section** the content's section
|
||||
* **:title** the content's title
|
||||
* **:slug** the content's slug (or title if no slug)
|
||||
* **:filename** the content's filename (without extension)
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
---
|
||||
lastmod: 2016-01-06
|
||||
date: 2015-12-08
|
||||
menu:
|
||||
main:
|
||||
parent: extras
|
||||
next: /extras/datafiles
|
||||
prev: /extras/crossreferences
|
||||
title: Custom robots.txt
|
||||
---
|
||||
|
||||
Hugo can generated a customized [robots.txt](http://www.robotstxt.org/) in the
|
||||
[same way as any other templates]({{< ref "templates/go-templates.md" >}}).
|
||||
|
||||
To enable it, just set `enableRobotsTXT` option to `true` in the [configuration file]({{< ref "overview/configuration.md" >}}). By default, it generates a robots.txt, which allows everything, with the following content:
|
||||
|
||||
```http
|
||||
User-agent: *
|
||||
```
|
||||
|
||||
|
||||
Hugo will use the template `robots.txt` according to the following list in descending precedence:
|
||||
|
||||
* /layouts/robots.txt
|
||||
* /themes/`THEME`/layout/robots.txt
|
||||
|
||||
An example of a robots.txt layout is:
|
||||
|
||||
```http
|
||||
User-agent: *
|
||||
|
||||
{{range .Data.Pages}}
|
||||
Disallow: {{.RelPermalink}}{{end}}
|
||||
```
|
||||
|
||||
This template disallows and all the pages of the site creating one `Disallow` entry for each one.
|
||||
@@ -1,63 +0,0 @@
|
||||
---
|
||||
aliases:
|
||||
- /doc/scratch/
|
||||
lastmod: 2015-08-02
|
||||
date: 2015-01-22
|
||||
menu:
|
||||
main:
|
||||
parent: extras
|
||||
next: /extras/shortcodes
|
||||
prev: /extras/permalinks
|
||||
title: Scratch
|
||||
---
|
||||
|
||||
`Scratch` -- a "scratchpad" for your page-scoped variables. In most cases you can do well without `Scratch`, but there are some use cases that aren't solvable with Go's templates without `Scratch`'s help, due to scoping issues.
|
||||
|
||||
`Scratch` is added to both `Page` and `Shortcode` -- with following methods:
|
||||
|
||||
* `Set` and `Add` takes a `key` and the `value` to add.
|
||||
* `Get` returns the `value` for the `key` given.
|
||||
* `SetInMap` takes a `key`, `mapKey` and `value`
|
||||
* `GetSortedMapValues` returns array of values from `key` sorted by `mapKey`
|
||||
|
||||
`Set` and `SetInMap` can store values of any type.
|
||||
|
||||
For single values, `Add` accepts values that support Go's `+` operator. If the first `Add` for a key is an array or slice, the following adds will be appended to that list.
|
||||
|
||||
The scope of the backing data is global for the given `Page` or `Shortcode`, and spans partial and shortcode includes.
|
||||
|
||||
Note that `.Scratch` from a shortcode will return the shortcode's `Scratch`, which in most cases is what you want. If you want to store it in the page scroped Scratch, then use `.Page.Scratch`.
|
||||
|
||||
## Sample usage
|
||||
|
||||
The usage is best illustrated with some samples:
|
||||
|
||||
```
|
||||
{{ $.Scratch.Add "a1" 12 }}
|
||||
{{ $.Scratch.Get "a1" }} {{/* => 12 */}}
|
||||
{{ $.Scratch.Add "a1" 1 }}
|
||||
{{ $.Scratch.Get "a1" }} // {{/* => 13 */}}
|
||||
|
||||
{{ $.Scratch.Add "a2" "AB" }}
|
||||
{{ $.Scratch.Get "a2" }} {{/* => AB */}}
|
||||
{{ $.Scratch.Add "a2" "CD" }}
|
||||
{{ $.Scratch.Get "a2" }} {{/* => ABCD */}}
|
||||
|
||||
{{ $.Scratch.Add "l1" (slice "A" "B") }}
|
||||
{{ $.Scratch.Get "l1" }} {{/* => [A B] */}}
|
||||
{{ $.Scratch.Add "l1" (slice "C" "D") }}
|
||||
{{ $.Scratch.Get "l1" }} {{/* => [A B C D] */}}
|
||||
|
||||
{{ $.Scratch.Set "v1" 123 }}
|
||||
{{ $.Scratch.Get "v1" }} {{/* => 123 */}}
|
||||
|
||||
{{ $.Scratch.SetInMap "a3" "b" "XX" }}
|
||||
{{ $.Scratch.SetInMap "a3" "a" "AA" }}
|
||||
{{ $.Scratch.SetInMap "a3" "c" "CC" }}
|
||||
{{ $.Scratch.SetInMap "a3" "b" "BB" }}
|
||||
{{ $.Scratch.GetSortedMapValues "a3" }} {{/* => []interface {}{"AA", "BB", "CC"} */}}
|
||||
```
|
||||
|
||||
**Note:** The examples above uses the special `$` variable, which refers to the top-level node. This is the behavior you most likely want, and will help remove some confusion when using `Scratch` inside page range loops -- and you start inadvertently calling the wrong `Scratch`. But there may be use cases for `{{ .Scratch.Add "key" "some value" }}`.
|
||||
|
||||
|
||||
@@ -1,408 +0,0 @@
|
||||
---
|
||||
aliases:
|
||||
- /doc/shortcodes/
|
||||
lastmod: 2016-02-03
|
||||
date: 2013-07-01
|
||||
menu:
|
||||
main:
|
||||
parent: extras
|
||||
next: /extras/highlighting
|
||||
prev: /extras/scratch
|
||||
title: Shortcodes
|
||||
toc: false
|
||||
---
|
||||
|
||||
Hugo uses Markdown for its simple content format. However, there are a lot
|
||||
of things that Markdown doesn’t support well.
|
||||
|
||||
We are unwilling to accept being constrained by our simple format. Also
|
||||
unacceptable is writing raw HTML in our Markdown every time we want to include
|
||||
unsupported content such as a video. To do so is in complete opposition to the
|
||||
intent of using a bare-bones format for our content and utilizing templates to
|
||||
apply styling for display.
|
||||
|
||||
To avoid both of these limitations, Hugo created shortcodes.
|
||||
|
||||
A shortcode is a simple snippet inside a content file that Hugo will render
|
||||
using a predefined template. Note that shortcodes will not work in template
|
||||
files---if you need a functionality like that in a template, you most likely
|
||||
want a [partial template](/templates/partials/) instead.
|
||||
|
||||
Another benefit is, you can update your shortcode with any related new classes or
|
||||
techniques, and upon generation, Hugo will easily merge in your changes. You
|
||||
avoid a possibly complicated search and replace operation.
|
||||
|
||||
## Using a shortcode
|
||||
|
||||
In your content files, a shortcode can be called by using the `{{%/* name parameters
|
||||
*/%}}` form. Shortcode parameters are space delimited. Parameters with spaces
|
||||
can be quoted.
|
||||
|
||||
The first word is always the name of the shortcode. Parameters follow the name.
|
||||
Depending upon how the shortcode is defined, the parameters may be named,
|
||||
positional or both (although you can't mixed parameter types in a single call).
|
||||
The format for named parameters models that of HTML with the format
|
||||
`name="value"`.
|
||||
|
||||
Some shortcodes use or require closing shortcodes. Like HTML, the opening and closing
|
||||
shortcodes match (name only), the closing being prepended with a slash.
|
||||
|
||||
Example of a paired shortcode:
|
||||
|
||||
{{</* highlight go */>}} A bunch of code here {{</* /highlight */>}}
|
||||
|
||||
The examples above use two different delimiters, the difference being the `%` and the `<` character:
|
||||
|
||||
### Shortcodes with Markdown
|
||||
|
||||
The `%` characters indicates that the shortcode's inner content needs further processing by the page's rendering processor (i.e. Markdown), needed to get the **bold** text in the example below:
|
||||
|
||||
|
||||
{{%/* myshortcode */%}}Hello **World!**{{%/* /myshortcode */%}}
|
||||
|
||||
|
||||
### Shortcodes without Markdown
|
||||
|
||||
The `<` character indicates that the shortcode's inner content doesn't need any further rendering, this will typically be pure HTML:
|
||||
|
||||
{{</* myshortcode */>}}<p>Hello <strong>World!</strong></p>{{</* /myshortcode */>}}
|
||||
|
||||
|
||||
## Built-in Shortcodes
|
||||
|
||||
Hugo ships with a set of predefined shortcodes.
|
||||
|
||||
### highlight
|
||||
|
||||
This shortcode will convert the source code provided into syntax highlighted
|
||||
HTML. Read more on [highlighting](/extras/highlighting/).
|
||||
|
||||
#### Usage
|
||||
|
||||
`highlight` takes exactly one required parameter of _language_ and requires a
|
||||
closing shortcode.
|
||||
|
||||
#### Example
|
||||
|
||||
{{</* highlight html */>}}
|
||||
<section id="main">
|
||||
<div>
|
||||
<h1 id="title">{{ .Title }}</h1>
|
||||
{{ range .Data.Pages }}
|
||||
{{ .Render "summary"}}
|
||||
{{ end }}
|
||||
</div>
|
||||
</section>
|
||||
{{</* /highlight */>}}
|
||||
|
||||
|
||||
#### Example Output
|
||||
|
||||
<span style="color: #f92672"><section</span> <span style="color: #a6e22e">id=</span><span style="color: #e6db74">"main"</span><span style="color: #f92672">></span>
|
||||
<span style="color: #f92672"><div></span>
|
||||
<span style="color: #f92672"><h1</span> <span style="color: #a6e22e">id=</span><span style="color: #e6db74">"title"</span><span style="color: #f92672">></span>{{ .Title }}<span style="color: #f92672"></h1></span>
|
||||
{{ range .Data.Pages }}
|
||||
{{ .Render "summary"}}
|
||||
{{ end }}
|
||||
<span style="color: #f92672"></div></span>
|
||||
<span style="color: #f92672"></section></span>
|
||||
|
||||
### figure
|
||||
|
||||
`figure` is simply an extension of the image capabilities present with Markdown.
|
||||
`figure` provides the ability to add captions, CSS classes, alt text, links etc.
|
||||
|
||||
#### Usage
|
||||
|
||||
`figure` can use the following named parameters:
|
||||
|
||||
* src
|
||||
* link
|
||||
* title
|
||||
* caption
|
||||
* class
|
||||
* attr (attribution)
|
||||
* attrlink
|
||||
* alt
|
||||
|
||||
#### Example
|
||||
|
||||
{{</* figure src="/media/spf13.jpg" title="Steve Francia" */>}}
|
||||
|
||||
#### Example output
|
||||
|
||||
<figure>
|
||||
<img src="/media/spf13.jpg" />
|
||||
<figcaption>
|
||||
<h4>Steve Francia</h4>
|
||||
</figcaption>
|
||||
</figure>
|
||||
|
||||
### ref, relref
|
||||
|
||||
These shortcodes will look up the pages by their relative path (e.g.,
|
||||
`blog/post.md`) or their logical name (`post.md`) and return the permalink
|
||||
(`ref`) or relative permalink (`relref`) for the found page.
|
||||
|
||||
`ref` and `relref` also make it possible to make fragmentary links that work
|
||||
for the header links generated by Hugo.
|
||||
|
||||
Read more on [cross-references]({{% ref "extras/crossreferences.md" %}}).
|
||||
|
||||
#### Usage
|
||||
|
||||
`ref` and `relref` take exactly one required parameter of _reference_.
|
||||
|
||||
#### Example
|
||||
|
||||
[Neat]({{</* ref "blog/neat.md" */>}})
|
||||
[Who]({{</* relref "about.md#who" */>}})
|
||||
|
||||
#### Example Output
|
||||
|
||||
Assuming that standard Hugo pretty URLs are turned on.
|
||||
|
||||
<a href="/blog/neat">Neat</a>
|
||||
<a href="/about/#who:c28654c202e73453784cfd2c5ab356c0">Who</a>
|
||||
|
||||
### Twitter
|
||||
|
||||
You want to include a single tweet into your blog post? Everything you need is the URL of the tweet, e.g.:
|
||||
|
||||
* https://twitter.com/spf13/status/666616452582129664
|
||||
|
||||
Pass the tweet's ID from the URL as parameter to the shortcode as shown below:
|
||||
|
||||
{{</* tweet 666616452582129664 */>}}
|
||||
|
||||
### YouTube
|
||||
|
||||
This shortcode embeds a responsive video player for [YouTube](https://www.youtube.com/) videos. Only the ID of the video is required, e.g.:
|
||||
|
||||
* https://www.youtube.com/watch?v=w7Ft2ymGmfc
|
||||
|
||||
Copy the ID from behind `v=` and pass it to the shortcode:
|
||||
|
||||
{{</* youtube w7Ft2ymGmfc */>}}
|
||||
|
||||
Furthermore, you can autostart the embedded video by setting the `autostart` parameter to true. Remember that you can't mix named an unamed parameters. Assign the yet unamed video id to the parameter `id` like below too.
|
||||
|
||||
{{</* youtube id="w7Ft2ymGmfc" autoplay="true" */>}}
|
||||
|
||||
|
||||
### Vimeo
|
||||
|
||||
Adding a video from [Vimeo](https://vimeo.com/) is equivalent to the YouTube shortcode above. Extract the ID from the URL, e.g.:
|
||||
|
||||
* https://vimeo.com/channels/staffpicks/146022717
|
||||
|
||||
and pass it to the shortcode:
|
||||
|
||||
{{</* vimeo 146022717 */>}}
|
||||
|
||||
### GitHub gists
|
||||
|
||||
Including code snippets with GitHub gists while writing a tutorial is common situation bloggers face. With a given URL of the gist, e.g.:
|
||||
|
||||
* https://gist.github.com/spf13/7896402
|
||||
|
||||
pass the owner and the ID of the gist to the shortcode:
|
||||
|
||||
{{</* gist spf13 7896402 */>}}
|
||||
|
||||
If the gist contains several files and you want to quote just one of them, you can pass the filename (quoted) as an optional third argument:
|
||||
|
||||
{{</* gist spf13 7896402 "img.html" */>}}
|
||||
|
||||
### Speaker Deck
|
||||
|
||||
To embed slides from [Speaker Deck](https://speakerdeck.com/), click on "< /> Embed" (under Share right next to the template on Speaker Deck) and copy the URL, e.g.:
|
||||
|
||||
<script async class="speakerdeck-embed" data-id="4e8126e72d853c0060001f97" data-ratio="1.33333333333333" src="//speakerdeck.com/assets/embed.js"></script>
|
||||
|
||||
Extract the value from the field `data-id` and pass it to the shortcode:
|
||||
|
||||
{{</* speakerdeck 4e8126e72d853c0060001f97 */>}}
|
||||
|
||||
### Instagram
|
||||
|
||||
If you'd like to embed photo from [Instagram](https://www.instagram.com/), all you need is photo ID from the URL, e. g.:
|
||||
|
||||
* https://www.instagram.com/p/BMokmydjG-M/
|
||||
|
||||
Pass it to the shortcode:
|
||||
|
||||
{{</* instagram BMokmydjG-M */>}}
|
||||
|
||||
Optionally, hide caption:
|
||||
|
||||
{{</* instagram BMokmydjG-M hidecaption */>}}
|
||||
|
||||
## Creating your own shortcodes
|
||||
|
||||
To create a shortcode, place a template in the layouts/shortcodes directory. The
|
||||
template name will be the name of the shortcode.
|
||||
|
||||
In creating a shortcode, you can choose if the shortcode will use _positional
|
||||
parameters_, or _named parameters_, or _both_. A good rule of thumb is that if a
|
||||
shortcode has a single required value in the case of the `youtube` example below,
|
||||
then positional works very well. For more complex layouts with optional
|
||||
parameters, named parameters work best. Allowing both types of parameters is
|
||||
useful for complex layouts where you want to set default values that can be
|
||||
overridden.
|
||||
|
||||
**Inside the template**
|
||||
|
||||
To access a parameter by position, the `.Get` method can be used:
|
||||
|
||||
{{ .Get 0 }}
|
||||
|
||||
To access a parameter by name, the `.Get` method should be utilized:
|
||||
|
||||
{{ .Get "class" }}
|
||||
|
||||
`with` is great when the output depends on a parameter being set:
|
||||
|
||||
{{ with .Get "class"}} class="{{.}}"{{ end }}
|
||||
|
||||
`.Get` can also be used to check if a parameter has been provided. This is
|
||||
most helpful when the condition depends on either one value or another...
|
||||
or both:
|
||||
|
||||
{{ or .Get "title" | .Get "alt" | if }} alt="{{ with .Get "alt"}}{{.}}{{else}}{{.Get "title"}}{{end}}"{{ end }}
|
||||
|
||||
If a closing shortcode is used, the variable `.Inner` will be populated with all
|
||||
of the content between the opening and closing shortcodes. If a closing
|
||||
shortcode is required, you can check the length of `.Inner` and provide a warning
|
||||
to the user.
|
||||
|
||||
A shortcode with `.Inner` content can be used without the inline content, and without the closing shortcode, by using the self-closing syntax:
|
||||
|
||||
{{</* innershortcode /*/>}}
|
||||
|
||||
The variable `.Params` contains the list of parameters in case you need to do
|
||||
more complicated things than `.Get`. It is sometimes useful to provide a
|
||||
flexible shortcode that can take named or positional parameters. To meet this
|
||||
need, Hugo shortcodes have a `.IsNamedParams` boolean available that can be used
|
||||
such as `{{ if .IsNamedParams }}...{{ else }}...{{ end }}`. See the
|
||||
`Single Flexible Example` below for an example.
|
||||
|
||||
You can also use the variable `.Page` to access all the normal [Page Variables](/templates/variables/).
|
||||
|
||||
A shortcodes can be nested. In a nested shortcode you can access the parent shortcode context with `.Parent`. This can be very useful for inheritance of common shortcode parameters from the root.
|
||||
|
||||
## Single Positional Example: youtube
|
||||
|
||||
{{</* youtube 09jf3ow9jfw */>}}
|
||||
|
||||
Would load the template /layouts/shortcodes/youtube.html
|
||||
|
||||
<div class="embed video-player">
|
||||
<iframe class="youtube-player" type="text/html" width="640" height="385" src="http://www.youtube.com/embed/{{ index .Params 0 }}" allowfullscreen frameborder="0">
|
||||
</iframe>
|
||||
</div>
|
||||
|
||||
This would be rendered as:
|
||||
|
||||
<div class="embed video-player">
|
||||
<iframe class="youtube-player" type="text/html"
|
||||
width="640" height="385"
|
||||
src="http://www.youtube.com/embed/09jf3ow9jfw"
|
||||
allowfullscreen frameborder="0">
|
||||
</iframe>
|
||||
</div>
|
||||
|
||||
## Single Named Example: image with caption
|
||||
|
||||
{{</* img src="/media/spf13.jpg" title="Steve Francia" */>}}
|
||||
|
||||
Would load the template /layouts/shortcodes/img.html
|
||||
|
||||
<!-- image -->
|
||||
<figure {{ with .Get "class" }}class="{{.}}"{{ end }}>
|
||||
{{ with .Get "link"}}<a href="{{.}}">{{ end }}
|
||||
<img src="{{ .Get "src" }}" {{ if or (.Get "alt") (.Get "caption") }}alt="{{ with .Get "alt"}}{{.}}{{else}}{{ .Get "caption" }}{{ end }}"{{ end }} />
|
||||
{{ if .Get "link"}}</a>{{ end }}
|
||||
{{ if or (or (.Get "title") (.Get "caption")) (.Get "attr")}}
|
||||
<figcaption>{{ if isset .Params "title" }}
|
||||
<h4>{{ .Get "title" }}</h4>{{ end }}
|
||||
{{ if or (.Get "caption") (.Get "attr")}}<p>
|
||||
{{ .Get "caption" }}
|
||||
{{ with .Get "attrlink"}}<a href="{{.}}"> {{ end }}
|
||||
{{ .Get "attr" }}
|
||||
{{ if .Get "attrlink"}}</a> {{ end }}
|
||||
</p> {{ end }}
|
||||
</figcaption>
|
||||
{{ end }}
|
||||
</figure>
|
||||
<!-- image -->
|
||||
|
||||
Would be rendered as:
|
||||
|
||||
<figure >
|
||||
<img src="/media/spf13.jpg" />
|
||||
<figcaption>
|
||||
<h4>Steve Francia</h4>
|
||||
</figcaption>
|
||||
</figure>
|
||||
|
||||
## Single Flexible Example: vimeo with defaults
|
||||
|
||||
{{</* vimeo 49718712 */>}}
|
||||
{{</* vimeo id="49718712" class="flex-video" */>}}
|
||||
|
||||
Would load the template /layouts/shortcodes/vimeo.html
|
||||
|
||||
{{ if .IsNamedParams }}
|
||||
<div class="{{ if .Get "class" }}{{ .Get "class" }}{{ else }}vimeo-container{{ end }}">
|
||||
<iframe src="//player.vimeo.com/video/{{ .Get "id" }}" allowfullscreen></iframe>
|
||||
</div>
|
||||
{{ else }}
|
||||
<div class="{{ if len .Params | eq 2 }}{{ .Get 1 }}{{ else }}vimeo-container{{ end }}">
|
||||
<iframe src="//player.vimeo.com/video/{{ .Get 0 }}" allowfullscreen></iframe>
|
||||
</div>
|
||||
{{ end }}
|
||||
|
||||
Would be rendered as:
|
||||
|
||||
<div class="vimeo-container">
|
||||
<iframe src="//player.vimeo.com/video/49718712" allowfullscreen></iframe>
|
||||
</div>
|
||||
<div class="flex-video">
|
||||
<iframe src="//player.vimeo.com/video/49718712" allowfullscreen></iframe>
|
||||
</div>
|
||||
|
||||
## Paired Example: Highlight
|
||||
*Hugo already ships with the `highlight` shortcode*
|
||||
|
||||
{{</* highlight html */>}}
|
||||
<html>
|
||||
<body> This HTML </body>
|
||||
</html>
|
||||
{{</* /highlight */>}}
|
||||
|
||||
The template for this utilizes the following code (already included in Hugo)
|
||||
|
||||
{{ .Get 0 | highlight .Inner }}
|
||||
|
||||
And will be rendered as:
|
||||
|
||||
<div class="highlight" style="background: #272822"><pre style="line-height: 125%"><span style="color: #f92672"><html></span>
|
||||
<span style="color: #f92672"><body></span> This HTML <span style="color: #f92672"></body></span>
|
||||
<span style="color: #f92672"></html></span>
|
||||
</pre></div>
|
||||
|
||||
Please notice that this template makes use of a Hugo-specific template function
|
||||
called `highlight` which uses Pygments to add the highlighting code.
|
||||
|
||||
## Simple Single-word Example: Year
|
||||
|
||||
Let's assume you would like to have a shortcode to be replaced by the current year in your Markdown content files, for a license or copyright statement. Calling a shortcode like this:
|
||||
|
||||
{{</* year */>}}
|
||||
|
||||
... would load your one-line template ``/layouts/shortcodes/year.html``, which contains:
|
||||
|
||||
{{ .Page.Now.Year }}
|
||||
|
||||
More shortcode examples can be found at [spf13.com](https://github.com/spf13/spf13.com/tree/master/layouts/shortcodes).
|
||||
@@ -1,37 +0,0 @@
|
||||
---
|
||||
lastmod: 2015-01-27
|
||||
date: 2013-07-09
|
||||
menu:
|
||||
main:
|
||||
parent: extras
|
||||
next: /extras/localfiles
|
||||
prev: /extras/highlighting
|
||||
title: Table of Contents
|
||||
---
|
||||
|
||||
Hugo will automatically parse the Markdown for your content and create
|
||||
a Table of Contents you can use to guide readers to the sections within
|
||||
your content.
|
||||
|
||||
## Usage
|
||||
|
||||
Simply create content like you normally would with the appropriate
|
||||
headers.
|
||||
|
||||
Hugo will take this Markdown and create a table of contents stored in the
|
||||
[content variable](/layout/variables/) `.TableOfContents`
|
||||
|
||||
|
||||
## Template Example
|
||||
|
||||
This is example code of a [single.html template](/layout/content/).
|
||||
|
||||
{{ partial "header.html" . }}
|
||||
<div id="toc" class="well col-md-4 col-sm-6">
|
||||
{{ .TableOfContents }}
|
||||
</div>
|
||||
<h1>{{ .Title }}</h1>
|
||||
{{ .Content }}
|
||||
{{ partial "footer.html" . }}
|
||||
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
---
|
||||
aliases:
|
||||
- /doc/urls/
|
||||
lastmod: 2016-05-07
|
||||
date: 2014-01-03
|
||||
menu:
|
||||
main:
|
||||
parent: extras
|
||||
next: /community/mailing-list
|
||||
notoc: true
|
||||
prev: /extras/localfiles
|
||||
title: URLs
|
||||
---
|
||||
|
||||
## Pretty URLs
|
||||
|
||||
By default, Hugo creates content with 'pretty' URLs. For example,
|
||||
content created at `/content/extras/urls.md` will be rendered at
|
||||
`/public/extras/urls/index.html`, thus accessible from the browser
|
||||
at http://example.com/extras/urls/. No non-standard server-side
|
||||
configuration is required for these pretty URLs to work.
|
||||
|
||||
If you would like to have what we call "ugly URLs",
|
||||
e.g. http://example.com/extras/urls.html, you are in luck.
|
||||
Hugo supports the ability to create your entire site with ugly URLs.
|
||||
Simply add `uglyurls = true` to your site-wide `config.toml`,
|
||||
or use the `--uglyURLs=true` flag on the command line.
|
||||
|
||||
If you want a specific piece of content to have an exact URL, you can
|
||||
specify this in the front matter under the `url` key. See [Content
|
||||
Organization](/content/organization/) for more details.
|
||||
|
||||
## Canonicalization
|
||||
|
||||
By default, all relative URLs encountered in the input are left unmodified,
|
||||
e.g. `/css/foo.css` would stay as `/css/foo.css`,
|
||||
i.e. `canonifyURLs` defaults to `false`.
|
||||
|
||||
By setting `canonifyURLs` to `true`, all relative URLs would instead
|
||||
be *canonicalized* using `baseURL`. For example, assuming you have
|
||||
`baseURL = http://yoursite.example.com/` defined in the site-wide
|
||||
`config.toml`, the relative URL `/css/foo.css` would be turned into
|
||||
the absolute URL `http://yoursite.example.com/css/foo.css`.
|
||||
|
||||
Benefits of canonicalization include fixing all URLs to be absolute, which may
|
||||
aid with some parsing tasks. Note though that all real browsers handle this
|
||||
client-side without issues.
|
||||
|
||||
Benefits of non-canonicalization include being able to have resource inclusion
|
||||
be scheme-relative, so that http vs https can be decided based on how this
|
||||
page was retrieved.
|
||||
|
||||
> Note: In the May 2014 release of Hugo v0.11, the default value of `canonifyURLs` was switched from `true` to `false`, which we think is the better default and should continue to be the case going forward. So, please verify and adjust your website accordingly if you are upgrading from v0.10 or older versions.
|
||||
|
||||
To find out the current value of `canonifyURLs` for your website, you may use the handy `hugo config` command added in v0.13:
|
||||
|
||||
hugo config | grep -i canon
|
||||
|
||||
Or, if you are on Windows and do not have `grep` installed:
|
||||
|
||||
hugo config | FINDSTR /I canon
|
||||
|
||||
## Relative URLs
|
||||
|
||||
By default, all relative URLs are left unchanged by Hugo,
|
||||
which can be problematic when you want to make your site browsable from a local file system.
|
||||
|
||||
Setting `relativeURLs` to `true` in the site configuration will cause Hugo to rewrite all relative URLs to be relative to the current content.
|
||||
|
||||
For example, if the `/post/first/` page contained a link with a relative URL of `/about/`, Hugo would rewrite that URL to `../../about/`.
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user