mirror of
https://github.com/gohugoio/hugo.git
synced 2026-09-01 19:22:38 +00:00
Compare commits
45 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 58ac83a98c | |||
| 2b8e8e6d96 | |||
| aef8369865 | |||
| f9e798e8c4 | |||
| ee56efffcb | |||
| 2c4e76e962 | |||
| 9c7d6e475c | |||
| 4482958f96 | |||
| e1ec3bc2b2 | |||
| 1cfa63b9ec | |||
| b9318e4315 | |||
| 5e39eb20a6 | |||
| e556848805 | |||
| 634938908e | |||
| c63db7f1f6 | |||
| 5e2a547cb5 | |||
| ee090c0940 | |||
| edc5c4741c | |||
| 05e358fd33 | |||
| a2e85d9a75 | |||
| 4fba78dd0e | |||
| c011b4667f | |||
| 35348b4b34 | |||
| 34915777c2 | |||
| 0f4a837ed1 | |||
| b395d686e9 | |||
| 97987e5c02 | |||
| 111344113b | |||
| 4855c186d8 | |||
| 0c3d2b67e0 | |||
| 6f07ec7e9e | |||
| 4318dc72f8 | |||
| acdc27a32d | |||
| 3acde9ae04 | |||
| 473b6610d5 | |||
| 0bce97703c | |||
| b254532b52 | |||
| 05a2289292 | |||
| 8e553dcdef | |||
| d4fc70a3b3 | |||
| d905abc002 | |||
| 8f3946746d | |||
| b01b2564ee | |||
| 9fa5ebe2c4 | |||
| efaed306b1 |
+27
-9
@@ -376,17 +376,36 @@ func (f *fileServer) createEndpoint(i int) (*http.ServeMux, string, string, erro
|
||||
}
|
||||
|
||||
if redirect := f.c.serverConfig.MatchRedirect(requestURI); !redirect.IsZero() {
|
||||
doRedirect := true
|
||||
// This matches Netlify's behaviour and is needed for SPA behaviour.
|
||||
// See https://docs.netlify.com/routing/redirects/rewrites-proxies/
|
||||
if redirect.Status == 200 {
|
||||
if r2 := f.rewriteRequest(r, strings.TrimPrefix(redirect.To, u.Path)); r2 != nil {
|
||||
requestURI = redirect.To
|
||||
r = r2
|
||||
if !redirect.Force {
|
||||
path := filepath.Clean(strings.TrimPrefix(requestURI, u.Path))
|
||||
fi, err := f.c.hugo().BaseFs.PublishFs.Stat(path)
|
||||
if err == nil {
|
||||
if fi.IsDir() {
|
||||
// There will be overlapping directories, so we
|
||||
// need to check for a file.
|
||||
_, err = f.c.hugo().BaseFs.PublishFs.Stat(filepath.Join(path, "index.html"))
|
||||
doRedirect = err != nil
|
||||
} else {
|
||||
doRedirect = false
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if doRedirect {
|
||||
if redirect.Status == 200 {
|
||||
if r2 := f.rewriteRequest(r, strings.TrimPrefix(redirect.To, u.Path)); r2 != nil {
|
||||
requestURI = redirect.To
|
||||
r = r2
|
||||
}
|
||||
} else {
|
||||
w.Header().Set("Content-Type", "")
|
||||
http.Redirect(w, r, redirect.To, redirect.Status)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
w.Header().Set("Content-Type", "")
|
||||
http.Redirect(w, r, redirect.To, redirect.Status)
|
||||
return
|
||||
}
|
||||
|
||||
}
|
||||
@@ -416,7 +435,6 @@ func (f *fileServer) createEndpoint(i int) (*http.ServeMux, string, string, erro
|
||||
|
||||
fileserver := decorate(http.FileServer(fs))
|
||||
mu := http.NewServeMux()
|
||||
|
||||
if u.Path == "" || u.Path == "/" {
|
||||
mu.Handle("/", fileserver)
|
||||
} else {
|
||||
|
||||
@@ -22,6 +22,42 @@ import (
|
||||
"github.com/gohugoio/hugo/common/types"
|
||||
)
|
||||
|
||||
// TODO(bep) replace the private versions in /tpl with these.
|
||||
// IsInt returns whether the given kind is a number.
|
||||
func IsNumber(kind reflect.Kind) bool {
|
||||
return IsInt(kind) || IsUint(kind) || IsFloat(kind)
|
||||
}
|
||||
|
||||
// IsInt returns whether the given kind is an int.
|
||||
func IsInt(kind reflect.Kind) bool {
|
||||
switch kind {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// IsUint returns whether the given kind is an uint.
|
||||
func IsUint(kind reflect.Kind) bool {
|
||||
switch kind {
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// IsFloat returns whether the given kind is a float.
|
||||
func IsFloat(kind reflect.Kind) bool {
|
||||
switch kind {
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// IsTruthful returns whether in represents a truthful value.
|
||||
// See IsTruthfulValue
|
||||
func IsTruthful(in interface{}) bool {
|
||||
|
||||
@@ -16,7 +16,7 @@ package hugo
|
||||
// CurrentVersion represents the current build version.
|
||||
// This should be the only one.
|
||||
var CurrentVersion = Version{
|
||||
Number: 0.75,
|
||||
Number: 0.76,
|
||||
PatchLevel: 1,
|
||||
Suffix: "",
|
||||
}
|
||||
|
||||
@@ -184,6 +184,7 @@ type Redirect struct {
|
||||
From string
|
||||
To string
|
||||
Status int
|
||||
Force bool
|
||||
}
|
||||
|
||||
func (r Redirect) IsZero() bool {
|
||||
@@ -206,7 +207,7 @@ func DecodeServer(cfg Provider) (*Server, error) {
|
||||
// There are some tricky infinite loop situations when dealing
|
||||
// when the target does not have a trailing slash.
|
||||
// This can certainly be handled better, but not time for that now.
|
||||
return nil, errors.Errorf("unspported redirect to value %q in server config; currently this must be either a remote destination or a local folder, e.g. \"/blog/\" or \"/blog/index.html\"", redir.To)
|
||||
return nil, errors.Errorf("unsupported redirect to value %q in server config; currently this must be either a remote destination or a local folder, e.g. \"/blog/\" or \"/blog/index.html\"", redir.To)
|
||||
}
|
||||
s.Redirects[i] = redir
|
||||
}
|
||||
|
||||
@@ -80,6 +80,10 @@ type Twitter struct {
|
||||
type Vimeo struct {
|
||||
Service `mapstructure:",squash"`
|
||||
|
||||
// When set to true, the Vimeo player will be blocked from tracking any session data,
|
||||
// including all cookies and stats.
|
||||
EnableDNT bool
|
||||
|
||||
// If simple mode is enabled, only a thumbnail is fetched from i.vimeocdn.com and
|
||||
// shown with a play button overlaid. If a user clicks the button, he/she will
|
||||
// be taken to the video page on vimeo.com in a new browser tab.
|
||||
|
||||
@@ -45,6 +45,7 @@ enableDNT = true
|
||||
simple = true
|
||||
[privacy.vimeo]
|
||||
disable = true
|
||||
enableDNT = true
|
||||
simple = true
|
||||
[privacy.youtube]
|
||||
disable = true
|
||||
@@ -63,7 +64,7 @@ simple = true
|
||||
pc.GoogleAnalytics.RespectDoNotTrack, pc.GoogleAnalytics.AnonymizeIP,
|
||||
pc.GoogleAnalytics.UseSessionStorage, pc.Instagram.Disable,
|
||||
pc.Instagram.Simple, pc.Twitter.Disable, pc.Twitter.EnableDNT,
|
||||
pc.Twitter.Simple, pc.Vimeo.Disable, pc.Vimeo.Simple,
|
||||
pc.Twitter.Simple, pc.Vimeo.Disable, pc.Vimeo.EnableDNT, pc.Vimeo.Simple,
|
||||
pc.YouTube.PrivacyEnhanced, pc.YouTube.Disable,
|
||||
}
|
||||
|
||||
|
||||
Vendored
+1
-1
@@ -66,7 +66,7 @@ type Deps struct {
|
||||
FileCaches filecache.Caches
|
||||
|
||||
// The translation func to use
|
||||
Translate func(translationID string, args ...interface{}) string `json:"-"`
|
||||
Translate func(translationID string, templateData interface{}) string `json:"-"`
|
||||
|
||||
// The language in use. TODO(bep) consolidate with site
|
||||
Language *langs.Language
|
||||
|
||||
@@ -51,6 +51,7 @@ enableDNT = false
|
||||
simple = false
|
||||
[privacy.vimeo]
|
||||
disable = false
|
||||
enableDNT = false
|
||||
simple = false
|
||||
[privacy.youtube]
|
||||
disable = false
|
||||
@@ -128,6 +129,9 @@ privacyEnhanced
|
||||
|
||||
### Vimeo
|
||||
|
||||
enableDNT
|
||||
: Enabling this for the vimeo shortcode, the Vimeo player will be blocked from tracking any session data, including all cookies and stats.
|
||||
|
||||
simple
|
||||
: If simple mode is enabled, the video thumbnail is fetched from Vimeo's servers and it is overlayed with a play button. If the user clicks to play the video, it will open in a new tab directly on Vimeo's website.
|
||||
|
||||
|
||||
@@ -20,13 +20,24 @@ They are stored in a reserved Front Matter object named `_build` with the follow
|
||||
|
||||
```yaml
|
||||
_build:
|
||||
render: true
|
||||
render: always
|
||||
list: always
|
||||
publishResources: true
|
||||
```
|
||||
|
||||
#### render
|
||||
If true, the page will be treated as a published page, holding its dedicated output files (`index.html`, etc...) and permalink.
|
||||
If `always`, the page will be treated as a published page, holding its dedicated output files (`index.html`, etc...) and permalink.
|
||||
|
||||
{{< new-in "0.76.0" >}} We extended this property from a boolean to an enum in Hugo 0.76.0. Valid values are:
|
||||
|
||||
never
|
||||
: The page will not be included in any page collection.
|
||||
|
||||
always (default)
|
||||
: The page will be rendered to disk and get a `RelPermalink` etc.
|
||||
|
||||
link
|
||||
: The page will be not be rendered to disk, but will get a `RelPermalink`.
|
||||
|
||||
#### list
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ The `markup identifier` is fetched from either the `markup` variable in front ma
|
||||
|
||||
## External Helpers
|
||||
|
||||
Some of the formats in the table above needs external helpers installed on your PC. For example, for AsciiDoc files,
|
||||
Some of the formats in the table above need external helpers installed on your PC. For example, for AsciiDoc files,
|
||||
Hugo will try to call the `asciidoctor` command. This means that you will have to install the associated
|
||||
tool on your machine to be able to use these formats.
|
||||
|
||||
@@ -69,33 +69,48 @@ The Asciidoctor community offers a wide set of tools for the AsciiDoc format tha
|
||||
[See the Asciidoctor docs for installation instructions](https://asciidoctor.org/docs/install-toolchain/). Make sure that also all
|
||||
optional extensions like `asciidoctor-diagram` or `asciidoctor-html5s` are installed if required.
|
||||
|
||||
Asciidoctor parameters can be customized in Hugo:
|
||||
{{% note %}}
|
||||
External `asciidoctor` command requires Hugo rendering to _disk_ to a specific destination directory. It is required to run Hugo with the command option `--destination`.
|
||||
{{% /note %}}
|
||||
|
||||
Parameter | Default | Comment
|
||||
--- | --- | ---
|
||||
backend | `html5` | Don't change this unless you know what you are doing.
|
||||
doctype | `article` | Currently supported Document type is `article`.
|
||||
extensions | | Possible extensions are `asciidoctor-html5s`, `asciidoctor-bibtex`, `asciidoctor-diagram`, `asciidoctor-interdoc-reftext`, `asciidoctor-katex`, `asciidoctor-latex`, `asciidoctor-mathematical`, `asciidoctor-question`, `asciidoctor-rouge`.
|
||||
attributes | | Variables to be referenced in your `adoc` file. This is a list of variable name/value maps. See [Asciidoctor#attributes](https://asciidoctor.org/docs/asciidoc-syntax-quick-reference/#attributes-and-substitutions).
|
||||
noheaderorfooter | true | Output an embeddable document, which excludes the header, the footer, and everything outside the body of the document. Don't change this unless you know what you are doing.
|
||||
safemode | `unsafe` | Safe mode level `unsafe`, `safe`, `server` or `secure`. Don't change this unless you know what you are doing.
|
||||
sectionnumbers | `false` | Auto-number section titles.
|
||||
verbose | `false` | Verbosely print processing information and configuration file checks to stderr.
|
||||
trace | `false` | Include backtrace information on errors.
|
||||
failurelevel | `fatal` | The minimum logging level that triggers a non-zero exit code (failure).
|
||||
workingfoldercurrent | `false` | Set the working folder to the rendered `adoc` file, so [include](https://asciidoctor.org/docs/asciidoc-syntax-quick-reference/#include-files) will work with relative paths. This setting uses the `asciidoctor` cli parameter `--base-dir` and attribute `outdir=`. For rendering [asciidoctor-diagram](https://asciidoctor.org/docs/asciidoctor-diagram/) `workingfoldercurrent` must be set to `true`.
|
||||
Some [Asciidoctor](https://asciidoctor.org/man/asciidoctor/) parameters can be customized in Hugo:
|
||||
|
||||
Parameter | Comment
|
||||
--- | ---
|
||||
backend | Don't change this unless you know what you are doing.
|
||||
doctype | Currently, the only document type supported in Hugo is `article`.
|
||||
extensions | Possible extensions are `asciidoctor-html5s`, `asciidoctor-bibtex`, `asciidoctor-diagram`, `asciidoctor-interdoc-reftext`, `asciidoctor-katex`, `asciidoctor-latex`, `asciidoctor-mathematical`, `asciidoctor-question`, `asciidoctor-rouge`.
|
||||
attributes | Variables to be referenced in your AsciiDoc file. This is a list of variable name/value maps. See [Asciidoctor's attributes](https://asciidoctor.org/docs/asciidoc-syntax-quick-reference/#attributes-and-substitutions).
|
||||
noHeaderOrFooter | Output an embeddable document, which excludes the header, the footer, and everything outside the body of the document. Don't change this unless you know what you are doing.
|
||||
safeMode | Safe mode level `unsafe`, `safe`, `server` or `secure`. Don't change this unless you know what you are doing.
|
||||
sectionNumbers | Auto-number section titles.
|
||||
verbose | Verbosely print processing information and configuration file checks to stderr.
|
||||
trace | Include backtrace information on errors.
|
||||
failureLevel | The minimum logging level that triggers a non-zero exit code (failure).
|
||||
|
||||
Hugo provides additional settings that don't map directly to Asciidoctor's CLI options:
|
||||
|
||||
workingFolderCurrent
|
||||
: Sets the working directory to be the same as that of the AsciiDoc file being processed, so that [include](https://asciidoctor.org/docs/asciidoc-syntax-quick-reference/#include-files) will work with relative paths. This setting uses the `asciidoctor` cli parameter `--base-dir` and attribute `outdir=`. For rendering diagrams with [asciidoctor-diagram](https://asciidoctor.org/docs/asciidoctor-diagram/), `workingFolderCurrent` must be set to `true`.
|
||||
|
||||
preserveTOC
|
||||
: By default, Hugo removes the table of contents generated by Asciidoctor and provides it through the built-in variable [`.TableOfContents`](/content-management/toc/) to enable further customization and better integration with the various Hugo themes. This option can be set to `true` to preserve Asciidoctor's TOC in the generated page.
|
||||
|
||||
Below are all the AsciiDoc related settings in Hugo with their default values:
|
||||
|
||||
{{< code-toggle config="markup.asciidocExt" />}}
|
||||
|
||||
Example of how to set extensions and attributes:
|
||||
|
||||
```
|
||||
[markup.asciidocext]
|
||||
[markup.asciidocExt]
|
||||
extensions = ["asciidoctor-html5s", "asciidoctor-diagram"]
|
||||
workingFolderCurrent = true
|
||||
[markup.asciidocext.attributes]
|
||||
[markup.asciidocExt.attributes]
|
||||
my-base-url = "https://example.com/"
|
||||
my-attribute-name = "my value"
|
||||
```
|
||||
|
||||
Important: External `asciidoctor` requires Hugo rendering to _disk_ to a specific destination folder. It is required to run Hugo with the command option `--destination`!
|
||||
|
||||
In a complex Asciidoctor environment it is sometimes helpful to debug the exact call to your external helper with all
|
||||
parameters. Run Hugo with `-v`. You will get an output like
|
||||
|
||||
|
||||
@@ -159,6 +159,39 @@ show_comments: false
|
||||
|
||||
Any node or section can pass down to descendents a set of Front Matter values as long as defined underneath the reserved `cascade` Front Matter key.
|
||||
|
||||
### Target Specific Pages
|
||||
|
||||
{{< new-in "0.76.0" >}}
|
||||
|
||||
Since Hugo 0.76 the `cascade` block can be a slice with a optional `_target` keyword, allowing for multiple `cascade` values targeting different page sets.
|
||||
|
||||
{{< code-toggle copy="false" >}}
|
||||
title ="Blog"
|
||||
[[cascade]]
|
||||
background = "yosemite.jpg"
|
||||
[cascade._target]
|
||||
path="/blog/**"
|
||||
lang="en"
|
||||
kind="page"
|
||||
[[cascade]]
|
||||
background = "goldenbridge.jpg"
|
||||
[cascade._target]
|
||||
kind="section"
|
||||
{{</ code-toggle >}}
|
||||
|
||||
Keywords available for `_target`:
|
||||
|
||||
path
|
||||
: A [Glob](https://github.com/gobwas/glob) pattern matching the content path below /content. Expects Unix-styled slashes. Note that this is the virtual path, so it starts at the mount root.
|
||||
|
||||
kind
|
||||
: A Glob pattern matching the Page's Kind(s), e.g. "{home,section}".
|
||||
|
||||
lang
|
||||
: A Glob pattern matching the Page's language, e.g. "{en,sv}".
|
||||
|
||||
Any of the above can be omitted.
|
||||
|
||||
### Example
|
||||
|
||||
In `content/blog/_index.md`
|
||||
@@ -174,6 +207,8 @@ With the above example the Blog section page and its descendents will return `im
|
||||
- Said descendent has its own `banner` value set
|
||||
- Or a closer ancestor node has its own `cascade.banner` value set.
|
||||
|
||||
|
||||
|
||||
## Order Content Through Front Matter
|
||||
|
||||
You can assign content-specific `weight` in the front matter of your content. These values are especially useful for [ordering][ordering] in list views. You can use `weight` for ordering of content and the convention of [`<TAXONOMY>_weight`][taxweight] for ordering content within a taxonomy. See [Ordering and Grouping Hugo Lists][lists] to see how `weight` can be used to organize your content in list views.
|
||||
|
||||
@@ -135,10 +135,6 @@ A leaf bundle can be made headless by adding below in the Front Matter
|
||||
headless = true
|
||||
```
|
||||
|
||||
{{% note %}}
|
||||
Only leaf bundles can be made headless.
|
||||
{{% /note %}}
|
||||
|
||||
There are many use cases of such headless page bundles:
|
||||
|
||||
- Shared media galleries
|
||||
|
||||
@@ -96,14 +96,13 @@ With the preceding example, even pages with > 400 words *and* `toc` not set to `
|
||||
|
||||
Hugo supports table of contents with AsciiDoc content format.
|
||||
|
||||
In the header of your content file, specify the AsciiDoc TOC directives, by using the macro or auto style:
|
||||
In the header of your content file, specify the AsciiDoc TOC directives necessary to ensure that the table of contents is generated. Hugo will use the generated TOC to populate the page variable `.TableOfContents` in the same way as described for Markdown. See example below:
|
||||
|
||||
```asciidoc
|
||||
// <!-- Your front matter up here -->
|
||||
:toc: macro
|
||||
:toc:
|
||||
// Set toclevels to be at least your hugo [markup.tableOfContents.endLevel] config key
|
||||
:toclevels: 4
|
||||
toc::[]
|
||||
|
||||
== Introduction
|
||||
|
||||
|
||||
@@ -30,6 +30,8 @@ This is the default configuration:
|
||||
|
||||
{{< code-toggle config="markup.goldmark" />}}
|
||||
|
||||
For details on the extensions, refer to [this section](https://github.com/yuin/goldmark/#built-in-extensions) of the Goldmark documentation
|
||||
|
||||
Some settings explained:
|
||||
|
||||
unsafe
|
||||
|
||||
@@ -67,7 +67,7 @@ In addition to using a single site config file, one can use the `configDir` dire
|
||||
|
||||
Considering the structure above, when running `hugo --environment staging`, Hugo will use every settings from `config/_default` and merge `staging`'s on top of those.
|
||||
{{% note %}}
|
||||
Default environments are __development__ with `hugo serve` and __production__ with `hugo`.
|
||||
Default environments are __development__ with `hugo server` and __production__ with `hugo`.
|
||||
{{%/ note %}}
|
||||
## All Configuration Settings
|
||||
|
||||
@@ -360,10 +360,10 @@ Note that a `status` code of 200 will trigger a [URL rewrite](https://docs.netli
|
||||
from = "/myspa/**"
|
||||
to = "/myspa/"
|
||||
status = 200
|
||||
force = false
|
||||
{{< /code-toggle >}}
|
||||
|
||||
|
||||
|
||||
{{< new-in "0.76.0" >}} Setting `force=true` will make a redirect even if there is existing content in the path. Note that before Hugo 0.76 `force` was the default behaviour, but this is inline with how Netlify does it.
|
||||
|
||||
## Configure Title Case
|
||||
|
||||
|
||||
@@ -88,7 +88,7 @@ ignoreConfig
|
||||
: If enabled, any module configuration file, e.g. `config.toml`, will not be loaded. Note that this will also stop the loading of any transitive module dependencies.
|
||||
|
||||
disable
|
||||
: Set to `true` to disable the module off while keeping any version info in the `go.*` files.
|
||||
: Set to `true` to disable the module while keeping any version info in the `go.*` files.
|
||||
|
||||
{{< gomodules-info >}}
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ The easiest way to use a Module for a theme is to import it in the config.
|
||||
```toml
|
||||
[module]
|
||||
[[module.imports]]
|
||||
path = "github.com/spf13/hyde/"
|
||||
path = "github.com/spf13/hyde"
|
||||
```
|
||||
|
||||
## Update Modules
|
||||
|
||||
@@ -38,6 +38,8 @@ externals [slice]
|
||||
{{ $externals := slice "react" "react-dom" }}
|
||||
```
|
||||
|
||||
> Marking a package as external doesn't imply that the library can be loaded from a CDN. It simply tells Hugo not to expand/include the package in the JS file.
|
||||
|
||||
defines [map]
|
||||
: Allow to define a set of string replacement to be performed when building. Should be a map where each key is to be replaced by its value.
|
||||
|
||||
@@ -66,3 +68,29 @@ Or with options:
|
||||
{{ $built := resources.Get "scripts/main.js" | js.Build $opts }}
|
||||
<script type="text/javascript" src="{{ $built.RelPermalink }}" defer></script>
|
||||
```
|
||||
|
||||
#### Shimming a JS library
|
||||
It's a very common practice to load external libraries using CDN rather than importing all packages in a single JS file, making it bulky. To do the same with Hugo, you'll need to shim the libraries as follows. In this example, `algoliasearch` and `instantsearch.js` will be shimmed.
|
||||
|
||||
Firstly, add the following to your project's `package.json`:
|
||||
```json
|
||||
{
|
||||
"browser": {
|
||||
"algoliasearch/lite": "./public/js/shims/algoliasearch.js",
|
||||
"instantsearch.js/es/lib/main": "./public/js/shims/instantsearch.js"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
What this does is it tells Hugo to look for the listed packages somewhere else. Here we're telling Hugo to look for `algoliasearch/lite` and `instantsearch.js/es/lib/main` in the project's `public/js/shims` folder.
|
||||
|
||||
Now we'll need to create the shim JS files which export the global JS variables `module.exports = window.something`. You can create a separate shim JS file in your `assets` directory, and redirect the import paths there if you wish, but a much cleaner way is to create these files on the go, by having the following before your JS is built.
|
||||
|
||||
```go-html-template
|
||||
{{ $a := "module.exports = window.algoliasearch" | resources.FromString "js/shims/algoliasearch.js" }}
|
||||
{{ $i := "module.exports = window.instantsearch" | resources.FromString "js/shims/instantsearch.js" }}
|
||||
|
||||
{{/* Call RelPermalink unnecessarily to generate JS files */}}
|
||||
{{ $placebo := slice $a.RelPermalink $i.RelPermalink }}
|
||||
```
|
||||
That's it! You should now have a browser-friendly JS which can use external JS libraries.
|
||||
|
||||
@@ -27,7 +27,7 @@ The resource will be processed using the project's or theme's own `postcss.confi
|
||||
```
|
||||
|
||||
{{% note %}}
|
||||
Hugo Pipe's PostCSS requires the `postcss-cli` JavaScript package to be installed in the environment (`npm install -g postcss-cli`) along with any PostCSS plugin(s) used (e.g., `npm install -g autoprefixer`).
|
||||
Hugo Pipe's PostCSS requires the `postcss-cli` JavaScript package to be installed in the environment (`npm install -g postcss postcss-cli`) along with any PostCSS plugin(s) used (e.g., `npm install -g autoprefixer`).
|
||||
|
||||
If you are using the Hugo Snap package, PostCSS and plugin(s) need to be installed locally within your Hugo site directory, e.g., `npm install postcss-cli` without the `-g` flag.
|
||||
{{% /note %}}
|
||||
@@ -78,4 +78,4 @@ module.exports = {
|
||||
: []
|
||||
]
|
||||
}
|
||||
```
|
||||
```
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 122 KiB |
@@ -1,16 +1,15 @@
|
||||
|
||||
---
|
||||
date: 2020-09-14
|
||||
title: "0.75.0"
|
||||
description: "0.75.0"
|
||||
title: "NPM Pack"
|
||||
description: "Hugo 0.75 comes with a new \"hugo mod npm pack\" command, several improvements re. Hugo Modules and the Node tools, and more."
|
||||
categories: ["Releases"]
|
||||
---
|
||||
|
||||
Hugo `0.75.0` brings several improvements to Hugo Modules, a new CLI command to bridge the JavaScript dependencies into Hugo, a refresh of the versions of the most important upstream dependencies, and more.
|
||||
Hugo `0.75.0` brings several improvements to Hugo Modules, a new CLI command to bridge the JavaScript dependencies into Hugo, a refresh of the versions of the most important upstream dependencies, and more. There are also some good bug fixes in this release. One notable one is covered by [this commit](https://github.com/gohugoio/hugo/commit/4055c121847847d8bd6b95a928185daee065091b) -- which covers a "stale content scenario in server" when you include content or page data via `GetPage` from a shortcode.
|
||||
|
||||
## NPM Pack
|
||||
|
||||
|
||||
The new CLI command is called `hugo mod npm pack`. We have marked it as experimental. It works great, go ahead and use it, but we need to test this out in real projects to get a feel of it; it is likely that it will change/improve in the upcoming versions of Hugo. The command creates a consolidated `package.json` from the project and all of its [theme components](https://gohugo.io/hugo-modules/theme-components/). On version conflicts, the version closest to the project is selected. We may revise that strategy in the future ([minimal version selection](https://about.sourcegraph.com/blog/the-pain-that-minimal-version-selection-solves/) maybe?), but this should give both control and the least amount of surprise for the site owner.
|
||||
|
||||
So, why did we do this? JavaScript is often a background actor in a Hugo project, and it doesn't make sense to publish it to a NPM registry. The JS dependencies are mostly build tools (PostCSS, TailwindCSS, Babel), `devDependencies`. This has been working fine as long as you kept the JS config files (including `package.json`) in the project, adding duplication/work when using ready-to-use theme components. These tools work best when you have everything below a single file tree, which is very much different to how [Hugo Modules](https://gohugo.io/hugo-modules/) work. An example of a module with TailwindCSS:
|
||||
@@ -44,7 +43,7 @@ const tailwind = require('tailwindcss')(tailwindConfig);
|
||||
|
||||
* We have added a `noVendor` Glob pattern config to the module config [d4611c43](https://github.com/gohugoio/hugo/commit/d4611c4322dabfd8d2520232be578388029867db) [@bep](https://github.com/bep) [#7647](https://github.com/gohugoio/hugo/issues/7647). This allows you to only vendor a subset of your dependencies.
|
||||
* We have added `ignoreImports` option to module imports config [20af9a07](https://github.com/gohugoio/hugo/commit/20af9a078189ce1e92a1d2047c90fba2a4e91827) [@bep](https://github.com/bep) [#7646](https://github.com/gohugoio/hugo/issues/7646), which allows you to import a module and load its config, but not follow its imports.
|
||||
* We have deprecated `--ignoreVendor` in favour of a `--ignoreVendor`, a patch matching Glob pattern [9a1e6d15](https://github.com/gohugoio/hugo/commit/9a1e6d15a31ec667b2ff9cf20e43b1daca61e004) [@bep](https://github.com/bep). A typical use for this would be when you have vendored your dependencies, but want to edit one of them.
|
||||
* We have deprecated `--ignoreVendor` in favour of a `--ignoreVendorPaths`, a patch matching Glob pattern [9a1e6d15](https://github.com/gohugoio/hugo/commit/9a1e6d15a31ec667b2ff9cf20e43b1daca61e004) [@bep](https://github.com/bep). A typical use for this would be when you have vendored your dependencies, but want to edit one of them.
|
||||
|
||||
|
||||
## Statistics
|
||||
@@ -62,6 +61,10 @@ Hugo now has:
|
||||
* 438+ [contributors](https://github.com/gohugoio/hugo/graphs/contributors)
|
||||
* 352+ [themes](http://themes.gohugo.io/)
|
||||
|
||||
## Notes
|
||||
* We now build with Go 1.15, which means that we no longer build release binaries for MacOS 32-bit.
|
||||
* You may now get an error message about "error calling partial: partials that returns a value needs a non-zero argument.". This error situation was not caught earlier, and comes from a limitation in Go's templates: If you use the `return` keyword in a partial, the argument you pass to that partial (e.g. the ".") cannot be zero (and 0 and "" is considered a zero argument).
|
||||
|
||||
## Enhancements
|
||||
|
||||
### Templates
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
|
||||
---
|
||||
date: 2020-10-06
|
||||
title: "0.76.0"
|
||||
description: "0.76.0"
|
||||
categories: ["Releases"]
|
||||
---
|
||||
|
||||
In **Hugo 0.76.0** you can now have a list of [cascade](https://gohugo.io/content-management/front-matter#front-matter-cascade) blocks per page and a new `_target` keyword where you can select which pages to _cascade_ upon using [Glob](https://github.com/gobwas/glob) patterns for a `Page`'s `Kind`, `Lang` and/or `Path`:
|
||||
|
||||
```toml
|
||||
title ="Blog"
|
||||
[[cascade]]
|
||||
background = "yosemite.jpg"
|
||||
[cascade._target]
|
||||
path="/blog/**"
|
||||
lang="en"
|
||||
kind="page"
|
||||
[[cascade]]
|
||||
background = "goldenbridge.jpg"
|
||||
[cascade._target]
|
||||
kind="section"
|
||||
```
|
||||
|
||||
Tasks that were earlier hard/borderline impossible to do are now simple. One common example would to apply a different template set to nested sections; you can now apply a custom `Type` to these sections using `path="/blog/*/**"` and similar.
|
||||
|
||||
A related improvement is that the [build option](https://gohugo.io/content-management/build-options/#readout) `render` is now an enum. In addition to turning on/off rendering of a given page you can tell Hugo to not render, but you want to preserve the `.Permalink`, useful for SPA applications.
|
||||
|
||||
This release represents **35 contributions by 8 contributors** to the main Hugo code base.[@dependabot[bot]](https://github.com/apps/dependabot) leads the Hugo development with a significant amount of contributions, but also a big shoutout to [@bep](https://github.com/bep), [@ai](https://github.com/ai), and [@jmooring](https://github.com/jmooring) 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 [@davidsneighbour](https://github.com/davidsneighbour), [@coliff](https://github.com/coliff) and [@kaushalmodi](https://github.com/kaushalmodi) for all the 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 6 contributors**. A special thanks to [@amdw](https://github.com/amdw), [@davidsneighbour](https://github.com/davidsneighbour), [@samrobbins85](https://github.com/samrobbins85), and [@yaythomas](https://github.com/yaythomas) for their work on the documentation site.
|
||||
|
||||
|
||||
Hugo now has:
|
||||
|
||||
* 47025+ [stars](https://github.com/gohugoio/hugo/stargazers)
|
||||
* 438+ [contributors](https://github.com/gohugoio/hugo/graphs/contributors)
|
||||
* 354+ [themes](http://themes.gohugo.io/)
|
||||
|
||||
## Notes
|
||||
|
||||
|
||||
We have added a `force` flag to the [server redirects](https://gohugo.io/getting-started/configuration/#configure-server) configuration, configuring whether to override any existing content in the path or not. This is inline with how [Netlify](https://docs.netlify.com/routing/redirects/#syntax-for-the-netlify-configuration-file) does it.
|
||||
|
||||
This is set to default `false`. If you want the old behaviour you need to add this flag to your configuration:
|
||||
|
||||
```toml
|
||||
[[redirects]]
|
||||
from = "/myspa/**"
|
||||
to = "/myspa/"
|
||||
status = 200
|
||||
force = true
|
||||
```
|
||||
|
||||
## Enhancements
|
||||
|
||||
### Templates
|
||||
|
||||
* Add Do Not Track (dnt) option to Vimeo shortcode [edc5c474](https://github.com/gohugoio/hugo/commit/edc5c4741caaee36ba4d42b5947c195a3e02e6aa) [@joshgerdes](https://github.com/joshgerdes) [#7700](https://github.com/gohugoio/hugo/issues/7700)
|
||||
|
||||
### Other
|
||||
|
||||
* Regen docshelper [b9318e43](https://github.com/gohugoio/hugo/commit/b9318e4315d9112f727140c0950d8836bf26eb87) [@bep](https://github.com/bep)
|
||||
* Make BuildConfig.Render an enum [63493890](https://github.com/gohugoio/hugo/commit/634938908ec8f393b9a05d26b4cfe19ca7abb0d0) [@bep](https://github.com/bep) [#7783](https://github.com/gohugoio/hugo/issues/7783)
|
||||
* Allow cascade to be a slice with a _target discriminator [c63db7f1](https://github.com/gohugoio/hugo/commit/c63db7f1f6774a2d661af1d8197c6fe377e3ad25) [@bep](https://github.com/bep) [#7782](https://github.com/gohugoio/hugo/issues/7782)
|
||||
* Add force flag to server redirects config [5e2a547c](https://github.com/gohugoio/hugo/commit/5e2a547cb594b31ecb0f089b08db2e15c6dc381a) [@bep](https://github.com/bep) [#7778](https://github.com/gohugoio/hugo/issues/7778)
|
||||
* bump github.com/evanw/esbuild from 0.7.8 to 0.7.9 [ee090c09](https://github.com/gohugoio/hugo/commit/ee090c0940cdbf636e3a55a40b41612d92b9c62d) [@dependabot[bot]](https://github.com/apps/dependabot)
|
||||
* bump github.com/tdewolff/minify/v2 from 2.9.5 to 2.9.7 [05e358fd](https://github.com/gohugoio/hugo/commit/05e358fd335bcb5c7bdc2783ab0c17ec42667df6) [@dependabot[bot]](https://github.com/apps/dependabot)
|
||||
* bump github.com/aws/aws-sdk-go from 1.34.34 to 1.35.0 [a2e85d9a](https://github.com/gohugoio/hugo/commit/a2e85d9a75aca59fd720cce6561ff64997858cd2) [@dependabot[bot]](https://github.com/apps/dependabot)
|
||||
* bump github.com/getkin/kin-openapi from 0.22.0 to 0.22.1 [4fba78dd](https://github.com/gohugoio/hugo/commit/4fba78dd0e950742132954a5d24629e4adfa1bb1) [@dependabot[bot]](https://github.com/apps/dependabot)
|
||||
* bump github.com/aws/aws-sdk-go from 1.34.33 to 1.34.34 [c011b466](https://github.com/gohugoio/hugo/commit/c011b4667f3e1e3c6ecea2fe8f251578884c53b6) [@dependabot[bot]](https://github.com/apps/dependabot)
|
||||
* bump github.com/evanw/esbuild from 0.7.7 to 0.7.8 [35348b4b](https://github.com/gohugoio/hugo/commit/35348b4b343600ec24b1eb1a06f4d3c59199df25) [@dependabot[bot]](https://github.com/apps/dependabot)
|
||||
* bump github.com/aws/aws-sdk-go from 1.34.27 to 1.34.33 [34915777](https://github.com/gohugoio/hugo/commit/34915777c2e8bc1457ff90d09cf814d494d9eece) [@dependabot[bot]](https://github.com/apps/dependabot)
|
||||
* bump github.com/evanw/esbuild from 0.7.4 to 0.7.7 [0f4a837e](https://github.com/gohugoio/hugo/commit/0f4a837ed1fd903bb6740b512683528ddb917918) [@dependabot[bot]](https://github.com/apps/dependabot)
|
||||
* bump github.com/tdewolff/minify/v2 from 2.9.4 to 2.9.5 [b395d686](https://github.com/gohugoio/hugo/commit/b395d686e9a77bf4e0d587ee9a3af4ae6e1aee02) [@dependabot[bot]](https://github.com/apps/dependabot)
|
||||
* Upgrade to go-i18n v2 [97987e5c](https://github.com/gohugoio/hugo/commit/97987e5c0254e35668dca7f89e67b79553e617c8) [@bep](https://github.com/bep) [#5242](https://github.com/gohugoio/hugo/issues/5242)
|
||||
* bump github.com/evanw/esbuild from 0.7.2 to 0.7.4 [4855c186](https://github.com/gohugoio/hugo/commit/4855c186d8f05e5e1b0f681b4aa6482a033df241) [@dependabot[bot]](https://github.com/apps/dependabot)
|
||||
* bump github.com/aws/aws-sdk-go from 1.34.26 to 1.34.27 [6f07ec7e](https://github.com/gohugoio/hugo/commit/6f07ec7e9ec5c43f78100aa36b82786ba0260d75) [@dependabot[bot]](https://github.com/apps/dependabot)
|
||||
* bump github.com/alecthomas/chroma from 0.8.0 to 0.8.1 [4318dc72](https://github.com/gohugoio/hugo/commit/4318dc72f8c562b3bc106cd953d9fce58a93455d) [@dependabot[bot]](https://github.com/apps/dependabot)
|
||||
* bump github.com/evanw/esbuild from 0.7.1 to 0.7.2 [acdc27a3](https://github.com/gohugoio/hugo/commit/acdc27a32de83f32557e7a108797ddbebe4eb464) [@dependabot[bot]](https://github.com/apps/dependabot)
|
||||
* Make sure CSS is rebuilt when postcss.config.js or tailwind.config.js changes [3acde9ae](https://github.com/gohugoio/hugo/commit/3acde9ae04fbf4a8c635d404608cb87218a8b803) [@bep](https://github.com/bep) [#7715](https://github.com/gohugoio/hugo/issues/7715)
|
||||
* bump github.com/aws/aws-sdk-go from 1.34.22 to 1.34.26 [0bce9770](https://github.com/gohugoio/hugo/commit/0bce97703c17318b13b95d78ba41f40efb06aea7) [@dependabot[bot]](https://github.com/apps/dependabot)
|
||||
* Update to github.com/tdewolff/minify v2.9.4 [b254532b](https://github.com/gohugoio/hugo/commit/b254532b52785954c98a473a635b9cea016d8565) [@bep](https://github.com/bep)
|
||||
* Bump bundled Node.js from v12.18.3 to v12.18.4 [05a22892](https://github.com/gohugoio/hugo/commit/05a22892921bd4618efe6135ce0d6fe2be545607) [@anthonyfok](https://github.com/anthonyfok)
|
||||
* Add preserveTOC option [8e553dcd](https://github.com/gohugoio/hugo/commit/8e553dcdefe50ab534f1199c006ae7754e14bee5) [@helfper](https://github.com/helfper)
|
||||
* bump github.com/frankban/quicktest from 1.10.2 to 1.11.0 [d4fc70a3](https://github.com/gohugoio/hugo/commit/d4fc70a3b320a55c4f571eed806d5ad5fdf1ef14) [@dependabot[bot]](https://github.com/apps/dependabot)
|
||||
* bump github.com/evanw/esbuild from 0.6.32 to 0.7.1 [d905abc0](https://github.com/gohugoio/hugo/commit/d905abc002aa6fd260e82063ef1edb8876aa76fd) [@dependabot[bot]](https://github.com/apps/dependabot)
|
||||
* bump github.com/rogpeppe/go-internal from 1.5.1 to 1.6.2 [8f394674](https://github.com/gohugoio/hugo/commit/8f3946746dda444f183ba235288c2b39d0d6a943) [@dependabot[bot]](https://github.com/apps/dependabot)
|
||||
* bump github.com/jdkato/prose from 1.1.1 to 1.2.0 [b01b2564](https://github.com/gohugoio/hugo/commit/b01b2564eefe342c9bf9767ffc256ebd04b94c71) [@dependabot[bot]](https://github.com/apps/dependabot)
|
||||
* bump github.com/spf13/afero from 1.2.2 to 1.4.0 [9fa5ebe2](https://github.com/gohugoio/hugo/commit/9fa5ebe2c42fbb37d066ffcd36bad4d08efe879a) [@dependabot[bot]](https://github.com/apps/dependabot)
|
||||
* Preserve the original package.json if it exists [214afe4c](https://github.com/gohugoio/hugo/commit/214afe4c1bb9c37bc6159e659d66ba9a268a2849) [@bep](https://github.com/bep) [#7690](https://github.com/gohugoio/hugo/issues/7690)
|
||||
|
||||
## Fixes
|
||||
|
||||
### Templates
|
||||
|
||||
* Fix grammar in the new 'requires non-zero' error message [cd830bb0](https://github.com/gohugoio/hugo/commit/cd830bb0275fc39240861627ef26e146985b5c86) [@nekr0z](https://github.com/nekr0z)
|
||||
|
||||
### Other
|
||||
|
||||
* Fix writeStats with quote inside quotes [11134411](https://github.com/gohugoio/hugo/commit/111344113bf8c16ae45528d67ff408da15961727) [@bep](https://github.com/bep) [#7746](https://github.com/gohugoio/hugo/issues/7746)
|
||||
* Fix CLI example for PostCSS 8 [0c3d2b67](https://github.com/gohugoio/hugo/commit/0c3d2b67e0af38a4c3935fb04f722a73ec1d3f8b) [@ai](https://github.com/ai)
|
||||
* Fix typo in redirect error message [473b6610](https://github.com/gohugoio/hugo/commit/473b6610d51d4a33ba35917f95b0d97ea78dad2b) [@jmooring](https://github.com/jmooring)
|
||||
* Fix nilpointer for images with no Exif [cd00f7f9](https://github.com/gohugoio/hugo/commit/cd00f7f9661d67951ef16c5198541f09f1c058b4) [@bep](https://github.com/bep) [#7688](https://github.com/gohugoio/hugo/issues/7688)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
|
||||
---
|
||||
date: 2020-10-07
|
||||
title: "Hugo 0.76.1: A couple of Bug Fixes"
|
||||
description: "This version fixes a couple of bugs introduced in 0.76.0."
|
||||
categories: ["Releases"]
|
||||
images:
|
||||
- images/blog/hugo-bug-poster.png
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
This is a bug-fix release with a couple of important fixes.
|
||||
|
||||
* langs/i18n: Fix i18n .Count regression [f9e798e8](https://github.com/gohugoio/hugo/commit/f9e798e8c4234bd60277e3cb10663ba254d4ecb7) [@bep](https://github.com/bep) [#7787](https://github.com/gohugoio/hugo/issues/7787)
|
||||
* Fix typo in 0.76.0 release note [ee56efff](https://github.com/gohugoio/hugo/commit/ee56efffcb3f81120b0d3e0297b4fb5966124354) [@digitalcraftsman](https://github.com/digitalcraftsman)
|
||||
|
||||
|
||||
|
||||
@@ -43,10 +43,16 @@ Setting `Paginate` to a positive value will split the list pages for the homepag
|
||||
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 subset of the pages with the available template functions and ordering options, and pass the slice to `.Paginate`, e.g. `{{ range (.Paginate ( first 50 .Pages.ByTitle )).Pages }}`.
|
||||
2. Select another set of pages with the available template functions and ordering options, and pass the slice to `.Paginate`, e.g.
|
||||
* `{{ range (.Paginate ( first 50 .Pages.ByTitle )).Pages }}` or
|
||||
* `{{ range (.Paginate .RegularPagesRecursive).Pages }}`.
|
||||
|
||||
For a given **Page**, it's one of the options above. The `.Paginator` is static and cannot change once created.
|
||||
|
||||
If you call `.Paginator` or `.Paginate` multiple times on the same page, you should ensure all the calls are identical. Once *either* `.Paginator` or `.Paginate` is called while generating a page, its result is cached, and any subsequent similar call will reuse the cached result. This means that any such calls which do not match the first one will not behave as written.
|
||||
|
||||
(Remember that function arguments are eagerly evaluated, so a call like `$paginator := cond x .Paginator (.Paginate .RegularPagesRecursive)` is an example of what you should *not* do. Use `if`/`else` instead to ensure exactly one evaluation.)
|
||||
|
||||
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 }}`
|
||||
|
||||
@@ -43,7 +43,7 @@ For multilingual sites, we also create a Sitemap index. You can provide a custom
|
||||
|
||||
## Hugo’s sitemap.xml
|
||||
|
||||
This template respects the version 0.9 of the [Sitemap Protocol](https://www.sitemaps.org/protocol.html).
|
||||
This template respects the version 1.0 of the [Sitemap Protocol](https://www.sitemaps.org/protocol.html).
|
||||
|
||||
```xml
|
||||
{{ printf "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\" ?>" | safeHTML }}
|
||||
|
||||
@@ -158,11 +158,11 @@ Hugo uses both `date` and `weight` to order content within taxonomies.
|
||||
|
||||
Each piece of content in Hugo can optionally be assigned a date. It can also be assigned a weight for each taxonomy it is assigned to.
|
||||
|
||||
When iterating over content within taxonomies, the default sort is the same as that used for section and list pages first by weight then by date. This means that if the weights for two pieces of content are the same, then the more recent content will be displayed first.
|
||||
When iterating over content within taxonomies, the default sort is the same as that used for section and list pages: first by weight, then by date. This means that if the weights for two pieces of content are the same, then the more recent content will be displayed first.
|
||||
|
||||
The default weight for any piece of content is 0.
|
||||
The default weight for any piece of content is 0. Zero means "does not have a weight", not "has a weight of numerical value zero".
|
||||
|
||||
Weights of zero are treated specially: if two pages have unequal weights, and one of them is zero, then the zero-weighted page will always appear after the other one, regardless of the other's weight. Zero weights should thus be used with care: for example, if both positive and negative weights are used to extend a sequence in both directions, a zero-weighted page will appear not in the middle of the list, but at the end.
|
||||
Weights of zero are thus treated specially: if two pages have unequal weights, and one of them is zero, then the zero-weighted page will always appear after the other one, regardless of the other's weight. Zero weights should thus be used with care: for example, if both positive and negative weights are used to extend a sequence in both directions, a zero-weighted page will appear not in the middle of the list, but at the end.
|
||||
|
||||
### Assign Weight
|
||||
|
||||
|
||||
@@ -30,5 +30,4 @@ toc: false
|
||||
* **Features:** inline PageDown editor, visual tree view, image upload and digital asset management with Cloudinary, site preview, continuous integration with GitHub, atomic deploy and hosting, Git and Hugo integration, autosave, custom domain, project syncing, theme cloning and management. Developers have complete control over the source code and can manage it with GitHub’s deceptively simple workflow.
|
||||
* [DATOCMS](https://www.datocms.com) DatoCMS is a fully customizable administrative area for your static websites. Use your favorite website generator, let your clients publish new content independently, and the host the site anywhere you like.
|
||||
* [Forestry.io](https://forestry.io/). Forestry is a git-backed CMS for Hugo, Gatsby, Jekyll and VuePress websites with support for GitHub, GitLab, Bitbucket and Azure Devops. Forestry provides a nice user interface to edit and model content for non technical editors. It supports S3, Cloudinary and Netlify Large Media integrations for storing media. Every time an update is made via the CMS, Forestry will commit changes back to your repo and vice-versa.
|
||||
* [Netlify.com](https://www.netlify.com). Netlify builds, deploys, and hosts your static website or app (Hugo, Jekyll, etc). Netlify offers a drag-and-drop interface and automatic deployments from GitHub or Bitbucket.
|
||||
* **Features:** global CDN, atomic deploys, ultra-fast DNS, instant cache invalidation, high availability, automated hosting, Git integration, form submission hooks, authentication providers, and custom domains. Developers have complete control over the source code and can manage it with GitHub or Bitbucket's deceptively simple workflow.
|
||||
|
||||
|
||||
+12
-6
@@ -1535,7 +1535,8 @@
|
||||
"verbose": false,
|
||||
"trace": false,
|
||||
"failureLevel": "fatal",
|
||||
"workingFolderCurrent": false
|
||||
"workingFolderCurrent": false,
|
||||
"preserveTOC": false
|
||||
}
|
||||
},
|
||||
"minify": {
|
||||
@@ -1556,13 +1557,18 @@
|
||||
"keepWhitespace": false
|
||||
},
|
||||
"css": {
|
||||
"decimals": -1,
|
||||
"keepCSS2": true
|
||||
"keepCSS2": true,
|
||||
"precision": 0
|
||||
},
|
||||
"js": {
|
||||
"precision": 0,
|
||||
"keepVarNames": false
|
||||
},
|
||||
"json": {
|
||||
"precision": 0
|
||||
},
|
||||
"js": {},
|
||||
"json": {},
|
||||
"svg": {
|
||||
"decimals": -1
|
||||
"precision": 0
|
||||
},
|
||||
"xml": {
|
||||
"keepWhitespace": false
|
||||
|
||||
+4
-4
@@ -3,7 +3,7 @@ publish = "public"
|
||||
command = "hugo --gc --minify"
|
||||
|
||||
[context.production.environment]
|
||||
HUGO_VERSION = "0.74.3"
|
||||
HUGO_VERSION = "0.75.1"
|
||||
HUGO_ENV = "production"
|
||||
HUGO_ENABLEGITINFO = "true"
|
||||
|
||||
@@ -11,20 +11,20 @@ HUGO_ENABLEGITINFO = "true"
|
||||
command = "hugo --gc --minify --enableGitInfo"
|
||||
|
||||
[context.split1.environment]
|
||||
HUGO_VERSION = "0.74.3"
|
||||
HUGO_VERSION = "0.75.1"
|
||||
HUGO_ENV = "production"
|
||||
|
||||
[context.deploy-preview]
|
||||
command = "hugo --gc --minify --buildFuture -b $DEPLOY_PRIME_URL"
|
||||
|
||||
[context.deploy-preview.environment]
|
||||
HUGO_VERSION = "0.74.3"
|
||||
HUGO_VERSION = "0.75.1"
|
||||
|
||||
[context.branch-deploy]
|
||||
command = "hugo --gc --minify -b $DEPLOY_PRIME_URL"
|
||||
|
||||
[context.branch-deploy.environment]
|
||||
HUGO_VERSION = "0.74.3"
|
||||
HUGO_VERSION = "0.75.1"
|
||||
|
||||
[context.next.environment]
|
||||
HUGO_ENABLEGITINFO = "true"
|
||||
|
||||
BIN
Binary file not shown.
|
After Width: | Height: | Size: 39 KiB |
BIN
Binary file not shown.
|
After Width: | Height: | Size: 68 KiB |
@@ -5,27 +5,27 @@ require (
|
||||
github.com/BurntSushi/toml v0.3.1
|
||||
github.com/PuerkitoBio/purell v1.1.1
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
|
||||
github.com/alecthomas/chroma v0.8.0
|
||||
github.com/alecthomas/chroma v0.8.1
|
||||
github.com/alecthomas/repr v0.0.0-20181024024818-d37bc2a10ba1 // indirect
|
||||
github.com/armon/go-radix v1.0.0
|
||||
github.com/aws/aws-sdk-go v1.34.22
|
||||
github.com/aws/aws-sdk-go v1.35.0
|
||||
github.com/bep/debounce v1.2.0
|
||||
github.com/bep/gitmap v1.1.2
|
||||
github.com/bep/golibsass v0.7.0
|
||||
github.com/bep/tmc v0.5.1
|
||||
github.com/disintegration/gift v1.2.1
|
||||
github.com/dustin/go-humanize v1.0.0
|
||||
github.com/evanw/esbuild v0.6.32
|
||||
github.com/evanw/esbuild v0.7.9
|
||||
github.com/fortytw2/leaktest v1.3.0
|
||||
github.com/frankban/quicktest v1.10.2
|
||||
github.com/frankban/quicktest v1.11.0
|
||||
github.com/fsnotify/fsnotify v1.4.9
|
||||
github.com/getkin/kin-openapi v0.22.0
|
||||
github.com/getkin/kin-openapi v0.22.1
|
||||
github.com/ghodss/yaml v1.0.0
|
||||
github.com/gobwas/glob v0.2.3
|
||||
github.com/gohugoio/testmodBuilder/mods v0.0.0-20190520184928-c56af20f2e95
|
||||
github.com/google/go-cmp v0.5.2
|
||||
github.com/gorilla/websocket v1.4.2
|
||||
github.com/jdkato/prose v1.1.1
|
||||
github.com/jdkato/prose v1.2.0
|
||||
github.com/kyokomi/emoji v2.2.4+incompatible
|
||||
github.com/magefile/mage v1.10.0
|
||||
github.com/markbates/inflect v1.0.4
|
||||
@@ -35,23 +35,23 @@ require (
|
||||
github.com/mitchellh/mapstructure v1.3.3
|
||||
github.com/muesli/smartcrop v0.3.0
|
||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect
|
||||
github.com/nicksnyder/go-i18n v1.10.1
|
||||
github.com/nicksnyder/go-i18n/v2 v2.1.1
|
||||
github.com/niklasfasching/go-org v1.3.2
|
||||
github.com/olekukonko/tablewriter v0.0.4
|
||||
github.com/pelletier/go-toml v1.6.0 // indirect
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/rogpeppe/go-internal v1.5.1
|
||||
github.com/rogpeppe/go-internal v1.6.2
|
||||
github.com/russross/blackfriday v1.5.3-0.20200218234912-41c5fccfd6f6
|
||||
github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd
|
||||
github.com/sanity-io/litter v1.3.0
|
||||
github.com/spf13/afero v1.2.2
|
||||
github.com/spf13/afero v1.4.0
|
||||
github.com/spf13/cast v1.3.1
|
||||
github.com/spf13/cobra v0.0.7
|
||||
github.com/spf13/fsync v0.9.0
|
||||
github.com/spf13/jwalterweatherman v1.1.0
|
||||
github.com/spf13/pflag v1.0.5
|
||||
github.com/spf13/viper v1.7.1
|
||||
github.com/tdewolff/minify/v2 v2.6.2
|
||||
github.com/tdewolff/minify/v2 v2.9.7
|
||||
github.com/yuin/goldmark v1.2.1
|
||||
github.com/yuin/goldmark-highlighting v0.0.0-20200307114337-60d527fdb691
|
||||
gocloud.dev v0.15.0
|
||||
|
||||
@@ -57,6 +57,8 @@ github.com/alecthomas/assert v0.0.0-20170929043011-405dbfeb8e38/go.mod h1:r7bzyV
|
||||
github.com/alecthomas/chroma v0.7.2-0.20200305040604-4f3623dce67a/go.mod h1:fv5SzZPFJbwp2NXJWpFIX7DZS4HgV1K4ew4Pc2OZD9s=
|
||||
github.com/alecthomas/chroma v0.8.0 h1:HS+HE97sgcqjQGu5uVr8jIE55Mmh5UeQ7kckAhHg2pY=
|
||||
github.com/alecthomas/chroma v0.8.0/go.mod h1:sko8vR34/90zvl5QdcUdvzL3J8NKjAUx9va9jPuFNoM=
|
||||
github.com/alecthomas/chroma v0.8.1 h1:ym20sbvyC6RXz45u4qDglcgr8E313oPROshcuCHqiEE=
|
||||
github.com/alecthomas/chroma v0.8.1/go.mod h1:sko8vR34/90zvl5QdcUdvzL3J8NKjAUx9va9jPuFNoM=
|
||||
github.com/alecthomas/colour v0.0.0-20160524082231-60882d9e2721 h1:JHZL0hZKJ1VENNfmXvHbgYlbUOvpzYzvy2aZU5gXVeo=
|
||||
github.com/alecthomas/colour v0.0.0-20160524082231-60882d9e2721/go.mod h1:QO9JBoKquHd+jz9nshCh40fOfO+JzsoXy8qTHF68zU0=
|
||||
github.com/alecthomas/kong v0.1.17-0.20190424132513-439c674f7ae0/go.mod h1:+inYUSluD+p4L8KdviBSgzcqEjUQOfC5fQDRFuc36lI=
|
||||
@@ -86,6 +88,16 @@ github.com/aws/aws-sdk-go v1.34.21 h1:M97FXuiJgDHwD4mXhrIZ7RJ4xXV6uZVPvIC2qb+HfY
|
||||
github.com/aws/aws-sdk-go v1.34.21/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
|
||||
github.com/aws/aws-sdk-go v1.34.22 h1:7V2sKilVVgHqdjbW+O/xaVWYfnmuLwZdF/+6JuUh6Cw=
|
||||
github.com/aws/aws-sdk-go v1.34.22/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
|
||||
github.com/aws/aws-sdk-go v1.34.26 h1:tw4nsSfGvCDnXt2xPe8NkxIrDui+asAWinMknPLEf80=
|
||||
github.com/aws/aws-sdk-go v1.34.26/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
|
||||
github.com/aws/aws-sdk-go v1.34.27 h1:qBqccUrlz43Zermh0U1O502bHYZsgMlBm+LUVabzBPA=
|
||||
github.com/aws/aws-sdk-go v1.34.27/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
|
||||
github.com/aws/aws-sdk-go v1.34.33 h1:ymkFm0rNPEOlgjyX3ojEd4zqzW6kGICBkqWs7LqgHtU=
|
||||
github.com/aws/aws-sdk-go v1.34.33/go.mod h1:H7NKnBqNVzoTJpGfLrQkkD+ytBA93eiDYi/+8rV9s48=
|
||||
github.com/aws/aws-sdk-go v1.34.34 h1:5dC0ZU0xy25+UavGNEkQ/5MOQwxXDA2YXtjCL1HfYKI=
|
||||
github.com/aws/aws-sdk-go v1.34.34/go.mod h1:H7NKnBqNVzoTJpGfLrQkkD+ytBA93eiDYi/+8rV9s48=
|
||||
github.com/aws/aws-sdk-go v1.35.0 h1:Pxqn1MWNfBCNcX7jrXCCTfsKpg5ms2IMUMmmcGtYJuo=
|
||||
github.com/aws/aws-sdk-go v1.35.0/go.mod h1:H7NKnBqNVzoTJpGfLrQkkD+ytBA93eiDYi/+8rV9s48=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
github.com/bep/debounce v1.2.0 h1:wXds8Kq8qRfwAOpAxHrJDbCXgC5aHSzgQb/0gKsHQqo=
|
||||
@@ -112,6 +124,7 @@ github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3Ee
|
||||
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/daaku/go.zipexe v1.0.0/go.mod h1:z8IiR6TsVLEYKwXAoE/I+8ys/sDkgTzSL0CLnGVd57E=
|
||||
@@ -137,6 +150,18 @@ github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1
|
||||
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
|
||||
github.com/evanw/esbuild v0.6.32 h1:hVuqC+IgEENPWnr0gic01EFgGCmyW8dUPnr78zC7K5k=
|
||||
github.com/evanw/esbuild v0.6.32/go.mod h1:mptxmSXIzBIKKCe4jo9A5SToEd1G+AKZ9JmY85dYRJ0=
|
||||
github.com/evanw/esbuild v0.7.1 h1:bkC9MpDxHPCLESOf3AQzK1QiyaxbnxFa3XLPnyARLSI=
|
||||
github.com/evanw/esbuild v0.7.1/go.mod h1:mptxmSXIzBIKKCe4jo9A5SToEd1G+AKZ9JmY85dYRJ0=
|
||||
github.com/evanw/esbuild v0.7.2 h1:LBY35Gw3fKs7jVpsbQwOmw7pJLDHdpliI1Mc/DqP0Hs=
|
||||
github.com/evanw/esbuild v0.7.2/go.mod h1:mptxmSXIzBIKKCe4jo9A5SToEd1G+AKZ9JmY85dYRJ0=
|
||||
github.com/evanw/esbuild v0.7.4 h1:mLb2tQ9315u23ulh/5Gg8xejOfgqHs2zm7bDNtNnNcM=
|
||||
github.com/evanw/esbuild v0.7.4/go.mod h1:mptxmSXIzBIKKCe4jo9A5SToEd1G+AKZ9JmY85dYRJ0=
|
||||
github.com/evanw/esbuild v0.7.7 h1:l/M5wHuU738LEX8RyGDP7Zkdrw84j3bpCPrJbKX33Ks=
|
||||
github.com/evanw/esbuild v0.7.7/go.mod h1:mptxmSXIzBIKKCe4jo9A5SToEd1G+AKZ9JmY85dYRJ0=
|
||||
github.com/evanw/esbuild v0.7.8 h1:DyCpTDLRAtjqRixfXFslGSsYaoKRQfYi+gwGkzW1FHI=
|
||||
github.com/evanw/esbuild v0.7.8/go.mod h1:mptxmSXIzBIKKCe4jo9A5SToEd1G+AKZ9JmY85dYRJ0=
|
||||
github.com/evanw/esbuild v0.7.9 h1:jXSoYpNpGkOK1VNx3tvd/KnbVbn5ULRYzvkumXaSkxo=
|
||||
github.com/evanw/esbuild v0.7.9/go.mod h1:mptxmSXIzBIKKCe4jo9A5SToEd1G+AKZ9JmY85dYRJ0=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/fortytw2/leaktest v1.2.0 h1:cj6GCiwJDH7l3tMHLjZDo0QqPtrXJiWSI9JgpeQKw+Q=
|
||||
github.com/fortytw2/leaktest v1.2.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
|
||||
@@ -148,6 +173,8 @@ github.com/frankban/quicktest v1.7.2 h1:2QxQoC1TS09S7fhCPsrvqYdvP1H5M1P1ih5ABm3B
|
||||
github.com/frankban/quicktest v1.7.2/go.mod h1:jaStnuzAqU1AJdCO0l53JDCJrVDKcS03DbaAcR7Ks/o=
|
||||
github.com/frankban/quicktest v1.10.2 h1:19ARM85nVi4xH7xPXuc5eM/udya5ieh7b/Sv+d844Tk=
|
||||
github.com/frankban/quicktest v1.10.2/go.mod h1:K+q6oSqb0W0Ininfk863uOk1lMy69l/P6txr3mVT54s=
|
||||
github.com/frankban/quicktest v1.11.0 h1:Yyrghcw93e1jKo4DTZkRFTTFvBsVhzbblBUPNU1vW6Q=
|
||||
github.com/frankban/quicktest v1.11.0/go.mod h1:K+q6oSqb0W0Ininfk863uOk1lMy69l/P6txr3mVT54s=
|
||||
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
|
||||
@@ -156,6 +183,8 @@ github.com/getkin/kin-openapi v0.14.0 h1:hqwQL7kze/adt0wB+0UJR2nJm+gfUHqM0Gu4D8n
|
||||
github.com/getkin/kin-openapi v0.14.0/go.mod h1:WGRs2ZMM1Q8LR1QBEwUxC6RJEfaBcD0s+pcEVXFuAjw=
|
||||
github.com/getkin/kin-openapi v0.22.0 h1:J5IFyKd/5yuB6AZAgwK0CMBKnabWcmkowtsl6bRkz4s=
|
||||
github.com/getkin/kin-openapi v0.22.0/go.mod h1:WGRs2ZMM1Q8LR1QBEwUxC6RJEfaBcD0s+pcEVXFuAjw=
|
||||
github.com/getkin/kin-openapi v0.22.1 h1:ODA1olTp175o//NfHko/uCAAhwUSfm5P4+K52XvTg4w=
|
||||
github.com/getkin/kin-openapi v0.22.1/go.mod h1:WGRs2ZMM1Q8LR1QBEwUxC6RJEfaBcD0s+pcEVXFuAjw=
|
||||
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||
@@ -258,12 +287,17 @@ github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NH
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/jdkato/prose v1.1.1 h1:r6CwY09U97IZNgNQEHoeCh2nvg2e8WCOGjPH/b7lowI=
|
||||
github.com/jdkato/prose v1.1.1/go.mod h1:jkF0lkxaX5PFSlk9l4Gh9Y+T57TqUZziWT7uZbW5ADg=
|
||||
github.com/jdkato/prose v1.2.0 h1:t/R3H6xOrVuIgNevWiOSJf1kEoeF2VWlrN6w76Tkzow=
|
||||
github.com/jdkato/prose v1.2.0/go.mod h1:WC4YKHtBdAMgBdmfdqBmEuVbBD0U5c9HQ6l1U8Cq0ts=
|
||||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||
github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM=
|
||||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||
github.com/jmespath/go-jmespath v0.3.0 h1:OS12ieG61fsCg5+qLJ+SsW9NicxNkg3b25OyT2yCeUc=
|
||||
github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik=
|
||||
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
|
||||
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
|
||||
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
|
||||
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
|
||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
@@ -274,6 +308,7 @@ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7V
|
||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
@@ -326,6 +361,7 @@ github.com/mitchellh/mapstructure v1.3.3 h1:SzB1nHZ2Xi+17FP0zVQBHIZqvwRN9408fJO8
|
||||
github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/montanaflynn/stats v0.6.3/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
|
||||
github.com/muesli/smartcrop v0.3.0 h1:JTlSkmxWg/oQ1TcLDoypuirdE8Y/jzNirQeLkxpA6Oc=
|
||||
github.com/muesli/smartcrop v0.3.0/go.mod h1:i2fCI/UorTfgEpPPLWiFBv4pye+YAG78RwcQLUkocpI=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
@@ -333,6 +369,8 @@ github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6
|
||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
|
||||
github.com/nicksnyder/go-i18n v1.10.1 h1:isfg77E/aCD7+0lD/D00ebR2MV5vgeQ276WYyDaCRQc=
|
||||
github.com/nicksnyder/go-i18n v1.10.1/go.mod h1:e4Di5xjP9oTVrC6y3C7C0HoSYXjSbhh/dU0eUV32nB4=
|
||||
github.com/nicksnyder/go-i18n/v2 v2.1.1 h1:ATCOanRDlrfKVB4WHAdJnLEqZtDmKYsweqsOUYflnBU=
|
||||
github.com/nicksnyder/go-i18n/v2 v2.1.1/go.mod h1:d++QJC9ZVf7pa48qrsRWhMJ5pSHIPmS3OLqK1niyLxs=
|
||||
github.com/niklasfasching/go-org v1.3.2 h1:ZKTSd+GdJYkoZl1pBXLR/k7DRiRXnmB96TRiHmHdzwI=
|
||||
github.com/niklasfasching/go-org v1.3.2/go.mod h1:AsLD6X7djzRIz4/RFZu8vwRL0VGjUvGZCCH1Nz0VdrU=
|
||||
github.com/nkovacs/streamquote v0.0.0-20170412213628-49af9bddb229/go.mod h1:0aYXnNPJ8l7uZxf45rWW1a/uME32OF0rhiYGNQ2oF2E=
|
||||
@@ -356,6 +394,7 @@ github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
|
||||
github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
@@ -378,6 +417,8 @@ github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6So
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.5.1 h1:asQ0uD7BN9RU5Im41SEEZTwCi/zAXdMOLS3npYaos2g=
|
||||
github.com/rogpeppe/go-internal v1.5.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||
github.com/rogpeppe/go-internal v1.6.2 h1:aIihoIOHCiLZHxyoNQ+ABL4NKhFTgKLBdMLyEAh98m0=
|
||||
github.com/rogpeppe/go-internal v1.6.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||
github.com/russross/blackfriday v1.5.3-0.20200218234912-41c5fccfd6f6 h1:tlXG832s5pa9x9Gs3Rp2rTvEqjiDEuETUOSfBEiTcns=
|
||||
github.com/russross/blackfriday v1.5.3-0.20200218234912-41c5fccfd6f6/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
||||
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
|
||||
@@ -390,6 +431,7 @@ github.com/sanity-io/litter v1.3.0/go.mod h1:5Z71SvaYy5kcGtyglXOC9rrUi3c1E8CamFW
|
||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||
github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
|
||||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||
github.com/shogo82148/go-shuffle v0.0.0-20180218125048-27e6095f230d/go.mod h1:2htx6lmL0NGLHlO8ZCf+lQBGBHIbEujyywxJArf+2Yc=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
@@ -403,6 +445,8 @@ github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI=
|
||||
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||
github.com/spf13/afero v1.2.2 h1:5jhuqJyZCZf2JRofRvN/nIFgIWNzPa3/Vz8mYylgbWc=
|
||||
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
|
||||
github.com/spf13/afero v1.4.0 h1:jsLTaI1zwYO3vjrzHalkVcIHXTNmdQFepW4OI8H3+x8=
|
||||
github.com/spf13/afero v1.4.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
|
||||
github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8=
|
||||
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng=
|
||||
@@ -432,14 +476,28 @@ github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
|
||||
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
||||
github.com/tdewolff/minify/v2 v2.6.2 h1:Jaod6aSABWmhftvnxvXogxcEoQt6yogfFeZgIQEMPOw=
|
||||
github.com/tdewolff/minify/v2 v2.6.2/go.mod h1:BkDSm8aMMT0ALGmpt7j3Ra7nLUgZL0qhyrAHXwxcy5w=
|
||||
github.com/tdewolff/minify/v2 v2.9.4 h1:sOqgmowmkZWmHZ0AqIFS300VvCCkgDNTw1eWw1tnNCY=
|
||||
github.com/tdewolff/minify/v2 v2.9.4/go.mod h1:4SrPavRSPLpv4U4jqV8jzSjiEuq2BH+BPgxorMkGrhc=
|
||||
github.com/tdewolff/minify/v2 v2.9.5 h1:+fHvqLencVdv14B+zgxQGhetF9qXl/nRTN/1mcyQwpM=
|
||||
github.com/tdewolff/minify/v2 v2.9.5/go.mod h1:jshtBj/uUJH6JX1fuxTLnnHOA1RVJhF5MM+leJzDKb4=
|
||||
github.com/tdewolff/minify/v2 v2.9.7 h1:r8ewdcX8VYUoNj+s9WSy4FtNNNqNPevWOkb/MksAtzQ=
|
||||
github.com/tdewolff/minify/v2 v2.9.7/go.mod h1:AcJ/ggtHex5N/QiafLI8rlIO3qwSlgbPNLi27VZSYz8=
|
||||
github.com/tdewolff/parse/v2 v2.4.2 h1:Bu2Qv6wepkc+Ou7iB/qHjAhEImlAP5vedzlQRUdj3BI=
|
||||
github.com/tdewolff/parse/v2 v2.4.2/go.mod h1:WzaJpRSbwq++EIQHYIRTpbYKNA3gn9it1Ik++q4zyho=
|
||||
github.com/tdewolff/parse/v2 v2.5.2 h1:OIUAejEkj9Oj6N1q18xg7ByYkpQ0xf4nA1aAH5nqxks=
|
||||
github.com/tdewolff/parse/v2 v2.5.2/go.mod h1:WzaJpRSbwq++EIQHYIRTpbYKNA3gn9it1Ik++q4zyho=
|
||||
github.com/tdewolff/parse/v2 v2.5.3 h1:fnPIstKgEfxd3+wwHnH73sAYydsR0o/jYhcQ6c5PkrA=
|
||||
github.com/tdewolff/parse/v2 v2.5.3/go.mod h1:WzaJpRSbwq++EIQHYIRTpbYKNA3gn9it1Ik++q4zyho=
|
||||
github.com/tdewolff/parse/v2 v2.5.4 h1:ggaQ1SVE8wErRrZwUs49I6iQ1zL/tFlb7KtYsk2I8Yk=
|
||||
github.com/tdewolff/parse/v2 v2.5.4/go.mod h1:WzaJpRSbwq++EIQHYIRTpbYKNA3gn9it1Ik++q4zyho=
|
||||
github.com/tdewolff/test v1.0.6 h1:76mzYJQ83Op284kMT+63iCNCI7NEERsIN8dLM+RiKr4=
|
||||
github.com/tdewolff/test v1.0.6/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE=
|
||||
github.com/tidwall/pretty v0.0.0-20190325153808-1166b9ac2b65/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
||||
@@ -448,6 +506,7 @@ github.com/uber-go/atomic v1.3.2/go.mod h1:/Ct5t2lcmbJ4OSe/waGBoaVvVqtO0bmtfVNex
|
||||
github.com/uber/jaeger-client-go v2.15.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk=
|
||||
github.com/uber/jaeger-lib v1.5.0/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U=
|
||||
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
|
||||
github.com/urfave/cli v1.22.4/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
|
||||
github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I=
|
||||
@@ -483,6 +542,7 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
|
||||
golang.org/x/crypto v0.0.0-20190422183909-d864b10871cd/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
@@ -573,6 +633,8 @@ golang.org/x/sys v0.0.0-20200413165638-669c56c373c4 h1:opSr2sbRXk5X5/givKrrKj9HX
|
||||
golang.org/x/sys v0.0.0-20200413165638-669c56c373c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200501145240-bc7a7d42d5c3 h1:5B6i6EAiSYyejWfvc5Rc9BbI3rzIsrrXfAQBWnYfn+w=
|
||||
golang.org/x/sys v0.0.0-20200501145240-bc7a7d42d5c3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200724161237-0e2f3a69832c h1:UIcGWL6/wpCfyGuJnRFJRurA+yj8RrW7Q6x2YMCXt6c=
|
||||
golang.org/x/sys v0.0.0-20200724161237-0e2f3a69832c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2 h1:z99zHgr7hKfrUcX/KsoJk5FJfjTceCKIp96+biqP4To=
|
||||
@@ -662,6 +724,7 @@ gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno=
|
||||
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/ini.v1 v1.51.1 h1:GyboHr4UqMiLUybYjd22ZjQIKEJEpgtLXtuGbR21Oho=
|
||||
gopkg.in/ini.v1 v1.51.1/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/neurosnap/sentences.v1 v1.0.6/go.mod h1:YlK+SN+fLQZj+kY3r8DkGDhDr91+S3JmTb5LSxFRQo0=
|
||||
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
||||
@@ -670,8 +733,10 @@ gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
|
||||
+20
-14
@@ -23,30 +23,36 @@ import (
|
||||
"github.com/gobwas/glob/syntax"
|
||||
)
|
||||
|
||||
type globErr struct {
|
||||
glob glob.Glob
|
||||
err error
|
||||
}
|
||||
|
||||
var (
|
||||
globCache = make(map[string]glob.Glob)
|
||||
globCache = make(map[string]globErr)
|
||||
globMu sync.RWMutex
|
||||
)
|
||||
|
||||
func GetGlob(pattern string) (glob.Glob, error) {
|
||||
var g glob.Glob
|
||||
var eg globErr
|
||||
|
||||
globMu.RLock()
|
||||
g, found := globCache[pattern]
|
||||
var found bool
|
||||
eg, found = globCache[pattern]
|
||||
globMu.RUnlock()
|
||||
if !found {
|
||||
var err error
|
||||
g, err = glob.Compile(strings.ToLower(pattern), '/')
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
globMu.Lock()
|
||||
globCache[pattern] = g
|
||||
globMu.Unlock()
|
||||
if found {
|
||||
return eg.glob, eg.err
|
||||
}
|
||||
|
||||
return g, nil
|
||||
var err error
|
||||
g, err := glob.Compile(strings.ToLower(pattern), '/')
|
||||
eg = globErr{g, err}
|
||||
|
||||
globMu.Lock()
|
||||
globCache[pattern] = eg
|
||||
globMu.Unlock()
|
||||
|
||||
return eg.glob, eg.err
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -73,5 +73,14 @@ func TestGetGlob(t *testing.T) {
|
||||
g, err := GetGlob("**.JSON")
|
||||
c.Assert(err, qt.IsNil)
|
||||
c.Assert(g.Match("data/my.json"), qt.Equals, true)
|
||||
}
|
||||
|
||||
func BenchmarkGetGlob(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, err := GetGlob("**/foo")
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+69
-1
@@ -229,7 +229,7 @@ Banner: post.jpg`,
|
||||
|
||||
counters := &testCounters{}
|
||||
b.Build(BuildCfg{testCounters: counters})
|
||||
// As we only changed the content, not the cascade front matter, make
|
||||
// As we only changed the content, not the cascade front matter,
|
||||
// only the home page is re-rendered.
|
||||
b.Assert(int(counters.contentRenderCounter), qt.Equals, 1)
|
||||
|
||||
@@ -392,3 +392,71 @@ defaultContentLanguageInSubDir = false
|
||||
|
||||
return b
|
||||
}
|
||||
|
||||
func TestCascadeTarget(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
c := qt.New(t)
|
||||
|
||||
newBuilder := func(c *qt.C) *sitesBuilder {
|
||||
b := newTestSitesBuilder(c)
|
||||
|
||||
b.WithTemplates("index.html", `
|
||||
{{ $p1 := site.GetPage "s1/p1" }}
|
||||
{{ $s1 := site.GetPage "s1" }}
|
||||
|
||||
P1|p1:{{ $p1.Params.p1 }}|p2:{{ $p1.Params.p2 }}|
|
||||
S1|p1:{{ $s1.Params.p1 }}|p2:{{ $s1.Params.p2 }}|
|
||||
`)
|
||||
b.WithContent("s1/_index.md", "---\ntitle: s1 section\n---")
|
||||
b.WithContent("s1/p1/index.md", "---\ntitle: p1\n---")
|
||||
b.WithContent("s1/p2/index.md", "---\ntitle: p2\n---")
|
||||
b.WithContent("s2/p1/index.md", "---\ntitle: p1_2\n---")
|
||||
|
||||
return b
|
||||
|
||||
}
|
||||
|
||||
c.Run("slice", func(c *qt.C) {
|
||||
b := newBuilder(c)
|
||||
b.WithContent("_index.md", `+++
|
||||
title = "Home"
|
||||
[[cascade]]
|
||||
p1 = "p1"
|
||||
[[cascade]]
|
||||
p2 = "p2"
|
||||
+++
|
||||
`)
|
||||
|
||||
b.Build(BuildCfg{})
|
||||
|
||||
b.AssertFileContent("public/index.html", "P1|p1:p1|p2:p2")
|
||||
|
||||
})
|
||||
|
||||
c.Run("slice with _target", func(c *qt.C) {
|
||||
b := newBuilder(c)
|
||||
|
||||
b.WithContent("_index.md", `+++
|
||||
title = "Home"
|
||||
[[cascade]]
|
||||
p1 = "p1"
|
||||
[cascade._target]
|
||||
path="**p1**"
|
||||
[[cascade]]
|
||||
p2 = "p2"
|
||||
[cascade._target]
|
||||
kind="section"
|
||||
+++
|
||||
`)
|
||||
|
||||
b.Build(BuildCfg{})
|
||||
|
||||
b.AssertFileContent("public/index.html", `
|
||||
P1|p1:p1|p2:|
|
||||
S1|p1:|p2:p2|
|
||||
`)
|
||||
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
@@ -789,7 +789,7 @@ func (m *pageMaps) withMaps(fn func(pm *pageMap) error) error {
|
||||
|
||||
type pagesMapBucket struct {
|
||||
// Cascading front matter.
|
||||
cascade maps.Params
|
||||
cascade map[page.PageMatcher]maps.Params
|
||||
|
||||
owner *pageState // The branch node
|
||||
|
||||
|
||||
@@ -54,7 +54,15 @@ title: No List
|
||||
_build:
|
||||
render: false
|
||||
---
|
||||
`, "sect/no-publishresources/index.md", `
|
||||
`,
|
||||
"sect/no-render-link.md", `
|
||||
---
|
||||
title: No Render Link
|
||||
_build:
|
||||
render: link
|
||||
---
|
||||
`,
|
||||
"sect/no-publishresources/index.md", `
|
||||
---
|
||||
title: No Publish Resources
|
||||
_build:
|
||||
@@ -303,6 +311,20 @@ title: Headless Local Lists Sub
|
||||
b.Assert(getPageInPagePages(sect, ref), qt.Not(qt.IsNil))
|
||||
})
|
||||
|
||||
c.Run("Build config, no render link", func(c *qt.C) {
|
||||
b := newSitesBuilder(c, disableKind)
|
||||
b.Build(BuildCfg{})
|
||||
ref := "/sect/no-render-link.md"
|
||||
b.Assert(b.CheckExists("public/sect/no-render/index.html"), qt.Equals, false)
|
||||
p := getPage(b, ref)
|
||||
b.Assert(p, qt.Not(qt.IsNil))
|
||||
b.Assert(p.RelPermalink(), qt.Equals, "/blog/sect/no-render-link/")
|
||||
b.Assert(p.OutputFormats(), qt.HasLen, 0)
|
||||
b.Assert(getPageInSitePages(b, ref), qt.Not(qt.IsNil))
|
||||
sect := getPage(b, "/sect")
|
||||
b.Assert(getPageInPagePages(sect, ref), qt.Not(qt.IsNil))
|
||||
})
|
||||
|
||||
c.Run("Build config, no publish resources", func(c *qt.C) {
|
||||
b := newSitesBuilder(c, disableKind)
|
||||
b.Build(BuildCfg{})
|
||||
|
||||
+59
-10
@@ -308,12 +308,22 @@ func (p *pageMeta) Weight() int {
|
||||
|
||||
func (pm *pageMeta) mergeBucketCascades(b1, b2 *pagesMapBucket) {
|
||||
if b1.cascade == nil {
|
||||
b1.cascade = make(map[string]interface{})
|
||||
b1.cascade = make(map[page.PageMatcher]maps.Params)
|
||||
}
|
||||
|
||||
if b2 != nil && b2.cascade != nil {
|
||||
for k, v := range b2.cascade {
|
||||
if _, found := b1.cascade[k]; !found {
|
||||
|
||||
vv, found := b1.cascade[k]
|
||||
if !found {
|
||||
b1.cascade[k] = v
|
||||
} else {
|
||||
// Merge
|
||||
for ck, cv := range v {
|
||||
if _, found := vv[ck]; !found {
|
||||
vv[ck] = cv
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -332,14 +342,44 @@ func (pm *pageMeta) setMetadata(parentBucket *pagesMapBucket, p *pageState, fron
|
||||
if p.bucket != nil {
|
||||
// Check for any cascade define on itself.
|
||||
if cv, found := frontmatter["cascade"]; found {
|
||||
p.bucket.cascade = maps.ToStringMap(cv)
|
||||
switch v := cv.(type) {
|
||||
case []map[string]interface{}:
|
||||
p.bucket.cascade = make(map[page.PageMatcher]maps.Params)
|
||||
|
||||
for _, vv := range v {
|
||||
var m page.PageMatcher
|
||||
if mv, found := vv["_target"]; found {
|
||||
err := page.DecodePageMatcher(mv, &m)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
c, found := p.bucket.cascade[m]
|
||||
if found {
|
||||
// Merge
|
||||
for k, v := range vv {
|
||||
if _, found := c[k]; !found {
|
||||
c[k] = v
|
||||
}
|
||||
}
|
||||
} else {
|
||||
p.bucket.cascade[m] = vv
|
||||
}
|
||||
|
||||
}
|
||||
default:
|
||||
p.bucket.cascade = map[page.PageMatcher]maps.Params{
|
||||
page.PageMatcher{}: maps.ToStringMap(cv),
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
} else {
|
||||
frontmatter = make(map[string]interface{})
|
||||
}
|
||||
|
||||
var cascade map[string]interface{}
|
||||
var cascade map[page.PageMatcher]maps.Params
|
||||
|
||||
if p.bucket != nil {
|
||||
if parentBucket != nil {
|
||||
@@ -351,9 +391,14 @@ func (pm *pageMeta) setMetadata(parentBucket *pagesMapBucket, p *pageState, fron
|
||||
cascade = parentBucket.cascade
|
||||
}
|
||||
|
||||
for k, v := range cascade {
|
||||
if _, found := frontmatter[k]; !found {
|
||||
frontmatter[k] = v
|
||||
for m, v := range cascade {
|
||||
if !m.Matches(p) {
|
||||
continue
|
||||
}
|
||||
for kk, vv := range v {
|
||||
if _, found := frontmatter[kk]; !found {
|
||||
frontmatter[kk] = vv
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -461,12 +506,12 @@ func (pm *pageMeta) setMetadata(parentBucket *pagesMapBucket, p *pageState, fron
|
||||
pm.params[loki] = isHeadless
|
||||
if p.File().TranslationBaseName() == "index" && isHeadless {
|
||||
pm.buildConfig.List = pagemeta.Never
|
||||
pm.buildConfig.Render = false
|
||||
pm.buildConfig.Render = pagemeta.Never
|
||||
}
|
||||
case "outputs":
|
||||
o := cast.ToStringSlice(v)
|
||||
if len(o) > 0 {
|
||||
// Output formats are exlicitly set in front matter, use those.
|
||||
// Output formats are explicitly set in front matter, use those.
|
||||
outFormats, err := p.s.outputFormatsConfig.GetByNames(o...)
|
||||
|
||||
if err != nil {
|
||||
@@ -638,7 +683,11 @@ func (p *pageMeta) getListFilter(local bool) contentTreeNodeCallback {
|
||||
}
|
||||
|
||||
func (p *pageMeta) noRender() bool {
|
||||
return !p.buildConfig.Render
|
||||
return p.buildConfig.Render != pagemeta.Always
|
||||
}
|
||||
|
||||
func (p *pageMeta) noLink() bool {
|
||||
return p.buildConfig.Render == pagemeta.Never
|
||||
}
|
||||
|
||||
func (p *pageMeta) applyDefaultValues(n *contentNode) error {
|
||||
|
||||
@@ -51,9 +51,11 @@ func newPagePaths(
|
||||
|
||||
var relPermalink, permalink string
|
||||
|
||||
// If a page is headless or marked as "no render", or bundled in another,
|
||||
// If a page is headless or bundled in another,
|
||||
// it will not get published on its own and it will have no links.
|
||||
if !pm.noRender() && !pm.bundled {
|
||||
// We also check the build options if it's set to not render or have
|
||||
// a link.
|
||||
if !pm.noLink() && !pm.bundled {
|
||||
relPermalink = paths.RelPermalink(s.PathSpec)
|
||||
permalink = paths.PermalinkForOutputFormat(s.PathSpec, f)
|
||||
}
|
||||
|
||||
@@ -1757,3 +1757,24 @@ $$$
|
||||
`<pre><code class="language-bash {hl_lines=[1]}" data-lang="bash {hl_lines=[1]}">SHORT`,
|
||||
)
|
||||
}
|
||||
|
||||
func TestPageCaseIssues(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
b := newTestSitesBuilder(t)
|
||||
b.WithConfigFile("toml", `defaultContentLanguage = "no"
|
||||
[languages]
|
||||
[languages.NO]
|
||||
title = "Norsk"
|
||||
`)
|
||||
b.WithContent("a/B/C/Page1.md", "---\ntitle: Page1\n---")
|
||||
b.WithTemplates("index.html", `
|
||||
{{ $p1 := site.GetPage "a/B/C/Page1" }}
|
||||
Lang: {{ .Lang }}
|
||||
Page1: {{ $p1.Path }}
|
||||
`)
|
||||
|
||||
b.Build(BuildCfg{})
|
||||
|
||||
b.AssertFileContent("public/index.html", "Lang: no", filepath.FromSlash("Page1: a/B/C/Page1.md"))
|
||||
}
|
||||
|
||||
@@ -137,6 +137,7 @@ func (c *pagesCollector) isCascadingEdit(dir contentDirKey) (bool, string) {
|
||||
hasCascade := n.p.bucket.cascade != nil && len(n.p.bucket.cascade) > 0
|
||||
if !ok {
|
||||
isCascade = hasCascade
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -145,7 +146,12 @@ func (c *pagesCollector) isCascadingEdit(dir contentDirKey) (bool, string) {
|
||||
return true
|
||||
}
|
||||
|
||||
isCascade = !reflect.DeepEqual(cascade1, n.p.bucket.cascade)
|
||||
for _, v := range n.p.bucket.cascade {
|
||||
isCascade = !reflect.DeepEqual(cascade1, v)
|
||||
if isCascade {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
|
||||
@@ -187,6 +193,7 @@ func (c *pagesCollector) Collect() (collectErr error) {
|
||||
collectErr = c.collectDir(dir.dirname, true, nil)
|
||||
case bundleBranch:
|
||||
isCascading, section := c.isCascadingEdit(dir)
|
||||
|
||||
if isCascading {
|
||||
c.contentMap.deleteSection(section)
|
||||
}
|
||||
|
||||
@@ -489,7 +489,7 @@ Min HTML: {{ ( resources.Get "mydata/html1.html" | resources.Minify ).Content |
|
||||
`)
|
||||
}, func(b *sitesBuilder) {
|
||||
b.AssertFileContent("public/index.html", `Min CSS: h1{font-style:bold}`)
|
||||
b.AssertFileContent("public/index.html", `Min JS: var x;x=5;document.getElementById("demo").innerHTML=x*10;`)
|
||||
b.AssertFileContent("public/index.html", `Min JS: var x;x=5,document.getElementById("demo").innerHTML=x*10`)
|
||||
b.AssertFileContent("public/index.html", `Min JSON: {"employees":[{"firstName":"John","lastName":"Doe"},{"firstName":"Anna","lastName":"Smith"},{"firstName":"Peter","lastName":"Jones"}]}`)
|
||||
b.AssertFileContent("public/index.html", `Min XML: <hello><world>Hugo Rocks!</<world></hello>`)
|
||||
b.AssertFileContent("public/index.html", `Min SVG: <svg height="100" width="100"><path d="M1e2 1e2H3e2 2e2z"/></svg>`)
|
||||
|
||||
@@ -23,6 +23,7 @@ import (
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -1027,11 +1028,20 @@ func (s *Site) processPartial(config *BuildCfg, init func(config *BuildCfg) erro
|
||||
logger = helpers.NewDistinctFeedbackLogger()
|
||||
)
|
||||
|
||||
var isCSSConfigRe = regexp.MustCompile(`(postcss|tailwind)\.config\.js`)
|
||||
var isCSSFileRe = regexp.MustCompile(`\.(css|scss|sass)`)
|
||||
|
||||
var cachePartitions []string
|
||||
// Special case
|
||||
// TODO(bep) I have a ongoing branch where I have redone the cache. Consider this there.
|
||||
var isCSSChange bool
|
||||
|
||||
for _, ev := range events {
|
||||
if assetsFilename := s.BaseFs.Assets.MakePathRelative(ev.Name); assetsFilename != "" {
|
||||
cachePartitions = append(cachePartitions, resources.ResourceKeyPartitions(assetsFilename)...)
|
||||
if !isCSSChange {
|
||||
isCSSChange = isCSSFileRe.MatchString(assetsFilename) || isCSSConfigRe.MatchString(assetsFilename)
|
||||
}
|
||||
}
|
||||
|
||||
id, found := s.eventToIdentity(ev)
|
||||
@@ -1078,6 +1088,9 @@ func (s *Site) processPartial(config *BuildCfg, init func(config *BuildCfg) erro
|
||||
// These in memory resource caches will be rebuilt on demand.
|
||||
for _, s := range s.h.Sites {
|
||||
s.ResourceSpec.ResourceCache.DeletePartitions(cachePartitions...)
|
||||
if isCSSChange {
|
||||
s.ResourceSpec.ResourceCache.DeleteContains("css", "scss", "sass")
|
||||
}
|
||||
}
|
||||
|
||||
if tmplChanged || i18nChanged {
|
||||
|
||||
+46
-47
@@ -14,35 +14,40 @@
|
||||
package i18n
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/gohugoio/hugo/common/hreflect"
|
||||
"github.com/gohugoio/hugo/common/loggers"
|
||||
"github.com/gohugoio/hugo/config"
|
||||
"github.com/gohugoio/hugo/helpers"
|
||||
|
||||
"github.com/nicksnyder/go-i18n/i18n/bundle"
|
||||
"github.com/nicksnyder/go-i18n/i18n/translation"
|
||||
"github.com/nicksnyder/go-i18n/v2/i18n"
|
||||
)
|
||||
|
||||
type translateFunc func(translationID string, templateData interface{}) string
|
||||
|
||||
var (
|
||||
i18nWarningLogger = helpers.NewDistinctFeedbackLogger()
|
||||
)
|
||||
|
||||
// Translator handles i18n translations.
|
||||
type Translator struct {
|
||||
translateFuncs map[string]bundle.TranslateFunc
|
||||
translateFuncs map[string]translateFunc
|
||||
cfg config.Provider
|
||||
logger *loggers.Logger
|
||||
}
|
||||
|
||||
// NewTranslator creates a new Translator for the given language bundle and configuration.
|
||||
func NewTranslator(b *bundle.Bundle, cfg config.Provider, logger *loggers.Logger) Translator {
|
||||
t := Translator{cfg: cfg, logger: logger, translateFuncs: make(map[string]bundle.TranslateFunc)}
|
||||
func NewTranslator(b *i18n.Bundle, cfg config.Provider, logger *loggers.Logger) Translator {
|
||||
t := Translator{cfg: cfg, logger: logger, translateFuncs: make(map[string]translateFunc)}
|
||||
t.initFuncs(b)
|
||||
return t
|
||||
}
|
||||
|
||||
// Func gets the translate func for the given language, or for the default
|
||||
// configured language if not found.
|
||||
func (t Translator) Func(lang string) bundle.TranslateFunc {
|
||||
func (t Translator) Func(lang string) translateFunc {
|
||||
if f, ok := t.translateFuncs[lang]; ok {
|
||||
return f
|
||||
}
|
||||
@@ -50,68 +55,62 @@ func (t Translator) Func(lang string) bundle.TranslateFunc {
|
||||
if f, ok := t.translateFuncs[t.cfg.GetString("defaultContentLanguage")]; ok {
|
||||
return f
|
||||
}
|
||||
|
||||
t.logger.INFO.Println("i18n not initialized; if you need string translations, check that you have a bundle in /i18n that matches the site language or the default language.")
|
||||
return func(translationID string, args ...interface{}) string {
|
||||
return func(translationID string, args interface{}) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (t Translator) initFuncs(bndl *bundle.Bundle) {
|
||||
defaultContentLanguage := t.cfg.GetString("defaultContentLanguage")
|
||||
|
||||
defaultT, err := bndl.Tfunc(defaultContentLanguage)
|
||||
if err != nil {
|
||||
t.logger.INFO.Printf("No translation bundle found for default language %q", defaultContentLanguage)
|
||||
}
|
||||
|
||||
translations := bndl.Translations()
|
||||
|
||||
func (t Translator) initFuncs(bndl *i18n.Bundle) {
|
||||
enableMissingTranslationPlaceholders := t.cfg.GetBool("enableMissingTranslationPlaceholders")
|
||||
for _, lang := range bndl.LanguageTags() {
|
||||
|
||||
currentLang := lang
|
||||
currentLangStr := currentLang.String()
|
||||
currentLangKey := strings.TrimPrefix(currentLangStr, artificialLangTagPrefix)
|
||||
localizer := i18n.NewLocalizer(bndl, currentLangStr)
|
||||
|
||||
t.translateFuncs[currentLang] = func(translationID string, args ...interface{}) string {
|
||||
tFunc, err := bndl.Tfunc(currentLang)
|
||||
if err != nil {
|
||||
t.logger.WARN.Printf("could not load translations for language %q (%s), will use default content language.\n", lang, err)
|
||||
t.translateFuncs[currentLangKey] = func(translationID string, templateData interface{}) string {
|
||||
|
||||
var pluralCount interface{}
|
||||
|
||||
if templateData != nil {
|
||||
tp := reflect.TypeOf(templateData)
|
||||
if hreflect.IsNumber(tp.Kind()) {
|
||||
pluralCount = templateData
|
||||
// This was how go-i18n worked in v1.
|
||||
templateData = map[string]interface{}{
|
||||
"Count": templateData,
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
translated := tFunc(translationID, args...)
|
||||
if translated != translationID {
|
||||
translated, translatedLang, err := localizer.LocalizeWithTag(&i18n.LocalizeConfig{
|
||||
MessageID: translationID,
|
||||
TemplateData: templateData,
|
||||
PluralCount: pluralCount,
|
||||
})
|
||||
|
||||
if err == nil && currentLang == translatedLang {
|
||||
return translated
|
||||
}
|
||||
// If there is no translation for translationID,
|
||||
// then Tfunc returns translationID itself.
|
||||
// But if user set same translationID and translation, we should check
|
||||
// if it really untranslated:
|
||||
if isIDTranslated(translations, currentLang, translationID) {
|
||||
return translated
|
||||
|
||||
if _, ok := err.(*i18n.MessageNotFoundErr); !ok {
|
||||
t.logger.WARN.Printf("Failed to get translated string for language %q and ID %q: %s", currentLangStr, translationID, err)
|
||||
}
|
||||
|
||||
if t.cfg.GetBool("logI18nWarnings") {
|
||||
i18nWarningLogger.Printf("i18n|MISSING_TRANSLATION|%s|%s", currentLang, translationID)
|
||||
i18nWarningLogger.Printf("i18n|MISSING_TRANSLATION|%s|%s", currentLangStr, translationID)
|
||||
}
|
||||
|
||||
if enableMissingTranslationPlaceholders {
|
||||
return "[i18n] " + translationID
|
||||
}
|
||||
if defaultT != nil {
|
||||
translated := defaultT(translationID, args...)
|
||||
if translated != translationID {
|
||||
return translated
|
||||
}
|
||||
if isIDTranslated(translations, defaultContentLanguage, translationID) {
|
||||
return translated
|
||||
}
|
||||
}
|
||||
return ""
|
||||
|
||||
return translated
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If the translation map contains translationID for specified currentLang,
|
||||
// then the translationID is actually translated.
|
||||
func isIDTranslated(translations map[string]map[string]translation.Translation, lang, id string) bool {
|
||||
_, contains := translations[lang][id]
|
||||
return contains
|
||||
}
|
||||
|
||||
+39
-7
@@ -14,6 +14,7 @@
|
||||
package i18n
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
@@ -125,6 +126,35 @@ var i18nTests = []i18nTest{
|
||||
expected: "¡Hola, 50 gente!",
|
||||
expectedFlag: "¡Hola, 50 gente!",
|
||||
},
|
||||
// https://github.com/gohugoio/hugo/issues/7787
|
||||
{
|
||||
name: "readingTime-one",
|
||||
data: map[string][]byte{
|
||||
"en.toml": []byte(`[readingTime]
|
||||
one = "One minute to read"
|
||||
other = "{{ .Count }} minutes to read"
|
||||
`),
|
||||
},
|
||||
args: 1,
|
||||
lang: "en",
|
||||
id: "readingTime",
|
||||
expected: "One minute to read",
|
||||
expectedFlag: "One minute to read",
|
||||
},
|
||||
{
|
||||
name: "readingTime-many",
|
||||
data: map[string][]byte{
|
||||
"en.toml": []byte(`[readingTime]
|
||||
one = "One minute to read"
|
||||
other = "{{ .Count }} minutes to read"
|
||||
`),
|
||||
},
|
||||
args: 21,
|
||||
lang: "en",
|
||||
id: "readingTime",
|
||||
expected: "21 minutes to read",
|
||||
expectedFlag: "21 minutes to read",
|
||||
},
|
||||
// Same id and translation in current language
|
||||
// https://github.com/gohugoio/hugo/issues/2607
|
||||
{
|
||||
@@ -242,13 +272,15 @@ func TestI18nTranslate(t *testing.T) {
|
||||
v.Set("enableMissingTranslationPlaceholders", enablePlaceholders)
|
||||
|
||||
for _, test := range i18nTests {
|
||||
if enablePlaceholders {
|
||||
expected = test.expectedFlag
|
||||
} else {
|
||||
expected = test.expected
|
||||
}
|
||||
actual = doTestI18nTranslate(t, test, v)
|
||||
c.Assert(actual, qt.Equals, expected)
|
||||
c.Run(fmt.Sprintf("%s-%t", test.name, enablePlaceholders), func(c *qt.C) {
|
||||
if enablePlaceholders {
|
||||
expected = test.expectedFlag
|
||||
} else {
|
||||
expected = test.expected
|
||||
}
|
||||
actual = doTestI18nTranslate(t, test, v)
|
||||
c.Assert(actual, qt.Equals, expected)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,16 +14,19 @@
|
||||
package i18n
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/gohugoio/hugo/common/herrors"
|
||||
"golang.org/x/text/language"
|
||||
yaml "gopkg.in/yaml.v2"
|
||||
|
||||
"github.com/BurntSushi/toml"
|
||||
"github.com/gohugoio/hugo/helpers"
|
||||
"github.com/nicksnyder/go-i18n/v2/i18n"
|
||||
|
||||
"github.com/gohugoio/hugo/deps"
|
||||
"github.com/gohugoio/hugo/helpers"
|
||||
"github.com/gohugoio/hugo/hugofs"
|
||||
"github.com/gohugoio/hugo/source"
|
||||
"github.com/nicksnyder/go-i18n/i18n/bundle"
|
||||
"github.com/nicksnyder/go-i18n/i18n/language"
|
||||
_errors "github.com/pkg/errors"
|
||||
)
|
||||
|
||||
@@ -42,13 +45,10 @@ func NewTranslationProvider() *TranslationProvider {
|
||||
func (tp *TranslationProvider) Update(d *deps.Deps) error {
|
||||
spec := source.NewSourceSpec(d.PathSpec, nil)
|
||||
|
||||
i18nBundle := bundle.New()
|
||||
|
||||
en := language.GetPluralSpec("en")
|
||||
if en == nil {
|
||||
return errors.New("the English language has vanished like an old oak table")
|
||||
}
|
||||
var newLangs []string
|
||||
bundle := i18n.NewBundle(language.English)
|
||||
bundle.RegisterUnmarshalFunc("toml", toml.Unmarshal)
|
||||
bundle.RegisterUnmarshalFunc("yaml", yaml.Unmarshal)
|
||||
bundle.RegisterUnmarshalFunc("json", json.Unmarshal)
|
||||
|
||||
// The source dirs are ordered so the most important comes first. Since this is a
|
||||
// last key win situation, we have to reverse the iteration order.
|
||||
@@ -56,33 +56,18 @@ func (tp *TranslationProvider) Update(d *deps.Deps) error {
|
||||
for i := len(dirs) - 1; i >= 0; i-- {
|
||||
dir := dirs[i]
|
||||
src := spec.NewFilesystemFromFileMetaInfo(dir)
|
||||
|
||||
files, err := src.Files()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, r := range files {
|
||||
currentSpec := language.GetPluralSpec(r.BaseFileName())
|
||||
if currentSpec == nil {
|
||||
// This may is a language code not supported by go-i18n, it may be
|
||||
// Klingon or ... not even a fake language. Make sure it works.
|
||||
newLangs = append(newLangs, r.BaseFileName())
|
||||
}
|
||||
}
|
||||
|
||||
if len(newLangs) > 0 {
|
||||
language.RegisterPluralSpec(newLangs, en)
|
||||
}
|
||||
|
||||
for _, file := range files {
|
||||
if err := addTranslationFile(i18nBundle, file); err != nil {
|
||||
if err := addTranslationFile(bundle, file); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tp.t = NewTranslator(i18nBundle, d.Cfg, d.Log)
|
||||
tp.t = NewTranslator(bundle, d.Cfg, d.Log)
|
||||
|
||||
d.Translate = tp.t.Func(d.Language.Lang)
|
||||
|
||||
@@ -90,16 +75,29 @@ func (tp *TranslationProvider) Update(d *deps.Deps) error {
|
||||
|
||||
}
|
||||
|
||||
func addTranslationFile(bundle *bundle.Bundle, r source.File) error {
|
||||
const artificialLangTagPrefix = "art-x-"
|
||||
|
||||
func addTranslationFile(bundle *i18n.Bundle, r source.File) error {
|
||||
f, err := r.FileInfo().Meta().Open()
|
||||
if err != nil {
|
||||
return _errors.Wrapf(err, "failed to open translations file %q:", r.LogicalName())
|
||||
}
|
||||
err = bundle.ParseTranslationFileBytes(r.LogicalName(), helpers.ReaderToBytes(f))
|
||||
|
||||
b := helpers.ReaderToBytes(f)
|
||||
f.Close()
|
||||
|
||||
name := r.LogicalName()
|
||||
lang := helpers.Filename(name)
|
||||
tag := language.Make(lang)
|
||||
if tag == language.Und {
|
||||
name = artificialLangTagPrefix + name
|
||||
}
|
||||
|
||||
_, err = bundle.ParseMessageFileBytes(b, name)
|
||||
if err != nil {
|
||||
return errWithFileContext(_errors.Wrapf(err, "failed to load translations"), r)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ var (
|
||||
Trace: false,
|
||||
FailureLevel: "fatal",
|
||||
WorkingFolderCurrent: false,
|
||||
PreserveTOC: false,
|
||||
}
|
||||
|
||||
// CliDefault holds Asciidoctor CLI defaults (see https://asciidoctor.org/docs/user-manual/)
|
||||
@@ -86,4 +87,5 @@ type Config struct {
|
||||
Trace bool
|
||||
FailureLevel string
|
||||
WorkingFolderCurrent bool
|
||||
PreserveTOC bool
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@ package asciidocext
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
|
||||
@@ -64,7 +63,7 @@ type asciidocConverter struct {
|
||||
}
|
||||
|
||||
func (a *asciidocConverter) Convert(ctx converter.RenderContext) (converter.Result, error) {
|
||||
content, toc, err := extractTOC(a.getAsciidocContent(ctx.Src, a.ctx))
|
||||
content, toc, err := a.extractTOC(a.getAsciidocContent(ctx.Src, a.ctx))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -204,7 +203,7 @@ func getAsciidoctorExecPath() string {
|
||||
|
||||
// extractTOC extracts the toc from the given src html.
|
||||
// It returns the html without the TOC, and the TOC data
|
||||
func extractTOC(src []byte) ([]byte, tableofcontents.Root, error) {
|
||||
func (a *asciidocConverter) extractTOC(src []byte) ([]byte, tableofcontents.Root, error) {
|
||||
var buf bytes.Buffer
|
||||
buf.Write(src)
|
||||
node, err := html.Parse(&buf)
|
||||
@@ -219,7 +218,9 @@ func extractTOC(src []byte) ([]byte, tableofcontents.Root, error) {
|
||||
f = func(n *html.Node) bool {
|
||||
if n.Type == html.ElementNode && n.Data == "div" && attr(n, "id") == "toc" {
|
||||
toc = parseTOC(n)
|
||||
n.Parent.RemoveChild(n)
|
||||
if !a.cfg.MarkupConfig.AsciidocExt.PreserveTOC {
|
||||
n.Parent.RemoveChild(n)
|
||||
}
|
||||
return true
|
||||
}
|
||||
if n.FirstChild != nil {
|
||||
@@ -285,7 +286,7 @@ func parseTOC(doc *html.Node) tableofcontents.Root {
|
||||
f(n.NextSibling, row, level)
|
||||
}
|
||||
}
|
||||
f(doc.FirstChild, 0, 0)
|
||||
f(doc.FirstChild, -1, 0)
|
||||
return toc
|
||||
}
|
||||
|
||||
@@ -300,9 +301,8 @@ func attr(node *html.Node, key string) string {
|
||||
|
||||
func nodeContent(node *html.Node) string {
|
||||
var buf bytes.Buffer
|
||||
w := io.Writer(&buf)
|
||||
for c := node.FirstChild; c != nil; c = c.NextSibling {
|
||||
html.Render(w, c)
|
||||
html.Render(&buf, c)
|
||||
}
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
@@ -277,11 +277,17 @@ func TestTableOfContents(t *testing.T) {
|
||||
t.Skip("asciidoctor not installed")
|
||||
}
|
||||
c := qt.New(t)
|
||||
p, err := Provider.New(converter.ProviderConfig{Logger: loggers.NewErrorLogger()})
|
||||
mconf := markup_config.Default
|
||||
p, err := Provider.New(
|
||||
converter.ProviderConfig{
|
||||
MarkupConfig: mconf,
|
||||
Logger: loggers.NewErrorLogger(),
|
||||
},
|
||||
)
|
||||
c.Assert(err, qt.IsNil)
|
||||
conv, err := p.New(converter.DocumentContext{})
|
||||
c.Assert(err, qt.IsNil)
|
||||
b, err := conv.Convert(converter.RenderContext{Src: []byte(`:toc: macro
|
||||
r, err := conv.Convert(converter.RenderContext{Src: []byte(`:toc: macro
|
||||
:toclevels: 4
|
||||
toc::[]
|
||||
|
||||
@@ -300,11 +306,52 @@ testContent
|
||||
== Section 2
|
||||
`)})
|
||||
c.Assert(err, qt.IsNil)
|
||||
toc, ok := b.(converter.TableOfContentsProvider)
|
||||
toc, ok := r.(converter.TableOfContentsProvider)
|
||||
c.Assert(ok, qt.Equals, true)
|
||||
root := toc.TableOfContents()
|
||||
c.Assert(root.ToHTML(2, 4, false), qt.Equals, "<nav id=\"TableOfContents\">\n <ul>\n <li><a href=\"#_introduction\">Introduction</a></li>\n <li><a href=\"#_section_1\">Section 1</a>\n <ul>\n <li><a href=\"#_section_1_1\">Section 1.1</a>\n <ul>\n <li><a href=\"#_section_1_1_1\">Section 1.1.1</a></li>\n </ul>\n </li>\n <li><a href=\"#_section_1_2\">Section 1.2</a></li>\n </ul>\n </li>\n <li><a href=\"#_section_2\">Section 2</a></li>\n </ul>\n</nav>")
|
||||
c.Assert(root.ToHTML(2, 3, false), qt.Equals, "<nav id=\"TableOfContents\">\n <ul>\n <li><a href=\"#_introduction\">Introduction</a></li>\n <li><a href=\"#_section_1\">Section 1</a>\n <ul>\n <li><a href=\"#_section_1_1\">Section 1.1</a></li>\n <li><a href=\"#_section_1_2\">Section 1.2</a></li>\n </ul>\n </li>\n <li><a href=\"#_section_2\">Section 2</a></li>\n </ul>\n</nav>")
|
||||
expected := tableofcontents.Root{
|
||||
Headers: tableofcontents.Headers{
|
||||
{
|
||||
ID: "",
|
||||
Text: "",
|
||||
Headers: tableofcontents.Headers{
|
||||
{
|
||||
ID: "_introduction",
|
||||
Text: "Introduction",
|
||||
Headers: nil,
|
||||
},
|
||||
{
|
||||
ID: "_section_1",
|
||||
Text: "Section 1",
|
||||
Headers: tableofcontents.Headers{
|
||||
{
|
||||
ID: "_section_1_1",
|
||||
Text: "Section 1.1",
|
||||
Headers: tableofcontents.Headers{
|
||||
{
|
||||
ID: "_section_1_1_1",
|
||||
Text: "Section 1.1.1",
|
||||
Headers: nil,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "_section_1_2",
|
||||
Text: "Section 1.2",
|
||||
Headers: nil,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "_section_2",
|
||||
Text: "Section 2",
|
||||
Headers: nil,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
c.Assert(toc.TableOfContents(), qt.DeepEquals, expected)
|
||||
c.Assert(string(r.Bytes()), qt.Not(qt.Contains), "<div id=\"toc\" class=\"toc\">")
|
||||
}
|
||||
|
||||
func TestTableOfContentsWithCode(t *testing.T) {
|
||||
@@ -322,26 +369,72 @@ func TestTableOfContentsWithCode(t *testing.T) {
|
||||
c.Assert(err, qt.IsNil)
|
||||
conv, err := p.New(converter.DocumentContext{})
|
||||
c.Assert(err, qt.IsNil)
|
||||
b, err := conv.Convert(converter.RenderContext{Src: []byte(`:toc: auto
|
||||
r, err := conv.Convert(converter.RenderContext{Src: []byte(`:toc: auto
|
||||
|
||||
== Some ` + "`code`" + ` in the title
|
||||
`)})
|
||||
c.Assert(err, qt.IsNil)
|
||||
toc, ok := b.(converter.TableOfContentsProvider)
|
||||
toc, ok := r.(converter.TableOfContentsProvider)
|
||||
c.Assert(ok, qt.Equals, true)
|
||||
expected := tableofcontents.Headers{
|
||||
{},
|
||||
{
|
||||
ID: "",
|
||||
Text: "",
|
||||
Headers: tableofcontents.Headers{
|
||||
{
|
||||
ID: "_some_code_in_the_title",
|
||||
Text: "Some <code>code</code> in the title",
|
||||
Headers: nil,
|
||||
expected := tableofcontents.Root{
|
||||
Headers: tableofcontents.Headers{
|
||||
{
|
||||
ID: "",
|
||||
Text: "",
|
||||
Headers: tableofcontents.Headers{
|
||||
{
|
||||
ID: "_some_code_in_the_title",
|
||||
Text: "Some <code>code</code> in the title",
|
||||
Headers: nil,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
c.Assert(toc.TableOfContents().Headers, qt.DeepEquals, expected)
|
||||
c.Assert(toc.TableOfContents(), qt.DeepEquals, expected)
|
||||
c.Assert(string(r.Bytes()), qt.Not(qt.Contains), "<div id=\"toc\" class=\"toc\">")
|
||||
}
|
||||
|
||||
func TestTableOfContentsPreserveTOC(t *testing.T) {
|
||||
if !Supports() {
|
||||
t.Skip("asciidoctor not installed")
|
||||
}
|
||||
c := qt.New(t)
|
||||
mconf := markup_config.Default
|
||||
mconf.AsciidocExt.PreserveTOC = true
|
||||
p, err := Provider.New(
|
||||
converter.ProviderConfig{
|
||||
MarkupConfig: mconf,
|
||||
Logger: loggers.NewErrorLogger(),
|
||||
},
|
||||
)
|
||||
c.Assert(err, qt.IsNil)
|
||||
conv, err := p.New(converter.DocumentContext{})
|
||||
c.Assert(err, qt.IsNil)
|
||||
r, err := conv.Convert(converter.RenderContext{Src: []byte(`:toc:
|
||||
:idprefix:
|
||||
:idseparator: -
|
||||
|
||||
== Some title
|
||||
`)})
|
||||
c.Assert(err, qt.IsNil)
|
||||
toc, ok := r.(converter.TableOfContentsProvider)
|
||||
c.Assert(ok, qt.Equals, true)
|
||||
expected := tableofcontents.Root{
|
||||
Headers: tableofcontents.Headers{
|
||||
{
|
||||
ID: "",
|
||||
Text: "",
|
||||
Headers: tableofcontents.Headers{
|
||||
{
|
||||
ID: "some-title",
|
||||
Text: "Some title",
|
||||
Headers: nil,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
c.Assert(toc.TableOfContents(), qt.DeepEquals, expected)
|
||||
c.Assert(string(r.Bytes()), qt.Contains, "<div id=\"toc\" class=\"toc\">")
|
||||
}
|
||||
|
||||
+21
-6
@@ -18,6 +18,7 @@ import (
|
||||
"github.com/gohugoio/hugo/config"
|
||||
"github.com/gohugoio/hugo/docshelper"
|
||||
"github.com/gohugoio/hugo/parser"
|
||||
"github.com/spf13/cast"
|
||||
|
||||
"github.com/mitchellh/mapstructure"
|
||||
"github.com/tdewolff/minify/v2/css"
|
||||
@@ -35,18 +36,16 @@ var defaultTdewolffConfig = tdewolffConfig{
|
||||
KeepEndTags: true,
|
||||
KeepDefaultAttrVals: true,
|
||||
KeepWhitespace: false,
|
||||
// KeepQuotes: false, >= v2.6.2
|
||||
KeepQuotes: false,
|
||||
},
|
||||
CSS: css.Minifier{
|
||||
Decimals: -1, // will be deprecated
|
||||
// Precision: 0, // use Precision with >= v2.7.0
|
||||
KeepCSS2: true,
|
||||
Precision: 0,
|
||||
KeepCSS2: true,
|
||||
},
|
||||
JS: js.Minifier{},
|
||||
JSON: json.Minifier{},
|
||||
SVG: svg.Minifier{
|
||||
Decimals: -1, // will be deprecated
|
||||
// Precision: 0, // use Precision with >= v2.7.0
|
||||
Precision: 0,
|
||||
},
|
||||
XML: xml.Minifier{
|
||||
KeepWhitespace: false,
|
||||
@@ -99,6 +98,22 @@ func decodeConfig(cfg config.Provider) (conf minifyConfig, err error) {
|
||||
|
||||
m := maps.ToStringMap(v)
|
||||
|
||||
// Handle upstream renames.
|
||||
if td, found := m["tdewolff"]; found {
|
||||
tdm := cast.ToStringMap(td)
|
||||
for _, key := range []string{"css", "svg"} {
|
||||
if v, found := tdm[key]; found {
|
||||
vm := cast.ToStringMap(v)
|
||||
if vv, found := vm["decimal"]; found {
|
||||
vvi := cast.ToInt(vv)
|
||||
if vvi > 0 {
|
||||
vm["precision"] = vvi
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
err = mapstructure.WeakDecode(m, &conf)
|
||||
|
||||
if err != nil {
|
||||
|
||||
@@ -34,7 +34,7 @@ func TestNew(t *testing.T) {
|
||||
var rawJS string
|
||||
var minJS string
|
||||
rawJS = " var foo =1 ; foo ++ ; "
|
||||
minJS = "var foo=1;foo++;"
|
||||
minJS = "var foo=1;foo++"
|
||||
|
||||
var rawJSON string
|
||||
var minJSON string
|
||||
@@ -168,3 +168,26 @@ func TestBugs(t *testing.T) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Renamed to Precision in v2.7.0. Check that we support both.
|
||||
func TestDecodeConfigDecimalIsNowPrecision(t *testing.T) {
|
||||
c := qt.New(t)
|
||||
v := viper.New()
|
||||
v.Set("minify", map[string]interface{}{
|
||||
"disablexml": true,
|
||||
"tdewolff": map[string]interface{}{
|
||||
"css": map[string]interface{}{
|
||||
"decimal": 3,
|
||||
},
|
||||
"svg": map[string]interface{}{
|
||||
"decimal": 3,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
conf, err := decodeConfig(v)
|
||||
|
||||
c.Assert(err, qt.IsNil)
|
||||
c.Assert(conf.Tdewolff.CSS.Precision, qt.Equals, 3)
|
||||
|
||||
}
|
||||
|
||||
@@ -67,7 +67,9 @@ type cssClassCollectorWriter struct {
|
||||
|
||||
isCollecting bool
|
||||
dropValue bool
|
||||
inQuote bool
|
||||
|
||||
inQuote bool
|
||||
quoteValue byte
|
||||
}
|
||||
|
||||
func (w *cssClassCollectorWriter) Write(p []byte) (n int, err error) {
|
||||
@@ -165,7 +167,12 @@ func (c *cssClassCollectorWriter) startCollecting() {
|
||||
|
||||
func (c *cssClassCollectorWriter) toggleIfQuote(b byte) {
|
||||
if isQuote(b) {
|
||||
c.inQuote = !c.inQuote
|
||||
if c.inQuote && b == c.quoteValue {
|
||||
c.inQuote = false
|
||||
} else if !c.inQuote {
|
||||
c.inQuote = true
|
||||
c.quoteValue = b
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -87,6 +87,8 @@ func TestClassCollector(t *testing.T) {
|
||||
|
||||
{"Alpine transition 1", `<div x-transition:enter-start="opacity-0 transform mobile:-translate-x-8 sm:-translate-y-8">`, f("div", "mobile:-translate-x-8 opacity-0 sm:-translate-y-8 transform", "")},
|
||||
{"Vue bind", `<div v-bind:class="{ active: isActive }"></div>`, f("div", "active", "")},
|
||||
// https://github.com/gohugoio/hugo/issues/7746
|
||||
{"Apostrophe inside attribute value", `<a class="missingclass" title="Plus d'information">my text</a><div></div>`, f("a div", "missingclass", "")},
|
||||
} {
|
||||
c.Run(test.name, func(c *qt.C) {
|
||||
w := newHTMLElementsCollectorWriter(newHTMLElementsCollector())
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
"github.com/gohugoio/hugo/common/maps"
|
||||
"github.com/gohugoio/hugo/config"
|
||||
"github.com/gohugoio/hugo/hugofs/files"
|
||||
"github.com/gohugoio/hugo/identity"
|
||||
"github.com/gohugoio/hugo/langs"
|
||||
"github.com/gohugoio/hugo/media"
|
||||
"github.com/gohugoio/hugo/navigation"
|
||||
@@ -87,6 +88,7 @@ func MarshalPageToJSON(p Page) ([]byte, error) {
|
||||
isTranslated := p.IsTranslated()
|
||||
allTranslations := p.AllTranslations()
|
||||
translations := p.Translations()
|
||||
getIdentity := p.GetIdentity()
|
||||
|
||||
s := struct {
|
||||
Content interface{}
|
||||
@@ -143,6 +145,7 @@ func MarshalPageToJSON(p Page) ([]byte, error) {
|
||||
IsTranslated bool
|
||||
AllTranslations Pages
|
||||
Translations Pages
|
||||
GetIdentity identity.Identity
|
||||
}{
|
||||
Content: content,
|
||||
Plain: plain,
|
||||
@@ -198,6 +201,7 @@ func MarshalPageToJSON(p Page) ([]byte, error) {
|
||||
IsTranslated: isTranslated,
|
||||
AllTranslations: allTranslations,
|
||||
Translations: translations,
|
||||
GetIdentity: getIdentity,
|
||||
}
|
||||
|
||||
return json.Marshal(&s)
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
// Copyright 2020 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 page
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/gohugoio/hugo/hugofs/glob"
|
||||
"github.com/mitchellh/mapstructure"
|
||||
)
|
||||
|
||||
// A PageMatcher can be used to match a Page with Glob patterns.
|
||||
// Note that the pattern matching is case insensitive.
|
||||
type PageMatcher struct {
|
||||
// A Glob pattern matching the content path below /content.
|
||||
// Expects Unix-styled slashes.
|
||||
// Note that this is the virtual path, so it starts at the mount root
|
||||
// with a leading "/".
|
||||
Path string
|
||||
|
||||
// A Glob pattern matching the Page's Kind(s), e.g. "{home,section}"
|
||||
Kind string
|
||||
|
||||
// A Glob pattern matching the Page's language, e.g. "{en,sv}".
|
||||
Lang string
|
||||
}
|
||||
|
||||
// Matches returns whether p matches this matcher.
|
||||
func (m PageMatcher) Matches(p Page) bool {
|
||||
|
||||
if m.Kind != "" {
|
||||
g, err := glob.GetGlob(m.Kind)
|
||||
if err == nil && !g.Match(p.Kind()) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
if m.Lang != "" {
|
||||
g, err := glob.GetGlob(m.Lang)
|
||||
if err == nil && !g.Match(p.Lang()) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
if m.Path != "" {
|
||||
g, err := glob.GetGlob(m.Path)
|
||||
// TODO(bep) Path() vs filepath vs leading slash.
|
||||
p := strings.ToLower(filepath.ToSlash(p.Path()))
|
||||
if !(strings.HasPrefix(p, "/")) {
|
||||
p = "/" + p
|
||||
}
|
||||
if err == nil && !g.Match(p) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// DecodePageMatcher decodes m into v.
|
||||
func DecodePageMatcher(m interface{}, v *PageMatcher) error {
|
||||
if err := mapstructure.WeakDecode(m, v); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
v.Kind = strings.ToLower(v.Kind)
|
||||
if v.Kind != "" {
|
||||
if _, found := kindMap[v.Kind]; !found {
|
||||
return errors.Errorf("%q is not a valid Page Kind", v.Kind)
|
||||
}
|
||||
}
|
||||
|
||||
v.Path = filepath.ToSlash(strings.ToLower(v.Path))
|
||||
|
||||
return nil
|
||||
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
// Copyright 2020 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 page
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
qt "github.com/frankban/quicktest"
|
||||
)
|
||||
|
||||
func TestPageMatcher(t *testing.T) {
|
||||
c := qt.New(t)
|
||||
|
||||
p1, p2, p3 := &testPage{path: "/p1", kind: "section", lang: "en"}, &testPage{path: "p2", kind: "page", lang: "no"}, &testPage{path: "p3", kind: "page", lang: "en"}
|
||||
|
||||
c.Run("Matches", func(c *qt.C) {
|
||||
m := PageMatcher{Kind: "section"}
|
||||
|
||||
c.Assert(m.Matches(p1), qt.Equals, true)
|
||||
c.Assert(m.Matches(p2), qt.Equals, false)
|
||||
|
||||
m = PageMatcher{Kind: "page"}
|
||||
c.Assert(m.Matches(p1), qt.Equals, false)
|
||||
c.Assert(m.Matches(p2), qt.Equals, true)
|
||||
c.Assert(m.Matches(p3), qt.Equals, true)
|
||||
|
||||
m = PageMatcher{Kind: "page", Path: "/p2"}
|
||||
c.Assert(m.Matches(p1), qt.Equals, false)
|
||||
c.Assert(m.Matches(p2), qt.Equals, true)
|
||||
c.Assert(m.Matches(p3), qt.Equals, false)
|
||||
|
||||
m = PageMatcher{Path: "/p*"}
|
||||
c.Assert(m.Matches(p1), qt.Equals, true)
|
||||
c.Assert(m.Matches(p2), qt.Equals, true)
|
||||
c.Assert(m.Matches(p3), qt.Equals, true)
|
||||
|
||||
m = PageMatcher{Lang: "en"}
|
||||
c.Assert(m.Matches(p1), qt.Equals, true)
|
||||
c.Assert(m.Matches(p2), qt.Equals, false)
|
||||
c.Assert(m.Matches(p3), qt.Equals, true)
|
||||
|
||||
})
|
||||
|
||||
c.Run("Decode", func(c *qt.C) {
|
||||
var v PageMatcher
|
||||
c.Assert(DecodePageMatcher(map[string]interface{}{"kind": "foo"}, &v), qt.Not((qt.IsNil)))
|
||||
c.Assert(DecodePageMatcher(map[string]interface{}{"kind": "home", "path": filepath.FromSlash("/a/b/**")}, &v), qt.IsNil)
|
||||
c.Assert(v, qt.Equals, PageMatcher{Kind: "home", Path: "/a/b/**"})
|
||||
})
|
||||
|
||||
}
|
||||
@@ -28,11 +28,12 @@ const (
|
||||
Never = "never"
|
||||
Always = "always"
|
||||
ListLocally = "local"
|
||||
Link = "link"
|
||||
)
|
||||
|
||||
var defaultBuildConfig = BuildConfig{
|
||||
List: Always,
|
||||
Render: true,
|
||||
Render: Always,
|
||||
PublishResources: true,
|
||||
set: true,
|
||||
}
|
||||
@@ -49,7 +50,10 @@ type BuildConfig struct {
|
||||
List string
|
||||
|
||||
// Whether to render it.
|
||||
Render bool
|
||||
// Valid values: never, always, link.
|
||||
// The value link means it will not be rendered, but it will get a RelPermalink/Permalink.
|
||||
// Note that before 0.76.0 this was a bool, so we accept those too.
|
||||
Render string
|
||||
|
||||
// Whether to publish its resources. These will still be published on demand,
|
||||
// but enabling this can be useful if the originals (e.g. images) are
|
||||
@@ -62,7 +66,7 @@ type BuildConfig struct {
|
||||
// Disable sets all options to their off value.
|
||||
func (b *BuildConfig) Disable() {
|
||||
b.List = Never
|
||||
b.Render = false
|
||||
b.Render = Never
|
||||
b.PublishResources = false
|
||||
b.set = true
|
||||
}
|
||||
@@ -91,5 +95,16 @@ func DecodeBuildConfig(m interface{}) (BuildConfig, error) {
|
||||
b.List = Always
|
||||
}
|
||||
|
||||
// In 0.76.0 we changed the Render from bool to a string.
|
||||
switch b.Render {
|
||||
case "0":
|
||||
b.Render = Never
|
||||
case "1":
|
||||
b.Render = Always
|
||||
case Always, Never, Link:
|
||||
default:
|
||||
b.Render = Always
|
||||
}
|
||||
|
||||
return b, err
|
||||
}
|
||||
|
||||
@@ -31,33 +31,61 @@ func TestDecodeBuildConfig(t *testing.T) {
|
||||
|
||||
configTempl := `
|
||||
[_build]
|
||||
render = true
|
||||
render = %s
|
||||
list = %s
|
||||
publishResources = true`
|
||||
|
||||
for _, test := range []struct {
|
||||
list interface{}
|
||||
expect string
|
||||
args []interface{}
|
||||
expect BuildConfig
|
||||
}{
|
||||
{"true", Always},
|
||||
{"false", Never},
|
||||
{`"always"`, Always},
|
||||
{`"local"`, ListLocally},
|
||||
{`"asdfadf"`, Always},
|
||||
{
|
||||
[]interface{}{"true", "true"},
|
||||
BuildConfig{
|
||||
Render: Always,
|
||||
List: Always,
|
||||
PublishResources: true,
|
||||
set: true,
|
||||
}},
|
||||
{[]interface{}{"true", "false"}, BuildConfig{
|
||||
Render: Always,
|
||||
List: Never,
|
||||
PublishResources: true,
|
||||
set: true,
|
||||
}},
|
||||
{[]interface{}{`"always"`, `"always"`}, BuildConfig{
|
||||
Render: Always,
|
||||
List: Always,
|
||||
PublishResources: true,
|
||||
set: true,
|
||||
}},
|
||||
{[]interface{}{`"never"`, `"never"`}, BuildConfig{
|
||||
Render: Never,
|
||||
List: Never,
|
||||
PublishResources: true,
|
||||
set: true,
|
||||
}},
|
||||
{[]interface{}{`"link"`, `"local"`}, BuildConfig{
|
||||
Render: Link,
|
||||
List: ListLocally,
|
||||
PublishResources: true,
|
||||
set: true,
|
||||
}},
|
||||
{[]interface{}{`"always"`, `"asdfadf"`}, BuildConfig{
|
||||
Render: Always,
|
||||
List: Always,
|
||||
PublishResources: true,
|
||||
set: true,
|
||||
}},
|
||||
} {
|
||||
cfg, err := config.FromConfigString(fmt.Sprintf(configTempl, test.list), "toml")
|
||||
cfg, err := config.FromConfigString(fmt.Sprintf(configTempl, test.args...), "toml")
|
||||
c.Assert(err, qt.IsNil)
|
||||
bcfg, err := DecodeBuildConfig(cfg.Get("_build"))
|
||||
c.Assert(err, qt.IsNil)
|
||||
|
||||
eq := qt.CmpEquals(hqt.DeepAllowUnexported(BuildConfig{}))
|
||||
|
||||
c.Assert(bcfg, eq, BuildConfig{
|
||||
Render: true,
|
||||
List: test.expect,
|
||||
PublishResources: true,
|
||||
set: true,
|
||||
})
|
||||
c.Assert(bcfg, eq, test.expect)
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -85,11 +85,12 @@ func newTestPathSpecFor(cfg config.Provider) *helpers.PathSpec {
|
||||
}
|
||||
|
||||
type testPage struct {
|
||||
kind string
|
||||
description string
|
||||
title string
|
||||
linkTitle string
|
||||
|
||||
section string
|
||||
lang string
|
||||
section string
|
||||
|
||||
content string
|
||||
|
||||
@@ -297,11 +298,11 @@ func (p *testPage) Keywords() []string {
|
||||
}
|
||||
|
||||
func (p *testPage) Kind() string {
|
||||
panic("not implemented")
|
||||
return p.kind
|
||||
}
|
||||
|
||||
func (p *testPage) Lang() string {
|
||||
panic("not implemented")
|
||||
return p.lang
|
||||
}
|
||||
|
||||
func (p *testPage) Language() *langs.Language {
|
||||
|
||||
@@ -295,3 +295,22 @@ func (c *ResourceCache) DeletePartitions(partitions ...string) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (c *ResourceCache) DeleteContains(parts ...string) {
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
|
||||
for k := range c.cache {
|
||||
clear := false
|
||||
for _, part := range parts {
|
||||
if strings.Contains(k, part) {
|
||||
clear = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if clear {
|
||||
delete(c.cache, k)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ from snapcraft.internal import errors
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
_NODEJS_BASE = "node-v{version}-linux-{arch}"
|
||||
_NODEJS_VERSION = "12.18.3"
|
||||
_NODEJS_VERSION = "12.18.4"
|
||||
_NODEJS_TMPL = "https://nodejs.org/dist/v{version}/{base}.tar.gz"
|
||||
_NODEJS_ARCHES = {"i386": "x86", "amd64": "x64", "armhf": "armv7l", "arm64": "arm64", "ppc64el": "ppc64le", "s390x": "s390x"}
|
||||
_YARN_URL = "https://yarnpkg.com/latest.tar.gz"
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
name: hugo
|
||||
version: "0.75.1"
|
||||
version: "0.76.1"
|
||||
summary: Fast and Flexible Static Site Generator
|
||||
description: |
|
||||
Hugo is a static HTML and CSS website generator written in Go. It is
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
|
||||
|
||||
This is a bug-fix release with a couple of important fixes.
|
||||
|
||||
* resources/image: Fix nilpointer for images with no Exif [cd00f7f9](https://github.com/gohugoio/hugo/commit/cd00f7f9661d67951ef16c5198541f09f1c058b4) [@bep](https://github.com/bep) [#7688](https://github.com/gohugoio/hugo/issues/7688)
|
||||
* modules/npm: Preserve the original package.json if it exists [214afe4c](https://github.com/gohugoio/hugo/commit/214afe4c1bb9c37bc6159e659d66ba9a268a2849) [@bep](https://github.com/bep) [#7690](https://github.com/gohugoio/hugo/issues/7690)
|
||||
* tpl: Fix grammar in the new 'requires non-zero' error message [cd830bb0](https://github.com/gohugoio/hugo/commit/cd830bb0275fc39240861627ef26e146985b5c86) [@nekr0z](https://github.com/nekr0z)
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
|
||||
|
||||
This is a bug-fix release with a couple of important fixes.
|
||||
|
||||
* langs/i18n: Fix i18n .Count regression [f9e798e8](https://github.com/gohugoio/hugo/commit/f9e798e8c4234bd60277e3cb10663ba254d4ecb7) [@bep](https://github.com/bep) [#7787](https://github.com/gohugoio/hugo/issues/7787)
|
||||
* Fix typo in 0.76.0 release note [ee56efff](https://github.com/gohugoio/hugo/commit/ee56efffcb3f81120b0d3e0297b4fb5966124354) [@digitalcraftsman](https://github.com/digitalcraftsman)
|
||||
|
||||
|
||||
|
||||
+12
-2
@@ -15,12 +15,13 @@
|
||||
package lang
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/gohugoio/hugo/deps"
|
||||
"github.com/spf13/cast"
|
||||
)
|
||||
@@ -39,12 +40,21 @@ type Namespace struct {
|
||||
|
||||
// Translate returns a translated string for id.
|
||||
func (ns *Namespace) Translate(id interface{}, args ...interface{}) (string, error) {
|
||||
var templateData interface{}
|
||||
|
||||
if len(args) > 0 {
|
||||
if len(args) > 1 {
|
||||
return "", errors.Errorf("wrong number of arguments, expecting at most 2, got %d", len(args)+1)
|
||||
}
|
||||
templateData = args[0]
|
||||
}
|
||||
|
||||
sid, err := cast.ToStringE(id)
|
||||
if err != nil {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
return ns.deps.Translate(sid, args...), nil
|
||||
return ns.deps.Translate(sid, templateData), nil
|
||||
}
|
||||
|
||||
// NumFmt formats a number with the given precision using the
|
||||
|
||||
+10
-7
@@ -496,16 +496,19 @@ if (!doNotTrack) {
|
||||
{{ template "_internal/shortcodes/vimeo_simple.html" . }}
|
||||
{{- else -}}
|
||||
{{ if .IsNamedParams }}<div {{ if .Get "class" }}class="{{ .Get "class" }}"{{ else }}style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;"{{ end }}>
|
||||
<iframe src="https://player.vimeo.com/video/{{ .Get "id" }}" {{ if not (.Get "class") }}style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" {{ end }}{{ if .Get "title"}}title="{{ .Get "title" }}"{{ else }}title="vimeo video"{{ end }} webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
|
||||
</div>{{ else }}
|
||||
<iframe src="https://player.vimeo.com/video/{{ .Get "id" }}{{- if $pc.EnableDNT -}}?dnt=1{{- end -}}" {{ if not (.Get "class") }}style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" {{ end }}{{ if .Get "title"}}title="{{ .Get "title" }}"{{ else }}title="vimeo video"{{ end }} webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
|
||||
</div>{{ else }}
|
||||
<div {{ if gt (len .Params) 1 }}class="{{ .Get 1 }}"{{ else }}style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;"{{ end }}>
|
||||
<iframe src="https://player.vimeo.com/video/{{ .Get 0 }}" {{ if len .Params | eq 1 }}style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" {{ end }}{{ if len .Params | eq 3 }}title="{{ .Get 2 }}"{{ else }}title="vimeo video"{{ end }} webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
|
||||
</div>
|
||||
<iframe src="https://player.vimeo.com/video/{{ .Get 0 }}{{- if $pc.EnableDNT -}}?dnt=1{{- end -}}" {{ if len .Params | eq 1 }}style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" {{ end }}{{ if len .Params | eq 3 }}title="{{ .Get 2 }}"{{ else }}title="vimeo video"{{ end }} webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
|
||||
</div>
|
||||
{{ end }}
|
||||
{{- end -}}
|
||||
{{- end -}}`},
|
||||
{`shortcodes/vimeo_simple.html`, `{{ $id := .Get "id" | default (.Get 0) }}
|
||||
{{- $item := getJSON "https://vimeo.com/api/oembed.json?url=https://vimeo.com/" $id -}}
|
||||
{`shortcodes/vimeo_simple.html`, `{{- $pc := .Page.Site.Config.Privacy.Vimeo -}}
|
||||
{{- if not $pc.Disable -}}
|
||||
{{ $id := .Get "id" | default (.Get 0) }}
|
||||
{{ $dnt := cond (eq $pc.EnableDNT true) "?dnt=1" "" }}
|
||||
{{- $item := getJSON (print "https://vimeo.com/api/oembed.json?url=https://vimeo.com/" $id $dnt) -}}
|
||||
{{ $class := .Get "class" | default (.Get 1) }}
|
||||
{{ $hasClass := $class }}
|
||||
{{ $class := $class | default "__h_video" }}
|
||||
@@ -522,7 +525,7 @@ if (!doNotTrack) {
|
||||
<img src="{{ $thumb }}" srcset="{{ $thumb }} 1x, {{ $original }} 2x" alt="{{ .title }}">
|
||||
<div class="play">{{ template "__h_simple_icon_play" $ }}</div></a></div>
|
||||
{{- end -}}
|
||||
`},
|
||||
{{- end -}}`},
|
||||
{`shortcodes/youtube.html`, `{{- $pc := .Page.Site.Config.Privacy.YouTube -}}
|
||||
{{- if not $pc.Disable -}}
|
||||
{{- $ytHost := cond $pc.PrivacyEnhanced "www.youtube-nocookie.com" "www.youtube.com" -}}
|
||||
|
||||
@@ -4,11 +4,11 @@
|
||||
{{ template "_internal/shortcodes/vimeo_simple.html" . }}
|
||||
{{- else -}}
|
||||
{{ if .IsNamedParams }}<div {{ if .Get "class" }}class="{{ .Get "class" }}"{{ else }}style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;"{{ end }}>
|
||||
<iframe src="https://player.vimeo.com/video/{{ .Get "id" }}" {{ if not (.Get "class") }}style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" {{ end }}{{ if .Get "title"}}title="{{ .Get "title" }}"{{ else }}title="vimeo video"{{ end }} webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
|
||||
</div>{{ else }}
|
||||
<iframe src="https://player.vimeo.com/video/{{ .Get "id" }}{{- if $pc.EnableDNT -}}?dnt=1{{- end -}}" {{ if not (.Get "class") }}style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" {{ end }}{{ if .Get "title"}}title="{{ .Get "title" }}"{{ else }}title="vimeo video"{{ end }} webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
|
||||
</div>{{ else }}
|
||||
<div {{ if gt (len .Params) 1 }}class="{{ .Get 1 }}"{{ else }}style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;"{{ end }}>
|
||||
<iframe src="https://player.vimeo.com/video/{{ .Get 0 }}" {{ if len .Params | eq 1 }}style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" {{ end }}{{ if len .Params | eq 3 }}title="{{ .Get 2 }}"{{ else }}title="vimeo video"{{ end }} webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
|
||||
</div>
|
||||
<iframe src="https://player.vimeo.com/video/{{ .Get 0 }}{{- if $pc.EnableDNT -}}?dnt=1{{- end -}}" {{ if len .Params | eq 1 }}style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" {{ end }}{{ if len .Params | eq 3 }}title="{{ .Get 2 }}"{{ else }}title="vimeo video"{{ end }} webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>
|
||||
</div>
|
||||
{{ end }}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
@@ -1,5 +1,8 @@
|
||||
{{- $pc := .Page.Site.Config.Privacy.Vimeo -}}
|
||||
{{- if not $pc.Disable -}}
|
||||
{{ $id := .Get "id" | default (.Get 0) }}
|
||||
{{- $item := getJSON "https://vimeo.com/api/oembed.json?url=https://vimeo.com/" $id -}}
|
||||
{{ $dnt := cond (eq $pc.EnableDNT true) "?dnt=1" "" }}
|
||||
{{- $item := getJSON (print "https://vimeo.com/api/oembed.json?url=https://vimeo.com/" $id $dnt) -}}
|
||||
{{ $class := .Get "class" | default (.Get 1) }}
|
||||
{{ $hasClass := $class }}
|
||||
{{ $class := $class | default "__h_video" }}
|
||||
@@ -16,3 +19,4 @@
|
||||
<img src="{{ $thumb }}" srcset="{{ $thumb }} 1x, {{ $original }} 2x" alt="{{ .title }}">
|
||||
<div class="play">{{ template "__h_simple_icon_play" $ }}</div></a></div>
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
Reference in New Issue
Block a user