Compare commits

...

61 Commits

Author SHA1 Message Date
hugoreleaser f1e799c2e1 releaser: Prepare repository for 0.145.0-DEV
[ci skip]
2025-02-17 16:36:56 +00:00
hugoreleaser b289b17c43 releaser: Bump versions for release of 0.144.0
[ci skip]
2025-02-17 16:22:31 +00:00
Bjørn Erik Pedersen 85c1727748 markup/goldmark: Fix panic on stray attribute nodes 2025-02-17 17:19:53 +01:00
Bjørn Erik Pedersen 641403f7de Fix Position for passthrough hooks
Fixes #13406
2025-02-17 12:23:49 +01:00
Bjørn Erik Pedersen 24cc25552f Fix auto generated header ids so they don't contain e.g. hyperlink destinations (note)
This makes the header ids match the newly added dt ids.

Also make sure newlines are preserved in hooks' `.PlainText`.

Fixes #13405
Fixes #13410
2025-02-17 12:23:49 +01:00
dependabot[bot] a2ca95629a build(deps): bump github.com/spf13/cobra from 1.8.1 to 1.9.1
Bumps [github.com/spf13/cobra](https://github.com/spf13/cobra) from 1.8.1 to 1.9.1.
- [Release notes](https://github.com/spf13/cobra/releases)
- [Commits](https://github.com/spf13/cobra/compare/v1.8.1...v1.9.1)

---
updated-dependencies:
- dependency-name: github.com/spf13/cobra
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-17 12:08:14 +01:00
dependabot[bot] 367fe526e2 build(deps): bump github.com/sanity-io/litter from 1.5.7 to 1.5.8
Bumps [github.com/sanity-io/litter](https://github.com/sanity-io/litter) from 1.5.7 to 1.5.8.
- [Changelog](https://github.com/sanity-io/litter/blob/main/CHANGELOG.md)
- [Commits](https://github.com/sanity-io/litter/compare/v1.5.7...v1.5.8)

---
updated-dependencies:
- dependency-name: github.com/sanity-io/litter
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-17 12:06:55 +01:00
Joe Mooring 5de3913ed4 config/allconfig: Deprecate :filename and :slugorfilename tokens 2025-02-17 12:06:32 +01:00
Bjørn Erik Pedersen 7b7a0f3624 resources/page: Revise the new contentbasename permalinks tokens
* Make it work for all pages, including those created from content adapters and not backed by a file.
* Allow the `slug` to win, so the new tokens are:

`:contentbasename`:

1. ContentBaseName

`:slugorcontentbasename`:

1. Slug
2. ContentBaseName

Note that a page will always have a `ContentBaseName`, so no need to fall back to e.g. the title.

Closes #11722
2025-02-17 09:41:49 +01:00
Henrique Dias cb7a4339b7 resources/page: Add :contentbasename and :contentbasenameorslug permalink tokens
See #11722
2025-02-17 09:41:49 +01:00
Bjørn Erik Pedersen 157d3703c3 Add autoID for definition terms
Fixes #13403
See #11566

Co-authored-by: Joe Mooring <joe@mooring.com>
2025-02-16 20:55:27 +01:00
dependabot[bot] 9c2f8ec61b build(deps): bump github.com/sanity-io/litter from 1.5.5 to 1.5.7
Bumps [github.com/sanity-io/litter](https://github.com/sanity-io/litter) from 1.5.5 to 1.5.7.
- [Changelog](https://github.com/sanity-io/litter/blob/main/CHANGELOG.md)
- [Commits](https://github.com/sanity-io/litter/compare/v1.5.5...v1.5.7)

---
updated-dependencies:
- dependency-name: github.com/sanity-io/litter
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-14 14:25:11 +01:00
dependabot[bot] bd77944ba2 build(deps): bump github.com/gohugoio/hugo-goldmark-extensions/extras
Bumps [github.com/gohugoio/hugo-goldmark-extensions/extras](https://github.com/gohugoio/hugo-goldmark-extensions) from 0.2.0 to 0.3.0.
- [Release notes](https://github.com/gohugoio/hugo-goldmark-extensions/releases)
- [Commits](https://github.com/gohugoio/hugo-goldmark-extensions/compare/extras/v0.2.0...extras/v0.3.0)

---
updated-dependencies:
- dependency-name: github.com/gohugoio/hugo-goldmark-extensions/extras
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-14 14:24:04 +01:00
Peter Weston c1f4228d61 config: Fix server.redirects.fromRe being ignored unless server.redirects.from is also set 2025-02-14 10:21:19 +01:00
Joe Mooring 503dcf6252 internal/warpc: Enable KaTeX mhchem extension 2025-02-14 10:04:15 +01:00
Joe Mooring 5dd0ba00f7 Update README.md
- Include section about editions
- Bump minimum required Go version for building from source
- Include instructions for building the extended/deploy edition
- Update dependency list
2025-02-13 17:17:59 +01:00
dependabot[bot] 2e835d0841 build(deps): bump golang.org/x/tools from 0.29.0 to 0.30.0
Bumps [golang.org/x/tools](https://github.com/golang/tools) from 0.29.0 to 0.30.0.
- [Release notes](https://github.com/golang/tools/releases)
- [Commits](https://github.com/golang/tools/compare/v0.29.0...v0.30.0)

---
updated-dependencies:
- dependency-name: golang.org/x/tools
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-13 15:01:51 +01:00
Bjørn Erik Pedersen 2c77719cd6 modules: Add GOAUTH to module config
Closes #13385
2025-02-13 15:01:28 +01:00
dependabot[bot] d89b9d891c build(deps): bump github.com/aws/aws-sdk-go-v2/service/cloudfront
Bumps [github.com/aws/aws-sdk-go-v2/service/cloudfront](https://github.com/aws/aws-sdk-go-v2) from 1.44.9 to 1.44.10.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Changelog](https://github.com/aws/aws-sdk-go-v2/blob/main/changelog-template.json)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/service/macie2/v1.44.9...service/s3control/v1.44.10)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/service/cloudfront
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-13 13:48:54 +01:00
dependabot[bot] 8721a35202 build(deps): bump google.golang.org/api from 0.206.0 to 0.221.0
Bumps [google.golang.org/api](https://github.com/googleapis/google-api-go-client) from 0.206.0 to 0.221.0.
- [Release notes](https://github.com/googleapis/google-api-go-client/releases)
- [Changelog](https://github.com/googleapis/google-api-go-client/blob/main/CHANGES.md)
- [Commits](https://github.com/googleapis/google-api-go-client/compare/v0.206.0...v0.221.0)

---
updated-dependencies:
- dependency-name: google.golang.org/api
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-13 13:47:55 +01:00
Bjørn Erik Pedersen fd38aee694 Support menus as maps in content adapters
Fixes #13384
2025-02-13 13:29:24 +01:00
Bjørn Erik Pedersen d25f7ec172 js/esbuild: Add drop option
Fixes #13362
2025-02-13 13:26:46 +01:00
Bjørn Erik Pedersen 304a7e5e74 Merge commit 'a024bc7d76fcc5e49e8210f9b0896db9ef21861a' 2025-02-13 10:40:34 +01:00
Bjørn Erik Pedersen a024bc7d76 Squashed 'docs/' changes from 73a01565c..d1a251933
d1a251933 theme: Optimize for printing
d906488d5 theme: Add border to highlighted code blocks within list items
9630c38cb theme: Display short command on commands list
7f81dd997 content: Regen commands markup
a84008e99 content: Cleanup primary list page
0874b03e9 content: Publish QR code examples to the images/qr directory
ef1ce3498 Restore static/img
489a68458 content: Restore KeyCDN screen captures
7d6e6184b theme: Move search button in navbar to the right on smaller screens
b03b96082 theme: Misc style adjustments
ecad97821 theme: Misc fixes
cf5e07b0f content: Restore example data and images
c7265041f content: Reformat css.TailwindCSS setup steps
3226e668f theme: Make the search button more compact on mobile
1f6614ee8 content: Update css.TailwindCSS example
49a2e7d71 theme: Improve search output
7e6b81ffa misc: Create issue template
826740223 theme: Misc search improvements
75f32b2f6 theme:  Remove the search alert
fd3de4ac2 config: Enable link render hook warnings
769e387cd Adjust logic to mark current section for Algolia
ba73ce646 Adjust markup to make it easier to match in Algolia
5accec5f1 Misc adjustments
eb5842566 Some content adjustments
bdf97b7b4 Add new theme
b19d68ee5 Remove old theme
a04e96e55 Rewrite the css.TailwindCSS page
1c46f1864 Update deprecation notes
aedcb444c Fix typo
c3290b876 Changes related to release of v0.144.0
a0012fcce netlify: Hugo 0.143.1
9e4d73e87 Include sections in quick-reference page collection
4591058f5 Miscellaneous edits
612b8528f glossary: More edits
1f0c54e60 Fit typo
6f14084c1 Move glossary to quick reference section
2d94905be Improve branch bundle admonition
2ea56bef3 Fix typos found with codespell
71c5fe951 Close shortcode
e95d06592 Document the responseHeaders option for resources.GetRemote
da7c12aaa Deprecate gist shortcode
c2d3e2c25 netlify: Bump to 0.143.0
367d3a7ab Improve new-in shortcode
1a7413a16 Clean up shortcode documentation
d847892aa Improve glossary
6a7fd42ff Update pages describing Store methods and functions
fa7643d1b Revert "Improve link render hook performance"
fe4c86ec4 Reformat MathJax example
cea44922a Update MathJax example to use safe mode
0b6d0292c Update KaTeX example to use latest version
fd4508645 Improve link render hook performance
23aeb5bd0 Update purgecss example
f7ef83e56 Refer each Hugo Pipe page to the corresponding function
81b91ef4e Remove related pages from pages for deprecated functions and methods
53c7627d5 Remove body from deprecated functions and methods
d9cf034c8 Consolidate css.ToCSS information
b7ed108f9 Improve js.Build example and presentation of options
86a4a5088 Improve babel example and description of options
d1874c5f5 Consistently use "edition" when referring to standard, extended, etc.
92f03a350 Revise description of privacy settings
152a92d80 Update Last.md
82a2365bd Add print-only QR code example
d22cadc25 Update mathematics.md
b8160af03 Delete page self-reference in page/type.md
ce24fe4e0 Update param.md
51cb92180 Improve description of output format template selection
78bcf358e Update Tailwind CSS npm package version to 4.0
2ca9da4af Include winget command to uninstall

git-subtree-dir: docs
git-subtree-split: d1a2519330
2025-02-13 10:40:34 +01:00
dependabot[bot] c054e18827 build(deps): bump github.com/bep/imagemeta from 0.8.3 to 0.8.4
Bumps [github.com/bep/imagemeta](https://github.com/bep/imagemeta) from 0.8.3 to 0.8.4.
- [Release notes](https://github.com/bep/imagemeta/releases)
- [Commits](https://github.com/bep/imagemeta/compare/v0.8.3...v0.8.4)

---
updated-dependencies:
- dependency-name: github.com/bep/imagemeta
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-13 09:02:59 +01:00
Joe Mooring 34dcac53bf config: Remove unused code 2025-02-13 08:40:49 +01:00
Joe Mooring ee438606dd commands: Use punctuation consistently in short description 2025-02-13 08:40:26 +01:00
Bjørn Erik Pedersen fd8b0fbf8a Upgrade to Go 1.24
Fixes #13381
2025-02-12 22:01:25 +01:00
Bjørn Erik Pedersen 9b5f786df8 Deprecate kind, lang, and path from front matter
These were added to the page meta object when we implemented "pages from data", but were not meant to be used in front matter.

That is not supported, so we might as well add validation.

Fixes #12484
2025-02-10 21:22:43 +01:00
Bjørn Erik Pedersen e6feb9e0be commands: Move the CHMOD event filter up
To prevent ghost rebuilds (from VSCode and possibly others).

Fixes #13373
2025-02-10 17:02:06 +01:00
dependabot[bot] 5e4ffa0e89 build(deps): bump golang.org/x/image from 0.22.0 to 0.24.0
Bumps [golang.org/x/image](https://github.com/golang/image) from 0.22.0 to 0.24.0.
- [Commits](https://github.com/golang/image/compare/v0.22.0...v0.24.0)

---
updated-dependencies:
- dependency-name: golang.org/x/image
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-10 12:46:06 +01:00
dependabot[bot] 0cdcc2b584 build(deps): bump golang.org/x/mod from 0.22.0 to 0.23.0
Bumps [golang.org/x/mod](https://github.com/golang/mod) from 0.22.0 to 0.23.0.
- [Commits](https://github.com/golang/mod/compare/v0.22.0...v0.23.0)

---
updated-dependencies:
- dependency-name: golang.org/x/mod
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-10 11:43:49 +01:00
dependabot[bot] a591c4406a build(deps): bump github.com/gohugoio/hashstructure from 0.3.0 to 0.5.0
Bumps [github.com/gohugoio/hashstructure](https://github.com/gohugoio/hashstructure) from 0.3.0 to 0.5.0.
- [Release notes](https://github.com/gohugoio/hashstructure/releases)
- [Commits](https://github.com/gohugoio/hashstructure/compare/v0.3.0...v0.5.0)

---
updated-dependencies:
- dependency-name: github.com/gohugoio/hashstructure
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-10 11:43:11 +01:00
dependabot[bot] 2d86a0512c build(deps): bump github.com/bep/simplecobra from 0.4.0 to 0.5.0
Bumps [github.com/bep/simplecobra](https://github.com/bep/simplecobra) from 0.4.0 to 0.5.0.
- [Release notes](https://github.com/bep/simplecobra/releases)
- [Commits](https://github.com/bep/simplecobra/compare/v0.4.0...v0.5.0)

---
updated-dependencies:
- dependency-name: github.com/bep/simplecobra
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-09 23:31:45 +01:00
Dominik Süß f02da7fbce parser: Handle org-mode filetags as slice
This adds support for filetags by slicing them according to [the org mode tag
specification](https://orgmode.org/guide/Tags.html).

Can be used to create taxonomies based on org-mode tags
2025-02-09 22:40:28 +01:00
dependabot[bot] 22ee0918f3 build(deps): bump github.com/aws/aws-sdk-go-v2/service/cloudfront
Bumps [github.com/aws/aws-sdk-go-v2/service/cloudfront](https://github.com/aws/aws-sdk-go-v2) from 1.41.0 to 1.44.9.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Changelog](https://github.com/aws/aws-sdk-go-v2/blob/main/changelog-template.json)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/service/s3/v1.41.0...service/macie2/v1.44.9)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/service/cloudfront
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-08 15:46:45 +01:00
dependabot[bot] b50ab04031 build(deps): bump github.com/aws/aws-sdk-go-v2 from 1.32.4 to 1.36.1
Bumps [github.com/aws/aws-sdk-go-v2](https://github.com/aws/aws-sdk-go-v2) from 1.32.4 to 1.36.1.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Changelog](https://github.com/aws/aws-sdk-go-v2/blob/main/changelog-template.json)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/v1.32.4...v1.36.1)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-08 10:33:03 +01:00
dependabot[bot] b772f0e3d2 build(deps): bump github.com/getkin/kin-openapi from 0.123.0 to 0.129.0
Bumps [github.com/getkin/kin-openapi](https://github.com/getkin/kin-openapi) from 0.123.0 to 0.129.0.
- [Release notes](https://github.com/getkin/kin-openapi/releases)
- [Commits](https://github.com/getkin/kin-openapi/compare/v0.123.0...v0.129.0)

---
updated-dependencies:
- dependency-name: github.com/getkin/kin-openapi
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-08 10:32:42 +01:00
dependabot[bot] d58c0198d3 build(deps): bump github.com/spf13/pflag from 1.0.5 to 1.0.6
Bumps [github.com/spf13/pflag](https://github.com/spf13/pflag) from 1.0.5 to 1.0.6.
- [Release notes](https://github.com/spf13/pflag/releases)
- [Commits](https://github.com/spf13/pflag/compare/v1.0.5...v1.0.6)

---
updated-dependencies:
- dependency-name: github.com/spf13/pflag
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-08 10:31:42 +01:00
Bjørn Erik Pedersen c2fb221209 Add ContentTypes to config
This is an empty struct for now, but we will most likely expand on that.

```
[contentTypes]
  [contentTypes.'text/markdown']
```

The above means that only Markdown will be considered a content type. E.g. HTML will be treated as plain text.

Fixes #12274
2025-02-08 10:31:15 +01:00
Oleksandr Redko 4245a4514d all: Remove deprecated build tags 2025-02-08 10:29:42 +01:00
Joe Mooring f0c1852978 helpers: Add Chroma styles to docs.yaml
Closes #13360
2025-02-08 00:30:05 +01:00
Joe Mooring a352e69b02 commands: Validate style argument passed to gen chromastyles
Closes #13357
2025-02-07 22:44:22 +01:00
Bjørn Erik Pedersen 1dd27be81a Update CONTRIBUTING.md 2025-02-07 22:25:19 +01:00
Bjørn Erik Pedersen eb7a5aabaa Move "print unused templates" after renderDeferred
Fixes #13355
2025-02-07 18:04:12 +01:00
Bjørn Erik Pedersen 029d1e0ced Add some more server options/improvements
New options:

* `FromHeaders`: Server header matching for redirects
* `FromRe`: Regexp with group support, i.e. it replaces $1, $2 in To with the group matches.

Note that if both `From` and `FromRe` is set, both must match.

Also

* Allow redirects to non HTML URLs as long as the Sec-Fetch-Mode is set to navigate on the request.
* Detect and stop redirect loops.

This was all done while testing out InertiaJS with Hugo. So, after this commit, this setup will support the main parts of the protocol that Inertia uses:

```toml
[server]
    [[server.headers]]
        for = '/**/inertia.json'
        [server.headers.values]
            Content-Type = 'text/html'
            X-Inertia    = 'true'
            Vary         = 'Accept'

    [[server.redirects]]
        force       = true
        from        = '/**/'
        fromRe      = "^/(.*)/$"
        fromHeaders = { "X-Inertia" = "true" }
        status      = 301
        to          = '/$1/inertia.json'
```

Unfortunately, a provider like Netlify does not support redirects matching by request headers. It should be possible with some edge function, but then again, I'm not sure that InertiaJS is a very good fit with the common Hugo use cases.

But this commit should be generally useful.
2025-02-05 18:14:15 +01:00
Bjørn Erik Pedersen e865d59844 Fix shortcode name in error message on self-closing shortcodes with no .Inner
Fixes #13344
2025-02-05 16:35:02 +01:00
hugoreleaser 377287a614 releaser: Prepare repository for 0.144.0-DEV
[ci skip]
2025-02-04 09:14:03 +00:00
hugoreleaser 0270364a34 releaser: Bump versions for release of 0.143.1
[ci skip]
2025-02-04 08:57:38 +00:00
Bjørn Erik Pedersen 760c13a7ac Fix RSS with baseURL with sub dir when render hooks is enabled
Fixes #13332
2025-02-03 19:00:12 +01:00
Oleksandr Redko 3bd73d262d mage: Simplify magefile 2025-02-03 18:34:16 +01:00
Joe Mooring 7104de83ce common/hugo: Adjust deprecation timing and message
Closes #13333
2025-02-03 18:32:30 +01:00
Bjørn Erik Pedersen 835579b338 Re-introduce the LRU-evicted identities in change set calculation
This is a follow up to db28695ff5 -- that commit dropped the cache items evicted in the LRU process. This was done as performance optimization for large Hugo sites.

That made much sense, but now there's a slight chance that we miss out on a change when rebuilding.

This commit fixes this by applying the same logic to the evicted items as if they were still in the cache. This should preserve the performance gains in db28695ff5 and close the hole for the possible false negatives.
2025-02-02 15:55:11 +01:00
hugoreleaser 05e067ced8 releaser: Prepare repository for 0.144.0-DEV
[ci skip]
2025-02-01 16:09:38 +00:00
hugoreleaser ee48d9692a releaser: Bump versions for release of 0.143.0
[ci skip]
2025-02-01 15:56:04 +00:00
Bjørn Erik Pedersen db28695ff5 Fix some server/watch rebuild issues
Two issues:

1. Fixe potential edit-loop in server/watch mode (see below)
2. Drain the cache eviction stack before we start calculating the change set. This should allow more fine grained rebuilds for bigger sites and/or in low memory situations.

The fix in 6c68142cc1 wasn't really fixing the complete problem.

In Hugo we have some steps that takes more time than others, one example being CSS building with TailwindCSS.

The symptom here is that sometimes when you:

1. Edit content or templates that does not trigger a CSS rebuild => Snappy rebuild.
2. Edit stylesheet or add a CSS class to template that triggers a CSS rebuild => relatively slow rebuild (expected)
3. Then back to content editing or template edits that should not trigger a CSS rebuild => relatively slow rebuild (not expected)

This commit fixes this by pulling the dynacache GC step up and merge it with the cache buster step.

Fixes #13316
2025-02-01 16:29:14 +01:00
Bjørn Erik Pedersen 778f0d9002 Don't re-render aliases on server rebuilds
This can lead to stale aliases when rebuilding, but that's a trade-off we need to take for snappier rebuilds on bigger sites.

Note that it should be possible to detect alias changes, but I'm not sure it's worth it.
2025-02-01 15:23:36 +01:00
Alex Shpak 13b208e2f7 tpl/tplimpl: Remove leading whitespaces produced by Youtube shortcode 2025-01-31 09:29:10 +01:00
Bjørn Erik Pedersen 329b2342f0 Fix "concurrent map iteration and map write" in pages from data
Fixes #13254
2025-01-30 19:57:09 +01:00
Joe Mooring 33b46d8a41 resources: Remove debug statement
Closes #13320
2025-01-30 11:32:57 +01:00
Bjørn Erik Pedersen 6c68142cc1 Fix TailwindCSS related server rebuild issue
Fixes #13316
2025-01-29 18:46:12 +01:00
965 changed files with 7782 additions and 16041 deletions
+2 -2
View File
@@ -4,7 +4,7 @@ parameters:
defaults: &defaults
resource_class: large
docker:
- image: bepsays/ci-hugoreleaser:1.22301.20401
- image: bepsays/ci-hugoreleaser:1.22400.20000
environment: &buildenv
GOMODCACHE: /root/project/gomodcache
version: 2
@@ -58,7 +58,7 @@ jobs:
environment:
<<: [*buildenv]
docker:
- image: bepsays/ci-hugoreleaser-linux-arm64:1.22301.20401
- image: bepsays/ci-hugoreleaser-linux-arm64:1.22400.20000
steps:
- *restore-cache
- &attach-workspace
+1 -1
View File
@@ -16,7 +16,7 @@ jobs:
test:
strategy:
matrix:
go-version: [1.22.x, 1.23.x]
go-version: [1.23.x, 1.24.x]
os: [ubuntu-latest, windows-latest] # macos disabled for now because of disk space issues.
runs-on: ${{ matrix.os }}
steps:
+1
View File
@@ -93,6 +93,7 @@ Most title/subjects should have a lower-cased prefix with a colon and one whites
* If this commit touches many packages without a common functional topic, prefix with `all:` (e.g. `all: Reformat Go code`)
* If this is a documentation update, prefix with `docs:`.
* If nothing of the above applies, just leave the prefix out.
* Note that the above excludes nouns seen in other repositories, e.g. "chore:".
Also, if your commit references one or more GitHub issues, always end your commit message body with *See #1234* or *Fixes #1234*.
Replace *1234* with the GitHub issue ID. The last example will close the issue when the commit is merged into *master*.
+62 -31
View File
@@ -34,6 +34,7 @@ A fast and flexible static site generator built with love by [bep], [spf13], and
[![Go Report Card](https://goreportcard.com/badge/github.com/gohugoio/hugo)](https://goreportcard.com/report/github.com/gohugoio/hugo)
[Website] | [Installation] | [Documentation] | [Support] | [Contributing] | <a rel="me" href="https://fosstodon.org/@gohugoio">Mastodon</a>
## Overview
Hugo is a [static site generator] written in [Go], optimized for speed and designed for flexibility. With its advanced templating system and fast asset pipelines, Hugo renders a complete site in seconds, often less.
@@ -69,6 +70,23 @@ See the [features] section of the documentation for a comprehensive summary of H
<a href="https://www.jetbrains.com/go/?utm_source=OSS&utm_medium=referral&utm_campaign=hugo" target="_blank"><img src="https://raw.githubusercontent.com/gohugoio/gohugoioTheme/master/assets/images/sponsors/goland.svg" width="200" alt="The complete IDE crafted for professional Go developers."></a>
</p>
## Editions
Hugo is available in three editions: standard, extended, and extended/deploy. While the standard edition provides core functionality, the extended and extended/deploy editions offer advanced features.
Feature|extended edition|extended/deploy edition
:--|:-:|:-:
Encode to the WebP format when [processing images]. You can decode WebP images with any edition.|:heavy_check_mark:|:heavy_check_mark:
[Transpile Sass to CSS] using the embedded LibSass transpiler. You can use the [Dart Sass] transpiler with any edition.|:heavy_check_mark:|:heavy_check_mark:
Deploy your site directly to a Google Cloud Storage bucket, an AWS S3 bucket, or an Azure Storage container. See&nbsp;[details].|:x:|:heavy_check_mark:
[dart sass]: /functions/css/sass/#dart-sass
[processing images]: /content-management/image-processing/
[transpile sass to css]: /functions/css/sass/
[details]: /hosting-and-deployment/hugo-deploy/
Unless your specific deployment needs require the extended/deploy edition, we recommend the extended edition.
## Installation
Install Hugo from a [prebuilt binary], package manager, or package repository. Please see the installation instructions for your operating system:
@@ -80,15 +98,11 @@ Install Hugo from a [prebuilt binary], package manager, or package repository. P
## Build from source
Hugo is available in two editions: standard and extended. With the extended edition you can:
- Encode to the WebP format when processing images. You can decode WebP images with either edition.
- Transpile Sass to CSS using the embedded LibSass transpiler. The extended edition is not required to use the Dart Sass transpiler.
Prerequisites to build Hugo from source:
- Standard edition: Go 1.20 or later
- Extended edition: Go 1.20 or later, and GCC
- Standard edition: Go 1.23.0 or later
- Extended edition: Go 1.23.0 or later, and GCC
- Extended/deploy edition: Go 1.23.0 or later, and GCC
Build the standard edition:
@@ -102,6 +116,12 @@ Build the extended edition:
CGO_ENABLED=1 go install -tags extended github.com/gohugoio/hugo@latest
```
Build the extended/deploy edition:
```text
CGO_ENABLED=1 go install -tags extended,withdeploy github.com/gohugoio/hugo@latest
```
## Star History
[![Star History Chart](https://api.star-history.com/svg?repos=gohugoio/hugo&type=Timeline)](https://star-history.com/#gohugoio/hugo&Timeline)
@@ -149,7 +169,9 @@ Hugo stands on the shoulders of great open source libraries. Run `hugo env --log
```text
github.com/BurntSushi/locker="v0.0.0-20171006230638-a6e239ea1c69"
github.com/alecthomas/chroma/v2="v2.14.0"
github.com/PuerkitoBio/goquery="v1.10.1"
github.com/alecthomas/chroma/v2="v2.15.0"
github.com/andybalholm/cascadia="v1.3.3"
github.com/armon/go-radix="v1.0.1-0.20221118154546-54df44f2176c"
github.com/bep/clocks="v0.5.0"
github.com/bep/debounce="v1.2.0"
@@ -158,73 +180,78 @@ github.com/bep/goat="v0.5.0"
github.com/bep/godartsass/v2="v2.3.2"
github.com/bep/golibsass="v1.2.0"
github.com/bep/gowebp="v0.3.0"
github.com/bep/imagemeta="v0.8.3"
github.com/bep/imagemeta="v0.8.4"
github.com/bep/lazycache="v0.7.0"
github.com/bep/logg="v0.4.0"
github.com/bep/mclib="v1.20400.20402"
github.com/bep/overlayfs="v0.9.2"
github.com/bep/simplecobra="v0.4.0"
github.com/bep/simplecobra="v0.5.0"
github.com/bep/tmc="v0.5.1"
github.com/cespare/xxhash/v2="v2.3.0"
github.com/clbanning/mxj/v2="v2.7.0"
github.com/cli/safeexec="v1.0.1"
github.com/cpuguy83/go-md2man/v2="v2.0.4"
github.com/disintegration/gift="v1.2.1"
github.com/dlclark/regexp2="v1.11.0"
github.com/evanw/esbuild="v0.24.0"
github.com/dlclark/regexp2="v1.11.5"
github.com/dop251/goja="v0.0.0-20250125213203-5ef83b82af17"
github.com/evanw/esbuild="v0.24.2"
github.com/fatih/color="v1.18.0"
github.com/frankban/quicktest="v1.14.6"
github.com/fsnotify/fsnotify="v1.8.0"
github.com/getkin/kin-openapi="v0.123.0"
github.com/getkin/kin-openapi="v0.129.0"
github.com/ghodss/yaml="v1.0.0"
github.com/go-openapi/jsonpointer="v0.20.2"
github.com/go-openapi/swag="v0.22.8"
github.com/go-openapi/jsonpointer="v0.21.0"
github.com/go-openapi/swag="v0.23.0"
github.com/go-sourcemap/sourcemap="v2.1.4+incompatible"
github.com/gobuffalo/flect="v1.0.3"
github.com/gobwas/glob="v0.2.3"
github.com/gohugoio/go-i18n/v2="v2.1.3-0.20230805085216-e63c13218d0e"
github.com/gohugoio/hashstructure="v0.1.0"
github.com/gohugoio/hashstructure="v0.5.0"
github.com/gohugoio/httpcache="v0.7.0"
github.com/gohugoio/hugo-goldmark-extensions/extras="v0.2.0"
github.com/gohugoio/hugo-goldmark-extensions/passthrough="v0.3.0"
github.com/gohugoio/locales="v0.14.0"
github.com/gohugoio/localescompressed="v1.0.1"
github.com/golang/freetype="v0.0.0-20170609003504-e2365dfdc4a0"
github.com/google/go-cmp="v0.6.0"
github.com/google/pprof="v0.0.0-20250208200701-d0013a598941"
github.com/gorilla/websocket="v1.5.3"
github.com/hairyhenderson/go-codeowners="v0.7.0"
github.com/hashicorp/golang-lru/v2="v2.0.7"
github.com/invopop/yaml="v0.2.0"
github.com/jdkato/prose="v1.2.1"
github.com/josharian/intern="v1.0.0"
github.com/kr/pretty="v0.3.1"
github.com/kr/text="v0.2.0"
github.com/kyokomi/emoji/v2="v2.2.13"
github.com/lucasb-eyer/go-colorful="v1.2.0"
github.com/mailru/easyjson="v0.7.7"
github.com/makeworld-the-better-one/dither/v2="v2.4.0"
github.com/marekm4/color-extractor="v1.2.1"
github.com/mattn/go-colorable="v0.1.13"
github.com/mattn/go-isatty="v0.0.20"
github.com/mattn/go-runewidth="v0.0.9"
github.com/mazznoer/csscolorparser="v0.1.5"
github.com/mitchellh/mapstructure="v1.5.1-0.20231216201459-8508981c8b6c"
github.com/mohae/deepcopy="v0.0.0-20170929034955-c48cc78d4826"
github.com/muesli/smartcrop="v0.3.0"
github.com/niklasfasching/go-org="v1.7.0"
github.com/oasdiff/yaml3="v0.0.0-20241210130736-a94c01f36349"
github.com/oasdiff/yaml="v0.0.0-20241210131133-6b86fb107d80"
github.com/olekukonko/tablewriter="v0.0.5"
github.com/pbnjay/memory="v0.0.0-20210728143218-7b4eea64cf58"
github.com/pelletier/go-toml/v2="v2.2.3"
github.com/perimeterx/marshmallow="v1.1.5"
github.com/pkg/browser="v0.0.0-20240102092130-5ac0b6a4141c"
github.com/pkg/errors="v0.9.1"
github.com/rivo/uniseg="v0.4.7"
github.com/rogpeppe/go-internal="v1.13.1"
github.com/russross/blackfriday/v2="v2.1.0"
github.com/sass/dart-sass/compiler="1.81.0"
github.com/sass/dart-sass/implementation="1.81.0"
github.com/sass/dart-sass/protocol="3.1.0"
github.com/sass/libsass="3.6.6"
github.com/spf13/afero="v1.11.0"
github.com/spf13/cast="v1.7.1"
github.com/spf13/cobra="v1.8.1"
github.com/spf13/fsync="v0.10.1"
github.com/spf13/pflag="v1.0.5"
github.com/spf13/pflag="v1.0.6"
github.com/tdewolff/minify/v2="v2.20.37"
github.com/tdewolff/parse/v2="v2.7.15"
github.com/tetratelabs/wazero="v1.8.2"
@@ -232,18 +259,22 @@ github.com/webmproject/libwebp="v1.3.2"
github.com/yuin/goldmark-emoji="v1.0.4"
github.com/yuin/goldmark="v1.7.8"
go.uber.org/automaxprocs="v1.5.3"
golang.org/x/crypto="v0.31.0"
golang.org/x/exp="v0.0.0-20221031165847-c99f073a8326"
golang.org/x/image="v0.22.0"
golang.org/x/mod="v0.22.0"
golang.org/x/net="v0.33.0"
golang.org/x/sync="v0.10.0"
golang.org/x/sys="v0.28.0"
golang.org/x/text="v0.21.0"
golang.org/x/tools="v0.28.0"
google.golang.org/protobuf="v1.35.2"
golang.org/x/crypto="v0.33.0"
golang.org/x/exp="v0.0.0-20250210185358-939b2ce775ac"
golang.org/x/image="v0.24.0"
golang.org/x/mod="v0.23.0"
golang.org/x/net="v0.35.0"
golang.org/x/sync="v0.11.0"
golang.org/x/sys="v0.30.0"
golang.org/x/text="v0.22.0"
golang.org/x/tools="v0.30.0"
golang.org/x/xerrors="v0.0.0-20240903120638-7835f813f4da"
gonum.org/v1/plot="v0.15.0"
google.golang.org/protobuf="v1.36.5"
gopkg.in/yaml.v2="v2.4.0"
gopkg.in/yaml.v3="v3.0.1"
oss.terrastruct.com/d2="v0.6.9"
oss.terrastruct.com/util-go="v0.0.0-20241005222610-44c011a04896"
rsc.io/qr="v0.2.0"
software.sslmate.com/src/go-pkcs12="v0.2.0"
```
+11 -5
View File
@@ -176,11 +176,12 @@ func (c *Cache) ClearMatching(predicatePartition func(k string, p PartitionManag
}
// ClearOnRebuild prepares the cache for a new rebuild taking the given changeset into account.
func (c *Cache) ClearOnRebuild(changeset ...identity.Identity) {
// predicate is optional and will clear any entry for which it returns true.
func (c *Cache) ClearOnRebuild(predicate func(k, v any) bool, changeset ...identity.Identity) {
g := rungroup.Run[PartitionManager](context.Background(), rungroup.Config[PartitionManager]{
NumWorkers: len(c.partitions),
Handle: func(ctx context.Context, partition PartitionManager) error {
partition.clearOnRebuild(changeset...)
partition.clearOnRebuild(predicate, changeset...)
return nil
},
})
@@ -479,7 +480,12 @@ func (p *Partition[K, V]) clearMatching(predicate func(k, v any) bool) {
})
}
func (p *Partition[K, V]) clearOnRebuild(changeset ...identity.Identity) {
func (p *Partition[K, V]) clearOnRebuild(predicate func(k, v any) bool, changeset ...identity.Identity) {
if predicate == nil {
predicate = func(k, v any) bool {
return false
}
}
opts := p.getOptions()
if opts.ClearWhen == ClearNever {
return
@@ -525,7 +531,7 @@ func (p *Partition[K, V]) clearOnRebuild(changeset ...identity.Identity) {
// Second pass needs to be done in a separate loop to catch any
// elements marked as stale in the other partitions.
p.c.DeleteFunc(func(key K, v V) bool {
if shouldDelete(key, v) {
if predicate(key, v) || shouldDelete(key, v) {
p.trace.Log(
logg.StringFunc(
func() string {
@@ -601,7 +607,7 @@ type PartitionManager interface {
adjustMaxSize(addend int) int
getMaxSize() int
getOptions() OptionsPartition
clearOnRebuild(changeset ...identity.Identity)
clearOnRebuild(predicate func(k, v any) bool, changeset ...identity.Identity)
clearMatching(predicate func(k, v any) bool)
clearStale()
}
+2 -2
View File
@@ -147,13 +147,13 @@ func TestClear(t *testing.T) {
c.Assert(cache.Keys(predicateAll), qt.HasLen, 4)
cache.ClearOnRebuild()
cache.ClearOnRebuild(nil)
// Stale items are always cleared.
c.Assert(cache.Keys(predicateAll), qt.HasLen, 2)
cache = newTestCache(t)
cache.ClearOnRebuild(identity.StringIdentity("changed"))
cache.ClearOnRebuild(nil, identity.StringIdentity("changed"))
c.Assert(cache.Keys(nil), qt.HasLen, 1)
+1 -1
View File
@@ -448,7 +448,7 @@ func (r *rootCommand) PreRun(cd, runner *simplecobra.Commandeer) error {
return err
}
// Set up the global logger early to allow info deprecations during config load.
loggers.InitGlobalLogger(r.logger.Level(), false)
loggers.SetGlobalLogger(r.logger)
r.changesFromBuild = make(chan []identity.Identity, 10)
-1
View File
@@ -12,7 +12,6 @@
// limitations under the License.
//go:build withdeploy
// +build withdeploy
package commands
-1
View File
@@ -12,7 +12,6 @@
// limitations under the License.
//go:build !withdeploy
// +build !withdeploy
// Copyright 2024 The Hugo Authors. All rights reserved.
//
+7 -2
View File
@@ -21,6 +21,7 @@ import (
"os"
"path"
"path/filepath"
"slices"
"strings"
"github.com/alecthomas/chroma/v2"
@@ -60,6 +61,10 @@ func newGenCommand() *genCommand {
See https://xyproto.github.io/splash/docs/all.html for a preview of the available styles`,
run: func(ctx context.Context, cd *simplecobra.Commandeer, r *rootCommand, args []string) error {
style = strings.ToLower(style)
if !slices.Contains(styles.Names(), style) {
return fmt.Errorf("invalid style: %s", style)
}
builder := styles.Get(style).Builder()
if highlightStyle != "" {
builder.Add(chroma.LineHighlight, highlightStyle)
@@ -144,7 +149,7 @@ url: %s
return &simpleCommand{
name: "doc",
short: "Generate Markdown documentation for the Hugo CLI.",
short: "Generate Markdown documentation for the Hugo CLI",
long: `Generate Markdown documentation for the Hugo CLI.
This command is, mostly, used to create up-to-date documentation
of Hugo's command-line interface for https://gohugo.io/.
@@ -196,7 +201,7 @@ url: %s
newDocsHelper := func() simplecobra.Commander {
return &simpleCommand{
name: "docshelper",
short: "Generate some data files for the Hugo docs.",
short: "Generate some data files for the Hugo docs",
run: func(ctx context.Context, cd *simplecobra.Commandeer, r *rootCommand, args []string) error {
r.Println("Generate docs data to", docsHelperTarget)
+14 -16
View File
@@ -663,7 +663,20 @@ func (c *hugoBuilder) handleEvents(watcher *watcher.Batcher,
var n int
for _, ev := range evs {
keep := true
if ev.Has(fsnotify.Create) || ev.Has(fsnotify.Write) {
// Write and rename operations are often followed by CHMOD.
// There may be valid use cases for rebuilding the site on CHMOD,
// but that will require more complex logic than this simple conditional.
// On OS X this seems to be related to Spotlight, see:
// https://github.com/go-fsnotify/fsnotify/issues/15
// A workaround is to put your site(s) on the Spotlight exception list,
// but that may be a little mysterious for most end users.
// So, for now, we skip reload on CHMOD.
// We do have to check for WRITE though. On slower laptops a Chmod
// could be aggregated with other important events, and we still want
// to rebuild on those
if ev.Op == fsnotify.Chmod {
keep = false
} else if ev.Has(fsnotify.Create) || ev.Has(fsnotify.Write) {
if _, err := os.Stat(ev.Name); err != nil {
keep = false
}
@@ -805,21 +818,6 @@ func (c *hugoBuilder) handleEvents(watcher *watcher.Batcher,
continue
}
// Write and rename operations are often followed by CHMOD.
// There may be valid use cases for rebuilding the site on CHMOD,
// but that will require more complex logic than this simple conditional.
// On OS X this seems to be related to Spotlight, see:
// https://github.com/go-fsnotify/fsnotify/issues/15
// A workaround is to put your site(s) on the Spotlight exception list,
// but that may be a little mysterious for most end users.
// So, for now, we skip reload on CHMOD.
// We do have to check for WRITE though. On slower laptops a Chmod
// could be aggregated with other important events, and we still want
// to rebuild on those
if ev.Op&(fsnotify.Chmod|fsnotify.Write|fsnotify.Create) == fsnotify.Chmod {
continue
}
walkAdder := func(path string, f hugofs.FileMetaInfo) error {
if f.IsDir() {
c.r.logger.Println("adding created directory to watchlist", path)
+14 -14
View File
@@ -44,16 +44,16 @@ func newModCommands() *modCommands {
npmCommand := &simpleCommand{
name: "npm",
short: "Various npm helpers.",
short: "Various npm helpers",
long: `Various npm (Node package manager) helpers.`,
commands: []simplecobra.Commander{
&simpleCommand{
name: "pack",
short: "Experimental: Prepares and writes a composite package.json file for your project.",
short: "Experimental: Prepares and writes a composite package.json file for your project",
long: `Prepares and writes a composite package.json file for your project.
On first run it creates a "package.hugo.json" in the project root if not already there. This file will be used as a template file
with the base dependency set.
with the base dependency set.
This set will be merged with all "package.hugo.json" files found in the dependency tree, picking the version closest to the project.
@@ -80,12 +80,12 @@ so this may/will change in future versions of Hugo.
commands: []simplecobra.Commander{
&simpleCommand{
name: "init",
short: "Initialize this project as a Hugo Module.",
short: "Initialize this project as a Hugo Module",
long: `Initialize this project as a Hugo Module.
It will try to guess the module path, but you may help by passing it as an argument, e.g:
hugo mod init github.com/gohugoio/testshortcodes
Note that Hugo Modules supports multi-module projects, so you can initialize a Hugo Module
inside a subfolder on GitHub, as one example.
`,
@@ -111,7 +111,7 @@ so this may/will change in future versions of Hugo.
},
&simpleCommand{
name: "verify",
short: "Verify dependencies.",
short: "Verify dependencies",
long: `Verify checks that the dependencies of the current module, which are stored in a local downloaded source cache, have not been modified since being downloaded.`,
withc: func(cmd *cobra.Command, r *rootCommand) {
cmd.ValidArgsFunction = cobra.NoFileCompletions
@@ -129,7 +129,7 @@ so this may/will change in future versions of Hugo.
},
&simpleCommand{
name: "graph",
short: "Print a module dependency graph.",
short: "Print a module dependency graph",
long: `Print a module dependency graph with information about module status (disabled, vendored).
Note that for vendored modules, that is the version listed and not the one from go.mod.
`,
@@ -149,7 +149,7 @@ Note that for vendored modules, that is the version listed and not the one from
},
&simpleCommand{
name: "clean",
short: "Delete the Hugo Module cache for the current project.",
short: "Delete the Hugo Module cache for the current project",
long: `Delete the Hugo Module cache for the current project.`,
withc: func(cmd *cobra.Command, r *rootCommand) {
cmd.ValidArgsFunction = cobra.NoFileCompletions
@@ -175,7 +175,7 @@ Note that for vendored modules, that is the version listed and not the one from
},
&simpleCommand{
name: "tidy",
short: "Remove unused entries in go.mod and go.sum.",
short: "Remove unused entries in go.mod and go.sum",
withc: func(cmd *cobra.Command, r *rootCommand) {
cmd.ValidArgsFunction = cobra.NoFileCompletions
applyLocalFlagsBuildConfig(cmd, r)
@@ -190,7 +190,7 @@ Note that for vendored modules, that is the version listed and not the one from
},
&simpleCommand{
name: "vendor",
short: "Vendor all module dependencies into the _vendor directory.",
short: "Vendor all module dependencies into the _vendor directory",
long: `Vendor all module dependencies into the _vendor directory.
If a module is vendored, that is where Hugo will look for it's dependencies.
`,
@@ -209,16 +209,16 @@ Note that for vendored modules, that is the version listed and not the one from
&simpleCommand{
name: "get",
short: "Resolves dependencies in your current Hugo Project.",
short: "Resolves dependencies in your current Hugo project",
long: `
Resolves dependencies in your current Hugo Project.
Resolves dependencies in your current Hugo project.
Some examples:
Install the latest version possible for a given module:
hugo mod get github.com/gohugoio/testshortcodes
Install a specific version:
hugo mod get github.com/gohugoio/testshortcodes@v0.3.0
+1 -1
View File
@@ -32,7 +32,7 @@ func newReleaseCommand() simplecobra.Commander {
return &simpleCommand{
name: "release",
short: "Release a new version of Hugo.",
short: "Release a new version of Hugo",
run: func(ctx context.Context, cd *simplecobra.Commandeer, r *rootCommand, args []string) error {
rel, err := releaser.New(skipPush, try, step)
if err != nil {
+75 -52
View File
@@ -84,6 +84,10 @@ const (
configChangeGoWork = "go work file"
)
const (
hugoHeaderRedirect = "X-Hugo-Redirect"
)
func newHugoBuilder(r *rootCommand, s *serverCommand, onConfigLoaded ...func(reloaded bool) error) *hugoBuilder {
var visitedURLs *types.EvictingQueue[string]
if s != nil && !s.disableFastRender {
@@ -115,7 +119,7 @@ func newServerCommand() *serverCommand {
commands: []simplecobra.Commander{
&simpleCommand{
name: "trust",
short: "Install the local CA in the system trust store.",
short: "Install the local CA in the system trust store",
run: func(ctx context.Context, cd *simplecobra.Commandeer, r *rootCommand, args []string) error {
action := "-install"
if uninstall {
@@ -307,67 +311,65 @@ func (f *fileServer) createEndpoint(i int) (*http.ServeMux, net.Listener, string
w.Header().Set(header.Key, header.Value)
}
if redirect := serverConfig.MatchRedirect(requestURI); !redirect.IsZero() {
// fullName := filepath.Join(dir, filepath.FromSlash(path.Clean("/"+name)))
doRedirect := true
// This matches Netlify's behavior and is needed for SPA behavior.
// See https://docs.netlify.com/routing/redirects/rewrites-proxies/
if !redirect.Force {
path := filepath.Clean(strings.TrimPrefix(requestURI, baseURL.Path()))
if root != "" {
path = filepath.Join(root, path)
}
var fs afero.Fs
f.c.withConf(func(conf *commonConfig) {
fs = conf.fs.PublishDirServer
})
fi, err := fs.Stat(path)
if err == nil {
if fi.IsDir() {
// There will be overlapping directories, so we
// need to check for a file.
_, err = fs.Stat(filepath.Join(path, "index.html"))
doRedirect = err != nil
} else {
doRedirect = false
if canRedirect(requestURI, r) {
if redirect := serverConfig.MatchRedirect(requestURI, r.Header); !redirect.IsZero() {
doRedirect := true
// This matches Netlify's behavior and is needed for SPA behavior.
// See https://docs.netlify.com/routing/redirects/rewrites-proxies/
if !redirect.Force {
path := filepath.Clean(strings.TrimPrefix(requestURI, baseURL.Path()))
if root != "" {
path = filepath.Join(root, path)
}
}
}
var fs afero.Fs
f.c.withConf(func(conf *commonConfig) {
fs = conf.fs.PublishDirServer
})
fi, err := fs.Stat(path)
if doRedirect {
switch redirect.Status {
case 404:
w.WriteHeader(404)
file, err := fs.Open(strings.TrimPrefix(redirect.To, baseURL.Path()))
if err == nil {
defer file.Close()
io.Copy(w, file)
} else {
fmt.Fprintln(w, "<h1>Page Not Found</h1>")
if fi.IsDir() {
// There will be overlapping directories, so we
// need to check for a file.
_, err = fs.Stat(filepath.Join(path, "index.html"))
doRedirect = err != nil
} else {
doRedirect = false
}
}
return
case 200:
if r2 := f.rewriteRequest(r, strings.TrimPrefix(redirect.To, baseURL.Path())); r2 != nil {
requestURI = redirect.To
r = r2
}
default:
w.Header().Set("Content-Type", "")
http.Redirect(w, r, redirect.To, redirect.Status)
return
}
if doRedirect {
w.Header().Set(hugoHeaderRedirect, "true")
switch redirect.Status {
case 404:
w.WriteHeader(404)
file, err := fs.Open(strings.TrimPrefix(redirect.To, baseURL.Path()))
if err == nil {
defer file.Close()
io.Copy(w, file)
} else {
fmt.Fprintln(w, "<h1>Page Not Found</h1>")
}
return
case 200:
if r2 := f.rewriteRequest(r, strings.TrimPrefix(redirect.To, baseURL.Path())); r2 != nil {
requestURI = redirect.To
r = r2
}
default:
w.Header().Set("Content-Type", "")
http.Redirect(w, r, redirect.To, redirect.Status)
return
}
}
}
}
if f.c.fastRenderMode && f.c.errState.buildErr() == nil {
// Sec-Fetch-Mode should be sent by all recent browser versions, see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Sec-Fetch-Mode#navigate
// Fall back to the file extension if not set.
// The main take here is that we don't want to have CSS/JS files etc. partake in this logic.
if r.Header.Get("Sec-Fetch-Mode") == "navigate" || strings.HasSuffix(requestURI, "/") || strings.HasSuffix(requestURI, "html") || strings.HasSuffix(requestURI, "htm") {
if isNavigation(requestURI, r) {
if !f.c.visitedURLs.Contains(requestURI) {
// If not already on stack, re-render that single page.
if err := f.c.partialReRender(requestURI); err != nil {
@@ -1233,3 +1235,24 @@ func formatByteCount(b uint64) string {
return fmt.Sprintf("%.1f %cB",
float64(b)/float64(div), "kMGTPE"[exp])
}
func canRedirect(requestURIWithoutQuery string, r *http.Request) bool {
if r.Header.Get(hugoHeaderRedirect) != "" {
return false
}
return isNavigation(requestURIWithoutQuery, r)
}
// Sec-Fetch-Mode should be sent by all recent browser versions, see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Sec-Fetch-Mode#navigate
// Fall back to the file extension if not set.
// The main take here is that we don't want to have CSS/JS files etc. partake in this logic.
func isNavigation(requestURIWithoutQuery string, r *http.Request) bool {
return r.Header.Get("Sec-Fetch-Mode") == "navigate" || isPropablyHTMLRequest(requestURIWithoutQuery)
}
func isPropablyHTMLRequest(requestURIWithoutQuery string) bool {
if strings.HasSuffix(requestURIWithoutQuery, "/") || strings.HasSuffix(requestURIWithoutQuery, "html") || strings.HasSuffix(requestURIWithoutQuery, "htm") {
return true
}
return !strings.Contains(requestURIWithoutQuery, ".")
}
+10
View File
@@ -74,6 +74,16 @@ func IsTruthful(in any) bool {
}
}
// IsMap reports whether v is a map.
func IsMap(v any) bool {
return reflect.ValueOf(v).Kind() == reflect.Map
}
// IsSlice reports whether v is a slice.
func IsSlice(v any) bool {
return reflect.ValueOf(v).Kind() == reflect.Slice
}
var zeroType = reflect.TypeOf((*types.Zeroer)(nil)).Elem()
// IsTruthfulValue returns whether the given value has a meaningful truth value.
+14 -5
View File
@@ -414,11 +414,20 @@ func Deprecate(item, alternative string, version string) {
DeprecateLevel(item, alternative, version, level)
}
// DeprecateLevelMin informs about a deprecation starting at the given version, but with a minimum log level.
func DeprecateLevelMin(item, alternative string, version string, minLevel logg.Level) {
level := deprecationLogLevelFromVersion(version)
if level < minLevel {
level = minLevel
}
DeprecateLevel(item, alternative, version, level)
}
// DeprecateLevel informs about a deprecation logging at the given level.
func DeprecateLevel(item, alternative, version string, level logg.Level) {
var msg string
if level == logg.LevelError {
msg = fmt.Sprintf("%s was deprecated in Hugo %s and will be removed in Hugo %s. %s", item, version, CurrentVersion.Next().ReleaseVersion(), alternative)
msg = fmt.Sprintf("%s was deprecated in Hugo %s and subsequently removed. %s", item, version, alternative)
} else {
msg = fmt.Sprintf("%s was deprecated in Hugo %s and will be removed in a future release. %s", item, version, alternative)
}
@@ -434,11 +443,11 @@ func deprecationLogLevelFromVersion(ver string) logg.Level {
to := CurrentVersion
minorDiff := to.Minor - from.Minor
switch {
case minorDiff >= 12:
// Start failing the build after about a year.
case minorDiff >= 15:
// Start failing the build after about 15 months.
return logg.LevelError
case minorDiff >= 6:
// Start printing warnings after about six months.
case minorDiff >= 3:
// Start printing warnings after about 3 months.
return logg.LevelWarn
default:
return logg.LevelInfo
+4 -4
View File
@@ -57,11 +57,11 @@ func TestDeprecationLogLevelFromVersion(t *testing.T) {
c.Assert(deprecationLogLevelFromVersion("0.55.0"), qt.Equals, logg.LevelError)
ver := CurrentVersion
c.Assert(deprecationLogLevelFromVersion(ver.String()), qt.Equals, logg.LevelInfo)
ver.Minor -= 1
c.Assert(deprecationLogLevelFromVersion(ver.String()), qt.Equals, logg.LevelInfo)
ver.Minor -= 6
ver.Minor -= 3
c.Assert(deprecationLogLevelFromVersion(ver.String()), qt.Equals, logg.LevelWarn)
ver.Minor -= 6
ver.Minor -= 4
c.Assert(deprecationLogLevelFromVersion(ver.String()), qt.Equals, logg.LevelWarn)
ver.Minor -= 13
c.Assert(deprecationLogLevelFromVersion(ver.String()), qt.Equals, logg.LevelError)
// Added just to find the threshold for where we can remove deprecated items.
-1
View File
@@ -12,7 +12,6 @@
// limitations under the License.
//go:build extended
// +build extended
package hugo
-1
View File
@@ -12,7 +12,6 @@
// limitations under the License.
//go:build !extended
// +build !extended
package hugo
-1
View File
@@ -12,7 +12,6 @@
// limitations under the License.
//go:build withdeploy
// +build withdeploy
package hugo
-1
View File
@@ -12,7 +12,6 @@
// limitations under the License.
//go:build !withdeploy
// +build !withdeploy
package hugo
+1 -1
View File
@@ -17,7 +17,7 @@ package hugo
// This should be the only one.
var CurrentVersion = Version{
Major: 0,
Minor: 143,
Minor: 145,
PatchLevel: 0,
Suffix: "-DEV",
}
+10 -2
View File
@@ -21,7 +21,15 @@ import (
"github.com/bep/logg"
)
func InitGlobalLogger(level logg.Level, panicOnWarnings bool) {
// SetGlobalLogger sets the global logger.
// This is used in a few places in Hugo, e.g. deprecated functions.
func SetGlobalLogger(logger Logger) {
logMu.Lock()
defer logMu.Unlock()
log = logger
}
func initGlobalLogger(level logg.Level, panicOnWarnings bool) {
logMu.Lock()
defer logMu.Unlock()
var logHookLast func(e *logg.Entry) error
@@ -50,5 +58,5 @@ func Log() Logger {
var log Logger
func init() {
InitGlobalLogger(logg.LevelWarn, false)
initGlobalLogger(logg.LevelWarn, false)
}
+4
View File
@@ -73,10 +73,14 @@ func TestPrepareParams(t *testing.T) {
for i, test := range tests {
t.Run(fmt.Sprint(i), func(t *testing.T) {
// PrepareParams modifies input.
prepareClone := PrepareParamsClone(test.input)
PrepareParams(test.input)
if !reflect.DeepEqual(test.expected, test.input) {
t.Errorf("[%d] Expected\n%#v, got\n%#v\n", i, test.expected, test.input)
}
if !reflect.DeepEqual(test.expected, prepareClone) {
t.Errorf("[%d] Expected\n%#v, got\n%#v\n", i, test.expected, prepareClone)
}
})
}
}
+40 -1
View File
@@ -303,7 +303,7 @@ func toMergeStrategy(v any) ParamsMergeStrategy {
}
// PrepareParams
// * makes all the keys in the given map lower cased and will do so
// * makes all the keys in the given map lower cased and will do so recursively.
// * This will modify the map given.
// * Any nested map[interface{}]interface{}, map[string]interface{},map[string]string will be converted to Params.
// * Any _merge value will be converted to proper type and value.
@@ -343,3 +343,42 @@ func PrepareParams(m Params) {
}
}
}
// PrepareParamsClone is like PrepareParams, but it does not modify the input.
func PrepareParamsClone(m Params) Params {
m2 := make(Params)
for k, v := range m {
var retyped bool
lKey := strings.ToLower(k)
if lKey == MergeStrategyKey {
v = toMergeStrategy(v)
retyped = true
} else {
switch vv := v.(type) {
case map[any]any:
var p Params = cast.ToStringMap(v)
v = PrepareParamsClone(p)
retyped = true
case map[string]any:
var p Params = v.(map[string]any)
v = PrepareParamsClone(p)
retyped = true
case map[string]string:
p := make(Params)
for k, v := range vv {
p[k] = v
}
v = p
PrepareParams(p)
retyped = true
}
}
if retyped || k != lKey {
m2[lKey] = v
} else {
m2[k] = v
}
}
return m2
}
+13 -3
View File
@@ -128,6 +128,9 @@ type Config struct {
// <docsmeta>{"identifiers": ["markup"] }</docsmeta>
Markup markup_config.Config `mapstructure:"-"`
// ContentTypes are the media types that's considered content in Hugo.
ContentTypes *config.ConfigNamespace[map[string]media.ContentTypeConfig, media.ContentTypes] `mapstructure:"-"`
// The mediatypes configuration section maps the MIME type (a string) to a configuration object for that type.
// <docsmeta>{"identifiers": ["mediatypes"], "refs": ["types:media:type"] }</docsmeta>
MediaTypes *config.ConfigNamespace[map[string]media.MediaTypeConfig, media.Types] `mapstructure:"-"`
@@ -424,6 +427,15 @@ func (c *Config) CompileConfig(logger loggers.Logger) error {
c.Services.X.DisableInlineCSS = c.Services.Twitter.DisableInlineCSS
}
// Legacy permalink tokens
vs := fmt.Sprintf("%v", c.Permalinks)
if strings.Contains(vs, ":filename") {
hugo.Deprecate("the \":filename\" permalink token", "Use \":contentbasename\" instead.", "0.144.0")
}
if strings.Contains(vs, ":slugorfilename") {
hugo.Deprecate("the \":slugorfilename\" permalink token", "Use \":slugorcontentbasename\" instead.", "0.144.0")
}
c.C = &ConfigCompiled{
Timeout: timeout,
BaseURL: baseURL,
@@ -433,7 +445,6 @@ func (c *Config) CompileConfig(logger loggers.Logger) error {
IgnoredLogs: ignoredLogIDs,
KindOutputFormats: kindOutputFormats,
DefaultOutputFormat: defaultOutputFormat,
ContentTypes: media.DefaultContentTypes.FromTypes(c.MediaTypes.Config),
CreateTitle: helpers.GetTitleFunc(c.TitleCaseStyle),
IsUglyURLSection: isUglyURL,
IgnoreFile: ignoreFile,
@@ -471,7 +482,6 @@ type ConfigCompiled struct {
ServerInterface string
KindOutputFormats map[string]output.Formats
DefaultOutputFormat output.Format
ContentTypes media.ContentTypes
DisabledKinds map[string]bool
DisabledLanguages map[string]bool
IgnoredLogs map[string]bool
@@ -839,7 +849,7 @@ func (c *Configs) Init() error {
c.Languages = languages
c.LanguagesDefaultFirst = languagesDefaultFirst
c.ContentPathParser = &paths.PathParser{LanguageIndex: languagesDefaultFirst.AsIndexSet(), IsLangDisabled: c.Base.IsLangDisabled, IsContentExt: c.Base.C.ContentTypes.IsContentSuffix}
c.ContentPathParser = &paths.PathParser{LanguageIndex: languagesDefaultFirst.AsIndexSet(), IsLangDisabled: c.Base.IsLangDisabled, IsContentExt: c.Base.ContentTypes.Config.IsContentSuffix}
c.configLangs = make([]config.AllProvider, len(c.Languages))
for i, l := range c.LanguagesDefaultFirst {
+20 -1
View File
@@ -7,6 +7,7 @@ import (
qt "github.com/frankban/quicktest"
"github.com/gohugoio/hugo/config/allconfig"
"github.com/gohugoio/hugo/hugolib"
"github.com/gohugoio/hugo/media"
)
func TestDirsMount(t *testing.T) {
@@ -97,7 +98,7 @@ suffixes = ["html", "xhtml"]
b := hugolib.Test(t, files)
conf := b.H.Configs.Base
contentTypes := conf.C.ContentTypes
contentTypes := conf.ContentTypes.Config
b.Assert(contentTypes.HTML.Suffixes(), qt.DeepEquals, []string{"html", "xhtml"})
b.Assert(contentTypes.Markdown.Suffixes(), qt.DeepEquals, []string{"md", "mdown", "markdown"})
@@ -215,3 +216,21 @@ weight = 3
b := hugolib.Test(t, files)
b.Assert(b.H.Configs.LanguageConfigSlice[0].Title, qt.Equals, `TITLE_DE`)
}
func TestContentTypesDefault(t *testing.T) {
files := `
-- hugo.toml --
baseURL = "https://example.com"
`
b := hugolib.Test(t, files)
ct := b.H.Configs.Base.ContentTypes
c := ct.Config
s := ct.SourceStructure.(map[string]media.ContentTypeConfig)
b.Assert(c.IsContentFile("foo.md"), qt.Equals, true)
b.Assert(len(s), qt.Equals, 6)
}
+9
View File
@@ -163,6 +163,15 @@ var allDecoderSetups = map[string]decodeWeight{
return err
},
},
"contenttypes": {
key: "contenttypes",
weight: 100, // This needs to be decoded after media types.
decode: func(d decodeWeight, p decodeConfig) error {
var err error
p.c.ContentTypes, err = media.DecodeContentTypes(p.p.GetStringMap(d.key), p.c.MediaTypes.Config)
return err
},
},
"mediatypes": {
key: "mediatypes",
decode: func(d decodeWeight, p decodeConfig) error {
+1 -1
View File
@@ -145,7 +145,7 @@ func (c ConfigLanguage) NewIdentityManager(name string, opts ...identity.Manager
}
func (c ConfigLanguage) ContentTypes() config.ContentTypesProvider {
return c.config.C.ContentTypes
return c.config.ContentTypes.Config
}
// GetConfigSection is mostly used in tests. The switch statement isn't complete, but what's in use.
+1 -1
View File
@@ -91,7 +91,7 @@ func LoadConfig(d ConfigSourceDescriptor) (*Configs, error) {
return nil, fmt.Errorf("failed to init config: %w", err)
}
loggers.InitGlobalLogger(d.Logger.Level(), configs.Base.PanicOnWarning)
loggers.SetGlobalLogger(d.Logger)
return configs, nil
}
+94 -23
View File
@@ -15,6 +15,7 @@ package config
import (
"fmt"
"net/http"
"regexp"
"sort"
"strings"
@@ -226,7 +227,22 @@ type Server struct {
Redirects []Redirect
compiledHeaders []glob.Glob
compiledRedirects []glob.Glob
compiledRedirects []redirect
}
type redirect struct {
from glob.Glob
fromRe *regexp.Regexp
headers map[string]glob.Glob
}
func (r redirect) matchHeader(header http.Header) bool {
for k, v := range r.headers {
if !v.Match(header.Get(k)) {
return false
}
}
return true
}
func (s *Server) CompileConfig(logger loggers.Logger) error {
@@ -234,10 +250,41 @@ func (s *Server) CompileConfig(logger loggers.Logger) error {
return nil
}
for _, h := range s.Headers {
s.compiledHeaders = append(s.compiledHeaders, glob.MustCompile(h.For))
g, err := glob.Compile(h.For)
if err != nil {
return fmt.Errorf("failed to compile Headers glob %q: %w", h.For, err)
}
s.compiledHeaders = append(s.compiledHeaders, g)
}
for _, r := range s.Redirects {
s.compiledRedirects = append(s.compiledRedirects, glob.MustCompile(r.From))
if r.From == "" && r.FromRe == "" {
return fmt.Errorf("redirects must have either From or FromRe set")
}
rd := redirect{
headers: make(map[string]glob.Glob),
}
if r.From != "" {
g, err := glob.Compile(r.From)
if err != nil {
return fmt.Errorf("failed to compile Redirect glob %q: %w", r.From, err)
}
rd.from = g
}
if r.FromRe != "" {
re, err := regexp.Compile(r.FromRe)
if err != nil {
return fmt.Errorf("failed to compile Redirect regexp %q: %w", r.FromRe, err)
}
rd.fromRe = re
}
for k, v := range r.FromHeaders {
g, err := glob.Compile(v)
if err != nil {
return fmt.Errorf("failed to compile Redirect header glob %q: %w", v, err)
}
rd.headers[k] = g
}
s.compiledRedirects = append(s.compiledRedirects, rd)
}
return nil
@@ -266,22 +313,42 @@ func (s *Server) MatchHeaders(pattern string) []types.KeyValueStr {
return matches
}
func (s *Server) MatchRedirect(pattern string) Redirect {
func (s *Server) MatchRedirect(pattern string, header http.Header) Redirect {
if s.compiledRedirects == nil {
return Redirect{}
}
pattern = strings.TrimSuffix(pattern, "index.html")
for i, g := range s.compiledRedirects {
for i, r := range s.compiledRedirects {
redir := s.Redirects[i]
// No redirect to self.
if redir.To == pattern {
return Redirect{}
var found bool
if r.from != nil {
if r.from.Match(pattern) {
found = header == nil || r.matchHeader(header)
// We need to do regexp group replacements if needed.
}
}
if g.Match(pattern) {
if r.fromRe != nil {
m := r.fromRe.FindStringSubmatch(pattern)
if m != nil {
if !found {
found = header == nil || r.matchHeader(header)
}
if found {
// Replace $1, $2 etc. in To.
for i, g := range m[1:] {
redir.To = strings.ReplaceAll(redir.To, fmt.Sprintf("$%d", i+1), g)
}
}
}
}
if found {
return redir
}
}
@@ -295,8 +362,22 @@ type Headers struct {
}
type Redirect struct {
// From is the Glob pattern to match.
// One of From or FromRe must be set.
From string
To string
// FromRe is the regexp to match.
// This regexp can contain group matches (e.g. $1) that can be used in the To field.
// One of From or FromRe must be set.
FromRe string
// To is the target URL.
To string
// Headers to match for the redirect.
// This maps the HTTP header name to a Glob pattern with values to match.
// If the map is empty, the redirect will always be triggered.
FromHeaders map[string]string
// HTTP status code to use for the redirect.
// A status code of 200 will trigger a URL rewrite.
@@ -369,7 +450,7 @@ func (c *CacheBuster) CompileConfig(logger loggers.Logger) error {
}
func (r Redirect) IsZero() bool {
return r.From == ""
return r.From == "" && r.FromRe == ""
}
const (
@@ -383,17 +464,7 @@ func DecodeServer(cfg Provider) (Server, error) {
_ = mapstructure.WeakDecode(cfg.GetStringMap("server"), s)
for i, redir := range s.Redirects {
// Get it in line with the Hugo server for OK responses.
// We currently treat the 404 as a special case, they are always "ugly", so keep them as is.
if redir.Status != 404 {
redir.To = strings.TrimSuffix(redir.To, "index.html")
if !strings.HasPrefix(redir.To, "https") && !strings.HasSuffix(redir.To, "/") {
// 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 Server{}, fmt.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)
}
}
redir.To = strings.TrimSuffix(redir.To, "index.html")
s.Redirects[i] = redir
}
@@ -401,7 +472,7 @@ func DecodeServer(cfg Provider) (Server, error) {
// Set up a default redirect for 404s.
s.Redirects = []Redirect{
{
From: "**",
From: "/**",
To: "/404.html",
Status: 404,
},
+41 -35
View File
@@ -71,7 +71,28 @@ X-Content-Type-Options = "nosniff"
[[server.redirects]]
from = "/foo/**"
to = "/foo/index.html"
to = "/baz/index.html"
status = 200
[[server.redirects]]
from = "/loop/**"
to = "/loop/foo/"
status = 200
[[server.redirects]]
from = "/b/**"
fromRe = "/b/(.*)/"
to = "/baz/$1/"
status = 200
[[server.redirects]]
fromRe = "/c/(.*)/"
to = "/boo/$1/"
status = 200
[[server.redirects]]
fromRe = "/d/(.*)/"
to = "/boo/$1/"
status = 200
[[server.redirects]]
@@ -79,11 +100,6 @@ from = "/google/**"
to = "https://google.com/"
status = 301
[[server.redirects]]
from = "/**"
to = "/default/index.html"
status = 301
`, "toml")
@@ -100,45 +116,35 @@ status = 301
{Key: "X-XSS-Protection", Value: "1; mode=block"},
})
c.Assert(s.MatchRedirect("/foo/bar/baz"), qt.DeepEquals, Redirect{
c.Assert(s.MatchRedirect("/foo/bar/baz", nil), qt.DeepEquals, Redirect{
From: "/foo/**",
To: "/foo/",
To: "/baz/",
Status: 200,
})
c.Assert(s.MatchRedirect("/someother"), qt.DeepEquals, Redirect{
From: "/**",
To: "/default/",
Status: 301,
c.Assert(s.MatchRedirect("/foo/bar/", nil), qt.DeepEquals, Redirect{
From: "/foo/**",
To: "/baz/",
Status: 200,
})
c.Assert(s.MatchRedirect("/google/foo"), qt.DeepEquals, Redirect{
c.Assert(s.MatchRedirect("/b/c/", nil), qt.DeepEquals, Redirect{
From: "/b/**",
FromRe: "/b/(.*)/",
To: "/baz/c/",
Status: 200,
})
c.Assert(s.MatchRedirect("/c/d/", nil).To, qt.Equals, "/boo/d/")
c.Assert(s.MatchRedirect("/c/d/e/", nil).To, qt.Equals, "/boo/d/e/")
c.Assert(s.MatchRedirect("/someother", nil), qt.DeepEquals, Redirect{})
c.Assert(s.MatchRedirect("/google/foo", nil), qt.DeepEquals, Redirect{
From: "/google/**",
To: "https://google.com/",
Status: 301,
})
// No redirect loop, please.
c.Assert(s.MatchRedirect("/default/index.html"), qt.DeepEquals, Redirect{})
c.Assert(s.MatchRedirect("/default/"), qt.DeepEquals, Redirect{})
for _, errorCase := range []string{
`[[server.redirects]]
from = "/**"
to = "/file"
status = 301`,
`[[server.redirects]]
from = "/**"
to = "/foo/file.html"
status = 301`,
} {
cfg, err := FromConfigString(errorCase, "toml")
c.Assert(err, qt.IsNil)
_, err = DecodeServer(cfg)
c.Assert(err, qt.Not(qt.IsNil))
}
}
func TestBuildConfigCacheBusters(t *testing.T) {
-37
View File
@@ -15,7 +15,6 @@ package config
import (
"fmt"
"sort"
"strings"
"sync"
@@ -26,42 +25,6 @@ import (
"github.com/gohugoio/hugo/common/maps"
)
var (
// ConfigRootKeysSet contains all of the config map root keys.
ConfigRootKeysSet = map[string]bool{
"build": true,
"caches": true,
"cascade": true,
"frontmatter": true,
"languages": true,
"imaging": true,
"markup": true,
"mediatypes": true,
"menus": true,
"minify": true,
"module": true,
"outputformats": true,
"params": true,
"permalinks": true,
"related": true,
"sitemap": true,
"privacy": true,
"security": true,
"taxonomies": true,
}
// ConfigRootKeys is a sorted version of ConfigRootKeysSet.
ConfigRootKeys []string
)
func init() {
for k := range ConfigRootKeysSet {
ConfigRootKeys = append(ConfigRootKeys, k)
}
sort.Strings(ConfigRootKeys)
}
// New creates a Provider backed by an empty maps.Params.
func New() Provider {
return &defaultConfigProvider{
+2 -6
View File
@@ -36,10 +36,6 @@ respectDoNotTrack = true
[privacy.instagram]
disable = true
simple = true
[privacy.twitter]
disable = true
enableDNT = true
simple = true
[privacy.x]
disable = true
enableDNT = true
@@ -63,8 +59,8 @@ simple = true
got := []bool{
pc.Disqus.Disable, pc.GoogleAnalytics.Disable,
pc.GoogleAnalytics.RespectDoNotTrack, pc.Instagram.Disable,
pc.Instagram.Simple, pc.Twitter.Disable, pc.Twitter.EnableDNT,
pc.Twitter.Simple, pc.Vimeo.Disable, pc.Vimeo.EnableDNT, pc.Vimeo.Simple,
pc.Instagram.Simple,
pc.Vimeo.Disable, pc.Vimeo.EnableDNT, pc.Vimeo.Simple,
pc.YouTube.PrivacyEnhanced, pc.YouTube.Disable, pc.X.Disable, pc.X.EnableDNT,
pc.X.Simple,
}
-1
View File
@@ -12,7 +12,6 @@
// limitations under the License.
//go:build withdeploy
// +build withdeploy
package deploy
-1
View File
@@ -12,7 +12,6 @@
// limitations under the License.
//go:build withdeploy
// +build withdeploy
package deploy
-1
View File
@@ -12,7 +12,6 @@
// limitations under the License.
//go:build !solaris && withdeploy
// +build !solaris,withdeploy
package deploy
-1
View File
@@ -12,7 +12,6 @@
// limitations under the License.
//go:build withdeploy
// +build withdeploy
package deploy
-1
View File
@@ -12,7 +12,6 @@
// limitations under the License.
//go:build withdeploy
// +build withdeploy
package deployconfig
-1
View File
@@ -12,7 +12,6 @@
// limitations under the License.
//go:build withdeploy
// +build withdeploy
package deploy
+13
View File
@@ -0,0 +1,13 @@
# Config file for codespell.
# https://github.com/codespell-project/codespell#using-a-config-file
[codespell]
# Comma separated list of dirs to be skipped.
skip = _vendor,.cspell.json,chroma.css,chroma_dark.css
# Comma separated list of words to be ignored. Words must be lowercased.
ignore-words-list = abl,edn,te,ue,trys,januar,womens,crossreferences
# Check file names as well.
check-filenames = true
+5
View File
@@ -68,6 +68,7 @@
"# ----------------------------------------------------------------------",
"# cspell: ignore hugo terminology",
"# ----------------------------------------------------------------------",
"alignx",
"attrlink",
"canonify",
"codeowners",
@@ -85,6 +86,7 @@
"stringifier",
"struct",
"toclevels",
"unmarshal",
"unpublishdate",
"zgotmplz",
"# ----------------------------------------------------------------------",
@@ -158,6 +160,8 @@
"# cspell: ignore miscellaneous",
"# ----------------------------------------------------------------------",
"achristie",
"ccpa",
"crpa",
"ddmaurier",
"dring",
"fleqn",
@@ -171,6 +175,7 @@
"rsmith",
"tdewolff",
"tjones",
"vcard",
"wcag",
"xfeff"
]
+1
View File
@@ -0,0 +1 @@
blank_issues_enabled: false
+6
View File
@@ -0,0 +1,6 @@
---
name: Default
about: This is the default issue template.
labels:
- NeedsTriage
---
+5
View File
@@ -20,3 +20,8 @@ jobs:
incremental_files_only: true
inline: warning
strict: false
- uses: codespell-project/actions-codespell@v2
with:
check_filenames: true
check_hidden: true
# by default, codespell uses configuration from the .codespellrc
+9 -6
View File
@@ -1,10 +1,13 @@
.DS_Store
.hugo_build.lock
/.idea
/.vscode
/public
/dist
node_modules
/public
hugo_stats.json
node_modules/
nohup.out
.DS_Store
trace.out
.hugo_build.lock
resources/_gen/images/
package-lock.json
public/
resources/
trace.out
+2 -200
View File
@@ -1,201 +1,3 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
See [content/LICENSE.md](content/LICENSE.md) for the license of the content of this repository.
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
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.
The theme (layouts, CSS, JavaScript etc.) of this repository has no open source license. It is custom made for the Hugo sites and is not meant for reuse.
+9
View File
@@ -16,3 +16,12 @@ Please see the [contributing] section for guidelines, examples, and process.
[friends]: https://github.com/gohugoio/hugo/graphs/contributors
[go]: https://go.dev/
[contributing]: https://gohugo.io/contribute/documentation
# Install
```bash
npm i
hugo server
```
**Note:** We're working on removing the need to run `npm i` for local development. Stay tuned.
File diff suppressed because one or more lines are too long
@@ -1,21 +0,0 @@
.animated {
animation-duration: .5s;
animation-fill-mode: forwards;
animation-timing-function: ease-in-out;
}
@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
.fadeIn {
animation-name: fadeIn;
}
.animated-delay-1 {
animation-delay: 0.5s;
}
@@ -1,25 +0,0 @@
/* These styles enhance the home page carousel, located here: themes/gohugoioTheme/layouts/partials/home-page-sections/showcase.html */
.overflow-x-scroll{
-webkit-overflow-scrolling: touch;
}
.row {
transition: 450ms transform;
font-size: 0;
}
.tile {
transition: 450ms all;
}
.details {
background: -webkit-gradient(linear, left bottom, left top, from(rgba(0,0,0,0.9)), to(rgba(0,0,0,0)));
background: linear-gradient(to top, rgba(0,0,0,0.9) 0%, rgba(0,0,0,0) 100%);
transition: 450ms opacity;
}
.tile:hover .details {
opacity: 1;
}
.row:hover .tile {
opacity: 0.3;
}
.row:hover .tile:hover {
opacity: 1;
}
@@ -1,89 +0,0 @@
.chroma .lntable pre {
padding: 0;
margin: 0;
border: 0;
}
.chroma .lntable pre code {
padding: 0;
margin: 0;
}
code {
padding: 2px 3px;
margin: 0;
font-size: 93.75%;
background-color: rgba(27,31,35,0.05);
border-radius: 3px;
}
pre code {
display: block;
padding: 1.5em 1.5em;
font-size: .875rem;
line-height: 2;
overflow-x: auto;
}
pre {
background-color: #fff;
color: #333;
white-space: pre;
hyphens: none;
position: relative;
border-width: 1px;
border-color: #ccc;
border-style: solid;
}
/* The Pygments highlighter comes with its own styles. */
.highlight pre {
background-color: inherit;
color: inherit;
padding: 0.5em;
font-size: .875rem;
}
/*We are adding the copy button content here so we can change it with javascript. See the "Clipboard scripts"*/
.copy:after {
content: "Copy"
}
.copied:after {
content: "Copied"
}
@media (--breakpoint-large) {
.full-width
{
/*width: 100vw;
position: relative;
left: 50%;
right: 50%;
margin-left: -50vw;
margin-right: -50vw;*/
/*width: 60vw;*/
/*position: relative;
left: 50%;
right: 50%;*/
/*margin-left: -30vw;*/
margin-right: -30vw;
max-width: 100vw;
}
}
.code-block .line-numbers-rows {
background: #2f3a46;
border: none;
bottom: -50px;
color: #98a4b3;
left: -178px;
padding: 50px 0;
top: -50px;
width: 138px
}
.code-block .line-numbers-rows>span:before {
color: inherit;
padding-right: 30px
}
@@ -1,38 +0,0 @@
.primary-color {color: var(--primary-color)}
.bg-primary-color {background-color: var(--primary-color)}
.hover-bg-primary-color:hover {background-color: var(--primary-color)}
.primary-color-dark {color: var(--primary-color-dark)}
.bg-primary-color-dark {background-color: var(--primary-color-dark)}
.hover-bg-primary-color-dark:hover {background-color: var(--primary-color-dark)}
.primary-color-light {color: var(--primary-color-light)}
.bg-primary-color-light {background-color: var(--primary-color-light)}
.hover-bg-primary-color-light:hover {background-color: var(--primary-color-light)}
.accent-color {color: var(--accent-color)}
.bg-accent-color {background-color: var(--accent-color)}
.hover-bg-accent-color:hover {background-color: var(--accent-color)}
.accent-color-light {color: var(--accent-color-light)}
.hover-accent-color-light:hover {color: var(--accent-color-light)}
.bg-accent-color-light {background-color: var(--accent-color-light)}
.hover-bg-accent-color-light:hover {background-color: var(--accent-color-light)}
.accent-color-dark {color: var(--accent-color-dark)}
.bg-accent-color-dark {background-color: var(--accent-color-dark)}
.hover-bg-accent-color-dark:hover {background-color: var(--accent-color-dark)}
.text-color-primary {color: var(--text-color-primary)}
.text-on-primary-color {color: var(--text-on-primary-color)}
.text-color-secondary {color: var(--text-color-secondary)}
.text-color-disabled {color: var(--text-color-disabled)}
.divider-color {color: var(--divider-color)}
.warn-color {color: var(--warn-color)}
.nested-links a {
color: var(--primary-color);
text-decoration: none;
}
@@ -1,11 +0,0 @@
.column-count-2 {column-count: 1}
.column-gap-1 {column-gap: 0}
.break-inside-avoid {break-inside: auto}
@media (--breakpoint-large) {
.column-count-3-l {column-count: 3}
.column-count-2-l {column-count: 2}
.column-gap-1-l {column-gap: 1}
.break-inside-avoid-l {break-inside: avoid}
}
@@ -1,28 +0,0 @@
.prose table {
width: 100%;
margin-bottom: 3em;
border-collapse: collapse;
border-spacing: 0;
font-size: 1em;
border: 1px solid var(--light-gray);
& th {
background-color: var(--primary-color);
border-bottom: 1px solid var(--primary-color);
color: white;
font-weight: 400;
text-align: left;
padding: .375em .5em;
}
& td, & tc {
padding: .75em .5em;
text-align: left;
border-right: 1px solid var(--light-gray);
}
}
.prose table tr:nth-child(even) {
background-color: var(--light-gray);
}
@@ -1,53 +0,0 @@
.prose ul, .prose ol {
margin-bottom: 2em;
}
.prose ul li, .prose ol li {
margin-bottom: .5em;
}
.prose li:hover {
background-color: var(--light-gray)
}
.prose ::selection {
background: var(--primary-color); /* WebKit/Blink Browsers */
color: white;
}
.prose-glossary h3 {
margin-top: 0;
font-size: 1.125rem;
}
.prose-glossary h3:first-of-type {
margin-top: 3em;
}
.prose-glossary h3 ~ p {
margin: 0.5em 0 2em 0;
}
body {
line-height: 1.45;
}
p {margin-bottom: 1.3em;}
h1, h2, h3, h4 {
margin: 1.414em 0 0.5em;
line-height: 1.2;
}
h1 {
margin-top: 0;
font-size: 2.441em;
}
h2 {font-size: 1.953em;}
h3 {font-size: 1.563em;}
h4 {font-size: 1.25em;}
small, .font_small {font-size: 0.8em;}
@@ -1,9 +0,0 @@
dl dt {
font-weight: bold;
font-size: 1.125rem;
}
dd {
margin: .5em 0 2em 0;
padding: 0;
}
@@ -1,54 +0,0 @@
.note,
.warning {
border-left-width: 4px;
border-left-style: solid;
position: relative;
border-color: var(--primary-color);
display: block;
}
.note #exclamation-icon,
.warning #exclamation-icon {
fill: var(--primary-color);
position: absolute;
top: 35%;
left: -12px;
/*background-color: white;*/
}
.admonition-content {
display: block;
margin: 0px;
padding: .125em 1em;
/*margin-left: 1em;*/
margin-top: 2em;
margin-bottom: 2em;
overflow-x: auto;
/*font-size: .9375em;*/
background-color: var(--black-05);
}
.hide-child-menu .child-menu {
display: none;
}
.hide-child-menu:hover .child-menu,
.hide-child-menu:focus .child-menu,
.hide-child-menu:active .child-menu {
display: block;
}
/*documentation-copy headings exaggerate spacing and size to chunk content */
.documentation-copy h2 {
margin-top: 3em;
&.minor {
font-size: inherit;
margin-top: inherit;
border-bottom: none;
}
}
@@ -1,10 +0,0 @@
.f2-fluid {
font-size: 2.25rem;
}
@media (--breakpoint-large) {
.f2-fluid {
font-size: 1.25rem;
font-size: calc(0.875rem + 0.5 * ((100vw - 20rem) / 60));
}
}
@@ -1,74 +0,0 @@
/* From https://www.cssfontstack.com */
code, .code, pre code, .highlight pre {
font-family: 'inconsolata',Menlo,Monaco,'Courier New',monospace;
}
.sans-serif {
font-family: 'Muli', Avenir, 'Helvetica Neue', Helvetica, Roboto, Noto, 'Segoe UI', Arial, sans-serif;
}
.serif {
font-family: Palatino,"Palatino Linotype","Palatino LT STD","Book Antiqua",Georgia,serif;
}
/* Monospaced Typefaces (for code) */
.courier {
font-family: 'Courier Next',
courier,
monospace;
}
/* Sans-Serif Typefaces */
.helvetica {
font-family: 'helvetica neue', helvetica,
sans-serif;
}
.avenir {
font-family: 'avenir next', avenir,
sans-serif;
}
/* Serif Typefaces */
.athelas {
font-family: athelas,
georgia,
serif;
}
.georgia {
font-family: georgia,
serif;
}
.times {
font-family: times,
serif;
}
.bodoni {
font-family: "Bodoni MT",
serif;
}
.calisto {
font-family: "Calisto MT",
serif;
}
.garamond {
font-family: garamond,
serif;
}
.baskerville {
font-family: baskerville,
serif;
}
@@ -1,15 +0,0 @@
.header-link:after {
position: relative;
left: 0.5em;
opacity: 0;
font-size: 0.8em;
-moz-transition: opacity 0.2s ease-in-out 0.1s;
-ms-transition: opacity 0.2s ease-in-out 0.1s;
}
h2:hover .header-link,
h3:hover .header-link,
h4:hover .header-link,
h5:hover .header-link,
h6:hover .header-link {
opacity: 1;
}
@@ -1,52 +0,0 @@
/* pagination.html: https://github.com/gohugoio/hugo/blob/master/tpl/tplimpl/template_embedded.go#L117 */
.pagination {
margin: 3rem 0;
}
.pagination li {
display: inline-block;
margin-right: .375rem;
font-size: .875rem;
margin-bottom: 2.5em;
}
.pagination li a {
padding: .5rem .625rem;
background-color: white;
color: #333;
border: 1px solid #ddd;
border-radius: 3px;
text-decoration: none;
}
.pagination li.disabled {
display: none;
}
.pagination li.active a:link,
.pagination li.active a:active,
.pagination li.active a:visited {
background-color: #ddd;
}
/* Hides non-meaningful TOC items*/
#TableOfContents ul li ul li ul li{
display: none;
}
#TableOfContents ul li {
color: black;
display: block;
margin-bottom: .375em;
line-height: 1.375;
}
#TableOfContents ul li a{
width: 100%;
padding: .25em .375em;
margin-left: -.375em;
}
#TableOfContents ul li a:hover {
background-color: #999;
color: white;
}
@@ -1,7 +0,0 @@
.no-js .needs-js {
opacity: 0
}
.js .needs-js {
opacity: 1;
transition: opacity .15s ease-in;
}
@@ -1,7 +0,0 @@
@media print {
#page-footer,
body > footer,
body > nav {
display: none;
}
}
@@ -1,11 +0,0 @@
#right-sidebar {
scrollbar-width: none; /* hide scrollbar: Firefox */
-ms-overflow-style: none; /* hide scrollbar: Internet Explorer 10+ */
height: calc(100vh - 9rem);
overflow-y: auto;
}
#right-sidebar::-webkit-scrollbar { /* hide scrollbar: WebKit */
width: 0;
height: 0;
}
@@ -1,25 +0,0 @@
/*
Make h6 elements behave like dt elements. Initially implemented to support
linkable glossary entries.
Yes, it's a hack. That's why it's in the shame file.
*/
h6 {
margin-top: 0;
margin-bottom: 0;
font-size: 1.125rem;
}
h6:first-of-type {
margin-top: 3em;
}
h6 ~ p {
margin: 0.5em 0 2em 0;
}
/* QR codes */
img.qrcode {
width: initial;
}
@@ -1,52 +0,0 @@
.facebook,
.twitter,
.instagram,
.youtube {
fill: #bababa;
}
.facebook:hover {
fill: #3b5998;
}
.twitter {
fill: #55acee;
}
.twitter:hover {
fill: #bababa;
}
.instagram:hover {
fill: #e95950;
}
.youtube:hover {
fill: #bb0000;
}
.mstdn {
display: inline-block;
background-color: #282c37;
color: #d9e1e8;
text-decoration: none;
padding: 4px 10px 4px 30px;
border-radius: 4px;
font-size: 16px;
background-image: url("data:image/svg+xml;charset=utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2261.076954mm%22%20height%3D%2265.47831mm%22%20viewBox%3D%220%200%20216.4144%20232.00976%22%3E%3Cpath%20d%3D%22M211.80734%20139.0875c-3.18125%2016.36625-28.4925%2034.2775-57.5625%2037.74875-15.15875%201.80875-30.08375%203.47125-45.99875%202.74125-26.0275-1.1925-46.565-6.2125-46.565-6.2125%200%202.53375.15625%204.94625.46875%207.2025%203.38375%2025.68625%2025.47%2027.225%2046.39125%2027.9425%2021.11625.7225%2039.91875-5.20625%2039.91875-5.20625l.8675%2019.09s-14.77%207.93125-41.08125%209.39c-14.50875.7975-32.52375-.365-53.50625-5.91875C9.23234%20213.82%201.40609%20165.31125.20859%20116.09125c-.365-14.61375-.14-28.39375-.14-39.91875%200-50.33%2032.97625-65.0825%2032.97625-65.0825C49.67234%203.45375%2078.20359.2425%20107.86484%200h.72875c29.66125.2425%2058.21125%203.45375%2074.8375%2011.09%200%200%2032.975%2014.7525%2032.975%2065.0825%200%200%20.41375%2037.13375-4.59875%2062.915%22%20fill%3D%22%233088d4%22%2F%3E%3Cpath%20d%3D%22M177.50984%2080.077v60.94125h-24.14375v-59.15c0-12.46875-5.24625-18.7975-15.74-18.7975-11.6025%200-17.4175%207.5075-17.4175%2022.3525v32.37625H96.20734V85.42325c0-14.845-5.81625-22.3525-17.41875-22.3525-10.49375%200-15.74%206.32875-15.74%2018.7975v59.15H38.90484V80.077c0-12.455%203.17125-22.3525%209.54125-29.675%206.56875-7.3225%2015.17125-11.07625%2025.85-11.07625%2012.355%200%2021.71125%204.74875%2027.8975%2014.2475l6.01375%2010.08125%206.015-10.08125c6.185-9.49875%2015.54125-14.2475%2027.8975-14.2475%2010.6775%200%2019.28%203.75375%2025.85%2011.07625%206.36875%207.3225%209.54%2017.22%209.54%2029.675%22%20fill%3D%22%23fff%22%2F%3E%3C%2Fsvg%3E");
background-size: 16px;
background-repeat: no-repeat;
background-position: top 50% left 8px;
transition: all 0.5s;
}
.mstdn:hover {
background-color: #484c56;
}
.mstdn > span {
color: #9baec8;
font-size: 12px;
padding-left: 3px;
}
.mstdn > span:before {
content: "@";
}
@@ -1,15 +0,0 @@
@media (min-width: 75em) {
[data-scrolldir="down"] .sticky {
position: fixed;
top:100px;
right:0;
}
[data-scrolldir="up"] .sticky {
position: fixed;
top:100px;
right:0;
}
}
@@ -1 +0,0 @@
.fill-current { fill: currentColor; }
@@ -1,34 +0,0 @@
.tab-button{
margin-bottom:1px;
position: relative;
z-index: 1;
color:#333;
border-color:#ccc;
outline: none;
background-color:white;
}
.tab-pane code{
background:#f1f2f2;
border-radius:0;
}
.tab-pane .chroma{
background:none;
padding:0;
}
.tab-button.active{
border-bottom-color:#f1f2f2;
background-color: #f1f2f2;
}
.tab-content .tab-pane{
display: none;
}
.tab-content .tab-pane.active{
display: block;
}
/* Treatment of copy buttons inside a tab module */
.tab-content .copy, .tab-content .copied{
display: none;
}
.tab-content .tab-pane.active + .copy, .tab-content .tab-pane.active + .copied{
display: block;
}
@@ -1,94 +0,0 @@
/*! TACHYONS v4.7.0 | http://tachyons.io */
/*
* NOTE: The Tachyons folder is for backup/reference only. This file references the module
* ________ ______
* ___ __/_____ _________ /______ ______________________
* __ / _ __ `/ ___/_ __ \_ / / / __ \_ __ \_ ___/
* _ / / /_/ // /__ _ / / / /_/ // /_/ / / / /(__ )
* /_/ \__,_/ \___/ /_/ /_/_\__, / \____//_/ /_//____/
* /____/
*
* TABLE OF CONTENTS
*
* 1. External Library Includes
* - Normalize.css | http://normalize.css.github.io
* 2. Tachyons Modules
* 3. Variables
* - Media Queries
* - Colors
* 4. Debugging
* - Debug all
* - Debug children
*
*/
/* External Library Includes */
@import 'tachyons/src/_normalize';
/* Modules */
@import 'tachyons/src/_box-sizing';
/*@import 'tachyons/src/_aspect-ratios';*/
@import 'tachyons/src/_images';
@import 'tachyons/src/_background-size';
@import 'tachyons/src/_background-position';
/*@import 'tachyons/src/_outlines';*/
@import 'tachyons/src/_borders';
@import 'tachyons/src/_border-colors';
@import 'tachyons/src/_border-radius';
@import 'tachyons/src/_border-style';
@import 'tachyons/src/_border-widths';
@import 'tachyons/src/_box-shadow';
/*@import 'tachyons/src/_code';*/
@import 'tachyons/src/_coordinates';
@import 'tachyons/src/_clears';
@import 'tachyons/src/_display';
@import 'tachyons/src/_flexbox';
@import 'tachyons/src/_floats';
/*@import 'tachyons/src/_font-family';*/
@import 'tachyons/src/_font-style';
@import 'tachyons/src/_font-weight';
@import 'tachyons/src/_forms';
@import 'tachyons/src/_heights';
@import 'tachyons/src/_letter-spacing';
@import 'tachyons/src/_line-height';
@import 'tachyons/src/_links';
@import 'tachyons/src/_lists';
@import 'tachyons/src/_max-widths';
@import 'tachyons/src/_widths';
@import 'tachyons/src/_overflow';
@import 'tachyons/src/_position';
@import 'tachyons/src/_opacity';
/*@import 'tachyons/src/_rotations';*/
@import 'tachyons/src/_skins';
@import 'tachyons/src/_skins-pseudo';
@import 'tachyons/src/_spacing';
@import 'tachyons/src/_negative-margins';
@import 'tachyons/src/_tables';
@import 'tachyons/src/_text-decoration';
@import 'tachyons/src/_text-align';
@import 'tachyons/src/_text-transform';
@import 'tachyons/src/_type-scale';
@import 'tachyons/src/_typography';
@import 'tachyons/src/_utilities';
@import 'tachyons/src/_visibility';
@import 'tachyons/src/_white-space';
@import 'tachyons/src/_vertical-align';
@import 'tachyons/src/_hovers';
@import 'tachyons/src/_z-index';
@import 'tachyons/src/_nested';
/*@import 'tachyons/src/_styles';*/
/* Variables */
/* Importing here will allow you to override any variables in the modules */
@import 'tachyons/src/_colors';
@import 'tachyons/src/_media-queries';
/* Debugging */
/*@import 'tachyons/src/_debug-children';
@import 'tachyons/src/_debug-grid';*/
/* Uncomment out the line below to help debug layout issues */
/* @import 'tachyons/src/_debug'; */
@@ -1,16 +0,0 @@
:root {
--primary-color: #0594CB;
--primary-color-dark: #0A1922;
--primary-color-light: #f9f9f9;
--accent-color: #EBB951;
--accent-color-light: #FF4088;
--accent-color-dark: #33ba91;
--text-color-primary: #373737;
--text-on-primary-color: #fff;
--text-color-secondary: #ccc;
--text-color-disabled: #F7f7f7;
--divider-color: #f6f6f6;
--warn-color: red;
--blue: var(--primary-color);
}
@@ -1,39 +0,0 @@
/*Base Styles*/
@import '_tachyons';
/* purgecss start ignore */
@import '_header-link';
@import '_animation';
@import '_documentation-styles';
@import 'docsearch.js/dist/cdn/docsearch.min';
@import '_carousel';
@import '_code';
@import '_tabs';
@import '_color-scheme';
@import '_columns';
@import '_content';
@import '_content-tables';
@import '_definition-lists';
@import '_fluid-type';
@import '_font-family';
@import '_hugo-internal-template-styling';
@import '_no-js';
@import '_social-icons';
@import '_stickyheader';
@import '_right-sidebar';
@import '_svg';
@import '_chroma';
@import '_variables';
@import '_print';
@import '_shame';
.nested-blockquote blockquote {
border-left: 4px solid var(--primary-color);
padding-left: 1em;
}
.mw-90 {
max-width:90%;
}
/* purgecss end ignore */
@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 575.8 178.3" viewBox="0 0 575.8 178.3"><path d="m148.6 78.9-24.7-13.6-20.8 12.7-.3 13-10.1-6.7-13.8 8.4c-.2-3.9-.4-8.6-.6-14.2l-14.2-9.5c3.9-2 8.4-4.3 13.5-7-.1 0 .1 1.4-2-46.5l-32-15.4-43.6 13.6 9.7 46.9 14.6 11.4-11.1 5.3 7.3 35.3 10.2 9.6-7.3 4.5 5.7 27.3 22.9 24.3c.1-.1 2.4-1.9 29.5-23.5l-.8-18.6 11.7 9.9c.2-.2 2.4-1.9 23.7-18.8l.8-13.7 8.8 6.1c.1-.2 2.1-1.7 19.3-15.3z"></path><path d="m128.1 93.5 20.5-14.6-24.7-13.6-20.8 12.7z" fill="#141414"></path><path d="m125.8 119.5 2.3-26-25-15.5-.5 25.4z" fill="#004b16"></path><path d="m92.6 146-.3-27-25.1-19.1 1.9 26.4z" fill="#004b16"></path><path d="m92.3 119 25.5-18.2-25.1-16.5-25.5 15.6z" fill="#141414"></path><path d="m52.1 178.2-4.1-27.6-24.6-24.1 5.7 27.4z" fill="#004b16"></path><path d="m48 150.6 32.4-23.1-25.1-20.4-31.9 19.4z" fill="#141414"></path><path d="m45.9 136.3-5.3-36.4-27.4-22.8 7.3 35.4z" fill="#004b16"></path><path d="m40.6 99.9 37.7-21.4-28.2-18.9-36.9 17.5z" fill="#141414"></path><path d="m38 82.5-7.3-49.9-30.7-19 9.7 46.9z" fill="#004b16"></path><path d="m30.7 32.6 44.9-17.2-32-15.4-43.6 13.6z" fill="#141414"></path><g fill="#1cb35c"><path d="m145.2 104.2c-19 15.1-19.4 15.4-19.3 15.4 2.4-27.2 2.2-26 2.3-26 21.8-15.5 20.4-14.6 20.5-14.6z"></path><path d="m116.2 127.2c-23.5 18.7-23.8 18.8-23.7 18.8-.2-28.2-.3-27-.2-27 27.1-19.4 25.4-18.2 25.5-18.2z"></path><path d="m81.6 154.7c-29.4 23.3-29.6 23.5-29.5 23.5-4.2-28.4-4.1-27.5-4-27.5 34.5-24.6 32.3-23.1 32.4-23.1z"></path><path d="m75.6 15.4c2.1 47.9 1.9 46.5 2 46.5-38.8 20.2-39.7 20.6-39.6 20.6-7.5-51-7.4-49.9-7.3-49.9z"></path><path d="m78.3 78.5c1.6 36.3 1.4 35.1 1.5 35.1-33.6 22.6-34 22.8-33.9 22.8-5.5-37.4-5.4-36.4-5.3-36.4z"></path></g><path d="m191.4 33.6 16.8-4c0 81.8-3.1 93.5 8 97.1-2.6 4.9-7.1 7.4-13.3 7.4-15.3 0-11.5-11.3-11.5-100.5z"></path><path d="m233.7 132.7v-58.4h-9.2v-13.8h26.3v72.2zm8.7-100.1c12.9 0 12.9 19.5 0 19.5s-12.9-19.5 0-19.5z"></path><path d="m316.8 132.7c0-43.6 1.1-49.6-3.5-55.2-5.8-6.9-20-5-26.1 3v52.2h-16.8v-72.2h12.1l3.1 6.7c9.1-10.8 30.4-10.9 40.6-.4 9.7 10 7.4 20.5 7.4 65.8z"></path><path d="m347.2 96.4c0-49.2 69.4-51.1 69.4 0-.1 50.7-69.4 50.8-69.4 0zm17.5 0c0 28.8 22.2 27.7 29.7 17.7 7-9.4 8.8-41.2-12.5-41.2-12.3 0-17.2 11.3-17.2 23.5z"></path><path d="m476.4 132.7c0-7.4 1.8-3.4-7.1-.4-10.2 3.5-25.1 2-34.1-7.9-11.1-12.3-12.6-39.5 1.3-54.6 11.4-12.3 28.5-13.1 39.9-7.4v-28.9l16.9-4v103.1zm0-54.9c-8.9-7.1-20.9-4.8-26.8 1.9-8.1 9.1-11.2 40.2 16.2 40.2 2.9 0 9-2.2 10.6-4.4z"></path><path d="m574.6 101.8h-51.6c1.2 22.3 29 21.4 38.1 12.2l6.5 12.9c-14 11.3-62.3 15-62.3-29.5.1-54.1 81.3-49 69.3 4.4zm-51-12.7h35.5c-1.2-10.6-7-15.8-17.5-15.8-9.7 0-15.6 5.2-18 15.8z"></path></svg>

Before

Width:  |  Height:  |  Size: 2.7 KiB

@@ -1,10 +0,0 @@
require('typeface-muli');
import styles from './css/main.css';
import './js/clipboardjs.js';
import './js/docsearch.js';
import './js/lazysizes.js';
import './js/menutoggle.js';
import './js/scrolldir.js';
import './js/smoothscroll.js';
import './js/tabs.js';
import './js/nojs.js';
@@ -1,30 +0,0 @@
var Clipboard = require('clipboard/dist/clipboard.js');
new Clipboard('.copy', {
target: function(trigger) {
if(trigger.classList.contains('copy-toggle')){
return trigger.previousElementSibling;
}
return trigger.nextElementSibling;
}
}).on('success', function(e) {
successMessage(e.trigger, 'Copied!');
e.clearSelection();
}).on('error', function(e) {
successMessage(e.trigger, fallbackMessage(e.action));
});
function successMessage(elem, msg) {
elem.setAttribute('class', 'copied bg-primary-color-dark f6 absolute top-0 right-0 lh-solid hover-bg-primary-color-dark bn white ph3 pv2');
elem.setAttribute('aria-label', msg);
}
function fallbackMessage(elem, action) {
var actionMsg = '';
var actionKey = (action === 'cut' ? 'X' : 'C');
if (isMac) {
actionMsg = 'Press ⌘-' + actionKey;
} else {
actionMsg = 'Press Ctrl-' + actionKey;
}
return actionMsg;
}
@@ -1,8 +0,0 @@
var docsearch = require('docsearch.js/dist/cdn/docsearch.js');
docsearch({
appId: 'D1BPLZHGYQ',
apiKey: '6df94e1e5d55d258c56f60d974d10314',
indexName: 'hugodocs',
inputSelector: '#search-input',
debug: true, // Set debug to true if you want to inspect the dropdown
});
@@ -1,3 +0,0 @@
var lazysizes = require('lazysizes');
// var lsnoscript = require('lazysizes/plugins/noscript/ls.noscript.js');
var unveilhooks = require('lazysizes/plugins/unveilhooks/ls.unveilhooks.js');
@@ -1,22 +0,0 @@
import styles from './../css/main.css';
import './clipboardjs.js'
import './codeblocks.js'
import './docsearch.js'
import './lazysizes.js'
import './menutoggle.js'
import './scrolldir.js'
import './smoothscroll.js'
import './tabs.js'
import './nojs.js'
// TO use jQuery, just call the modules you want
// var $ = require('jquery/src/core');
// require('jquery/src/core/init');
// require('jquery/src/manipulation');
// OR, use all of them
// var $ = require('jquery/src/jquery');
// And write your code
// $('body').append('<p>Jquery is working</p>');
//
@@ -1,31 +0,0 @@
// Grab any element that has the 'js-toggle' class and add an event listener for the toggleClass function
var toggleBtns = document.getElementsByClassName('js-toggle')
for (var i = 0; i < toggleBtns.length; i++) {
toggleBtns[i].addEventListener('click', toggleClass, false)
}
function toggleClass() {
// Define the data target via the dataset "target" (e.g. data-target=".docsmenu")
var content = this.dataset.target.split(' ')
// Find any menu items that are open
var mobileCurrentlyOpen = document.querySelector('.mobilemenu:not(.dn)')
var desktopCurrentlyOpen = document.querySelector('.desktopmenu:not(.dn)')
var desktopActive = document.querySelector('.desktopmenu:not(.dn)')
// Loop through the targets' divs
for (var i = 0; i < content.length; i++) {
var matches = document.querySelectorAll(content[i]);
//for each, if the div has the 'dn' class (which is "display:none;"), remove it, otherwise, add that class
[].forEach.call(matches, function(dom) {
dom.classList.contains('dn') ?
dom.classList.remove('dn') :
dom.classList.add('dn');
return false;
});
// close the currently open menu items
if (mobileCurrentlyOpen) mobileCurrentlyOpen.classList.add('dn')
if (desktopCurrentlyOpen) desktopCurrentlyOpen.classList.add('dn')
if (desktopActive) desktopActive.classList.remove('db')
}
}
@@ -1 +0,0 @@
document.documentElement.className = document.documentElement.className.replace(/\bno-js\b/, 'js');
@@ -1 +0,0 @@
var scrollDir = require('scrolldir/dist/scrolldir.auto.min.js');
@@ -1,80 +0,0 @@
// query selector targets Hugo TOC
(function() {
'use strict';
// Feature Test
if ('querySelector' in document && 'addEventListener' in window && Array.prototype.forEach) {
// Function to animate the scroll
var smoothScroll = function(anchor, duration) {
// Calculate how far and how fast to scroll
var startLocation = window.pageYOffset;
var endLocation = anchor.offsetTop;
var distance = endLocation - startLocation;
var increments = distance / (duration / 16);
var stopAnimation;
// Scroll the page by an increment, and check if it's time to stop
var animateScroll = function() {
window.scrollBy(0, increments);
stopAnimation();
};
// If scrolling down
if (increments >= 0) {
// Stop animation when you reach the anchor OR the bottom of the page
stopAnimation = function() {
var travelled = window.pageYOffset;
if ((travelled >= (endLocation - increments)) || ((window.innerHeight + travelled) >= document.body.offsetHeight)) {
clearInterval(runAnimation);
}
};
}
// If scrolling up
else {
// Stop animation when you reach the anchor OR the top of the page
stopAnimation = function() {
var travelled = window.pageYOffset;
if (travelled <= (endLocation || 0)) {
clearInterval(runAnimation);
}
};
}
// Loop the animation function
var runAnimation = setInterval(animateScroll, 16);
};
// Define smooth scroll links
var scrollToggle = document.querySelectorAll('#TableOfContents ul li a');
// For each smooth scroll link
[].forEach.call(scrollToggle, function(toggle) {
// When the smooth scroll link is clicked
toggle.addEventListener('click', function(e) {
// Prevent the default link behavior
e.preventDefault();
// Get anchor link and calculate distance from the top
var dataID = toggle.getAttribute('href');
var dataTarget = document.querySelector(dataID);
var dataSpeed = toggle.getAttribute('data-speed');
// If the anchor exists
if (dataTarget) {
// Scroll to the anchor
smoothScroll(dataTarget, dataSpeed || 500);
}
}, false);
});
}
})();
@@ -1,43 +0,0 @@
/**
* Scripts which manages Code Toggle tabs.
*/
var i;
// store tabs variable
var allTabs = document.querySelectorAll("[data-toggle-tab]");
var allPanes = document.querySelectorAll("[data-pane]");
function toggleTabs(event) {
if(event.target){
event.preventDefault();
var clickedTab = event.currentTarget;
var targetKey = clickedTab.getAttribute("data-toggle-tab")
}else {
var targetKey = event
}
// We store the config language selected in users' localStorage
if(window.localStorage){
window.localStorage.setItem("configLangPref", targetKey)
}
var selectedTabs = document.querySelectorAll("[data-toggle-tab='" + targetKey + "']");
var selectedPanes = document.querySelectorAll("[data-pane='" + targetKey + "']");
for (var i = 0; i < allTabs.length; i++) {
allTabs[i].classList.remove("active");
allPanes[i].classList.remove("active");
}
for (var i = 0; i < selectedTabs.length; i++) {
selectedTabs[i].classList.add("active");
selectedPanes[i].classList.add("active");
}
}
for (i = 0; i < allTabs.length; i++) {
allTabs[i].addEventListener("click", toggleTabs)
}
// Upon page load, if user has a preferred language in its localStorage, tabs are set to it.
if(window.localStorage.getItem('configLangPref')) {
toggleTabs(window.localStorage.getItem('configLangPref'))
}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,4 +0,0 @@
[module]
[module.hugoVersion]
min = "0.56.0"
@@ -1,10 +0,0 @@
{{ define "main" }}
<main class="cf pa5 pa4-l f4 tc center measure-wide lh-copy gray">
<h1 class="f3 f2-ns">The page you're looking for doesn't exist. Perhaps you'd like to gopher something else? Sorry.</h1>
<div class="h6">
<img src="/images/gopher-hero.svg" alt="" class="h5">
</div>
{{ .Content }}
</main>
{{ end }}
@@ -1,4 +0,0 @@
<pre class="mermaid">
{{- .Inner | safeHTML }}
</pre>
{{ .Page.Store.Set "hasMermaid" true }}
@@ -1,5 +0,0 @@
<h{{ .Level }} id="{{ .Anchor | safeURL }}">{{ .Text | safeHTML }}
{{- if in (slice 2 3 4 6) .Level }}{{" " -}}
<a class="header-link" href="#{{ .Anchor | safeURL }}"><svg class="fill-current o-60 hover-accent-color-light" height="22px" viewBox="0 0 24 24" width="22px" xmlns="http://www.w3.org/2000/svg"><path d="M0 0h24v24H0z" fill="none"/><path d="M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z"/></svg></a>
{{- end -}}
</h{{ .Level }}>
@@ -1,245 +0,0 @@
{{- /* Last modified: 2024-04-26T13:54:00-07:00 */}}
{{- /*
Copyright 2023 Veriphor LLC
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
https://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.
*/}}
{{- /*
This render hook resolves internal destinations by looking for a matching:
1. Content page
2. Page resource (a file in the current page bundle)
3. Section resource (a file in the current section)
4. Global resource (a file in the assets directory)
It skips the section resource lookup if the current page is a leaf bundle.
External destinations are not modified.
You must place global resources in the assets directory. If you have placed
your resources in the static directory, and you are unable or unwilling to move
them, you must mount the static directory to the assets directory by including
both of these entries in your site configuration:
[[module.mounts]]
source = 'assets'
target = 'assets'
[[module.mounts]]
source = 'static'
target = 'assets'
By default, if this render hook is unable to resolve a destination, including a
fragment if present, it passes the destination through without modification. To
emit a warning or error, set the error level in your site configuration:
[params.render_hooks.link]
errorLevel = 'warning' # ignore (default), warning, or error (fails the build)
When you set the error level to warning, and you are in a development
environment, you can visually highlight broken internal links:
[params.render_hooks.link]
errorLevel = 'warning' # ignore (default), warning, or error (fails the build)
highlightBroken = true # true or false (default)
This will add a "broken" class to anchor elements with invalid src attributes.
Add a rule to your CSS targeting the broken links:
a.broken {
background: #ff0;
border: 2px solid #f00;
padding: 0.1em 0.2em;
}
This render hook may be unable to resolve destinations created with the ref and
relref shortcodes. Unless you set the error level to ignore you should not use
either of these shortcodes in conjunction with this render hook.
@context {string} Destination The link destination.
@context {page} Page A reference to the page containing the link.
@context {string} PlainText The link description as plain text.
@context {string} Text The link description.
@context {string} Title The link title.
@returns {template.html}
*/}}
{{- /* Initialize. */}}
{{- $renderHookName := "link" }}
{{- /* Verify minimum required version. */}}
{{- $minHugoVersion := "0.120.0" }}
{{- if lt hugo.Version $minHugoVersion }}
{{- errorf "The %q render hook requires Hugo v%s or later." $renderHookName $minHugoVersion }}
{{- end }}
{{- /* Error level when unable to resolve destination: ignore, warning, or error. */}}
{{- $errorLevel := or site.Params.render_hooks.link.errorLevel "ignore" | lower }}
{{- /* If true, adds "broken" class to broken links. Applicable in development environment when errorLevel is warning. */}}
{{- $highlightBrokenLinks := or site.Params.render_hooks.link.highlightBroken false }}
{{- /* Validate error level. */}}
{{- if not (in (slice "ignore" "warning" "error") $errorLevel) }}
{{- errorf "The %q render hook is misconfigured. The errorLevel %q is invalid. Please check your site configuration." $renderHookName $errorLevel }}
{{- end }}
{{- /* Determine content path for warning and error messages. */}}
{{- $contentPath := .Page.String }}
{{- /* Parse destination. */}}
{{- $u := urls.Parse .Destination }}
{{- /* Set common message. */}}
{{- $msg := printf "The %q render hook was unable to resolve the destination %q in %s" $renderHookName $u.String $contentPath }}
{{- /* Set attributes for anchor element. */}}
{{- $attrs := dict "href" $u.String }}
{{- if $u.IsAbs }}
{{- /* Destination is a remote resource. */}}
{{- $attrs = merge $attrs (dict "rel" "external") }}
{{- else }}
{{- with $u.Path }}
{{- with $p := or ($.PageInner.GetPage .) ($.PageInner.GetPage (strings.TrimRight "/" .)) }}
{{- /* Destination is a page. */}}
{{- $href := .RelPermalink }}
{{- with $u.RawQuery }}
{{- $href = printf "%s?%s" $href . }}
{{- end }}
{{- with $u.Fragment }}
{{- $ctx := dict
"contentPath" $contentPath
"errorLevel" $errorLevel
"page" $p
"parsedURL" $u
"renderHookName" $renderHookName
}}
{{- partial "inline/h-rh-l/validate-fragment.html" $ctx }}
{{- $href = printf "%s#%s" $href . }}
{{- end }}
{{- $attrs = dict "href" $href }}
{{- else }}
{{- with $.PageInner.Resources.Get $u.Path }}
{{- /* Destination is a page resource; drop query and fragment. */}}
{{- $attrs = dict "href" .RelPermalink }}
{{- else }}
{{- with (and (ne $.Page.BundleType "leaf") ($.Page.CurrentSection.Resources.Get $u.Path)) }}
{{- /* Destination is a section resource, and current page is not a leaf bundle. */}}
{{- $attrs = dict "href" .RelPermalink }}
{{- else }}
{{- with resources.Get $u.Path }}
{{- /* Destination is a global resource; drop query and fragment. */}}
{{- $attrs = dict "href" .RelPermalink }}
{{- else }}
{{- if eq $errorLevel "warning" }}
{{- warnf $msg }}
{{- if and $highlightBrokenLinks hugo.IsDevelopment }}
{{- $attrs = merge $attrs (dict "class" "broken") }}
{{- end }}
{{- else if eq $errorLevel "error" }}
{{- errorf $msg }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}
{{- else }}
{{- with $u.Fragment }}
{{- /* Destination is on the same page; prepend relative permalink. */}}
{{- $ctx := dict
"contentPath" $contentPath
"errorLevel" $errorLevel
"page" $.Page
"parsedURL" $u
"renderHookName" $renderHookName
}}
{{- partial "inline/h-rh-l/validate-fragment.html" $ctx }}
{{- $attrs = dict "href" (printf "%s#%s" $.Page.RelPermalink .) }}
{{- else }}
{{- if eq $errorLevel "warning" }}
{{- warnf $msg }}
{{- if and $highlightBrokenLinks hugo.IsDevelopment }}
{{- $attrs = merge $attrs (dict "class" "broken") }}
{{- end }}
{{- else if eq $errorLevel "error" }}
{{- errorf $msg }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}
{{- $attrs = merge $attrs (dict "title" (.Title | transform.HTMLEscape)) }}
{{- /* Render anchor element. */ -}}
<a
{{- range $k, $v := $attrs }}
{{- if $v }}
{{- printf " %s=%q" $k $v | safeHTMLAttr }}
{{- end }}
{{- end -}}
>{{ .Text | safeHTML }}</a>
{{- define "partials/inline/h-rh-l/validate-fragment.html" }}
{{- /*
Validates the fragment portion of a link destination.
@context {string} contentPath The page containing the link.
@context {string} errorLevel The error level when unable to resolve destination; ignore (default), warning, or error.
@context {page} page The page corresponding to the link destination
@context {struct} parsedURL The link destination parsed by urls.Parse.
@context {string} renderHookName The name of the render hook.
*/}}
{{- /* Initialize. */}}
{{- $contentPath := .contentPath }}
{{- $errorLevel := .errorLevel }}
{{- $p := .page }}
{{- $u := .parsedURL }}
{{- $renderHookName := .renderHookName }}
{{- /* Validate. */}}
{{- with $u.Fragment }}
{{- if $p.Fragments.Identifiers.Contains . }}
{{- if gt ($p.Fragments.Identifiers.Count .) 1 }}
{{- $msg := printf "The %q render hook detected duplicate heading IDs %q in %s" $renderHookName . $contentPath }}
{{- if eq $errorLevel "warning" }}
{{- warnf $msg }}
{{- else if eq $errorLevel "error" }}
{{- errorf $msg }}
{{- end }}
{{- end }}
{{- else }}
{{- /* Determine target path for warning and error message. */}}
{{- $targetPath := "" }}
{{- with $p.File }}
{{- $targetPath = .Path }}
{{- else }}
{{- $targetPath = .Path }}
{{- end }}
{{- /* Set common message. */}}
{{- $msg := printf "The %q render hook was unable to find heading ID %q in %s. See %s" $renderHookName . $targetPath $contentPath }}
{{- if eq $targetPath $contentPath }}
{{- $msg = printf "The %q render hook was unable to find heading ID %q in %s" $renderHookName . $targetPath }}
{{- end }}
{{- /* Throw warning or error. */}}
{{- if eq $errorLevel "warning" }}
{{- warnf $msg }}
{{- else if eq $errorLevel "error" }}
{{- errorf $msg }}
{{- end }}
{{- end }}
{{- end }}
{{- end -}}
@@ -1,122 +0,0 @@
<!doctype html>
<html
class="no-js"
lang="{{ with $.Site.LanguageCode }}
{{ . }}
{{ else }}
en-us
{{ end }}
">
<head>
<meta charset="utf-8" />
{{/* https://www.zachleat.com/web/preload/ */}}
<link
rel="preload"
href="{{ "fonts/muli-latin-200.woff2" | absURL }}"
as="font"
type="font/woff2"
crossorigin />
<link
rel="preload"
href="{{ "fonts/muli-latin-400.woff2" | absURL }}"
as="font"
type="font/woff2"
crossorigin />
<link
rel="preload"
href="{{ "fonts/muli-latin-800.woff2" | absURL }}"
as="font"
type="font/woff2"
crossorigin />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
{{/* NOTE: the Site's title, and if there is a page title, that is set too */}}
<title>
{{ block "title" . }}
{{ with .Title }}{{ . }} | {{ end }}{{ .Site.Title }}
{{ end }}
</title>
<meta name="viewport" content="width=device-width,minimum-scale=1" />
{{ hugo.Generator }}
{{ if hugo.IsProduction }}
<meta name="robots" content="index, follow" />
{{ else }}
<meta name="robots" content="noindex, nofollow" />
{{ end }}
{{ range .AlternativeOutputFormats -}}
<link
rel="{{ .Rel }}"
type="{{ .MediaType.Type }}"
href="{{ .Permalink | safeURL }}" />
{{ end -}}
{{ $isDev := eq hugo.Environment "development" }}
{{ $stylesheet := resources.Get "output/css/app.css" }}
{{ if not $isDev }}
{{ $stylesheet = $stylesheet | minify | fingerprint }}
{{ end }}
{{ with $stylesheet }}
{{ if $isDev }}
<link
rel="stylesheet"
href="{{ .RelPermalink }}"
crossorigin="anonymous" />
{{ else }}
<link
rel="stylesheet"
href="{{ .RelPermalink }}"
integrity="{{ .Data.Integrity }}"
crossorigin="anonymous" />
{{ end }}
{{ $.Scratch.Set "stylesheet" . }}
{{ end }}
<meta
name="description"
content="{{ with .Description }}
{{ . }}
{{ else }}
{{ with .Site.Params.description }}{{ . }}{{ end }}
{{ end }}
" />
{{ block "scripts" . }}
{{- partial "site-scripts.html" . -}}
{{ end }}
{{ partial "site-manifest.html" . }}
{{- partial "head-additions.html" . -}}
{{- partial "opengraph/opengraph.html" . -}}
{{- template "_internal/schema.html" . -}}
{{- partial "opengraph/twitter_cards.html" . -}}
{{ if hugo.IsProduction }}
{{ partial "gtag.html" . }}
{{ end }}
{{ $hasMath := .Param "math" }}
{{ if $hasMath }}
{{ partialCached "math.html" . }}
{{ end }}
</head>
<body
class="ma0 sans-serif bg-primary-color-light{{ with getenv "HUGO_ENV" }} {{ . }}{{ end }}">
{{ partial "hooks/after-body-start.html" . }}
{{ block "nav" . }}{{ partial "site-nav.html" . }}{{ end }}
{{ block "header" . }}{{ end }}
<main role="main" class="content-with-sidebar min-vh-100 pb7 pb0-ns">
{{ block "main" . }}{{ end }}
</main>
{{ block "footer" . }}{{ partialCached "site-footer.html" . }}{{ end }}
{{ partial "hooks/before-body-end.html" . }}
</body>
</html>
@@ -1,4 +0,0 @@
{{ define "main" }}
{{ $section_to_display := (.Site.Taxonomies.categories.fundamentals).Pages | lang.Merge (.Sites.Default.Taxonomies.categories.fundamentals).Pages }}
{{ partial "pagelayout.html" (dict "context" . "section_to_display" $section_to_display ) }}
{{ end }}
@@ -1,5 +0,0 @@
{{ define "main" }}
{{ $paginator := .Paginate (.Pages | lang.Merge (where .Sites.Default.RegularPages "Section" .Section)) }}
{{ $section_to_display := .Sections | default $paginator.Pages }}
{{ partial "pagelayout.html" (dict "context" . "section_to_display" $section_to_display ) }}
{{ end }}
@@ -1,48 +0,0 @@
<header class="flex-none w-100">
{{ if in (slice "functions" "methods") .Type }}
{{ with .FirstSection }}
<a href="{{ .RelPermalink }}" class="f6 fw8 mb0 link mid-gray dim mr3">
{{ humanize .Title | upper }}
</a>
{{ end }}
{{ with .CurrentSection }}
<a href="{{ .RelPermalink }}" class="f6 fw8 mb0 link mid-gray dim mr3">
{{ humanize .Title | upper }}
</a>
{{ end }}
{{ else }}
{{ range .Params.categories }}
<a href="{{ "/categories/" | relLangURL }}{{ . | urlize }}" class="f6 fw8 mb0 link mid-gray dim mr3">
{{ humanize . | upper }}
</a>
{{ end }}
{{ end }}
<h1 class="lh-title mb3 mv0 pt3 primary-color-dark">
{{ .Title }}
</h1>
</header>
<aside class="bt bw1 pt3 mt2 mid-gray b--mid-gray fn w-100">
{{ with .Params.description }}
<div class="mb4 f4 fw4 lh-copy">
{{ . | markdownify }}
</div>
{{ end }}
<!--
NOTE: Removed to test builds without it.
partial "components/author-github-data" (dict "context" . "size" "110") -->
</aside>
{{ with .Params.featured_image_path }}
<img src="{{ . }}" alt="Featured Image for {{ $.Title }}" class="mw-100">
{{ end }}
<div class="prose" id="prose">
<div class="mb4">
{{- partial "docs/functions-signatures.html" . -}}
{{- partial "docs/functions-return-type.html" . -}}
{{- partial "docs/functions-aliases.html" . -}}
</div>
{{ .Content }}
</div>
@@ -1,29 +0,0 @@
{{ define "main" }}
<article class="w-100 ph4 pb5 pb6-ns pt1 pt5-ns">
<div class="flex-l">
<div class="order-0 w-20 dn db-l">
{{ partial "nav-links-docs.html" . }}
</div>
<div class="order-1 flex-grow-1 ph0 ph5-ns mt0-ns mid-gray nested-copy-line-height no-underline nested-links nested-img nested-copy-seperator nested-blockquote">
<div style="max-width: 40rem;" class="documentation-copy">
<div id="readout" class="fixed right-0 bottom-0"></div>
{{ .Render "page" }}
{{ partial "related.html" . }}
</div>
</div>
<div id="right-sidebar" class="order-2 w-20 dn db-l sticky pt2">
{{ partial "right-sidebar.html" . }}
</div>
</div>
</article>
<div id="page-footer" class="w-100 bg-light-gray">
<div class="mw7 pa4 center nested-lh-copy lh-copy">
{{ partial "docs/page-meta-data.html" . }}
{{ partial "page-edit.html" . }}
{{ partial "tags.html" . }}
</div>
</div>
{{ end }}
@@ -1,4 +0,0 @@
{{ define "main" }}
{{ $section_to_display := .Pages }}
{{ partial "pagelayout.html" (dict "context" . "section_to_display" $section_to_display ) }}
{{ end }}
@@ -1,48 +0,0 @@
{{ define "main" }}
{{ $section_to_display := .Pages }}
<div class="w-100 ph4 pb5 pb6-ns pt1 pt3-ns">
<div class="flex">
<div class="dn db-l w-20">
{{ partial "nav-links-docs.html" . }}
</div>
<div class="w-100 w-80-l ph0 ph4-l">
<article class="w-100 nested-copy-line-height nested-links nested-img">
<h1 class="primary-color-dark f2">
{{ .Title }}
</h1>
</article>
<div class="pa3 pa4-ns w-100 v-top column-count-3-l column-gap-1-l">
{{ range $key, $value := .Data.Terms }}
<div class="break-inside-avoid-l nested-copy-line-height mb5">
<h2 class="f3">
<a href="{{ "/" | relLangURL }}{{ $.Data.Plural | urlize }}/{{ $key | urlize }}" class="link black hover-blue">
{{ $key }} <span class="f6 gray"> &#8599;</span>
</a>
</h2>
{{ range $value.Pages }}
<h3>
<a href="{{ .Permalink }}" class="link blue">
{{ .Title }}
</a>
</h3>
{{ end }}
</div>
{{ end }}
</div>
</div>
</div>
</div>
{{ end }}
@@ -1,27 +0,0 @@
{{ define "header" }}
{{ partial "hero.html" . }}
{{ partial "boxes-small-news.html" . }}
{{ end }}
{{ define "main" }}
<section class="w-100 ph4 ph5-ns pv4">
{{- partial "home-page-sections/features-icons.html" . -}}
</section>
{{ partial "home-page-sections/sponsors.html" (dict "cx" . "gtag" "home" ) }}
{{- partial "home-page-sections/features-single.html" . -}}
{{/*- partial "home-page-sections/showcase.html" . -*/}}
<section class="w-100 ph4 ph5-ns pv4 pv6-ns mid-gray bg-white bb bt b--light-gray">
{{- partial "home-page-sections/installation.html" . -}}
</section>
<section class="w-100 ph4 ph5-ns pv4 pv6-ns mid-gray bg-accent-color-dark">
{{- partial "home-page-sections/tweets.html" . -}}
</section>
<section class="w-100 ph4 ph5-ns pt4 pb5 mid-gray bg-primary-color-light bb bt b--light-gray ">
{{- partial "home-page-sections/open-source-involvement.html" . -}}
</section>
{{ end }}

Some files were not shown because too many files have changed in this diff Show More