Compare commits

..

19 Commits

Author SHA1 Message Date
hugoreleaser 9f9695cf7b releaser: Add release notes to /docs for release of 0.44
[ci skip]
2018-07-13 06:03:09 +00:00
hugoreleaser 0831d8ccaf releaser: Bump versions for release of 0.44
[ci skip]
2018-07-13 06:03:09 +00:00
Bjørn Erik Pedersen 1d4ff024ca Finish release notes 0.44 2018-07-13 07:53:33 +02:00
hugoreleaser 521e63ac7c releaser: Add release notes draft for 0.44
Rename to *-ready.md to continue. [ci skip]
2018-07-13 05:27:58 +00:00
Bjørn Erik Pedersen 47d38628ec resource: Clean up the in-memory Resource reader usage
Turns out `strings.Reader` implements both `io.Reader` and `io.Seeker`, so we don't need anything special.

Updates #4936
2018-07-12 21:32:52 +02:00
Bjørn Erik Pedersen 0024dcfe3e resource: Move opening of the transformed resources after cache check
The old version should be functionally the same, but opening up these readers (potentially files) every time is wasteful if we don't read from them.
2018-07-12 19:36:12 +02:00
Bjørn Erik Pedersen beec1fc98e resource: Fix resources.Concat for transformed resources
Fixes #4936
2018-07-12 19:36:12 +02:00
Bjørn Erik Pedersen 306573def0 Improve type support in resources.Concat
This allows the result of `.Resources.Match` and similar to be concatenated.

Fixes #4934
2018-07-12 13:43:27 +02:00
Bjørn Erik Pedersen 80c8f3b81a hugolib: Fix static filesystem for themed multihost sites
Multihost is where each language has its own `baseURL`. In this configuration, static files from the theme was not picked up.

This was a regression in Hugo `0.42`. This commit also adds proper tests for this, so that does not happen again.

Fixes #4929
2018-07-12 12:18:56 +02:00
Bjørn Erik Pedersen 6b6dcb44a0 Flush partialCached cache on rebuilds
Fixes #4931
2018-07-11 20:40:04 +02:00
Bjørn Erik Pedersen d96f2a460f resource: Include the transformation step in the error message
Fixes #4924
2018-07-11 11:03:15 +02:00
Bjørn Erik Pedersen ac53035030 media: Only show deprecation warning when needed
Fixes #4927
2018-07-10 23:21:48 +02:00
Bjørn Erik Pedersen b874a1ba7a media: Allow multiple file suffixes per media type
Before this commit, `Suffix` on `MediaType` was used both to set a custom file suffix and as a way to augment the mediatype definition (what you see after the "+", e.g. "image/svg+xml").

This had its limitations. For one, it was only possible with one file extension per MIME type.

Now you can specify multiple file suffixes using "suffixes", but you need to specify the full MIME type
identifier:

[mediaTypes]
[mediaTypes."image/svg+xml"]
suffixes = ["svg", "abc ]

In most cases, it will be enough to just change:

[mediaTypes]
[mediaTypes."my/custom-mediatype"]
suffix = "txt"

To:

[mediaTypes]
[mediaTypes."my/custom-mediatype"]
suffixes = ["txt"]

Hugo will still respect values set in "suffix" if no value for "suffixes" is provided, but this will be removed in a future release.

Note that you can still get the Media Type's suffix from a template: {{ $mediaType.Suffix }}. But this will now map to the MIME type filename.

Fixes #4920
2018-07-10 22:13:52 +02:00
Anthony Fok 4108705934 hugolib: Remove empty resources/ dir after TestNewSiteDefaultLang 2018-07-10 09:01:54 +02:00
Anthony Fok 9c1e82085e .gitattributes: Exclude *.svg from CRLF/LF conversion
I ran into trouble after importing the Hugo v0.43 release tarball
into the Debian packaging git repository...
2018-07-09 21:06:15 -06:00
Anthony Fok 2b73e89d6d tpl: Set permission of embedded templates to 0644 2018-07-09 12:57:08 -06:00
Bjørn Erik Pedersen febf0aec8b Build a fully static Windows extended binary 2018-07-09 20:42:08 +02:00
Bjørn Erik Pedersen a4fad5be6b Adjust release notes
[ci skip]
2018-07-09 12:11:57 +02:00
hugoreleaser 6084f0433c releaser: Prepare repository for 0.44-DEV
[ci skip]
2018-07-09 10:03:30 +00:00
63 changed files with 904 additions and 291 deletions
+3
View File
@@ -3,3 +3,6 @@
# Go source files always have LF line endings
*.go text eol=lf
# SVG files should not be modified
*.svg -text
Generated
+209 -25
View File
@@ -3,35 +3,46 @@
[[projects]]
branch = "master"
digest = "1:f6a10073544cc0bd1eb9fd9f8d9bf4644971910a0f8393d51b5b4d286e554849"
name = "github.com/BurntSushi/locker"
packages = ["."]
pruneopts = ""
revision = "a6e239ea1c69bff1cfdb20c4b73dadf52f784b6a"
[[projects]]
branch = "master"
digest = "1:af3600b068c8dd0e004122f154de7ece06b0b13376f79e976701aab4834c860a"
name = "github.com/BurntSushi/toml"
packages = ["."]
pruneopts = ""
revision = "a368813c5e648fee92e5f6c30e3944ff9d5e8895"
[[projects]]
digest = "1:1080c443bebc98b1c25665b46b321dc02f8a4d384fe544379dcba1e651f59321"
name = "github.com/PuerkitoBio/purell"
packages = ["."]
pruneopts = ""
revision = "0bcb03f4b4d0a9428594752bd2a3b9aa0a9d4bd4"
version = "v1.1.0"
[[projects]]
branch = "master"
digest = "1:331a419049c2be691e5ba1d24342fc77c7e767a80c666a18fd8a9f7b82419c1c"
name = "github.com/PuerkitoBio/urlesc"
packages = ["."]
pruneopts = ""
revision = "de5bf2ad457846296e2031421a34e2568e304e35"
[[projects]]
branch = "master"
digest = "1:60d5ffa86fb76749180841154b3714cde4771723b7e52329fb97ec916a6a68a6"
name = "github.com/alecthomas/assert"
packages = ["."]
pruneopts = ""
revision = "405dbfeb8e38effee6e723317226e93fff912d06"
[[projects]]
digest = "1:2d78d7ffff1988e613e4946d6a6914190db0b38d533e392208797d2f557c92b6"
name = "github.com/alecthomas/chroma"
packages = [
".",
@@ -64,111 +75,135 @@
"lexers/w",
"lexers/x",
"lexers/y",
"styles"
"styles",
]
pruneopts = ""
revision = "1b755a90bd109f170385cb3964f0abdfd3451145"
[[projects]]
branch = "master"
digest = "1:ba0a389824c3c3d378f5f334370524b7d04b5a5ccedce7dd2da05ae8d3868609"
name = "github.com/alecthomas/colour"
packages = ["."]
pruneopts = ""
revision = "60882d9e27213e8552dcff6328914fe4c2b44bc9"
[[projects]]
branch = "master"
digest = "1:5723237c9114bb92b4571532d9580dd0ed885ec3eb371d58085c074895c04a51"
name = "github.com/alecthomas/repr"
packages = ["."]
pruneopts = ""
revision = "f49988b46e025398b9f834f7c726afe001ec481f"
[[projects]]
digest = "1:05d0e4ae6b8d0273647964fe26762e3345d5d196aaeb858838e75336703451ba"
name = "github.com/bep/debounce"
packages = ["."]
pruneopts = ""
revision = "844797fa1dd9ba969d71b62797ff19d1e49d4eac"
version = "v1.1.0"
[[projects]]
branch = "master"
digest = "1:88b2a2ccfbcf8aa697ec140e196c524f40bbdc8e6f6d03ff79354bc694cb677d"
name = "github.com/bep/gitmap"
packages = ["."]
pruneopts = ""
revision = "012701e8669671499fc43e9792335a1dcbfe2afb"
[[projects]]
branch = "master"
digest = "1:7337271448975bc9cf3deae77bb2d7f7fc937c60c59b606ffcd25bfc754dd2ec"
name = "github.com/bep/go-tocss"
packages = [
"scss",
"scss/libsass",
"tocss"
"tocss",
]
pruneopts = ""
revision = "2abb118dc8688b6c7df44e12f4152c2bded9b19c"
[[projects]]
digest = "1:e5ad472b763adca2591568384b8f07974d2da4a98b55ffb360e2cecc2a216bae"
name = "github.com/chaseadamsio/goorgeous"
packages = ["."]
pruneopts = ""
revision = "dcf1ef873b8987bf12596fe6951c48347986eb2f"
version = "v1.1.0"
[[projects]]
digest = "1:f30036d9c6eb2b9262edac69b5f6b59e25b25310ffee3035ab0e7c4b722a8552"
name = "github.com/cpuguy83/go-md2man"
packages = ["md2man"]
pruneopts = ""
revision = "a65d4d2de4d5f7c74868dfa9b202a3c8be315aaa"
version = "v1.0.6"
[[projects]]
branch = "master"
digest = "1:8f6c36ee73ded871996ada894e20dfecde56557d08b4d1849d5489076679971f"
name = "github.com/danwakefield/fnmatch"
packages = ["."]
pruneopts = ""
revision = "cbb64ac3d964b81592e64f957ad53df015803288"
[[projects]]
digest = "1:0a39ec8bf5629610a4bc7873a92039ee509246da3cef1a0ea60f1ed7e5f9cea5"
name = "github.com/davecgh/go-spew"
packages = ["spew"]
pruneopts = ""
revision = "346938d642f2ec3594ed81d874461961cd0faa76"
version = "v1.1.0"
[[projects]]
digest = "1:8dc164acd41f84c9f704362d061f90cf45014c3b7eb3fead126efb7d152e2efc"
name = "github.com/disintegration/imaging"
packages = ["."]
pruneopts = ""
revision = "dd50a3ee9985ccd313a2f03c398fcaedc96dc707"
version = "v1.2.4"
[[projects]]
digest = "1:536d2bdf1cdef7ec49e1cb4a8a083ae639159f0fd11a5829fe4d35ecb8cc3a1a"
name = "github.com/dlclark/regexp2"
packages = [
".",
"syntax"
"syntax",
]
pruneopts = ""
revision = "487489b64fb796de2e55f4e8a4ad1e145f80e957"
version = "v1.1.6"
[[projects]]
branch = "master"
name = "github.com/dsnet/golib"
packages = ["memfile"]
revision = "1ea1667757804fdcccc5a1810e09aba618885ac2"
[[projects]]
branch = "master"
digest = "1:fbbae68d476d61afb78178dd4c5532dbfff154e2fea72d1312138bf35c613ec1"
name = "github.com/eknkc/amber"
packages = [
".",
"parser"
"parser",
]
pruneopts = ""
revision = "cdade1c073850f4ffc70a829e31235ea6892853b"
[[projects]]
digest = "1:e5c807ac3b60699ccec9263f6eec756251b17e78582eb149f90ac345d9e58327"
name = "github.com/fortytw2/leaktest"
packages = ["."]
pruneopts = ""
revision = "a5ef70473c97b71626b9abeda80ee92ba2a7de9e"
version = "v1.2.0"
[[projects]]
digest = "1:b2106f1668ea5efc1ecc480f7e922a093adb9563fd9ce58585292871f0d0f229"
name = "github.com/fsnotify/fsnotify"
packages = ["."]
pruneopts = ""
revision = "c2828203cd70a50dcccfb2761f8b1f8ceef9a8e9"
version = "v1.4.7"
[[projects]]
digest = "1:b7a7e17513aeee6492d93015c7bf29c86a0c1c91210ea56b21e36c1a40958cba"
name = "github.com/gobwas/glob"
packages = [
".",
@@ -178,31 +213,39 @@
"syntax/ast",
"syntax/lexer",
"util/runes",
"util/strings"
"util/strings",
]
pruneopts = ""
revision = "5ccd90ef52e1e632236f7326478d4faa74f99438"
version = "v0.2.3"
[[projects]]
digest = "1:fe1b4d4cbe48c0d55507c55f8663aa4185576cc58fa0c8be03bb8f19dfe17a9c"
name = "github.com/gorilla/websocket"
packages = ["."]
pruneopts = ""
revision = "ea4d1f681babbce9545c9c5f3d5194a789c89f5b"
version = "v1.2.0"
[[projects]]
branch = "master"
digest = "1:4423ee95d6ee30bb22f680445c58889bb5b91e1b955405bf34374a053784a8a2"
name = "github.com/hashicorp/go-immutable-radix"
packages = ["."]
pruneopts = ""
revision = "7f3cd4390caab3250a57f30efdb2a65dd7649ecf"
[[projects]]
branch = "master"
digest = "1:9c776d7d9c54b7ed89f119e449983c3f24c0023e75001d6092442412ebca6b94"
name = "github.com/hashicorp/golang-lru"
packages = ["simplelru"]
pruneopts = ""
revision = "0fb14efe8c47ae851c0034ed7a448854d3d34cf3"
[[projects]]
branch = "master"
digest = "1:ccfc44438ba7fc24effffbe9c7b75bbbb51e7a275e361e62a4dbffbc9e8e43d9"
name = "github.com/hashicorp/hcl"
packages = [
".",
@@ -214,206 +257,266 @@
"hcl/token",
"json/parser",
"json/scanner",
"json/token"
"json/token",
]
pruneopts = ""
revision = "ef8a98b0bbce4a65b5aa4c368430a80ddc533168"
[[projects]]
digest = "1:870d441fe217b8e689d7949fef6e43efbc787e50f200cb1e70dbca9204a1d6be"
name = "github.com/inconshreveable/mousetrap"
packages = ["."]
pruneopts = ""
revision = "76626ae9c91c4f2a10f34cad8ce83ea42c93bb75"
version = "v1.0"
[[projects]]
digest = "1:3b82a4308adc7319d0c7efbad106e966cbbf70e47f16fb5f7aca131b01f6f9b1"
name = "github.com/jdkato/prose"
packages = [
"internal/util",
"transform"
"transform",
]
pruneopts = ""
revision = "20d3663d4bc9dd10d75abcde9d92e04b4861c674"
version = "v1.1.0"
[[projects]]
digest = "1:f72872791669f287262777a6a635c7aaebbdd9919cffacea802f8f9c1dc2e6f6"
name = "github.com/kyokomi/emoji"
packages = ["."]
pruneopts = ""
revision = "7e06b236c489543f53868841f188a294e3383eab"
version = "v1.5"
[[projects]]
digest = "1:3ee69edc976a8e66debd179073163cbbef426faa7c0ef2d8ff8e3be159699d2e"
name = "github.com/magefile/mage"
packages = [
"mg",
"sh"
"sh",
]
pruneopts = ""
revision = "2f974307b636f59c13b88704cf350a4772fef271"
version = "v1.0.2"
[[projects]]
digest = "1:093cd7ebfdecf5692c66f0b0f7a1877d796c89d9940f5769439c53dc65264036"
name = "github.com/magiconair/properties"
packages = ["."]
pruneopts = ""
revision = "c3beff4c2358b44d0493c7dda585e7db7ff28ae6"
version = "v1.7.6"
[[projects]]
digest = "1:fd46423a2fe75d52968baf37471b99e6f05cea3ac29c756128ead26af34e1c35"
name = "github.com/markbates/inflect"
packages = ["."]
pruneopts = ""
revision = "a12c3aec81a6a938bf584a4bac567afed9256586"
[[projects]]
digest = "1:78229b46ddb7434f881390029bd1af7661294af31f6802e0e1bedaad4ab0af3c"
name = "github.com/mattn/go-isatty"
packages = ["."]
pruneopts = ""
revision = "0360b2af4f38e8d38c7fce2a9f4e702702d73a39"
version = "v0.0.3"
[[projects]]
digest = "1:81e673df85e765593a863f67cba4544cf40e8919590f04d67664940786c2b61a"
name = "github.com/mattn/go-runewidth"
packages = ["."]
pruneopts = ""
revision = "9e777a8366cce605130a531d2cd6363d07ad7317"
version = "v0.0.2"
[[projects]]
digest = "1:6066f4c384723dd468c96adc13bfe4d977f182c2305e1a82c94bb50e1507d528"
name = "github.com/miekg/mmark"
packages = ["."]
pruneopts = ""
revision = "fd2f6c1403b37925bd7fe13af05853b8ae58ee5f"
version = "v1.3.6"
[[projects]]
branch = "master"
digest = "1:0de0f377aeccd41384e883c59c6f184c9db01c96db33a2724a1eaadd60f92629"
name = "github.com/mitchellh/hashstructure"
packages = ["."]
pruneopts = ""
revision = "2bca23e0e452137f789efbc8610126fd8b94f73b"
[[projects]]
branch = "master"
digest = "1:59fa50d593e5673a0dfffa1852b66fd700c05b35e368680b4b89a68fdb2c1379"
name = "github.com/mitchellh/mapstructure"
packages = ["."]
pruneopts = ""
revision = "00c29f56e2386353d58c599509e8dc3801b0d716"
[[projects]]
branch = "master"
digest = "1:08b8db6381176e5472815f67f29b2b8b21d5bf3adaba4de3e5416faaf26f3689"
name = "github.com/muesli/smartcrop"
packages = [
".",
"options"
"options",
]
pruneopts = ""
revision = "f6ebaa786a12a0fdb2d7c6dee72808e68c296464"
[[projects]]
digest = "1:34afc91b88b56c71639e275ff3ea8179a8f094ddc86df96e26074000cade42fe"
name = "github.com/nicksnyder/go-i18n"
packages = [
"i18n/bundle",
"i18n/language",
"i18n/translation"
"i18n/translation",
]
pruneopts = ""
revision = "0dc1626d56435e9d605a29875701721c54bc9bbd"
version = "v1.10.0"
[[projects]]
branch = "master"
digest = "1:2656200f82783893859c77903afc794d97c1f5054e2b57f7021e33a6047e7b1e"
name = "github.com/olekukonko/tablewriter"
packages = ["."]
pruneopts = ""
revision = "b8a9be070da40449e501c3c4730a889e42d87a9e"
[[projects]]
digest = "1:fef37519c971ab3c464318a0c9da6a7fb9c21439aa587e61bf10af651e6119b9"
name = "github.com/pelletier/go-toml"
packages = ["."]
pruneopts = ""
revision = "acdc4509485b587f5e675510c4f2c63e90ff68a8"
version = "v1.1.0"
[[projects]]
digest = "1:256484dbbcd271f9ecebc6795b2df8cad4c458dd0f5fd82a8c2fa0c29f233411"
name = "github.com/pmezard/go-difflib"
packages = ["difflib"]
pruneopts = ""
revision = "792786c7400a136282c1664665ae0a8db921c6c2"
version = "v1.0.0"
[[projects]]
branch = "master"
digest = "1:10bc894f31df5ca3366a50122ee2ade6b56f3f5531c523a8a551748a0663aa1b"
name = "github.com/russross/blackfriday"
packages = ["."]
pruneopts = ""
revision = "11635eb403ff09dbc3a6b5a007ab5ab09151c229"
[[projects]]
digest = "1:afa9b7bb3d9e633ef32e46ab4b6a87b5376271e3d86b09a379029bbb10e26fa0"
name = "github.com/sanity-io/litter"
packages = ["."]
pruneopts = ""
revision = "ae543b7ba8fd6af63e4976198f146e1348ae53c1"
version = "v1.1.0"
[[projects]]
digest = "1:1ebe873a8dc99e3316c30fea2e211038c4d1fcb605eee17e00a5e91b8817925e"
name = "github.com/sergi/go-diff"
packages = ["diffmatchpatch"]
pruneopts = ""
revision = "1744e2970ca51c86172c8190fadad617561ed6e7"
version = "v1.0.0"
[[projects]]
branch = "master"
digest = "1:606fa779c7a80ab6a9ec5836cd12759f86cd6e1d82d5d60cf7ec5133e78c6cf8"
name = "github.com/shurcooL/sanitized_anchor_name"
packages = ["."]
pruneopts = ""
revision = "86672fcb3f950f35f2e675df2240550f2a50762f"
[[projects]]
digest = "1:3d6c88f060fdaac3291f3d18f58eb542fe3a2b330609b269962d26d0c99104be"
name = "github.com/spf13/afero"
packages = [
".",
"mem"
"mem",
]
pruneopts = ""
revision = "787d034dfe70e44075ccc060d346146ef53270ad"
version = "v1.1.1"
[[projects]]
digest = "1:d0b38ba6da419a6d4380700218eeec8623841d44a856bb57369c172fbf692ab4"
name = "github.com/spf13/cast"
packages = ["."]
pruneopts = ""
revision = "8965335b8c7107321228e3e3702cab9832751bac"
version = "v1.2.0"
[[projects]]
digest = "1:9e14345bfb9aa30952b41ffceaa2acd559933cfe3d17bd87b7f6e54b6c618492"
name = "github.com/spf13/cobra"
packages = [
".",
"doc"
"doc",
]
pruneopts = ""
revision = "a1f051bc3eba734da4772d60e2d677f47cf93ef4"
version = "v0.0.2"
[[projects]]
branch = "master"
digest = "1:7c00f445c89f468abd5ab86546ba1fa11bac66e63325ade8ca05aa7220791fc7"
name = "github.com/spf13/fsync"
packages = ["."]
pruneopts = ""
revision = "12a01e648f05a938100a26858d2d59a120307a18"
[[projects]]
branch = "master"
digest = "1:104517520aab91164020ab6524a5d6b7cafc641b2e42ac6236f6ac1deac4f66a"
name = "github.com/spf13/jwalterweatherman"
packages = ["."]
pruneopts = ""
revision = "7c0cea34c8ece3fbeb2b27ab9b59511d360fb394"
[[projects]]
branch = "master"
digest = "1:5082c0d57a199dabc0868010784039249af0932fad2990b51ad9404c9a6b6e5d"
name = "github.com/spf13/nitro"
packages = ["."]
pruneopts = ""
revision = "24d7ef30a12da0bdc5e2eb370a79c659ddccf0e8"
[[projects]]
digest = "1:261bc565833ef4f02121450d74eb88d5ae4bd74bfe5d0e862cddb8550ec35000"
name = "github.com/spf13/pflag"
packages = ["."]
pruneopts = ""
revision = "e57e3eeb33f795204c1ca35f56c44f83227c6e66"
version = "v1.0.0"
[[projects]]
digest = "1:79af66c513727a0ed32fb4137ad7d0613b01e8e2f5ce9479724e26e2c9068011"
name = "github.com/spf13/viper"
packages = ["."]
pruneopts = ""
revision = "b5e8006cbee93ec955a89ab31e0e3ce3204f3736"
version = "v1.0.2"
[[projects]]
digest = "1:a70d585d45f695f2e8e6782569bdf181419667a35e6035ceb086706b495aa21a"
name = "github.com/stretchr/testify"
packages = [
"assert",
"require"
"require",
]
pruneopts = ""
revision = "12b6f73e6084dad08a7c6e575284b177ecafbc71"
version = "v1.2.1"
[[projects]]
digest = "1:54b1c3f97e0d74b571055cc17af4a978b6160e6ccfda73608aba048e404319c1"
name = "github.com/tdewolff/minify"
packages = [
".",
@@ -422,12 +525,14 @@
"js",
"json",
"svg",
"xml"
"xml",
]
pruneopts = ""
revision = "8d72a4127ae33b755e95bffede9b92e396267ce2"
version = "v2.3.5"
[[projects]]
digest = "1:33d327ae34260328b00ed15f89961446d805797a96de8643a983020825bb51ae"
name = "github.com/tdewolff/parse"
packages = [
".",
@@ -438,25 +543,31 @@
"json",
"strconv",
"svg",
"xml"
"xml",
]
pruneopts = ""
revision = "d739d6fccb0971177e06352fea02d3552625efb1"
version = "v2.3.3"
[[projects]]
branch = "master"
digest = "1:12e69a2969bdcdf2928607e51966a868482c2a450f1c97c5dde004257c8369ff"
name = "github.com/wellington/go-libsass"
packages = ["libs"]
pruneopts = ""
revision = "615eaa47ef794d037c1906a0eb7bf85375a5decf"
[[projects]]
digest = "1:b1e5dc66cd8ad9712eb8fd4dfaecac6ae45cbcde94476c5b64d905c5d789eef7"
name = "github.com/yosssi/ace"
packages = ["."]
pruneopts = ""
revision = "ea038f4770b6746c3f8f84f14fa60d9fe1205b56"
version = "v0.0.5"
[[projects]]
branch = "master"
digest = "1:4525c51a65e4974007814da8e2621343840d769d80b2b2ab79e6958342726587"
name = "golang.org/x/image"
packages = [
"bmp",
@@ -467,33 +578,41 @@
"tiff/lzw",
"vp8",
"vp8l",
"webp"
"webp",
]
pruneopts = ""
revision = "f315e440302883054d0c2bd85486878cb4f8572c"
[[projects]]
branch = "master"
digest = "1:8bb19e8d6e1321626d3f58ffee75699e86940c79d959b30fcf632883d7c4d303"
name = "golang.org/x/net"
packages = [
"context",
"idna"
"idna",
]
pruneopts = ""
revision = "61147c48b25b599e5b561d2e9c4f3e1ef489ca41"
[[projects]]
branch = "master"
digest = "1:d84d0f563cc649de4c9a8272a0395f75b11952202d18d4d927e933cc91493062"
name = "golang.org/x/sync"
packages = ["errgroup"]
pruneopts = ""
revision = "1d60e4601c6fd243af51cc01ddf169918a5407ca"
[[projects]]
branch = "master"
digest = "1:137a530894d869c2fb09e135e6bb7a5d701347ba273471eaa2483053f8fbeb35"
name = "golang.org/x/sys"
packages = ["unix"]
pruneopts = ""
revision = "3b87a42e500a6dc65dae1a55d0b641295971163e"
[[projects]]
branch = "master"
digest = "1:4cf01dae652ef4428cf9d354bdec79467e436ecfa92d943b1ada8184e1a938b6"
name = "golang.org/x/text"
packages = [
"collate",
@@ -512,19 +631,84 @@
"unicode/cldr",
"unicode/norm",
"unicode/rangetable",
"width"
"width",
]
pruneopts = ""
revision = "2cb43934f0eece38629746959acc633cba083fe4"
[[projects]]
branch = "v2"
digest = "1:f0620375dd1f6251d9973b5f2596228cc8042e887cd7f827e4220bc1ce8c30e2"
name = "gopkg.in/yaml.v2"
packages = ["."]
pruneopts = ""
revision = "5420a8b6744d3b0345ab293f6fcba19c978f1183"
[solve-meta]
analyzer-name = "dep"
analyzer-version = 1
inputs-digest = "993acf46c3937e5cebef4f39a2733150aad7cbf96913a017e56cd03c8241a56e"
input-imports = [
"github.com/BurntSushi/locker",
"github.com/BurntSushi/toml",
"github.com/PuerkitoBio/purell",
"github.com/alecthomas/assert",
"github.com/alecthomas/chroma",
"github.com/alecthomas/chroma/formatters",
"github.com/alecthomas/chroma/formatters/html",
"github.com/alecthomas/chroma/lexers",
"github.com/alecthomas/chroma/styles",
"github.com/bep/debounce",
"github.com/bep/gitmap",
"github.com/bep/go-tocss/scss",
"github.com/bep/go-tocss/scss/libsass",
"github.com/bep/go-tocss/tocss",
"github.com/chaseadamsio/goorgeous",
"github.com/disintegration/imaging",
"github.com/eknkc/amber",
"github.com/fortytw2/leaktest",
"github.com/fsnotify/fsnotify",
"github.com/gobwas/glob",
"github.com/gorilla/websocket",
"github.com/hashicorp/go-immutable-radix",
"github.com/jdkato/prose/transform",
"github.com/kyokomi/emoji",
"github.com/magefile/mage/mg",
"github.com/magefile/mage/sh",
"github.com/markbates/inflect",
"github.com/miekg/mmark",
"github.com/mitchellh/hashstructure",
"github.com/mitchellh/mapstructure",
"github.com/muesli/smartcrop",
"github.com/nicksnyder/go-i18n/i18n/bundle",
"github.com/nicksnyder/go-i18n/i18n/language",
"github.com/olekukonko/tablewriter",
"github.com/russross/blackfriday",
"github.com/sanity-io/litter",
"github.com/spf13/afero",
"github.com/spf13/cast",
"github.com/spf13/cobra",
"github.com/spf13/cobra/doc",
"github.com/spf13/fsync",
"github.com/spf13/jwalterweatherman",
"github.com/spf13/nitro",
"github.com/spf13/pflag",
"github.com/spf13/viper",
"github.com/stretchr/testify/assert",
"github.com/stretchr/testify/require",
"github.com/tdewolff/minify",
"github.com/tdewolff/minify/css",
"github.com/tdewolff/minify/html",
"github.com/tdewolff/minify/js",
"github.com/tdewolff/minify/json",
"github.com/tdewolff/minify/svg",
"github.com/tdewolff/minify/xml",
"github.com/yosssi/ace",
"golang.org/x/image/webp",
"golang.org/x/net/context",
"golang.org/x/sync/errgroup",
"golang.org/x/text/transform",
"golang.org/x/text/unicode/norm",
"gopkg.in/yaml.v2",
]
solver-name = "gps-cdcl"
solver-version = 1
+29
View File
@@ -1,6 +1,7 @@
package deps
import (
"sync"
"time"
"github.com/gohugoio/hugo/common/loggers"
@@ -22,6 +23,7 @@ import (
// There will be normally 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:"-"`
@@ -69,6 +71,30 @@ type Deps struct {
// Timeout is configurable in site config.
Timeout time.Duration
// BuildStartListeners will be notified before a build starts.
BuildStartListeners *Listeners
}
type Listeners struct {
sync.Mutex
// A list of funcs to be notified about an event.
listeners []func()
}
func (b *Listeners) Add(f func()) {
b.Lock()
defer b.Unlock()
b.listeners = append(b.listeners, f)
}
func (b *Listeners) Notify() {
b.Lock()
defer b.Unlock()
for _, notify := range b.listeners {
notify()
}
}
// ResourceProvider is used to create and refresh, and clone resources needed.
@@ -168,6 +194,7 @@ func New(cfg DepsCfg) (*Deps, error) {
ResourceSpec: resourceSpec,
Cfg: cfg.Language,
Language: cfg.Language,
BuildStartListeners: &Listeners{},
Timeout: time.Duration(timeoutms) * time.Millisecond,
}
@@ -210,6 +237,8 @@ func (d Deps) ForLanguage(cfg DepsCfg) (*Deps, error) {
return nil, err
}
d.BuildStartListeners = &Listeners{}
return &d, nil
}
+1 -1
View File
@@ -70,7 +70,7 @@ twitter = "GoHugoIO"
[params]
description = "The worlds fastest framework for building websites"
## Used for views in rendered HTML (i.e., rather than using the .Hugo variable)
release = "0.43"
release = "0.44"
## Setting this to true will add a "noindex" to *EVERY* page on the site
removefromexternalsearch = false
## Gh repo for site footer (include trailing slash)
+18 -2
View File
@@ -8,8 +8,6 @@ categories: ["Releases"]
Hugo `0.43` adds a powerful and very simple to use **Assets Pipeline** with **SASS and SCSS** with source map support, **PostCSS** and **minification** and **fingerprinting** and **Subresource Integrity** and ... much more. Oh, did we mention that you can now do **ad-hoc image processing** and execute text resources as Go templates?
I, [@bep](https://github.com/bep), implemented this in [dea71670](https://github.com/gohugoio/hugo/commit/dea71670c059ab4d5a42bd22503f18c087dd22d4) [#4381]. We will work hard to get the documentation up to date, but follow the links above for details, and also see this [demo project](https://github.com/bep/hugo-sass-test).
An example pipeline:
```go-html-template
@@ -19,6 +17,24 @@ An example pipeline:
To me, the above is beautiful in its speed and simplicity. It could be printed on a t-shirt. I wrote in the [Hugo Birthday Post](https://gohugo.io/news/lets-celebrate-hugos-5th-birthday/) some days ago about the value of a single binary with native and fast implementations. I should have added _simplicity_ as a keyword. There seem to be a misconception that all of this needs to be hard and painful.
New functions to create `Resource` objects:
* `resources.Get`
* `resources.FromString`: Create a Resource from a string.
New `Resource` transformation funcs:
* `resources.ToCSS`: Compile `SCSS` or `SASS` into `CSS`.
* `resources.PostCSS`: Process your CSS with PostCSS. Config file support (project or theme or passed as an option).
* `resources.Minify`: Currently supports `css`, `js`, `json`, `html`, `svg`, `xml`.
* `resources.Fingerprint`: Creates a fingerprinted version of the given Resource with Subresource Integrity.
* `resources.Concat`: Concatenates a list of Resource objects. Think of this as a poor man's bundler.
* `resources.ExecuteAsTemplate`: Parses and executes the given Resource and data context (e.g. .Site) as a Go template.
I, [@bep](https://github.com/bep), implemented this in [dea71670](https://github.com/gohugoio/hugo/commit/dea71670c059ab4d5a42bd22503f18c087dd22d4). We will work hard to get the documentation up to date, but follow the links above for details, and also see this [demo project](https://github.com/bep/hugo-sass-test).
This release represents **35 contributions by 7 contributors** to the main Hugo code base.
[@bep](https://github.com/bep) leads the Hugo development with a significant amount of contributions, but also a big shoutout to [@anthonyfok](https://github.com/anthonyfok), [@openscript](https://github.com/openscript), and [@caarlos0](https://github.com/caarlos0) for their ongoing contributions.
And a big thanks to [@digitalcraftsman](https://github.com/digitalcraftsman) for his relentless work on keeping the themes site in pristine condition and to [@kaushalmodi](https://github.com/kaushalmodi) for his great work on the documentation site.
@@ -0,0 +1,39 @@
---
date: 2018-07-13
title: "0.44"
description: "0.44"
categories: ["Releases"]
---
Hugo `0.44` is the follow-up release, or **The Sequel**, of the very well received `0.43` only days ago. That release added **Hugo Pipes**, with SCSS/SASS support, assets bundling and minification, ad-hoc image processing and much more.
This is mostly a bug-fix release, but it also includes several important improvements.
Many complained that their SVG images vanished when browsed from the `hugo server`. With **Hugo Pipes** MIME types suddenly got really important, but Hugo's use of `Suffix` was ambiguous. This became visible when we redefined the `image/svg+xml` to work with **Hugo Pipes**. We have now added a `Suffixes` field on the MIME type definition in Hugo, which is a list of one or more filename suffixes the MIME type is identified with. If you need to add a custom MIME type definition, this means that you also need to specify the full MIME type as the key, e.g. `image/svg+xml`.
Hugo now has:
* 27120+ [stars](https://github.com/gohugoio/hugo/stargazers)
* 443+ [contributors](https://github.com/gohugoio/hugo/graphs/contributors)
* 239+ [themes](http://themes.gohugo.io/)
## Notes
* `MediaType.Suffix` is deprecated and replaced with a plural version, `MediaType.Suffixes`, with a more specific definition. You will get a detailed WARNING in the console if you need to do anything.
## Enhancements
* Allow multiple file suffixes per media type [b874a1ba](https://github.com/gohugoio/hugo/commit/b874a1ba7ab8394dc741c8c70303a30a35b63e43) [@bep](https://github.com/bep) [#4920](https://github.com/gohugoio/hugo/issues/4920)
* Clean up the in-memory Resource reader usage [47d38628](https://github.com/gohugoio/hugo/commit/47d38628ec0f4e72ff17661f13456b2a1511fe13) [@bep](https://github.com/bep) [#4936](https://github.com/gohugoio/hugo/issues/4936)
* Move opening of the transformed resources after cache check [0024dcfe](https://github.com/gohugoio/hugo/commit/0024dcfe3e016c67046de06d1dac5e7f5235f9e1) [@bep](https://github.com/bep)
* Improve type support in `resources.Concat` [306573de](https://github.com/gohugoio/hugo/commit/306573def0e20ec16ee5c447981cc09ed8bb7ec7) [@bep](https://github.com/bep) [#4934](https://github.com/gohugoio/hugo/issues/4934)
* Flush `partialCached` cache on rebuilds [6b6dcb44](https://github.com/gohugoio/hugo/commit/6b6dcb44a014699c289bf32fe57d4c4216777be0) [@bep](https://github.com/bep) [#4931](https://github.com/gohugoio/hugo/issues/4931)
* Include the transformation step in the error message [d96f2a46](https://github.com/gohugoio/hugo/commit/d96f2a460f58e91d8f6253a489d4879acfec6916) [@bep](https://github.com/bep) [#4924](https://github.com/gohugoio/hugo/issues/4924)
* Exclude *.svg from CRLF/LF conversion [9c1e8208](https://github.com/gohugoio/hugo/commit/9c1e82085eb07d5b4dcdacbe82d5bafd26e08631) [@anthonyfok](https://github.com/anthonyfok)
## Fixes
* Fix `resources.Concat` for transformed resources [beec1fc9](https://github.com/gohugoio/hugo/commit/beec1fc98e5d37bba742d6bc2a0ff7c344b469f8) [@bep](https://github.com/bep) [#4936](https://github.com/gohugoio/hugo/issues/4936)
* Fix static filesystem for themed multihost sites [80c8f3b8](https://github.com/gohugoio/hugo/commit/80c8f3b81a9849080e64bf877288ede28d960d3f) [@bep](https://github.com/bep) [#4929](https://github.com/gohugoio/hugo/issues/4929)
* Set permission of embedded templates to 0644 [2b73e89d](https://github.com/gohugoio/hugo/commit/2b73e89d6d2822e86360a6c92c87f539677c119b) [@anthonyfok](https://github.com/anthonyfok)
+4 -1
View File
@@ -1,11 +1,14 @@
project_name: hugo_extended
builds:
- binary: hugo
ldflags: -s -w -X github.com/gohugoio/hugo/hugolib.BuildDate={{.Date}}
ldflags:
- -s -w -X github.com/gohugoio/hugo/hugolib.BuildDate={{.Date}}
- "-extldflags '-static'"
env:
- CGO_ENABLED=1
- CC=x86_64-w64-mingw32-gcc
- CXX=x86_64-w64-mingw32-g++
- CGO_LDFLAGS="-static"
flags:
- -tags
- extended
+1 -1
View File
@@ -123,7 +123,7 @@ func (v HugoVersion) NextPatchLevel(level int) HugoVersion {
// CurrentHugoVersion represents the current build version.
// This should be the only one.
var CurrentHugoVersion = HugoVersion{
Number: 0.43,
Number: 0.44,
PatchLevel: 0,
Suffix: "",
}
+8 -2
View File
@@ -219,8 +219,11 @@ map[string]interface {}{
"mediatype": Type{
MainType: "text",
SubType: "m1",
Suffix: "m1main",
OldSuffix: "m1main",
Delimiter: ".",
Suffixes: []string{
"m1main",
},
},
},
"o2": map[string]interface {}{
@@ -228,8 +231,11 @@ map[string]interface {}{
"mediatype": Type{
MainType: "text",
SubType: "m2",
Suffix: "m2theme",
OldSuffix: "m2theme",
Delimiter: ".",
Suffixes: []string{
"m2theme",
},
},
},
}`, got["outputformats"])
+8 -1
View File
@@ -499,7 +499,6 @@ func (b *sourceFilesystemsBuilder) createRootMappingFs(dirKey, themeFolder strin
s.Fs = afero.NewReadOnlyFs(fs)
return s, nil
}
func (b *sourceFilesystemsBuilder) existsInSource(abspath string) bool {
@@ -536,6 +535,14 @@ func (b *sourceFilesystemsBuilder) createStaticFs() error {
return err
}
if b.hasTheme {
themeFolder := "static"
fs = afero.NewCopyOnWriteFs(newRealBase(afero.NewBasePathFs(b.themeFs, themeFolder)), fs)
for _, absThemeDir := range b.absThemeDirs {
s.Dirnames = append(s.Dirnames, filepath.Join(absThemeDir, themeFolder))
}
}
s.Fs = fs
ms[l.Lang] = s
+84 -3
View File
@@ -20,6 +20,8 @@ import (
"path/filepath"
"testing"
"github.com/gohugoio/hugo/langs"
"github.com/spf13/afero"
"github.com/gohugoio/hugo/hugofs"
@@ -167,9 +169,6 @@ func TestRealDirs(t *testing.T) {
}()
v.Set("workingDir", root)
v.Set("contentDir", "content")
v.Set("resourceDir", "resources")
v.Set("publishDir", "public")
v.Set("themesDir", themesDir)
v.Set("theme", "mytheme")
@@ -211,12 +210,94 @@ func TestRealDirs(t *testing.T) {
}
func TestStaticFs(t *testing.T) {
assert := require.New(t)
v := createConfig()
workDir := "mywork"
v.Set("workingDir", workDir)
v.Set("themesDir", "themes")
v.Set("theme", "t1")
fs := hugofs.NewMem(v)
themeStaticDir := filepath.Join(workDir, "themes", "t1", "static")
afero.WriteFile(fs.Source, filepath.Join(workDir, "mystatic", "f1.txt"), []byte("Hugo Rocks!"), 0755)
afero.WriteFile(fs.Source, filepath.Join(themeStaticDir, "f1.txt"), []byte("Hugo Themes Rocks!"), 0755)
afero.WriteFile(fs.Source, filepath.Join(themeStaticDir, "f2.txt"), []byte("Hugo Themes Still Rocks!"), 0755)
p, err := paths.New(fs, v)
assert.NoError(err)
bfs, err := NewBase(p)
sfs := bfs.StaticFs("en")
checkFileContent(sfs, "f1.txt", assert, "Hugo Rocks!")
checkFileContent(sfs, "f2.txt", assert, "Hugo Themes Still Rocks!")
}
func TestStaticFsMultiHost(t *testing.T) {
assert := require.New(t)
v := createConfig()
workDir := "mywork"
v.Set("workingDir", workDir)
v.Set("themesDir", "themes")
v.Set("theme", "t1")
v.Set("multihost", true)
vn := viper.New()
vn.Set("staticDir", "nn_static")
en := langs.NewLanguage("en", v)
no := langs.NewLanguage("no", v)
no.Set("staticDir", "static_no")
languages := langs.Languages{
en,
no,
}
v.Set("languagesSorted", languages)
fs := hugofs.NewMem(v)
themeStaticDir := filepath.Join(workDir, "themes", "t1", "static")
afero.WriteFile(fs.Source, filepath.Join(workDir, "mystatic", "f1.txt"), []byte("Hugo Rocks!"), 0755)
afero.WriteFile(fs.Source, filepath.Join(workDir, "static_no", "f1.txt"), []byte("Hugo Rocks in Norway!"), 0755)
afero.WriteFile(fs.Source, filepath.Join(themeStaticDir, "f1.txt"), []byte("Hugo Themes Rocks!"), 0755)
afero.WriteFile(fs.Source, filepath.Join(themeStaticDir, "f2.txt"), []byte("Hugo Themes Still Rocks!"), 0755)
p, err := paths.New(fs, v)
assert.NoError(err)
bfs, err := NewBase(p)
enFs := bfs.StaticFs("en")
checkFileContent(enFs, "f1.txt", assert, "Hugo Rocks!")
checkFileContent(enFs, "f2.txt", assert, "Hugo Themes Still Rocks!")
noFs := bfs.StaticFs("no")
checkFileContent(noFs, "f1.txt", assert, "Hugo Rocks in Norway!")
checkFileContent(noFs, "f2.txt", assert, "Hugo Themes Still Rocks!")
}
func checkFileCount(fs afero.Fs, dirname string, assert *require.Assertions, expected int) {
count, _, err := countFileaAndGetDirs(fs, dirname)
assert.NoError(err)
assert.Equal(expected, count)
}
func checkFileContent(fs afero.Fs, filename string, assert *require.Assertions, expected ...string) {
b, err := afero.ReadFile(fs, filename)
assert.NoError(err)
content := string(b)
for _, e := range expected {
assert.Contains(content, e)
}
}
func countFileaAndGetDirs(fs afero.Fs, dirname string) (int, []string, error) {
if fs == nil {
return 0, nil, errors.New("no fs")
+5
View File
@@ -28,6 +28,7 @@ import (
// Build builds all sites. If filesystem events are provided,
// this is considered to be a potential partial rebuild.
func (h *HugoSites) Build(config BuildCfg, events ...fsnotify.Event) error {
if h.Metrics != nil {
h.Metrics.Reset()
}
@@ -42,6 +43,10 @@ func (h *HugoSites) Build(config BuildCfg, events ...fsnotify.Event) error {
conf.whatChanged = &whatChanged{source: true, other: true}
}
for _, s := range h.Sites {
s.Deps.BuildStartListeners.Notify()
}
if len(events) > 0 {
// Rebuild
if err := h.initRebuild(conf); err != nil {
+1 -1
View File
@@ -218,7 +218,7 @@ func newOutputFormat(p *Page, f output.Format) *OutputFormat {
func (p *PageOutput) AlternativeOutputFormats() (OutputFormats, error) {
var o OutputFormats
for _, of := range p.OutputFormats() {
if of.f.NotAlternative || of.f == p.outputFormat {
if of.f.NotAlternative || of.f.Name == p.outputFormat.Name {
continue
}
o = append(o, of)
+1 -1
View File
@@ -239,7 +239,7 @@ func createTargetPath(d targetPathDescriptor) string {
}
if isUgly {
pagePath += d.Type.MediaType.Delimiter + d.Type.MediaType.Suffix
pagePath += d.Type.MediaType.FullSuffix()
} else {
pagePath = filepath.Join(pagePath, d.Type.BaseName+d.Type.MediaType.FullSuffix())
}
+3 -3
View File
@@ -30,7 +30,7 @@ func TestPageTargetPath(t *testing.T) {
pathSpec := newTestDefaultPathSpec(t)
noExtNoDelimMediaType := media.TextType
noExtNoDelimMediaType.Suffix = ""
noExtNoDelimMediaType.Suffixes = []string{}
noExtNoDelimMediaType.Delimiter = ""
// Netlify style _redirects
@@ -169,8 +169,8 @@ func TestPageTargetPath(t *testing.T) {
} else if test.d.Kind == KindHome && test.d.Type.Path != "" {
} else if (!strings.HasPrefix(expected, "/index") || test.d.Addends != "") && test.d.URL == "" && isUgly {
expected = strings.Replace(expected,
"/"+test.d.Type.BaseName+"."+test.d.Type.MediaType.Suffix,
"."+test.d.Type.MediaType.Suffix, -1)
"/"+test.d.Type.BaseName+"."+test.d.Type.MediaType.Suffix(),
"."+test.d.Type.MediaType.Suffix(), -1)
}
if test.d.LangPrefix != "" && !(test.d.Kind == KindPage && test.d.URL != "") {
+1 -1
View File
@@ -239,7 +239,7 @@ func TestPaginationURLFactory(t *testing.T) {
}
if uglyURLs {
expected = expected[:len(expected)-1] + "." + test.d.Type.MediaType.Suffix
expected = expected[:len(expected)-1] + "." + test.d.Type.MediaType.Suffix()
}
pathSpec := newTestPathSpec(fs, cfg)
+40 -7
View File
@@ -36,12 +36,15 @@ func TestResourceChain(t *testing.T) {
{{ $sass := resources.Get "sass/styles3.sass" | toCSS }}
{{ $scssCustomTarget := resources.Get "scss/styles2.scss" | toCSS (dict "targetPath" "styles/main.css") }}
{{ $scssCustomTargetString := resources.Get "scss/styles2.scss" | toCSS "styles/main.css" }}
{{ $scssMin := resources.Get "scss/styles2.scss" | toCSS | minify }}
{{ $scssMin := resources.Get "scss/styles2.scss" | toCSS | minify }}
{{ $scssFromTempl := ".{{ .Kind }} { color: blue; }" | resources.FromString "kindofblue.templ" | resources.ExecuteAsTemplate "kindofblue.scss" . | toCSS (dict "targetPath" "styles/templ.css") | minify }}
{{ $bundle1 := slice $scssFromTempl $scssMin | resources.Concat "styles/bundle1.css" }}
T1: Len Content: {{ len $scss.Content }}|RelPermalink: {{ $scss.RelPermalink }}|Permalink: {{ $scss.Permalink }}|MediaType: {{ $scss.MediaType.Type }}
T2: Content: {{ $scssMin.Content }}|RelPermalink: {{ $scssMin.RelPermalink }}
T3: Content: {{ len $scssCustomTarget.Content }}|RelPermalink: {{ $scssCustomTarget.RelPermalink }}|MediaType: {{ $scssCustomTarget.MediaType.Type }}
T4: Content: {{ len $scssCustomTargetString.Content }}|RelPermalink: {{ $scssCustomTargetString.RelPermalink }}|MediaType: {{ $scssCustomTargetString.MediaType.Type }}
T5: Content: {{ $sass.Content }}|T5 RelPermalink: {{ $sass.RelPermalink }}|
T6: {{ $bundle1.Permalink }}
`)
}, func(b *sitesBuilder) {
b.AssertFileContent("public/index.html", `T1: Len Content: 24|RelPermalink: /scss/styles2.css|Permalink: http://example.com/scss/styles2.css|MediaType: text/css`)
@@ -50,6 +53,10 @@ T5: Content: {{ $sass.Content }}|T5 RelPermalink: {{ $sass.RelPermalink }}|
b.AssertFileContent("public/index.html", `T4: Content: 24|RelPermalink: /styles/main.css|MediaType: text/css`)
b.AssertFileContent("public/index.html", `T5: Content: .content-navigation {`)
b.AssertFileContent("public/index.html", `T5 RelPermalink: /sass/styles3.css|`)
b.AssertFileContent("public/index.html", `T6: http://example.com/styles/bundle1.css`)
b.AssertFileContent("public/styles/templ.min.css", `.home{color:blue}`)
b.AssertFileContent("public/styles/bundle1.css", `.home{color:blue}body{color:#333}`)
}},
@@ -80,14 +87,21 @@ Min HTML: {{ ( resources.Get "mydata/html1.html" | resources.Minify ).Content |
{{ $a := "A" | resources.FromString "a.txt"}}
{{ $b := "B" | resources.FromString "b.txt"}}
{{ $c := "C" | resources.FromString "c.txt"}}
{{ $textResources := .Resources.Match "*.txt" }}
{{ $combined := slice $a $b $c | resources.Concat "bundle/concat.txt" }}
T: Content: {{ $combined.Content }}|RelPermalink: {{ $combined.RelPermalink }}|Permalink: {{ $combined.Permalink }}|MediaType: {{ $combined.MediaType.Type }}
T1: Content: {{ $combined.Content }}|RelPermalink: {{ $combined.RelPermalink }}|Permalink: {{ $combined.Permalink }}|MediaType: {{ $combined.MediaType.Type }}
{{ with $textResources }}
{{ $combinedText := . | resources.Concat "bundle/concattxt.txt" }}
T2: Content: {{ $combinedText.Content }}|{{ $combinedText.RelPermalink }}
{{ end }}
`)
}, func(b *sitesBuilder) {
b.AssertFileContent("public/index.html", `T: Content: ABC|RelPermalink: /bundle/concat.txt|Permalink: http://example.com/bundle/concat.txt|MediaType: text/plain`)
b.AssertFileContent("public/index.html", `T1: Content: ABC|RelPermalink: /bundle/concat.txt|Permalink: http://example.com/bundle/concat.txt|MediaType: text/plain`)
b.AssertFileContent("public/bundle/concat.txt", "ABC")
}},
b.AssertFileContent("public/index.html", `T2: Content: t1t|t2t|`)
b.AssertFileContent("public/bundle/concattxt.txt", "t1t|t2t|")
}},
{"fromstring", func() bool { return true }, func(b *sitesBuilder) {
b.WithTemplates("home.html", `
{{ $r := "Hugo Rocks!" | resources.FromString "rocks/hugo.txt" }}
@@ -137,12 +151,31 @@ T3: {{ $resultMD5.Content }}|{{ $resultMD5.RelPermalink}}|{{$resultMD5.MediaType
b := newTestSitesBuilder(t).WithLogger(loggers.NewWarningLogger())
b.WithSimpleConfigFile()
b.WithContent("page.md", `
b.WithContent("_index.md", `
---
title: Hello
title: Home
---
`)
Home.
`,
"page1.md", `
---
title: Hello1
---
Hello1
`,
"page2.md", `
---
title: Hello2
---
Hello2
`,
"t1.txt", "t1t|",
"t2.txt", "t2t|",
)
b.WithSourceFile(filepath.Join("assets", "css", "styles1.css"), `
h1 {
+2 -2
View File
@@ -173,11 +173,11 @@ type scKey struct {
}
func newScKey(m media.Type, shortcodeplaceholder string) scKey {
return scKey{Suffix: m.Suffix, ShortcodePlaceholder: shortcodeplaceholder}
return scKey{Suffix: m.Suffix(), ShortcodePlaceholder: shortcodeplaceholder}
}
func newScKeyFromLangAndOutputFormat(lang string, o output.Format, shortcodeplaceholder string) scKey {
return scKey{Lang: lang, Suffix: o.MediaType.Suffix, OutputFormat: o.Name, ShortcodePlaceholder: shortcodeplaceholder}
return scKey{Lang: lang, Suffix: o.MediaType.Suffix(), OutputFormat: o.Name, ShortcodePlaceholder: shortcodeplaceholder}
}
func newDefaultScKey(shortcodeplaceholder string) scKey {
+3 -2
View File
@@ -586,8 +586,9 @@ type whatChanged struct {
// package, so it will behave correctly with Hugo's built-in server.
func (s *Site) RegisterMediaTypes() {
for _, mt := range s.mediaTypesConfig {
// The last one will win if there are any duplicates.
_ = mime.AddExtensionType("."+mt.Suffix, mt.Type()+"; charset=utf-8")
for _, suffix := range mt.Suffixes {
_ = mime.AddExtensionType(mt.Delimiter+suffix, mt.Type()+"; charset=utf-8")
}
}
}
+2 -2
View File
@@ -179,7 +179,7 @@ Len Pages: {{ .Kind }} {{ len .Site.RegularPages }} Page Number: {{ .Paginator.P
th.assertFileContent("public/index.html",
// The HTML entity is a deliberate part of this test: The HTML templates are
// parsed with html/template.
`List HTML|JSON Home|<atom:link href=http://example.com/blog/ rel="self" type="text/html&#43;html" />`,
`List HTML|JSON Home|<atom:link href=http://example.com/blog/ rel="self" type="text/html" />`,
"en: Elbow",
"ShortHTML",
"OtherShort: <h1>Hi!</h1>",
@@ -195,7 +195,7 @@ Len Pages: {{ .Kind }} {{ len .Site.RegularPages }} Page Number: {{ .Paginator.P
th.assertFileContent("public/index.json",
"Output/Rel: JSON/canonical|",
// JSON is plain text, so no need to safeHTML this and that
`<atom:link href=http://example.com/blog/index.json rel="self" type="application/json+json" />`,
`<atom:link href=http://example.com/blog/index.json rel="self" type="application/json" />`,
"ShortJSON",
"OtherShort: <h1>Hi!</h1>",
)
+2 -2
View File
@@ -69,7 +69,7 @@ func headlessPagesPublisher(s *Site, wg *sync.WaitGroup) {
defer wg.Done()
for _, page := range s.headlessPages {
outFormat := page.outputFormats[0] // There is only one
if outFormat != s.rc.Format {
if outFormat.Name != s.rc.Format.Name {
// Avoid double work.
continue
}
@@ -92,7 +92,7 @@ func pageRenderer(s *Site, pages <-chan *Page, results chan<- error, wg *sync.Wa
for i, outFormat := range page.outputFormats {
if outFormat != page.s.rc.Format {
if outFormat.Name != page.s.rc.Format.Name {
// Will be rendered ... later.
continue
}
+2
View File
@@ -15,6 +15,7 @@ package hugolib
import (
"fmt"
"os"
"path/filepath"
"strings"
"testing"
@@ -359,6 +360,7 @@ func doTestShouldAlwaysHaveUglyURLs(t *testing.T, uglyURLs bool) {
func TestNewSiteDefaultLang(t *testing.T) {
t.Parallel()
defer os.Remove("resources")
s, err := NewSiteDefaultLang()
require.NoError(t, err)
require.Equal(t, hugofs.Os, s.Fs.Source)
+192 -61
View File
@@ -19,6 +19,7 @@ import (
"sort"
"strings"
"github.com/gohugoio/hugo/helpers"
"github.com/mitchellh/mapstructure"
)
@@ -29,19 +30,39 @@ const (
// Type (also known as MIME type and content type) is a two-part identifier for
// file formats and format contents transmitted on the Internet.
// For Hugo's use case, we use the top-level type name / subtype name + suffix.
// One example would be image/jpeg+jpg
// One example would be application/svg+xml
// If suffix is not provided, the sub type will be used.
// See // https://en.wikipedia.org/wiki/Media_type
type Type struct {
MainType string `json:"mainType"` // i.e. text
SubType string `json:"subType"` // i.e. html
Suffix string `json:"suffix"` // i.e html
Delimiter string `json:"delimiter"` // defaults to "."
MainType string `json:"mainType"` // i.e. text
SubType string `json:"subType"` // i.e. html
// Deprecated in Hugo 0.44. To be renamed and unexported.
// Was earlier used both to set file suffix and to augment the MIME type.
// This had its limitations and issues.
OldSuffix string `json:"-" mapstructure:"suffix"`
Delimiter string `json:"delimiter"` // e.g. "."
Suffixes []string `json:"suffixes"`
// Set when doing lookup by suffix.
fileSuffix string
}
// FromString creates a new Type given a type sring on the form MainType/SubType and
// FromStringAndExt is same as FromString, but adds the file extension to the type.
func FromStringAndExt(t, ext string) (Type, error) {
tp, err := fromString(t)
if err != nil {
return tp, err
}
tp.Suffixes = []string{strings.TrimPrefix(ext, ".")}
return tp, nil
}
// FromString creates a new Type given a type string on the form MainType/SubType and
// an optional suffix, e.g. "text/html" or "text/html+html".
func FromString(t string) (Type, error) {
func fromString(t string) (Type, error) {
t = strings.ToLower(t)
parts := strings.Split(t, "/")
if len(parts) != 2 {
@@ -54,54 +75,67 @@ func FromString(t string) (Type, error) {
var suffix string
if len(subParts) == 1 {
suffix = subType
} else {
if len(subParts) > 1 {
suffix = subParts[1]
}
return Type{MainType: mainType, SubType: subType, Suffix: suffix, Delimiter: defaultDelimiter}, nil
return Type{MainType: mainType, SubType: subType, OldSuffix: suffix}, nil
}
// Type returns a string representing the main- and sub-type of a media type, i.e. "text/css".
// Type returns a string representing the main- and sub-type of a media type, e.g. "text/css".
// A suffix identifier will be appended after a "+" if set, e.g. "image/svg+xml".
// Hugo will register a set of default media types.
// These can be overridden by the user in the configuration,
// by defining a media type with the same Type.
func (m Type) Type() string {
// Examples are
// image/svg+xml
// text/css
if m.OldSuffix != "" {
return fmt.Sprintf("%s/%s+%s", m.MainType, m.SubType, m.OldSuffix)
}
return fmt.Sprintf("%s/%s", m.MainType, m.SubType)
}
func (m Type) String() string {
if m.Suffix != "" {
return fmt.Sprintf("%s/%s+%s", m.MainType, m.SubType, m.Suffix)
}
return fmt.Sprintf("%s/%s", m.MainType, m.SubType)
return m.Type()
}
// FullSuffix returns the file suffix with any delimiter prepended.
func (m Type) FullSuffix() string {
return m.Delimiter + m.Suffix
return m.Delimiter + m.Suffix()
}
// Suffix returns the file suffix without any delmiter prepended.
func (m Type) Suffix() string {
if m.fileSuffix != "" {
return m.fileSuffix
}
if len(m.Suffixes) > 0 {
return m.Suffixes[0]
}
// There are MIME types without file suffixes.
return ""
}
var (
CalendarType = Type{"text", "calendar", "ics", defaultDelimiter}
CSSType = Type{"text", "css", "css", defaultDelimiter}
SCSSType = Type{"text", "x-scss", "scss", defaultDelimiter}
SASSType = Type{"text", "x-sass", "sass", defaultDelimiter}
CSVType = Type{"text", "csv", "csv", defaultDelimiter}
HTMLType = Type{"text", "html", "html", defaultDelimiter}
JavascriptType = Type{"application", "javascript", "js", defaultDelimiter}
JSONType = Type{"application", "json", "json", defaultDelimiter}
RSSType = Type{"application", "rss", "xml", defaultDelimiter}
XMLType = Type{"application", "xml", "xml", defaultDelimiter}
// The official MIME type of SVG is image/svg+xml. We currently only support one extension
// per mime type. The workaround in projects is to create multiple media type definitions,
// but we need to improve this to take other known suffixes into account.
// But until then, svg has an svg extension, which is very common. TODO(bep)
SVGType = Type{"image", "svg", "svg", defaultDelimiter}
TextType = Type{"text", "plain", "txt", defaultDelimiter}
// Definitions from https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types etc.
// Note that from Hugo 0.44 we only set Suffix if it is part of the MIME type.
CalendarType = Type{MainType: "text", SubType: "calendar", Suffixes: []string{"ics"}, Delimiter: defaultDelimiter}
CSSType = Type{MainType: "text", SubType: "css", Suffixes: []string{"css"}, Delimiter: defaultDelimiter}
SCSSType = Type{MainType: "text", SubType: "x-scss", Suffixes: []string{"scss"}, Delimiter: defaultDelimiter}
SASSType = Type{MainType: "text", SubType: "x-sass", Suffixes: []string{"sass"}, Delimiter: defaultDelimiter}
CSVType = Type{MainType: "text", SubType: "csv", Suffixes: []string{"csv"}, Delimiter: defaultDelimiter}
HTMLType = Type{MainType: "text", SubType: "html", Suffixes: []string{"html"}, Delimiter: defaultDelimiter}
JavascriptType = Type{MainType: "application", SubType: "javascript", Suffixes: []string{"js"}, Delimiter: defaultDelimiter}
JSONType = Type{MainType: "application", SubType: "json", Suffixes: []string{"json"}, Delimiter: defaultDelimiter}
RSSType = Type{MainType: "application", SubType: "rss", OldSuffix: "xml", Suffixes: []string{"xml"}, Delimiter: defaultDelimiter}
XMLType = Type{MainType: "application", SubType: "xml", Suffixes: []string{"xml"}, Delimiter: defaultDelimiter}
SVGType = Type{MainType: "image", SubType: "svg", OldSuffix: "xml", Suffixes: []string{"svg"}, Delimiter: defaultDelimiter}
TextType = Type{MainType: "text", SubType: "plain", Suffixes: []string{"txt"}, Delimiter: defaultDelimiter}
OctetType = Type{"application", "octet-stream", "", ""}
OctetType = Type{MainType: "application", SubType: "octet-stream"}
)
var DefaultTypes = Types{
@@ -136,13 +170,23 @@ func (t Types) GetByType(tp string) (Type, bool) {
return tt, true
}
}
if !strings.Contains(tp, "+") {
// Try with the main and sub type
parts := strings.Split(tp, "/")
if len(parts) == 2 {
return t.GetByMainSubType(parts[0], parts[1])
}
}
return Type{}, false
}
// GetFirstBySuffix will return the first media type matching the given suffix.
func (t Types) GetFirstBySuffix(suffix string) (Type, bool) {
for _, tt := range t {
if strings.EqualFold(suffix, tt.Suffix) {
if match := tt.matchSuffix(suffix); match != "" {
tt.fileSuffix = match
return tt, true
}
}
@@ -155,12 +199,46 @@ func (t Types) GetFirstBySuffix(suffix string) (Type, bool) {
// The lookup is case insensitive.
func (t Types) GetBySuffix(suffix string) (tp Type, found bool) {
for _, tt := range t {
if strings.EqualFold(suffix, tt.Suffix) {
if match := tt.matchSuffix(suffix); match != "" {
if found {
// ambiguous
found = false
return
}
tp = tt
tp.fileSuffix = match
found = true
}
}
return
}
func (t Type) matchSuffix(suffix string) string {
if strings.EqualFold(suffix, t.OldSuffix) {
return t.OldSuffix
}
for _, s := range t.Suffixes {
if strings.EqualFold(suffix, s) {
return s
}
}
return ""
}
// GetMainSubType gets a media type given a main and a sub type e.g. "text" and "plain".
// It will return false if no format could be found, or if the combination given
// is ambiguous.
// The lookup is case insensitive.
func (t Types) GetByMainSubType(mainType, subType string) (tp Type, found bool) {
for _, tt := range t {
if strings.EqualFold(mainType, tt.MainType) && strings.EqualFold(subType, tt.SubType) {
if found {
// ambiguous
found = false
return
}
tp = tt
found = true
}
@@ -168,46 +246,99 @@ func (t Types) GetBySuffix(suffix string) (tp Type, found bool) {
return
}
func suffixIsDeprecated() {
helpers.Deprecated("MediaType", "Suffix in config.toml", `
Before Hugo 0.44 this was used both to set a custom file suffix and as way
to augment the mediatype definition (what you see after the "+", e.g. "image/svg+xml").
This had its limitations. For one, it was only possible with one file extension per MIME type.
Now you can specify multiple file suffixes using "suffixes", but you need to specify the full MIME type
identifier:
[mediaTypes]
[mediaTypes."image/svg+xml"]
suffixes = ["svg", "abc" ]
In most cases, it will be enough to just change:
[mediaTypes]
[mediaTypes."my/custom-mediatype"]
suffix = "txt"
To:
[mediaTypes]
[mediaTypes."my/custom-mediatype"]
suffixes = ["txt"]
Hugo will still respect values set in "suffix" if no value for "suffixes" is provided, but this will be removed
in a future release.
Note that you can still get the Media Type's suffix from a template: {{ $mediaType.Suffix }}. But this will now map to the MIME type filename.
`, false)
}
// DecodeTypes takes a list of media type configurations and merges those,
// in the order given, with the Hugo defaults as the last resort.
func DecodeTypes(maps ...map[string]interface{}) (Types, error) {
m := make(Types, len(DefaultTypes))
copy(m, DefaultTypes)
var m Types
// Maps type string to Type. Type string is the full application/svg+xml.
mmm := make(map[string]Type)
for _, dt := range DefaultTypes {
suffixes := make([]string, len(dt.Suffixes))
copy(suffixes, dt.Suffixes)
dt.Suffixes = suffixes
mmm[dt.Type()] = dt
}
for _, mm := range maps {
for k, v := range mm {
// It may be tempting to put the full media type in the key, e.g.
// "text/css+css", but that will break the logic below.
if strings.Contains(k, "+") {
return Types{}, fmt.Errorf("media type keys cannot contain any '+' chars. Valid example is %q", "text/css")
}
var mediaType Type
found := false
for i, vv := range m {
// Match by type, i.e. "text/css"
if strings.EqualFold(k, vv.Type()) {
// Merge it with the existing
if err := mapstructure.WeakDecode(v, &m[i]); err != nil {
return m, err
}
found = true
}
}
mediaType, found := mmm[k]
if !found {
mediaType, err := FromString(k)
var err error
mediaType, err = fromString(k)
if err != nil {
return m, err
}
if err := mapstructure.WeakDecode(v, &mediaType); err != nil {
return m, err
}
m = append(m, mediaType)
}
if err := mapstructure.WeakDecode(v, &mediaType); err != nil {
return m, err
}
vm := v.(map[string]interface{})
_, delimiterSet := vm["delimiter"]
_, suffixSet := vm["suffix"]
if suffixSet {
suffixIsDeprecated()
}
// Before Hugo 0.44 we had a non-standard use of the Suffix
// attribute, and this is now deprecated (use Suffixes for file suffixes).
// But we need to keep old configurations working for a while.
if len(mediaType.Suffixes) == 0 && mediaType.OldSuffix != "" {
mediaType.Suffixes = []string{mediaType.OldSuffix}
}
// The user may set the delimiter as an empty string.
if !delimiterSet && len(mediaType.Suffixes) != 0 {
mediaType.Delimiter = defaultDelimiter
} else if suffixSet && !delimiterSet {
mediaType.Delimiter = defaultDelimiter
}
mmm[k] = mediaType
}
}
for _, v := range mmm {
m = append(m, v)
}
sort.Sort(m)
return m, nil
+87 -34
View File
@@ -28,21 +28,21 @@ func TestDefaultTypes(t *testing.T) {
expectedType string
expectedString string
}{
{CalendarType, "text", "calendar", "ics", "text/calendar", "text/calendar+ics"},
{CSSType, "text", "css", "css", "text/css", "text/css+css"},
{SCSSType, "text", "x-scss", "scss", "text/x-scss", "text/x-scss+scss"},
{CSVType, "text", "csv", "csv", "text/csv", "text/csv+csv"},
{HTMLType, "text", "html", "html", "text/html", "text/html+html"},
{JavascriptType, "application", "javascript", "js", "application/javascript", "application/javascript+js"},
{JSONType, "application", "json", "json", "application/json", "application/json+json"},
{RSSType, "application", "rss", "xml", "application/rss", "application/rss+xml"},
{SVGType, "image", "svg", "svg", "image/svg", "image/svg+svg"},
{TextType, "text", "plain", "txt", "text/plain", "text/plain+txt"},
{XMLType, "application", "xml", "xml", "application/xml", "application/xml+xml"},
{CalendarType, "text", "calendar", "ics", "text/calendar", "text/calendar"},
{CSSType, "text", "css", "css", "text/css", "text/css"},
{SCSSType, "text", "x-scss", "scss", "text/x-scss", "text/x-scss"},
{CSVType, "text", "csv", "csv", "text/csv", "text/csv"},
{HTMLType, "text", "html", "html", "text/html", "text/html"},
{JavascriptType, "application", "javascript", "js", "application/javascript", "application/javascript"},
{JSONType, "application", "json", "json", "application/json", "application/json"},
{RSSType, "application", "rss", "xml", "application/rss+xml", "application/rss+xml"},
{SVGType, "image", "svg", "svg", "image/svg+xml", "image/svg+xml"},
{TextType, "text", "plain", "txt", "text/plain", "text/plain"},
{XMLType, "application", "xml", "xml", "application/xml", "application/xml"},
} {
require.Equal(t, test.expectedMainType, test.tp.MainType)
require.Equal(t, test.expectedSubType, test.tp.SubType)
require.Equal(t, test.expectedSuffix, test.tp.Suffix)
require.Equal(t, test.expectedSuffix, test.tp.Suffix(), test.tp.String())
require.Equal(t, defaultDelimiter, test.tp.Delimiter)
require.Equal(t, test.expectedType, test.tp.Type())
@@ -61,34 +61,68 @@ func TestGetByType(t *testing.T) {
_, found = types.GetByType("text/nono")
require.False(t, found)
mt, found = types.GetByType("application/rss+xml")
require.True(t, found)
require.Equal(t, mt, RSSType)
mt, found = types.GetByType("application/rss")
require.True(t, found)
require.Equal(t, mt, RSSType)
}
func TestGetByMainSubType(t *testing.T) {
assert := require.New(t)
f, found := DefaultTypes.GetByMainSubType("text", "plain")
assert.True(found)
assert.Equal(f, TextType)
_, found = DefaultTypes.GetByMainSubType("foo", "plain")
assert.False(found)
}
func TestGetFirstBySuffix(t *testing.T) {
assert := require.New(t)
f, found := DefaultTypes.GetFirstBySuffix("xml")
assert.True(found)
assert.Equal(Type{MainType: "application", SubType: "rss", Suffix: "xml", Delimiter: "."}, f)
assert.Equal(Type{MainType: "application", SubType: "rss", OldSuffix: "xml", Delimiter: ".", Suffixes: []string{"xml"}, fileSuffix: "xml"}, f)
}
func TestFromTypeString(t *testing.T) {
f, err := FromString("text/html")
f, err := fromString("text/html")
require.NoError(t, err)
require.Equal(t, HTMLType, f)
require.Equal(t, HTMLType.Type(), f.Type())
f, err = FromString("application/custom")
f, err = fromString("application/custom")
require.NoError(t, err)
require.Equal(t, Type{MainType: "application", SubType: "custom", Suffix: "custom", Delimiter: defaultDelimiter}, f)
require.Equal(t, Type{MainType: "application", SubType: "custom", OldSuffix: "", fileSuffix: ""}, f)
f, err = FromString("application/custom+pdf")
f, err = fromString("application/custom+sfx")
require.NoError(t, err)
require.Equal(t, Type{MainType: "application", SubType: "custom", Suffix: "pdf", Delimiter: defaultDelimiter}, f)
require.Equal(t, Type{MainType: "application", SubType: "custom", OldSuffix: "sfx"}, f)
_, err = FromString("noslash")
_, err = fromString("noslash")
require.Error(t, err)
f, err = FromString("text/xml; charset=utf-8")
f, err = fromString("text/xml; charset=utf-8")
require.NoError(t, err)
require.Equal(t, Type{MainType: "text", SubType: "xml", Suffix: "xml", Delimiter: "."}, f)
require.Equal(t, Type{MainType: "text", SubType: "xml", OldSuffix: ""}, f)
require.Equal(t, "", f.Suffix())
}
// Add a test for the SVG case
// https://github.com/gohugoio/hugo/issues/4920
func TestFromExtensionMultipleSuffixes(t *testing.T) {
assert := require.New(t)
tp, found := DefaultTypes.GetBySuffix("svg")
assert.True(found)
assert.Equal("image/svg+xml", tp.String())
assert.Equal("svg", tp.fileSuffix)
assert.Equal(".svg", tp.FullSuffix())
tp, found = DefaultTypes.GetByType("image/svg+xml")
assert.True(found)
assert.Equal("image/svg+xml", tp.String())
assert.True(found)
assert.Equal(".svg", tp.FullSuffix())
}
@@ -105,13 +139,40 @@ func TestDecodeTypes(t *testing.T) {
[]map[string]interface{}{
{
"application/json": map[string]interface{}{
"suffix": "jsn"}}},
"suffixes": []string{"jasn"}}}},
false,
func(t *testing.T, name string, tt Types) {
require.Len(t, tt, len(DefaultTypes))
json, found := tt.GetBySuffix("jsn")
json, found := tt.GetBySuffix("jasn")
require.True(t, found)
require.Equal(t, "application/json+jsn", json.String(), name)
require.Equal(t, "application/json", json.String(), name)
}},
{
"Suffix from key, multiple file suffixes",
[]map[string]interface{}{
{
"application/hugo+hg": map[string]interface{}{
"Suffixes": []string{"hg1", "hg2"},
}}},
false,
func(t *testing.T, name string, tt Types) {
require.Len(t, tt, len(DefaultTypes)+1)
hg, found := tt.GetBySuffix("hg")
require.True(t, found)
require.Equal(t, "hg", hg.OldSuffix)
require.Equal(t, "hg", hg.Suffix())
require.Equal(t, ".hg", hg.FullSuffix())
require.Equal(t, "application/hugo+hg", hg.String(), name)
hg, found = tt.GetBySuffix("hg2")
require.True(t, found)
require.Equal(t, "hg", hg.OldSuffix)
require.Equal(t, "hg2", hg.Suffix())
require.Equal(t, ".hg2", hg.FullSuffix())
require.Equal(t, "application/hugo+hg", hg.String(), name)
hg, found = tt.GetByType("application/hugo+hg")
require.True(t, found)
}},
{
"Add custom media type",
@@ -123,6 +184,7 @@ func TestDecodeTypes(t *testing.T) {
func(t *testing.T, name string, tt Types) {
require.Len(t, tt, len(DefaultTypes)+1)
// Make sure we have not broken the default config.
_, found := tt.GetBySuffix("json")
require.True(t, found)
@@ -130,15 +192,6 @@ func TestDecodeTypes(t *testing.T) {
require.True(t, found)
require.Equal(t, "text/hugo+hgo", hugo.String(), name)
}},
{
"Add media type invalid key",
[]map[string]interface{}{
{
"text/hugo+hgo": map[string]interface{}{}}},
true,
func(t *testing.T, name string, tt Types) {
}},
}
for _, test := range tests {
+1 -1
View File
@@ -72,7 +72,7 @@ func createLayoutExamples() interface{} {
Example: example.name,
Kind: example.d.Kind,
OutputFormat: example.f.Name,
Suffix: example.f.MediaType.Suffix,
Suffix: example.f.MediaType.Suffix(),
Layouts: makeLayoutsPresentable(layouts)})
}
+3 -3
View File
@@ -47,7 +47,7 @@ type LayoutHandler struct {
type layoutCacheKey struct {
d LayoutDescriptor
f Format
f string
}
// NewLayoutHandler creates a new LayoutHandler.
@@ -60,7 +60,7 @@ func NewLayoutHandler() *LayoutHandler {
func (l *LayoutHandler) For(d LayoutDescriptor, f Format) ([]string, error) {
// We will get lots of requests for the same layouts, so avoid recalculations.
key := layoutCacheKey{d, f}
key := layoutCacheKey{d, f.Name}
l.mu.RLock()
if cacheVal, found := l.cache[key]; found {
l.mu.RUnlock()
@@ -209,7 +209,7 @@ func (l *layoutBuilder) resolveVariations() []string {
"TYPE", typeVar,
"LAYOUT", layoutVar,
"VARIATIONS", variation,
"EXTENSION", l.f.MediaType.Suffix,
"EXTENSION", l.f.MediaType.Suffix(),
))
}
}
+3 -2
View File
@@ -27,11 +27,11 @@ import (
func TestLayout(t *testing.T) {
noExtNoDelimMediaType := media.TextType
noExtNoDelimMediaType.Suffix = ""
noExtNoDelimMediaType.Suffixes = nil
noExtNoDelimMediaType.Delimiter = ""
noExtMediaType := media.TextType
noExtMediaType.Suffix = ""
noExtMediaType.Suffixes = nil
var (
ampType = Format{
@@ -47,6 +47,7 @@ func TestLayout(t *testing.T) {
MediaType: noExtNoDelimMediaType,
BaseName: "_redirects",
}
noExt = Format{
Name: "NEX",
MediaType: noExtMediaType,
+2 -2
View File
@@ -178,7 +178,7 @@ func (formats Formats) Less(i, j int) bool { return formats[i].Name < formats[j]
// The lookup is case insensitive.
func (formats Formats) GetBySuffix(suffix string) (f Format, found bool) {
for _, ff := range formats {
if strings.EqualFold(suffix, ff.MediaType.Suffix) {
if strings.EqualFold(suffix, ff.MediaType.Suffix()) {
if found {
// ambiguous
found = false
@@ -331,7 +331,7 @@ func decode(mediaTypes media.Types, input, output interface{}) error {
}
func (formats Format) BaseFilename() string {
return formats.BaseName + "." + formats.MediaType.Suffix
return formats.BaseName + formats.MediaType.FullSuffix()
}
func (formats Format) MarshalJSON() ([]byte, error) {
+2 -2
View File
@@ -93,11 +93,11 @@ func TestGetFormatByExt(t *testing.T) {
func TestGetFormatByFilename(t *testing.T) {
noExtNoDelimMediaType := media.TextType
noExtNoDelimMediaType.Suffix = ""
noExtNoDelimMediaType.OldSuffix = ""
noExtNoDelimMediaType.Delimiter = ""
noExtMediaType := media.TextType
noExtMediaType.Suffix = ""
noExtMediaType.OldSuffix = ""
var (
noExtDelimFormat = Format{
+2 -2
View File
@@ -62,7 +62,7 @@ func (r *multiReadSeekCloser) Close() error {
}
// Concat concatenates the list of Resource objects.
func (c *Client) Concat(targetPath string, resources []resource.Resource) (resource.Resource, error) {
func (c *Client) Concat(targetPath string, resources resource.Resources) (resource.Resource, error) {
// The CACHE_OTHER will make sure this will be re-created and published on rebuilds.
return c.rs.ResourceCache.GetOrCreate(resource.CACHE_OTHER, targetPath, func() (resource.Resource, error) {
var resolvedm media.Type
@@ -70,7 +70,7 @@ func (c *Client) Concat(targetPath string, resources []resource.Resource) (resou
// The given set of resources must be of the same Media Type.
// We may improve on that in the future, but then we need to know more.
for i, r := range resources {
if i > 0 && r.MediaType() != resolvedm {
if i > 0 && r.MediaType().Type() != resolvedm.Type() {
return nil, errors.New("resources in Concat must be of the same Media Type")
}
resolvedm = r.MediaType()
+1 -15
View File
@@ -16,12 +16,10 @@
package create
import (
"io"
"path/filepath"
"github.com/spf13/afero"
"github.com/dsnet/golib/memfile"
"github.com/gohugoio/hugo/resource"
)
@@ -36,15 +34,6 @@ func New(rs *resource.Spec) *Client {
return &Client{rs: rs}
}
type memFileCloser struct {
*memfile.File
io.Closer
}
func (m *memFileCloser) Close() error {
return nil
}
// Get creates a new Resource by opening the given filename in the given filesystem.
func (c *Client) Get(fs afero.Fs, filename string) (resource.Resource, error) {
filename = filepath.Clean(filename)
@@ -53,7 +42,6 @@ func (c *Client) Get(fs afero.Fs, filename string) (resource.Resource, error) {
resource.ResourceSourceDescriptor{
LazyPublish: true,
SourceFilename: filename})
})
}
@@ -66,9 +54,7 @@ func (c *Client) FromString(targetPath, content string) (resource.Resource, erro
resource.ResourceSourceDescriptor{
LazyPublish: true,
OpenReadSeekCloser: func() (resource.ReadSeekCloser, error) {
return &memFileCloser{
File: memfile.New([]byte(content)),
}, nil
return resource.NewReadSeekerNoOpCloserFromString(content), nil
},
RelTargetFilename: filepath.Clean(targetPath)})
+1 -1
View File
@@ -45,7 +45,7 @@ func New(rs *resource.Spec) *Client {
addMinifierFunc(m, mt, "text/html", "html", html.Minify)
addMinifierFunc(m, mt, "application/javascript", "js", js.Minify)
addMinifierFunc(m, mt, "application/json", "json", json.Minify)
addMinifierFunc(m, mt, "image/svg", "xml", svg.Minify)
addMinifierFunc(m, mt, "image/svg+xml", "svg", svg.Minify)
addMinifierFunc(m, mt, "application/xml", "xml", xml.Minify)
addMinifierFunc(m, mt, "application/rss", "xml", xml.Minify)
+53
View File
@@ -0,0 +1,53 @@
// Copyright 2018 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 resource
import (
"io"
"strings"
)
// ReadSeeker wraps io.Reader and io.Seeker.
type ReadSeeker interface {
io.Reader
io.Seeker
}
// ReadSeekCloser is implemented by afero.File. We use this as the common type for
// content in Resource objects, even for strings.
type ReadSeekCloser interface {
ReadSeeker
io.Closer
}
// ReadSeekerNoOpCloser implements ReadSeekCloser by doing nothing in Close.
type ReadSeekerNoOpCloser struct {
ReadSeeker
}
// Close does nothing.
func (r ReadSeekerNoOpCloser) Close() error {
return nil
}
// NewReadSeekerNoOpCloser creates a new ReadSeekerNoOpCloser with the given ReadSeeker.
func NewReadSeekerNoOpCloser(r ReadSeeker) ReadSeekerNoOpCloser {
return ReadSeekerNoOpCloser{r}
}
// NewReadSeekerNoOpCloserFromString uses strings.NewReader to create a new ReadSeekerNoOpCloser
// from the given string.
func NewReadSeekerNoOpCloserFromString(content string) ReadSeekerNoOpCloser {
return ReadSeekerNoOpCloser{strings.NewReader(content)}
}
+2 -12
View File
@@ -16,7 +16,6 @@ package resource
import (
"errors"
"fmt"
"io"
"io/ioutil"
"mime"
"os"
@@ -134,14 +133,6 @@ type ContentResource interface {
Content() (interface{}, error)
}
// ReadSeekCloser is implemented by afero.File. We use this as the common type for
// content in Resource objects, even for strings.
type ReadSeekCloser interface {
io.Reader
io.Seeker
io.Closer
}
// OpenReadSeekeCloser allows setting some other way (than reading from a filesystem)
// to open or create a ReadSeekCloser.
type OpenReadSeekCloser func() (ReadSeekCloser, error)
@@ -416,16 +407,15 @@ func (r *Spec) newResource(sourceFs afero.Fs, fd ResourceSourceDescriptor) (Reso
mimeType, found := r.MediaTypes.GetFirstBySuffix(strings.TrimPrefix(ext, "."))
// TODO(bep) we need to handle these ambigous types better, but in this context
// we most likely want the application/xml type.
if mimeType.Suffix == "xml" && mimeType.SubType == "rss" {
if mimeType.Suffix() == "xml" && mimeType.SubType == "rss" {
mimeType, found = r.MediaTypes.GetByType("application/xml")
}
if !found {
mimeStr := mime.TypeByExtension(ext)
if mimeStr != "" {
mimeType, _ = media.FromString(mimeStr)
mimeType, _ = media.FromStringAndExt(mimeStr, ext)
}
}
gr := r.newGenericResourceWithBase(
+1 -1
View File
@@ -97,7 +97,7 @@ func TestNewResourceFromFilenameSubPathInBaseURL(t *testing.T) {
}
var pngType, _ = media.FromString("image/png")
var pngType, _ = media.FromStringAndExt("image/png", "png")
func TestResourcesByType(t *testing.T) {
assert := require.New(t)
+13 -11
View File
@@ -17,6 +17,7 @@ import (
"bytes"
"path"
"strconv"
"strings"
"github.com/gohugoio/hugo/common/errors"
"github.com/gohugoio/hugo/helpers"
@@ -188,11 +189,10 @@ type transformedResource struct {
}
func (r *transformedResource) ReadSeekCloser() (ReadSeekCloser, error) {
rc, ok := r.Resource.(ReadSeekCloserResource)
if !ok {
return nil, fmt.Errorf("resource %T is not a ReadSeekerCloserResource", rc)
if err := r.initContent(); err != nil {
return nil, err
}
return rc.ReadSeekCloser()
return NewReadSeekerNoOpCloserFromString(r.content), nil
}
func (r *transformedResource) transferTransformedValues(another *transformedResource) {
@@ -289,12 +289,6 @@ func (r *transformedResource) transform(setContent bool) (err error) {
first := chain[0]
contentrc, err := contentReadSeekerCloser(first)
if err != nil {
return err
}
defer contentrc.Close()
// Files with a suffix will be stored in cache (both on disk and in memory)
// partitioned by their suffix. There will be other files below /other.
// This partition is also how we determine what to delete on server reloads.
@@ -333,6 +327,7 @@ func (r *transformedResource) transform(setContent bool) (err error) {
r.cache.nlocker.Unlock(key)
return
}
defer r.cache.nlocker.Unlock(key)
defer r.cache.set(key, r)
@@ -348,6 +343,13 @@ func (r *transformedResource) transform(setContent bool) (err error) {
tctx.InMediaType = first.MediaType()
tctx.OutMediaType = first.MediaType()
contentrc, err := contentReadSeekerCloser(first)
if err != nil {
return err
}
defer contentrc.Close()
tctx.From = contentrc
tctx.To = b1
@@ -389,7 +391,7 @@ func (r *transformedResource) transform(setContent bool) (err error) {
// If a prepared bundle for this transformation chain is available, use that.
f := r.tryTransformedFileCache(key)
if f == nil {
return fmt.Errorf("failed to transform %q (%s): %s", tctx.InPath, tctx.InMediaType.Type(), err)
return fmt.Errorf("%s: failed to transform %q (%s): %s", strings.ToUpper(tr.transformation.Key().name), tctx.InPath, tctx.InMediaType.Type(), err)
}
transformedContentr = f
defer f.Close()
+1 -1
View File
@@ -1,5 +1,5 @@
name: hugo
version: "0.43"
version: "0.44"
summary: Fast and Flexible Static Site Generator
description: |
Hugo is a static HTML and CSS website generator written in Go. It is
-76
View File
@@ -1,76 +0,0 @@
Hugo `0.43` adds a powerful and very simple to use **Assets Pipeline** with **SASS and SCSS** with source map support, **PostCSS** and **minification** and **fingerprinting** and **Subresource Integrity** and ... much more. Oh, did we mention that you can now do **ad-hoc image processing** and execute text resources as Go templates?
I, [@bep](https://github.com/bep), implemented this in [dea71670](https://github.com/gohugoio/hugo/commit/dea71670c059ab4d5a42bd22503f18c087dd22d4) [#4381]. We will work hard to get the documentation up to date, but follow the links above for details, and also see this [demo project](https://github.com/bep/hugo-sass-test).
An example pipeline:
```go-html-template
{{ $styles := resources.Get "scss/main.scss" | toCSS | postCSS | minify | fingerprint }}
<link rel="stylesheet" href="{{ $styles.Permalink }}" integrity="{{ $styles.Data.Integrity }}" media="screen">
```
To me, the above is beautiful in its speed and simplicity. It could be printed on a t-shirt. I wrote in the [Hugo Birthday Post](https://gohugo.io/news/lets-celebrate-hugos-5th-birthday/) some days ago about the value of a single binary with native and fast implementations. I should have added _simplicity_ as a keyword. There seem to be a misconception that all of this needs to be hard and painful.
This release represents **35 contributions by 7 contributors** to the main Hugo code base.
[@bep](https://github.com/bep) leads the Hugo development with a significant amount of contributions, but also a big shoutout to [@anthonyfok](https://github.com/anthonyfok), [@openscript](https://github.com/openscript), and [@caarlos0](https://github.com/caarlos0) for their ongoing contributions.
And a big thanks to [@digitalcraftsman](https://github.com/digitalcraftsman) for his relentless work on keeping the themes site in pristine condition and to [@kaushalmodi](https://github.com/kaushalmodi) for his great work on the documentation site.
Many have also been busy writing and fixing the documentation in [hugoDocs](https://github.com/gohugoio/hugoDocs),
which has received **11 contributions by 5 contributors**. A special thanks to [@bep](https://github.com/bep), [@danrl](https://github.com/danrl), [@regisphilibert](https://github.com/regisphilibert), and [@digitalcraftsman](https://github.com/digitalcraftsman) for their work on the documentation site.
Hugo now has:
* 26968+ [stars](https://github.com/gohugoio/hugo/stargazers)
* 443+ [contributors](https://github.com/gohugoio/hugo/graphs/contributors)
* 238+ [themes](http://themes.gohugo.io/)
## Notes
* Replace deprecated {Get,}ByPrefix with {Get,}Match [42ed6025](https://github.com/gohugoio/hugo/commit/42ed602580a672e420e1d860384e812f4871ff67) [@anthonyfok](https://github.com/anthonyfok)
* Hugo is now released with two binary version: One with and one without SCSS/SASS support. At the time of writing, this is only available in the binaries on the GitHub release page. Brew, Snap builds etc. will come. But note that you **only need the extended version if you want to edit SCSS**. For your CI server, or if you don't use SCSS, you will most likely want the non-extended version.
## Enhancements
### Templates
* Return en empty slice in `after` instead of error [f8212d20](https://github.com/gohugoio/hugo/commit/f8212d20009c4b5cc6e1ec733d09531eb6525d9f) [@bep](https://github.com/bep) [#4894](https://github.com/gohugoio/hugo/issues/4894)
* Update internal pagination template to support Bootstrap 4 [ca1e46ef](https://github.com/gohugoio/hugo/commit/ca1e46efb94e3f3d2c8482cb9434d2f38ffd2683) [@bep](https://github.com/bep) [#4881](https://github.com/gohugoio/hugo/issues/4881)
* Support text/template/parse API change in go1.11 [9f27091e](https://github.com/gohugoio/hugo/commit/9f27091e1067875e2577c331acc60adaef5bb234) [@anthonyfok](https://github.com/anthonyfok) [#4784](https://github.com/gohugoio/hugo/issues/4784)
### Core
* Allow forward slash in shortcode names [de37455e](https://github.com/gohugoio/hugo/commit/de37455ec73cffd039b44e8f6c62d2884b1d6bbd) [@bep](https://github.com/bep) [#4886](https://github.com/gohugoio/hugo/issues/4886)
* Reset the global pages cache on server rebuilds [128f14ef](https://github.com/gohugoio/hugo/commit/128f14efad90886ffef37c01ac1e20436a732f97) [@bep](https://github.com/bep) [#4845](https://github.com/gohugoio/hugo/issues/4845)
### Other
* Bump CircleCI image [e3df6478](https://github.com/gohugoio/hugo/commit/e3df6478f09a7a5fed96aced791fa94fd2c35d1a) [@bep](https://github.com/bep)
* Add Goreleaser extended config [626afc98](https://github.com/gohugoio/hugo/commit/626afc98254421f5a5edc97c541b10bd81d5bbbb) [@bep](https://github.com/bep) [#4908](https://github.com/gohugoio/hugo/issues/4908)
* Build both hugo and hugo.extended for 0.43 [e1027c58](https://github.com/gohugoio/hugo/commit/e1027c5846b48c4ad450f6cc27e2654c9e0dae39) [@anthonyfok](https://github.com/anthonyfok) [#4908](https://github.com/gohugoio/hugo/issues/4908)
* Add temporary build script [bfc3488b](https://github.com/gohugoio/hugo/commit/bfc3488b8e8b3dc1ffc6a339ee2dac8dcbdb55a9) [@bep](https://github.com/bep)
* Add "extended" to "hugo version" [ce84b524](https://github.com/gohugoio/hugo/commit/ce84b524f4e94299b5b66afe7ce1a9bd4a9959fc) [@anthonyfok](https://github.com/anthonyfok) [#4913](https://github.com/gohugoio/hugo/issues/4913)
* Add a newScratch template func [2b8d907a](https://github.com/gohugoio/hugo/commit/2b8d907ab731627f4e2a30442cd729064516c8bb) [@bep](https://github.com/bep) [#4685](https://github.com/gohugoio/hugo/issues/4685)
* Add Hugo Piper with SCSS support and much more [dea71670](https://github.com/gohugoio/hugo/commit/dea71670c059ab4d5a42bd22503f18c087dd22d4) [@bep](https://github.com/bep) [#4381](https://github.com/gohugoio/hugo/issues/4381)[#4903](https://github.com/gohugoio/hugo/issues/4903)[#4858](https://github.com/gohugoio/hugo/issues/4858)
* Consider root and current section's content type if set in front matter [c790029e](https://github.com/gohugoio/hugo/commit/c790029e1dbb0b66af18d05764bd6045deb2e180) [@bep](https://github.com/bep) [#4891](https://github.com/gohugoio/hugo/issues/4891)
* Update docker image [554553c0](https://github.com/gohugoio/hugo/commit/554553c09c7657d28681e1fa0638806a452737a0) [@bep](https://github.com/bep)
* Merge branch 'release-0.42.2' [282f6035](https://github.com/gohugoio/hugo/commit/282f6035e7c36f8550d91033e3a66718468c6c8b) [@bep](https://github.com/bep)
* Release 0.42.2 [1637d12e](https://github.com/gohugoio/hugo/commit/1637d12e3762fc1ebab4cd675f75afaf25f59cdb) [@bep](https://github.com/bep)
* Update GoReleaser config [1f0c4e1f](https://github.com/gohugoio/hugo/commit/1f0c4e1fb347bb233f3312c424fbf5a013c03604) [@caarlos0](https://github.com/caarlos0)
* Create missing head.html partial on new theme generation [fd71fa89](https://github.com/gohugoio/hugo/commit/fd71fa89bd6c197402582c87b2b76d4b96d562bf) [@openscript](https://github.com/openscript)
* Add html doctype to baseof.html template for new themes [b5a3aa70](https://github.com/gohugoio/hugo/commit/b5a3aa7082135d0a573f4fbb00f798e26b67b902) [@openscript](https://github.com/openscript)
* Adds .gitattributes to force Go files to LF [6a2968fd](https://github.com/gohugoio/hugo/commit/6a2968fd5c0116d93de0f379ac615e9076821899) [@neurocline](https://github.com/neurocline)
* Update to Go 1.9.7 and Go 1.10.3 [23d5fc82](https://github.com/gohugoio/hugo/commit/23d5fc82ee01d56440d0991c899acd31e9b63e27) [@anthonyfok](https://github.com/anthonyfok)
* Update Dockerfile to a multi-stage build [8531ec7c](https://github.com/gohugoio/hugo/commit/8531ec7ca36fd35a57fba06bbb06a65c94dfd3ed) [@skoblenick](https://github.com/skoblenick) [#4154](https://github.com/gohugoio/hugo/issues/4154)
* Release 0.42.1 [d67e843c](https://github.com/gohugoio/hugo/commit/d67e843c1212e1f53933556b5f946c8541188d9a) [@bep](https://github.com/bep)
* Do not fail server build when /static is missing [34ee27a7](https://github.com/gohugoio/hugo/commit/34ee27a78b9e2b5f475d44253ae234067b76cc6e) [@bep](https://github.com/bep) [#4846](https://github.com/gohugoio/hugo/issues/4846)
## Fixes
* Do not create paginator pages for the other output formats [43338c3a](https://github.com/gohugoio/hugo/commit/43338c3a99769eb7d0df0c12559b8b3d42b67dba) [@bep](https://github.com/bep) [#4890](https://github.com/gohugoio/hugo/issues/4890)
* Fix the shortcodes/partials vs base template detection [a5d0a57e](https://github.com/gohugoio/hugo/commit/a5d0a57e6bdab583134a68c035aac9b3007f006a) [@bep](https://github.com/bep) [#4897](https://github.com/gohugoio/hugo/issues/4897)
* nfpm replacements [e1a052ec](https://github.com/gohugoio/hugo/commit/e1a052ecb823c688406a8af97dfaaf52a75231da) [@caarlos0](https://github.com/caarlos0)
* Fix typos [3cea2932](https://github.com/gohugoio/hugo/commit/3cea2932e17a08ebc19cd05f3079d9379bc8fba5) [@idealhack](https://github.com/idealhack)
+31
View File
@@ -0,0 +1,31 @@
Hugo `0.44` is the follow-up release, or **The Sequel**, of the very well received `0.43` only days ago. That release added **Hugo Pipes**, with SCSS/SASS support, assets bundling and minification, ad-hoc image processing and much more.
This is mostly a bug-fix release, but it also includes several important improvements.
Many complained that their SVG images vanished when browsed from the `hugo server`. With **Hugo Pipes** MIME types suddenly got really important, but Hugo's use of `Suffix` was ambiguous. This became visible when we redefined the `image/svg+xml` to work with **Hugo Pipes**. We have now added a `Suffixes` field on the MIME type definition in Hugo, which is a list of one or more filename suffixes the MIME type is identified with. If you need to add a custom MIME type definition, this means that you also need to specify the full MIME type as the key, e.g. `image/svg+xml`.
Hugo now has:
* 27120+ [stars](https://github.com/gohugoio/hugo/stargazers)
* 443+ [contributors](https://github.com/gohugoio/hugo/graphs/contributors)
* 239+ [themes](http://themes.gohugo.io/)
## Notes
* `MediaType.Suffix` is deprecated and replaced with a plural version, `MediaType.Suffixes`, with a more specific definition. You will get a detailed WARNING in the console if you need to do anything.
## Enhancements
* Allow multiple file suffixes per media type [b874a1ba](https://github.com/gohugoio/hugo/commit/b874a1ba7ab8394dc741c8c70303a30a35b63e43) [@bep](https://github.com/bep) [#4920](https://github.com/gohugoio/hugo/issues/4920)
* Clean up the in-memory Resource reader usage [47d38628](https://github.com/gohugoio/hugo/commit/47d38628ec0f4e72ff17661f13456b2a1511fe13) [@bep](https://github.com/bep) [#4936](https://github.com/gohugoio/hugo/issues/4936)
* Move opening of the transformed resources after cache check [0024dcfe](https://github.com/gohugoio/hugo/commit/0024dcfe3e016c67046de06d1dac5e7f5235f9e1) [@bep](https://github.com/bep)
* Improve type support in `resources.Concat` [306573de](https://github.com/gohugoio/hugo/commit/306573def0e20ec16ee5c447981cc09ed8bb7ec7) [@bep](https://github.com/bep) [#4934](https://github.com/gohugoio/hugo/issues/4934)
* Flush `partialCached` cache on rebuilds [6b6dcb44](https://github.com/gohugoio/hugo/commit/6b6dcb44a014699c289bf32fe57d4c4216777be0) [@bep](https://github.com/bep) [#4931](https://github.com/gohugoio/hugo/issues/4931)
* Include the transformation step in the error message [d96f2a46](https://github.com/gohugoio/hugo/commit/d96f2a460f58e91d8f6253a489d4879acfec6916) [@bep](https://github.com/bep) [#4924](https://github.com/gohugoio/hugo/issues/4924)
* Exclude *.svg from CRLF/LF conversion [9c1e8208](https://github.com/gohugoio/hugo/commit/9c1e82085eb07d5b4dcdacbe82d5bafd26e08631) [@anthonyfok](https://github.com/anthonyfok)
## Fixes
* Fix `resources.Concat` for transformed resources [beec1fc9](https://github.com/gohugoio/hugo/commit/beec1fc98e5d37bba742d6bc2a0ff7c344b469f8) [@bep](https://github.com/bep) [#4936](https://github.com/gohugoio/hugo/issues/4936)
* Fix static filesystem for themed multihost sites [80c8f3b8](https://github.com/gohugoio/hugo/commit/80c8f3b81a9849080e64bf877288ede28d960d3f) [@bep](https://github.com/bep) [#4929](https://github.com/gohugoio/hugo/issues/4929)
* Set permission of embedded templates to 0644 [2b73e89d](https://github.com/gohugoio/hugo/commit/2b73e89d6d2822e86360a6c92c87f539677c119b) [@anthonyfok](https://github.com/anthonyfok)
+3 -1
View File
@@ -26,7 +26,9 @@ func TestInit(t *testing.T) {
var ns *internal.TemplateFuncsNamespace
for _, nsf := range internal.TemplateFuncsNamespaceRegistry {
ns = nsf(&deps.Deps{})
ns = nsf(&deps.Deps{
BuildStartListeners: &deps.Listeners{},
})
if ns.Name == name {
found = true
break
+14 -2
View File
@@ -34,18 +34,30 @@ type partialCache struct {
p map[string]interface{}
}
func (p *partialCache) clear() {
p.Lock()
defer p.Unlock()
p.p = make(map[string]interface{})
}
// New returns a new instance of the templates-namespaced template functions.
func New(deps *deps.Deps) *Namespace {
cache := &partialCache{p: make(map[string]interface{})}
deps.BuildStartListeners.Add(
func() {
cache.clear()
})
return &Namespace{
deps: deps,
cachedPartials: partialCache{p: make(map[string]interface{})},
cachedPartials: cache,
}
}
// Namespace provides template functions for the "templates" namespace.
type Namespace struct {
deps *deps.Deps
cachedPartials partialCache
cachedPartials *partialCache
}
// Include executes the named partial and returns either a string,
+26 -7
View File
@@ -79,19 +79,38 @@ func (ns *Namespace) Get(filename interface{}) (resource.Resource, error) {
// Concat concatenates a slice of Resource objects. These resources must
// (currently) be of the same Media Type.
func (ns *Namespace) Concat(targetPathIn interface{}, r []interface{}) (resource.Resource, error) {
func (ns *Namespace) Concat(targetPathIn interface{}, r interface{}) (resource.Resource, error) {
targetPath, err := cast.ToStringE(targetPathIn)
if err != nil {
return nil, err
}
rr := make([]resource.Resource, len(r))
for i := 0; i < len(r); i++ {
rv, ok := r[i].(resource.Resource)
if !ok {
return nil, fmt.Errorf("cannot concat type %T", rv)
var rr resource.Resources
switch v := r.(type) {
// This is what we get from the slice func.
case []interface{}:
rr = make([]resource.Resource, len(v))
for i := 0; i < len(v); i++ {
rv, ok := v[i].(resource.Resource)
if !ok {
return nil, fmt.Errorf("cannot concat type %T", v[i])
}
rr[i] = rv
}
rr[i] = rv
// This is what we get from .Resources.Match etc.
case resource.Resources:
rr = v
default:
// We may support Page collections at one point, but we need to think about ...
// what to acutually concatenate.
return nil, fmt.Errorf("slice %T not supported in concat", r)
}
if len(rr) == 0 {
return nil, errors.New("must provide one or more Resource objects to concat")
}
return ns.bundlerClient.Concat(targetPath, rr)
}
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File
View File