diff options
author | Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com> | 2024-01-27 10:48:33 +0100 |
---|---|---|
committer | Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com> | 2024-01-27 10:48:57 +0100 |
commit | 5fd1e7490305570872d3899f5edda950903c5213 (patch) | |
tree | f0cdc490a0942d720494c0044a64c6397d1ab6a5 /docs/content/en | |
parent | fc7de7136acbcf0aef54ae8460c7702bc83709be (diff) | |
parent | 9b0050e9aabe4be65c78ccf292a348f309d50ccd (diff) | |
download | hugo-5fd1e7490305570872d3899f5edda950903c5213.tar.gz hugo-5fd1e7490305570872d3899f5edda950903c5213.zip |
Merge commit '9b0050e9aabe4be65c78ccf292a348f309d50ccd' as 'docs'
```
git subtree add --prefix=docs/ https://github.com/gohugoio/hugoDocs.git master --squash
```
Closes #11925
Diffstat (limited to 'docs/content/en')
788 files changed, 44090 insertions, 0 deletions
diff --git a/docs/content/en/_index.md b/docs/content/en/_index.md new file mode 100644 index 000000000..69d40ebcf --- /dev/null +++ b/docs/content/en/_index.md @@ -0,0 +1,49 @@ +--- +title: The world’s fastest framework for building websites +date: 2017-03-02T12:00:00-05:00 +features: + - heading: Blistering Speed + image_path: /images/icon-fast.svg + tagline: What's modern about waiting for your site to build? + copy: Hugo is the fastest tool of its kind. At <1 ms per page, the average site builds in less than a second. + + - heading: Robust Content Management + image_path: /images/icon-content-management.svg + tagline: Flexibility rules. Hugo is a content strategist's dream. + copy: Hugo supports unlimited content types, taxonomies, menus, dynamic API-driven content, and more, all without plugins. + + - heading: Shortcodes + image_path: /images/icon-shortcodes.svg + tagline: Hugo's shortcodes are Markdown's hidden superpower. + copy: We love the beautiful simplicity of markdown’s syntax, but there are times when we want more flexibility. Hugo shortcodes allow for both beauty and flexibility. + + - heading: Built-in Templates + image_path: /images/icon-built-in-templates.svg + tagline: Hugo has common patterns to get your work done quickly. + copy: Hugo ships with pre-made templates to make quick work of SEO, commenting, analytics and other functions. One line of code, and you're done. + + - heading: Multilingual and i18n + image_path: /images/icon-multilingual2.svg + tagline: Polyglot baked in. + copy: Hugo provides full i18n support for multi-language sites with the same straightforward development experience Hugo users love in single-language sites. + + - heading: Custom Outputs + image_path: /images/icon-custom-outputs.svg + tagline: HTML not enough? + copy: Hugo allows you to output your content in multiple formats, including JSON or AMP, and makes it easy to create your own. +sections: + - heading: "300+ Themes" + cta: Check out the Hugo themes. + link: https://themes.gohugo.io/ + color_classes: bg-accent-color white + image: /images/homepage-screenshot-hugo-themes.jpg + copy: "Hugo provides a robust theming system that is easy to implement but capable of producing even the most complicated websites." + - heading: "Capable Templating" + cta: Get Started. + link: templates/ + color_classes: bg-primary-color-light black + image: /images/home-page-templating-example.png + copy: "Hugo's Go-based templating provides just the right amount of logic to build anything from the simple to complex." +--- + +Hugo is one of the most popular open-source static site generators. With its amazing speed and flexibility, Hugo makes building websites fun again. diff --git a/docs/content/en/about/_index.md b/docs/content/en/about/_index.md new file mode 100644 index 000000000..3a8319029 --- /dev/null +++ b/docs/content/en/about/_index.md @@ -0,0 +1,16 @@ +--- +title: About Hugo +linkTitle: Overview +description: Hugo's features, roadmap, license, and motivation. +categories: [] +keywords: [] +menu: + docs: + identifier: about-hugo-overview + parent: about + weight: 10 +weight: 10 +aliases: [/about-hugo/,/docs/] +--- + +Hugo is not your average static site generator. diff --git a/docs/content/en/about/benefits.md b/docs/content/en/about/benefits.md new file mode 100644 index 000000000..82952c4e6 --- /dev/null +++ b/docs/content/en/about/benefits.md @@ -0,0 +1,36 @@ +--- +title: Benefits of static site generators +linkTitle: Static site generators +description: Improved performance, security and ease of use are just a few of the reasons static site generators are so appealing. +categories: [about] +keywords: [ssg,static,performance,security] +menu: + docs: + parent: about + weight: 40 +weight: 40 +--- + +The purpose of website generators is to render content into HTML files. Most are "dynamic site generators." That means the HTTP server---i.e., the program that sends files to the browser to be viewed---runs the generator to create a new HTML file every time an end user requests a page. + +Over time, dynamic site generators were programmed to cache their HTML files to prevent unnecessary delays in delivering pages to end users. A cached page is a static version of a web page. + +Hugo takes caching a step further and all HTML files are rendered on your computer. You can review the files locally before copying them to the computer hosting the HTTP server. Since the HTML files aren't generated dynamically, we say that Hugo is a *static site generator*. + +This has many benefits. The most noticeable is performance. HTTP servers are *very* good at sending files---so good, in fact, that you can effectively serve the same number of pages with a fraction of the memory and CPU needed for a dynamic site. + +## More on static site generators + +* ["An Introduction to Static Site Generators", David Walsh] +* ["Hugo vs. WordPress page load speed comparison: Hugo leaves WordPress in its dust", GettingThingsTech][hugovwordpress] +* ["Static Site Generators", O'Reilly] +* [StaticGen: Top Open-Source Static Site Generators (GitHub Stars)] +* ["Top 10 Static Website Generators", Netlify blog] +* ["The Resurgence of Static", dotCMS][dotcms] + +["An Introduction to Static Site Generators", David Walsh]: https://davidwalsh.name/introduction-static-site-generators +["Static Site Generators", O'Reilly]: https://github.com/gohugoio/hugoDocs/files/1242701/static-site-generators.pdf +["Top 10 Static Website Generators", Netlify blog]: https://www.netlify.com/blog/2016/05/02/top-ten-static-website-generators/ +[hugovwordpress]: https://gettingthingstech.com/hugo-vs.-wordpress-page-load-speed-comparison-hugo-leaves-wordpress-in-its-dust/ +[StaticGen: Top Open-Source Static Site Generators (GitHub Stars)]: https://www.staticgen.com/ +[dotcms]: https://dotcms.com/blog/post/the-resurgence-of-static diff --git a/docs/content/en/about/features.md b/docs/content/en/about/features.md new file mode 100644 index 000000000..a94ce5526 --- /dev/null +++ b/docs/content/en/about/features.md @@ -0,0 +1,80 @@ +--- +title: Hugo features +description: Hugo boasts blistering speed, robust content management, and a powerful templating language making it a great fit for all kinds of static websites. +categories: [about] +keywords: [] +menu: + docs: + parent: about + weight: 30 +weight: 30 +toc: true +--- + +## General + +* [Extremely fast] build times (< 1 ms per page) +* Completely cross platform, with [easy installation][install] on macOS, Linux, Windows, and more +* Renders changes on the fly with [LiveReload] as you develop +* [Powerful theming] +* [Host your site anywhere][hostanywhere] + +## Organization + +* Straightforward [organization for your projects], including website sections +* Customizable [URLs] +* Support for configurable [taxonomies], including categories and tags +* [Sort content] as you desire through powerful template [functions] +* Automatic [table of contents] generation +* [Dynamic menu] creation +* [Pretty URLs] support +* [Permalink] pattern support +* Redirects via [aliases] + +## Content + +* Native Markdown and Emacs Org-Mode support, as well as other languages via *external helpers* (see [supported formats]) +* TOML, YAML, and JSON metadata support in [front matter] +* Customizable [homepage] +* Multiple [content types] +* Automatic and user defined [content summaries] +* [Shortcodes] to enable rich content inside of Markdown +* ["Minutes to Read"][pagevars] functionality +* ["WordCount"][pagevars] functionality + +## Additional features + +* Integrated [Disqus] comment support +* Integrated [Google Analytics] support +* Automatic [RSS] creation +* Support for [Go] HTML templates +* [Syntax highlighting] powered by [Chroma] + +[aliases]: /content-management/urls/#aliases +[Chroma]: https://github.com/alecthomas/chroma +[content summaries]: /content-management/summaries/ +[content types]: /content-management/types/ +[Disqus]: https://disqus.com/ +[Dynamic menu]: /templates/menu-templates/ +[Extremely fast]: https://github.com/bep/hugo-benchmark +[front matter]: /content-management/front-matter/ +[functions]: /functions/ +[Go]: https://pkg.go.dev/html/template +[Google Analytics]: https://google-analytics.com/ +[homepage]: /templates/homepage/ +[hostanywhere]: /hosting-and-deployment/ +[install]: /installation/ +[LiveReload]: /getting-started/usage/ +[organization for your projects]: /getting-started/directory-structure/ +[pagevars]: /variables/page/ +[Permalink]: /content-management/urls/#permalinks +[Powerful theming]: /hugo-modules/theme-components/ +[Pretty URLs]: /content-management/urls/ +[RSS]: /templates/rss/ +[Shortcodes]: /content-management/shortcodes/ +[sort content]: /templates/ +[supported formats]: /content-management/formats/ +[Syntax highlighting]: /content-management/syntax-highlighting/ +[table of contents]: /content-management/toc/ +[taxonomies]: /content-management/taxonomies/ +[URLs]: /content-management/urls/ diff --git a/docs/content/en/about/hugo-and-gdpr.md b/docs/content/en/about/hugo-and-gdpr.md new file mode 100644 index 000000000..daf4e80f0 --- /dev/null +++ b/docs/content/en/about/hugo-and-gdpr.md @@ -0,0 +1,134 @@ +--- +title: Hugo and the General Data Protection Regulation +linkTitle: Hugo and the GDPR +description: About how to configure your Hugo site to meet the new regulations. +categories: [about] +keywords: ["GDPR", "Privacy", "Data Protection"] +menu: + docs: + parent: about + weight: 60 +weight: 60 +toc: true +aliases: [/privacy/,/gdpr/] +--- + + General Data Protection Regulation ([GDPR](https://en.wikipedia.org/wiki/General_Data_Protection_Regulation)) is a regulation in EU law on data protection and privacy for all individuals within the European Union and the European Economic Area. It became enforceable on 25 May 2018. + + **Hugo is a static site generator. By using Hugo you are already standing on very solid ground. Static HTML files on disk are much easier to reason about compared to server and database driven web sites.** + + But even static websites can integrate with external services, so from version `0.41`, Hugo provides a **privacy configuration** that covers the relevant built-in templates. + + Note that: + + * These settings have their defaults setting set to _off_, i.e. how it worked before Hugo `0.41`. You must do your own evaluation of your site and apply the appropriate settings. + * These settings work with the [internal templates](/templates/internal/). Some theme may contain custom templates for embedding services like Google Analytics. In that case these options have no effect. + * We will continue this work and improve this further in future Hugo versions. + +## All privacy settings + +Below are all privacy settings and their default value. These settings need to be put in your site configuration (e.g. `hugo.toml`). + +{{< code-toggle file=hugo >}} +[privacy] +[privacy.disqus] +disable = false +[privacy.googleAnalytics] +disable = false +respectDoNotTrack = false +anonymizeIP = false +useSessionStorage = false +[privacy.instagram] +disable = false +simple = false +[privacy.twitter] +disable = false +enableDNT = false +simple = false +[privacy.vimeo] +disable = false +enableDNT = false +simple = false +[privacy.youtube] +disable = false +privacyEnhanced = false +{{< /code-toggle >}} + +## Disable all services + +An example privacy configuration that disables all the relevant services in Hugo. With this configuration, the other settings will not matter. + +{{< code-toggle file=hugo >}} +[privacy] +[privacy.disqus] +disable = true +[privacy.googleAnalytics] +disable = true +[privacy.instagram] +disable = true +[privacy.twitter] +disable = true +[privacy.vimeo] +disable = true +[privacy.youtube] +disable = true +{{< /code-toggle >}} + +## The privacy settings explained + +### GoogleAnalytics + +anonymizeIP +: Enabling this will make it so the users' IP addresses are anonymized within Google Analytics. + +respectDoNotTrack +: Enabling this will make the GA templates respect the "Do Not Track" HTTP header. + +useSessionStorage +: Enabling this will disable the use of Cookies and use Session Storage to Store the GA Client ID. + +{{% note %}} +`useSessionStorage` is not supported when using Google Analytics v4 (gtag.js). +{{% /note %}} + +### Instagram + +simple +: If simple mode is enabled, a static and no-JS version of the Instagram image card will be built. Note that this only supports image cards and the image itself will be fetched from Instagram's servers. + +**Note:** If you use the _simple mode_ for Instagram and a site styled with Bootstrap 4, you may want to disable the inline styles provided by Hugo: + +{{< code-toggle file=hugo >}} +[services] +[services.instagram] +disableInlineCSS = true +{{< /code-toggle >}} + +### Twitter + +enableDNT +: Enabling this for the twitter/tweet shortcode, the tweet and its embedded page on your site are not used for purposes that include personalized suggestions and personalized ads. + +simple +: If simple mode is enabled, a static and no-JS version of a tweet will be built. + +**Note:** If you use the _simple mode_ for Twitter, you may want to disable the inline styles provided by Hugo: + +{{< code-toggle file=hugo >}} +[services] +[services.twitter] +disableInlineCSS = true +{{< /code-toggle >}} + +### YouTube + +privacyEnhanced +: When you turn on privacy-enhanced mode, YouTube won’t store information about visitors on your website unless the user plays the embedded video. + +### Vimeo + +enableDNT +: Enabling this for the vimeo shortcode, the Vimeo player will be blocked from tracking any session data, including all cookies and stats. + +simple +: If simple mode is enabled, the video thumbnail is fetched from Vimeo's servers and it is overlaid with a play button. If the user clicks to play the video, it will open in a new tab directly on Vimeo's website. diff --git a/docs/content/en/about/license.md b/docs/content/en/about/license.md new file mode 100644 index 000000000..e488bb87a --- /dev/null +++ b/docs/content/en/about/license.md @@ -0,0 +1,80 @@ +--- +title: License +description: Hugo is released under the Apache 2.0 license. +categories: [about] +keywords: [license,apache] +menu: + docs: + parent: about + weight: 70 +weight: 70 +--- + +## Apache License + + +_Version 2.0, January 2004_ +_<http://www.apache.org/licenses/>_ + +### 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. diff --git a/docs/content/en/about/security-model.md b/docs/content/en/about/security-model.md new file mode 100644 index 000000000..af1dd7d75 --- /dev/null +++ b/docs/content/en/about/security-model.md @@ -0,0 +1,63 @@ +--- +title: Hugo's security model +description: A summary of Hugo's security model. +categories: [about] +keywords: [security,privacy] +menu: + docs: + parent: about + weight: 50 +weight: 50 +toc: true +aliases: [/security/] +--- + +## Runtime security + +Hugo produces static output, so once built, the runtime is the browser (assuming the output is HTML) and any server (API) that you integrate with. + +But when developing and building your site, the runtime is the `hugo` executable. Securing a runtime can be [a real challenge](https://blog.logrocket.com/how-to-protect-your-node-js-applications-from-malicious-dependencies-5f2e60ea08f9/). + +**Hugo's main approach is that of sandboxing and a security policy with strict defaults:** + +* Hugo has a virtual file system and only the main project (not third-party components) is allowed to mount directories or files outside the project root. +* Only the main project can walk symbolic links. +* User-defined components have read-only access to the filesystem. +* We shell out to some external binaries to support [Asciidoctor](/content-management/formats/#list-of-content-formats) and similar, but those binaries and their flags are predefined and disabled by default (see [Security Policy](#security-policy)). General functions to run arbitrary external OS commands have been [discussed](https://github.com/gohugoio/hugo/issues/796), but not implemented because of security concerns. + +## Security policy + +Hugo has a built-in security policy that restricts access to [os/exec](https://pkg.go.dev/os/exec), remote communication and similar. + +The default configuration is listed below. Any build using features not in the allow list of the security policy will fail with a detailed message about what needs to be done. Most of these settings are allow lists (string or slice, [Regular Expressions](https://pkg.go.dev/regexp) or `none` which matches nothing). + +{{< code-toggle config=security />}} + +Note that these and other configuration settings in Hugo can be overridden by the OS environment. If you want to block all remote HTTP fetching of data: + +```txt +HUGO_SECURITY_HTTP_URLS=none hugo +``` + +## Dependency security + +Hugo is built as a static binary using [Go Modules](https://github.com/golang/go/wiki/Modules) to manage its dependencies. Go Modules have several safeguards, one of them being the `go.sum` file. This is a database of the expected cryptographic checksums of all of your dependencies, including transitive dependencies. + +[Hugo Modules](/hugo-modules/) is a feature built on top of the functionality of Go Modules. Like Go Modules, a Hugo project using Hugo Modules will have a `go.sum` file. We recommend that you commit this file to your version control system. The Hugo build will fail if there is a checksum mismatch, which would be an indication of [dependency tampering](https://julienrenaux.fr/2019/12/20/github-actions-security-risk/). + +## Web application security + +These are the security threats as defined by [OWASP](https://en.wikipedia.org/wiki/OWASP). + +For HTML output, this is the core security model: + +<https://pkg.go.dev/html/template#hdr-Security_Model> + +In short: + +Template and configuration authors (you) are trusted, but the data you send in is not. +This is why you sometimes need to use the _safe_ functions, such as `safeHTML`, to avoid escaping of data you know is safe. +There is one exception to the above, as noted in the documentation: If you enable inline shortcodes, you also say that the shortcodes and data handling in content files are trusted, as those macros are treated as pure text. +It may be worth adding that Hugo is a static site generator with no concept of dynamic user input. + +For content, the default Markdown renderer is [configured](/getting-started/configuration-markup) to remove or escape potentially unsafe content. This behavior can be reconfigured if you trust your content. diff --git a/docs/content/en/about/what-is-hugo.md b/docs/content/en/about/what-is-hugo.md new file mode 100644 index 000000000..e4326d173 --- /dev/null +++ b/docs/content/en/about/what-is-hugo.md @@ -0,0 +1,57 @@ +--- +title: What is Hugo +description: Hugo is a fast and modern static site generator written in Go, and designed to make website creation fun again. +categories: [about] +keywords: [] +menu: + docs: + parent: about + weight: 20 +weight: 20 +toc: true +aliases: [/overview/introduction/,/about/why-i-built-hugo/] +--- + +Hugo is a general-purpose website framework. Technically speaking, Hugo is a [static site generator]. Unlike systems that dynamically build a page with each visitor request, Hugo builds pages when you create or update your content. Since websites are viewed far more often than they are edited, Hugo is designed to provide an optimal viewing experience for your website's end users and an ideal writing experience for website authors. + +Websites built with Hugo are extremely fast and secure. Hugo sites can be hosted anywhere, including [Netlify], [Heroku], [GoDaddy], [DreamHost], [GitHub Pages], [GitLab Pages], [Surge], [Firebase], [Google Cloud Storage], [Amazon S3], [Rackspace], [Azure], and [CloudFront] and work well with CDNs. Hugo sites run without the need for a database or dependencies on expensive runtimes like Ruby, Python, or PHP. + +We think of Hugo as the ideal website creation tool with nearly instant build times, able to rebuild whenever a change is made. + +## How fast is Hugo? + +{{< youtube "CdiDYZ51a2o" >}} + +## What does Hugo do? + +In technical terms, Hugo takes a source directory of files and templates and uses these as input to create a complete website. + +## Who should use Hugo? + +Hugo is for people that prefer writing in a text editor over a browser. + +Hugo is for people who want to hand code their own website without worrying about setting up complicated runtimes, dependencies and databases. + +Hugo is for people building a blog, a company site, a portfolio site, documentation, a single landing page, or a website with thousands of pages. + +[@spf13]: https://twitter.com/spf13 +[Amazon S3]: https://aws.amazon.com/s3/ +[Azure]: https://docs.microsoft.com/en-us/azure/storage/blobs/storage-blob-static-website +[CloudFront]: https://aws.amazon.com/cloudfront/ +[DreamHost]: https://www.dreamhost.com/ +[Firebase]: https://firebase.google.com/docs/hosting/ +[GitHub Pages]: https://pages.github.com/ +[GitLab Pages]: https://about.gitlab.com/features/pages/ +[Go language]: https://go.dev/ +[GoDaddy]: https://www.godaddy.com/ +[Google Cloud Storage]: https://cloud.google.com/storage/ +[Heroku]: https://www.heroku.com/ +[Jekyll]: https://jekyllrb.com/ +[Middleman]: https://middlemanapp.com/ +[Nanoc]: https://nanoc.ws/ +[Netlify]: https://netlify.com +[Rackspace]: https://www.rackspace.com/cloud/files +[Surge]: https://surge.sh +[contributing to it]: https://github.com/gohugoio/hugo +[rackspace]: https://www.rackspace.com/openstack/public/files +[static site generator]: /about/benefits/ diff --git a/docs/content/en/commands/hugo.md b/docs/content/en/commands/hugo.md new file mode 100644 index 000000000..fa8f6d1ed --- /dev/null +++ b/docs/content/en/commands/hugo.md @@ -0,0 +1,84 @@ +--- +title: "hugo" +slug: hugo +url: /commands/hugo/ +--- +## hugo + +hugo builds your site + +### Synopsis + +hugo is the main command, used to build your Hugo site. + +Hugo is a Fast and Flexible Static Site Generator +built with love by spf13 and friends in Go. + +Complete documentation is available at https://gohugo.io/. + +``` +hugo [flags] +``` + +### Options + +``` + -b, --baseURL string hostname (and path) to the root, e.g. https://spf13.com/ + -D, --buildDrafts include content marked as draft + -E, --buildExpired include expired content + -F, --buildFuture include content with publishdate in the future + --cacheDir string filesystem path to cache directory + --cleanDestinationDir remove files from destination not found in static directories + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + -c, --contentDir string filesystem path to content directory + --debug debug output + -d, --destination string filesystem path to write files to + --disableKinds strings disable different kind of pages (home, RSS etc.) + --enableGitInfo add Git revision, date, author, and CODEOWNERS info to the pages + -e, --environment string build environment + --forceSyncStatic copy all files when static is changed. + --gc enable to run some cleanup tasks (remove unused cache files) after the build + -h, --help help for hugo + --ignoreCache ignores the cache directory + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + -l, --layoutDir string filesystem path to layout directory + --logLevel string log level (debug|info|warn|error) + --minify minify any supported output format (HTML, XML etc.) + --noBuildLock don't create .hugo_build.lock file + --noChmod don't sync permission mode of files + --noTimes don't sync modification time of files + --panicOnWarning panic on first WARNING log + --poll string set this to a poll interval, e.g --poll 700ms, to use a poll based approach to watch for file system changes + --printI18nWarnings print missing translations + --printMemoryUsage print memory usage to screen at intervals + --printPathWarnings print warnings on duplicate target paths etc. + --printUnusedTemplates print warnings on unused templates. + --quiet build in quiet mode + --renderToMemory render to memory (only useful for benchmark testing) + -s, --source string filesystem path to read files relative from + --templateMetrics display metrics about template executions + --templateMetricsHints calculate some improvement hints when combined with --templateMetrics + -t, --theme strings themes to use (located in /themes/THEMENAME/) + --themesDir string filesystem path to themes directory + --trace file write trace to file (not useful in general) + -v, --verbose verbose output + -w, --watch watch filesystem for changes and recreate as needed +``` + +### SEE ALSO + +* [hugo completion](/commands/hugo_completion/) - Generate the autocompletion script for the specified shell +* [hugo config](/commands/hugo_config/) - Print the site configuration +* [hugo convert](/commands/hugo_convert/) - Convert your content to different formats +* [hugo deploy](/commands/hugo_deploy/) - Deploy your site to a Cloud provider. +* [hugo env](/commands/hugo_env/) - Print Hugo version and environment info +* [hugo gen](/commands/hugo_gen/) - A collection of several useful generators. +* [hugo import](/commands/hugo_import/) - Import your site from others. +* [hugo list](/commands/hugo_list/) - Listing out various types of content +* [hugo mod](/commands/hugo_mod/) - Various Hugo Modules helpers. +* [hugo new](/commands/hugo_new/) - Create new content for your site +* [hugo server](/commands/hugo_server/) - A high performance webserver +* [hugo version](/commands/hugo_version/) - Print Hugo version and environment info + diff --git a/docs/content/en/commands/hugo_completion.md b/docs/content/en/commands/hugo_completion.md new file mode 100644 index 000000000..c9b370da6 --- /dev/null +++ b/docs/content/en/commands/hugo_completion.md @@ -0,0 +1,46 @@ +--- +title: "hugo completion" +slug: hugo_completion +url: /commands/hugo_completion/ +--- +## hugo completion + +Generate the autocompletion script for the specified shell + +### Synopsis + +Generate the autocompletion script for hugo for the specified shell. +See each sub-command's help for details on how to use the generated script. + + +### Options + +``` + -h, --help help for completion +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + --debug debug output + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --quiet build in quiet mode + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory + -v, --verbose verbose output +``` + +### SEE ALSO + +* [hugo](/commands/hugo/) - hugo builds your site +* [hugo completion bash](/commands/hugo_completion_bash/) - Generate the autocompletion script for bash +* [hugo completion fish](/commands/hugo_completion_fish/) - Generate the autocompletion script for fish +* [hugo completion powershell](/commands/hugo_completion_powershell/) - Generate the autocompletion script for powershell +* [hugo completion zsh](/commands/hugo_completion_zsh/) - Generate the autocompletion script for zsh + diff --git a/docs/content/en/commands/hugo_completion_bash.md b/docs/content/en/commands/hugo_completion_bash.md new file mode 100644 index 000000000..875ecfc19 --- /dev/null +++ b/docs/content/en/commands/hugo_completion_bash.md @@ -0,0 +1,65 @@ +--- +title: "hugo completion bash" +slug: hugo_completion_bash +url: /commands/hugo_completion_bash/ +--- +## hugo completion bash + +Generate the autocompletion script for bash + +### Synopsis + +Generate the autocompletion script for the bash shell. + +This script depends on the 'bash-completion' package. +If it is not installed already, you can install it via your OS's package manager. + +To load completions in your current shell session: + + source <(hugo completion bash) + +To load completions for every new session, execute once: + +#### Linux: + + hugo completion bash > /etc/bash_completion.d/hugo + +#### macOS: + + hugo completion bash > $(brew --prefix)/etc/bash_completion.d/hugo + +You will need to start a new shell for this setup to take effect. + + +``` +hugo completion bash +``` + +### Options + +``` + -h, --help help for bash + --no-descriptions disable completion descriptions +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + --debug debug output + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --quiet build in quiet mode + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory + -v, --verbose verbose output +``` + +### SEE ALSO + +* [hugo completion](/commands/hugo_completion/) - Generate the autocompletion script for the specified shell + diff --git a/docs/content/en/commands/hugo_completion_fish.md b/docs/content/en/commands/hugo_completion_fish.md new file mode 100644 index 000000000..87b84a702 --- /dev/null +++ b/docs/content/en/commands/hugo_completion_fish.md @@ -0,0 +1,56 @@ +--- +title: "hugo completion fish" +slug: hugo_completion_fish +url: /commands/hugo_completion_fish/ +--- +## hugo completion fish + +Generate the autocompletion script for fish + +### Synopsis + +Generate the autocompletion script for the fish shell. + +To load completions in your current shell session: + + hugo completion fish | source + +To load completions for every new session, execute once: + + hugo completion fish > ~/.config/fish/completions/hugo.fish + +You will need to start a new shell for this setup to take effect. + + +``` +hugo completion fish [flags] +``` + +### Options + +``` + -h, --help help for fish + --no-descriptions disable completion descriptions +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + --debug debug output + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --quiet build in quiet mode + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory + -v, --verbose verbose output +``` + +### SEE ALSO + +* [hugo completion](/commands/hugo_completion/) - Generate the autocompletion script for the specified shell + diff --git a/docs/content/en/commands/hugo_completion_powershell.md b/docs/content/en/commands/hugo_completion_powershell.md new file mode 100644 index 000000000..77cfeda5f --- /dev/null +++ b/docs/content/en/commands/hugo_completion_powershell.md @@ -0,0 +1,53 @@ +--- +title: "hugo completion powershell" +slug: hugo_completion_powershell +url: /commands/hugo_completion_powershell/ +--- +## hugo completion powershell + +Generate the autocompletion script for powershell + +### Synopsis + +Generate the autocompletion script for powershell. + +To load completions in your current shell session: + + hugo completion powershell | Out-String | Invoke-Expression + +To load completions for every new session, add the output of the above command +to your powershell profile. + + +``` +hugo completion powershell [flags] +``` + +### Options + +``` + -h, --help help for powershell + --no-descriptions disable completion descriptions +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + --debug debug output + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --quiet build in quiet mode + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory + -v, --verbose verbose output +``` + +### SEE ALSO + +* [hugo completion](/commands/hugo_completion/) - Generate the autocompletion script for the specified shell + diff --git a/docs/content/en/commands/hugo_completion_zsh.md b/docs/content/en/commands/hugo_completion_zsh.md new file mode 100644 index 000000000..84856b6b3 --- /dev/null +++ b/docs/content/en/commands/hugo_completion_zsh.md @@ -0,0 +1,67 @@ +--- +title: "hugo completion zsh" +slug: hugo_completion_zsh +url: /commands/hugo_completion_zsh/ +--- +## hugo completion zsh + +Generate the autocompletion script for zsh + +### Synopsis + +Generate the autocompletion script for the zsh shell. + +If shell completion is not already enabled in your environment you will need +to enable it. You can execute the following once: + + echo "autoload -U compinit; compinit" >> ~/.zshrc + +To load completions in your current shell session: + + source <(hugo completion zsh) + +To load completions for every new session, execute once: + +#### Linux: + + hugo completion zsh > "${fpath[1]}/_hugo" + +#### macOS: + + hugo completion zsh > $(brew --prefix)/share/zsh/site-functions/_hugo + +You will need to start a new shell for this setup to take effect. + + +``` +hugo completion zsh [flags] +``` + +### Options + +``` + -h, --help help for zsh + --no-descriptions disable completion descriptions +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + --debug debug output + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --quiet build in quiet mode + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory + -v, --verbose verbose output +``` + +### SEE ALSO + +* [hugo completion](/commands/hugo_completion/) - Generate the autocompletion script for the specified shell + diff --git a/docs/content/en/commands/hugo_config.md b/docs/content/en/commands/hugo_config.md new file mode 100644 index 000000000..3ec3748a3 --- /dev/null +++ b/docs/content/en/commands/hugo_config.md @@ -0,0 +1,51 @@ +--- +title: "hugo config" +slug: hugo_config +url: /commands/hugo_config/ +--- +## hugo config + +Print the site configuration + +### Synopsis + +Print the site configuration, both default and custom settings. + +``` +hugo config [command] [flags] +``` + +### Options + +``` + -b, --baseURL string hostname (and path) to the root, e.g. https://spf13.com/ + --cacheDir string filesystem path to cache directory + -c, --contentDir string filesystem path to content directory + --format string preferred file format (toml, yaml or json) (default "toml") + -h, --help help for config + --lang string the language to display config for. Defaults to the first language defined. + -t, --theme strings themes to use (located in /themes/THEMENAME/) +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + --debug debug output + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --quiet build in quiet mode + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory + -v, --verbose verbose output +``` + +### SEE ALSO + +* [hugo](/commands/hugo/) - hugo builds your site +* [hugo config mounts](/commands/hugo_config_mounts/) - Print the configured file mounts + diff --git a/docs/content/en/commands/hugo_config_mounts.md b/docs/content/en/commands/hugo_config_mounts.md new file mode 100644 index 000000000..90b171912 --- /dev/null +++ b/docs/content/en/commands/hugo_config_mounts.md @@ -0,0 +1,44 @@ +--- +title: "hugo config mounts" +slug: hugo_config_mounts +url: /commands/hugo_config_mounts/ +--- +## hugo config mounts + +Print the configured file mounts + +``` +hugo config mounts [flags] [args] +``` + +### Options + +``` + -b, --baseURL string hostname (and path) to the root, e.g. https://spf13.com/ + --cacheDir string filesystem path to cache directory + -c, --contentDir string filesystem path to content directory + -h, --help help for mounts + -t, --theme strings themes to use (located in /themes/THEMENAME/) +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + --debug debug output + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --quiet build in quiet mode + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory + -v, --verbose verbose output +``` + +### SEE ALSO + +* [hugo config](/commands/hugo_config/) - Print the site configuration + diff --git a/docs/content/en/commands/hugo_convert.md b/docs/content/en/commands/hugo_convert.md new file mode 100644 index 000000000..07f7f9c13 --- /dev/null +++ b/docs/content/en/commands/hugo_convert.md @@ -0,0 +1,47 @@ +--- +title: "hugo convert" +slug: hugo_convert +url: /commands/hugo_convert/ +--- +## hugo convert + +Convert your content to different formats + +### Synopsis + +Convert your content (e.g. front matter) to different formats. + +See convert's subcommands toJSON, toTOML and toYAML for more information. + +### Options + +``` + -h, --help help for convert + -o, --output string filesystem path to write files to + --unsafe enable less safe operations, please backup first +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + --debug debug output + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --quiet build in quiet mode + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory + -v, --verbose verbose output +``` + +### SEE ALSO + +* [hugo](/commands/hugo/) - hugo builds your site +* [hugo convert toJSON](/commands/hugo_convert_tojson/) - Convert front matter to JSON +* [hugo convert toTOML](/commands/hugo_convert_totoml/) - Convert front matter to TOML +* [hugo convert toYAML](/commands/hugo_convert_toyaml/) - Convert front matter to YAML + diff --git a/docs/content/en/commands/hugo_convert_toJSON.md b/docs/content/en/commands/hugo_convert_toJSON.md new file mode 100644 index 000000000..23d6a1032 --- /dev/null +++ b/docs/content/en/commands/hugo_convert_toJSON.md @@ -0,0 +1,47 @@ +--- +title: "hugo convert toJSON" +slug: hugo_convert_toJSON +url: /commands/hugo_convert_tojson/ +--- +## hugo convert toJSON + +Convert front matter to JSON + +### Synopsis + +toJSON converts all front matter in the content directory +to use JSON for the front matter. + +``` +hugo convert toJSON [flags] [args] +``` + +### Options + +``` + -h, --help help for toJSON +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + --debug debug output + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + -o, --output string filesystem path to write files to + --quiet build in quiet mode + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory + --unsafe enable less safe operations, please backup first + -v, --verbose verbose output +``` + +### SEE ALSO + +* [hugo convert](/commands/hugo_convert/) - Convert your content to different formats + diff --git a/docs/content/en/commands/hugo_convert_toTOML.md b/docs/content/en/commands/hugo_convert_toTOML.md new file mode 100644 index 000000000..431547a79 --- /dev/null +++ b/docs/content/en/commands/hugo_convert_toTOML.md @@ -0,0 +1,47 @@ +--- +title: "hugo convert toTOML" +slug: hugo_convert_toTOML +url: /commands/hugo_convert_totoml/ +--- +## hugo convert toTOML + +Convert front matter to TOML + +### Synopsis + +toTOML converts all front matter in the content directory +to use TOML for the front matter. + +``` +hugo convert toTOML [flags] [args] +``` + +### Options + +``` + -h, --help help for toTOML +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + --debug debug output + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + -o, --output string filesystem path to write files to + --quiet build in quiet mode + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory + --unsafe enable less safe operations, please backup first + -v, --verbose verbose output +``` + +### SEE ALSO + +* [hugo convert](/commands/hugo_convert/) - Convert your content to different formats + diff --git a/docs/content/en/commands/hugo_convert_toYAML.md b/docs/content/en/commands/hugo_convert_toYAML.md new file mode 100644 index 000000000..03f7fbb25 --- /dev/null +++ b/docs/content/en/commands/hugo_convert_toYAML.md @@ -0,0 +1,47 @@ +--- +title: "hugo convert toYAML" +slug: hugo_convert_toYAML +url: /commands/hugo_convert_toyaml/ +--- +## hugo convert toYAML + +Convert front matter to YAML + +### Synopsis + +toYAML converts all front matter in the content directory +to use YAML for the front matter. + +``` +hugo convert toYAML [flags] [args] +``` + +### Options + +``` + -h, --help help for toYAML +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + --debug debug output + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + -o, --output string filesystem path to write files to + --quiet build in quiet mode + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory + --unsafe enable less safe operations, please backup first + -v, --verbose verbose output +``` + +### SEE ALSO + +* [hugo convert](/commands/hugo_convert/) - Convert your content to different formats + diff --git a/docs/content/en/commands/hugo_deploy.md b/docs/content/en/commands/hugo_deploy.md new file mode 100644 index 000000000..b4ab3e618 --- /dev/null +++ b/docs/content/en/commands/hugo_deploy.md @@ -0,0 +1,55 @@ +--- +title: "hugo deploy" +slug: hugo_deploy +url: /commands/hugo_deploy/ +--- +## hugo deploy + +Deploy your site to a Cloud provider. + +### Synopsis + +Deploy your site to a Cloud provider. + +See https://gohugo.io/hosting-and-deployment/hugo-deploy/ for detailed +documentation. + + +``` +hugo deploy [flags] [args] +``` + +### Options + +``` + --confirm ask for confirmation before making changes to the target + --dryRun dry run + --force force upload of all files + -h, --help help for deploy + --invalidateCDN invalidate the CDN cache listed in the deployment target (default true) + --maxDeletes int maximum # of files to delete, or -1 to disable (default 256) + --target string target deployment from deployments section in config file; defaults to the first one + --workers int number of workers to transfer files. defaults to 10 (default 10) +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + --debug debug output + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --quiet build in quiet mode + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory + -v, --verbose verbose output +``` + +### SEE ALSO + +* [hugo](/commands/hugo/) - hugo builds your site + diff --git a/docs/content/en/commands/hugo_env.md b/docs/content/en/commands/hugo_env.md new file mode 100644 index 000000000..076ddef26 --- /dev/null +++ b/docs/content/en/commands/hugo_env.md @@ -0,0 +1,44 @@ +--- +title: "hugo env" +slug: hugo_env +url: /commands/hugo_env/ +--- +## hugo env + +Print Hugo version and environment info + +### Synopsis + +Print Hugo version and environment info. This is useful in Hugo bug reports + +``` +hugo env [flags] [args] +``` + +### Options + +``` + -h, --help help for env +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + --debug debug output + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --quiet build in quiet mode + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory + -v, --verbose verbose output +``` + +### SEE ALSO + +* [hugo](/commands/hugo/) - hugo builds your site + diff --git a/docs/content/en/commands/hugo_gen.md b/docs/content/en/commands/hugo_gen.md new file mode 100644 index 000000000..5c8bd6f2c --- /dev/null +++ b/docs/content/en/commands/hugo_gen.md @@ -0,0 +1,39 @@ +--- +title: "hugo gen" +slug: hugo_gen +url: /commands/hugo_gen/ +--- +## hugo gen + +A collection of several useful generators. + +### Options + +``` + -h, --help help for gen +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + --debug debug output + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --quiet build in quiet mode + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory + -v, --verbose verbose output +``` + +### SEE ALSO + +* [hugo](/commands/hugo/) - hugo builds your site +* [hugo gen chromastyles](/commands/hugo_gen_chromastyles/) - Generate CSS stylesheet for the Chroma code highlighter +* [hugo gen doc](/commands/hugo_gen_doc/) - Generate Markdown documentation for the Hugo CLI. +* [hugo gen man](/commands/hugo_gen_man/) - Generate man pages for the Hugo CLI + diff --git a/docs/content/en/commands/hugo_gen_chromastyles.md b/docs/content/en/commands/hugo_gen_chromastyles.md new file mode 100644 index 000000000..3ec890412 --- /dev/null +++ b/docs/content/en/commands/hugo_gen_chromastyles.md @@ -0,0 +1,49 @@ +--- +title: "hugo gen chromastyles" +slug: hugo_gen_chromastyles +url: /commands/hugo_gen_chromastyles/ +--- +## hugo gen chromastyles + +Generate CSS stylesheet for the Chroma code highlighter + +### Synopsis + +Generate CSS stylesheet for the Chroma code highlighter for a given style. This stylesheet is needed if markup.highlight.noClasses is disabled in config. + +See https://xyproto.github.io/splash/docs/all.html for a preview of the available styles + +``` +hugo gen chromastyles [flags] [args] +``` + +### Options + +``` + -h, --help help for chromastyles + --highlightStyle string style used for highlighting lines (see https://github.com/alecthomas/chroma) + --linesStyle string style used for line numbers (see https://github.com/alecthomas/chroma) + --style string highlighter style (see https://xyproto.github.io/splash/docs/) (default "friendly") +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + --debug debug output + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --quiet build in quiet mode + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory + -v, --verbose verbose output +``` + +### SEE ALSO + +* [hugo gen](/commands/hugo_gen/) - A collection of several useful generators. + diff --git a/docs/content/en/commands/hugo_gen_doc.md b/docs/content/en/commands/hugo_gen_doc.md new file mode 100644 index 000000000..13fb23106 --- /dev/null +++ b/docs/content/en/commands/hugo_gen_doc.md @@ -0,0 +1,50 @@ +--- +title: "hugo gen doc" +slug: hugo_gen_doc +url: /commands/hugo_gen_doc/ +--- +## hugo gen doc + +Generate Markdown documentation for the Hugo CLI. + +### Synopsis + +Generate Markdown documentation for the Hugo CLI. + This command is, mostly, used to create up-to-date documentation + of Hugo's command-line interface for https://gohugo.io/. + + It creates one Markdown file per command with front matter suitable + for rendering in Hugo. + +``` +hugo gen doc [flags] [args] +``` + +### Options + +``` + --dir string the directory to write the doc. (default "/tmp/hugodoc/") + -h, --help help for doc +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + --debug debug output + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --quiet build in quiet mode + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory + -v, --verbose verbose output +``` + +### SEE ALSO + +* [hugo gen](/commands/hugo_gen/) - A collection of several useful generators. + diff --git a/docs/content/en/commands/hugo_gen_man.md b/docs/content/en/commands/hugo_gen_man.md new file mode 100644 index 000000000..6a63a583e --- /dev/null +++ b/docs/content/en/commands/hugo_gen_man.md @@ -0,0 +1,47 @@ +--- +title: "hugo gen man" +slug: hugo_gen_man +url: /commands/hugo_gen_man/ +--- +## hugo gen man + +Generate man pages for the Hugo CLI + +### Synopsis + +This command automatically generates up-to-date man pages of Hugo's + command-line interface. By default, it creates the man page files + in the "man" directory under the current directory. + +``` +hugo gen man [flags] [args] +``` + +### Options + +``` + --dir string the directory to write the man pages. (default "man/") + -h, --help help for man +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + --debug debug output + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --quiet build in quiet mode + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory + -v, --verbose verbose output +``` + +### SEE ALSO + +* [hugo gen](/commands/hugo_gen/) - A collection of several useful generators. + diff --git a/docs/content/en/commands/hugo_import.md b/docs/content/en/commands/hugo_import.md new file mode 100644 index 000000000..a6bd40f34 --- /dev/null +++ b/docs/content/en/commands/hugo_import.md @@ -0,0 +1,43 @@ +--- +title: "hugo import" +slug: hugo_import +url: /commands/hugo_import/ +--- +## hugo import + +Import your site from others. + +### Synopsis + +Import your site from other web site generators like Jekyll. + +Import requires a subcommand, e.g. `hugo import jekyll jekyll_root_path target_path`. + +### Options + +``` + -h, --help help for import +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + --debug debug output + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --quiet build in quiet mode + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory + -v, --verbose verbose output +``` + +### SEE ALSO + +* [hugo](/commands/hugo/) - hugo builds your site +* [hugo import jekyll](/commands/hugo_import_jekyll/) - hugo import from Jekyll + diff --git a/docs/content/en/commands/hugo_import_jekyll.md b/docs/content/en/commands/hugo_import_jekyll.md new file mode 100644 index 000000000..af751348c --- /dev/null +++ b/docs/content/en/commands/hugo_import_jekyll.md @@ -0,0 +1,47 @@ +--- +title: "hugo import jekyll" +slug: hugo_import_jekyll +url: /commands/hugo_import_jekyll/ +--- +## hugo import jekyll + +hugo import from Jekyll + +### Synopsis + +hugo import from Jekyll. + +Import from Jekyll requires two paths, e.g. `hugo import jekyll jekyll_root_path target_path`. + +``` +hugo import jekyll [flags] [args] +``` + +### Options + +``` + --force allow import into non-empty target directory + -h, --help help for jekyll +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + --debug debug output + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --quiet build in quiet mode + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory + -v, --verbose verbose output +``` + +### SEE ALSO + +* [hugo import](/commands/hugo_import/) - Import your site from others. + diff --git a/docs/content/en/commands/hugo_list.md b/docs/content/en/commands/hugo_list.md new file mode 100644 index 000000000..294a8eaa4 --- /dev/null +++ b/docs/content/en/commands/hugo_list.md @@ -0,0 +1,46 @@ +--- +title: "hugo list" +slug: hugo_list +url: /commands/hugo_list/ +--- +## hugo list + +Listing out various types of content + +### Synopsis + +Listing out various types of content. + +List requires a subcommand, e.g. hugo list drafts + +### Options + +``` + -h, --help help for list +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + --debug debug output + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --quiet build in quiet mode + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory + -v, --verbose verbose output +``` + +### SEE ALSO + +* [hugo](/commands/hugo/) - hugo builds your site +* [hugo list all](/commands/hugo_list_all/) - List all posts +* [hugo list drafts](/commands/hugo_list_drafts/) - List all drafts +* [hugo list expired](/commands/hugo_list_expired/) - List all posts already expired +* [hugo list future](/commands/hugo_list_future/) - List all posts dated in the future + diff --git a/docs/content/en/commands/hugo_list_all.md b/docs/content/en/commands/hugo_list_all.md new file mode 100644 index 000000000..49f692de0 --- /dev/null +++ b/docs/content/en/commands/hugo_list_all.md @@ -0,0 +1,44 @@ +--- +title: "hugo list all" +slug: hugo_list_all +url: /commands/hugo_list_all/ +--- +## hugo list all + +List all posts + +### Synopsis + +List all of the posts in your content directory, include drafts, future and expired pages. + +``` +hugo list all [flags] [args] +``` + +### Options + +``` + -h, --help help for all +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + --debug debug output + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --quiet build in quiet mode + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory + -v, --verbose verbose output +``` + +### SEE ALSO + +* [hugo list](/commands/hugo_list/) - Listing out various types of content + diff --git a/docs/content/en/commands/hugo_list_drafts.md b/docs/content/en/commands/hugo_list_drafts.md new file mode 100644 index 000000000..e84e582e6 --- /dev/null +++ b/docs/content/en/commands/hugo_list_drafts.md @@ -0,0 +1,44 @@ +--- +title: "hugo list drafts" +slug: hugo_list_drafts +url: /commands/hugo_list_drafts/ +--- +## hugo list drafts + +List all drafts + +### Synopsis + +List all of the drafts in your content directory. + +``` +hugo list drafts [flags] [args] +``` + +### Options + +``` + -h, --help help for drafts +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + --debug debug output + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --quiet build in quiet mode + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory + -v, --verbose verbose output +``` + +### SEE ALSO + +* [hugo list](/commands/hugo_list/) - Listing out various types of content + diff --git a/docs/content/en/commands/hugo_list_expired.md b/docs/content/en/commands/hugo_list_expired.md new file mode 100644 index 000000000..43feb5d8e --- /dev/null +++ b/docs/content/en/commands/hugo_list_expired.md @@ -0,0 +1,44 @@ +--- +title: "hugo list expired" +slug: hugo_list_expired +url: /commands/hugo_list_expired/ +--- +## hugo list expired + +List all posts already expired + +### Synopsis + +List all of the posts in your content directory which has already expired. + +``` +hugo list expired [flags] [args] +``` + +### Options + +``` + -h, --help help for expired +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + --debug debug output + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --quiet build in quiet mode + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory + -v, --verbose verbose output +``` + +### SEE ALSO + +* [hugo list](/commands/hugo_list/) - Listing out various types of content + diff --git a/docs/content/en/commands/hugo_list_future.md b/docs/content/en/commands/hugo_list_future.md new file mode 100644 index 000000000..419accd6c --- /dev/null +++ b/docs/content/en/commands/hugo_list_future.md @@ -0,0 +1,44 @@ +--- +title: "hugo list future" +slug: hugo_list_future +url: /commands/hugo_list_future/ +--- +## hugo list future + +List all posts dated in the future + +### Synopsis + +List all of the posts in your content directory which will be posted in the future. + +``` +hugo list future [flags] [args] +``` + +### Options + +``` + -h, --help help for future +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + --debug debug output + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --quiet build in quiet mode + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory + -v, --verbose verbose output +``` + +### SEE ALSO + +* [hugo list](/commands/hugo_list/) - Listing out various types of content + diff --git a/docs/content/en/commands/hugo_mod.md b/docs/content/en/commands/hugo_mod.md new file mode 100644 index 000000000..dc712b1de --- /dev/null +++ b/docs/content/en/commands/hugo_mod.md @@ -0,0 +1,59 @@ +--- +title: "hugo mod" +slug: hugo_mod +url: /commands/hugo_mod/ +--- +## hugo mod + +Various Hugo Modules helpers. + +### Synopsis + +Various helpers to help manage the modules in your project's dependency graph. +Most operations here requires a Go version installed on your system (>= Go 1.12) and the relevant VCS client (typically Git). +This is not needed if you only operate on modules inside /themes or if you have vendored them via "hugo mod vendor". + + +Note that Hugo will always start out by resolving the components defined in the site +configuration, provided by a _vendor directory (if no --ignoreVendorPaths flag provided), +Go Modules, or a folder inside the themes directory, in that order. + +See https://gohugo.io/hugo-modules/ for more information. + + + +### Options + +``` + -h, --help help for mod +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + --debug debug output + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --quiet build in quiet mode + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory + -v, --verbose verbose output +``` + +### SEE ALSO + +* [hugo](/commands/hugo/) - hugo builds your site +* [hugo mod clean](/commands/hugo_mod_clean/) - Delete the Hugo Module cache for the current project. +* [hugo mod get](/commands/hugo_mod_get/) - Resolves dependencies in your current Hugo Project. +* [hugo mod graph](/commands/hugo_mod_graph/) - Print a module dependency graph. +* [hugo mod init](/commands/hugo_mod_init/) - Initialize this project as a Hugo Module. +* [hugo mod npm](/commands/hugo_mod_npm/) - Various npm helpers. +* [hugo mod tidy](/commands/hugo_mod_tidy/) - Remove unused entries in go.mod and go.sum. +* [hugo mod vendor](/commands/hugo_mod_vendor/) - Vendor all module dependencies into the _vendor directory. +* [hugo mod verify](/commands/hugo_mod_verify/) - Verify dependencies. + diff --git a/docs/content/en/commands/hugo_mod_clean.md b/docs/content/en/commands/hugo_mod_clean.md new file mode 100644 index 000000000..c1c2b0c0d --- /dev/null +++ b/docs/content/en/commands/hugo_mod_clean.md @@ -0,0 +1,50 @@ +--- +title: "hugo mod clean" +slug: hugo_mod_clean +url: /commands/hugo_mod_clean/ +--- +## hugo mod clean + +Delete the Hugo Module cache for the current project. + +### Synopsis + +Delete the Hugo Module cache for the current project. + +``` +hugo mod clean [flags] [args] +``` + +### Options + +``` + --all clean entire module cache + -b, --baseURL string hostname (and path) to the root, e.g. https://spf13.com/ + --cacheDir string filesystem path to cache directory + -c, --contentDir string filesystem path to content directory + -h, --help help for clean + --pattern string pattern matching module paths to clean (all if not set), e.g. "**hugo*" + -t, --theme strings themes to use (located in /themes/THEMENAME/) +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + --debug debug output + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --quiet build in quiet mode + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory + -v, --verbose verbose output +``` + +### SEE ALSO + +* [hugo mod](/commands/hugo_mod/) - Various Hugo Modules helpers. + diff --git a/docs/content/en/commands/hugo_mod_get.md b/docs/content/en/commands/hugo_mod_get.md new file mode 100644 index 000000000..f4803d723 --- /dev/null +++ b/docs/content/en/commands/hugo_mod_get.md @@ -0,0 +1,75 @@ +--- +title: "hugo mod get" +slug: hugo_mod_get +url: /commands/hugo_mod_get/ +--- +## hugo mod get + +Resolves dependencies in your current Hugo Project. + +### Synopsis + + +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 + +Install the latest versions of all direct module dependencies: + + hugo mod get + hugo mod get ./... (recursive) + +Install the latest versions of all module dependencies (direct and indirect): + + hugo mod get -u + hugo mod get -u ./... (recursive) + +Run "go help get" for more information. All flags available for "go get" is also relevant here. + +Note that Hugo will always start out by resolving the components defined in the site +configuration, provided by a _vendor directory (if no --ignoreVendorPaths flag provided), +Go Modules, or a folder inside the themes directory, in that order. + +See https://gohugo.io/hugo-modules/ for more information. + + + +``` +hugo mod get [flags] [args] +``` + +### Options + +``` + -h, --help help for get +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + --debug debug output + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --quiet build in quiet mode + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory + -v, --verbose verbose output +``` + +### SEE ALSO + +* [hugo mod](/commands/hugo_mod/) - Various Hugo Modules helpers. + diff --git a/docs/content/en/commands/hugo_mod_graph.md b/docs/content/en/commands/hugo_mod_graph.md new file mode 100644 index 000000000..a2e2b51a3 --- /dev/null +++ b/docs/content/en/commands/hugo_mod_graph.md @@ -0,0 +1,51 @@ +--- +title: "hugo mod graph" +slug: hugo_mod_graph +url: /commands/hugo_mod_graph/ +--- +## hugo mod graph + +Print a module dependency graph. + +### Synopsis + +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. + + +``` +hugo mod graph [flags] [args] +``` + +### Options + +``` + -b, --baseURL string hostname (and path) to the root, e.g. https://spf13.com/ + --cacheDir string filesystem path to cache directory + --clean delete module cache for dependencies that fail verification + -c, --contentDir string filesystem path to content directory + -h, --help help for graph + -t, --theme strings themes to use (located in /themes/THEMENAME/) +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + --debug debug output + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --quiet build in quiet mode + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory + -v, --verbose verbose output +``` + +### SEE ALSO + +* [hugo mod](/commands/hugo_mod/) - Various Hugo Modules helpers. + diff --git a/docs/content/en/commands/hugo_mod_init.md b/docs/content/en/commands/hugo_mod_init.md new file mode 100644 index 000000000..49b2609e1 --- /dev/null +++ b/docs/content/en/commands/hugo_mod_init.md @@ -0,0 +1,55 @@ +--- +title: "hugo mod init" +slug: hugo_mod_init +url: /commands/hugo_mod_init/ +--- +## hugo mod init + +Initialize this project as a Hugo Module. + +### Synopsis + +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. + + +``` +hugo mod init [flags] [args] +``` + +### Options + +``` + -b, --baseURL string hostname (and path) to the root, e.g. https://spf13.com/ + --cacheDir string filesystem path to cache directory + -c, --contentDir string filesystem path to content directory + -h, --help help for init + -t, --theme strings themes to use (located in /themes/THEMENAME/) +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + --debug debug output + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --quiet build in quiet mode + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory + -v, --verbose verbose output +``` + +### SEE ALSO + +* [hugo mod](/commands/hugo_mod/) - Various Hugo Modules helpers. + diff --git a/docs/content/en/commands/hugo_mod_npm.md b/docs/content/en/commands/hugo_mod_npm.md new file mode 100644 index 000000000..fcd834798 --- /dev/null +++ b/docs/content/en/commands/hugo_mod_npm.md @@ -0,0 +1,45 @@ +--- +title: "hugo mod npm" +slug: hugo_mod_npm +url: /commands/hugo_mod_npm/ +--- +## hugo mod npm + +Various npm helpers. + +### Synopsis + +Various npm (Node package manager) helpers. + +``` +hugo mod npm [command] [flags] +``` + +### Options + +``` + -h, --help help for npm +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + --debug debug output + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --quiet build in quiet mode + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory + -v, --verbose verbose output +``` + +### SEE ALSO + +* [hugo mod](/commands/hugo_mod/) - Various Hugo Modules helpers. +* [hugo mod npm pack](/commands/hugo_mod_npm_pack/) - Experimental: Prepares and writes a composite package.json file for your project. + diff --git a/docs/content/en/commands/hugo_mod_npm_pack.md b/docs/content/en/commands/hugo_mod_npm_pack.md new file mode 100644 index 000000000..30214d556 --- /dev/null +++ b/docs/content/en/commands/hugo_mod_npm_pack.md @@ -0,0 +1,58 @@ +--- +title: "hugo mod npm pack" +slug: hugo_mod_npm_pack +url: /commands/hugo_mod_npm_pack/ +--- +## hugo mod npm pack + +Experimental: Prepares and writes a composite package.json file for your project. + +### Synopsis + +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. + +This set will be merged with all "package.hugo.json" files found in the dependency tree, picking the version closest to the project. + +This command is marked as 'Experimental'. We think it's a great idea, so it's not likely to be +removed from Hugo, but we need to test this out in "real life" to get a feel of it, +so this may/will change in future versions of Hugo. + + +``` +hugo mod npm pack [flags] [args] +``` + +### Options + +``` + -b, --baseURL string hostname (and path) to the root, e.g. https://spf13.com/ + --cacheDir string filesystem path to cache directory + -c, --contentDir string filesystem path to content directory + -h, --help help for pack + -t, --theme strings themes to use (located in /themes/THEMENAME/) +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + --debug debug output + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --quiet build in quiet mode + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory + -v, --verbose verbose output +``` + +### SEE ALSO + +* [hugo mod npm](/commands/hugo_mod_npm/) - Various npm helpers. + diff --git a/docs/content/en/commands/hugo_mod_tidy.md b/docs/content/en/commands/hugo_mod_tidy.md new file mode 100644 index 000000000..803ef1c5b --- /dev/null +++ b/docs/content/en/commands/hugo_mod_tidy.md @@ -0,0 +1,44 @@ +--- +title: "hugo mod tidy" +slug: hugo_mod_tidy +url: /commands/hugo_mod_tidy/ +--- +## hugo mod tidy + +Remove unused entries in go.mod and go.sum. + +``` +hugo mod tidy [flags] [args] +``` + +### Options + +``` + -b, --baseURL string hostname (and path) to the root, e.g. https://spf13.com/ + --cacheDir string filesystem path to cache directory + -c, --contentDir string filesystem path to content directory + -h, --help help for tidy + -t, --theme strings themes to use (located in /themes/THEMENAME/) +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + --debug debug output + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --quiet build in quiet mode + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory + -v, --verbose verbose output +``` + +### SEE ALSO + +* [hugo mod](/commands/hugo_mod/) - Various Hugo Modules helpers. + diff --git a/docs/content/en/commands/hugo_mod_vendor.md b/docs/content/en/commands/hugo_mod_vendor.md new file mode 100644 index 000000000..3a829d5fd --- /dev/null +++ b/docs/content/en/commands/hugo_mod_vendor.md @@ -0,0 +1,50 @@ +--- +title: "hugo mod vendor" +slug: hugo_mod_vendor +url: /commands/hugo_mod_vendor/ +--- +## hugo mod vendor + +Vendor all module dependencies into the _vendor directory. + +### Synopsis + +Vendor all module dependencies into the _vendor directory. + If a module is vendored, that is where Hugo will look for it's dependencies. + + +``` +hugo mod vendor [flags] [args] +``` + +### Options + +``` + -b, --baseURL string hostname (and path) to the root, e.g. https://spf13.com/ + --cacheDir string filesystem path to cache directory + -c, --contentDir string filesystem path to content directory + -h, --help help for vendor + -t, --theme strings themes to use (located in /themes/THEMENAME/) +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + --debug debug output + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --quiet build in quiet mode + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory + -v, --verbose verbose output +``` + +### SEE ALSO + +* [hugo mod](/commands/hugo_mod/) - Various Hugo Modules helpers. + diff --git a/docs/content/en/commands/hugo_mod_verify.md b/docs/content/en/commands/hugo_mod_verify.md new file mode 100644 index 000000000..b647a2cbb --- /dev/null +++ b/docs/content/en/commands/hugo_mod_verify.md @@ -0,0 +1,49 @@ +--- +title: "hugo mod verify" +slug: hugo_mod_verify +url: /commands/hugo_mod_verify/ +--- +## hugo mod verify + +Verify dependencies. + +### Synopsis + +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. + +``` +hugo mod verify [flags] [args] +``` + +### Options + +``` + -b, --baseURL string hostname (and path) to the root, e.g. https://spf13.com/ + --cacheDir string filesystem path to cache directory + --clean delete module cache for dependencies that fail verification + -c, --contentDir string filesystem path to content directory + -h, --help help for verify + -t, --theme strings themes to use (located in /themes/THEMENAME/) +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + --debug debug output + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --quiet build in quiet mode + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory + -v, --verbose verbose output +``` + +### SEE ALSO + +* [hugo mod](/commands/hugo_mod/) - Various Hugo Modules helpers. + diff --git a/docs/content/en/commands/hugo_new.md b/docs/content/en/commands/hugo_new.md new file mode 100644 index 000000000..ef0ff4cd4 --- /dev/null +++ b/docs/content/en/commands/hugo_new.md @@ -0,0 +1,50 @@ +--- +title: "hugo new" +slug: hugo_new +url: /commands/hugo_new/ +--- +## hugo new + +Create new content for your site + +### Synopsis + +Create a new content file and automatically set the date and title. +It will guess which kind of file to create based on the path provided. + +You can also specify the kind with `-k KIND`. + +If archetypes are provided in your theme or site, they will be used. + +Ensure you run this within the root directory of your site. + +### Options + +``` + -h, --help help for new +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + --debug debug output + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --quiet build in quiet mode + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory + -v, --verbose verbose output +``` + +### SEE ALSO + +* [hugo](/commands/hugo/) - hugo builds your site +* [hugo new content](/commands/hugo_new_content/) - Create new content for your site +* [hugo new site](/commands/hugo_new_site/) - Create a new site (skeleton) +* [hugo new theme](/commands/hugo_new_theme/) - Create a new theme (skeleton) + diff --git a/docs/content/en/commands/hugo_new_content.md b/docs/content/en/commands/hugo_new_content.md new file mode 100644 index 000000000..cc53346ad --- /dev/null +++ b/docs/content/en/commands/hugo_new_content.md @@ -0,0 +1,58 @@ +--- +title: "hugo new content" +slug: hugo_new_content +url: /commands/hugo_new_content/ +--- +## hugo new content + +Create new content for your site + +### Synopsis + +Create a new content file and automatically set the date and title. +It will guess which kind of file to create based on the path provided. + +You can also specify the kind with `-k KIND`. + +If archetypes are provided in your theme or site, they will be used. + +Ensure you run this within the root directory of your site. + +``` +hugo new content [path] [flags] +``` + +### Options + +``` + -b, --baseURL string hostname (and path) to the root, e.g. https://spf13.com/ + --cacheDir string filesystem path to cache directory + -c, --contentDir string filesystem path to content directory + --editor string edit new content with this editor, if provided + -f, --force overwrite file if it already exists + -h, --help help for content + -k, --kind string content type to create + -t, --theme strings themes to use (located in /themes/THEMENAME/) +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + --debug debug output + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --quiet build in quiet mode + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory + -v, --verbose verbose output +``` + +### SEE ALSO + +* [hugo new](/commands/hugo_new/) - Create new content for your site + diff --git a/docs/content/en/commands/hugo_new_site.md b/docs/content/en/commands/hugo_new_site.md new file mode 100644 index 000000000..f8a939df5 --- /dev/null +++ b/docs/content/en/commands/hugo_new_site.md @@ -0,0 +1,48 @@ +--- +title: "hugo new site" +slug: hugo_new_site +url: /commands/hugo_new_site/ +--- +## hugo new site + +Create a new site (skeleton) + +### Synopsis + +Create a new site in the provided directory. +The new site will have the correct structure, but no content or theme yet. +Use `hugo new [contentPath]` to create new content. + +``` +hugo new site [path] [flags] +``` + +### Options + +``` + -f, --force init inside non-empty directory + --format string preferred file format (toml, yaml or json) (default "toml") + -h, --help help for site +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + --debug debug output + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --quiet build in quiet mode + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory + -v, --verbose verbose output +``` + +### SEE ALSO + +* [hugo new](/commands/hugo_new/) - Create new content for your site + diff --git a/docs/content/en/commands/hugo_new_theme.md b/docs/content/en/commands/hugo_new_theme.md new file mode 100644 index 000000000..301c79e0c --- /dev/null +++ b/docs/content/en/commands/hugo_new_theme.md @@ -0,0 +1,47 @@ +--- +title: "hugo new theme" +slug: hugo_new_theme +url: /commands/hugo_new_theme/ +--- +## hugo new theme + +Create a new theme (skeleton) + +### Synopsis + +Create a new theme (skeleton) called [name] in ./themes. +New theme is a skeleton. Please add content to the touched files. Add your +name to the copyright line in the license and adjust the theme.toml file +according to your needs. + +``` +hugo new theme [name] [flags] +``` + +### Options + +``` + -h, --help help for theme +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + --debug debug output + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --quiet build in quiet mode + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory + -v, --verbose verbose output +``` + +### SEE ALSO + +* [hugo new](/commands/hugo_new/) - Create new content for your site + diff --git a/docs/content/en/commands/hugo_server.md b/docs/content/en/commands/hugo_server.md new file mode 100644 index 000000000..49cd1867b --- /dev/null +++ b/docs/content/en/commands/hugo_server.md @@ -0,0 +1,98 @@ +--- +title: "hugo server" +slug: hugo_server +url: /commands/hugo_server/ +--- +## hugo server + +A high performance webserver + +### Synopsis + +Hugo provides its own webserver which builds and serves the site. +While hugo server is high performance, it is a webserver with limited options. + +'hugo server' will avoid writing the rendered and served content to disk, +preferring to store it in memory. + +By default hugo will also watch your files for any changes you make and +automatically rebuild the site. It will then live reload any open browser pages +and push the latest content to them. As most Hugo sites are built in a fraction +of a second, you will be able to save and see your changes nearly instantly. + +``` +hugo server [command] [flags] +``` + +### Options + +``` + --appendPort append port to baseURL (default true) + -b, --baseURL string hostname (and path) to the root, e.g. https://spf13.com/ + --bind string interface to which the server will bind (default "127.0.0.1") + -D, --buildDrafts include content marked as draft + -E, --buildExpired include expired content + -F, --buildFuture include content with publishdate in the future + --cacheDir string filesystem path to cache directory + --cleanDestinationDir remove files from destination not found in static directories + -c, --contentDir string filesystem path to content directory + --disableBrowserError do not show build errors in the browser + --disableFastRender enables full re-renders on changes + --disableKinds strings disable different kind of pages (home, RSS etc.) + --disableLiveReload watch without enabling live browser reload on rebuild + --enableGitInfo add Git revision, date, author, and CODEOWNERS info to the pages + --forceSyncStatic copy all files when static is changed. + --gc enable to run some cleanup tasks (remove unused cache files) after the build + -h, --help help for server + --ignoreCache ignores the cache directory + -l, --layoutDir string filesystem path to layout directory + --liveReloadPort int port for live reloading (i.e. 443 in HTTPS proxy situations) (default -1) + --meminterval string interval to poll memory usage (requires --memstats), valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h". (default "100ms") + --memstats string log memory usage to this file + --minify minify any supported output format (HTML, XML etc.) + --navigateToChanged navigate to changed content file on live browser reload + --noBuildLock don't create .hugo_build.lock file + --noChmod don't sync permission mode of files + --noHTTPCache prevent HTTP caching + --noTimes don't sync modification time of files + --panicOnWarning panic on first WARNING log + --poll string set this to a poll interval, e.g --poll 700ms, to use a poll based approach to watch for file system changes + -p, --port int port on which the server will listen (default 1313) + --printI18nWarnings print missing translations + --printMemoryUsage print memory usage to screen at intervals + --printPathWarnings print warnings on duplicate target paths etc. + --printUnusedTemplates print warnings on unused templates. + --renderStaticToDisk serve static files from disk and dynamic files from memory + --renderToDisk serve all files from disk (default is from memory) + --templateMetrics display metrics about template executions + --templateMetricsHints calculate some improvement hints when combined with --templateMetrics + -t, --theme strings themes to use (located in /themes/THEMENAME/) + --tlsAuto generate and use locally-trusted certificates. + --tlsCertFile string path to TLS certificate file + --tlsKeyFile string path to TLS key file + --trace file write trace to file (not useful in general) + -w, --watch watch filesystem for changes and recreate as needed (default true) +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + --debug debug output + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --quiet build in quiet mode + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory + -v, --verbose verbose output +``` + +### SEE ALSO + +* [hugo](/commands/hugo/) - hugo builds your site +* [hugo server trust](/commands/hugo_server_trust/) - Install the local CA in the system trust store. + diff --git a/docs/content/en/commands/hugo_server_trust.md b/docs/content/en/commands/hugo_server_trust.md new file mode 100644 index 000000000..b789eb69a --- /dev/null +++ b/docs/content/en/commands/hugo_server_trust.md @@ -0,0 +1,41 @@ +--- +title: "hugo server trust" +slug: hugo_server_trust +url: /commands/hugo_server_trust/ +--- +## hugo server trust + +Install the local CA in the system trust store. + +``` +hugo server trust [flags] [args] +``` + +### Options + +``` + -h, --help help for trust + --uninstall Uninstall the local CA (but do not delete it). +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + --debug debug output + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --quiet build in quiet mode + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory + -v, --verbose verbose output +``` + +### SEE ALSO + +* [hugo server](/commands/hugo_server/) - A high performance webserver + diff --git a/docs/content/en/commands/hugo_version.md b/docs/content/en/commands/hugo_version.md new file mode 100644 index 000000000..cf23e7fef --- /dev/null +++ b/docs/content/en/commands/hugo_version.md @@ -0,0 +1,44 @@ +--- +title: "hugo version" +slug: hugo_version +url: /commands/hugo_version/ +--- +## hugo version + +Print Hugo version and environment info + +### Synopsis + +Print Hugo version and environment info. This is useful in Hugo bug reports. + +``` +hugo version [flags] [args] +``` + +### Options + +``` + -h, --help help for version +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + --debug debug output + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --quiet build in quiet mode + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory + -v, --verbose verbose output +``` + +### SEE ALSO + +* [hugo](/commands/hugo/) - hugo builds your site + diff --git a/docs/content/en/content-management/_common/_index.md b/docs/content/en/content-management/_common/_index.md new file mode 100644 index 000000000..47d5812fb --- /dev/null +++ b/docs/content/en/content-management/_common/_index.md @@ -0,0 +1,13 @@ +--- +cascade: + _build: + list: never + publishResources: false + render: never +--- + +<!-- +Files within this headless branch bundle are markdown snippets. Each file must contain front matter delimiters, though front matter fields are not required. + +Include the rendered content using the "include" shortcode. +--> diff --git a/docs/content/en/content-management/_common/page-kinds.md b/docs/content/en/content-management/_common/page-kinds.md new file mode 100644 index 000000000..07a53e8e6 --- /dev/null +++ b/docs/content/en/content-management/_common/page-kinds.md @@ -0,0 +1,17 @@ +--- +# Do not remove front matter. +--- + +| Kind | Description | Example | +|----------------|--------------------------------------------------------------------|-------------------------------------------------------------------------------| +| `home` | The landing page for the home page | `/index.html` | +| `page` | The landing page for a given page | `my-post` page (`/posts/my-post/index.html`) | +| `section` | The landing page of a given section | `posts` section (`/posts/index.html`) | +| `taxonomy` | The landing page for a taxonomy | `tags` taxonomy (`/tags/index.html`) | +| `term` | The landing page for one taxonomy's term | term `awesome` in `tags` taxonomy (`/tags/awesome/index.html`) | + +Four other page kinds unrelated to content are `robotsTXT`, `RSS`, `sitemap`, and `404`. Although primarily for internal use, you can specify the name when disabling one or more page kinds on your site. For example: + +{{< code-toggle file=hugo >}} +disableKinds = ['robotsTXT','404'] +{{< /code-toggle >}} diff --git a/docs/content/en/content-management/_index.md b/docs/content/en/content-management/_index.md new file mode 100644 index 000000000..66af24681 --- /dev/null +++ b/docs/content/en/content-management/_index.md @@ -0,0 +1,16 @@ +--- +title: Content management +linkTitle: Overview +description: Hugo makes managing large static sites easy with support for archetypes, content types, menus, cross references, summaries, and more. +categories: [] +keywords: [] +menu: + docs: + identifier: content-management-overview + parent: content-management + weight: 10 +weight: 10 +aliases: [/content/,/content/organization] +--- + +A static site generator needs to extend beyond front matter and a couple of templates to be both scalable and *manageable*. Hugo was designed with not only developers in mind, but also content managers and authors. diff --git a/docs/content/en/content-management/archetypes.md b/docs/content/en/content-management/archetypes.md new file mode 100644 index 000000000..94f038848 --- /dev/null +++ b/docs/content/en/content-management/archetypes.md @@ -0,0 +1,184 @@ +--- +title: Archetypes +description: An archetype is a template for new content. +categories: [content management] +keywords: [archetypes,generators,metadata,front matter] +menu: + docs: + parent: content-management + weight: 140 + quicklinks: +weight: 140 +toc: true +aliases: [/content/archetypes/] +--- + +## Overview + +A content file consists of [front matter] and markup. The markup is typically markdown, but Hugo also supports other [content formats]. Front matter can be TOML, YAML, or JSON. + +The `hugo new content` command creates a new file in the `content` directory, using an archetype as a template. This is the default archetype: + +{{< code-toggle file=archetypes/default.md fm=true >}} +title = '{{ replace .File.ContentBaseName `-` ` ` | title }}' +date = '{{ .Date }}' +draft = true +{{< /code-toggle >}} + +When you create new content, Hugo evaluates the [template actions] within the archetype. For example: + +```sh +hugo new content posts/my-first-post.md +``` + +With the default archetype shown above, Hugo creates this content file: + +{{< code-toggle file=content/posts/my-first-post.md fm=true >}} +title = 'My First Post' +date = '2023-08-24T11:49:46-07:00' +draft = true +{{< /code-toggle >}} + +You can create an archetype for one or more [content types]. For example, use one archetype for posts, and use the default archetype for everything else: + +```text +archetypes/ +├── default.md +└── posts.md +``` + +## Lookup order + +Hugo looks for archetypes in the `archetypes` directory in the root of your project, falling back to the `archetypes` directory in themes or installed modules. An archetype for a specific content type takes precedence over the default archetype. + +For example, with this command: + +```sh +hugo new content posts/my-first-post.md +``` + +The archetype lookup order is: + +1. archetypes/posts.md +1. archetypes/default.md +1. themes/my-theme/archetypes/posts.md +1. themes/my-theme/archetypes/default.md + +If none of these exists, Hugo uses a built-in default archetype. + +## Functions and context + +You can use any [template function] within an archetype. As shown above, the default archetype uses the [`replace`](/functions/strings/replace) function to replace hyphens with spaces when populating the title in front matter. + +Archetypes receive the following objects and values in [context]: + +- `.Date` +- `.Type` +- `.Site` (see [details](/variables/site/)) +- `.File` (see [details](/variables/file/)) + +As shown above, the default archetype passes `.File.ContentBaseName` as the argument to the `replace` function when populating the title in front matter. + +## Include content + +Although typically used as a front matter template, you can also use an archetype to populate content. + +For example, in a documentation site you might have a section (content type) for functions. Every page within this section should follow the same format: a brief description, the function signature, examples, and notes. We can pre-populate the page to remind content authors of the standard format. + +{{< code file=archetypes/functions.md >}} +--- +date: '{{ .Date }}' +draft: true +title: '{{ replace .File.ContentBaseName `-` ` ` | title }}' +--- + +A brief description of what the function does, using simple present tense in the third person singular form. For example: + +`someFunction` returns the string `s` repeated `n` times. + +## Signature + +```text +func someFunction(s string, n int) string +``` + +## Examples + +One or more practical examples, each within a fenced code block. + +## Notes + +Additional information to clarify as needed. +{{< /code >}} + +Although you can include [template actions] within the content body, remember that Hugo evaluates these once---at the time of content creation. In most cases, place template actions in a [template] where Hugo evaluates the actions every time you [build](/getting-started/glossary/#build) the site. + +## Leaf bundles + +You can also create archetypes for [leaf bundles](/getting-started/glossary/#leaf-bundle). + +For example, in a photography site you might have a section (content type) for galleries. Each gallery is leaf bundle with content and images. + +Create an archetype for galleries: + +```text +archetypes/ +├── galleries/ +│ ├── images/ +│ │ └── .gitkeep +│ └── index.md <-- same format as default.md +└── default.md +``` + +Subdirectories within an archetype must contain at least one file. Without a file, Hugo will not create the subdirectory when you create new content. The name and size of the file are irrelevant. The example above includes a `.gitkeep` file, an empty file commonly used to preserve otherwise empty directories in a Git repository. + +To create a new gallery: + +```sh +hugo new galleries/bryce-canyon +``` + +This produces: + +```text +content/ +├── galleries/ +│ └── bryce-canyon/ +│ ├── images/ +│ │ └── .gitkeep +│ └── index.md +└── _index.md +``` + +## Use alternate archetype + +Use the `--kind` command line flag to specify an alternate archetype when creating content. + +For example, let's say your site has two sections: articles and tutorials. Create an archetype for each content type: + +```text +archetypes/ +├── articles.md +├── default.md +└── tutorials.md +``` + +To create an article using the articles archetype: + +```sh +hugo new content articles/something.md +``` + +To create an article using the tutorials archetype: + +```sh +hugo new content --kind tutorials articles/something.md +``` + +[content formats]: /getting-started/glossary/#content-format +[content types]: /getting-started/glossary/#content-type +[context]: /getting-started/glossary/#context +[front matter]: /getting-started/glossary/#front-matter +[template actions]: /getting-started/glossary/#template-action +[template]: /getting-started/glossary/#template +[template function]: /getting-started/glossary/#function diff --git a/docs/content/en/content-management/build-options.md b/docs/content/en/content-management/build-options.md new file mode 100644 index 000000000..bc9d7ff49 --- /dev/null +++ b/docs/content/en/content-management/build-options.md @@ -0,0 +1,321 @@ +--- +title: Build options +description: Build options help define how Hugo must treat a given page when building the site. +categories: [content management,fundamentals] +keywords: [build,content,front matter, page resources] +menu: + docs: + parent: content-management + weight: 70 +weight: 70 +toc: true +aliases: [/content/build-options/] +--- + +Build options are stored in a reserved front matter object named `_build` with these defaults: + +{{< code-toggle file=content/example/index.md fm=true >}} +[_build] +list = 'always' +publishResources = true +render = 'always' +{{< /code-toggle >}} + + +list +: When to include the page within page collections. Specify one of: + + - `always` + : Include the page in _all_ page collections. For example, `site.RegularPages`, `.Pages`, etc. This is the default value. + + - `local` + : Include the page in _local_ page collections. For example, `.RegularPages`, `.Pages`, etc. Use this option to create fully navigable but headless content sections. + + - `never` + : Do not include the page in _any_ page collection. + +publishResources +: Applicable to [page bundles], determines whether to publish the associated [page resources]. Specify one of: + + - `true` + : Always publish resources. This is the default value. + + - `false` + : Only publish a resource when invoking its [`Permalink`], [`RelPermalink`], or [`Publish`] method within a template. + +render +: When to render the page. Specify one of: + + - `always` + : Always render the page to disk. This is the default value. + + - `link` + : Do not render the page to disk, but include it in all page collections. + + - `never` + : Never render the page to disk, and exclude it from all page collections. + +[page bundles]: content-management/page-bundles +[page resources]: /content-management/page-resources +[`Permalink`]: /methods/resource/permalink +[`RelPermalink`]: /methods/resource/relpermalink +[`Publish`]: /methods/resource/publish + +{{% note %}} +Any page, regardless of its build options, will always be available by using the [`.Page.GetPage`] or [`.Site.GetPage`] method. + +[`.Page.GetPage`]: /methods/page/getpage +[`.Site.GetPage`]: /methods/site/getpage +{{% /note %}} + +## Example -- headless page + +Create a unpublished page whose content and resources can be included in other pages. + +```text +content/ +├── headless/ +│ ├── a.jpg +│ ├── b.jpg +│ └── index.md <-- leaf bundle +└── _index.md <-- home page +``` + +Set the build options in front matter: + +{{< code-toggle file=content/headless/index.md fm=true >}} +title = 'Headless page' +[_build] + list = 'never' + publishResources = false + render = 'never' +{{< /code-toggle >}} + +To include the content and images on the home page: + +{{< code file=layouts/_default/home.html >}} +{{ with .Site.GetPage "/headless" }} + {{ .Content }} + {{ range .Resources.ByType "image" }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> + {{ end }} +{{ end }} +{{< /code >}} + +The published site will have this structure: + +```text +public/ +├── headless/ +│ ├── a.jpg +│ └── b.jpg +└── index.html +``` + +In the example above, note that: + +1. Hugo did not publish an HTML file for the page. +2. Despite setting `publishResources` to `false` in front matter, Hugo published the [page resources] because we invoked the [`RelPermalink`] method on each resource. This is the expected behavior. + +## Example -- headless section + +Create a unpublished section whose content and resources can be included in other pages. + +[branch bundle]: /content-management/page-bundles + +```text +content/ +├── headless/ +│ ├── note-1/ +│ │ ├── a.jpg +│ │ ├── b.jpg +│ │ └── index.md <-- leaf bundle +│ ├── note-2/ +│ │ ├── c.jpg +│ │ ├── d.jpg +│ │ └── index.md <-- leaf bundle +│ └── _index.md <-- branch bundle +└── _index.md <-- home page +``` + +Set the build options in front matter, using the `cascade` keyword to "cascade" the values down to descendant pages. + +{{< code-toggle file=content/headless/_index.md fm=true >}} +title = 'Headless section' +[[cascade]] +[cascade._build] + list = 'local' + publishResources = false + render = 'never' +{{< /code-toggle >}} + +In the front matter above, note that we have set `list` to `local` to include the descendant pages in local page collections. + +To include the content and images on the home page: + +{{< code file=layouts/_default/home.html >}} +{{ with .Site.GetPage "/headless" }} + {{ range .Pages }} + {{ .Content }} + {{ range .Resources.ByType "image" }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> + {{ end }} + {{ end }} +{{ end }} +{{< /code >}} + +The published site will have this structure: + +```text +public/ +├── headless/ +│ ├── note-1/ +│ │ ├── a.jpg +│ │ └── b.jpg +│ └── note-2/ +│ ├── c.jpg +│ └── d.jpg +└── index.html +``` + +In the example above, note that: + +1. Hugo did not publish an HTML file for the page. +2. Despite setting `publishResources` to `false` in front matter, Hugo correctly published the [page resources] because we invoked the [`RelPermalink`] method on each resource. This is the expected behavior. + +## Example -- list without publishing + +Publish a section page without publishing the descendant pages. For example, to create a glossary: + +```text +content/ +├── glossary/ +│ ├── _index.md +│ ├── bar.md +│ ├── baz.md +│ └── foo.md +└── _index.md +``` + +Set the build options in front matter, using the `cascade` keyword to "cascade" the values down to descendant pages. + +{{< code-toggle file=content/glossary/_index.md fm=true >}} +title = 'Glossary' +[_build] +render = 'always' +[[cascade]] +[cascade._build] + list = 'local' + publishResources = false + render = 'never' +{{< /code-toggle >}} + +To render the glossary: + +{{< code file=layouts/glossary/list.html >}} +<dl> + {{ range .Pages }} + <dt>{{ .Title }}</dt> + <dd>{{ .Content }}</dd> + {{ end }} +</dl> +{{< /code >}} + +The published site will have this structure: + +```text +public/ +├── glossary/ +│ └── index.html +└── index.html +``` + +## Example -- publish without listing + +Publish a section's descendant pages without publishing the section page itself. + +```text +content/ +├── books/ +│ ├── _index.md +│ ├── book-1.md +│ └── book-2.md +└── _index.md +``` + +Set the build options in front matter: + +{{< code-toggle file=content/books/_index.md >}} +title = 'Books' +[_build] +render = 'never' +list = 'never' +{{< /code-toggle >}} + +The published site will have this structure: + +```html +public/ +├── books/ +│ ├── book-1/ +│ │ └── index.html +│ └── book-2/ +│ └── index.html +└── index.html +``` + +## Example -- conditionally hide section + +Consider this example. A documentation site has a team of contributors with access to 20 custom shortcodes. Each shortcode takes several arguments, and requires documentation for the contributors to reference when using them. + +Instead of external documentation for the shortcodes, include an "internal" section that is hidden when building the production site. + +```text +content/ +├── internal/ +│ ├── shortcodes/ +│ │ ├── _index.md +│ │ ├── shortcode-1.md +│ │ └── shortcode-2.md +│ └── _index.md +├── reference/ +│ ├── _index.md +│ ├── reference-1.md +│ └── reference-2.md +├── tutorials/ +│ ├── _index.md +│ ├── tutorial-1.md +│ └── tutorial-2.md +└── _index.md +``` + +Set the build options in front matter, using the `cascade` keyword to "cascade" the values down to descendant pages, and use the `target` keyword to target the production environment. + +{{< code-toggle file=content/internal/_index.md >}} +title = 'Internal' +[[cascade]] +[cascade._build] +render = 'never' +list = 'never' +[cascade._target] +environment = 'production' +{{< /code-toggle >}} + +The production site will have this structure: + +```html +public/ +├── reference/ +│ ├── reference-1/ +│ │ └── index.html +│ ├── reference-2/ +│ │ └── index.html +│ └── index.html +├── tutorials/ +│ ├── tutorial-1/ +│ │ └── index.html +│ ├── tutorial-2/ +│ │ └── index.html +│ └── index.html +└── index.html +``` diff --git a/docs/content/en/content-management/comments.md b/docs/content/en/content-management/comments.md new file mode 100644 index 000000000..6e58b36e4 --- /dev/null +++ b/docs/content/en/content-management/comments.md @@ -0,0 +1,74 @@ +--- +title: Comments +description: Hugo ships with an internal Disqus template, but this isn't the only commenting system that will work with your new Hugo website. +categories: [content management] +keywords: [sections,content,organization] +menu: + docs: + parent: content-management + weight: 220 +weight: 220 +toc: true +aliases: [/extras/comments/] +--- + +Hugo ships with support for [Disqus](https://disqus.com/), a third-party service that provides comment and community capabilities to websites via JavaScript. + +Your theme may already support Disqus, but if not, it is easy to add to your templates via [Hugo's built-in Disqus partial][disquspartial]. + +## Add Disqus + +Hugo comes with all the code you need to load Disqus into your templates. Before adding Disqus to your site, you'll need to [set up an account][disqussetup]. + +### Configure Disqus + +Disqus comments require you set a single value in your [site's configuration file][configuration] like so: + +{{< code-toggle file=hugo >}} +[services.disqus] +shortname = 'your-disqus-shortname' +{{</ code-toggle >}} + +For many websites, this is enough configuration. However, you also have the option to set the following in the [front matter] of a single content file: + +* `disqus_identifier` +* `disqus_title` +* `disqus_url` + +### Render Hugo's built-in Disqus partial template + +Disqus has its own [internal template](/templates/internal/#disqus) available, to render it add the following code where you want comments to appear: + +```go-html-template +{{ template "_internal/disqus.html" . }} +``` + +## Alternatives + +These are some alternatives to Disqus: + +* [Cactus Comments](https://cactus.chat/docs/integrations/hugo/) (Open Source, Matrix appservice, Docker install) +* [Comentario](https://gitlab.com/comentario/comentario) (Open Source, self-hosted, Go/Angular, run locally, in Docker or Kubernetes) +* [Commento](https://commento.io/) (Open Source, available as a service, local install, or docker image) +* [Giscus](https://giscus.app/) (Open source, comments system powered by GitHub Discussions) +* [Graph Comment](https://graphcomment.com/) +* [Hyvor Talk](https://talk.hyvor.com/) (Available as a service) +* [IntenseDebate](https://intensedebate.com/) +* [Isso](https://isso-comments.de/) (Self-hosted, Python) ([tutorial][issotutorial]) +* [Muut](https://muut.com/) +* [Remark42](https://remark42.com/) (Open source, Golang, Easy to run docker) +* [ReplyBox](https://getreplybox.com/) +* [Staticman](https://staticman.net/) +* [Talkyard](https://blog-comments.talkyard.io/) (Open source, & serverless hosting) +* [Utterances](https://utteranc.es/) (Open source, GitHub comments widget built on GitHub issues) + +[configuration]: /getting-started/configuration/ +[disquspartial]: /templates/internal/#disqus +[disqussetup]: https://disqus.com/profile/signup/ +[forum]: https://discourse.gohugo.io +[front matter]: /content-management/front-matter/ +[kaijuissue]: https://github.com/spf13/kaiju/issues/new +[issotutorial]: https://stiobhart.net/2017-02-24-isso-comments/ +[partials]: /templates/partials/ +[MongoDB]: https://www.mongodb.com/ +[tweet]: https://twitter.com/spf13 diff --git a/docs/content/en/content-management/cross-references.md b/docs/content/en/content-management/cross-references.md new file mode 100644 index 000000000..500e388a4 --- /dev/null +++ b/docs/content/en/content-management/cross-references.md @@ -0,0 +1,150 @@ +--- +title: Links and cross references +description: Shortcodes for creating links to documents. +categories: [content management] +keywords: [cross references,references,anchors,urls] +menu: + docs: + parent: content-management + weight: 170 +weight: 170 +toc: true +aliases: [/extras/crossreferences/] +--- + +The `ref` and `relref` shortcodes display the absolute and relative permalinks to a document, respectively. + +## Use of `ref` and `relref` + +The `ref` and `relref` shortcodes require a single parameter: the path to a content document, with or without a file extension, with or without an anchor. Paths without a leading `/` are first resolved relative to the current page, then to the remainder of the site. + +```text +. +└── content + ├── about + | ├── _index.md + | └── credits.md + ├── pages + | ├── document1.md + | └── document2.md // has anchor #anchor + ├── products + | └── index.md + └── blog + └── my-post.md +``` + +The pages can be referenced as follows: + +```text +{{</* ref "document2" */>}} // <- From pages/document1.md, relative path +{{</* ref "document2#anchor" */>}} +{{</* ref "document2.md" */>}} +{{</* ref "document2.md#anchor" */>}} +{{</* ref "#anchor" */>}} // <- From pages/document2.md +{{</* ref "/blog/my-post" */>}} // <- From anywhere, absolute path +{{</* ref "/blog/my-post.md" */>}} +{{</* relref "document" */>}} +{{</* relref "document.md" */>}} +{{</* relref "#anchor" */>}} +{{</* relref "/blog/my-post.md" */>}} +``` + +index.md can be reference either by its path or by its containing folder without the ending `/`. \_index.md can be referenced only by its containing folder: + +```text +{{</* ref "/about" */>}} // <- References /about/_index.md +{{</* ref "/about/_index" */>}} // Raises REF_NOT_FOUND error +{{</* ref "/about/credits.md" */>}} // <- References /about/credits.md + +{{</* ref "/products" */>}} // <- References /products/index.md +{{</* ref "/products/index" */>}} // <- References /products/index.md +``` + +To generate a hyperlink using `ref` or `relref` in markdown: + +```text +[About]({{</* ref "/about" */>}} "About Us") +``` + +Hugo emits an error or warning if a document cannot be uniquely resolved. The error behavior is configurable; see below. + +### Link to another language version + +To link to another language version of a document, use this syntax: + +```go-html-template +{{</* relref path="document.md" lang="ja" */>}} +``` + +### Get another output format + +To link to another Output Format of a document, use this syntax: + +```go-html-template +{{</* relref path="document.md" outputFormat="rss" */>}} +``` + +### Heading IDs + +When using Markdown document types, Hugo generates element IDs for every heading on a page. For example: + +```md +## Reference +``` + +produces this HTML: + +```html +<h2 id="reference">Reference</h2> +``` + +Get the permalink to a heading by appending the ID to the path when using the `ref` or `relref` shortcodes: + +```go-html-template +{{</* ref "document.md#reference" */>}} +{{</* relref "document.md#reference" */>}} +``` + +Generate a custom heading ID by including an attribute. For example: + +```md +## Reference A {#foo} +## Reference B {id="bar"} +``` + +produces this HTML: + +```html +<h2 id="foo">Reference A</h2> +<h2 id="bar">Reference B</h2> +``` + +Hugo will generate unique element IDs if the same heading appears more than once on a page. For example: + +```md +## Reference +## Reference +## Reference +``` + +produces this HTML: + +```html +<h2 id="reference">Reference</h2> +<h2 id="reference-1">Reference</h2> +<h2 id="reference-2">Reference</h2> +``` + +## Ref and RelRef Configuration + +The behavior can be configured in `hugo.toml`: + +refLinksErrorLevel ("ERROR") +: When using `ref` or `relref` to resolve page links and a link cannot resolved, it will be logged with this log level. Valid values are `ERROR` (default) or `WARNING`. Any `ERROR` will fail the build (`exit -1`). + +refLinksNotFoundURL +: URL to be used as a placeholder when a page reference cannot be found in `ref` or `relref`. Is used as-is. + +[lists]: /templates/lists/ +[output formats]: /templates/output-formats/ +[shortcode]: /content-management/shortcodes/ diff --git a/docs/content/en/content-management/diagrams.md b/docs/content/en/content-management/diagrams.md new file mode 100644 index 000000000..17407098f --- /dev/null +++ b/docs/content/en/content-management/diagrams.md @@ -0,0 +1,263 @@ +--- +title: Diagrams +description: Use fenced code blocks and markdown render hooks to display diagrams. +categories: [content management] +keywords: [diagrams,drawing] +menu: + docs: + parent: content-management + weight: 50 +weight: 50 +toc: true +--- +{{< new-in 0.93.0 >}} + +## GoAT diagrams (ASCII) + +Hugo supports [GoAT](https://github.com/bep/goat) natively. This means that this code block: + +````txt +```goat + . . . .--- 1 .-- 1 / 1 + / \ | | .---+ .-+ + + / \ .---+---. .--+--. | '--- 2 | '-- 2 / \ 2 + + + | | | | ---+ ---+ + + / \ / \ .-+-. .-+-. .+. .+. | .--- 3 | .-- 3 \ / 3 + / \ / \ | | | | | | | | '---+ '-+ + + 1 2 3 4 1 2 3 4 1 2 3 4 '--- 4 '-- 4 \ 4 + +``` +```` + +Will be rendered as: + +```goat + + . . . .--- 1 .-- 1 / 1 + / \ | | .---+ .-+ + + / \ .---+---. .--+--. | '--- 2 | '-- 2 / \ 2 + + + | | | | ---+ ---+ + + / \ / \ .-+-. .-+-. .+. .+. | .--- 3 | .-- 3 \ / 3 + / \ / \ | | | | | | | | '---+ '-+ + + 1 2 3 4 1 2 3 4 1 2 3 4 '--- 4 '-- 4 \ 4 +``` + +## Mermaid diagrams + +Hugo currently does not provide default templates for Mermaid diagrams. But you can easily add your own. One way to do it would be to create `layouts/_default/_markup/render-codeblock-mermaid.html`: + +```go-html-template +<pre class="mermaid"> + {{- .Inner | safeHTML }} +</pre> +{{ .Page.Store.Set "hasMermaid" true }} +``` + +And then include this snippet at the bottom of the content template (**Note**: below `.Content` as the render hook is not processed until `.Content` is executed): + +```go-html-template +{{ if .Page.Store.Get "hasMermaid" }} + <script type="module"> + import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.esm.min.mjs'; + mermaid.initialize({ startOnLoad: true }); + </script> +{{ end }} +``` + +With that you can use the `mermaid` language in Markdown code blocks: + +````text +```mermaid +sequenceDiagram + participant Alice + participant Bob + Alice->>John: Hello John, how are you? + loop Healthcheck + John->>John: Fight against hypochondria + end + Note right of John: Rational thoughts <br/>prevail! + John-->>Alice: Great! + John->>Bob: How about you? + Bob-->>John: Jolly good! +``` +```` + +## Goat ASCII diagram examples + +### Graphics + +```goat + . + 0 3 P * Eye / ^ / + *-------* +y \ +) \ / Reflection + 1 /| 2 /| ^ \ \ \ v + *-------* | | v0 \ v3 --------*-------- + | |4 | |7 | *----\-----* + | *-----|-* +-----> +x / v X \ .-.<-------- o + |/ |/ / / o \ | / | Refraction / \ + *-------* v / \ +-' / \ + 5 6 +z v1 *------------------* v2 | o-----o + v + +``` + +### Complex + +```goat ++-------------------+ ^ .---. +| A Box |__.--.__ __.--> | .-. | | +| | '--' v | * |<--- | | ++-------------------+ '-' | | + Round *---(-. | + .-----------------. .-------. .----------. .-------. | | | + | Mixed Rounded | | | / Diagonals \ | | | | | | + | & Square Corners | '--. .--' / \ |---+---| '-)-' .--------. + '--+------------+-' .--. | '-------+--------' | | | | / Search / + | | | | '---. | '-------' | '-+------' + |<---------->| | | | v Interior | ^ + ' <---' '----' .-----------. ---. .--- v | + .------------------. Diag line | .-------. +---. \ / . | + | if (a > b) +---. .--->| | | | | Curved line \ / / \ | + | obj->fcn() | \ / | '-------' |<--' + / \ | + '------------------' '--' '--+--------' .--. .--. | .-. +Done?+-' + .---+-----. | ^ |\ | | /| .--+ | | \ / + | | | Join \|/ | | Curved | \| |/ | | \ | \ / + | | +----> o --o-- '-' Vertical '--' '--' '-- '--' + .---. + <--+---+-----' | /|\ | | 3 | + v not:line 'quotes' .-' '---' + .-. .---+--------. / A || B *bold* | ^ + | | | Not a dot | <---+---<-- A dash--is not a line v | + '-' '---------+--' / Nor/is this. --- + +``` + +### Process + +```goat + . + .---------. / \ + | START | / \ .-+-------+-. ___________ + '----+----' .-------. A / \ B | |COMPLEX| | / \ .-. + | | END |<-----+CHOICE +----->| | | +--->+ PREPARATION +--->| X | + v '-------' \ / | |PROCESS| | \___________/ '-' + .---------. \ / '-+---+---+-' + / INPUT / \ / + '-----+---' ' + | ^ + v | + .-----------. .-----+-----. .-. + | PROCESS +---------------->| PROCESS |<------+ X | + '-----------' '-----------' '-' +``` + +### File tree + +Created from <https://arthursonzogni.com/Diagon/#Tree> + +```goat { width=300 color="orange" } +───Linux─┬─Android + ├─Debian─┬─Ubuntu─┬─Lubuntu + │ │ ├─Kubuntu + │ │ ├─Xubuntu + │ │ └─Xubuntu + │ └─Mint + ├─Centos + └─Fedora +``` + +### Sequence diagram + +<https://arthursonzogni.com/Diagon/#Sequence> + +```goat { class="w-40" } +┌─────┐ ┌───┐ +│Alice│ │Bob│ +└──┬──┘ └─┬─┘ + │ │ + │ Hello Bob! │ + │───────────>│ + │ │ + │Hello Alice!│ + │<───────────│ +┌──┴──┐ ┌─┴─┐ +│Alice│ │Bob│ +└─────┘ └───┘ + +``` + +### Flowchart + +<https://arthursonzogni.com/Diagon/#Flowchart> + +```goat + _________________ + ╱ ╲ ┌─────┐ + ╱ DO YOU UNDERSTAND ╲____________________________________________________│GOOD!│ + ╲ FLOW CHARTS? ╱yes └──┬──┘ + ╲_________________╱ │ + │no │ + _________▽_________ ______________________ │ + ╱ ╲ ╱ ╲ ┌────┐ │ +╱ OKAY, YOU SEE THE ╲________________╱ ... AND YOU CAN SEE ╲___│GOOD│ │ +╲ LINE LABELED 'YES'? ╱yes ╲ THE ONES LABELED 'NO'? ╱yes└──┬─┘ │ + ╲___________________╱ ╲______________________╱ │ │ + │no │no │ │ + ________▽_________ _________▽__________ │ │ + ╱ ╲ ┌───────────┐ ╱ ╲ │ │ + ╱ BUT YOU SEE THE ╲___│WAIT, WHAT?│ ╱ BUT YOU JUST ╲___ │ │ + ╲ ONES LABELED 'NO'? ╱yes└───────────┘ ╲ FOLLOWED THEM TWICE? ╱yes│ │ │ + ╲__________________╱ ╲____________________╱ │ │ │ + │no │no │ │ │ + ┌───▽───┐ │ │ │ │ + │LISTEN.│ └───────┬───────┘ │ │ + └───┬───┘ ┌──────▽─────┐ │ │ + ┌─────▽────┐ │(THAT WASN'T│ │ │ + │I HATE YOU│ │A QUESTION) │ │ │ + └──────────┘ └──────┬─────┘ │ │ + ┌────▽───┐ │ │ + │SCREW IT│ │ │ + └────┬───┘ │ │ + └─────┬─────┘ │ + │ │ + └─────┬─────┘ + ┌───────▽──────┐ + │LET'S GO DRING│ + └───────┬──────┘ + ┌─────────▽─────────┐ + │HEY, I SHOULD TRY │ + │INSTALLING FREEBSD!│ + └───────────────────┘ + +``` + +### Table + +<https://arthursonzogni.com/Diagon/#Table> + +```goat { class="w-80 dark-blue" } +┌────────────────────────────────────────────────┐ +│ │ +├────────────────────────────────────────────────┤ +│SYNTAX = { PRODUCTION } . │ +├────────────────────────────────────────────────┤ +│PRODUCTION = IDENTIFIER "=" EXPRESSION "." . │ +├────────────────────────────────────────────────┤ +│EXPRESSION = TERM { "|" TERM } . │ +├────────────────────────────────────────────────┤ +│TERM = FACTOR { FACTOR } . │ +├────────────────────────────────────────────────┤ +│FACTOR = IDENTIFIER │ +├────────────────────────────────────────────────┤ +│ | LITERAL │ +├────────────────────────────────────────────────┤ +│ | "[" EXPRESSION "]" │ +├────────────────────────────────────────────────┤ +│ | "(" EXPRESSION ")" │ +├────────────────────────────────────────────────┤ +│ | "{" EXPRESSION "}" . │ +├────────────────────────────────────────────────┤ +│IDENTIFIER = letter { letter } . │ +├────────────────────────────────────────────────┤ +│LITERAL = """" character { character } """" .│ +└────────────────────────────────────────────────┘ +``` diff --git a/docs/content/en/content-management/formats.md b/docs/content/en/content-management/formats.md new file mode 100644 index 000000000..76c8102b5 --- /dev/null +++ b/docs/content/en/content-management/formats.md @@ -0,0 +1,93 @@ +--- +title: Content formats +description: Both HTML and Markdown are supported content formats. +categories: [content management] +keywords: [markdown,asciidoc,pandoc,content format] +menu: + docs: + parent: content-management + weight: 40 +weight: 40 +toc: true +aliases: [/content/markdown-extras/,/content/supported-formats/,/doc/supported-formats/] +--- + +You can put any file type into your `/content` directories, but Hugo uses the `markup` front matter value if set or the file extension (see `Markup identifiers` in the table below) to determine if the markup needs to be processed, e.g.: + +* Markdown converted to HTML +* [Shortcodes](/content-management/shortcodes/) processed +* Layout applied + +## List of content formats + +The current list of content formats in Hugo: + +| Name | Markup identifiers | Comment | +| ------------- | ------------- |-------------| +| Goldmark | `markdown`, `goldmark` |Note that you can set the default handler of `md` and `markdown` to something else, see [Configure Markup](/getting-started/configuration-markup/).| +|Emacs Org-Mode|`org`|See [go-org](https://github.com/niklasfasching/go-org).| +|AsciiDoc|`asciidocext`, `adoc`, `ad`|Needs [Asciidoctor][ascii] installed.| +|RST|`rst`|Needs [RST](https://docutils.sourceforge.io/rst.html) installed.| +|Pandoc|`pandoc`, `pdc`|Needs [Pandoc](https://www.pandoc.org/) installed.| +|HTML|`html`, `htm`|To be treated as a content file, with layout, shortcodes etc., it must have front matter. If not, it will be copied as-is.| + +The `markup identifier` is fetched from either the `markup` variable in front matter or from the file extension. For markup-related configuration, see [Configure Markup](/getting-started/configuration-markup/). + +## External helpers + +Some of the formats in the table above need external helpers installed on your PC. For example, for AsciiDoc files, +Hugo will try to call the `asciidoctor` command. This means that you will have to install the associated +tool on your machine to be able to use these formats. + +Hugo passes reasonable default arguments to these external helpers by default: + +- `asciidoctor`: `--no-header-footer -` +- `rst2html`: `--leave-comments --initial-header-level=2` +- `pandoc`: `--mathjax` + +{{% note %}} +Because additional formats are external commands, generation performance will rely heavily on the performance of the external tool you are using. As this feature is still in its infancy, feedback is welcome. +{{% /note %}} + +### Asciidoctor + +The Asciidoctor community offers a wide set of tools for the AsciiDoc format that can be installed additionally to Hugo. +[See the Asciidoctor docs for installation instructions](https://asciidoctor.org/docs/install-toolchain/). Make sure that also all +optional extensions like `asciidoctor-diagram` or `asciidoctor-html5s` are installed if required. + +{{% note %}} +External `asciidoctor` command requires Hugo rendering to _disk_ to a specific destination directory. It is required to run Hugo with the command option `--destination`. +{{% /note %}} + +Some Asciidoctor parameters can be customized in Hugo. See [details]. + +[details]: /getting-started/configuration-markup/#asciidoc + +## Learn markdown + +Markdown syntax is simple enough to learn in a single sitting. The following are excellent resources to get you up and running: + +* [Daring Fireball: Markdown, John Gruber (Creator of Markdown)][fireball] +* [Markdown Cheatsheet, Adam Pritchard][mdcheatsheet] +* [Markdown Tutorial (Interactive), Garen Torikian][mdtutorial] +* [The Markdown Guide, Matt Cone][mdguide] + +[ascii]: https://asciidoctor.org/ +[config]: /getting-started/configuration/ +[developer tools]: /tools/ +[fireball]: https://daringfireball.net/projects/markdown/ +[gfmtasks]: https://guides.github.com/features/mastering-markdown/#syntax +[helperssource]: https://github.com/gohugoio/hugo/blob/77c60a3440806067109347d04eb5368b65ea0fe8/helpers/general.go#L65 +[hl]: /content-management/syntax-highlighting/ +[hlsc]: /content-management/shortcodes/#highlight +[hugocss]: /css/style.css +[ietf]: https://tools.ietf.org/html/ +[mathjaxdocs]: https://docs.mathjax.org/en/latest/ +[mdcheatsheet]: https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet +[mdguide]: https://www.markdownguide.org/ +[mdtutorial]: https://www.markdowntutorial.com/ +[org]: https://orgmode.org/ +[pandoc]: https://www.pandoc.org/ +[rest]: https://docutils.sourceforge.io/rst.html +[sc]: /content-management/shortcodes/ +[sct]: /templates/shortcode-templates/ diff --git a/docs/content/en/content-management/front-matter.md b/docs/content/en/content-management/front-matter.md new file mode 100644 index 000000000..7593fb759 --- /dev/null +++ b/docs/content/en/content-management/front-matter.md @@ -0,0 +1,244 @@ +--- +title: Front matter +description: Hugo allows you to add front matter in yaml, toml, or json to your content files. +categories: [content management] +keywords: [front matter,yaml,toml,json,metadata,archetypes] +menu: + docs: + parent: content-management + weight: 60 +weight: 60 +toc: true +aliases: [/content/front-matter/] +--- + +**Front matter** allows you to keep metadata attached to an instance of a [content type]---i.e., embedded inside a content file---and is one of the many features that gives Hugo its strength. + +{{< youtube Yh2xKRJGff4 >}} + +## Front matter formats + +Hugo supports four formats for front matter, each with their own identifying tokens. + +TOML +: identified by opening and closing `+++`. + +YAML +: identified by opening and closing `---`. + +JSON +: a single JSON object surrounded by '`{`' and '`}`', followed by a new line. + +ORG +: a group of Org mode keywords in the format '`#+KEY: VALUE`'. Any line that does not start with `#+` ends the front matter section. + Array values can either be separated into multiple lines (`#+KEY: VALUE_1` and `#+KEY: VALUE_2`) or a whitespace separated list of strings (`#+KEY[]: VALUE_1 VALUE_2`). + +### Example + +{{< code-toggle >}} +title = "spf13-vim 3.0 release and new website" +description = "spf13-vim is a cross platform distribution of vim plugins and resources for Vim." +tags = [ ".vimrc", "plugins", "spf13-vim", "vim" ] +date = "2012-04-06" +categories = [ + "Development", + "VIM" +] +slug = "spf13-vim-3-0-release-and-new-website" +{{< /code-toggle >}} + +## Front matter variables + +### Predefined + +There are a few predefined variables that Hugo is aware of. See [Page Variables][pagevars] for how to call many of these predefined variables in your templates. + +aliases +: An array of one or more aliases (e.g., old published paths of renamed content) that will be created in the output directory structure . See [Aliases][aliases] for details. + +audio +: An array of paths to audio files related to the page; used by the `opengraph` [internal template](/templates/internal) to populate `og:audio`. + +cascade +: A map of front matter keys whose values are passed down to the page's descendants unless overwritten by self or a closer ancestor's cascade. See [Front Matter Cascade](#front-matter-cascade) for details. + +date +: The datetime assigned to this page. This is usually fetched from the `date` field in front matter, but this behavior is configurable. + +description +: The description for the content. + +draft +: If `true`, the content will not be rendered unless the `--buildDrafts` flag is passed to the `hugo` command. + +expiryDate +: The datetime at which the content should no longer be published by Hugo; expired content will not be rendered unless the `--buildExpired` flag is passed to the `hugo` command. + +headless +: If `true`, sets a leaf bundle to be [headless][headless-bundle]. + +images +: An array of paths to images related to the page; used by [internal templates](/templates/internal) such as `_internal/twitter_cards.html`. + +isCJKLanguage +: If `true`, Hugo will explicitly treat the content as a CJK language; both `.Summary` and `.WordCount` work properly in CJK languages. + +keywords +: The meta keywords for the content. + +layout +: The layout Hugo should select from the [lookup order][lookup] when rendering the content. If a `type` is not specified in the front matter, Hugo will look for the layout of the same name in the layout directory that corresponds with a content's section. See [Content Types][content type]. + +lastmod +: The datetime at which the content was last modified. + +linkTitle +: Used for creating links to content; if set, Hugo defaults to using the `linkTitle` before the `title`. + +markup +: **experimental**; specify `"rst"` for reStructuredText (requires`rst2html`) or `"md"` (default) for Markdown. + +outputs +: Allows you to specify output formats specific to the content. See [output formats][outputs]. + +publishDate +: If in the future, content will not be rendered unless the `--buildFuture` flag is passed to `hugo`. + +resources +: Used for configuring page bundle resources. See [Page Resources][page-resources]. + +series +: An array of series this page belongs to, as a subset of the `series` [taxonomy](/content-management/taxonomies/); used by the `opengraph` [internal template](/templates/internal) to populate `og:see_also`. + +slug +: Overrides the last segment of the URL path. Not applicable to section pages. See [URL Management](/content-management/urls/#slug) for details. + +summary +: Text used when providing a summary of the article in the `.Summary` page variable; details available in the [content-summaries](/content-management/summaries/) section. + +title +: The title for the content. + +type +: The type of the content; this value will be automatically derived from the directory (i.e., the [section]) if not specified in front matter. + +url +: Overrides the entire URL path. Applicable to regular pages and section pages. See [URL Management](/content-management/urls/#url) for details. + +videos +: An array of paths to videos related to the page; used by the `opengraph` [internal template](/templates/internal) to populate `og:video`. + +weight +: used for [ordering your content in lists][ordering]. Lower weight gets higher precedence. So content with lower weight will come first. If set, weights should be non-zero, as 0 is interpreted as an *unset* weight. + +taxonomies +: Field name of the *plural* form of the index. See `tags` and `categories` in the above front matter examples. *Note that the plural form of user-defined taxonomies cannot be the same as any of the predefined front matter variables.* + +{{% note %}} +If neither `slug` nor `url` is present and [permalinks are not configured otherwise in your site configuration file](/content-management/urls/#permalinks), Hugo will use the file name of your content to create the output URL. See [Content Organization](/content-management/organization) for an explanation of paths in Hugo and [URL Management](/content-management/urls/) for ways to customize Hugo's default behaviors. +{{% /note %}} + +### User-defined + +You can add fields to your front matter arbitrarily to meet your needs. These user-defined key-values are placed into a single `.Params` variable for use in your templates. + +The following fields can be accessed via `.Params.include_toc` and `.Params.show_comments`, respectively. The [Variables] section provides more information on using Hugo's page- and site-level variables in your templates. + +{{< code-toggle >}} +include_toc: true +show_comments: false +{{</ code-toggle >}} + +## Front matter cascade + +Any node or section can pass down to descendants a set of front matter values as long as defined underneath the reserved `cascade` front matter key. + +### Target specific pages + +The `cascade` block can be a slice with a optional `_target` keyword, allowing for multiple `cascade` values targeting different page sets. + +{{< code-toggle >}} +title ="Blog" +[[cascade]] +background = "yosemite.jpg" +[cascade._target] +path="/blog/**" +lang="en" +kind="page" +[[cascade]] +background = "goldenbridge.jpg" +[cascade._target] +kind="section" +{{</ code-toggle >}} + +Keywords available for `_target`: + +path +: A [Glob](https://github.com/gobwas/glob) pattern matching the content path below /content. Expects Unix-styled slashes. Note that this is the virtual path, so it starts at the mount root. The matching supports double-asterisks so you can match for patterns like `/blog/*/**` to match anything from the third level and down. + +kind +: A Glob pattern matching the Page's Kind(s), e.g. "{home,section}". + +lang +: A Glob pattern matching the Page's language, e.g. "{en,sv}". + +environment +: A Glob pattern matching the build environment, e.g. "{production,development}" + +Any of the above can be omitted. + +{{% note %}} +When making a site that supports multiple languages, defining a `[[cascade]]` is recommended to be done in [Site Config](../../getting-started/configuration/#cascade) to prevent duplication. + +If you instea define a `[[cascade]]` in front matter for multiple languages, an `content/XX/foo/_index.md` file needs to be made on a per-language basis, with `XX` the glob pattern matching the Page's language. In this case, the **lang** keyword is ignored. +{{% /note %}} + +### Example + +In `content/blog/_index.md` + +{{< code-toggle >}} +title: Blog +cascade: + banner: images/typewriter.jpg +{{</ code-toggle >}} + +With the above example the Blog section page and its descendants will return `images/typewriter.jpg` when `.Params.banner` is invoked unless: + +- Said descendant has its own `banner` value set +- Or a closer ancestor node has its own `cascade.banner` value set. + +## Order content through front matter + +You can assign content-specific `weight` in the front matter of your content. These values are especially useful for [ordering][ordering] in list views. You can use `weight` for ordering of content and the convention of [`<TAXONOMY>_weight`][taxweight] for ordering content within a taxonomy. See [Ordering and Grouping Hugo Lists][lists] to see how `weight` can be used to organize your content in list views. + +## Override global markdown configuration + +It's possible to set some options for Markdown rendering in a content's front matter as an override to the [rendering options set in your project configuration][config]. + +## Front matter format specs + +- [TOML Spec][toml] +- [YAML Spec][yaml] +- [JSON Spec][json] + +[variables]: /variables/ +[aliases]: /content-management/urls/#aliases +[archetype]: /content-management/archetypes/ +[config]: /getting-started/configuration/ +[content type]: /content-management/types/ +[contentorg]: /content-management/organization/ +[headless-bundle]: /content-management/page-bundles/#headless-bundle +[json]: https://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf +[lists]: /templates/lists/#sort-content +[lookup]: /templates/lookup-order/ +[ordering]: /templates/lists/ +[outputs]: /templates/output-formats/ +[page-resources]: /content-management/page-resources/ +[pagevars]: /variables/page/ +[section]: /content-management/sections/ +[taxweight]: /content-management/taxonomies/ +[toml]: https://toml.io/ +[urls]: /content-management/urls/ +[variables]: /variables/ +[yaml]: https://yaml.org/spec/ diff --git a/docs/content/en/content-management/image-processing/index.md b/docs/content/en/content-management/image-processing/index.md new file mode 100644 index 000000000..9a4f55da1 --- /dev/null +++ b/docs/content/en/content-management/image-processing/index.md @@ -0,0 +1,521 @@ +--- +title: Image processing +description: Resize, crop, rotate, filter, and convert images. +categories: [content management,fundamentals] +keywords: [resources,images] +menu: + docs: + parent: content-management + weight: 90 +toc: true +weight: 90 +--- + +## Image resources + +To process an image you must access the file as a page resource, global resource, or remote resource. + +### Page resource + +A page resource is a file within a [page bundle]. A page bundle is a directory with an `index.md` or `_index.md` file at its root. + +```text +content/ +└── posts/ + └── post-1/ <-- page bundle + ├── index.md + └── sunset.jpg <-- page resource +``` + +To access an image as a page resource: + +```go-html-template +{{ $image := .Resources.Get "sunset.jpg" }} +``` + +### Global resource + +A global resource is a file within the `assets` directory, or within any directory [mounted] to the `assets` directory. + +```text +assets/ +└── images/ + └── sunset.jpg <-- global resource +``` + +To access an image as a global resource: + +```go-html-template +{{ $image := resources.Get "images/sunset.jpg" }} +``` + +### Remote resource + +A remote resource is a file on a remote server, accessible via HTTP or HTTPS. To access an image as a remote resource: + +```go-html-template +{{ $image := resources.GetRemote "https://gohugo.io/img/hugo-logo.png" }} +``` + +## Image rendering + +Once you have accessed an image as either a page resource or a global resource, render it in your templates using the `Permalink`, `RelPermalink`, `Width`, and `Height` properties. + +Example 1: Throws an error if the resource is not found. + +```go-html-template +{{ $image := .Resources.GetMatch "sunset.jpg" }} +<img src="{{ $image.RelPermalink }}" width="{{ $image.Width }}" height="{{ $image.Height }}"> +``` + +Example 2: Skips image rendering if the resource is not found. + +```go-html-template +{{ $image := .Resources.GetMatch "sunset.jpg" }} +{{ with $image }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}"> +{{ end }} +``` + +Example 3: A more concise way to skip image rendering if the resource is not found. + +```go-html-template +{{ with .Resources.GetMatch "sunset.jpg" }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}"> +{{ end }} +``` + +Example 4: Skips rendering if there's problem accessing a remote resource. + +```go-html-template +{{ $u := "https://gohugo.io/img/hugo-logo.png" }} +{{ with resources.GetRemote $u }} + {{ with .Err }} + {{ errorf "%s" . }} + {{ else }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}"> + {{ end }} +{{ else }} + {{ errorf "Unable to get remote resource %q" $u }} +{{ end }} +``` + +## Image processing methods + +The `image` resource implements the [`Process`], [`Resize`], [`Fit`], [`Fill`], [`Crop`], [`Filter`], [`Colors`] and [`Exif`] methods. + +{{% note %}} +Metadata (EXIF, IPTC, XMP, etc.) is not preserved during image transformation. Use the `Exif` method with the _original_ image to extract EXIF metadata from JPEG or TIFF images. +{{% /note %}} + +### Process + +{{< new-in 0.119.0 >}} + +{{% note %}} +The `Process` method is also available as a filter, which is more effective if you need to apply multiple filters to an image. See [Process filter](/functions/images/process). +{{% /note %}} + +Process processes the image with the given specification. The specification can contain an optional action, one of `resize`, `crop`, `fit` or `fill`. This means that you can use this method instead of [`Resize`], [`Fit`], [`Fill`], or [`Crop`]. + +See [Options](#image-processing-options) for available options. + +You can also use this method apply image processing that does not need any scaling, e.g. format conversions: + +```go-html-template +{{/* Convert the image from JPG to PNG. */}} +{{ $png := $jpg.Process "png" }} +``` + +Some more examples: + +```go-html-template +{{/* Rotate the image 90 degrees counter-clockwise. */}} +{{ $image := $image.Process "r90" }} + +{{/* Scaling actions. */}} +{{ $image := $image.Process "resize 600x" }} +{{ $image := $image.Process "crop 600x400" }} +{{ $image := $image.Process "fit 600x400" }} +{{ $image := $image.Process "fill 600x400" }} +``` + +### Resize + +Resize an image to the given width and/or height. + +If you specify both width and height, the resulting image will be disproportionally scaled unless the original image has the same aspect ratio. + +```go-html-template +{{/* Resize to a width of 600px and preserve aspect ratio */}} +{{ $image := $image.Resize "600x" }} + +{{/* Resize to a height of 400px and preserve aspect ratio */}} +{{ $image := $image.Resize "x400" }} + +{{/* Resize to a width of 600px and a height of 400px */}} +{{ $image := $image.Resize "600x400" }} +``` + +### Fit + +Downscale an image to fit the given dimensions while maintaining aspect ratio. You must provide both width and height. + +```go-html-template +{{ $image := $image.Fit "600x400" }} +``` + +### Fill + +Crop and resize an image to match the given dimensions. You must provide both width and height. Use the [`anchor`] option to change the crop box anchor point. + +```go-html-template +{{ $image := $image.Fill "600x400" }} +``` + +### Crop + +Crop an image to match the given dimensions without resizing. You must provide both width and height. Use the [`anchor`] option to change the crop box anchor point. + +```go-html-template +{{ $image := $image.Crop "600x400" }} +``` + +### Filter + +Apply one or more [filters] to an image. + +```go-html-template +{{ $image := $image.Filter (images.GaussianBlur 6) (images.Pixelate 8) }} +``` + +Write this in a more functional style using pipes. Hugo applies the filters in the order given. + +```go-html-template +{{ $image := $image | images.Filter (images.GaussianBlur 6) (images.Pixelate 8) }} +``` + +Sometimes it can be useful to create the filter chain once and then reuse it. + +```go-html-template +{{ $filters := slice (images.GaussianBlur 6) (images.Pixelate 8) }} +{{ $image1 := $image1.Filter $filters }} +{{ $image2 := $image2.Filter $filters }} +``` + +### Colors + +{{< new-in 0.104.0 >}} + +`.Colors` returns a slice of hex strings with the dominant colors in the image using a simple histogram method. + +```go-html-template +{{ $colors := $image.Colors }} +``` + +This method is fast, but if you also scale down your images, it would be good for performance to extract the colors from the scaled down image. + +### EXIF + +Provides an [EXIF] object containing image metadata. + +You may access EXIF data in JPEG and TIFF images. To prevent errors when processing images without EXIF data, wrap the access in a [`with`] statement. + +```go-html-template +{{ with $image.Exif }} + Date: {{ .Date }} + Lat/Long: {{ .Lat }}/{{ .Long }} + Tags: + {{ range $k, $v := .Tags }} + TAG: {{ $k }}: {{ $v }} + {{ end }} +{{ end }} +``` + +You may also access EXIF fields individually, using the [`lang.FormatNumber`] function to format the fields as needed. + +```go-html-template +{{ with $image.Exif }} + <ul> + {{ with .Date }}<li>Date: {{ .Format "January 02, 2006" }}</li>{{ end }} + {{ with .Tags.ApertureValue }}<li>Aperture: {{ lang.FormatNumber 2 . }}</li>{{ end }} + {{ with .Tags.BrightnessValue }}<li>Brightness: {{ lang.FormatNumber 2 . }}</li>{{ end }} + {{ with .Tags.ExposureTime }}<li>Exposure Time: {{ . }}</li>{{ end }} + {{ with .Tags.FNumber }}<li>F Number: {{ . }}</li>{{ end }} + {{ with .Tags.FocalLength }}<li>Focal Length: {{ . }}</li>{{ end }} + {{ with .Tags.ISOSpeedRatings }}<li>ISO Speed Ratings: {{ . }}</li>{{ end }} + {{ with .Tags.LensModel }}<li>Lens Model: {{ . }}</li>{{ end }} + </ul> +{{ end }} +``` + +#### EXIF variables + +.Date +: Image creation date/time. Format with the [time.Format] function. + +.Lat +: GPS latitude in degrees. + +.Long +: GPS longitude in degrees. + +.Tags +: A collection of the available EXIF tags for this image. You may include or exclude specific tags from this collection in the [site configuration](#exif-data). + +## Image processing options + +The [`Resize`], [`Fit`], [`Fill`], and [`Crop`] methods accept a space-delimited, case-insensitive list of options. The order of the options within the list is irrelevant. + +### Dimensions + +With the [`Resize`] method you must specify width, height, or both. The [`Fit`], [`Fill`], and [`Crop`] methods require both width and height. All dimensions are in pixels. + +```go-html-template +{{ $image := $image.Resize "600x" }} +{{ $image := $image.Resize "x400" }} +{{ $image := $image.Resize "600x400" }} +{{ $image := $image.Fit "600x400" }} +{{ $image := $image.Fill "600x400" }} +{{ $image := $image.Crop "600x400" }} +``` + +### Rotation + +Rotates an image counter-clockwise by the given angle. Hugo performs rotation _before_ scaling. For example, if the original image is 600x400 and you wish to rotate the image 90 degrees counter-clockwise while scaling it by 50%: + +```go-html-template +{{ $image = $image.Resize "200x r90" }} +``` + +In the example above, the width represents the desired width _after_ rotation. + +To rotate an image without scaling, use the dimensions of the original image: + +```go-html-template +{{ with .Resources.GetMatch "sunset.jpg" }} + {{ with .Resize (printf "%dx%d r90" .Height .Width) }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}"> + {{ end }} +{{ end }} +``` + +In the example above, on the second line, we have reversed width and height to reflect the desired dimensions _after_ rotation. + +### Anchor + +When using the [`Crop`] or [`Fill`] method, the _anchor_ determines the placement of the crop box. You may specify `TopLeft`, `Top`, `TopRight`, `Left`, `Center`, `Right`, `BottomLeft`, `Bottom`, `BottomRight`, or `Smart`. + +The default value is `Smart`, which uses [Smartcrop] image analysis to determine the optimal placement of the crop box. You may override the default value in the [site configuration]. + +For example, if you have a 400x200 image with a bird in the upper left quadrant, you can create a 200x100 thumbnail containing the bird: + +```go-html-template +{{ $image.Crop "200x100 TopLeft" }} +``` + +If you apply [rotation](#rotation) when using the [`Crop`] or [`Fill`] method, specify the anchor relative to the rotated image. + +### Target format + +By default, Hugo encodes the image in the source format. You may convert the image to another format by specifying `bmp`, `gif`, `jpeg`, `jpg`, `png`, `tif`, `tiff`, or `webp`. + +```go-html-template +{{ $image.Resize "600x webp" }} +``` + +To convert an image without scaling, use the dimensions of the original image: + +```go-html-template +{{ with .Resources.GetMatch "sunset.jpg" }} + {{ with .Resize (printf "%dx%d webp" .Width .Height) }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}"> + {{ end }} +{{ end }} +``` + +### Quality + +Applicable to JPEG and WebP images, the `q` value determines the quality of the converted image. Higher values produce better quality images, while lower values produce smaller files. Set this value to a whole number between 1 and 100, inclusive. + +The default value is 75. You may override the default value in the [site configuration]. + +```go-html-template +{{ $image.Resize "600x webp q50" }} +``` + +### Hint + +Applicable to WebP images, this option corresponds to a set of predefined encoding parameters, and is equivalent to the `-preset` flag for the [`cwebp`] encoder. + +[`cwebp`]: https://developers.google.com/speed/webp/docs/cwebp + +Value|Example +:--|:-- +`drawing`|Hand or line drawing with high-contrast details +`icon`|Small colorful image +`photo`|Outdoor photograph with natural lighting +`picture`|Indoor photograph such as a portrait +`text`|Image that is primarily text + +The default value is `photo`. You may override the default value in the [site configuration]. + +```go-html-template +{{ $image.Resize "600x webp picture" }} +``` + +### Background color + +When converting an image from a format that supports transparency (e.g., PNG) to a format that does _not_ support transparency (e.g., JPEG), you may specify the background color of the resulting image. + +Use either a 3-digit or 6-digit hexadecimal color code (e.g., `#00f` or `#0000ff`). + +The default value is `#ffffff` (white). You may override the default value in the [site configuration]. + +```go-html-template +{{ $image.Resize "600x jpg #b31280" }} +``` + +### Resampling filter + +You may specify the resampling filter used when resizing an image. Commonly used resampling filters include: + +Filter|Description +:--|:-- +`Box`|Simple and fast averaging filter appropriate for downscaling +`Lanczos`|High-quality resampling filter for photographic images yielding sharp results +`CatmullRom`|Sharp cubic filter that is faster than the Lanczos filter while providing similar results +`MitchellNetravali`|Cubic filter that produces smoother results with less ringing artifacts than CatmullRom +`Linear`|Bilinear resampling filter, produces smooth output, faster than cubic filters +`NearestNeighbor`|Fastest resampling filter, no antialiasing + +The default value is `Box`. You may override the default value in the [site configuration]. + +```go-html-template +{{ $image.Resize "600x400 Lanczos" }} +``` + +See [github.com/disintegration/imaging] for the complete list of resampling filters. If you wish to improve image quality at the expense of performance, you may wish to experiment with the alternative filters. + +## Image processing examples + +_The photo of the sunset used in the examples below is Copyright [Bjørn Erik Pedersen](https://commons.wikimedia.org/wiki/User:Bep) (Creative Commons Attribution-Share Alike 4.0 International license)_ + +{{< imgproc "sunset.jpg" "resize 300x" />}} + +{{< imgproc "sunset.jpg" "fill 90x120 left" />}} + +{{< imgproc "sunset.jpg" "fill 90x120 right" />}} + +{{< imgproc "sunset.jpg" "fit 90x90" />}} + +{{< imgproc "sunset.jpg" "crop 250x250 center" />}} + +{{< imgproc "sunset.jpg" "resize 300x q10" />}} + +This is the shortcode used to generate the examples above: + +{{< readfile file=layouts/shortcodes/imgproc.html highlight=go-html-template >}} + +Call the shortcode from your Markdown like this: + +```go-html-template +{{</* imgproc "sunset.jpg" "resize 300x" /*/>}} +``` + +{{% note %}} +Note the self-closing shortcode syntax above. You may call the `imgproc` shortcode with or without **inner content**. +{{% /note %}} + +## Imaging configuration + +### Processing options + +Define an `imaging` section in your site configuration to set the default [image processing options](#image-processing-options). + +{{< code-toggle config=imaging />}} + +anchor +: See image processing options: [anchor](#anchor). + +bgColor +: See image processing options: [background color](#background-color). + +hint +: See image processing options: [hint](#hint). + +quality +: See image processing options: [quality](#quality). + +resampleFilter +: See image processing options: [resampling filter](#resampling-filter). + +### EXIF data + +Define an `imaging.exif` section in your site configuration to control the availability of EXIF data. + +{{< code-toggle file=hugo >}} +[imaging.exif] +includeFields = "" +excludeFields = "" +disableDate = false +disableLatLong = false +{{< /code-toggle >}} + +disableDate +: Hugo extracts the image creation date/time into `.Date`. Set this to `true` to disable. Default is `false`. + +disableLatLong +: Hugo extracts the GPS latitude and longitude into `.Lat` and `.Long`. Set this to `true` to disable. Default is `false`. + +excludeFields +: Regular expression matching the EXIF tags to exclude from the `.Tags` collection. Default is `""`. + +includeFields +: Regular expression matching the EXIF tags to include in the `.Tags` collection. Default is `""`. To include all available tags, set this value to `".*"`. + +{{% note %}} +To improve performance and decrease cache size, Hugo excludes the following tags: `ColorSpace`, `Contrast`, `Exif`, `Exposure[M|P|B]`, `Flash`, `GPS`, `JPEG`, `Metering`, `Resolution`, `Saturation`, `Sensing`, `Sharp`, and `WhiteBalance`. + +To control tag availability, change the `excludeFields` or `includeFields` settings as described above. +{{% /note %}} + +## Smart cropping of images + +By default, Hugo uses the [Smartcrop] library when cropping images with the `Crop` or`Fill` methods. You can set the anchor point manually, but in most cases the `Smart` option will make a good choice. + +Examples using the sunset image from above: + +{{< imgproc "sunset.jpg" "fill 200x200 smart" />}} + +{{< imgproc "sunset.jpg" "crop 200x200 smart" />}} + +## Image processing performance consideration + +Hugo caches processed images in the `resources` directory. If you include this directory in source control, Hugo will not have to regenerate the images in a CI/CD workflow (e.g., GitHub Pages, GitLab Pages, Netlify, etc.). This results in faster builds. + +If you change image processing methods or options, or if you rename or remove images, the `resources` directory will contain unused images. To remove the unused images, perform garbage collection with: + +```sh +hugo --gc +``` + +[time.Format]: /functions/time/format +[`anchor`]: /content-management/image-processing#anchor +[mounted]: /hugo-modules/configuration#module-configuration-mounts +[page bundle]: /content-management/page-bundles +[`lang.FormatNumber`]: /functions/lang/formatnumber +[filters]: /functions/images/filter/#image-filters +[github.com/disintegration/imaging]: <https://github.com/disintegration/imaging#image-resizing> +[Smartcrop]: <https://github.com/muesli/smartcrop#smartcrop> +[Exif]: <https://en.wikipedia.org/wiki/Exif> +[`Process`]: #process +[`Colors`]: #colors +[`Crop`]: #crop +[`Exif`]: #exif +[`Fill`]: #fill +[`Filter`]: #filter +[`Fit`]: #fit +[`Resize`]: #resize +[site configuration]: #processing-options +[`with`]: /functions/go-template/with/ diff --git a/docs/content/en/content-management/image-processing/sunset.jpg b/docs/content/en/content-management/image-processing/sunset.jpg Binary files differnew file mode 100644 index 000000000..4dbcc0836 --- /dev/null +++ b/docs/content/en/content-management/image-processing/sunset.jpg diff --git a/docs/content/en/content-management/mathematics.md b/docs/content/en/content-management/mathematics.md new file mode 100644 index 000000000..d2c71e630 --- /dev/null +++ b/docs/content/en/content-management/mathematics.md @@ -0,0 +1,227 @@ +--- +title: Mathematics in markdown +linkTitle: Mathematics +description: Include mathematical equations and expressions in your markdown using LaTeX or TeX typsetting syntax. +categories: [content management] +keywords: [chemical,chemistry,latex,math,mathjax,tex,typsetting] +menu: + docs: + parent: content-management + weight: 250 +weight: 250 +toc: true +math: true +--- + +{{< new-in 0.122.0 >}} + +\[ +\begin{aligned} +KL(\hat{y} || y) &= \sum_{c=1}^{M}\hat{y}_c \log{\frac{\hat{y}_c}{y_c}} \\ +JS(\hat{y} || y) &= \frac{1}{2}(KL(y||\frac{y+\hat{y}}{2}) + KL(\hat{y}||\frac{y+\hat{y}}{2})) +\end{aligned} +\] + +## Overview + +Mathematical equations and expressions authored in [LaTeX] or [TeX] are common in academic and scientific publications. Your browser typically renders this mathematical markup using an open-source JavaScript display engine such as [MathJax] or [KaTeX]. + +For example, this is the mathematical markup for the equations displayed at the top of this page: + +```text +\[ +\begin{aligned} +KL(\hat{y} || y) &= \sum_{c=1}^{M}\hat{y}_c \log{\frac{\hat{y}_c}{y_c}} \\ +JS(\hat{y} || y) &= \frac{1}{2}(KL(y||\frac{y+\hat{y}}{2}) + KL(\hat{y}||\frac{y+\hat{y}}{2})) +\end{aligned} +\] +``` + +Equations and expressions can be displayed inline with other text, or as standalone blocks. Block presentation is also known as "display" mode. + +Whether an equation or expression appears inline, or as a block, depends on the delimiters that surround the mathematical markup. Delimiters are defined in pairs, where each pair consists of an opening and closing delimiter. The opening and closing delimiters may be the same, or different. Common delimiter pairs are shown in [Step 1]. + +The approach described below avoids reliance on platform-specific features like shortcodes or code block render hooks. Instead, it utilizes a standardized markup format for mathematical equations and expressions, compatible with the rendering engines used by GitHub, GitLab, [Microsoft VS Code], [Obsidian], [Typora], and others. + +## Setup + +Follow these instructions to include mathematical equations and expressions in your markdown using LaTeX or TeX typsetting syntax. + +###### Step 1 + +Enable and configure the Goldmark [passthrough extension] in your site configuration. The passthrough extension preserves raw markdown within delimited snippets of text, including the delimiters themselves. + +{{< code-toggle file=hugo copy=true >}} +[markup.goldmark.extensions.passthrough] +enable = true + +[markup.goldmark.extensions.passthrough.delimiters] +block = [['\[', '\]'], ['$$', '$$']] +inline = [['\(', '\)']] + +[params] +math = true +{{< /code-toggle >}} + +The configuration above enables mathematical rendering on every page unless you set the `math` parameter to `false` in front matter. To enable mathematical rendering as needed, set the `math` parameter to `false` in your site configuration, and set the `math` parameter to `true` in front matter. Use this parameter in your base template as shown in [Step 3]. + +{{% note %}} +The configuration above precludes the use of the `$...$` delimiter pair for inline equations. Although you can add this delimiter pair to the configuration and JavaScript, you will need to double-escape the `$` symbol when used outside of math contexts to avoid unintended formatting. + +See the [inline delimiters](#inline-delimiters) section for details. +{{% /note %}} + +To disable passthrough of inline snippets, omit the `inline` key from the configuration: + +{{< code-toggle file=hugo >}} +[markup.goldmark.extensions.passthrough.delimiters] +block = [['\[', '\]'], ['$$', '$$']] +{{< /code-toggle >}} + +You can define your own opening and closing delimiters, provided they match the delimiters that you set in [Step 2]. + +{{< code-toggle file=hugo >}} +[markup.goldmark.extensions.passthrough.delimiters] +block = [['@@', '@@']] +inline = [['@', '@']] +{{< /code-toggle >}} + +###### Step 2 + +Create a partial template to load MathJax or KaTeX. The example below loads MathJax, or you can use KaTeX as described in the [engines](#engines) section. + +{{< code file=layouts/partials/math.html copy=true >}} +<script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js"></script> +<script> + MathJax = { + tex: { + displayMath: [['\\[', '\\]'], ['$$', '$$']], // block + inlineMath: [['\\(', '\\)']] // inline + } + }; +</script> +{{< /code >}} + +The delimiters above must match the delimiters in your site configuration. + +###### Step 3 + +Conditionally call the partial template from the base template. + +{{< code file=layouts/_default/baseof.html >}} +<head> + ... + {{ if .Param "math" }} + {{ partialCached "math.html" . }} + {{ end }} + ... +</head> +{{< /code >}} + +The example above loads the partial template if you have set the `math` parameter in front matter to `true`. If you have not set the `math` parameter in front matter, the conditional statement falls back to the `math` parameter in your site configuration. + +###### Step 4 + +Include mathematical equations and expressions in your markdown using LaTeX or TeX typsetting syntax. + +{{< code file=content/math-examples.md copy=true >}} +This is an inline \(a^*=x-b^*\) equation. + +These are block equations: + +\[a^*=x-b^*\] + +\[ a^*=x-b^* \] + +\[ +a^*=x-b^* +\] + +These are block equations using alternate delimiters: + +$$a^*=x-b^*$$ + +$$ a^*=x-b^* $$ + +$$ +a^*=x-b^* +$$ +{{< /code >}} + +If you set the `math` parameter to `false` in your site configuration, you must set the `math` parameter to `true` in front matter. For example: + +{{< code-toggle file=content/math-examples.md fm=true >}} +title = 'Math examples' +math = true +date = 2024-01-24T18:09:49-08:00 +{{< /code-toggle >}} + +## Inline delimiters + +The configuration, JavaScript, and examples above use the `\(...\)` delimiter pair for inline equations. The `$...$` delimiter pair is a common alternative, but using it may result in unintended formatting if you use the `$` symbol outside of math contexts. + +If you add the `$...$` delimiter pair to your configuration and JavaScript, you must double-escape the `$` when outside of math contexts, regardless of whether mathematical rendering is enabled on the page. For example: + +```text +A \\$5 bill _saved_ is a \\$5 bill _earned_. +``` + +{{% note %}} +If you use the `$...$` delimiter pair for inline equations, and occasionally use the `$` symbol outside of math contexts, you must use MathJax instead of KaTeX to avoid unintended formatting caused by [this KaTeX limitation](https://github.com/KaTeX/KaTeX/issues/437). +{{% /note %}} + +## Engines + +MathJax and KaTeX are open-source JavaScript display engines. Both engines are fast, but at the time of this writing MathJax v3.2.2 is slightly faster than KaTeX v0.16.9. + +{{% note %}} +If you use the `$...$` delimiter pair for inline equations, and occasionally use the `$` symbol outside of math contexts, you must use MathJax instead of KaTeX to avoid unintended formatting caused by [this KaTeX limitation](https://github.com/KaTeX/KaTeX/issues/437). + +See the [inline delimiters](#inline-delimiters) section for details. +{{% /note %}} + +To use KaTeX instead of MathJax, replace the partial template from [Step 2] with this: + +{{< code file=layouts/partials/math.html copy=true >}} +<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.css" integrity="sha384-n8MVd4RsNIU0tAv4ct0nTaAbDJwPJzDEaqSD1odI+WdtXRGWt2kTvGFasHpSy3SV" crossorigin="anonymous"> +<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.js" integrity="sha384-XjKyOOlGwcjNTAIQHIpgOno0Hl1YQqzUOEleOLALmuqehneUG+vnGctmUb0ZY0l8" crossorigin="anonymous"></script> +<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/contrib/auto-render.min.js" integrity="sha384-+VBxd3r6XgURycqtZ117nYw44OOcIax56Z4dCRWbxyPt0Koah1uHoK0o4+/RRE05" crossorigin="anonymous"></script> +<script> + document.addEventListener("DOMContentLoaded", function() { + renderMathInElement(document.body, { + delimiters: [ + {left: '\\[', right: '\\]', display: true}, // block + {left: '$$', right: '$$', display: true}, // block + {left: '\\(', right: '\\)', display: false}, // inline + ], + throwOnError : false + }); + }); +</script> +{{< /code >}} + +The delimiters above must match the delimiters in your site configuration. + +## Chemistry + +Both MathJax and KaTeX provide support for chemical equations. For example: + +```text +$$C_p[\ce{H2O(l)}] = \pu{75.3 J // mol K}$$ +``` + +$$C_p[\ce{H2O(l)}] = \pu{75.3 J // mol K}$$ + +As shown in [Step 2] above, MathJax supports chemical equations without additional configuration. To add chemistry support to KaTeX, enable the mhchem extension as described in the KaTeX [documentation](https://katex.org/docs/libs). + +[KaTeX]: https://katex.org/ +[LaTeX]: https://www.latex-project.org/ +[MathJax]: https://www.mathjax.org/ +[Microsoft VS Code]: https://code.visualstudio.com/ +[Obsidian]: https://obsidian.md/ +[Step 1]: #step-1 +[Step 2]: #step-2 +[Step 3]: #step-3 +[TeX]: https://en.wikipedia.org/wiki/TeX +[Typora]: https://typora.io/ +[passthrough extension]: https://github.com/gohugoio/hugo-goldmark-extensions diff --git a/docs/content/en/content-management/menus.md b/docs/content/en/content-management/menus.md new file mode 100644 index 000000000..1f5d1ef71 --- /dev/null +++ b/docs/content/en/content-management/menus.md @@ -0,0 +1,232 @@ +--- +title: Menus +description: Create menus by defining entries, localizing each entry, and rendering the resulting data structure. +categories: [content management] +keywords: [menus] +menu: + docs: + parent: content-management + weight: 190 +weight: 190 +toc: true +aliases: [/extras/menus/] +--- + +## Overview + +To create a menu for your site: + +1. Define the menu entries +2. [Localize] each entry +3. Render the menu with a [template] + +Create multiple menus, either flat or nested. For example, create a main menu for the header, and a separate menu for the footer. + +There are three ways to define menu entries: + +1. Automatically +1. In front matter +1. In site configuration + +{{% note %}} +Although you can use these methods in combination when defining a menu, the menu will be easier to conceptualize and maintain if you use one method throughout the site. +{{% /note %}} + +## Define automatically + +To automatically define menu entries for each top-level section of your site, enable the section pages menu in your site configuration. + +{{< code-toggle file=hugo >}} +sectionPagesMenu = "main" +{{< /code-toggle >}} + +This creates a menu structure that you can access with `site.Menus.main` in your templates. See [menu templates] for details. + +## Define in front matter + +To add a page to the "main" menu: + +{{< code-toggle file=content/about.md fm=true >}} +title = 'About' +menus = 'main' +{{< /code-toggle >}} + +Access the entry with `site.Menus.main` in your templates. See [menu templates] for details. + +To add a page to the "main" and "footer" menus: + +{{< code-toggle file=content/contact.md fm=true >}} +title = 'Contact' +menus = ['main','footer'] +{{< /code-toggle >}} + +Access the entry with `site.Menus.main` and `site.Menus.footer` in your templates. See [menu templates] for details. + +{{% note %}} +The configuration key in the examples above is `menus`. The `menu` (singular) configuration key is an alias for `menus`. +{{% /note %}} + +### Properties {#properties-front-matter} + +Use these properties when defining menu entries in front matter: + +identifier +: (`string`) Required when two or more menu entries have the same `name`, or when localizing the `name` using translation tables. Must start with a letter, followed by letters, digits, or underscores. + +name +: (`string`) The text to display when rendering the menu entry. + +params +: (`map`) User-defined properties for the menu entry. + +parent +: (`string`) The `identifier` of the parent menu entry. If `identifier` is not defined, use `name`. Required for child entries in a nested menu. + +post +: (`string`) The HTML to append when rendering the menu entry. + +pre +: (`string`) The HTML to prepend when rendering the menu entry. + +title +: (`string`) The HTML `title` attribute of the rendered menu entry. + +weight +: (`int`) A non-zero integer indicating the entry's position relative the root of the menu, or to its parent for a child entry. Lighter entries float to the top, while heavier entries sink to the bottom. + +### Example {#example-front-matter} + +This front matter menu entry demonstrates some of the available properties: + +{{< code-toggle file=content/products/software.md fm=true >}} +title = 'Software' +[[menus.main]] +parent = 'Products' +weight = 20 +pre = '<i class="fa-solid fa-code"></i>' +[menus.main.params] +class = 'center' +{{< /code-toggle >}} + +Access the entry with `site.Menus.main` in your templates. See [menu templates] for details. + +## Define in site configuration + +To define entries for the "main" menu: + +{{< code-toggle file=hugo >}} +[[menus.main]] +name = 'Home' +pageRef = '/' +weight = 10 + +[[menus.main]] +name = 'Products' +pageRef = '/products' +weight = 20 + +[[menus.main]] +name = 'Services' +pageRef = '/services' +weight = 30 +{{< /code-toggle >}} + +This creates a menu structure that you can access with `site.Menus.main` in your templates. See [menu templates] for details. + +To define entries for the "footer" menu: + +{{< code-toggle file=hugo >}} +[[menus.footer]] +name = 'Terms' +pageRef = '/terms' +weight = 10 + +[[menus.footer]] +name = 'Privacy' +pageRef = '/privacy' +weight = 20 +{{< /code-toggle >}} + +This creates a menu structure that you can access with `site.Menus.footer` in your templates. See [menu templates] for details. + +{{% note %}} +The configuration key in the examples above is `menus`. The `menu` (singular) configuration key is an alias for `menus`. +{{% /note %}} + +### Properties {#properties-site-configuration} + +{{% note %}} +The [properties available to entries defined in front matter] are also available to entries defined in site configuration. + +[properties available to entries defined in front matter]: /content-management/menus/#properties-front-matter +{{% /note %}} + +Each menu entry defined in site configuration requires two or more properties: + +- Specify `name` and `pageRef` for internal links +- Specify `name` and `url` for external links + +pageRef +: (`string`) The file path of the target page, relative to the `content` directory. Omit language code and file extension. Required for *internal* links. + +Kind|pageRef +:--|:-- +home|`/` +page|`/books/book-1` +section|`/books` +taxonomy|`/tags` +term|`/tags/foo` + +url +: (`string`) Required for *external* links. + +### Example {#example-site-configuration} + +This nested menu demonstrates some of the available properties: + +{{< code-toggle file=hugo >}} +[[menus.main]] +name = 'Products' +pageRef = '/products' +weight = 10 + +[[menus.main]] +name = 'Hardware' +pageRef = '/products/hardware' +parent = 'Products' +weight = 1 + +[[menus.main]] +name = 'Software' +pageRef = '/products/software' +parent = 'Products' +weight = 2 + +[[menus.main]] +name = 'Services' +pageRef = '/services' +weight = 20 + +[[menus.main]] +name = 'Hugo' +pre = '<i class="fa fa-heart"></i>' +url = 'https://gohugo.io/' +weight = 30 +[menus.main.params] +rel = 'external' +{{< /code-toggle >}} + +This creates a menu structure that you can access with `site.Menus.main` in your templates. See [menu templates] for details. + +## Localize + +Hugo provides two methods to localize your menu entries. See [multilingual]. + +## Render + +See [menu templates]. + +[localize]: /content-management/multilingual/#menus +[menu templates]: /templates/menu-templates/ +[multilingual]: /content-management/multilingual/#menus +[template]: /templates/menu-templates/ diff --git a/docs/content/en/content-management/multilingual.md b/docs/content/en/content-management/multilingual.md new file mode 100644 index 000000000..ea9f71787 --- /dev/null +++ b/docs/content/en/content-management/multilingual.md @@ -0,0 +1,716 @@ +--- +title: Multilingual mode +linkTitle: Multilingual +description: Hugo supports the creation of websites with multiple languages side by side. +categories: [content management] +keywords: [multilingual,i18n,internationalization] +menu: + docs: + parent: content-management + weight: 230 +weight: 230 +toc: true +aliases: [/content/multilingual/,/tutorials/create-a-multilingual-site/] +--- + +You should define the available languages in a `languages` section in your site configuration. + +Also See [Hugo Multilingual Part 1: Content translation]. + +## Configure languages + +This is the default language configuration: + +{{< code-toggle config=languages />}} + +This is an example of a site configuration for a multilingual project. Any key not defined in a `languages` object will fall back to the global value in the root of your site configuration. + +{{< code-toggle file=hugo >}} +defaultContentLanguage = 'de' +defaultContentLanguageInSubdir = true + +[languages.de] +contentDir = 'content/de' +disabled = false +languageCode = 'de-DE' +languageDirection = 'ltr' +languageName = 'Deutsch' +title = 'Projekt Dokumentation' +weight = 1 + +[languages.de.params] +subtitle = 'Referenz, Tutorials und Erklärungen' + +[languages.en] +contentDir = 'content/en' +disabled = false +languageCode = 'en-US' +languageDirection = 'ltr' +languageName = 'English' +title = 'Project Documentation' +weight = 2 + +[languages.en.params] +subtitle = 'Reference, Tutorials, and Explanations' +{{< /code-toggle >}} + +defaultContentLanguage +: (`string`) The project's default language tag as defined by [RFC 5646]. Must be lower case, and must match one of the defined language keys. Default is `en`. Examples: + +- `en` +- `en-gb` +- `pt-br` + +defaultContentLanguageInSubdir +: (`bool`) If `true`, Hugo renders the default language site in a subdirectory matching the `defaultContentLanguage`. Default is `false`. + +contentDir +: (`string`) The content directory for this language. Omit if [translating by file name]. + +disabled +: (`bool`) If `true`, Hugo will not render content for this language. Default is `false`. + +languageCode +: (`string`) The language tag as defined by [RFC 5646]. This value may include upper and lower case characters, hyphens, or underscores, and does not affect localization or URLs. Hugo uses this value to populate the `language` element in the [built-in RSS template], and the `lang` attribute of the `html` element in the [built-in alias template]. Examples: + +- `en` +- `en-GB` +- `pt-BR` + +languageDirection +: (`string`) The language direction, either left-to-right (`ltr`) or right-to-left (`rtl`). Use this value in your templates with the global [`dir`] HTML attribute. + +languageName +: (`string`) The language name, typically used when rendering a language switcher. + +title +: (`string`) The language title. When set, this overrides the site title for this language. + +weight +: (`int`) The language weight. When set to a non-zero value, this is the primary sort criteria for this language. + +[`dir`]: https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/dir +[built-in RSS template]: https://github.com/gohugoio/hugo/blob/master/tpl/tplimpl/embedded/templates/_default/rss.xml +[built-in alias template]: https://github.com/gohugoio/hugo/blob/master/tpl/tplimpl/embedded/templates/alias.html +[RFC 5646]: https://datatracker.ietf.org/doc/html/rfc5646 +[translating by file name]: #translation-by-file-name + +### Changes in Hugo 0.112.0 + +{{< new-in 0.112.0 >}} + +In Hugo `v0.112.0` we consolidated all configuration options, and improved how the languages and their parameters are merged with the main configuration. But while testing this on Hugo sites out there, we received some error reports and reverted some of the changes in favor of deprecation warnings: + +1. `site.Language.Params` is deprecated. Use `site.Params` directly. +1. Adding custom parameters to the top level language configuration is deprecated. Define custom parameters within `languages.xx.params`. See `color` in the example below. + +{{< code-toggle file=hugo >}} + +title = "My blog" +languageCode = "en-us" + +[languages] +[languages.sv] +title = "Min blogg" +languageCode = "sv" +[languages.en.params] +color = "blue" +{{< /code-toggle >}} + +In the example above, all settings except `color` below `params` map to predefined configuration options in Hugo for the site and its language, and should be accessed via the documented accessors: + +```go-html-template +{{ site.Title }} +{{ site.LanguageCode }} +{{ site.Params.color }} +``` + +### Disable a language + +To disable a language within a `languages` object in your site configuration: + +{{< code-toggle file=hugo >}} +[languages.es] +disabled = true +{{< /code-toggle >}} + +To disable one or more languages in the root of your site configuration: + +{{< code-toggle file=hugo >}} +disableLanguages = ["es", "fr"] +{{< /code-toggle >}} + +To disable one or more languages using an environment variable: + +```sh +HUGO_DISABLELANGUAGES="es fr" hugo +``` + +Note that you cannot disable the default content language. + +### Configure multilingual multihost + +From **Hugo 0.31** we support multiple languages in a multihost configuration. See [this issue](https://github.com/gohugoio/hugo/issues/4027) for details. + +This means that you can now configure a `baseURL` per `language`: + +{{% note %}} +If a `baseURL` is set on the `language` level, then all languages must have one and they must all be different. +{{% /note %}} + +Example: + +{{< code-toggle file=hugo >}} +[languages] +[languages.fr] +baseURL = "https://example.fr" +languageName = "Français" +weight = 1 +title = "En Français" + +[languages.en] +baseURL = "https://example.org/" +languageName = "English" +weight = 2 +title = "In English" +{{</ code-toggle >}} + +With the above, the two sites will be generated into `public` with their own root: + +```text +public +├── en +└── fr +``` + +**All URLs (i.e `.Permalink` etc.) will be generated from that root. So the English home page above will have its `.Permalink` set to `https://example.org/`.** + +When you run `hugo server` we will start multiple HTTP servers. You will typically see something like this in the console: + +```text +Web Server is available at 127.0.0.1:1313 (bind address 127.0.0.1) fr +Web Server is available at 127.0.0.1:1314 (bind address 127.0.0.1) en +Press Ctrl+C to stop +``` + +Live reload and `--navigateToChanged` between the servers work as expected. + +## Translate your content + +There are two ways to manage your content translations. Both ensure each page is assigned a language and is linked to its counterpart translations. + +### Translation by file name + +Considering the following example: + +1. `/content/about.en.md` +2. `/content/about.fr.md` + +The first file is assigned the English language and is linked to the second. +The second file is assigned the French language and is linked to the first. + +Their language is __assigned__ according to the language code added as a __suffix to the file name__. + +By having the same **path and base file name**, the content pieces are __linked__ together as translated pages. + +{{% note %}} +If a file has no language code, it will be assigned the default language. +{{% /note %}} + +### Translation by content directory + +This system uses different content directories for each of the languages. Each language's content directory is set using the `contentDir` parameter. + +{{< code-toggle file=hugo >}} +languages: + en: + weight: 10 + languageName: "English" + contentDir: "content/english" + fr: + weight: 20 + languageName: "Français" + contentDir: "content/french" +{{< /code-toggle >}} + +The value of `contentDir` can be any valid path -- even absolute path references. The only restriction is that the content directories cannot overlap. + +Considering the following example in conjunction with the configuration above: + +1. `/content/english/about.md` +2. `/content/french/about.md` + +The first file is assigned the English language and is linked to the second. +The second file is assigned the French language and is linked to the first. + +Their language is __assigned__ according to the content directory they are __placed__ in. + +By having the same **path and basename** (relative to their language content directory), the content pieces are __linked__ together as translated pages. + +### Bypassing default linking + +Any pages sharing the same `translationKey` set in front matter will be linked as translated pages regardless of basename or location. + +Considering the following example: + +1. `/content/about-us.en.md` +2. `/content/om.nn.md` +3. `/content/presentation/a-propos.fr.md` + +{{< code-toggle >}} +translationKey: "about" +{{< /code-toggle >}} + +By setting the `translationKey` front matter parameter to `about` in all three pages, they will be __linked__ as translated pages. + +### Localizing permalinks + +Because paths and file names are used to handle linking, all translated pages will share the same URL (apart from the language subdirectory). + +To localize URLs: + +- For a regular page, set either [`slug`] or [`url`] in front matter +- For a section page, set [`url`] in front matter + +[`slug`]: /content-management/urls/#slug +[`url`]: /content-management/urls/#url + +For example, a French translation can have its own localized slug. + +{{< code-toggle file=content/about.fr.md fm=true >}} +title: A Propos +slug: "a-propos" +{{< /code-toggle >}} + +At render, Hugo will build both `/about/` and `/fr/a-propos/` without affecting the translation link. + +### Page bundles + +To avoid the burden of having to duplicate files, each Page Bundle inherits the resources of its linked translated pages' bundles except for the content files (Markdown files, HTML files etc...). + +Therefore, from within a template, the page will have access to the files from all linked pages' bundles. + +If, across the linked bundles, two or more files share the same basename, only one will be included and chosen as follows: + +* File from current language bundle, if present. +* First file found across bundles by order of language `Weight`. + +{{% note %}} +Page Bundle resources follow the same language assignment logic as content files, both by file name (`image.jpg`, `image.fr.jpg`) and by directory (`english/about/header.jpg`, `french/about/header.jpg`). +{{%/ note %}} + +## Reference translated content + +To create a list of links to translated content, use a template similar to the following: + +{{< code file=layouts/partials/i18nlist.html >}} +{{ if .IsTranslated }} +<h4>{{ i18n "translations" }}</h4> +<ul> + {{ range .Translations }} + <li> + <a href="{{ .RelPermalink }}">{{ .Lang }}: {{ .LinkTitle }}{{ if .IsPage }} ({{ i18n "wordCount" . }}){{ end }}</a> + </li> + {{ end }} +</ul> +{{ end }} +{{< /code >}} + +The above can be put in a `partial` (i.e., inside `layouts/partials/`) and included in any template, whether a [single content page][contenttemplate] or the [homepage]. It will not print anything if there are no translations for a given page. + +The above also uses the [`i18n` function][i18func] described in the next section. + +### List all available languages + +`.AllTranslations` on a `Page` can be used to list all translations, including the page itself. On the home page it can be used to build a language navigator: + +{{< code file=layouts/partials/allLanguages.html >}} +<ul> +{{ range $.Site.Home.AllTranslations }} +<li><a href="{{ .RelPermalink }}">{{ .Language.LanguageName }}</a></li> +{{ end }} +</ul> +{{< /code >}} + +## Translation of strings + +Hugo uses [go-i18n] to support string translations. [See the project's source repository][go-i18n-source] to find tools that will help you manage your translation workflows. + +Translations are collected from the `themes/<THEME>/i18n/` folder (built into the theme), as well as translations present in `i18n/` at the root of your project. In the `i18n`, the translations will be merged and take precedence over what is in the theme folder. Language files should be named according to [RFC 5646] with names such as `en-US.toml`, `fr.toml`, etc. + +Artificial languages with private use subtags as defined in [RFC 5646 § 2.2.7](https://datatracker.ietf.org/doc/html/rfc5646#section-2.2.7) are also supported. You may omit the `art-x-` prefix for brevity. For example: + +```text +art-x-hugolang +hugolang +``` + +Private use subtags must not exceed 8 alphanumeric characters. + +### Query basic translation + +From within your templates, use the [`i18n`] function like this: + +[`i18n`]: /functions/lang/translate + +```go-html-template +{{ i18n "home" }} +``` + +The function will search for the `"home"` id: + +{{< code-toggle file=i18n/en-US >}} +[home] +other = "Home" +{{< /code-toggle >}} + +The result will be + +```text +Home +``` + +### Query a flexible translation with variables + +Often you will want to use the page variables in the translation strings. To do so, pass the `.` context when calling `i18n`: + +```go-html-template +{{ i18n "wordCount" . }} +``` + +The function will pass the `.` context to the `"wordCount"` id: + +{{< code-toggle file=i18n/en-US >}} +[wordCount] +other = "This article has {{ .WordCount }} words." +{{< /code-toggle >}} + +Assume `.WordCount` in the context has value is 101. The result will be: + +```text +This article has 101 words. +``` + +### Query a singular/plural translation + +To enable pluralization when translating, pass a map with a numeric `.Count` property to the `i18n` function. The example below uses `.ReadingTime` variable which has a built-in `.Count` property. + +```go-html-template +{{ i18n "readingTime" .ReadingTime }} +``` + +The function will read `.Count` from `.ReadingTime` and evaluate whether the number is singular (`one`) or plural (`other`). After that, it will pass to `readingTime` id in `i18n/en-US.toml` file: + +{{< code-toggle file=i18n/en-US >}} +[readingTime] +one = "One minute to read" +other = "{{ .Count }} minutes to read" +{{< /code-toggle >}} + +Assuming `.ReadingTime.Count` in the context has value is 525600. The result will be: + +```text +525600 minutes to read +``` + +If `.ReadingTime.Count` in the context has value is 1. The result is: + +```text +One minute to read +``` + +In case you need to pass a custom data: (`(dict "Count" numeric_value_only)` is minimum requirement) + +```go-html-template +{{ i18n "readingTime" (dict "Count" 25 "FirstArgument" true "SecondArgument" false "Etc" "so on, so far") }} +``` + +## Localization + +The following localization examples assume your site's primary language is English, with translations to French and German. + +{{< code-toggle file=hugo >}} +defaultContentLanguage = 'en' + +[languages] +[languages.en] +contentDir = 'content/en' +languageName = 'English' +weight = 1 +[languages.fr] +contentDir = 'content/fr' +languageName = 'Français' +weight = 2 +[languages.de] +contentDir = 'content/de' +languageName = 'Deutsch' +weight = 3 + +{{< /code-toggle >}} + +### Dates + +With this front matter: + +{{< code-toggle >}} +date = 2021-11-03T12:34:56+01:00 +{{< /code-toggle >}} + +And this template code: + +```go-html-template +{{ .Date | time.Format ":date_full" }} +``` + +The rendered page displays: + +Language|Value +:--|:-- +English|Wednesday, November 3, 2021 +Français|mercredi 3 novembre 2021 +Deutsch|Mittwoch, 3. November 2021 + +See [`time.Format`] for details. + +### Currency + +With this template code: + +```go-html-template +{{ 512.5032 | lang.FormatCurrency 2 "USD" }} +``` + +The rendered page displays: + +Language|Value +:--|:-- +English|$512.50 +Français|512,50 $US +Deutsch|512,50 $ + +See [lang.FormatCurrency] and [lang.FormatAccounting] for details. + +### Numbers + +With this template code: + +```go-html-template +{{ 512.5032 | lang.FormatNumber 2 }} +``` + +The rendered page displays: + +Language|Value +:--|:-- +English|512.50 +Français|512,50 +Deutsch|512,50 + +See [lang.FormatNumber] and [lang.FormatNumberCustom] for details. + +### Percentages + +With this template code: + +```go-html-template +{{ 512.5032 | lang.FormatPercent 2 }} +``` + +The rendered page displays: + +Language|Value +:--|:-- +English|512.50% +Français|512,50 % +Deutsch|512,50 % + +See [lang.FormatPercent] for details. + +## Menus + +Localization of menu entries depends on how you define them: + +- When you define menu entries [automatically] using the section pages menu, you must use translation tables to localize each entry. +- When you define menu entries [in front matter], they are already localized based on the front matter itself. If the front matter values are insufficient, use translation tables to localize each entry. +- When you define menu entries [in site configuration], you must create language-specific menu entries under each language key. If the names of the menu entries are insufficient, use translation tables to localize each entry. + +### Create language-specific menu entries + +#### Method 1 -- Use a single configuration file + +For a simple menu with a small number of entries, use a single configuration file. For example: + +{{< code-toggle file=hugo >}} +[languages.de] +languageCode = 'de-DE' +languageName = 'Deutsch' +weight = 1 + +[[languages.de.menus.main]] +name = 'Produkte' +pageRef = '/products' +weight = 10 + +[[languages.de.menus.main]] +name = 'Leistungen' +pageRef = '/services' +weight = 20 + +[languages.en] +languageCode = 'en-US' +languageName = 'English' +weight = 2 + +[[languages.en.menus.main]] +name = 'Products' +pageRef = '/products' +weight = 10 + +[[languages.en.menus.main]] +name = 'Services' +pageRef = '/services' +weight = 20 +{{< /code-toggle >}} + +#### Method 2 -- Use a configuration directory + +With a more complex menu structure, create a [configuration directory] and split the menu entries into multiple files, one file per language. For example: + +```text +config/ +└── _default/ + ├── menus.de.toml + ├── menus.en.toml + └── hugo.toml +``` + +{{< code-toggle file=config/_default/menus.de >}} +[[main]] +name = 'Produkte' +pageRef = '/products' +weight = 10 +[[main]] +name = 'Leistungen' +pageRef = '/services' +weight = 20 +{{< /code-toggle >}} + +{{< code-toggle file=config/_default/menus.en >}} +[[main]] +name = 'Products' +pageRef = '/products' +weight = 10 +[[main]] +name = 'Services' +pageRef = '/services' +weight = 20 +{{< /code-toggle >}} + +[configuration directory]: /getting-started/configuration/#configuration-directory + +### Use translation tables + +When rendering the text that appears in menu each entry, the [example menu template] does this: + +```go-html-template +{{ or (T .Identifier) .Name | safeHTML }} +``` + +It queries the translation table for the current language using the menu entry's `identifier` and returns the translated string. If the translation table does not exist, or if the `identifier` key is not present in the translation table, it falls back to `name`. + +The `identifier` depends on how you define menu entries: + +- If you define the menu entry [automatically] using the section pages menu, the `identifier` is the page's `.Section`. +- If you define the menu entry [in site configuration] or [in front matter], set the `identifier` property to the desired value. + +For example, if you define menu entries in site configuration: + +{{< code-toggle file=hugo >}} +[[menus.main]] + identifier = 'products' + name = 'Products' + pageRef = '/products' + weight = 10 +[[menus.main]] + identifier = 'services' + name = 'Services' + pageRef = '/services' + weight = 20 +{{< / code-toggle >}} + +Create corresponding entries in the translation tables: + +{{< code-toggle file=i18n/de >}} +products = 'Produkte' +services = 'Leistungen' +{{< / code-toggle >}} + +[example menu template]: /templates/menu-templates/#example +[automatically]: /content-management/menus/#define-automatically +[in front matter]: /content-management/menus/#define-in-front-matter +[in site configuration]: /content-management/menus/#define-in-site-configuration + +## Missing translations + +If a string does not have a translation for the current language, Hugo will use the value from the default language. If no default value is set, an empty string will be shown. + +While translating a Hugo website, it can be handy to have a visual indicator of missing translations. The [`enableMissingTranslationPlaceholders` configuration option][config] will flag all untranslated strings with the placeholder `[i18n] identifier`, where `identifier` is the id of the missing translation. + +{{% note %}} +Hugo will generate your website with these missing translation placeholders. It might not be suitable for production environments. +{{% /note %}} + +For merging of content from other languages (i.e. missing content translations), see [lang.Merge]. + +To track down missing translation strings, run Hugo with the `--printI18nWarnings` flag: + +```sh +hugo --printI18nWarnings | grep i18n +i18n|MISSING_TRANSLATION|en|wordCount +``` + +## Multilingual themes support + +To support Multilingual mode in your themes, some considerations must be taken for the URLs in the templates. If there is more than one language, URLs must meet the following criteria: + +* Come from the built-in `.Permalink` or `.RelPermalink` +* Be constructed with the [`relLangURL`] or [`absLangURL`] template function, or be prefixed with `{{ .LanguagePrefix }}` + +If there is more than one language defined, the `LanguagePrefix` variable will equal `/en` (or whatever your `CurrentLanguage` is). If not enabled, it will be an empty string (and is therefore harmless for single-language Hugo websites). + +## Generate multilingual content with `hugo new content` + +If you organize content with translations in the same directory: + +```sh +hugo new content post/test.en.md +hugo new content post/test.de.md +``` + +If you organize content with translations in different directories: + +```sh +hugo new content content/en/post/test.md +hugo new content content/de/post/test.md +``` + +[`abslangurl`]: /functions/urls/abslangurl +[config]: /getting-started/configuration/ +[contenttemplate]: /templates/single-page-templates/ +[go-i18n-source]: https://github.com/nicksnyder/go-i18n +[go-i18n]: https://github.com/nicksnyder/go-i18n +[homepage]: /templates/homepage/ +[Hugo Multilingual Part 1: Content translation]: https://regisphilibert.com/blog/2018/08/hugo-multilingual-part-1-managing-content-translation/ +[i18func]: /functions/lang/translate +[lang.FormatAccounting]: /functions/lang/formataccounting +[lang.FormatCurrency]: /functions/lang/formatcurrency +[lang.FormatNumber]: /functions/lang/formatnumber +[lang.FormatNumberCustom]: /functions/lang/formatnumbercustom +[lang.FormatPercent]: /functions/lang/formatpercent +[lang.Merge]: /functions/lang/merge/ +[menus]: /content-management/menus/ +[OS environment]: /getting-started/configuration/#configure-with-environment-variables +[`rellangurl`]: /functions/urls/rellangurl +[RFC 5646]: https://tools.ietf.org/html/rfc5646 +[single page templates]: /templates/single-page-templates/ +[`time.Format`]: /functions/time/format diff --git a/docs/content/en/content-management/organization/1-featured-content-bundles.png b/docs/content/en/content-management/organization/1-featured-content-bundles.png Binary files differnew file mode 100644 index 000000000..501e671e2 --- /dev/null +++ b/docs/content/en/content-management/organization/1-featured-content-bundles.png diff --git a/docs/content/en/content-management/organization/index.md b/docs/content/en/content-management/organization/index.md new file mode 100644 index 000000000..22b341fcf --- /dev/null +++ b/docs/content/en/content-management/organization/index.md @@ -0,0 +1,154 @@ +--- +title: Content organization +linkTitle: Organization +description: Hugo assumes that the same structure that works to organize your source content is used to organize the rendered site. +categories: [content management,fundamentals] +keywords: [sections,content,organization,bundle,resources] +menu: + docs: + parent: content-management + weight: 20 +weight: 20 +toc: true +aliases: [/content/sections/] +--- + +## Page bundles + +Hugo `0.32` announced page-relative images and other resources packaged into `Page Bundles`. + +These terms are connected, and you also need to read about [Page Resources](/content-management/page-resources) and [Image Processing](/content-management/image-processing) to get the full picture. + +{{< imgproc "1-featured-content-bundles.png" "resize 300x" >}} +The illustration shows three bundles. Note that the home page bundle cannot contain other content pages, although other files (images etc.) are allowed. +{{< /imgproc >}} + +{{% note %}} +The bundle documentation is a **work in progress**. We will publish more comprehensive docs about this soon. +{{% /note %}} + +## Organization of content source + +In Hugo, your content should be organized in a manner that reflects the rendered website. + +While Hugo supports content nested at any level, the top levels (i.e. `content/<DIRECTORIES>`) are special in Hugo and are considered the content type used to determine layouts etc. To read more about sections, including how to nest them, see [sections]. + +Without any additional configuration, the following will automatically work: + +```txt +. +└── content + └── about + | └── index.md // <- https://example.org/about/ + ├── posts + | ├── firstpost.md // <- https://example.org/posts/firstpost/ + | ├── happy + | | └── ness.md // <- https://example.org/posts/happy/ness/ + | └── secondpost.md // <- https://example.org/posts/secondpost/ + └── quote + ├── first.md // <- https://example.org/quote/first/ + └── second.md // <- https://example.org/quote/second/ +``` + +## Path breakdown in Hugo + +The following demonstrates the relationships between your content organization and the output URL structure for your Hugo website when it renders. These examples assume you are [using pretty URLs][pretty], which is the default behavior for Hugo. The examples also assume a key-value of `baseURL = "https://example.org"` in your [site's configuration file][config]. + +### Index pages: `_index.md` + +`_index.md` has a special role in Hugo. It allows you to add front matter and content to your [list templates][lists]. These templates include those for [section templates], [taxonomy templates], [taxonomy terms templates], and your [homepage template]. + +{{% note %}} +**Tip:** You can get a reference to the content and metadata in `_index.md` using the [`.Site.GetPage` function](/methods/page/getpage). +{{% /note %}} + +You can create one `_index.md` for your homepage and one in each of your content sections, taxonomies, and taxonomy terms. The following shows typical placement of an `_index.md` that would contain content and front matter for a `posts` section list page on a Hugo website: + +```txt +. url +. ⊢--^-⊣ +. path slug +. ⊢--^-⊣⊢---^---⊣ +. filepath +. ⊢------^------⊣ +content/posts/_index.md +``` + +At build, this will output to the following destination with the associated values: + +```txt + + url ("/posts/") + ⊢-^-⊣ + baseurl section ("posts") +⊢--------^---------⊣⊢-^-⊣ + permalink +⊢----------^-------------⊣ +https://example.org/posts/index.html +``` + +The [sections] can be nested as deeply as you want. The important thing to understand is that to make the section tree fully navigational, at least the lower-most section must include a content file. (i.e. `_index.md`). + +### Single pages in sections + +Single content files in each of your sections will be rendered as [single page templates][singles]. Here is an example of a single `post` within `posts`: + +```txt + path ("posts/my-first-hugo-post.md") +. ⊢-----------^------------⊣ +. section slug +. ⊢-^-⊣⊢--------^----------⊣ +content/posts/my-first-hugo-post.md +``` + +When Hugo builds your site, the content will be output to the following destination: + +```txt + + url ("/posts/my-first-hugo-post/") + ⊢------------^----------⊣ + baseurl section slug +⊢--------^--------⊣⊢-^--⊣⊢-------^---------⊣ + permalink +⊢--------------------^---------------------⊣ +https://example.org/posts/my-first-hugo-post/index.html +``` + +## Paths explained + +The following concepts provide more insight into the relationship between your project's organization and the default Hugo behavior when building output for the website. + +### `section` + +A default content type is determined by the section in which a content item is stored. `section` is determined by the location within the project's `content` directory. `section` *cannot* be specified or overridden in front matter. + +### `slug` + +The `slug` is the last segment of the URL path, defined by the file name and optionally overridden by a `slug` value in front matter. See [URL Management](/content-management/urls/#slug) for details. + +### `path` + +A content's `path` is determined by the section's path to the file. The file `path` + +* is based on the path to the content's location AND +* does not include the slug + +### `url` + +The `url` is the entire URL path, defined by the file path and optionally overridden by a `url` value in front matter. See [URL Management](/content-management/urls/#slug) for details. + +[config]: /getting-started/configuration/ +[formats]: /content-management/formats/ +[front matter]: /content-management/front-matter/ +[getpage]: /methods/page/getpage +[homepage template]: /templates/homepage/ +[homepage]: /templates/homepage/ +[lists]: /templates/lists/ +[pretty]: /content-management/urls/#appearance +[section templates]: /templates/section-templates/ +[sections]: /content-management/sections/ +[singles]: /templates/single-page-templates/ +[taxonomy templates]: /templates/taxonomy-templates/ +[taxonomy terms templates]: /templates/taxonomy-templates/ +[types]: /content-management/types/ +[urls]: /content-management/urls/ diff --git a/docs/content/en/content-management/page-bundles.md b/docs/content/en/content-management/page-bundles.md new file mode 100644 index 000000000..860fff2bb --- /dev/null +++ b/docs/content/en/content-management/page-bundles.md @@ -0,0 +1,183 @@ +--- +title: Page bundles +description: Content organization using Page Bundles +categories: [content management] +keywords: [page,bundle,leaf,branch] +menu : + docs: + parent: content-management + weight: 30 +weight: 30 +toc: true +--- + +Page Bundles are a way to group [Page Resources](/content-management/page-resources/). + +A Page Bundle can be one of: + +- Leaf Bundle (leaf means it has no children) +- Branch Bundle (home page, section, taxonomy terms, taxonomy list) + +| | Leaf Bundle | Branch Bundle | +|-------------------------------------|----------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| Usage | Collection of content and attachments for single pages | Collection of attachments for section pages (home page, section, taxonomy terms, taxonomy list) | +| Index file name | `index.md` [^fn:1] | `_index.md` [^fn:1] | +| Allowed Resources | Page and non-page (like images, PDF, etc.) types | Only non-page (like images, PDF, etc.) types | +| Where can the Resources live? | At any directory level within the leaf bundle directory. | Only in the directory level **of** the branch bundle directory i.e. the directory containing the `_index.md` ([ref](https://discourse.gohugo.io/t/question-about-content-folder-structure/11822/4?u=kaushalmodi)). | +| Layout type | [`single`](/templates/single-page-templates/) | [`list`](/templates/lists) | +| Nesting | Does not allow nesting of more bundles under it | Allows nesting of leaf or branch bundles under it | +| Example | `content/posts/my-post/index.md` | `content/posts/_index.md` | +| Content from non-index page files...| Accessed only as page resources | Accessed only as regular pages | + +## Leaf bundles + +A _Leaf Bundle_ is a directory at any hierarchy within the `content/` +directory, that contains an **`index.md`** file. + +### Examples of leaf bundle organization {#examples-of-leaf-bundle-organization} + +```text +content/ +├── about +│ ├── index.md +├── posts +│ ├── my-post +│ │ ├── content1.md +│ │ ├── content2.md +│ │ ├── image1.jpg +│ │ ├── image2.png +│ │ └── index.md +│ └── my-other-post +│ └── index.md +│ +└── another-section + ├── .. + └── not-a-leaf-bundle + ├── .. + └── another-leaf-bundle + └── index.md +``` + +In the above example `content/` directory, there are four leaf +bundles: + +about +: This leaf bundle is at the root level (directly under + `content` directory) and has only the `index.md`. + +my-post +: This leaf bundle has the `index.md`, two other content + Markdown files and two image files. + +- image1, image2: +These images are page resources of `my-post` + and only available in `my-post/index.md` resources. + +- content1, content2: +These content files are page resources of `my-post` + and only available in `my-post/index.md` resources. + They will **not** be rendered as individual pages. + +my-other-post +: This leaf bundle has only the `index.md`. + +another-leaf-bundle +: This leaf bundle is nested under couple of + directories. This bundle also has only the `index.md`. + +{{% note %}} +The hierarchy depth at which a leaf bundle is created does not matter, +as long as it is not inside another **leaf** bundle. +{{% /note %}} + +### Headless bundle + +A headless bundle is a bundle that is configured to not get published +anywhere: + +- It will have no `Permalink` and no rendered HTML in `public/`. +- It will not be part of `.Site.RegularPages`, etc. + +But you can get it by `.Site.GetPage`. Here is an example: + +```go-html-template +{{ $headless := .Site.GetPage "/some-headless-bundle" }} +{{ $reusablePages := $headless.Resources.Match "author*" }} +<h2>Authors</h2> +{{ range $reusablePages }} + <h3>{{ .Title }}</h3> + {{ .Content }} +{{ end }} +``` + +_In this example, we are assuming the `some-headless-bundle` to be a headless + bundle containing one or more **page** resources whose `.Name` matches + `"author*"`._ + +Explanation of the above example: + +1. Get the `some-headless-bundle` Page "object". +2. Collect a _slice_ of resources in this _Page Bundle_ that matches + `"author*"` using `.Resources.Match`. +3. Loop through that _slice_ of nested pages, and output their `.Title` and + `.Content`. + +--- + +A leaf bundle can be made headless by adding below in the front matter +(in the `index.md`): + +{{< code-toggle file=content/headless/index.md fm=true >}} +headless = true +{{< /code-toggle >}} + +There are many use cases of such headless page bundles: + +- Shared media galleries +- Reusable page content "snippets" + +## Branch bundles + +A _Branch Bundle_ is any directory at any hierarchy within the +`content/` directory, that contains at least an **`_index.md`** file. + +This `_index.md` can also be directly under the `content/` directory. + +{{% note %}} +Here `md` (markdown) is used just as an example. You can use any file +type as a content resource as long as it is a content type recognized by Hugo. +{{% /note %}} + +### Examples of branch bundle organization + +```text +content/ +├── branch-bundle-1 +│ ├── branch-content1.md +│ ├── branch-content2.md +│ ├── image1.jpg +│ ├── image2.png +│ └── _index.md +└── branch-bundle-2 + ├── _index.md + └── a-leaf-bundle + └── index.md +``` + +In the above example `content/` directory, there are two branch +bundles (and a leaf bundle): + +branch-bundle-1 +: This branch bundle has the `_index.md`, two + other content Markdown files and two image files. + +branch-bundle-2 +: This branch bundle has the `_index.md` and a + nested leaf bundle. + +{{% note %}} +The hierarchy depth at which a branch bundle is created does not +matter. +{{% /note %}} + +[^fn:1]: The `.md` extension is just an example. The extension can be `.html`, `.json` or any valid MIME type. diff --git a/docs/content/en/content-management/page-resources.md b/docs/content/en/content-management/page-resources.md new file mode 100644 index 000000000..f141510bb --- /dev/null +++ b/docs/content/en/content-management/page-resources.md @@ -0,0 +1,203 @@ +--- +title: Page resources +description: Page resources -- images, other pages, documents, etc. -- have page-relative URLs and their own metadata. +categories: [content management] +keywords: [bundle,content,resources] +menu: + docs: + parent: content-management + weight: 80 +weight: 80 +toc: true +--- +Page resources are only accessible from [page bundles](/content-management/page-bundles), those directories with `index.md` or +`_index.md` files at their root. Page resources are only available to the +page with which they are bundled. + +In this example, `first-post` is a page bundle with access to 10 page resources including audio, data, documents, images, and video. Although `second-post` is also a page bundle, it has no page resources and is unable to directly access the page resources associated with `first-post`. + +```text +content +└── post + ├── first-post + │ ├── images + │ │ ├── a.jpg + │ │ ├── b.jpg + │ │ └── c.jpg + │ ├── index.md (root of page bundle) + │ ├── latest.html + │ ├── manual.json + │ ├── notice.md + │ ├── office.mp3 + │ ├── pocket.mp4 + │ ├── rating.pdf + │ └── safety.txt + └── second-post + └── index.md (root of page bundle) +``` + +## Properties + +ResourceType +: The main type of the resource's [Media Type](/templates/output-formats/#media-types). For example, a file of MIME type `image/jpeg` has the ResourceType `image`. A `Page` will have `ResourceType` with value `page`. + +Name +: Default value is the file name (relative to the owning page). Can be set in front matter. + +Title +: Default value is the same as `.Name`. Can be set in front matter. + +Permalink +: The absolute URL to the resource. Resources of type `page` will have no value. + +RelPermalink +: The relative URL to the resource. Resources of type `page` will have no value. + +Content +: The content of the resource itself. For most resources, this returns a string +with the contents of the file. Use this to create inline resources. + +```go-html-template +{{ with .Resources.GetMatch "script.js" }} + <script>{{ .Content | safeJS }}</script> +{{ end }} + +{{ with .Resources.GetMatch "style.css" }} + <style>{{ .Content | safeCSS }}</style> +{{ end }} + +{{ with .Resources.GetMatch "img.png" }} + <img src="data:{{ .MediaType.Type }};base64,{{ .Content | base64Encode }}"> +{{ end }} +``` + +MediaType.Type +: The media type (formerly known as a MIME type) of the resource (e.g., `image/jpeg`). + +MediaType.MainType +: The main type of the resource's media type (e.g., `image`). + +MediaType.SubType +: The subtype of the resource's type (e.g., `jpeg`). This may or may not correspond to the file suffix. + +MediaType.Suffixes +: A slice of possible file suffixes for the resource's media type (e.g., `[jpg jpeg jpe jif jfif]`). + +## Methods + +ByType +: Returns the page resources of the given type. + +```go-html-template +{{ .Resources.ByType "image" }} +``` +Match +: Returns all the page resources (as a slice) whose `Name` matches the given Glob pattern ([examples](https://github.com/gobwas/glob/blob/master/readme.md)). The matching is case-insensitive. + +```go-html-template +{{ .Resources.Match "images/*" }} +``` + +GetMatch +: Same as `Match` but will return the first match. + +### Pattern matching + +```go +// Using Match/GetMatch to find this images/sunset.jpg ? +.Resources.Match "images/sun*" ✅ +.Resources.Match "**/sunset.jpg" ✅ +.Resources.Match "images/*.jpg" ✅ +.Resources.Match "**.jpg" ✅ +.Resources.Match "*" 🚫 +.Resources.Match "sunset.jpg" 🚫 +.Resources.Match "*sunset.jpg" 🚫 +``` + +## Page resources metadata + +The page resources' metadata is managed from the corresponding page's front matter with an array/table parameter named `resources`. You can batch assign values using [wildcards](https://tldp.org/LDP/GNU-Linux-Tools-Summary/html/x11655.htm). + +{{% note %}} +Resources of type `page` get `Title` etc. from their own front matter. +{{% /note %}} + +name +: Sets the value returned in `Name`. + +{{% note %}} +The methods `Match`, `Get` and `GetMatch` use `Name` to match the resources. +{{% /note %}} + +title +: Sets the value returned in `Title` + +params +: A map of custom key/values. + +### Resources metadata example + +{{< code-toggle >}} +title: Application +date : 2018-01-25 +resources : +- src : "images/sunset.jpg" + name : "header" +- src : "documents/photo_specs.pdf" + title : "Photo Specifications" + params: + icon : "photo" +- src : "documents/guide.pdf" + title : "Instruction Guide" +- src : "documents/checklist.pdf" + title : "Document Checklist" +- src : "documents/payment.docx" + title : "Proof of Payment" +- src : "**.pdf" + name : "pdf-file-:counter" + params : + icon : "pdf" +- src : "**.docx" + params : + icon : "word" +{{</ code-toggle >}} + +From the example above: + +- `sunset.jpg` will receive a new `Name` and can now be found with `.GetMatch "header"`. +- `documents/photo_specs.pdf` will get the `photo` icon. +- `documents/checklist.pdf`, `documents/guide.pdf` and `documents/payment.docx` will get `Title` as set by `title`. +- Every `PDF` in the bundle except `documents/photo_specs.pdf` will get the `pdf` icon. +- All `PDF` files will get a new `Name`. The `name` parameter contains a special placeholder [`:counter`](#the-counter-placeholder-in-name-and-title), so the `Name` will be `pdf-file-1`, `pdf-file-2`, `pdf-file-3`. +- Every docx in the bundle will receive the `word` icon. + +{{% note %}} +The __order matters__ --- Only the **first set** values of the `title`, `name` and `params`-**keys** will be used. Consecutive parameters will be set only for the ones not already set. In the above example, `.Params.icon` is first set to `"photo"` in `src = "documents/photo_specs.pdf"`. So that would not get overridden to `"pdf"` by the later set `src = "**.pdf"` rule. +{{% /note %}} + +### The `:counter` placeholder in `name` and `title` + +The `:counter` is a special placeholder recognized in `name` and `title` parameters `resources`. + +The counter starts at 1 the first time they are used in either `name` or `title`. + +For example, if a bundle has the resources `photo_specs.pdf`, `other_specs.pdf`, `guide.pdf` and `checklist.pdf`, and the front matter has specified the `resources` as: + +{{< code-toggle file=content/inspections/engine/index.md fm=true >}} +title = 'Engine inspections' +[[resources]] + src = "*specs.pdf" + title = "Specification #:counter" +[[resources]] + src = "**.pdf" + name = "pdf-file-:counter" +{{</ code-toggle >}} + +the `Name` and `Title` will be assigned to the resource files as follows: + +| Resource file | `Name` | `Title` | +|-------------------|-------------------|-----------------------| +| checklist.pdf | `"pdf-file-1.pdf` | `"checklist.pdf"` | +| guide.pdf | `"pdf-file-2.pdf` | `"guide.pdf"` | +| other\_specs.pdf | `"pdf-file-3.pdf` | `"Specification #1"` | +| photo\_specs.pdf | `"pdf-file-4.pdf` | `"Specification #2"` | diff --git a/docs/content/en/content-management/related.md b/docs/content/en/content-management/related.md new file mode 100644 index 000000000..e73dfc32a --- /dev/null +++ b/docs/content/en/content-management/related.md @@ -0,0 +1,178 @@ +--- +title: Related content +description: List related content in "See Also" sections. +categories: [content management] +keywords: [content] +menu: + docs: + parent: content-management + weight: 110 +weight: 110 +toc: true +aliases: [/content/related/,/related/] +--- + +Hugo uses a set of factors to identify a page's related content based on front matter parameters. This can be tuned to the desired set of indices and parameters or left to Hugo's default [Related Content configuration](#configure-related-content). + +## List related content + +To list up to 5 related pages (which share the same _date_ or _keyword_ parameters) is as simple as including something similar to this partial in your single page template: + +{{< code file=layouts/partials/related.html >}} +{{ $related := .Site.RegularPages.Related . | first 5 }} +{{ with $related }} +<h3>See Also</h3> +<ul> + {{ range . }} + <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li> + {{ end }} +</ul> +{{ end }} +{{< /code >}} + +The `Related` method takes one argument which may be a `Page` or a options map. The options map have these options: + +indices +: (`slice`) The indices to search within. + +document +: (`page`) The page for which to find related content. Required when specifying an options map. + +namedSlices +: (`slice`) The keywords to search for, expressed as a slice of `KeyValues` using the [`keyVals`] function. + +fragments +: (`slice`) A list of special keywords that is used for indices configured as type "fragments". This will match the [fragment] identifiers of the documents. + +[fragment]: /getting-started/glossary/#fragment +[`keyVals`]: /functions/collections/keyvals/ + +A fictional example using all of the above options: + +```go-html-template +{{ $page := . }} +{{ $opts := dict + "indices" (slice "tags" "keywords") + "document" $page + "namedSlices" (slice (keyVals "tags" "hugo" "rocks") (keyVals "date" $page.Date)) + "fragments" (slice "heading-1" "heading-2") +}} +``` + +{{% note %}} +We improved and simplified this feature in Hugo 0.111.0. Before this we had 3 different methods: `Related`, `RelatedTo` and `RelatedIndices`. Now we have only one method: `Related`. The old methods are still available but deprecated. Also see [this blog article](https://regisphilibert.com/blog/2018/04/hugo-optmized-relashionships-with-related-content/) for a great explanation of more advanced usage of this feature. +{{% /note %}} + +## Index content headings in related content + +{{< new-in 0.111.0 >}} + +Hugo can index the headings in your content and use this to find related content. You can enable this by adding a index of type `fragments` to your `related` configuration: + +{{< code-toggle file=hugo >}} +[related] +threshold = 20 +includeNewer = true +toLower = false +[[related.indices]] +name = "fragmentrefs" +type = "fragments" +applyFilter = true +weight = 80 +{{< /code-toggle >}} + +* The `name` maps to a optional front matter slice attribute that can be used to link from the page level down to the fragment/heading level. +* If `applyFilter`is enabled, the `.HeadingsFiltered` on each page in the result will reflect the filtered headings. This is useful if you want to show the headings in the related content listing: + +```go-html-template +{{ $related := .Site.RegularPages.Related . | first 5 }} +{{ with $related }} + <h2>See Also</h2> + <ul> + {{ range $i, $p := . }} + <li> + <a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a> + {{ with .HeadingsFiltered }} + <ul> + {{ range . }} + {{ $link := printf "%s#%s" $p.RelPermalink .ID | safeURL }} + <li> + <a href="{{ $link }}">{{ .Title }}</a> + </li> + {{ end }} + </ul> + {{ end }} + </li> + {{ end }} + </ul> +{{ end }} +``` + +## Configure related content + +Hugo provides a sensible default configuration of Related Content, but you can fine-tune this in your configuration, on the global or language level if needed. + +### Default configuration + +Without any `related` configuration set on the project, Hugo's Related Content methods will use the following. + +{{< code-toggle config=related />}} + +Custom configuration should be set using the same syntax. + +{{% note %}} +If you add a `related` configuration section, you need to add a complete configuration. It is not possible to just set, say, `includeNewer` and use the rest from the Hugo defaults. +{{% /note %}} + +### Top level configuration options + +threshold +: (`int`) A value between 0-100. Lower value will give more, but maybe not so relevant, matches. + +includeNewer +: (`bool`) Set to `true` to include **pages newer than the current page** in the related content listing. This will mean that the output for older posts may change as new related content gets added. + +toLower +: (`bool`) Set to `true` to lower case keywords in both the indexes and the queries. This may give more accurate results at a slight performance penalty. Note that this can also be set per index. + +### Configuration options per index + +name +: (`string`) The index name. This value maps directly to a page parameter. Hugo supports string values (`author` in the example) and lists (`tags`, `keywords` etc.) and time and date objects. + +type {{< new-in 0.111.0 >}} +: (`string`) One of `basic`(default) or `fragments`. + +applyFilter {{< new-in 0.111.0 >}} +: (`string`) Apply a `type` specific filter to the result of a search. This is currently only used for the `fragments` type. + +weight +: (`int`) An integer weight that indicates _how important_ this parameter is relative to the other parameters. It can be `0`, which has the effect of turning this index off, or even negative. Test with different values to see what fits your content best. + +cardinalityThreshold {{< new-in 0.111.0 >}} +: (`int`) A percentage (0-100) used to remove common keywords from the index. As an example, setting this to `50` will remove all keywords that are used in more than 50% of the documents in the index. Default is `0`. + +pattern +: (`string`) This is currently only relevant for dates. When listing related content, we may want to list content that is also close in time. Setting "2006" (default value for date indexes) as the pattern for a date index will add weight to pages published in the same year. For busier blogs, "200601" (year and month) may be a better default. + +toLower +: (`bool`) See above. + +## Performance considerations + +**Fast is Hugo's middle name** and we would not have released this feature had it not been blistering fast. + +This feature has been in the back log and requested by many for a long time. The development got this recent kick start from this Twitter thread: + +{{< tweet user="scott_lowe" id="898398437527363585" >}} + +Scott S. Lowe removed the "Related Content" section built using the `intersect` template function on tags, and the build time dropped from 30 seconds to less than 2 seconds on his 1700 content page sized blog. + +He should now be able to add an improved version of that "Related Content" section without giving up the fast live-reloads. But it's worth noting that: + +* If you don't use any of the `Related` methods, you will not use the Relate Content feature, and performance will be the same as before. +* Calling `.RegularPages.Related` etc. will create one inverted index, also sometimes named posting list, that will be reused for any lookups in that same page collection. Doing that in addition to, as an example, calling `.Pages.Related` will work as expected, but will create one additional inverted index. This should still be very fast, but worth having in mind, especially for bigger sites. + +{{% note %}} +We currently do not index **Page content**. We thought we would release something that will make most people happy before we start solving [Sherlock's last case](https://github.com/joearms/sherlock). +{{% /note %}} diff --git a/docs/content/en/content-management/sections.md b/docs/content/en/content-management/sections.md new file mode 100644 index 000000000..1b694ce44 --- /dev/null +++ b/docs/content/en/content-management/sections.md @@ -0,0 +1,161 @@ +--- +title: Sections +description: Organize content into sections. + +categories: [content management] +keywords: [lists,sections,content types,organization] +menu: + docs: + parent: content-management + weight: 120 +weight: 120 +toc: true +aliases: [/content/sections/] +--- + +## Overview + +A section is a top-level content directory, or any content directory with an _index.md file. A content directory with an _index.md file is also known as a [branch bundle](/getting-started/glossary/#branch-bundle). Section templates receive one or more page [collections](/getting-started/glossary/#collection) in [context](/getting-started/glossary/#context). + +{{% note %}} +Although top-level directories without _index.md files are sections, we recommend creating _index.md files in _all_ sections. +{{% /note %}} + +A typical site consists of one or more sections. For example: + +```text +content/ +├── articles/ <-- section (top-level directory) +│ ├── 2022/ +│ │ ├── article-1/ +│ │ │ ├── cover.jpg +│ │ │ └── index.md +│ │ └── article-2.md +│ └── 2023/ +│ ├── article-3.md +│ └── article-4.md +├── products/ <-- section (top-level directory) +│ ├── product-1/ <-- section (has _index.md file) +│ │ ├── benefits/ <-- section (has _index.md file) +│ │ │ ├── _index.md +│ │ │ ├── benefit-1.md +│ │ │ └── benefit-2.md +│ │ ├── features/ <-- section (has _index.md file) +│ │ │ ├── _index.md +│ │ │ ├── feature-1.md +│ │ │ └── feature-2.md +│ │ └── _index.md +│ └── product-2/ <-- section (has _index.md file) +│ ├── benefits/ <-- section (has _index.md file) +│ │ ├── _index.md +│ │ ├── benefit-1.md +│ │ └── benefit-2.md +│ ├── features/ <-- section (has _index.md file) +│ │ ├── _index.md +│ │ ├── feature-1.md +│ │ └── feature-2.md +│ └── _index.md +├── _index.md +└── about.md +``` + +The example above has two top-level sections: articles and products. None of the directories under articles are sections, while all of the directories under products are sections. A section within a section is a known as a nested section or subsection. + +## Explanation + +Sections and non-sections behave differently. + +||Sections|Non-sections +:--|:-:|:-: +Directory names become URL segments|:heavy_check_mark:|:heavy_check_mark: +Have logical ancestors and descendants|:heavy_check_mark:|:x: +Have list pages|:heavy_check_mark:|:x: + +With the file structure from the [example above](#overview): + +1. The list page for the articles section includes all articles, regardless of directory structure; none of the subdirectories are sections. + +1. The articles/2022 and articles/2023 directories do not have list pages; they are not sections. + +1. The list page for the products section, by default, includes product-1 and product-2, but not their descendant pages. To include descendant pages, use the `.RegularPagesRecursive` collection instead of the `.Pages` collection in the list template. See [details](/variables/page/#page-collections). + +1. All directories in the products section have list pages; each directory is a section. + +## Template selection + +Hugo has a defined [lookup order] to determine which template to use when rendering a page. The [lookup rules] consider the top-level section name; subsection names are not considered when selecting a template. + +With the file structure from the [example above](#overview): + +Content directory|List page template +:--|:-- +content/products|layouts/products/list.html +content/products/product-1|layouts/products/list.html +content/products/product-1/benefits|layouts/products/list.html + +Content directory|Single page template +:--|:-- +content/products|layouts/products/single.html +content/products/product-1|layouts/products/single.html +content/products/product-1/benefits|layouts/products/single.html + +If you need to use a different template for a subsection, specify `type` and/or `layout` in front matter. + +[lookup rules]: /templates/lookup-order/#lookup-rules +[lookup order]: /templates/lookup-order/ + +## Ancestors and descendants + +A section has one or more ancestors (including the home page), and zero or more descendants. With the file structure from the [example above](#overview): + +```text +content/products/product-1/benefits/benefit-1.md +``` + +The content file (benefit-1.md) has four ancestors: benefits, product-1, products, and the home page. This logical relationship allows us to use the `.Parent` and `.Ancestors` methods to traverse the site structure. + +For example, use the `.Ancestors` method to render breadcrumb navigation. + +{{< code file=layouts/partials/breadcrumb.html >}} +<nav aria-label="breadcrumb" class="breadcrumb"> + <ol> + {{ range .Ancestors.Reverse }} + <li> + <a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a> + </li> + {{ end }} + <li class="active"> + <a aria-current="page" href="{{ .RelPermalink }}">{{ .LinkTitle }}</a> + </li> + </ol> +</nav> +{{< /code >}} + +With this CSS: + +```css +.breadcrumb ol { + padding-left: 0; +} + +.breadcrumb li { + display: inline; +} + +.breadcrumb li:not(:last-child)::after { + content: "»"; +} +``` + +Hugo renders this, where each breadcrumb is a link to the corresponding page: + +```text +Home » Products » Product 1 » Benefits » Benefit 1 +``` + +[archetype]: /content-management/archetypes/ +[content type]: /content-management/types/ +[directory structure]: /getting-started/directory-structure/ +[section templates]: /templates/section-templates/ +[leaf bundles]: /content-management/page-bundles/#leaf-bundles +[branch bundles]: /content-management/page-bundles/#branch-bundles diff --git a/docs/content/en/content-management/shortcodes.md b/docs/content/en/content-management/shortcodes.md new file mode 100644 index 000000000..bbc2b0cc8 --- /dev/null +++ b/docs/content/en/content-management/shortcodes.md @@ -0,0 +1,404 @@ +--- +title: Shortcodes +description: Shortcodes are simple snippets inside your content files calling built-in or custom templates. +categories: [content management] +keywords: [markdown,content,shortcodes] +menu: + docs: + parent: content-management + weight: 100 +weight: 100 +toc: true +aliases: [/extras/shortcodes/] +testparam: "Hugo Rocks!" +--- + +## What a shortcode is + +Hugo loves Markdown because of its simple content format, but there are times when Markdown falls short. Often, content authors are forced to add raw HTML (e.g., video `<iframe>`'s) to Markdown content. We think this contradicts the beautiful simplicity of Markdown's syntax. + +Hugo created **shortcodes** to circumvent these limitations. + +A shortcode is a simple snippet inside a content file that Hugo will render using a predefined template. Note that shortcodes will not work in template files. If you need the type of drop-in functionality that shortcodes provide but in a template, you most likely want a [partial template][partials] instead. + +In addition to cleaner Markdown, shortcodes can be updated any time to reflect new classes, techniques, or standards. At the point of site generation, Hugo shortcodes will easily merge in your changes. You avoid a possibly complicated search and replace operation. + +## Use shortcodes + +{{< youtube 2xkNJL4gJ9E >}} + +In your content files, a shortcode can be called by calling `{{%/* shortcodename parameters */%}}`. Shortcode parameters are space delimited, and parameters with internal spaces can be quoted. + +The first word in the shortcode declaration is always the name of the shortcode. Parameters follow the name. Depending upon how the shortcode is defined, the parameters may be named, positional, or both, although you can't mix parameter types in a single call. The format for named parameters models that of HTML with the format `name="value"`. + +Some shortcodes use or require closing shortcodes. Again like HTML, the opening and closing shortcodes match (name only) with the closing declaration, which is prepended with a slash. + +Here are two examples of paired shortcodes: + +```go-html-template +{{%/* mdshortcode */%}}Stuff to `process` in the *center*.{{%/* /mdshortcode */%}} +``` + +```go-html-template +{{</* highlight go */>}} A bunch of code here {{</* /highlight */>}} +``` + +The examples above use two different delimiters, the difference being the `%` character in the first and the `<>` characters in the second. + +### Shortcodes with raw string parameters + +You can pass multiple lines as parameters to a shortcode by using raw string literals: + +```go-html-template +{{</* myshortcode `This is some <b>HTML</b>, +and a new line with a "quoted string".` */>}} +``` + +### Shortcodes with markdown + +Shortcodes using the `%` as the outer-most delimiter will be fully rendered when sent to the content renderer. This means that the rendered output from a shortcode can be part of the page's table of contents, footnotes, etc. + +### Shortcodes without markdown + +The `<` character indicates that the shortcode's inner content does *not* need further rendering. Often shortcodes without Markdown include internal HTML: + +```go-html-template +{{</* myshortcode */>}}<p>Hello <strong>World!</strong></p>{{</* /myshortcode */>}} +``` + +### Nested shortcodes + +You can call shortcodes within other shortcodes by creating your own templates that leverage the `.Parent` variable. `.Parent` allows you to check the context in which the shortcode is being called. See [Shortcode templates][sctemps]. + +## Use Hugo's built-in shortcodes + +Hugo ships with a set of predefined shortcodes that represent very common usage. These shortcodes are provided for author convenience and to keep your Markdown content clean. + +### `figure` + +`figure` is an extension of the image syntax in Markdown, which does not provide a shorthand for the more semantic [HTML5 `<figure>` element][figureelement]. + +The `figure` shortcode can use the following named parameters: + +src +: URL of the image to be displayed. + +link +: If the image needs to be hyperlinked, URL of the destination. + +target +: Optional `target` attribute for the URL if `link` parameter is set. + +rel +: Optional `rel` attribute for the URL if `link` parameter is set. + +alt +: Alternate text for the image if the image cannot be displayed. + +title +: Image title. + +caption +: Image caption. Markdown within the value of `caption` will be rendered. + +class +: `class` attribute of the HTML `figure` tag. + +height +: `height` attribute of the image. + +width +: `width` attribute of the image. + +loading +: `loading` attribute of the image. + +attr +: Image attribution text. Markdown within the value of `attr` will be rendered. + +attrlink +: If the attribution text needs to be hyperlinked, URL of the destination. + +#### Example `figure` input + +{{< code file=figure-input-example.md >}} +{{</* figure src="elephant.jpg" title="An elephant at sunset" */>}} +{{< /code >}} + +#### Example `figure` output + +```html +<figure> + <img src="elephant.jpg"> + <figcaption><h4>An elephant at sunset</h4></figcaption> +</figure> +``` + +### `gist` + +To display a GitHub [gist] with this URL: + +[gist]: https://docs.github.com/en/get-started/writing-on-github/editing-and-sharing-content-with-gists + +```text +https://gist.github.com/user/50a7482715eac222e230d1e64dd9a89b +``` + +Include this in your markdown: + +```text +{{</* gist user 50a7482715eac222e230d1e64dd9a89b */>}} +``` + +This will display all files in the gist alphabetically by file name. + +{{< gist jmooring 23932424365401ffa5e9d9810102a477 >}} + +To display a specific file within the gist: + +```text +{{</* gist user 23932424365401ffa5e9d9810102a477 list.html */>}} +``` + +Rendered: + +{{< gist jmooring 23932424365401ffa5e9d9810102a477 list.html >}} + +### `highlight` + +To display a highlighted code sample: + +```text +{{</* highlight go-html-template */>}} +{{ range .Pages }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +{{</* /highlight */>}} +``` + +Rendered: + +{{< highlight go-html-template >}} +{{ range .Pages }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +{{< /highlight >}} + +To specify one or more [highlighting options], include a quotation-encapsulated, comma-separated list: + +[highlighting options]: /functions/transform/highlight/ + +```text +{{</* highlight go-html-template "lineNos=inline, lineNoStart=42" */>}} +{{ range .Pages }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +{{</* /highlight */>}} +``` + +Rendered: + +{{< highlight go-html-template "lineNos=inline, lineNoStart=42" >}} +{{ range .Pages }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +{{< /highlight >}} + +### `instagram` + +The `instagram` shortcode uses Facebook's **oEmbed Read** feature. The Facebook [developer documentation] states: + +- This permission or feature requires successful completion of the App Review process before your app can access live data. [Learn More] +- This permission or feature is only available with business verification. You may also need to sign additional contracts before your app can access data. [Learn More Here] + +[developer documentation]: https://developers.facebook.com/docs/features-reference/oembed-read +[Learn More]: https://developers.facebook.com/docs/app-review +[Learn More Here]: https://developers.facebook.com/docs/development/release/business-verification + +You must obtain an Access Token to use the `instagram` shortcode. + +If your site configuration is private: + +{{< code-toggle file=hugo >}} +[services.instagram] +accessToken = 'xxx' +{{< /code-toggle >}} + +If your site configuration is _not_ private, set the Access Token with an environment variable: + +```sh +HUGO_SERVICES_INSTAGRAM_ACCESSTOKEN=xxx hugo --gc --minify +``` + +{{% note %}} +If you are using a Client Access Token, you must combine the Access Token with your App ID using a pipe symbol (`APPID|ACCESSTOKEN`). +{{% /note %}} + +To display an Instagram post with this URL: + +```text +https://www.instagram.com/p/BWNjjyYFxVx/ +``` + +Include this in your markdown: + +```text +{{</* instagram BWNjjyYFxVx */>}} +``` + +### `param` + +Gets a value from the current `Page's` parameters set in front matter, with a fallback to the site parameter value. It will log an `ERROR` if the parameter with the given key could not be found in either. + +```sh +{{</* param testparam */>}} +``` + +Since `testparam` is a parameter defined in front matter of this page with the value `Hugo Rocks!`, the above will print: + +{{< param testparam >}} + +To access deeply nested parameters, use "dot syntax", e.g: + +```sh +{{</* param "my.nested.param" */>}} +``` + +### `ref` and `relref` + +These shortcodes will look up the pages by their relative path (e.g., `blog/post.md`) or their logical name (`post.md`) and return the permalink (`ref`) or relative permalink (`relref`) for the found page. + +`ref` and `relref` also make it possible to make fragmentary links that work for the header links generated by Hugo. + +{{% note %}} +Read a more extensive description of `ref` and `relref` in the [cross references](/content-management/cross-references/) documentation. +{{% /note %}} + +`ref` and `relref` take exactly one required parameter of _reference_, quoted and in position `0`. + +#### Example `ref` and `relref` input + +```go-html-template +[Neat]({{</* ref "blog/neat.md" */>}}) +[Who]({{</* relref "about.md#who" */>}}) +``` + +#### Example `ref` and `relref` output + +Assuming that standard Hugo pretty URLs are turned on. + +```html +<a href="https://example.org/blog/neat">Neat</a> +<a href="/about/#who">Who</a> +``` + +### `tweet` + +To display a Twitter post with this URL: + +```txt +https://twitter.com/SanDiegoZoo/status/1453110110599868418 +``` + +Include this in your markdown: + +```text +{{</* tweet user="SanDiegoZoo" id="1453110110599868418" */>}} +``` + +Rendered: + +{{< tweet user="SanDiegoZoo" id="1453110110599868418" >}} + +### `vimeo` + +To display a Vimeo video with this URL: + +```text +https://vimeo.com/channels/staffpicks/55073825 +``` + +Include this in your markdown: + +```text +{{</* vimeo 55073825 */>}} +``` + +Rendered: + +{{< vimeo 55073825 >}} + +{{% note %}} +If you want to further customize the visual styling of the YouTube or Vimeo output, add a `class` named parameter when calling the shortcode. The new `class` will be added to the `<div>` that wraps the `<iframe>` *and* will remove the inline styles. Note that you will need to call the `id` as a named parameter as well. You can also give the vimeo video a descriptive title with `title`. + +```go +{{</* vimeo id="146022717" class="my-vimeo-wrapper-class" title="My vimeo video" */>}} +``` +{{% /note %}} + +### `youtube` + +The `youtube` shortcode embeds a responsive video player for [YouTube videos]. Only the ID of the video is required, e.g.: + +```txt +https://www.youtube.com/watch?v=w7Ft2ymGmfc +``` + +#### Example `youtube` input + +Copy the YouTube video ID that follows `v=` in the video's URL and pass it to the `youtube` shortcode: + +{{< code file=example-youtube-input.md >}} +{{</* youtube w7Ft2ymGmfc */>}} +{{< /code >}} + +Furthermore, you can automatically start playback of the embedded video by setting the `autoplay` parameter to `true`. Remember that you can't mix named and unnamed parameters, so you'll need to assign the yet unnamed video ID to the parameter `id`: + +{{< code file=example-youtube-input-with-autoplay.md >}} +{{</* youtube id="w7Ft2ymGmfc" autoplay="true" */>}} +{{< /code >}} + +For [accessibility reasons](https://dequeuniversity.com/tips/provide-iframe-titles), it's best to provide a title for your YouTube video. You can do this using the shortcode by providing a `title` parameter. If no title is provided, a default of "YouTube Video" will be used. + +{{< code file=example-youtube-input-with-title.md >}} +{{</* youtube id="w7Ft2ymGmfc" title="A New Hugo Site in Under Two Minutes" */>}} +{{< /code >}} + +#### Example `youtube` output + +Using the preceding `youtube` example, the following HTML will be added to your rendered website's markup: + +{{< code file=example-youtube-output.html >}} +{{< youtube id="w7Ft2ymGmfc" autoplay="true" >}} +{{< /code >}} + +#### Example `youtube` display + +Using the preceding `youtube` example (without `autoplay="true"`), the following simulates the displayed experience for visitors to your website. Naturally, the final display will be contingent on your style sheets and surrounding markup. The video is also include in the [Quick Start of the Hugo documentation][quickstart]. + +{{< youtube w7Ft2ymGmfc >}} + +## Privacy configuration + +To learn how to configure your Hugo site to meet the new EU privacy regulation, see [Hugo and the GDPR]. + +## Create custom shortcodes + +To learn more about creating custom shortcodes, see the [shortcode template documentation]. + +[`figure` shortcode]: #figure +[contentmanagementsection]: /content-management/formats/ +[examplegist]: https://gist.github.com/spf13/7896402 +[figureelement]: https://html5doctor.com/the-figure-figcaption-elements/ +[Hugo and the GDPR]: /about/hugo-and-gdpr/ +[Instagram]: https://www.instagram.com/ +[pagevariables]: /variables/page/ +[partials]: /templates/partials/ +[quickstart]: /getting-started/quick-start/ +[sctemps]: /templates/shortcode-templates/ +[scvars]: /variables/shortcode/ +[shortcode template documentation]: /templates/shortcode-templates/ +[templatessection]: /templates/ +[Vimeo]: https://vimeo.com/ +[YouTube Videos]: https://www.youtube.com/ +[YouTube Input shortcode]: #youtube diff --git a/docs/content/en/content-management/static-files.md b/docs/content/en/content-management/static-files.md new file mode 100644 index 000000000..c1197ede1 --- /dev/null +++ b/docs/content/en/content-management/static-files.md @@ -0,0 +1,68 @@ +--- +title: Static files +description: Files that get served **statically** (as-is, no modification) on the site root. +categories: [content management] +keywords: [source, directories] +menu: + docs: + parent: content-management + weight: 200 +weight: 200 +toc: true +aliases: [/static-files] +--- + +By default, the `static/` directory in the site project is used for +all **static files** (e.g. stylesheets, JavaScript, images). The static files are served on the site root path (eg. if you have the file `static/image.png` you can access it using `http://{server-url}/image.png`, to include it in a document you can use ` )`. + +Hugo can be configured to look into a different directory, or even +**multiple directories** for such static files by configuring the +`staticDir` parameter in the [site configuration]. All the files in all the +static directories will form a union filesystem. + +This union filesystem will be served from your site root. So a file +`<SITE PROJECT>/static/me.png` will be accessible as +`<MY_BASEURL>/me.png`. + +Here's an example of setting `staticDir` and `staticDir2` for a +multi-language site: + +{{< code-toggle file=hugo >}} +staticDir = ["static1", "static2"] + +[languages] +[languages.en] +staticDir2 = "static_en" +baseURL = "https://example.org/" +languageName = "English" +weight = 2 +title = "In English" +[languages.no] +staticDir = ["staticDir_override", "static_no"] +baseURL = "https://example.no" +languageName = "Norsk" +weight = 1 +title = "På norsk" +{{</ code-toggle >}} + +In the above, with no theme used: + +- The English site will get its static files as a union of "static1", + "static2" and "static_en". On file duplicates, the right-most + version will win. +- The Norwegian site will get its static files as a union of + "staticDir_override" and "static_no". + +Note 1 +: The **2** (can be a number between 0 and 10) in `staticDir2` is + added to tell Hugo that you want to **add** this directory to the + global set of static directories defined using `staticDir`. Using + `staticDir` on the language level would replace the global value (as + can be seen in the Norwegian site case). + +Note 2 +: The example above is a [multihost setup]. In a regular setup, all + the static directories will be available to all sites. + +[site configuration]: /getting-started/configuration/#all-configuration-settings +[multihost setup]: /content-management/multilingual/#configure-multilingual-multihost diff --git a/docs/content/en/content-management/summaries.md b/docs/content/en/content-management/summaries.md new file mode 100644 index 000000000..22ed3fc81 --- /dev/null +++ b/docs/content/en/content-management/summaries.md @@ -0,0 +1,110 @@ +--- +title: Content summaries +linkTitle: Summaries +description: Hugo generates summaries of your content. +categories: [content management] +keywords: [summaries,abstracts,read more] +menu: + docs: + parent: content-management + weight: 160 +weight: 160 +toc: true +aliases: [/content/summaries/,/content-management/content-summaries/] +--- + +<!--more--> + +With the use of the `.Summary` [page variable][pagevariables], Hugo generates summaries of content to use as a short version in summary views. + +## Summary splitting options + +* Automatic Summary Split +* Manual Summary Split +* Front Matter Summary + +It is natural to accompany the summary with links to the original content, and a common design pattern is to see this link in the form of a "Read More ..." button. See the `.RelPermalink`, `.Permalink`, and `.Truncated` [page variables][pagevariables]. + +### Automatic summary splitting + +By default, Hugo automatically takes the first 70 words of your content as its summary and stores it into the `.Summary` page variable for use in your templates. You may customize the summary length by setting `summaryLength` in your [site configuration](/getting-started/configuration/). + +{{% note %}} +You can customize how HTML tags in the summary are loaded using functions such as `plainify` and `safeHTML`. +{{% /note %}} + +{{% note %}} +The Hugo-defined summaries are set to use word count calculated by splitting the text by one or more consecutive whitespace characters. If you are creating content in a `CJK` language and want to use Hugo's automatic summary splitting, set `hasCJKLanguage` to `true` in your [site configuration](/getting-started/configuration/). +{{% /note %}} + +### Manual summary splitting + +Alternatively, you may add the `<!--more-->` summary divider where you want to split the article. + +For [Org mode content][org], use `# more` where you want to split the article. + +Content that comes before the summary divider will be used as that content's summary and stored in the `.Summary` page variable with all HTML formatting intact. + +{{% note %}} +The concept of a *summary divider* is not unique to Hugo. It is also called the "more tag" or "excerpt separator" in other literature. +{{% /note %}} + +Pros +: Freedom, precision, and improved rendering. All HTML tags and formatting are preserved. + +Cons +: Extra work for content authors, since they need to remember to type `<!--more-->` (or `# more` for [org content][org]) in each content file. This can be automated by adding the summary divider below the front matter of an [archetype](/content-management/archetypes/). + +{{% note %}} +Be careful to enter `<!--more-->` exactly; i.e., all lowercase and with no whitespace. +{{% /note %}} + +### Front matter summary + +You might want your summary to be something other than the text that starts the article. In this case you can provide a separate summary in the `summary` variable of the article front matter. + +Pros +: Complete freedom of text independent of the content of the article. Markup can be used within the summary. + +Cons +: Extra work for content authors as they need to write an entirely separate piece of text as the summary of the article. + +## Summary selection order + +Because there are multiple ways in which a summary can be specified it is useful to understand the order of selection Hugo follows when deciding on the text to be returned by `.Summary`. It is as follows: + +1. If there is a `<!--more-->` summary divider present in the article, the text up to the divider will be provided as per the manual summary split method +2. If there is a `summary` variable in the article front matter the value of the variable will be provided as per the front matter summary method +3. The text at the start of the article will be provided as per the automatic summary split method + +{{% note %}} +Hugo uses the _first_ of the above steps that returns text. So if, for example, your article has both `summary` variable in its front matter and a `<!--more-->` summary divider Hugo will use the manual summary split method. +{{% /note %}} + +## Example: first 10 articles with summaries + +You can show content summaries with the following code. You could use the following snippet, for example, in a [section template]. + +{{< code file=page-list-with-summaries.html >}} +{{ range first 10 .Pages }} + <article> + <!-- this <div> includes the title summary --> + <div> + <h2><a href="{{ .RelPermalink }}">{{ .Title }}</a></h2> + {{ .Summary }} + </div> + {{ if .Truncated }} + <!-- This <div> includes a read more link, but only if the summary is truncated... --> + <div> + <a href="{{ .RelPermalink }}">Read More…</a> + </div> + {{ end }} + </article> +{{ end }} +{{< /code >}} + +Note how the `.Truncated` boolean variable value may be used to hide the "Read More..." link when the content is not truncated; i.e., when the summary contains the entire article. + +[org]: /content-management/formats/ +[pagevariables]: /variables/page/ +[section template]: /templates/section-templates/ diff --git a/docs/content/en/content-management/syntax-highlighting.md b/docs/content/en/content-management/syntax-highlighting.md new file mode 100644 index 000000000..62071cd46 --- /dev/null +++ b/docs/content/en/content-management/syntax-highlighting.md @@ -0,0 +1,138 @@ +--- +title: Syntax highlighting +description: Hugo comes with really fast syntax highlighting from Chroma. +categories: [content management] +keywords: [highlighting,chroma,code blocks,syntax] +menu: + docs: + parent: content-management + weight: 240 +weight: 240 +toc: true +aliases: [/extras/highlighting/,/extras/highlight/,/tools/syntax-highlighting/] +--- + +Hugo uses [Chroma](https://github.com/alecthomas/chroma) as its code highlighter; it is built in Go and is really, really fast. + +## Configure syntax highlighter + +See [Configure Highlight](/getting-started/configuration-markup#highlight). + +## Generate syntax highlighter CSS + +If you run with `markup.highlight.noClasses=false` in your site configuration, you need a style sheet. + +You can generate one with Hugo: + +```sh +hugo gen chromastyles --style=monokai > syntax.css +``` + +Run `hugo gen chromastyles -h` for more options. See https://xyproto.github.io/splash/docs/ for a gallery of available styles. + +## Highlight shortcode + +Highlighting is carried out via the built-in [`highlight` shortcode](/content-management/shortcodes/#highlight). It takes exactly one required parameter for the programming language to be highlighted and requires a closing shortcode. + +Options: + +* `linenos`: configure line numbers. Valid values are `true`, `false`, `table`, or `inline`. `false` will turn off line numbers if it's configured to be on in site configuration. `table` will give copy-and-paste friendly code blocks. +* `hl_lines`: lists a set of line numbers or line number ranges to be highlighted. +* `linenostart=199`: starts the line number count from 199. +* `anchorlinenos`: Configure anchors on line numbers. Valid values are `true` or `false`; +* `lineanchors`: Configure a prefix for the anchors on line numbers. Will be suffixed with `-`, so linking to the line number 1 with the option `lineanchors=prefix` adds the anchor `prefix-1` to the page. +* `hl_inline` Highlight inside a `<code>` (inline HTML element) tag. Valid values are `true` or `false`. The `code` tag will get a class with name `code-inline`. {{< new-in 0.101.0 >}} + +### Example: highlight shortcode + +```go-html-template +{{</* highlight go "linenos=table,hl_lines=8 15-17,linenostart=199" */>}} +// ... code +{{</* / highlight */>}} +``` + +Gives this: + +{{< highlight go "linenos=table,hl_lines=8 15-17,linenostart=199" >}} +// GetTitleFunc returns a func that can be used to transform a string to +// title case. +// +// The supported styles are +// +// - "Go" (strings.Title) +// - "AP" (see https://www.apstylebook.com/) +// - "Chicago" (see https://www.chicagomanualofstyle.org/home.html) +// +// If an unknown or empty style is provided, AP style is what you get. +func GetTitleFunc(style string) func(s string) string { + switch strings.ToLower(style) { + case "go": + return strings.Title + case "chicago": + return transform.NewTitleConverter(transform.ChicagoStyle) + default: + return transform.NewTitleConverter(transform.APStyle) + } +} +{{< / highlight >}} + +## Highlight Hugo/Go template code + +For highlighting Hugo/Go template code on your page, add `/*` after the opening double curly braces and `*/` before closing curly braces. + +``` go +{{</*/* myshortcode */*/>}} +``` + +Gives this: + +``` go +{{</* myshortcode */>}} +``` + +## Highlight template function + +See [Highlight](/functions/transform/highlight/). + +## Highlighting in code fences + +Highlighting in code fences is enabled by default. + +````txt +```go {linenos=table,hl_lines=[8,"15-17"],linenostart=199} +// ... code +``` +```` + +Gives this: + +```go {linenos=table,hl_lines=[8,"15-17"],linenostart=199} +// GetTitleFunc returns a func that can be used to transform a string to +// title case. +// +// The supported styles are +// +// - "Go" (strings.Title) +// - "AP" (see https://www.apstylebook.com/) +// - "Chicago" (see https://www.chicagomanualofstyle.org/home.html) +// +// If an unknown or empty style is provided, AP style is what you get. +func GetTitleFunc(style string) func(s string) string { + switch strings.ToLower(style) { + case "go": + return strings.Title + case "chicago": + return transform.NewTitleConverter(transform.ChicagoStyle) + default: + return transform.NewTitleConverter(transform.APStyle) + } +} +``` + +The options are the same as in the [highlighting shortcode](/content-management/syntax-highlighting/#highlight-shortcode), including `linenos=false`, but note the slightly different Markdown attribute syntax. + +## List of Chroma highlighting languages + +The full list of Chroma lexers and their aliases (which is the identifier used in the `highlight` template func or when doing highlighting in code fences): + +{{< chroma-lexers >}} diff --git a/docs/content/en/content-management/taxonomies.md b/docs/content/en/content-management/taxonomies.md new file mode 100644 index 000000000..94f2f6357 --- /dev/null +++ b/docs/content/en/content-management/taxonomies.md @@ -0,0 +1,188 @@ +--- +title: Taxonomies +description: Hugo includes support for user-defined taxonomies. +categories: [content management] +keywords: [taxonomies,metadata,front matter,terms] +menu: + docs: + parent: content-management + weight: 150 +weight: 150 +toc: true +aliases: [/taxonomies/overview/,/taxonomies/usage/,/indexes/overview/,/doc/indexes/,/extras/indexes] +--- + +## What is a taxonomy? + +Hugo includes support for user-defined groupings of content called **taxonomies**. Taxonomies are classifications of logical relationships between content. + +### Definitions + +Taxonomy +: a categorization that can be used to classify content + +Term +: a key within the taxonomy + +Value +: a piece of content assigned to a term + +## Example taxonomy: movie website + +Let's assume you are making a website about movies. You may want to include the following taxonomies: + +* Actors +* Directors +* Studios +* Genre +* Year +* Awards + +Then, in each of the movies, you would specify terms for each of these taxonomies (i.e., in the [front matter] of each of your movie content files). From these terms, Hugo would automatically create pages for each Actor, Director, Studio, Genre, Year, and Award, with each listing all of the Movies that matched that specific Actor, Director, Studio, Genre, Year, and Award. + +### Movie taxonomy organization + +To continue with the example of a movie site, the following demonstrates content relationships from the perspective of the taxonomy: + +```txt +Actor <- Taxonomy + Bruce Willis <- Term + The Sixth Sense <- Value + Unbreakable <- Value + Moonrise Kingdom <- Value + Samuel L. Jackson <- Term + Unbreakable <- Value + The Avengers <- Value + xXx <- Value +``` + +From the perspective of the content, the relationships would appear differently, although the data and labels used are the same: + +```txt +Unbreakable <- Value + Actors <- Taxonomy + Bruce Willis <- Term + Samuel L. Jackson <- Term + Director <- Taxonomy + M. Night Shyamalan <- Term + ... +Moonrise Kingdom <- Value + Actors <- Taxonomy + Bruce Willis <- Term + Bill Murray <- Term + Director <- Taxonomy + Wes Anderson <- Term + ... +``` + +## Default taxonomies + +Hugo natively supports taxonomies. + +Without adding a single line to your [site configuration] file, Hugo will automatically create taxonomies for `tags` and `categories`. That would be the same as manually [configuring your taxonomies](#configure-taxonomies) as below: + +{{< code-toggle config=taxonomies />}} + +If you do not want Hugo to create any taxonomies, set `disableKinds` in your [site configuration] to the following: + +{{< code-toggle file=hugo >}} +disableKinds = ["taxonomy","term"] +{{</ code-toggle >}} + +{{% include "content-management/_common/page-kinds.md" %}} + +### Default destinations + +When taxonomies are used---and [taxonomy templates] are provided---Hugo will automatically create both a page listing all the taxonomy's terms and individual pages with lists of content associated with each term. For example, a `categories` taxonomy declared in your configuration and used in your content front matter will create the following pages: + +* A single page at `example.com/categories/` that lists all the [terms within the taxonomy] +* [Individual taxonomy list pages][taxonomy templates] (e.g., `/categories/development/`) for each of the terms that shows a listing of all pages marked as part of that taxonomy within any content file's [front matter] + +## Configure taxonomies + +Custom taxonomies other than the [defaults](#default-taxonomies) must be defined in your [site configuration] before they can be used throughout the site. You need to provide both the plural and singular labels for each taxonomy. For example, `singular key = "plural value"` for TOML and `singular key: "plural value"` for YAML. + +### Example: adding a custom taxonomy named "series" + +{{% note %}} +While adding custom taxonomies, you need to put in the default taxonomies too, _if you want to keep them_. +{{% /note %}} + +{{< code-toggle file=hugo >}} +[taxonomies] + tag = "tags" + category = "categories" + series = "series" +{{</ code-toggle >}} + +### Example: removing default taxonomies + +If you want to have just the default `tags` taxonomy, and remove the `categories` taxonomy for your site, you can do so by modifying the `taxonomies` value in your [site configuration]. + +{{< code-toggle file=hugo >}} +[taxonomies] + tag = "tags" +{{</ code-toggle >}} + +If you want to disable all taxonomies altogether, see the use of `disableKinds` in [Hugo Taxonomy Defaults](#default-taxonomies). + +{{% note %}} +You can add content and front matter to your taxonomy list and taxonomy terms pages. See [Content Organization](/content-management/organization/) for more information on how to add an `_index.md` for this purpose. +{{% /note %}} + +## Add taxonomies to content + +Once a taxonomy is defined at the site level, any piece of content can be assigned to it, regardless of [content type] or [content section]. + +Assigning content to a taxonomy is done in the [front matter]. Simply create a variable with the *plural* name of the taxonomy and assign all terms you want to apply to the instance of the content type. + +{{% note %}} +If you would like the ability to quickly generate content files with preconfigured taxonomies or terms, read the docs on [Hugo archetypes](/content-management/archetypes/). +{{% /note %}} + +### Example: front matter with taxonomies + +{{< code-toggle file=content/example.md fm=true >}} +title = "Hugo: A fast and flexible static site generator" +tags = [ "Development", "Go", "fast", "Blogging" ] +categories = [ "Development" ] +series = [ "Go Web Dev" ] +slug = "hugo" +project_url = "https://github.com/gohugoio/hugo" +{{</ code-toggle >}} + +## Order taxonomies + +A content file can assign weight for each of its associate taxonomies. Taxonomic weight can be used for sorting or ordering content in [taxonomy list templates] and is declared in a content file's [front matter]. The convention for declaring taxonomic weight is `taxonomyname_weight`. + +The following show a piece of content that has a weight of 22, which can be used for ordering purposes when rendering the pages assigned to the "a", "b" and "c" values of the `tags` taxonomy. It has also been assigned the weight of 44 when rendering the "d" category page. + +### Example: taxonomic `weight` + +{{< code-toggle >}} +title = "foo" +tags = [ "a", "b", "c" ] +tags_weight = 22 +categories = ["d"] +categories_weight = 44 +{{</ code-toggle >}} + +By using taxonomic weight, the same piece of content can appear in different positions in different taxonomies. + +## Add custom metadata to a taxonomy or term + +If you need to add custom metadata to your taxonomy terms, you will need to create a page for that term at `/content/<TAXONOMY>/<TERM>/_index.md` and add your metadata in its front matter. Continuing with our 'Actors' example, let's say you want to add a Wikipedia page link to each actor. Your terms pages would be something like this: + +{{< code-toggle file=content/actors/bruce-willis/_index.md fm=true >}} +title: "Bruce Willis" +wikipedia: "https://en.wikipedia.org/wiki/Bruce_Willis" +{{< /code-toggle >}} + +[content section]: /content-management/sections/ +[content type]: /content-management/types/ +[documentation on archetypes]: /content-management/archetypes/ +[front matter]: /content-management/front-matter/ +[taxonomy list templates]: /templates/taxonomy-templates/#taxonomy-list-templates +[taxonomy templates]: /templates/taxonomy-templates/ +[terms within the taxonomy]: /templates/taxonomy-templates/#taxonomy-terms-templates +[site configuration]: /getting-started/configuration/ diff --git a/docs/content/en/content-management/toc.md b/docs/content/en/content-management/toc.md new file mode 100644 index 000000000..69021ac45 --- /dev/null +++ b/docs/content/en/content-management/toc.md @@ -0,0 +1,117 @@ +--- +title: Table of contents +description: Hugo can automatically parse Markdown content and create a Table of Contents you can use in your templates. +categories: [content management] +keywords: [table of contents, toc] +menu: + docs: + parent: content-management + weight: 210 +weight: 210 +toc: true +aliases: [/extras/toc/] +--- + +{{% note %}} + +Previously, there was no out-of-the-box way to specify which heading levels you want the TOC to render. [See the related GitHub discussion (#1778)](https://github.com/gohugoio/hugo/issues/1778). As such, the resulting `<nav id="TableOfContents"><ul></ul></nav>` was going to start at `<h1>` when pulling from `{{ .Content }}`. + +Hugo [v0.60.0](https://github.com/gohugoio/hugo/releases/tag/v0.60.0) made a switch to [Goldmark](https://github.com/yuin/goldmark/) as the default library for Markdown which has improved and configurable implementation of TOC. Take a look at [how to configure TOC](/getting-started/configuration-markup/#table-of-contents) for Goldmark renderer. + +{{% /note %}} + +## Usage + +Create your Markdown the way you normally would with the appropriate headings. Here is some example content: + +```md +<!-- Your front matter up here --> + +## Introduction + +One morning, when Gregor Samsa woke from troubled dreams, he found himself transformed in his bed into a horrible vermin. + +## My Heading + +He lay on his armour-like back, and if he lifted his head a little he could see his brown belly, slightly domed and divided by arches into stiff sections. The bedding was hardly able to cover it and seemed ready to slide off any moment. + +### My Subheading + +A collection of textile samples lay spread out on the table - Samsa was a traveling salesman - and above it there hung a picture that he had recently cut out of an illustrated magazine and housed in a nice, gilded frame. It showed a lady fitted out with a fur hat and fur boa who sat upright, raising a heavy fur muff that covered the whole of her lower arm towards the viewer. Gregor then turned to look out the window at the dull weather. Drops +``` + +Hugo will take this Markdown and create a table of contents from `## Introduction`, `## My Heading`, and `### My Subheading` and then store it in the [page variable][pagevars]`.TableOfContents`. + +The built-in `.TableOfContents` variables outputs a `<nav id="TableOfContents">` element with a child `<ul>`, whose child `<li>` elements begin with appropriate HTML headings. See [the available settings](/getting-started/configuration-markup/#table-of-contents) to configure what heading levels you want to include in TOC. + +## Template example: basic TOC + +The following is an example of a very basic [single page template]: + +{{< code file=layout/_default/single.html >}} +{{ define "main" }} + <main> + <article> + <header> + <h1>{{ .Title }}</h1> + </header> + {{ .Content }} + </article> + <aside> + {{ .TableOfContents }} + </aside> + </main> +{{ end }} +{{< /code >}} + +## Template example: TOC partial + +The following is a [partial template][partials] that adds slightly more logic for page-level control over your table of contents. It assumes you are using a `toc` field in your content's [front matter] that, unless specifically set to `false`, will add a TOC to any page with a `.WordCount` (see [Page Variables][pagevars]) greater than 400. This example also demonstrates how to use [conditionals] in your templating: + +{{< code file=layouts/partials/toc.html >}} +{{ if and (gt .WordCount 400 ) (.Params.toc) }} +<aside> + <header> + <h2>{{ .Title }}</h2> + </header> + {{ .TableOfContents }} +</aside> +{{ end }} +{{< /code >}} + +{{% note %}} +With the preceding example, even pages with > 400 words *and* `toc` not set to `false` will not render a table of contents if there are no headings in the page for the `{{ .TableOfContents }}` variable to pull from. +{{% /note %}} + +## Usage with AsciiDoc + +Hugo supports table of contents with AsciiDoc content format. + +In the header of your content file, specify the AsciiDoc TOC directives necessary to ensure that the table of contents is generated. Hugo will use the generated TOC to populate the page variable `.TableOfContents` in the same way as described for Markdown. See example below: + +```asciidoc +// <!-- Your front matter up here --> +:toc: +// Set toclevels to be at least your hugo [markup.tableOfContents.endLevel] configuration key +:toclevels: 4 + +== Introduction + +One morning, when Gregor Samsa woke from troubled dreams, he found himself transformed in his bed into a horrible vermin. + +== My Heading + +He lay on his armour-like back, and if he lifted his head a little he could see his brown belly, slightly domed and divided by arches into stiff sections. The bedding was hardly able to cover it and seemed ready to slide off any moment. + +=== My Subheading + +A collection of textile samples lay spread out on the table - Samsa was a traveling salesman - and above it there hung a picture that he had recently cut out of an illustrated magazine and housed in a nice, gilded frame. It showed a lady fitted out with a fur hat and fur boa who sat upright, raising a heavy fur muff that covered the whole of her lower arm towards the viewer. Gregor then turned to look out the window at the dull weather. Drops +``` + +Hugo will take this AsciiDoc and create a table of contents store it in the page variable `.TableOfContents`, in the same as described for Markdown. + +[conditionals]: /templates/introduction/#conditionals +[front matter]: /content-management/front-matter/ +[pagevars]: /variables/page/ +[partials]: /templates/partials/ +[single page template]: /templates/single-page-templates/ diff --git a/docs/content/en/content-management/types.md b/docs/content/en/content-management/types.md new file mode 100644 index 000000000..67dbe1596 --- /dev/null +++ b/docs/content/en/content-management/types.md @@ -0,0 +1,20 @@ +--- +title: Content types +description: Hugo is built around content organized in sections. +categories: [content management] +keywords: [lists,sections,content types,types,organization] +menu: + docs: + parent: content-management + weight: 130 +weight: 130 +toc: true +aliases: [/content/types] +--- + +A **content type** is a way to organize your content. Hugo resolves the content type from either the `type` in front matter or, if not set, the first directory in the file path. E.g. `content/blog/my-first-event.md` will be of type `blog` if no `type` is set. + +A content type is used to + +- Determine how the content is rendered. See [Template Lookup Order](/templates/lookup-order/) and [Content Views](/templates/views) for more. +- Determine which [archetype](/content-management/archetypes/) template to use for new content. diff --git a/docs/content/en/content-management/urls.md b/docs/content/en/content-management/urls.md new file mode 100644 index 000000000..a91fe21c0 --- /dev/null +++ b/docs/content/en/content-management/urls.md @@ -0,0 +1,432 @@ +--- +title: URL management +description: Control the structure and appearance of URLs through front matter entries and settings in your site configuration. +categories: [content management] +keywords: [aliases,redirects,permalinks,urls] +menu: + docs: + parent: content-management + weight: 180 +weight: 180 +toc: true +aliases: [/extras/permalinks/,/extras/aliases/,/extras/urls/,/doc/redirects/,/doc/alias/,/doc/aliases/] +--- + +## Overview + +By default, when Hugo renders a page, the resulting URL matches the file path within the `content` directory. For example: + +```text +content/posts/post-1.md → https://example.org/posts/post-1/ +``` + +You can change the structure and appearance of URLs with front matter values and site configuration options. + +## Front matter + +### `slug` + +Set the `slug` in front matter to override the last segment of the path. The `slug` value does not affect section pages. + +{{< code-toggle file=content/posts/post-1.md fm=true >}} +title = 'My First Post' +slug = 'my-first-post' +{{< /code-toggle >}} + +The resulting URL will be: + +```text +https://example.org/posts/my-first-post/ +``` + +### `url` + +Set the `url` in front matter to override the entire path. Use this with either regular pages or section pages. + +With this front matter: + +{{< code-toggle file=content/posts/post-1.md fm=true >}} +title = 'My First Article' +url = '/articles/my-first-article' +{{< /code-toggle >}} + +The resulting URL will be: + +```text +https://example.org/articles/my-first-article/ +``` + +If you include a file extension: + +{{< code-toggle file=content/posts/post-1.md fm=true >}} +title = 'My First Article' +url = '/articles/my-first-article.html' +{{< /code-toggle >}} + +The resulting URL will be: + +```text +https://example.org/articles/my-first-article.html +``` + +In a monolingual site, a `url` value with or without a leading slash is relative to the `baseURL`. + +In a multilingual site: + +- A `url` value with a leading slash is relative to the `baseURL`. +- A `url` value without a leading slash is relative to the `baseURL` plus the language prefix. + +Site type|Front matter `url`|Resulting URL +:--|:--|:-- +monolingual|`/about`|`https://example.org/about/` +monolingual|`about`|`https://example.org/about/` +multilingual|`/about`|`https://example.org/about/` +multilingual|`about`|`https://example.org/de/about/` + +If you set both `slug` and `url` in front matter, the `url` value takes precedence. + +## Site configuration + +### Permalinks + +In your site configuration, define a URL pattern for each top-level section. Each URL pattern can target a given language and/or [page kind]. + +Front matter `url` values override the URL patterns defined in the `permalinks` section of your site configuration. + +[page kind]: /templates/section-templates/#page-kinds + +#### Monolingual examples {#permalinks-monolingual-examples} + +With this content structure: + +```text +content/ +├── posts/ +│ ├── bash-in-slow-motion.md +│ └── tls-in-a-nutshell.md +├── tutorials/ +│ ├── git-for-beginners.md +│ └── javascript-bundling-with-hugo.md +└── _index.md +``` + +Render tutorials under "training", and render the posts under "articles" with a date-base hierarchy: + +{{< code-toggle file=hugo >}} +[permalinks.page] +posts = '/articles/:year/:month/:slug/' +tutorials = '/training/:slug/' +[permalinks.section] +posts = '/articles/' +tutorials = '/training/' +{{< /code-toggle >}} + +The structure of the published site will be: + +```text +public/ +├── articles/ +│ ├── 2023/ +│ │ ├── 04/ +│ │ │ └── bash-in-slow-motion/ +│ │ │ └── index.html +│ │ └── 06/ +│ │ └── tls-in-a-nutshell/ +│ │ └── index.html +│ └── index.html +├── training/ +│ ├── git-for-beginners/ +│ │ └── index.html +│ ├── javascript-bundling-with-hugo/ +│ │ └── index.html +│ └── index.html +└── index.html +``` + +To create a date-based hierarchy for regular pages in the content root: + +{{< code-toggle file=hugo >}} +[permalinks.page] +"/" = "/:year/:month/:slug/" +{{< /code-toggle >}} + +Use the same approach with taxonomy terms. For example, to omit the taxonomy segment of the URL: + +{{< code-toggle file=hugo >}} +[permalinks.term] +'tags' = '/:slug/' +{{< /code-toggle >}} + +#### Multilingual example {#permalinks-multilingual-example} + +Use the `permalinks` configuration as a component of your localization strategy. + +With this content structure: + +```text +content/ +├── en/ +│ ├── books/ +│ │ ├── les-miserables.md +│ │ └── the-hunchback-of-notre-dame.md +│ └── _index.md +└── es/ + ├── books/ + │ ├── les-miserables.md + │ └── the-hunchback-of-notre-dame.md + └── _index.md +``` + +And this site configuration: + +{{< code-toggle file=hugo >}} +defaultContentLanguage = 'en' +defaultContentLanguageInSubdir = true + +[languages.en] +contentDir = 'content/en' +languageCode = 'en-US' +languageDirection = 'ltr' +languageName = 'English' +weight = 1 + +[languages.en.permalinks.page] +books = "/books/:slug/" + +[languages.en.permalinks.section] +books = "/books/" + +[languages.es] +contentDir = 'content/es' +languageCode = 'es-ES' +languageDirection = 'ltr' +languageName = 'Español' +weight = 2 + +[languages.es.permalinks.page] +books = "/libros/:slug/" + +[languages.es.permalinks.section] +books = "/libros/" +{{< /code-toggle >}} + +The structure of the published site will be: + +```text +public/ +├── en/ +│ ├── books/ +│ │ ├── les-miserables/ +│ │ │ └── index.html +│ │ ├── the-hunchback-of-notre-dame/ +│ │ │ └── index.html +│ │ └── index.html +│ └── index.html +├── es/ +│ ├── libros/ +│ │ ├── les-miserables/ +│ │ │ └── index.html +│ │ ├── the-hunchback-of-notre-dame/ +│ │ │ └── index.html +│ │ └── index.html +│ └── index.html +└── index.html +```` + +#### Tokens + +Use these tokens when defining the URL pattern. The `date` field in front matter determines the value of time-related tokens. + +`:year` +: the 4-digit year + +`:month` +: the 2-digit month + +`:monthname` +: the name of the month + +`:day` +: the 2-digit day + +`:weekday` +: the 1-digit day of the week (Sunday = 0) + +`:weekdayname` +: the name of the day of the week + +`:yearday` +: the 1- to 3-digit day of the year + +`:section` +: the content's section + +`:sections` +: the content's sections hierarchy. You can use a selection of the sections using _slice syntax_: `:sections[1:]` includes all but the first, `:sections[:last]` includes all but the last, `:sections[last]` includes only the last, `:sections[1:2]` includes section 2 and 3. Note that this slice access will not throw any out-of-bounds errors, so you don't have to be exact. + +`:title` +: the content's title + +`:slug` +: the content's slug (or title if no slug is provided in the front matter) + +`:slugorfilename` +: the content's slug (or file name if no slug is provided in the front matter) + +`:filename` +: the content's file name (without extension) + +For time-related values, you can also use the layout string components defined in Go's [time package]. For example: + +[time package]: https://pkg.go.dev/time#pkg-constants + +{{< code-toggle file=hugo >}} +permalinks: + posts: /:06/:1/:2/:title/ +{{< /code-toggle >}} + +### Appearance + +The appearance of a URL is either ugly or pretty. + +Type|Path|URL +:--|:--|:-- +ugly|content/about.md|`https://example.org/about.html` +pretty|content/about.md|`https://example.org/about/` + +By default, Hugo produces pretty URLs. To generate ugly URLs, change your site configuration: + +{{< code-toggle file=hugo >}} +uglyURLs = true +{{< /code-toggle >}} + +### Post-processing + +Hugo provides two mutually exclusive configuration options to alter URLs _after_ it renders a page. + +#### Canonical URLs + +{{% note %}} +This is a legacy configuration option, superseded by template functions and markdown render hooks, and will likely be [removed in a future release]. + +[removed in a future release]: https://github.com/gohugoio/hugo/issues/4733 +{{% /note %}} + +If enabled, Hugo performs a search and replace _after_ it renders the page. It searches for site-relative URLs (those with a leading slash) associated with `action`, `href`, `src`, `srcset`, and `url` attributes. It then prepends the `baseURL` to create absolute URLs. + +```html +<a href="/about"> → <a href="https://example.org/about/"> +<img src="/a.gif"> → <img src="https://example.org/a.gif"> +``` + +This is an imperfect, brute force approach that can affect content as well as HTML attributes. As noted above, this is a legacy configuration option that will likely be removed in a future release. + +To enable: + +{{< code-toggle file=hugo >}} +canonifyURLs = true +{{< /code-toggle >}} + +#### Relative URLs + +{{% note %}} +Do not enable this option unless you are creating a serverless site, navigable via the file system. +{{% /note %}} + +If enabled, Hugo performs a search and replace _after_ it renders the page. It searches for site-relative URLs (those with a leading slash) associated with `action`, `href`, `src`, `srcset`, and `url` attributes. It then transforms the URL to be relative to the current page. + +For example, when rendering `content/posts/post-1`: + +```html +<a href="/about"> → <a href="../../about"> +<img src="/a.gif"> → <img src="../../a.gif"> +``` + +This is an imperfect, brute force approach that can affect content as well as HTML attributes. As noted above, do not enable this option unless you are creating a serverless site. + +To enable: + +{{< code-toggle file=hugo >}} +relativeURLs = true +{{< /code-toggle >}} + +## Aliases + +Create redirects from old URLs to new URLs with aliases: + +- An alias with a leading slash is relative to the `baseURL` +- An alias without a leading slash is relative to the current directory + +### Examples {#alias-examples} + +Change the file name of an existing page, and create an alias from the previous URL to the new URL: + +{{< code-toggle file=content/posts/new-file-name.md >}} +aliases = ['/posts/previous-file-name'] +{{< /code-toggle >}} + +Each of these directory-relative aliases is equivalent to the site-relative alias above: + +- `previous-file-name` +- `./previous-file-name` +- `../posts/previous-file-name` + +You can create more than one alias to the current page: + +{{< code-toggle file=content/posts/new-file-name.md >}} +aliases = ['previous-file-name','original-file-name'] +{{< /code-toggle >}} + +In a multilingual site, use a directory-relative alias, or include the language prefix with a site-relative alias: + +{{< code-toggle file=content/posts/new-file-name.de.md >}} +aliases = ['/de/posts/previous-file-name'] +{{< /code-toggle >}} + +### How aliases work + +Using the first example above, Hugo generates the following site structure: + +```text +public/ +├── posts/ +│ ├── new-file-name/ +│ │ └── index.html +│ ├── previous-file-name/ +│ │ └── index.html +│ └── index.html +└── index.html +``` + +The alias from the previous URL to the new URL is a client-side redirect: + +{{< code file=posts/previous-file-name/index.html >}} +<!DOCTYPE html> +<html lang="en-us"> + <head> + <title>https://example.org/posts/new-file-name/</title> + <link rel="canonical" href="https://example.org/posts/new-file-name/"> + <meta name="robots" content="noindex"> + <meta charset="utf-8"> + <meta http-equiv="refresh" content="0; url=https://example.org/posts/new-file-name/"> + </head> +</html> +{{< /code >}} + +Collectively, the elements in the `head` section: + +- Tell search engines that the new URL is canonical +- Tell search engines not to index the previous URL +- Tell the browser to redirect to the new URL + +Hugo renders alias files before rendering pages. A new page with the previous file name will overwrite the alias, as expected. + +### Customize + +Create a new template (`layouts/alias.html`) to customize the content of the alias files. The template receives the following context: + +Permalink +: the link to the page being aliased + +Page +: the Page data for the page being aliased diff --git a/docs/content/en/contribute/_index.md b/docs/content/en/contribute/_index.md new file mode 100644 index 000000000..ca7a18c36 --- /dev/null +++ b/docs/content/en/contribute/_index.md @@ -0,0 +1,16 @@ +--- +title: Contribute to the Hugo project +linkTitle: Overview +description: Contribute to Hugo development, documentation, and themes. +categories: [] +keywords: [] +menu: + docs: + identifier: contribute-overview + parent: contribute + weight: 10 +weight: 10 +aliases: [/tutorials/how-to-contribute-to-hugo/,/community/contributing/] +--- + +Hugo relies heavily on the enthusiasm and participation of the open-source community. We need your support. diff --git a/docs/content/en/contribute/development.md b/docs/content/en/contribute/development.md new file mode 100644 index 000000000..b4de88256 --- /dev/null +++ b/docs/content/en/contribute/development.md @@ -0,0 +1,430 @@ +--- +title: Development +description: Contribute to the development of Hugo. +categories: [contribute] +keywords: [development] +menu: + docs: + parent: contribute + weight: 20 +weight: 20 +toc: true +--- + +## Introduction + +Hugo is an open-source project and lives by the work of its [contributors]. There are plenty of [open issues][issues], and we need your help to make Hugo even more awesome. You don't need to be a Go guru to contribute to the project's development. + +## Assumptions + +This contribution guide takes a step-by-step approach in hopes of helping newcomers. Therefore, we only assume the following: + +* You are new to Git or open-source projects in general +* You are a fan of Hugo and enthusiastic about contributing to the project + +{{% note %}} +If you're struggling at any point in this contribution guide, reach out to the Hugo community in [Hugo's Discussion forum](https://discourse.gohugo.io). +{{% /note %}} + +## Install Go + +The installation of Go should take only a few minutes. You have more than one option to get Go up and running on your machine. + +If you are having trouble following the installation guides for Go, check out [Go Bootcamp, which contains setups for every platform][gobootcamp] or reach out to the Hugo community in the [Hugo Discussion Forums][forums]. + +### Install Go from source + +[Download the latest stable version of Go][godl] and follow the official [Go installation guide][goinstall]. + +Once you're finished installing Go, let's confirm everything is working correctly. Open a terminal---or command line under Windows--and type the following: + +```txt +go version +``` + +You should see something similar to the following written to the console. Note that the version here reflects the most recent version of Go as of the last update for this page: + +```txt +go version go1.12 darwin/amd64 +``` + +Next, make sure that you set up your `GOPATH` [as described in the installation guide][setupgopath]. + +You can print the `GOPATH` with `echo $GOPATH`. You should see a non-empty string containing a valid path to your Go workspace; for example: + +```txt +/Users/<yourusername>/Code/go +``` + +### Install Go with Homebrew + +If you are a macOS user and have [Homebrew](https://brew.sh/) installed on your machine, installing Go is as simple as the following command: + +{{< code file=install-go.sh >}} +brew install go +{{< /code >}} + +### Install Go via GVM + +More experienced users can use the [Go Version Manager][gvm] (GVM). GVM allows you to switch between different Go versions *on the same machine*. If you're a beginner, you probably don't need this feature. However, GVM makes it easy to upgrade to a new released Go version with just a few commands. + +GVM comes in especially handy if you follow the development of Hugo over a longer period of time. Future versions of Hugo will usually be compiled with the latest version of Go. Sooner or later, you will have to upgrade if you want to keep up. + +## Create a GitHub account + +If you're going to contribute code, you'll need to have an account on GitHub. Go to [www.github.com/join](https://github.com/join) and set up a personal account. + +## Install Git on your system + +You will need to have Git installed on your computer to contribute to Hugo development. Teaching Git is outside the scope of the Hugo docs, but if you're looking for an excellent reference to learn the basics of Git, we recommend the [Git book][gitbook] if you are not sure where to begin. We will include short explanations of the Git commands in this document. + +Git is a [version control system](https://en.wikipedia.org/wiki/Version_control) to track the changes of source code. Hugo depends on smaller third-party packages that are used to extend the functionality. We use them because we don't want to reinvent the wheel. + +Go ships with a sub-command called `get` that will download these packages for us when we set up our working environment. The source code of the packages is tracked with Git. `get` will interact with the Git servers of the package hosters in order to fetch all dependencies. + +Move back to the terminal and check if Git is already installed. Type in `git version` and press enter. You can skip the rest of this section if the command returned a version number. Otherwise [download](https://git-scm.com/downloads) the latest version of Git and follow this [installation guide](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git). + +Finally, check again with `git version` if Git was installed successfully. + +### Git graphical front ends + +There are several [GUI clients](https://git-scm.com/downloads/guis) that help you to operate Git. Not all are available for all operating systems and maybe differ in their usage. Because of this we will document how to use the command-line, since the commands are the same everywhere. + +### Install Hub on your system (optional) + +Hub is a great tool for working with GitHub. The main site for it is [hub.github.com](https://hub.github.com/). Feel free to install this little Git wrapper. + +On a Mac, you can install [Hub](https://github.com/github/hub) using [Homebrew](https://brew.sh): + +```txt +brew install hub +``` + +Now we'll create an [alias in Bash](https://tldp.org/LDP/abs/html/aliases.html) so that typing `git` actually runs `Hub`: + +```txt +echo "alias git='hub'" >> ~/.bash_profile +``` + +Confirm the installation: + +```txt +git version 2.21.0 +hub version 2.10.0 +``` + +## Set up your working copy + +You set up the working copy of the repository locally on your computer. Your local copy of the files is what you'll edit, compile, and end up pushing back to GitHub. The main steps are cloning the repository and creating your fork as a remote. + +### Clone the repository + +We assume that you've set up your `GOPATH` (see the section above if you're unsure about this). You should now copy the Hugo repository down to your computer. You'll hear this called "clone the repo". GitHub's [help pages](https://help.github.com/articles/cloning-a-repository/) give us a short explanation: + +{{% note %}} +When you create a repository on GitHub, it exists as a remote repository. You can create a local clone of your repository on your computer and sync between the two locations. +{{% /note %}} + +We're going to clone the [master Hugo repository](https://github.com/gohugoio/hugo). That seems counter-intuitive, since you won't have commit rights on it. But it's required for the Go workflow. You'll work on a copy of the master and push your changes to your own repository on GitHub. + +So, let's make a new directory and clone that master repository: + +```txt +mkdir $HOME/src +cd $HOME/src +git clone https://github.com/gohugoio/hugo.git +``` + +Since Hugo 0.48, Hugo uses the Go Modules support built into Go 1.11 to build. The easiest is to clone Hugo in a directory outside of GOPATH + +And then, install dependencies of Hugo by running the following in the cloned directory: + +```txt +cd $HOME/src/hugo +go install +``` + +Hugo relies on [mage](https://github.com/magefile/mage) for some convenient build and test targets. If you don't already have it, get it: + +```txt +go install github.com/magefile/mage@latest +``` + +### Fork the repository + +If you're not familiar with this term, GitHub's [help pages](https://help.github.com/articles/fork-a-repo/) provide again a simple explanation: + +{{% note %}} +A fork is a copy of a repository. Forking a repository allows you to freely experiment with changes without affecting the original project. +{{% /note %}} + +#### Fork by hand + +Open the [Hugo repository](https://github.com/gohugoio/hugo) on GitHub and click on the "Fork" button in the top right. + + + +Now open your fork repository on GitHub and copy the remote URL of your fork. You can choose between HTTPS and SSH as protocol that Git should use for the following operations. HTTPS works always [if you're not sure](https://help.github.com/articles/which-remote-url-should-i-use/). + + + +Switch back to the terminal and move into the directory of the cloned master repository from the last step. + +```txt +cd $HOME/src/hugo +``` + +Now Git needs to know that our fork exists by adding the copied remote url: + +```txt +git remote add <YOUR-GITHUB-USERNAME> <COPIED REMOTE-URL> +``` + +#### Fork with Hub + +Alternatively, you can use the Git wrapper Hub. Hub makes forking a repository easy: + +```txt +git fork +``` + +That command will log in to GitHub using your account, create a fork of the repository that you're currently working in, and add it as a remote to your working copy. + +#### Trust, but verify + +Let's check if everything went right by listing all known remotes: + +```txt +git remote -v +``` + +The output should look similar: + +```txt +digitalcraftsman git@github.com:digitalcraftsman/hugo.git (fetch) +digitalcraftsman git@github.com:digitalcraftsman/hugo.git (push) +origin https://github.com/gohugoio/hugo (fetch) +origin https://github.com/gohugoio/hugo (push) +``` + +## The Hugo Git contribution workflow + +### Create a new branch + +You should never develop against the "master" branch. The development team will not accept a pull request against that branch. Instead, create a descriptive named branch and work on it. + +First, you should always pull the latest changes from the master repository: + +```txt +git checkout master +git pull +``` + +Now we can create a new branch for your additions: + +```txt +git checkout -b <BRANCH-NAME> +``` + +You can check on which branch you are with `git branch`. You should see a list of all local branches. The current branch is indicated with a little asterisk. + +### Contribute to documentation + +Perhaps you want to start contributing to the Hugo docs. If so, you can ignore most of the following steps and focus on the `/docs` directory within your newly cloned repository. You can change directories into the Hugo docs using `cd docs`. + +You can start Hugo's built-in server via `hugo server`. Browse the documentation by entering [http://localhost:1313](http://localhost:1313) in the address bar of your browser. The server automatically updates the page whenever you change content. + +We have developed a [separate Hugo documentation contribution guide][docscontrib] for more information on how the Hugo docs are built, organized, and improved by the generosity of people like you. + +### Build Hugo + +While making changes in the codebase it's a good idea to build the binary to test them: + +```txt +mage hugo +``` + +This command generates the binary file at the root of the repository. + +If you want to install the binary in `$GOPATH/bin`, run + +```txt +mage install +``` + +### Test + +Sometimes changes on the codebase can cause unintended side effects. Or they don't work as expected. Most functions have their own test cases. You can find them in files ending with `_test.go`. + +Make sure the commands + +```txt +mage -v check +``` + +passes. + +### Formatting + +The Go code style guide maybe is opinionated but it ensures that the codebase looks the same, regardless who wrote the code. Go comes with its own formatting tool. Let's apply the style guide to our additions: + +```txt +mage fmt +``` + +Once you made your additions commit your changes. Make sure that you follow our [code contribution guidelines](https://github.com/gohugoio/hugo/blob/master/CONTRIBUTING.md): + +```txt +# Add all changed files +git add --all +git commit --message "YOUR COMMIT MESSAGE" +``` + +The commit message should describe what the commit does (e.g. add feature XYZ), not how it is done. + +### Modify commits + +You noticed some commit messages don't fulfill the code contribution guidelines or you just forget something to add some files? No problem. Git provides the necessary tools to fix such problems. The next two methods cover all common cases. + +If you are unsure what a command does leave the commit as it is. We can fix your commits later in the pull request. + +#### Modify the last commit + +Let's say you want to modify the last commit message. Run the following command and replace the current message: + +```txt +git commit --amend -m"YOUR NEW COMMIT MESSAGE" +``` + +Take a look at the commit log to see the change: + +```txt +git log +# Exit with q +``` + +After making the last commit you may have forgotten something. There is no need to create a new commit. Just add the latest changes and merge them into the intended commit: + +```txt +git add --all +git commit --amend +``` + +#### Modify multiple commits + +{{% note %}} +Modifications such as those described in this section can have serious unintended consequences. Skip this section if you're not sure! +{{% /note %}} + +This is a bit more advanced. Git allows you to [rebase](https://git-scm.com/docs/git-rebase) commits interactively. In other words: it allows you to rewrite the commit history. + +```txt +git rebase --interactive @~6 +``` + +The `6` at the end of the command represents the number of commits that should be modified. An editor should open and present a list of last six commit messages: + +```txt +pick 80d02a1 tpl: Add hasPrefix to template function smoke test" +pick aaee038 tpl: Sort the smoke tests +pick f0dbf2c tpl: Add the other test case for hasPrefix +pick 911c35b Add "How to contribute to Hugo" tutorial +pick 33c8973 Begin workflow +pick 3502f2e Refactoring and typo fixes +``` + +In the case above we should merge the last two commits in the commit of this tutorial (`Add "How to contribute to Hugo" tutorial`). You can "squash" commits, i.e. merge two or more commits into a single one. + +All operations are written before the commit message. Replace "pick" with an operation. In this case `squash` or `s` for short: + +```txt +pick 80d02a1 tpl: Add hasPrefix to template function smoke test" +pick aaee038 tpl: Sort the smoke tests +pick f0dbf2c tpl: Add the other test case for hasPrefix +pick 911c35b Add "How to contribute to Hugo" tutorial +squash 33c8973 Begin workflow +squash 3502f2e Refactoring and typo fixes +``` + +We also want to rewrite the commits message of the third last commit. We forgot "docs:" as prefix according to the code contribution guidelines. The operation to rewrite a commit is called `reword` (or `r` as shortcut). + +You should end up with a similar setup: + +```txt +pick 80d02a1 tpl: Add hasPrefix to template function smoke test" +pick aaee038 tpl: Sort the smoke tests +pick f0dbf2c tpl: Add the other test case for hasPrefix +reword 911c35b Add "How to contribute to Hugo" tutorial +squash 33c8973 Begin workflow +squash 3502f2e Refactoring and typo fixes +``` + +Close the editor. It should open again with a new tab. A text is instructing you to define a new commit message for the last two commits that should be merged (aka "squashed"). Save the file with <kbd>CTRL</kbd>+<kbd>S</kbd> and close the editor again. + +A last time a new tab opens. Enter a new commit message and save again. Your terminal should contain a status message. Hopefully this one: + +```txt +Successfully rebased and updated refs/heads/<BRANCHNAME>. +``` + +Check the commit log if everything looks as expected. Should an error occur you can abort this rebase with `git rebase --abort`. + +### Push commits + +To push our commits to the fork on GitHub we need to specify a destination. A destination is defined by the remote and a branch name. Earlier, the defined that the remote URL of our fork is the same as our GitHub handle, in my case `digitalcraftsman`. The branch should have the same as our local one. This makes it easy to identify corresponding branches. + +```txt +git push --set-upstream <YOUR-GITHUB-USERNAME> <BRANCHNAME> +``` + +Now Git knows the destination. Next time when you to push commits you just need to enter `git push`. + +If you modified your commit history in the last step GitHub will reject your try to push. This is a safety-feature because the commit history isn't the same and new commits can't be appended as usual. You can enforce this push explicitly with `git push --force`. + +## Open a pull request + +We made a lot of progress. Good work. In this step we finally open a pull request to submit our additions. Open the [Hugo master repository](https://github.com/gohugoio/hugo/) on GitHub in your browser. + +You should find a green button labeled with "New pull request". But GitHub is clever and probably suggests you a pull request like in the beige box below: + + + +The new page summaries the most important information of your pull request. Scroll down and you find the additions of all your commits. Make sure everything looks as expected and click on "Create pull request". + +### Accept the contributor license agreement + +Last but not least you should accept the contributor license agreement (CLA). A new comment should be added automatically to your pull request. Click on the yellow badge, accept the agreement and authenticate yourself with your GitHub account. It just takes a few clicks and only needs to be done once. + + + +### Automatic builds + +We use a GitHub Actions workflow to build and test. This is a matrix build across combinations of operating system (macOS, Windows, and Ubuntu) and Go versions. The workflow is triggered by the submission of a pull request. If you are a first-time contributor, the workflow requires approval from a project maintainer. + +## Where to start? + +Thank you for reading through this contribution guide. Hopefully, we will see you again soon on GitHub. There are plenty of [open issues][issues] for you to help with. + +Feel free to [open an issue][newissue] if you think you found a bug or you have a new idea to improve Hugo. We are happy to hear from you. + +## Additional references for learning Git and Go + +* [Codecademy's Free "Learn Git" Course][codecademy] (Free) +* [Code School and GitHub's "Try Git" Tutorial][trygit] (Free) +* [The Git Book][gitbook] (Free) +* [Go Bootcamp][gobootcamp] + +[codecademy]: https://www.codecademy.com/learn/learn-git +[contributors]: https://github.com/gohugoio/hugo/graphs/contributors +[docscontrib]: /contribute/documentation/ +[forums]: https://discourse.gohugo.io +[gitbook]: https://git-scm.com/ +[gobootcamp]: https://www.golang-book.com/guides/machine_setup +[godl]: https://go.dev/dl/ +[goinstall]: https://go.dev/doc/install +[gvm]: https://github.com/moovweb/gvm +[issues]: https://github.com/gohugoio/hugo/issues +[newissue]: https://github.com/gohugoio/hugo/issues/new +[releases]: /getting-started/ +[setupgopath]: https://go.dev/doc/code#Workspaces +[trygit]: https://try.github.io/levels/1/challenges/1 diff --git a/docs/content/en/contribute/documentation.md b/docs/content/en/contribute/documentation.md new file mode 100644 index 000000000..862df619f --- /dev/null +++ b/docs/content/en/contribute/documentation.md @@ -0,0 +1,371 @@ +--- +title: Documentation +description: Help us to improve the documentation by identifying issues and suggesting changes. +categories: [contribute] +keywords: [documentation] +menu: + docs: + parent: contribute + weight: 30 +weight: 30 +toc: true +aliases: [/contribute/docs/] +--- + +## Introduction + +We welcome corrections and improvements to the documentation. Please note that the documentation resides in its own repository, separate from the project repository. + +For corrections and improvements to the current documentation, please submit issues and pull requests to the [documentation repository]. + +For documentation related to a new feature, please include the documentation changes when you submit a pull request to the [project repository]. + +## Guidelines + +### Markdown + +Please follow these markdown guidelines: + +- Use [ATX] headings, not [setext] headings, levels 2 through 4 +- Use [fenced code blocks], not [indented code blocks] +- Use hyphens, not asterisks, with unordered [list items] +- Use the [note shortcode] instead of blockquotes +- Do not mix [raw HTML] within markdown +- Do not use bold text instead of a heading or description term (`dt`) +- Remove consecutive blank lines (maximum of two) +- Remove trailing spaces + +### Style + +Although we do not strictly adhere to the [Microsoft Writing Style Guide], it is an excellent resource for questions related to style, grammar, and voice. + +#### Terminology + +Please link to the [glossary of terms] when necessary, and use the terms consistently throughout the documentation. Of special note: + +- The term "front matter" is two words unless you are referring to the configuration key +- Use the word "map" instead of "dictionary" +- Use the word "flag" instead of "option" when referring to a command line flag + +#### Page titles and headings + +Please follow these guidelines for page titles and headings: + +- Use sentence-style capitalization +- Avoid markdown in headings and page titles +- Shorter is better + +#### Use active voice with present tense + +In software documentation, passive voice is unavoidable in some cases. Please use active voice when possible. + +No → With Hugo you can build a static site.\ +Yes → Build a static site with Hugo. + +No → This will cause Hugo to generate HTML files in the public directory.\ +Yes → Hugo generates HTML files in the public directory. + +#### Use second person instead of third person + +No → Users should exercise caution when deleting files.\ +Better → You must be cautious when deleting files.\ +Best → Be cautious when deleting files. + +#### Avoid adverbs when possible + +No → Hugo is extremely fast.\ +Yes → Hugo is fast. + +{{% note %}} +"It's an adverb, Sam. It's a lazy tool of a weak mind." (Outbreak, 1995). +{{% /note %}} + +#### Miscellaneous + +Other guidelines to consider: + +- Do not place list items directly under a heading; include an introductory sentence or phrase before the list. +- Avoid use of **bold** text. Use the [note shortcode] to draw attention to important content. +- Do not place description terms (`dt`) within backticks unless required for syntactic clarity. +- Do not use Hugo's `ref` or `relref` shortcodes. We use a link render hook to resolve and validate link destinations, including fragments. +- Shorter is better. If there is more than one way to do something, describe the current best practice. For example, avoid phrases such as "you can also do..." and "in older versions you had to..." +- When including code samples, use short snippets that demonstrate the concept. +- The Hugo user community is global; use [basic english](https://simple.wikipedia.org/wiki/Basic_English) when possible. + +#### Level 6 markdown headings + +Level 6 markdown headings are styled as `dt` elements. This was implemented to support a [glossary] with linkable terms. + +[glossary]: /getting-started/glossary + +## Code examples + +Indent code by two spaces. With examples of template code, include a space after opening action delimiters, and include a space before closing action delimiters. + +### Fenced code blocks + +Always include the language code when using a fenced code block: + +````text +```go-html-template +{{ if eq $foo "bar" }} + {{ print "foo is bar" }} +{{ end }} +``` +```` + +Rendered: + +```go-html-template +{{ if eq $foo "bar" }} + {{ print "foo is bar" }} +{{ end }} +``` + +### Shortcode calls + +Use this syntax to include shortcodes calls within your code examples: + +```text +{{</*/* foo */*/>}} +{{%/*/* foo */*/%}} +``` + +Rendered: + +```text +{{</* foo */>}} +{{%/* foo */%}} +``` + +### Site configuration + +Use the [code-toggle shortcode] to include site configuration examples: + +```text +{{</* code-toggle file=hugo */>}} +baseURL = 'https://example.org/' +languageCode = 'en-US' +title = 'My Site' +{{</* /code-toggle */>}} +``` + +Rendered: + +{{< code-toggle file=hugo >}} +baseURL = 'https://example.org/' +languageCode = 'en-US' +title = 'My Site' +{{< /code-toggle >}} + +### Front matter + +Use the [code-toggle shortcode] to include front matter examples: + +```text +{{</* code-toggle file=content/posts/my-first-post.md fm=true */>}} +title = 'My first post' +date = 2023-11-09T12:56:07-08:00 +draft = false +{{</* /code-toggle */>}} +``` + +Rendered: + +{{< code-toggle file=content/posts/my-first-post.md fm=true >}} +title = 'My first post' +date = 2023-11-09T12:56:07-08:00 +draft = false +{{< /code-toggle >}} + +### Other code examples + +Use the [code shortcode] for other code examples that require a file name: + +```text +{{</* code file=layouts/_default/single.html */>}} +{{ range .Site.RegularPages }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +{{</* /code */>}} +``` + +Rendered: + +{{< code file=layouts/_default/single.html >}} +{{ range .Site.RegularPages }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +{{< /code >}} + +## Shortcodes + +These shortcodes are commonly used throughout the documentation. Other shortcodes are available for specialized use. + +### deprecated-in + +Use the “deprecated-in” shortcode to indicate that a feature is deprecated: + +```text +{{%/* deprecated-in 0.120.0 */%}} +Use [`hugo.IsServer`] instead. + +[`hugo.IsServer`]: /functions/hugo/isserver +{{%/* /deprecated-in */%}} +``` + +Rendered: + +{{% deprecated-in 0.120.0 %}} +Use [`hugo.IsServer`] instead. + +[`hugo.IsServer`]: /functions/hugo/isserver +{{% /deprecated-in %}} + +### code + +Use the "code" shortcode for other code examples that require a file name. See the [code examples] above. This shortcode takes these arguments: + +copy +: (`bool`) Whether to display a copy-to-clipboard button. Default is `false`. + +file +: (`string`) The file name to display. + +lang +: (`string`) The code language. If you do not provide a `lang` argument, the code language is determined by the file extension. If the file extension is "html", sets the code language to `go-html-template`. Default is `text`. + +### code-toggle + +Use the "code-toggle" shortcode to display examples of site configuration, front matter, or data files. See the [code examples] above. This shortcode takes these arguments: + +copy +: (`bool`) Whether to display a copy-to-clipboard button. Default is `false`. + +file +: (`string`) The file name to display. Omit the file extension for site configuration examples. + +fm +: (`bool`) Whether the example is front matter. Default is `false`. + +### new-in + +Use the "new-in" shortcode to indicate a new feature: + +```text +{{</* new-in 0.120.0 */>}} +``` + +Rendered: + +{{< new-in 0.120.0 >}} + +### note + +Use the "note" shortcode with `{{%/* */%}}` delimiters to call attention to important content: + +```text +{{%/* note */%}} +Use the [`math.Mod`] function to control... + +[`math.Mod`]: /functions/math/mod/ +{{%/* /note */%}} +``` + +Rendered: + +{{% note %}} +Use the [`math.Mod`] function to control... + +[`math.Mod`]: /functions/math/mod/ +{{% /note %}} + +## New features + +Use the "new-in" shortcode to indicate a new feature: + +{{< code file=content/something/foo.md lang=text >}} +{{</* new-in 0.120.0 */>}} +{{< /code >}} + +The "new in" label will be hidden if the specified version is older than a predefined threshold, based on differences in major and minor versions. See [details](https://github.com/gohugoio/hugoDocs/blob/master/layouts/shortcodes/new-in.html). + +## Deprecated features + +Use the "deprecated-in" shortcode to indicate that a feature is deprecated: + +{{< code file=content/something/foo.md >}} +{{%/* deprecated-in 0.120.0 */%}} +Use [`hugo.IsServer`] instead. + +[`hugo.IsServer`]: /functions/hugo/isserver +{{%/* /deprecated-in */%}} +{{< /code >}} + +When deprecating a function or method, add this to front matter: + +{{< code-toggle file=content/something/foo.md fm=true >}} +expiryDate: 2024-10-30 +{{< /code-toggle >}} + +Set the `expiryDate` to one year from the date of deprecation, and add a brief front matter comment to explain the setting. + +## GitHub workflow + +{{% note %}} +This section assumes that you have a working knowledge of Git and GitHub, and are comfortable working on the command line. +{{% /note %}} + +Use this workflow to create and submit pull requests. + +Step 1 +: Fork the [documentation repository]. + +Step 2 +: Clone your fork. + +Step 3 +: Create a new branch with a descriptive name. + +```sh +git checkout -b fix/typos-shortcode-templates +``` + +Step 4 +: Make changes. + +Step 5 +: Commit your changes with a descriptive commit message, typically 50 characters or less. Add the "Closes" keyword if your change addresses one or more open [issues]. + +```sh +git commit -m "Fix typos on the shortcode templates page + +Closes #1234 +Closes #5678" +``` + +Step 6 +: Push the new branch to your fork of the documentation repository. + +Step 7 +: Visit the [documentation repository] and create a pull request (PR). + +Step 8 +: A project maintainer will review your PR and may request changes. You may delete your branch after the maintainer merges your PR. + +[ATX]: https://spec.commonmark.org/0.30/#atx-headings +[Microsoft Writing Style Guide]: https://learn.microsoft.com/en-us/style-guide/welcome/ +[basic english]: https://simple.wikipedia.org/wiki/Basic_English +[code examples]: #code-examples +[code shortcode]: #code +[code-toggle shortcode]: #code-toggle +[documentation repository]: https://github.com/gohugoio/hugoDocs/ +[fenced code blocks]: https://spec.commonmark.org/0.30/#fenced-code-blocks +[glossary of terms]: /getting-started/glossary/ +[indented code blocks]: https://spec.commonmark.org/0.30/#indented-code-blocks +[issues]: https://github.com/gohugoio/hugoDocs/issues +[list items]: https://spec.commonmark.org/0.30/#list-items +[note shortcode]: #note +[project repository]: https://github.com/gohugoio/hugo +[raw HTML]: https://spec.commonmark.org/0.30/#raw-html +[setext]: https://spec.commonmark.org/0.30/#setext-heading diff --git a/docs/content/en/contribute/themes.md b/docs/content/en/contribute/themes.md new file mode 100644 index 000000000..34056c35a --- /dev/null +++ b/docs/content/en/contribute/themes.md @@ -0,0 +1,30 @@ +--- +title: Themes +description: If you've built a Hugo theme and want to contribute back to the Hugo Community, please share it with us. +categories: [contribute] +keywords: [themes] +menu: + docs: + parent: contribute + weight: 40 +weight: 40 +aliases: [/contribute/theme/] +--- + +Visit [themes.gohugo.io] to browse a collection of themes created by the Hugo community. + +To submit your theme: + +1. Read the [submission guidelines] +2. Open a pull request in the [themes repository] + +Other useful theme directories: + +- [jamstack.club] +- [jamstackthemes.dev] + +[jamstack.club]: https://jamstack.club/#ssg=hugo +[jamstackthemes.dev]: https://jamstackthemes.dev/ssg/hugo +[submission guidelines]: https://github.com/gohugoio/hugoThemesSiteBuilder/tree/main#readme +[themes repository]: https://github.com/gohugoio/hugoThemesSiteBuilder +[themes.gohugo.io]: https://themes.gohugo.io/ diff --git a/docs/content/en/documentation.md b/docs/content/en/documentation.md new file mode 100644 index 000000000..da7b3ef9b --- /dev/null +++ b/docs/content/en/documentation.md @@ -0,0 +1,22 @@ +--- +title: Hugo Documentation +linkTitle: Hugo +description: Hugo is the world's fastest static website engine. It's written in Go (aka Golang) and developed by bep, spf13 and friends. +menu: + main: + weight: 1 +weight: 1 +layout: documentation-home +--- + +A fast and flexible [static site generator] built with love by [bep], [spf13], and [friends] in [Go]. + +Hugo is 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. + +[bep]: https://github.com/bep +[spf13]: https://github.com/spf13 +[friends]: https://github.com/gohugoio/hugo/graphs/contributors +[go]: https://go.dev/ +[static site generator]: https://en.wikipedia.org/wiki/Static_site_generator + +Below you will find some of the most common and helpful pages from our documentation. diff --git a/docs/content/en/featured.png b/docs/content/en/featured.png Binary files differnew file mode 100644 index 000000000..09953aed9 --- /dev/null +++ b/docs/content/en/featured.png diff --git a/docs/content/en/functions/_common/_index.md b/docs/content/en/functions/_common/_index.md new file mode 100644 index 000000000..47d5812fb --- /dev/null +++ b/docs/content/en/functions/_common/_index.md @@ -0,0 +1,13 @@ +--- +cascade: + _build: + list: never + publishResources: false + render: never +--- + +<!-- +Files within this headless branch bundle are markdown snippets. Each file must contain front matter delimiters, though front matter fields are not required. + +Include the rendered content using the "include" shortcode. +--> diff --git a/docs/content/en/functions/_common/glob-patterns.md b/docs/content/en/functions/_common/glob-patterns.md new file mode 100644 index 000000000..3b0813f6f --- /dev/null +++ b/docs/content/en/functions/_common/glob-patterns.md @@ -0,0 +1,23 @@ +--- +# Do not remove front matter. +--- + +Path|Pattern|Match +:--|:--|:-- +`images/foo/a.jpg`|`images/foo/*.jpg`|`true` +`images/foo/a.jpg`|`images/foo/*.*`|`true` +`images/foo/a.jpg`|`images/foo/*`|`true` +`images/foo/a.jpg`|`images/*/*.jpg`|`true` +`images/foo/a.jpg`|`images/*/*.*`|`true` +`images/foo/a.jpg`|`images/*/*`|`true` +`images/foo/a.jpg`|`*/*/*.jpg`|`true` +`images/foo/a.jpg`|`*/*/*.*`|`true` +`images/foo/a.jpg`|`*/*/*`|`true` +`images/foo/a.jpg`|`**/*.jpg`|`true` +`images/foo/a.jpg`|`**/*.*`|`true` +`images/foo/a.jpg`|`**/*`|`true` +`images/foo/a.jpg`|`**`|`true` +`images/foo/a.jpg`|`*/*.jpg`|`false` +`images/foo/a.jpg`|`*.jpg`|`false` +`images/foo/a.jpg`|`*.*`|`false` +`images/foo/a.jpg`|`*`|`false` diff --git a/docs/content/en/functions/_common/locales.md b/docs/content/en/functions/_common/locales.md new file mode 100644 index 000000000..fd8415781 --- /dev/null +++ b/docs/content/en/functions/_common/locales.md @@ -0,0 +1,10 @@ +--- +# Do not remove front matter. +--- + +{{% note %}} + +Localization of dates, currencies, numbers, and percentages is performed by the [gohugoio/locales] package. The language tag of the current site must match one of the listed locales. + +[gohugoio/locales]: https://github.com/gohugoio/locales +{{% /note %}} diff --git a/docs/content/en/functions/_common/regular-expressions.md b/docs/content/en/functions/_common/regular-expressions.md new file mode 100644 index 000000000..48e020ac6 --- /dev/null +++ b/docs/content/en/functions/_common/regular-expressions.md @@ -0,0 +1,12 @@ +--- +# Do not remove front matter. +--- + +When specifying the regular expression, use a raw [string literal] (backticks) instead of an interpreted string literal (double quotes) to simplify the syntax. With an interpreted string literal you must escape backslashes. + +Go's regular expression package implements the [RE2 syntax]. The RE2 syntax is a subset of that accepted by [PCRE], roughly speaking, and with various [caveats]. Note that the RE2 `\C` escape sequence is not supported. + +[caveats]: https://swtch.com/~rsc/regexp/regexp3.html#caveats +[PCRE]: https://www.pcre.org/ +[RE2 syntax]: https://github.com/google/re2/wiki/Syntax/ +[string literal]: https://go.dev/ref/spec#String_literals diff --git a/docs/content/en/functions/_common/time-layout-string.md b/docs/content/en/functions/_common/time-layout-string.md new file mode 100644 index 000000000..827dc9894 --- /dev/null +++ b/docs/content/en/functions/_common/time-layout-string.md @@ -0,0 +1,46 @@ +--- +# Do not remove front matter. +--- + +Format a `time.Time` value based on [Go's reference time]: + +[Go's reference time]: https://pkg.go.dev/time#pkg-constants + +```text +Mon Jan 2 15:04:05 MST 2006 +``` + +Create a layout string using these components: + +Description|Valid components +:--|:-- +Year|`"2006" "06"` +Month|`"Jan" "January" "01" "1"` +Day of the week|`"Mon" "Monday"` +Day of the month|`"2" "_2" "02"` +Day of the year|`"__2" "002"` +Hour|`"15" "3" "03"` +Minute|`"4" "04"` +Second|`"5" "05"` +AM/PM mark|`"PM"` +Time zone offsets|`"-0700" "-07:00" "-07" "-070000" "-07:00:00"` + +Replace the sign in the layout string with a Z to print Z instead of an offset for the UTC zone. + +Description|Valid components +:--|:-- +Time zone offsets|`"Z0700" "Z07:00" "Z07" "Z070000" "Z07:00:00"` + +```go-html-template +{{ $t := "2023-01-27T23:44:58-08:00" }} +{{ $t = time.AsTime $t }} +{{ $t = $t.Format "Jan 02, 2006 3:04 PM Z07:00" }} + +{{ $t }} → Jan 27, 2023 11:44 PM -08:00 +``` + +Strings such as `PST` and `CET` are not time zones. They are time zone _abbreviations_. + +Strings such as `-07:00` and `+01:00` are not time zones. They are time zone _offsets_. + +A time zone is a geographic area with the same local time. For example, the time zone abbreviated by `PST` and `PDT` (depending on Daylight Savings Time) is `America/Los_Angeles`. diff --git a/docs/content/en/functions/_index.md b/docs/content/en/functions/_index.md new file mode 100644 index 000000000..b4b58eada --- /dev/null +++ b/docs/content/en/functions/_index.md @@ -0,0 +1,17 @@ +--- +title: Functions +linkTitle: Overview +description: A list of Hugo template functions including examples. +categories: [] +keywords: [] +menu: + docs: + identifier: functions-overview + parent: functions + weight: 10 +weight: 10 +showSectionMenu: true +aliases: [/layout/functions/,/templates/functions] +--- + +Use these functions within your templates and archetypes. diff --git a/docs/content/en/functions/cast/ToFloat.md b/docs/content/en/functions/cast/ToFloat.md new file mode 100644 index 000000000..51bc908b6 --- /dev/null +++ b/docs/content/en/functions/cast/ToFloat.md @@ -0,0 +1,48 @@ +--- +title: cast.ToFloat +description: Converts a value to a decimal floating-point number (base 10). +categories: [] +keywords: [] +action: + aliases: [float] + related: + - functions/cast/ToInt + - functions/cast/ToString + returnType: float64 + signatures: [cast.ToFloat INPUT] +aliases: [/functions/float] +--- + +With a decimal (base 10) input: + +```go-html-template +{{ float 11 }} → 11 (float64) +{{ float "11" }} → 11 (float64) + +{{ float 11.1 }} → 11.1 (float64) +{{ float "11.1" }} → 11.1 (float64) + +{{ float 11.9 }} → 11.9 (float64) +{{ float "11.9" }} → 11.9 (float64) +``` + +With a binary (base 2) input: + +```go-html-template +{{ float 0b11 }} → 3 (float64) +``` + +With an octal (base 8) input (use either notation): + +```go-html-template +{{ float 011 }} → 9 (float64) +{{ float "011" }} → 11 (float64) + +{{ float 0o11 }} → 9 (float64) +``` + +With a hexadecimal (base 16) input: + +```go-html-template +{{ float 0x11 }} → 17 (float64) +``` diff --git a/docs/content/en/functions/cast/ToInt.md b/docs/content/en/functions/cast/ToInt.md new file mode 100644 index 000000000..f82f029d5 --- /dev/null +++ b/docs/content/en/functions/cast/ToInt.md @@ -0,0 +1,53 @@ +--- +title: cast.ToInt +description: Converts a value to a decimal integer (base 10). +keywords: [] +action: + aliases: [int] + related: + - functions/cast/ToFloat + - functions/cast/ToString + returnType: int + signatures: [cast/ToInt INPUT] +aliases: [/functions/int] +--- + +With a decimal (base 10) input: + +```go-html-template +{{ int 11 }} → 11 (int) +{{ int "11" }} → 11 (int) + +{{ int 11.1 }} → 11 (int) +{{ int 11.9 }} → 11 (int) +``` + +With a binary (base 2) input: + +```go-html-template +{{ int 0b11 }} → 3 (int) +{{ int "0b11" }} → 3 (int) +``` + +With an octal (base 8) input (use either notation): + +```go-html-template +{{ int 011 }} → 9 (int) +{{ int "011" }} → 9 (int) + +{{ int 0o11 }} → 9 (int) +{{ int "0o11" }} → 9 (int) +``` + +With a hexadecimal (base 16) input: + +```go-html-template +{{ int 0x11 }} → 17 (int) +{{ int "0x11" }} → 17 (int) +``` + +{{% note %}} +Values with a leading zero are octal (base 8). When casting a string representation of a decimal (base 10) number, remove leading zeros: + +`{{ strings/TrimLeft "0" "0011" | int }} → 11` +{{% /note %}} diff --git a/docs/content/en/functions/cast/ToString.md b/docs/content/en/functions/cast/ToString.md new file mode 100644 index 000000000..a701c9421 --- /dev/null +++ b/docs/content/en/functions/cast/ToString.md @@ -0,0 +1,51 @@ +--- +title: cast.ToString +description: Converts a value to a string. +categories: [] +keywords: [] +action: + aliases: [string] + related: + - functions/cast/ToFloat + - functions/cast/ToInt + returnType: string + signatures: [cast.ToString INPUT] +aliases: [/functions/string] +--- + +With a decimal (base 10) input: + +```go-html-template +{{ string 11 }} → 11 (string) +{{ string "11" }} → 11 (string) + +{{ string 11.1 }} → 11.1 (string) +{{ string "11.1" }} → 11.1 (string) + +{{ string 11.9 }} → 11.9 (string) +{{ string "11.9" }} → 11.9 (string) +``` + +With a binary (base 2) input: + +```go-html-template +{{ string 0b11 }} → 3 (string) +{{ string "0b11" }} → 0b11 (string) +``` + +With an octal (base 8) input (use either notation): + +```go-html-template +{{ string 011 }} → 9 (string) +{{ string "011" }} → 011 (string) + +{{ string 0o11 }} → 9 (string) +{{ string "0o11" }} → 0o11 (string) +``` + +With a hexadecimal (base 16) input: + +```go-html-template +{{ string 0x11 }} → 17 (string) +{{ string "0x11" }} → 0x11 (string) +``` diff --git a/docs/content/en/functions/cast/_index.md b/docs/content/en/functions/cast/_index.md new file mode 100644 index 000000000..82389237a --- /dev/null +++ b/docs/content/en/functions/cast/_index.md @@ -0,0 +1,12 @@ +--- +title: Cast functions +linkTitle: cast +description: Template functions to cast a value from one data type to another. +categories: [] +keywords: [] +menu: + docs: + parent: functions +--- + +Use these functions to cast a value from one data type to another. diff --git a/docs/content/en/functions/collections/After.md b/docs/content/en/functions/collections/After.md new file mode 100644 index 000000000..0cf25c7dd --- /dev/null +++ b/docs/content/en/functions/collections/After.md @@ -0,0 +1,71 @@ +--- +title: collections.After +description: Slices an array to the items after the Nth item. +categories: [] +keywords: [] +action: + aliases: [after] + related: + - functions/collections/First + - functions/collections/Last + returnType: any + signatures: [collections.After INDEX COLLECTION] +aliases: [/functions/after] +--- + +The following shows `after` being used in conjunction with the [`slice`]function: + +```go-html-template +{{ $data := slice "one" "two" "three" "four" }} +<ul> + {{ range after 2 $data }} + <li>{{ . }}</li> + {{ end }} +</ul> +``` + +The template above is rendered to: + +```html +<ul> + <li>three</li> + <li>four</li> +</ul> +``` + +## Example of `after` with `first`: 2nd–4th most recent articles + +You can use `after` in combination with the [`first`] function and Hugo's [powerful sorting methods][lists]. Let's assume you have a list page at `example.com/articles`. You have 10 articles, but you want your templating for the [list/section page] to show only two rows: + +1. The top row is titled "Featured" and shows only the most recently published article (i.e. by `publishdate` in the content files' front matter). +2. The second row is titled "Recent Articles" and shows only the 2nd- to 4th-most recently published articles. + +{{< code file=layouts/section/articles.html >}} +{{ define "main" }} + <section class="row featured-article"> + <h2>Featured Article</h2> + {{ range first 1 .Pages.ByPublishDate.Reverse }} + <header> + <h3><a href="{{ .RelPermalink }}">{{ .Title }}</a></h3> + </header> + <p>{{ .Description }}</p> + {{ end }} + </section> + <div class="row recent-articles"> + <h2>Recent Articles</h2> + {{ range first 3 (after 1 .Pages.ByPublishDate.Reverse) }} + <section class="recent-article"> + <header> + <h3><a href="{{ .RelPermalink }}">{{ .Title }}</a></h3> + </header> + <p>{{ .Description }}</p> + </section> + {{ end }} + </div> +{{ end }} +{{< /code >}} + +[`first`]: /functions/collections/first +[list/section page]: /templates/section-templates +[lists]: /templates/lists/#sort-content +[`slice`]: /functions/collections/slice/ diff --git a/docs/content/en/functions/collections/Append.md b/docs/content/en/functions/collections/Append.md new file mode 100644 index 000000000..cb29dc2f2 --- /dev/null +++ b/docs/content/en/functions/collections/Append.md @@ -0,0 +1,101 @@ +--- +title: collections.Append +description: Appends one or more elements to a slice and returns the resulting slice. +categories: [] +keywords: [] +action: + aliases: [append] + related: + - functions/collections/Merge + returnType: any + signatures: + - collections.Append ELEMENT [ELEMENT...] COLLECTION + - collections.Append COLLECTION1 COLLECTION2 +aliases: [/functions/append] +--- + +This function appends all elements, excluding the last, to the last element. This allows [pipe](/getting-started/glossary/#pipeline) constructs as shown below. + +Append a single element to a slice: + +```go-html-template +{{ $s := slice "a" "b" }} +{{ $s }} → [a b] + +{{ $s = $s | append "c" }} +{{ $s }} → [a b c] +``` + +Append two elements to a slice: + +```go-html-template +{{ $s := slice "a" "b" }} +{{ $s }} → [a b] + +{{ $s = $s | append "c" "d" }} +{{ $s }} → [a b c d] +``` + +Append two elements, as a slice, to a slice. This produces the same result as the previous example: + +```go-html-template +{{ $s := slice "a" "b" }} +{{ $s }} → [a b] + +{{ $s = $s | append (slice "c" "d") }} +{{ $s }} → [a b c d] +``` + +Start with an empty slice: + +```go-html-template +{{ $s := slice }} +{{ $s }} → [] + +{{ $s = $s | append "a" }} +{{ $s }} → [a] + +{{ $s = $s | append "b" "c" }} +{{ $s }} → [a b c] + +{{ $s = $s | append (slice "d" "e") }} +{{ $s }} → [a b c d e] +``` + +If you start with a slice of a slice: + +```go-html-template +{{ $s := slice (slice "a" "b") }} +{{ $s }} → [[a b]] + +{{ $s = $s | append (slice "c" "d") }} +{{ $s }} → [[a b] [c d]] +``` + +To create a slice of slices, starting with an empty slice: + +```go-html-template +{{ $s := slice }} +{{ $s }} → [] + +{{ $s = $s | append (slice (slice "a" "b")) }} +{{ $s }} → [[a b]] + +{{ $s = $s | append (slice "c" "d") }} +{{ $s }} → [[a b] [c d]] +``` + +Although the elements in the examples above are strings, you can use the `append` function with any data type, including Pages. For example, on the home page of a corporate site, to display links to the two most recent press releases followed by links to the four most recent articles: + +```go-html-template +{{ $p := where site.RegularPages "Type" "press-releases" | first 2 }} +{{ $p = $p | append (where site.RegularPages "Type" "articles" | first 4) }} + +{{ with $p }} + <ul> + {{ range . }} + <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li> + {{ end }} + </ul> +{{ end }} +``` diff --git a/docs/content/en/functions/collections/Apply.md b/docs/content/en/functions/collections/Apply.md new file mode 100644 index 000000000..9153e546a --- /dev/null +++ b/docs/content/en/functions/collections/Apply.md @@ -0,0 +1,26 @@ +--- +title: collections.Apply +description: Returns a new collection with each element transformed by the given function. +categories: [] +keywords: [] +action: + aliases: [apply] + related: [] + returnType: '[]any' + signatures: [collections.Apply COLLECTION FUNCTION PARAM...] +aliases: [/functions/apply] +--- + +The `apply` function takes three or more arguments, depending on the function being applied to the collection elements. + +The first argument is the collection itself, the second argument is the function name, and the remaining arguments are passed to the function, with the string `"."` representing the collection element. + +```go-html-template +{{ $s := slice "hello" "world" }} + +{{ $s = apply $s "strings.FirstUpper" "." }} +{{ $s }} → [Hello World] + +{{ $s = apply $s "strings.Replace" "." "l" "_" }} +{{ $s }} → [He__o Wor_d] +``` diff --git a/docs/content/en/functions/collections/Complement.md b/docs/content/en/functions/collections/Complement.md new file mode 100644 index 000000000..b2a4b42a4 --- /dev/null +++ b/docs/content/en/functions/collections/Complement.md @@ -0,0 +1,80 @@ +--- +title: collections.Complement +description: Returns the elements of the last collection that are not in any of the others. +categories: [] +keywords: [] +action: + aliases: [complement] + related: + - functions/collections/Intersect + - functions/collections/SymDiff + - functions/collections/Union + returnType: any + signatures: ['collections.Complement COLLECTION [COLLECTION...]'] +aliases: [/functions/complement] +--- + +To find the elements within `$c3` that do not exist in `$c1` or `$c2`: + +```go-html-template +{{ $c1 := slice 3 }} +{{ $c2 := slice 4 5 }} +{{ $c3 := slice 1 2 3 4 5 }} + +{{ complement $c1 $c2 $c3 }} → [1 2] +``` + +{{% note %}} +Make your code simpler to understand by using a [chained pipeline]: + +[chained pipeline]: https://pkg.go.dev/text/template#hdr-Pipelines +{{% /note %}} + +```go-html-template +{{ $c3 | complement $c1 $c2 }} → [1 2] +``` + +You can also use the `complement` function with page collections. Let's say your site has five content types: + +```text +content/ +├── blog/ +├── books/ +├── faqs/ +├── films/ +└── songs/ +``` + +To list everything except blog articles (`blog`) and frequently asked questions (`faqs`): + +```go-html-template +{{ $blog := where site.RegularPages "Type" "blog" }} +{{ $faqs := where site.RegularPages "Type" "faqs" }} +{{ range site.RegularPages | complement $blog $faqs }} + <a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a> +{{ end }} +``` + +{{% note %}} +Although the example above demonstrates the `complement` function, you could use the [`where`] function as well: + +[`where`]: /functions/collections/where +{{% /note %}} + +```go-html-template +{{ range where site.RegularPages "Type" "not in" (slice "blog" "faqs") }} + <a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a> +{{ end }} +``` + +In this example we use the `complement` function to remove [stop words] from a sentence: + +```go-html-template +{{ $text := "The quick brown fox jumps over the lazy dog" }} +{{ $stopWords := slice "a" "an" "in" "over" "the" "under" }} +{{ $filtered := split $text " " | complement $stopWords }} + +{{ delimit $filtered " " }} → The quick brown fox jumps lazy dog +``` + +[stop words]: https://en.wikipedia.org/wiki/Stop_word diff --git a/docs/content/en/functions/collections/Delimit.md b/docs/content/en/functions/collections/Delimit.md new file mode 100644 index 000000000..b85059d4b --- /dev/null +++ b/docs/content/en/functions/collections/Delimit.md @@ -0,0 +1,33 @@ +--- +title: collections.Delimit +description: Loops through any array, slice, or map and returns a string of all the values separated by a delimiter. +categories: [] +keywords: [] +action: + aliases: [delimit] + related: + - functions/strings/Split + returnType: string + signatures: ['collections.Delimit COLLECTION DELIMITER [LAST]'] +aliases: [/functions/delimit] +--- + +Delimit a slice: + +```go-html-template +{{ $s := slice "b" "a" "c" }} +{{ delimit $s ", " }} → b, a, c +{{ delimit $s ", " " and "}} → b, a and c +``` + +Delimit a map: + +{{% note %}} +The `delimit` function sorts maps by key, returning the values. +{{% /note %}} + +```go-html-template +{{ $m := dict "b" 2 "a" 1 "c" 3 }} +{{ delimit $m ", " }} → 1, 2, 3 +{{ delimit $m ", " " and "}} → 1, 2 and 3 +``` diff --git a/docs/content/en/functions/collections/Dictionary.md b/docs/content/en/functions/collections/Dictionary.md new file mode 100644 index 000000000..f46b02e75 --- /dev/null +++ b/docs/content/en/functions/collections/Dictionary.md @@ -0,0 +1,68 @@ +--- +title: collections.Dictionary +description: Creates a map from a list of key and value pairs. +categories: [] +keywords: [] +action: + aliases: [dict] + related: + - functions/collections/Slice + returnType: mapany + signatures: ['collections.Dictionary KEY VALUE [VALUE...]'] +aliases: [/functions/dict] +--- + +```go-html-template +{{ $m := dict "a" 1 "b" 2 }} +``` + +The above produces this data structure: + +```json +{ + "a": 1, + "b": 2 +} +``` + + +Note that the `key` can be either a `string` or a `string slice`. The latter is useful to create a deeply nested structure, e.g.: + +```go-html-template +{{ $m := dict (slice "a" "b" "c") "value" }} +``` + +The above produces this data structure: + +```json +{ + "a": { + "b": { + "c": "value" + } + } +} +``` + +## Pass values to a partial template + +The partial below creates an SVG and expects `fill`, `height` and `width` from the caller: + +### Partial definition + +{{< code file=layouts/partials/svgs/external-links.svg >}} +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" +fill="{{ .fill }}" width="{{ .width }}" height="{{ .height }}" viewBox="0 0 32 32" aria-label="External Link"> +<path d="M25.152 16.576v5.696q0 2.144-1.504 3.648t-3.648 1.504h-14.848q-2.144 0-3.648-1.504t-1.504-3.648v-14.848q0-2.112 1.504-3.616t3.648-1.536h12.576q0.224 0 0.384 0.16t0.16 0.416v1.152q0 0.256-0.16 0.416t-0.384 0.16h-12.576q-1.184 0-2.016 0.832t-0.864 2.016v14.848q0 1.184 0.864 2.016t2.016 0.864h14.848q1.184 0 2.016-0.864t0.832-2.016v-5.696q0-0.256 0.16-0.416t0.416-0.16h1.152q0.256 0 0.416 0.16t0.16 0.416zM32 1.152v9.12q0 0.48-0.352 0.8t-0.8 0.352-0.8-0.352l-3.136-3.136-11.648 11.648q-0.16 0.192-0.416 0.192t-0.384-0.192l-2.048-2.048q-0.192-0.16-0.192-0.384t0.192-0.416l11.648-11.648-3.136-3.136q-0.352-0.352-0.352-0.8t0.352-0.8 0.8-0.352h9.12q0.48 0 0.8 0.352t0.352 0.8z"></path> +</svg> +{{< /code >}} + +### Partial call + +The `fill`, `height` and `width` values can be stored in one object with `dict` and passed to the partial: + +{{< code file=layouts/_default/list.html >}} +{{ partial "svgs/external-links.svg" (dict "fill" "#01589B" "width" 10 "height" 20 ) }} +{{< /code >}} + +[partials]: /templates/partials/ diff --git a/docs/content/en/functions/collections/First.md b/docs/content/en/functions/collections/First.md new file mode 100644 index 000000000..cb2397af1 --- /dev/null +++ b/docs/content/en/functions/collections/First.md @@ -0,0 +1,37 @@ +--- +title: collections.First +description: Returns the given collection, limited to the first N elements. +categories: [] +keywords: [] +action: + aliases: [first] + related: + - functions/collections/After + - functions/collections/Last + - methods/pages/Limit + returnType: any + signatures: [collections.First N COLLECTION] +aliases: [/functions/first] +--- + +```go-html-template +{{ range first 5 .Pages }} + {{ .Render "summary" }} +{{ end }} +``` + +Set `N` to zero to return an empty collection. + +```go-html-template +{{ $emptyPageCollection := first 0 .Pages}} +``` + +Use `first` and [`where`] together. + +```go-html-template +{{ range where .Pages "Section" "articles" | first 5 }} + {{ .Render "summary" }} +{{ end }} +``` + +[`where`]: /functions/collections/where diff --git a/docs/content/en/functions/collections/Group.md b/docs/content/en/functions/collections/Group.md new file mode 100644 index 000000000..2f5a333c0 --- /dev/null +++ b/docs/content/en/functions/collections/Group.md @@ -0,0 +1,31 @@ +--- +title: collections.Group +description: Groups the given page collection by the given key. +categories: [] +keywords: [] +action: + aliases: [group] + related: [] + returnType: any + signatures: [collections.Group KEY PAGES] +aliases: [/functions/group] +--- + +```go-html-template +{{ $new := .Site.RegularPages | first 10 | group "New" }} +{{ $old := .Site.RegularPages | last 10 | group "Old" }} +{{ $groups := slice $new $old }} +{{ range $groups }} + <h3>{{ .Key }}{{/* Prints "New", "Old" */}}</h3> + <ul> + {{ range .Pages }} + <li> + <a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a> + <div class="meta">{{ .Date.Format "Mon, Jan 2, 2006" }}</div> + </li> + {{ end }} + </ul> +{{ end }} +``` + +The page group you get from `group` is of the same type you get from the built-in [group methods](/templates/lists#group-content) in Hugo. The above example can be [paginated](/templates/pagination/#list-paginator-pages). diff --git a/docs/content/en/functions/collections/In.md b/docs/content/en/functions/collections/In.md new file mode 100644 index 000000000..131c0abcf --- /dev/null +++ b/docs/content/en/functions/collections/In.md @@ -0,0 +1,43 @@ +--- +title: collections.In +description: Reports whether the given value is a member of the given set. +categories: [] +keywords: [] +action: + aliases: [in] + related: + - functions/strings/Contains + - functions/strings/ContainsAny + - functions/strings/ContainsNonSpace + - functions/strings/HasPrefix + - functions/strings/HasSuffix + returnType: bool + signatures: [collections.In SET VALUE] +aliases: [/functions/in] +--- + +The `SET` can be an [array], [slice], or [string]. + +[array]: /getting-started/glossary/#array +[slice]: /getting-started/glossary/#slice +[string]: /getting-started/glossary/#string + +```go-html-template +{{ $s := slice "a" "b" "c" }} +{{ in $s "b" }} → true +``` + +```go-html-template +{{ $s := slice 1 2 3 }} +{{ in $s 2 }} → true +``` + +```go-html-template +{{ $s := slice 1.11 2.22 3.33 }} +{{ in $s 2.22 }} → true +``` + +```go-html-template +{{ $s := "abc" }} +{{ in $s "b" }} → true +``` diff --git a/docs/content/en/functions/collections/IndexFunction.md b/docs/content/en/functions/collections/IndexFunction.md new file mode 100644 index 000000000..6482884fd --- /dev/null +++ b/docs/content/en/functions/collections/IndexFunction.md @@ -0,0 +1,95 @@ +--- +title: collections.Index +description: Looks up the index(es) or key(s) of the data structure passed into it. +categories: [] +keywords: [] +action: + aliases: [index] + related: [] + returnType: any + signatures: + - collections.Index COLLECTION INDEXES + - collections.Index COLLECTION KEYS +aliases: [/functions/index,/functions/index-function] +--- + +The `index` functions returns the result of indexing its first argument by the following arguments. Each indexed item must be a map or a slice, e.g.: + +```go-html-template +{{ $slice := slice "a" "b" "c" }} +{{ index $slice 0 }} → a +{{ index $slice 1 }} → b + +{{ $map := dict "a" 100 "b" 200 }} +{{ index $map "b" }} → 200 +``` + +The function takes multiple indices as arguments, and this can be used to get nested values, e.g.: + +```go-html-template +{{ $map := dict "a" 100 "b" 200 "c" (slice 10 20 30) }} +{{ index $map "c" 1 }} → 20 +{{ $map := dict "a" 100 "b" 200 "c" (dict "d" 10 "e" 20) }} +{{ index $map "c" "e" }} → 20 +``` + +You may write multiple indices as a slice: + +```go-html-template +{{ $map := dict "a" 100 "b" 200 "c" (dict "d" 10 "e" 20) }} +{{ $slice := slice "c" "e" }} +{{ index $map $slice }} → 20 +``` + +## Example: load data from a path based on front matter parameters + +Assume you want to add a `location = ""` field to your front matter for every article written in `content/vacations/`. You want to use this field to populate information about the location at the bottom of the article in your `single.html` template. You also have a directory in `data/locations/` that looks like the following: + +```text +data/ + └── locations/ + ├── abilene.toml + ├── chicago.toml + ├── oslo.toml + └── provo.toml +``` + +Here is an example: + +{{< code-toggle file=data/locations/oslo >}} +website = "https://www.oslo.kommune.no" +pop_city = 658390 +pop_metro = 1717900 +{{< /code-toggle >}} + +The example we will use will be an article on Oslo, whose front matter should be set to exactly the same name as the corresponding file name in `data/locations/`: + +{{< code-toggle file=content/articles/oslo.md fm=true >}} +title = "My Norwegian Vacation" +location = "oslo" +{{< /code-toggle >}} + +The content of `oslo.toml` can be accessed from your template using the following node path: `.Site.Data.locations.oslo`. However, the specific file you need is going to change according to the front matter. + +This is where the `index` function is needed. `index` takes 2 arguments in this use case: + +1. The node path +2. A string corresponding to the desired data; e.g.— + +```go-html-template +{{ index .Site.Data.locations "oslo" }} +``` + +The variable for `.Params.location` is a string and can therefore replace `oslo` in the example above: + +```go-html-template +{{ index .Site.Data.locations .Params.location }} +=> map[website:https://www.oslo.kommune.no pop_city:658390 pop_metro:1717900] +``` + +Now the call will return the specific file according to the location specified in the content's front matter, but you will likely want to write specific properties to the template. You can do this by continuing down the node path via dot notation (`.`): + +```go-html-template +{{ (index .Site.Data.locations .Params.location).pop_city }} +=> 658390 +``` diff --git a/docs/content/en/functions/collections/Intersect.md b/docs/content/en/functions/collections/Intersect.md new file mode 100644 index 000000000..8bc60f8e1 --- /dev/null +++ b/docs/content/en/functions/collections/Intersect.md @@ -0,0 +1,30 @@ +--- +title: collections.Intersect +description: Returns the common elements of two arrays or slices, in the same order as the first array. +categories: [] +keywords: [] +action: + aliases: [intersect] + related: + - functions/collections/Complement + - functions/collections/SymDiff + - functions/collections/Union + returnType: any + signatures: [collections.Intersect SET1 SET2] +aliases: [/functions/intersect] +--- + +A useful example is to use it as `AND` filters when combined with where: + +```go-html-template +{{ $pages := where .Site.RegularPages "Type" "not in" (slice "page" "about") }} +{{ $pages := $pages | union (where .Site.RegularPages "Params.pinned" true) }} +{{ $pages := $pages | intersect (where .Site.RegularPages "Params.images" "!=" nil) }} +``` + +The above fetches regular pages not of `page` or `about` type unless they are pinned. And finally, we exclude all pages with no `images` set in Page parameters. + +See [union](/functions/collections/union) for `OR`. + +[partials]: /templates/partials/ +[single]: /templates/single-page-templates/ diff --git a/docs/content/en/functions/collections/IsSet.md b/docs/content/en/functions/collections/IsSet.md new file mode 100644 index 000000000..62b81b712 --- /dev/null +++ b/docs/content/en/functions/collections/IsSet.md @@ -0,0 +1,45 @@ +--- +title: collections.IsSet +description: Reports whether the key exists within the collection. +categories: [] +keywords: [] +action: + aliases: [isset] + related: + - functions/go-template/if + - functions/go-template/with + returnType: bool + signatures: [collections.IsSet COLLECTION KEY] +aliases: [/functions/isset] +--- + +For example, consider this site configuration: + +{{< code-toggle file=hugo >}} +[params] +showHeroImage = false +{{< /code-toggle >}} + +It the value of `showHeroImage` is `true`, we can detect that it exists using either `if` or `with`: + +```go-html-template +{{ if site.Params.showHeroImage }} + {{ site.Params.showHeroImage }} → true +{{ end }} + +{{ with site.Params.showHeroImage }} + {{ . }} → true +{{ end }} +``` + +But if the value of `showHeroImage` is `false`, we can't use either `if` or `with` to detect its existence. In this case, you must use the `isset` function: + +```go-html-template +{{ if isset site.Params "showheroimage" }} + <p>The showHeroImage parameter is set to {{ site.Params.showHeroImage }}.<p> +{{ end }} +``` + +{{% note %}} +When using the `isset` function you must reference the key using lower case. See the previous example. +{{% /note %}} diff --git a/docs/content/en/functions/collections/KeyVals.md b/docs/content/en/functions/collections/KeyVals.md new file mode 100644 index 000000000..3d21ca6fd --- /dev/null +++ b/docs/content/en/functions/collections/KeyVals.md @@ -0,0 +1,43 @@ +--- +title: collections.KeyVals +description: Returns a KeyVals struct. +categories: [] +keywords: [] +action: + aliases: [keyVals] + related: + - methods/pages/Related + returnType: types.KeyValues + signatures: [collections.KeyVals KEY VALUES...] +aliases: [/functions/keyvals] +--- + +The primary application for this function is the definition of the `namedSlices` parameter in the options map passed to the [`Related`] method on the `Pages` object. + +[`Related`]: /methods/pages/related + +See [related content](/content-management/related). + +```go-html-template +{{ $kv := keyVals "foo" "a" "b" "c" }} +``` + +The resulting data structure is: + +```json +{ + "Key": "foo", + "Values": [ + "a", + "b", + "c" + ] +} +``` + +To extract the key and values: + +```go-html-template +{{ $kv.Key }} → foo +{{ $kv.Values }} → [a b c] +``` diff --git a/docs/content/en/functions/collections/Last.md b/docs/content/en/functions/collections/Last.md new file mode 100644 index 000000000..8219e120d --- /dev/null +++ b/docs/content/en/functions/collections/Last.md @@ -0,0 +1,34 @@ +--- +title: collections.Last +description: Returns the given collection, limited to the last N elements. +categories: [] +keywords: [] +action: + aliases: [last] + related: + - functions/collections/After + - functions/collections/First + returnType: any + signatures: [collections.Last N COLLECTION] +aliases: [/functions/last] +--- + +```go-html-template +{{ range last 10 .Pages }} + {{ .Render "summary" }} +{{ end }} +``` + +Set `N` to zero to return an empty collection. + +```go-html-template +{{ $emptyPageCollection := last 0 .Pages}} +``` + +Use `last` and [`where`] together. + +```go-html-template +{{ range where .Pages "Section" "articles" | last 5 }} + {{ .Render "summary" }} +{{ end }} +``` diff --git a/docs/content/en/functions/collections/Merge.md b/docs/content/en/functions/collections/Merge.md new file mode 100644 index 000000000..3f5208cfc --- /dev/null +++ b/docs/content/en/functions/collections/Merge.md @@ -0,0 +1,69 @@ +--- +title: collections.Merge +description: Returns the result of merging two or more maps. +categories: [] +keywords: [] +action: + aliases: [merge] + related: + - functions/collections/Append + returnType: any + signatures: [collections.Merge MAP MAP...] +aliases: [/functions/merge] +--- + +Returns the result of merging two or more maps from left to right. If a key already exists, `merge` updates its value. If a key is absent, `merge` inserts the value under the new key. + +Key handling is case-insensitive. + +The following examples use these map definitions: + +```go-html-template +{{ $m1 := dict "x" "foo" }} +{{ $m2 := dict "x" "bar" "y" "wibble" }} +{{ $m3 := dict "x" "baz" "y" "wobble" "z" (dict "a" "huey") }} +``` + +Example 1 + +```go-html-template +{{ $merged := merge $m1 $m2 $m3 }} + +{{ $merged.x }} → baz +{{ $merged.y }} → wobble +{{ $merged.z.a }} → huey +``` + +Example 2 + +```go-html-template +{{ $merged := merge $m3 $m2 $m1 }} + +{{ $merged.x }} → foo +{{ $merged.y }} → wibble +{{ $merged.z.a }} → huey +``` + +Example 3 + +```go-html-template +{{ $merged := merge $m2 $m3 $m1 }} + +{{ $merged.x }} → foo +{{ $merged.y }} → wobble +{{ $merged.z.a }} → huey +``` + +Example 4 + +```go-html-template +{{ $merged := merge $m1 $m3 $m2 }} + +{{ $merged.x }} → bar +{{ $merged.y }} → wibble +{{ $merged.z.a }} → huey +``` + +{{% note %}} +Regardless of depth, merging only applies to maps. For slices, use [append](/functions/collections/append). +{{% /note %}} diff --git a/docs/content/en/functions/collections/NewScratch.md b/docs/content/en/functions/collections/NewScratch.md new file mode 100644 index 000000000..96f85a8d0 --- /dev/null +++ b/docs/content/en/functions/collections/NewScratch.md @@ -0,0 +1,124 @@ +--- +title: collections.NewScratch +description: Returns a locally scoped "scratch pad" to store and manipulate data. +categories: [] +keywords: [] +action: + aliases: [newScratch] + related: + - methods/page/scratch + - methods/page/store + - methods/shortcode/scratch + returnType: maps.Scratch + signatures: [collections.NewScratch ] +--- + +The `collections.NewScratch` function creates a locally scoped [scratch pad] to store and manipulate data. To create a scratch pad that is attached to a `Page` object, use the [`Scratch`] or [`Store`] method. + +[`Scratch`]: /methods/page/scratch +[`Store`]: /methods/page/store +[scratch pad]: /getting-started/glossary/#scratch-pad + +## Methods + +###### Set + +Sets the value of a given key. + +```go-html-template +{{ $s := newScratch }} +{{ $s.Set "greeting" "Hello" }} +``` + +###### Get + +Gets the value of a given key. + +```go-html-template +{{ $s := newScratch }} +{{ $s.Set "greeting" "Hello" }} +{{ $s.Get "greeting" }} → Hello +``` + +###### Add + +Adds a given value to existing value(s) of the given key. + +For single values, `Add` accepts values that support Go's `+` operator. If the first `Add` for a key is an array or slice, the following adds will be appended to that list. + +```go-html-template +{{ $s := newScratch }} +{{ $s.Set "greeting" "Hello" }} +{{ $s.Add "greeting" "Welcome" }} +{{ $s.Get "greeting" }} → HelloWelcome +``` + +```go-html-template +{{ $s := newScratch }} +{{ $s.Set "total" 3 }} +{{ $s.Add "total" 7 }} +{{ $s.Get "total" }} → 10 +``` + +```go-html-template +{{ $s := newScratch }} +{{ $s.Set "greetings" (slice "Hello") }} +{{ $s.Add "greetings" (slice "Welcome" "Cheers") }} +{{ $s.Get "greetings" }} → [Hello Welcome Cheers] +``` + +###### SetInMap + +Takes a `key`, `mapKey` and `value` and adds a map of `mapKey` and `value` to the given `key`. + +```go-html-template +{{ $s := newScratch }} +{{ $s.SetInMap "greetings" "english" "Hello" }} +{{ $s.SetInMap "greetings" "french" "Bonjour" }} +{{ $s.Get "greetings" }} → map[english:Hello french:Bonjour] +``` + +###### DeleteInMap + +Takes a `key` and `mapKey` and removes the map of `mapKey` from the given `key`. + +```go-html-template +{{ $s := newScratch }} +{{ $s.SetInMap "greetings" "english" "Hello" }} +{{ $s.SetInMap "greetings" "french" "Bonjour" }} +{{ $s.DeleteInMap "greetings" "english" }} +{{ $s.Get "greetings" }} → map[french:Bonjour] +``` + +###### GetSortedMapValues + +Returns an array of values from `key` sorted by `mapKey`. + +```go-html-template +{{ $s := newScratch }} +{{ $s.SetInMap "greetings" "english" "Hello" }} +{{ $s.SetInMap "greetings" "french" "Bonjour" }} +{{ $s.GetSortedMapValues "greetings" }} → [Hello Bonjour] +``` + +###### Delete + +Removes the given key. + +```go-html-template +{{ $s := newScratch }} +{{ $s.Set "greeting" "Hello" }} +{{ $s.Delete "greeting" }} +``` + +###### Values + +Returns the raw backing map. Do not use with `Scratch` or `Store` methods on a `Page` object due to concurrency issues. + +```go-html-template +{{ $s := newScratch }} +{{ $s.SetInMap "greetings" "english" "Hello" }} +{{ $s.SetInMap "greetings" "french" "Bonjour" }} + +{{ $map := $s.Values }} +``` diff --git a/docs/content/en/functions/collections/Querify.md b/docs/content/en/functions/collections/Querify.md new file mode 100644 index 000000000..ea0434fc5 --- /dev/null +++ b/docs/content/en/functions/collections/Querify.md @@ -0,0 +1,32 @@ +--- +title: collections.Querify +description: Takes a set or slice of key-value pairs and returns a query string to be appended to URLs. +categories: [] +keywords: [] +action: + aliases: [querify] + related: + - functions/go-template/urlquery.md + returnType: string + signatures: + - collections.Querify VALUE [VALUE...] + - collections.Querify COLLECTION +aliases: [/functions/querify] +--- + +`querify` takes a set or slice of key-value pairs and returns a [query string](https://en.wikipedia.org/wiki/Query_string) that can be appended to a URL. + +The following examples create a link to a search results page on Google. + +```go-html-template +<a href="https://www.google.com?{{ (querify "q" "test" "page" 3) | safeURL }}">Search</a> + +{{ $qs := slice "q" "test" "page" 3 }} +<a href="https://www.google.com?{{ (querify $qs) | safeURL }}">Search</a> +``` + +Both of these examples render the following HTML: + +```html +<a href="https://www.google.com?page=3&q=test">Search</a> +``` diff --git a/docs/content/en/functions/collections/Reverse.md b/docs/content/en/functions/collections/Reverse.md new file mode 100644 index 000000000..d0a449763 --- /dev/null +++ b/docs/content/en/functions/collections/Reverse.md @@ -0,0 +1,19 @@ +--- +title: collections.Reverse +description: Reverses the order of a collection. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/collections/Sort + - functions/collections/Shuffle + - functions/collections/Uniq + returnType: any + signatures: [collections.Reverse COLLECTION] +aliases: [/functions/collections.reverse] +--- + +```go-html-template +{{ slice 2 1 3 | collections.Reverse }} → [3 1 2] +``` diff --git a/docs/content/en/functions/collections/Seq.md b/docs/content/en/functions/collections/Seq.md new file mode 100644 index 000000000..b572bd7c0 --- /dev/null +++ b/docs/content/en/functions/collections/Seq.md @@ -0,0 +1,36 @@ +--- +title: collections.Seq +description: Returns a slice of integers. +categories: [] +keywords: [] +action: + aliases: [seq] + related: [] + returnType: '[]int' + signatures: + - collections.Seq LAST + - collections.Seq FIRST LAST + - collections.Seq FIRST INCREMENT LAST +aliases: [/functions/seq] +--- + +```go-html-template +{{ seq 2 }} → [1 2] +{{ seq 0 2 }} → [0 1 2] +{{ seq -2 2 }} → [-2 -1 0 1 2] +{{ seq -2 2 2 }} → [-2 0 2] +``` + +A contrived example of iterating over a sequence of integers: + +```go-html-template +{{ $product := 1 }} +{{ range seq 4 }} + {{ $product = mul $product . }} +{{ end }} +{{ $product }} → 24 +``` + +{{% note %}} +The slice created by the `seq` function is limited to 2000 elements. +{{% /note %}} diff --git a/docs/content/en/functions/collections/Shuffle.md b/docs/content/en/functions/collections/Shuffle.md new file mode 100644 index 000000000..0f28eb4d8 --- /dev/null +++ b/docs/content/en/functions/collections/Shuffle.md @@ -0,0 +1,22 @@ +--- +title: collections.Shuffle +description: Returns a random permutation of a given array or slice. +categories: [] +keywords: [] +action: + aliases: [shuffle] + related: + - functions/collections/Reverse + - functions/collections/Sort + - functions/collections/Uniq + returnType: any + signatures: [collections.Shuffle COLLECTION] +aliases: [/functions/shuffle] +--- + +```go-html-template +{{ shuffle (seq 1 2 3) }} → [3 1 2] +{{ shuffle (slice "a" "b" "c") }} → [b a c] +``` + +The result will vary from one build to the next. diff --git a/docs/content/en/functions/collections/Slice.md b/docs/content/en/functions/collections/Slice.md new file mode 100644 index 000000000..56c068d4b --- /dev/null +++ b/docs/content/en/functions/collections/Slice.md @@ -0,0 +1,18 @@ +--- +title: collections.Slice +description: Creates a slice of all passed arguments. +categories: [] +keywords: [] +action: + aliases: [slice] + related: + - functions/collections/Dictionary + returnType: any + signatures: [collections.Slice ITEM...] +aliases: [/functions/slice] +--- + +```go-html-template +{{ $s := slice "a" "b" "c" }} +{{ $s }} → [a b c] +``` diff --git a/docs/content/en/functions/collections/Sort.md b/docs/content/en/functions/collections/Sort.md new file mode 100644 index 000000000..2277f883c --- /dev/null +++ b/docs/content/en/functions/collections/Sort.md @@ -0,0 +1,156 @@ +--- +title: collections.Sort +description: Sorts slices, maps, and page collections. +categories: [] +keywords: [] +action: + aliases: [sort] + related: + - functions/collections/Reverse + - functions/collections/Shuffle + - functions/collections/Uniq + returnType: any + signatures: ['collections.Sort COLLECTION [KEY] [ORDER]'] +toc: true +aliases: [/functions/sort] +--- + +The `KEY` is optional when sorting slices in ascending order, otherwise it is required. When sorting slices, use the literal `value` in place of the `KEY`. See examples below. + +The `ORDER` may be either `asc` (ascending) or `desc` (descending). The default sort order is ascending. + +## Sort a slice + +The examples below assume this site configuration: + +{{< code-toggle file=hugo >}} +[params] +grades = ['b','a','c'] +{{< /code-toggle >}} + +### Ascending order {#slice-ascending-order} + +Sort slice elements in ascending order using either of these constructs: + +```go-html-template +{{ sort site.Params.grades }} → [a b c] +{{ sort site.Params.grades "value" "asc" }} → [a b c] +``` + +In the examples above, `value` is the `KEY` representing the value of the slice element. + +### Descending order {#slice-descending-order} + +Sort slice elements in descending order: + +```go-html-template +{{ sort site.Params.grades "value" "desc" }} → [c b a] +``` + +In the example above, `value` is the `KEY` representing the value of the slice element. + +## Sort a map + +The examples below assume this site configuration: + +{{< code-toggle file=hugo >}} +[params.authors.a] +firstName = "Marius" +lastName = "Pontmercy" +[params.authors.b] +firstName = "Victor" +lastName = "Hugo" +[params.authors.c] +firstName = "Jean" +lastName = "Valjean" +{{< /code-toggle >}} + +{{% note %}} +When sorting maps, the `KEY` argument must be lowercase. +{{% /note %}} + +### Ascending order {#map-ascending-order} + +Sort map objects in ascending order using either of these constructs: + +```go-html-template +{{ range sort site.Params.authors "firstname" }} + {{ .firstName }} +{{ end }} + +{{ range sort site.Params.authors "firstname" "asc" }} + {{ .firstName }} +{{ end }} +``` + +These produce: + +```text +Jean Marius Victor +``` + +### Descending order {#map-descending-order} + +Sort map objects in descending order: + +```go-html-template +{{ range sort site.Params.authors "firstname" "desc" }} + {{ .firstName }} +{{ end }} +``` + +This produces: + +```text +Victor Marius Jean +``` + +### First level key removal + +Hugo removes the first level keys when sorting a map. + +Original map: + +```json +{ + "felix": { + "breed": "malicious", + "type": "cat" + }, + "spot": { + "breed": "boxer", + "type": "dog" + } +} +``` + +After sorting: + +```json +[ + { + "breed": "malicious", + "type": "cat" + }, + { + "breed": "boxer", + "type": "dog" + } +] +``` + +## Sort a page collection + +{{% note %}} +Although you can use the `sort` function to sort a page collection, Hugo provides [sorting and grouping methods] as well. + +[sorting and grouping methods]: /methods/pages +{{% /note %}} + +In this contrived example, sort the site's regular pages by `.Type` in descending order: + +```go-html-template +{{ range sort site.RegularPages "Type" "desc" }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +``` diff --git a/docs/content/en/functions/collections/SymDiff.md b/docs/content/en/functions/collections/SymDiff.md new file mode 100644 index 000000000..7eba3ef42 --- /dev/null +++ b/docs/content/en/functions/collections/SymDiff.md @@ -0,0 +1,24 @@ +--- +title: collections.SymDiff +description: Returns the symmetric difference of two collections. +categories: [] +keywords: [] +action: + aliases: [symdiff] + related: + - functions/collections/Complement + - functions/collections/Intersect + - functions/collections/SymDiff + - functions/collections/Union + returnType: any + signatures: [COLLECTION | collections.SymDiff COLLECTION] +aliases: [/functions/symdiff] +--- + +Example: + +```go-html-template +{{ slice 1 2 3 | symdiff (slice 3 4) }} → [1 2 4] +``` + +Also see <https://en.wikipedia.org/wiki/Symmetric_difference>. diff --git a/docs/content/en/functions/collections/Union.md b/docs/content/en/functions/collections/Union.md new file mode 100644 index 000000000..7fed49a10 --- /dev/null +++ b/docs/content/en/functions/collections/Union.md @@ -0,0 +1,46 @@ +--- +title: collections.Union +description: Given two arrays or slices, returns a new array that contains the elements that belong to either or both arrays/slices. +categories: [] +keywords: [] +action: + aliases: [union] + related: + - functions/collections/Complement + - functions/collections/Intersect + - functions/collections/SymDiff + - functions/collections/Union + returnType: any + signatures: [collections.Union SET1 SET2] +aliases: [/functions/union] +--- + +Given two arrays (or slices) A and B, this function will return a new array that contains the elements or objects that belong to either A or to B or to both. + +```go-html-template +{{ union (slice 1 2 3) (slice 3 4 5) }} +<!-- returns [1 2 3 4 5] --> + +{{ union (slice 1 2 3) nil }} +<!-- returns [1 2 3] --> + +{{ union nil (slice 1 2 3) }} +<!-- returns [1 2 3] --> + +{{ union nil nil }} +<!-- returns an error because both arrays/slices have to be of the same type --> +``` + +## OR filter in where query + +This is also very useful to use as `OR` filters when combined with where: + +```go-html-template +{{ $pages := where .Site.RegularPages "Type" "not in" (slice "page" "about") }} +{{ $pages = $pages | union (where .Site.RegularPages "Params.pinned" true) }} +{{ $pages = $pages | intersect (where .Site.RegularPages "Params.images" "!=" nil) }} +``` + +The above fetches regular pages not of `page` or `about` type unless they are pinned. And finally, we exclude all pages with no `images` set in Page parameters. + +See [intersect](/functions/collections/intersect) for `AND`. diff --git a/docs/content/en/functions/collections/Uniq.md b/docs/content/en/functions/collections/Uniq.md new file mode 100644 index 000000000..02b590c18 --- /dev/null +++ b/docs/content/en/functions/collections/Uniq.md @@ -0,0 +1,20 @@ +--- +title: collections.Uniq +description: Returns the given collection, removing duplicate elements. +categories: [] +keywords: [] +action: + aliases: [uniq] + related: + - functions/collections/Reverse + - functions/collections/Shuffle + - functions/collections/Sort + - functions/collections/Uniq + returnType: any + signatures: [collections.Uniq COLLECTION] +aliases: [/functions/uniq] +--- + +```go-html-template +{{ slice 1 3 2 1 | uniq }} → [1 3 2] +``` diff --git a/docs/content/en/functions/collections/Where.md b/docs/content/en/functions/collections/Where.md new file mode 100644 index 000000000..f18ae507b --- /dev/null +++ b/docs/content/en/functions/collections/Where.md @@ -0,0 +1,446 @@ +--- +title: collections.Where +description: Returns the given collection, removing elements that do not satisfy the comparison condition. +categories: [] +keywords: [] +action: + aliases: [where] + related: [] + returnType: any + signatures: ['collections.Where COLLECTION KEY [OPERATOR] VALUE'] +toc: true +aliases: [/functions/where] +--- + +The `where` function returns the given collection, removing elements that do not satisfy the comparison condition. The comparison condition is comprised of the `KEY`, `OPERATOR`, and `VALUE` arguments: + +```text +collections.Where COLLECTION KEY [OPERATOR] VALUE + -------------------- + comparison condition +``` + +Hugo will test for equality if you do not provide an `OPERATOR` argument. For example: + +```go-html-template +{{ $pages := where .Site.RegularPages "Section" "books" }} +{{ $books := where .Site.Data.books "genres" "suspense" }} +``` + +## Arguments + +The where function takes three or four arguments. The `OPERATOR` argument is optional. + +COLLECTION +: (`any`) A [page collection] or a [slice] of [maps]. + +[maps]: /getting-started/glossary/#map +[page collection]: /getting-started/glossary/#page-collection +[slice]: /getting-started/glossary/#slice + +KEY +: (`string`) The key of the page or map value to compare with `VALUE`. With page collections, commonly used comparison keys are `Section`, `Type`, and `Params`. To compare with a member of the page `Params` map, [chain] the subkey as shown below: + +```go-html-template +{{ $result := where .Site.RegularPages "Params.foo" "bar" }} +``` + +[chain]: /getting-started/glossary/#chain + +OPERATOR +: (`string`) The logical comparison [operator](#operators). + +VALUE +: (`any`) The value with which to compare. The values to compare must have comparable data types. For example: + +Comparison|Result +:--|:-- +`"123" "eq" "123"`|`true` +`"123" "eq" 123`|`false` +`false "eq" "false"`|`false` +`false "eq" false`|`true` + +When one or both of the values to compare is a slice, use the `in`, `not in`, or `intersect` operators as described below. + +## Operators + +Use any of the following logical operators: + +`=`, `==`, `eq` +: (`bool`) Reports whether the given field value is equal to `VALUE`. + +`!=`, `<>`, `ne` +: (`bool`) Reports whether the given field value is not equal to `VALUE`. + +`>=`, `ge` +: (`bool`) Reports whether the given field value is greater than or equal to `VALUE`. + +`>`, `gt` +: `true` Reports whether the given field value is greater than `VALUE`. + +`<=`, `le` +: (`bool`) Reports whether the given field value is less than or equal to `VALUE`. + +`<`, `lt` +: (`bool`) Reports whether the given field value is less than `VALUE`. + +`in` +: (`bool`) Reports whether the given field value is a member of `VALUE`. Compare string to slice, or string to string. See [details](/functions/collections/in). + +`not in` +: (`bool`) Reports whether the given field value is not a member of `VALUE`. Compare string to slice, or string to string. See [details](/functions/collections/in). + +`intersect` +: (`bool`) Reports whether the given field value (a slice) contains one or more elements in common with `VALUE`. See [details](/functions/collections/intersect). + +`like` {{< new-in 0.116.0 >}} +: (`bool`) Reports whether the given field value matches the regular expression specified in `VALUE`. Use the `like` operator to compare `string` values. The `like` operator returns `false` when comparing other data types to the regular expression. + +{{% note %}} +The examples below perform comparisons within a page collection, but the same comparisons are applicable to a slice of maps. +{{% /note %}} + +## String comparison + +Compare the value of the given field to a [`string`]: + +[`string`]: /getting-started/glossary/#string + +```go-html-template +{{ $pages := where .Site.RegularPages "Section" "eq" "books" }} +{{ $pages := where .Site.RegularPages "Section" "ne" "books" }} +``` + +## Numeric comparison + +Compare the value of the given field to an [`int`] or [`float`]: + +[`int`]: /getting-started/glossary/#int +[`float`]: /getting-started/glossary/#float + +```go-html-template +{{ $books := where site.RegularPages "Section" "eq" "books" }} + +{{ $pages := where $books "Params.price" "eq" 42 }} +{{ $pages := where $books "Params.price" "ne" 42.67 }} +{{ $pages := where $books "Params.price" "ge" 42 }} +{{ $pages := where $books "Params.price" "gt" 42.67 }} +{{ $pages := where $books "Params.price" "le" 42 }} +{{ $pages := where $books "Params.price" "lt" 42.67 }} +``` + +## Boolean comparison + +Compare the value of the given field to a [`bool`]: + +[`bool`]: /getting-started/glossary/#bool + +```go-html-template +{{ $books := where site.RegularPages "Section" "eq" "books" }} + +{{ $pages := where $books "Params.fiction" "eq" true }} +{{ $pages := where $books "Params.fiction" "eq" false }} +{{ $pages := where $books "Params.fiction" "ne" true }} +{{ $pages := where $books "Params.fiction" "ne" false }} +``` + +## Member comparison + +Compare a [`scalar`] to a [`slice`]. + +[`scalar`]: /getting-started/glossary/#scalar +[`slice`]: /getting-started/glossary/#slice + +For example, to return a collection of pages where the `color` page parameter is either "red" or "yellow": + +```go-html-template +{{ $fruit := where site.RegularPages "Section" "eq" "fruit" }} + +{{ $colors := slice "red" "yellow" }} +{{ $pages := where $fruit "Params.color" "in" $colors }} +``` + +To return a collection of pages where the "color" page parameter is neither "red" nor "yellow": + +```go-html-template +{{ $fruit := where site.RegularPages "Section" "eq" "fruit" }} + +{{ $colors := slice "red" "yellow" }} +{{ $pages := where $fruit "Params.color" "not in" $colors }} +``` + +## Intersection comparison + +Compare a [`slice`] to a [`slice`], returning collection elements with common values. This is frequently used when comparing taxonomy terms. + +For example, to return a collection of pages where any of the terms in the "genres" taxonomy are "suspense" or "romance": + +```go-html-template +{{ $books := where site.RegularPages "Section" "eq" "books" }} + +{{ $genres := slice "suspense" "romance" }} +{{ $pages := where $books "Params.genres" "intersect" $genres }} +``` + +## Regular expression comparison + +{{< new-in 0.116.0 >}} + +To return a collection of pages where the "author" page parameter begins with either "victor" or "Victor": + +```go-html-template +{{ $pages := where .Site.RegularPages "Params.author" "like" `(?i)^victor` }} +``` + +{{% include "functions/_common/regular-expressions.md" %}} + +{{% note %}} +Use the `like` operator to compare string values. Comparing other data types will result in an empty collection. +{{% /note %}} + +## Date comparison + +### Predefined dates + +There are four predefined front matter dates: [`date`], [`publishDate`], [`lastmod`], and [`expiryDate`]. Regardless of the front matter data format (TOML, YAML, or JSON) these are [`time.Time`] values, allowing precise comparisons. + +[`date`]: /methods/page/date +[`publishdate`]: /methods/page/publishdate +[`lastmod`]: /methods/page/lastmod +[`expirydate`]: /methods/page/expirydate +[`time.Time`]: https://pkg.go.dev/time#Time + +For example, to return a collection of pages that were created before the current year: + +```go-html-template +{{ $startOfYear := time.AsTime (printf "%d-01-01" now.Year) }} +{{ $pages := where .Site.RegularPages "Date" "lt" $startOfYear }} +``` + +### Custom dates + +With custom front matter dates, the comparison depends on the front matter data format (TOML, YAML, or JSON). + +{{% note %}} +Using TOML for pages with custom front matter dates enables precise date comparisons. +{{% /note %}} + +With TOML, date values are first-class citizens. TOML has a date data type while JSON and YAML do not. If you quote a TOML date, it is a string. If you do not quote a TOML date value, it is [`time.Time`] value, enabling precise comparisons. + +In the TOML example below, note that the event date is not quoted. + +{{< code file="content/events/2024-user-conference.md" >}} ++++ +title = '2024 User Conference" +eventDate = 2024-04-01 ++++ +{{< /code >}} + +To return a collection of future events: + +```go-html-template +{{ $events := where .Site.RegularPages "Type" "events" }} +{{ $futureEvents := where $events "Params.eventDate" "gt" now }} +``` + +When working with YAML or JSON, or quoted TOML values, custom dates are strings; you cannot compare them with `time.Time` values. String comparisons may be possible if the custom date layout is consistent from one page to the next. However, to be safe, filter the pages by ranging through the collection: + +```go-html-template +{{ $events := where .Site.RegularPages "Type" "events" }} +{{ $futureEvents := slice }} +{{ range $events }} + {{ if gt (time.AsTime .Params.eventDate) now }} + {{ $futureEvents = $futureEvents | append . }} + {{ end }} +{{ end }} +``` + +## Nil comparison + +To return a collection of pages where the "color" parameter is present in front matter, compare to `nil`: + +```go-html-template +{{ $pages := where .Site.RegularPages "Params.color" "ne" nil }} +``` + +To return a collection of pages where the "color" parameter is not present in front matter, compare to `nil`: + +```go-html-template +{{ $pages := where .Site.RegularPages "Params.color" "eq" nil }} +``` + +In both examples above, note that `nil` is not quoted. + +## Nested comparison + +These are equivalent: + +```go-html-template +{{ $pages := where .Site.RegularPages "Type" "tutorials" }} +{{ $pages = where $pages "Params.level" "eq" "beginner" }} +``` + +```go-html-template +{{ $pages := where (where .Site.RegularPages "Type" "tutorials") "Params.level" "eq" "beginner" }} +``` + +## Portable section comparison + +Useful for theme authors, avoid hardcoding section names by using the `where` function with the [`MainSections`] method on a `Site` object. + +[`MainSections`]: /methods/site/mainsections + +```go-html-template +{{ $pages := where .Site.RegularPages "Section" "in" .Site.MainSections }} +``` + +With this construct, a theme author can instruct users to specify their main sections in the site configuration: + +{{< code-toggle file=hugo >}} +[params] +mainSections = ['blog','galleries'] +{{< /code-toggle >}} + +If `params.mainSections` is not defined in the site configuration, the `MainSections` method returns a slice with one element---the top level section with the most pages. + +## Boolean/undefined comparison + +Consider this site content: + +```text +content/ +├── posts/ +│ ├── _index.md +│ ├── post-1.md <-- front matter: exclude = false +│ ├── post-2.md <-- front matter: exclude = true +│ └── post-3.md <-- front matter: exclude not defined +└── _index.md +``` + +The first two pages have an "exclude" field in front matter, but the last page does not. When testing for _equality_, the third page is _excluded_ from the result. When testing for _inequality_, the third page is _included_ in the result. + +### Equality test + +This template: + +```go-html-template +<ul> + {{ range where .Site.RegularPages "Params.exclude" "eq" false }} + <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li> + {{ end }} +</ul> +``` + +Is rendered to: + +```html +<ul> + <li><a href="/posts/post-1/">Post 1</a></li> +</ul> +``` + +This template: + +```go-html-template +<ul> + {{ range where .Site.RegularPages "Params.exclude" "eq" true }} + <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li> + {{ end }} +</ul> +``` + +Is rendered to: + +```html +<ul> + <li><a href="/posts/post-2/">Post 2</a></li> +</ul> +``` + +### Inequality test + +This template: + +```go-html-template +<ul> + {{ range where .Site.RegularPages "Params.exclude" "ne" false }} + <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li> + {{ end }} +</ul> +``` + +Is rendered to: + +```html +<ul> + <li><a href="/posts/post-2/">Post 2</a></li> + <li><a href="/posts/post-3/">Post 3</a></li> +</ul> +``` + +This template: + +```go-html-template +<ul> + {{ range where .Site.RegularPages "Params.exclude" "ne" true }} + <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li> + {{ end }} +</ul> +``` + +Is rendered to: + +```html +<ul> + <li><a href="/posts/post-1/">Post 1</a></li> + <li><a href="/posts/post-3/">Post 3</a></li> +</ul> +``` + +To exclude a page with an undefined field from a boolean _inequality_ test: + +1. Create a collection using a boolean comparison +2. Create a collection using a nil comparison +3. Subtract the second collection from the first collection using the [`collections.Complement`] function. + +[`collections.Complement`]: /functions/collections/complement + +This template: + +```go-html-template +{{ $p1 := where .Site.RegularPages "Params.exclude" "ne" true }} +{{ $p2 := where .Site.RegularPages "Params.exclude" "eq" nil }} +<ul> + {{ range $p1 | complement $p2 }} + <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li> + {{ end }} +</ul> +``` + +Is rendered to: + +```html +<ul> + <li><a href="/posts/post-1/">Post 1</a></li> +</ul> +``` + +This template: + +```go-html-template +{{ $p1 := where .Site.RegularPages "Params.exclude" "ne" false }} +{{ $p2 := where .Site.RegularPages "Params.exclude" "eq" nil }} +<ul> + {{ range $p1 | complement $p2 }} + <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li> + {{ end }} +</ul> +``` + +Is rendered to: + +```html +<ul> + <li><a href="/posts/post-1/">Post 2</a></li> +</ul> +``` diff --git a/docs/content/en/functions/collections/_index.md b/docs/content/en/functions/collections/_index.md new file mode 100644 index 000000000..51981f79b --- /dev/null +++ b/docs/content/en/functions/collections/_index.md @@ -0,0 +1,12 @@ +--- +title: Collections functions +linkTitle: collections +description: Template functions to work with arrays, slices, maps, and page collections. +categories: [] +keywords: [] +menu: + docs: + parent: functions +--- + +Use these functions to work with arrays, slices, maps, and page collections. diff --git a/docs/content/en/functions/compare/Conditional.md b/docs/content/en/functions/compare/Conditional.md new file mode 100644 index 000000000..6d693770d --- /dev/null +++ b/docs/content/en/functions/compare/Conditional.md @@ -0,0 +1,41 @@ +--- +title: compare.Conditional +description: Returns one of two arguments depending on the value of the control argument. +categories: [] +keywords: [] +action: + aliases: [cond] + related: + - functions/compare/Default + returnType: any + signatures: [compare.Conditional CONTROL ARG1 ARG2] +aliases: [/functions/cond] +--- + +The CONTROL argument is a boolean value that indicates whether the function should return ARG1 or ARG2. If CONTROL is `true`, the function returns ARG1. Otherwise, the function returns ARG2. + +```go-html-template +{{ $qty := 42 }} +{{ cond (le $qty 3) "few" "many" }} → many +``` + +The CONTROL argument must be either `true` or `false`. To cast a non-boolean value to boolean, pass it through the `not` operator twice. + +```go-html-template +{{ cond (42 | not | not) "truthy" "falsy" }} → truthy +{{ cond ("" | not | not) "truthy" "falsy" }} → falsy +``` + +{{% note %}} +Unlike [ternary operators] in other languages, the `cond` function does not perform [short-circuit evaluation]. The function evaluates both ARG1 and ARG2, regardless of the CONTROL value. + +[short-circuit evaluation]: https://en.wikipedia.org/wiki/Short-circuit_evaluation +[ternary operators]: https://en.wikipedia.org/wiki/Ternary_conditional_operator +{{% /note %}} + +Due to the absence of short-circuit evaluation, these examples throw an error: + +```go-html-template +{{ cond true "true" (div 1 0) }} +{{ cond false (div 1 0) "false" }} +``` diff --git a/docs/content/en/functions/compare/Default.md b/docs/content/en/functions/compare/Default.md new file mode 100644 index 000000000..1e6bd7968 --- /dev/null +++ b/docs/content/en/functions/compare/Default.md @@ -0,0 +1,48 @@ +--- +title: compare.Default +description: Returns the second argument if set, else the first argument. +keywords: [] +action: + aliases: [default] + related: + - functions/compare/Conditional + - functions/go-template/Or + returnType: any + signatures: [compare.Default DEFAULT INPUT] +aliases: [/functions/default] +--- + +The `default` function returns the second argument if set, else the first argument. + +{{% note %}} +When the second argument is the boolean `false` value, the `default` function returns `false`. All _other_ falsy values are considered unset. + +{{% include "functions/go-template/_common/truthy-falsy.md" %}} + +To set a default value based on truthiness, use the [`or`] operator instead. + +[`or`]: /functions/go-template/or +{{% /note %}} + +The `default` function returns the second argument if set: + +```go-html-template +{{ default 42 1 }} → 1 +{{ default 42 "foo" }} → foo +{{ default 42 (dict "k" "v") }} → map[k:v] +{{ default 42 (slice "a" "b") }} → [a b] +{{ default 42 true }} → true + +<!-- As noted above, the boolean "false" is considered set --> +{{ default 42 false }} → false +``` + +The `default` function returns the first argument if the second argument is not set: + +```go-html-template +{{ default 42 0 }} → 42 +{{ default 42 "" }} → 42 +{{ default 42 dict }} → 42 +{{ default 42 slice }} → 42 +{{ default 42 <nil> }} → 42 +``` diff --git a/docs/content/en/functions/compare/Eq.md b/docs/content/en/functions/compare/Eq.md new file mode 100644 index 000000000..49350e676 --- /dev/null +++ b/docs/content/en/functions/compare/Eq.md @@ -0,0 +1,27 @@ +--- +title: compare.Eq +description: Returns the boolean truth of arg1 == arg2 || arg1 == arg3. +categories: [] +keywords: [] +action: + aliases: [eq] + related: + - functions/compare/Ge + - functions/compare/Gt + - functions/compare/Le + - functions/compare/Lt + - functions/compare/Ne + returnType: bool + signatures: ['compare.Eq ARG1 ARG2 [ARG...]'] +aliases: [/functions/eq] +--- + +```go-html-template +{{ eq 1 1 }} → true +{{ eq 1 2 }} → false + +{{ eq 1 1 1 }} → true +{{ eq 1 1 2 }} → true +{{ eq 1 2 1 }} → true +{{ eq 1 2 2 }} → false +``` diff --git a/docs/content/en/functions/compare/Ge.md b/docs/content/en/functions/compare/Ge.md new file mode 100644 index 000000000..479ecf990 --- /dev/null +++ b/docs/content/en/functions/compare/Ge.md @@ -0,0 +1,32 @@ +--- +title: compare.Ge +description: Returns the boolean truth of arg1 >= arg2 && arg1 >= arg3. +categories: [] +keywords: [] +action: + aliases: [ge] + related: + - functions/compare/Eq + - functions/compare/Gt + - functions/compare/Le + - functions/compare/Lt + - functions/compare/Ne + returnType: bool + signatures: ['compare.Ge ARG1 ARG2 [ARG...]'] +aliases: [/functions/ge] +--- + +```go-html-template +{{ ge 1 1 }} → true +{{ ge 1 2 }} → false +{{ ge 2 1 }} → true + +{{ ge 1 1 1 }} → true +{{ ge 1 1 2 }} → false +{{ ge 1 2 1 }} → false +{{ ge 1 2 2 }} → false + +{{ ge 2 1 1 }} → true +{{ ge 2 1 2 }} → true +{{ ge 2 2 1 }} → true +``` diff --git a/docs/content/en/functions/compare/Gt.md b/docs/content/en/functions/compare/Gt.md new file mode 100644 index 000000000..0af289ce2 --- /dev/null +++ b/docs/content/en/functions/compare/Gt.md @@ -0,0 +1,32 @@ +--- +title: compare.Gt +description: Returns the boolean truth of arg1 > arg2 && arg1 > arg3. +categories: [] +keywords: [] +action: + aliases: [gt] + related: + - functions/compare/Eq + - functions/compare/Ge + - functions/compare/Le + - functions/compare/Lt + - functions/compare/Ne + returnType: bool + signatures: ['compare.Gt ARG1 ARG2 [ARG...]'] +aliases: [/functions/gt] +--- + +```go-html-template +{{ gt 1 1 }} → false +{{ gt 1 2 }} → false +{{ gt 2 1 }} → true + +{{ gt 1 1 1 }} → false +{{ gt 1 1 2 }} → false +{{ gt 1 2 1 }} → false +{{ gt 1 2 2 }} → false + +{{ gt 2 1 1 }} → true +{{ gt 2 1 2 }} → false +{{ gt 2 2 1 }} → false +``` diff --git a/docs/content/en/functions/compare/Le.md b/docs/content/en/functions/compare/Le.md new file mode 100644 index 000000000..319d376f6 --- /dev/null +++ b/docs/content/en/functions/compare/Le.md @@ -0,0 +1,32 @@ +--- +title: compare.Le +description: Returns the boolean truth of arg1 <= arg2 && arg1 <= arg3. +categories: [] +keywords: [] +action: + aliases: [le] + related: + - functions/compare/Eq + - functions/compare/Ge + - functions/compare/Gt + - functions/compare/Lt + - functions/compare/Ne + returnType: bool + signatures: ['compare.Le ARG1 ARG2 [ARG...]'] +aliases: [/functions/le] +--- + +```go-html-template +{{ le 1 1 }} → true +{{ le 1 2 }} → true +{{ le 2 1 }} → false + +{{ le 1 1 1 }} → true +{{ le 1 1 2 }} → true +{{ le 1 2 1 }} → true +{{ le 1 2 2 }} → true + +{{ le 2 1 1 }} → false +{{ le 2 1 2 }} → false +{{ le 2 2 1 }} → false +``` diff --git a/docs/content/en/functions/compare/Lt.md b/docs/content/en/functions/compare/Lt.md new file mode 100644 index 000000000..3fe8f1d2c --- /dev/null +++ b/docs/content/en/functions/compare/Lt.md @@ -0,0 +1,32 @@ +--- +title: compare.Lt +description: Returns the boolean truth of arg1 < arg2 && arg1 < arg3. +categories: [] +keywords: [] +action: + aliases: [lt] + related: + - functions/compare/Eq + - functions/compare/Ge + - functions/compare/Gt + - functions/compare/Le + - functions/compare/Ne + returnType: bool + signatures: ['compare.Lt ARG1 ARG2 [ARG...]'] +aliases: [/functions/lt] +--- + +```go-html-template +{{ lt 1 1 }} → false +{{ lt 1 2 }} → true +{{ lt 2 1 }} → false + +{{ lt 1 1 1 }} → false +{{ lt 1 1 2 }} → false +{{ lt 1 2 1 }} → false +{{ lt 1 2 2 }} → true + +{{ lt 2 1 1 }} → false +{{ lt 2 1 2 }} → false +{{ lt 2 2 1 }} → false +``` diff --git a/docs/content/en/functions/compare/Ne.md b/docs/content/en/functions/compare/Ne.md new file mode 100644 index 000000000..2d9f826fc --- /dev/null +++ b/docs/content/en/functions/compare/Ne.md @@ -0,0 +1,27 @@ +--- +title: compare.Ne +description: Returns the boolean truth of arg1 != arg2 && arg1 != arg3. +categories: [] +keywords: [] +action: + aliases: [ne] + related: + - functions/compare/Eq + - functions/compare/Ge + - functions/compare/Gt + - functions/compare/Le + - functions/compare/Lt + returnType: bool + signatures: ['compare.Ne ARG1 ARG2 [ARG...]'] +aliases: [/functions/ne] +--- + +```go-html-template +{{ ne 1 1 }} → false +{{ ne 1 2 }} → true + +{{ ne 1 1 1 }} → false +{{ ne 1 1 2 }} → false +{{ ne 1 2 1 }} → false +{{ ne 1 2 2 }} → true +``` diff --git a/docs/content/en/functions/compare/_index.md b/docs/content/en/functions/compare/_index.md new file mode 100644 index 000000000..a9b3a7b27 --- /dev/null +++ b/docs/content/en/functions/compare/_index.md @@ -0,0 +1,12 @@ +--- +title: Compare functions +linkTitle: compare +description: Template functions to compare two or more values. +categories: [] +keywords: [] +menu: + docs: + parent: functions +--- + +Use these functions to compare two or more values. diff --git a/docs/content/en/functions/crypto/FNV32a.md b/docs/content/en/functions/crypto/FNV32a.md new file mode 100644 index 000000000..eda303e62 --- /dev/null +++ b/docs/content/en/functions/crypto/FNV32a.md @@ -0,0 +1,22 @@ +--- +title: crypto.FNV32a +description: Returns the FNV (Fowler–Noll–Vo) 32-bit hash of a given string. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/crypto/HMAC + - functions/crypto/MD5 + - functions/crypto/SHA1 + - functions/crypto/SHA256 + returnType: int + signatures: [crypto.FNV32a STRING] +aliases: [/functions/crypto.fnv32a] +--- + +This function calculates the 32-bit [FNV1a hash](https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function#FNV-1a_hash) of a given string according to the [specification](https://datatracker.ietf.org/doc/html/draft-eastlake-fnv-12): + +```go-html-template +{{ crypto.FNV32a "Hello world" }} → 1498229191 +``` diff --git a/docs/content/en/functions/crypto/HMAC.md b/docs/content/en/functions/crypto/HMAC.md new file mode 100644 index 000000000..1906689a2 --- /dev/null +++ b/docs/content/en/functions/crypto/HMAC.md @@ -0,0 +1,31 @@ +--- +title: crypto.HMAC +description: Returns a cryptographic hash that uses a key to sign a message. +categories: [] +keywords: [] +action: + aliases: [hmac] + related: + - functions/crypto/FNV32a + - functions/crypto/MD5 + - functions/crypto/SHA1 + - functions/crypto/SHA256 + returnType: string + signatures: ['crypto.HMAC HASH_TYPE KEY MESSAGE [ENCODING]'] +aliases: [/functions/hmac] +--- + +Set the `HASH_TYPE` argument to `md5`, `sha1`, `sha256`, or `sha512`. + +Set the optional `ENCODING` argument to either `hex` (default) or `binary`. + +```go-html-template +{{ hmac "sha256" "Secret key" "Secret message" }} +5cceb491f45f8b154e20f3b0a30ed3a6ff3027d373f85c78ffe8983180b03c84 + +{{ hmac "sha256" "Secret key" "Secret message" "hex" }} +5cceb491f45f8b154e20f3b0a30ed3a6ff3027d373f85c78ffe8983180b03c84 + +{{ hmac "sha256" "Secret key" "Secret message" "binary" | base64Encode }} +XM60kfRfixVOIPOwow7Tpv8wJ9Nz+Fx4/+iYMYCwPIQ= +``` diff --git a/docs/content/en/functions/crypto/MD5.md b/docs/content/en/functions/crypto/MD5.md new file mode 100644 index 000000000..ba44660df --- /dev/null +++ b/docs/content/en/functions/crypto/MD5.md @@ -0,0 +1,26 @@ +--- +title: crypto.MD5 +description: Hashes the given input and returns its MD5 checksum encoded to a hexadecimal string. +categories: [] +keywords: [] +action: + aliases: [md5] + related: + - functions/crypto/FNV32a + - functions/crypto/HMAC + - functions/crypto/SHA1 + - functions/crypto/SHA256 + returnType: string + signatures: [crypto.MD5 INPUT] +aliases: [/functions/md5] +--- + +```go-html-template +{{ md5 "Hello world" }} → 3e25960a79dbc69b674cd4ec67a72c62 +``` + +This can be useful if you want to use [Gravatar](https://en.gravatar.com/) for generating a unique avatar: + +```html +<img src="https://www.gravatar.com/avatar/{{ md5 "your@email.com" }}?s=100&d=identicon"> +``` diff --git a/docs/content/en/functions/crypto/SHA1.md b/docs/content/en/functions/crypto/SHA1.md new file mode 100644 index 000000000..204ff0384 --- /dev/null +++ b/docs/content/en/functions/crypto/SHA1.md @@ -0,0 +1,20 @@ +--- +title: crypto.SHA1 +description: Hashes the given input and returns its SHA1 checksum encoded to a hexadecimal string. +categories: [] +keywords: [] +action: + aliases: [sha1] + related: + - functions/crypto/FNV32a + - functions/crypto/HMAC + - functions/crypto/MD5 + - functions/crypto/SHA256 + returnType: string + signatures: [crypto.SHA1 INPUT] +aliases: [/functions/sha,/functions/sha1] +--- + +```go-html-template +{{ sha1 "Hello world" }} → 7b502c3a1f48c8609ae212cdfb639dee39673f5e +``` diff --git a/docs/content/en/functions/crypto/SHA256.md b/docs/content/en/functions/crypto/SHA256.md new file mode 100644 index 000000000..6fb657767 --- /dev/null +++ b/docs/content/en/functions/crypto/SHA256.md @@ -0,0 +1,20 @@ +--- +title: crypto.SHA256 +description: Hashes the given input and returns its SHA256 checksum encoded to a hexadecimal string. +categories: [] +keywords: [] +action: + aliases: [sha256] + related: + - functions/crypto/FNV32a + - functions/crypto/HMAC + - functions/crypto/MD5 + - functions/crypto/SHA1 + returnType: string + signatures: [crypto.SHA256 INPUT] +aliases: [/functions/sha256] +--- + +```go-html-template +{{ sha256 "Hello world" }} → 64ec88ca00b268e5ba1a35678a1b5316d212f4f366b2477232534a8aeca37f3c +``` diff --git a/docs/content/en/functions/crypto/_index.md b/docs/content/en/functions/crypto/_index.md new file mode 100644 index 000000000..5c95aab6e --- /dev/null +++ b/docs/content/en/functions/crypto/_index.md @@ -0,0 +1,12 @@ +--- +title: Crypto functions +linkTitle: crypto +description: Template functions to create cryptographic hashes. +categories: [] +keywords: [] +menu: + docs: + parent: functions +--- + +Use these functions to create cryptographic hashes. diff --git a/docs/content/en/functions/data/GetCSV.md b/docs/content/en/functions/data/GetCSV.md new file mode 100644 index 000000000..d61ea791d --- /dev/null +++ b/docs/content/en/functions/data/GetCSV.md @@ -0,0 +1,140 @@ +--- +title: data.GetCSV +description: Returns an array of arrays from a local or remote CSV file, or an error if the file does not exist. +categories: [] +keywords: [] +action: + aliases: [getCSV] + related: + - functions/data/GetJSON + - functions/resources/Get + - functions/resources/GetRemote + - methods/page/Resources + returnType: '[][]string' + signatures: ['data.GetCSV SEPARATOR INPUT... [OPTIONS]'] +toc: true +--- + +Given the following directory structure: + +```text +my-project/ +└── other-files/ + └── pets.csv +``` + +Access the data with either of the following: + +```go-html-template +{{ $data := getCSV "," "other-files/pets.csv" }} +{{ $data := getCSV "," "other-files/" "pets.csv" }} +``` + +{{% note %}} +When working with local data, the filepath is relative to the working directory. + +You must not place CSV files in the project's data directory. +{{% /note %}} + +Access remote data with either of the following: + +```go-html-template +{{ $data := getCSV "," "https://example.org/pets.csv" }} +{{ $data := getCSV "," "https://example.org/" "pets.csv" }} +``` + +The resulting data structure is an array of arrays: + +```json +[ + ["name","type","breed","age"], + ["Spot","dog","Collie","3"], + ["Felix","cat","Malicious","7"] +] +``` + +## Options + +Add headers to the request by providing an options map: + +```go-html-template +{{ $opts := dict "Authorization" "Bearer abcd" }} +{{ $data := getCSV "," "https://example.org/pets.csv" $opts }} +``` + +Add multiple headers using a slice: + +```go-html-template +{{ $opts := dict "X-List" (slice "a" "b" "c") }} +{{ $data := getCSV "," "https://example.org/pets.csv" $opts }} +``` + +## Global resource alternative + +Consider using the [`resources.Get`] function with [`transform.Unmarshal`] when accessing a global resource. + +```text +my-project/ +└── assets/ + └── data/ + └── pets.csv +``` + +```go-html-template +{{ $data := "" }} +{{ $p := "data/pets.csv" }} +{{ with resources.Get $p }} + {{ $opts := dict "delimiter" "," }} + {{ $data = . | transform.Unmarshal $opts }} +{{ else }} + {{ errorf "Unable to get resource %q" $p }} +{{ end }} +``` + +## Page resource alternative + +Consider using the [`Resources.Get`] method with [`transform.Unmarshal`] when accessing a page resource. + +```text +my-project/ +└── content/ + └── posts/ + └── my-pets/ + ├── index.md + └── pets.csv +``` + +```go-html-template +{{ $data := "" }} +{{ $p := "pets.csv" }} +{{ with .Resources.Get $p }} + {{ $opts := dict "delimiter" "," }} + {{ $data = . | transform.Unmarshal $opts }} +{{ else }} + {{ errorf "Unable to get resource %q" $p }} +{{ end }} +``` + +## Remote resource alternative + +Consider using the [`resources.GetRemote`] function with [`transform.Unmarshal`] when accessing a remote resource to improve error handling and cache control. + +```go-html-template +{{ $data := "" }} +{{ $u := "https://example.org/pets.csv" }} +{{ with resources.GetRemote $u }} + {{ with .Err }} + {{ errorf "%s" . }} + {{ else }} + {{ $opts := dict "delimiter" "," }} + {{ $data = . | transform.Unmarshal $opts }} + {{ end }} +{{ else }} + {{ errorf "Unable to get remote resource %q" $u }} +{{ end }} +``` + +[`Resources.Get`]: methods/page/Resources +[`resources.GetRemote`]: /functions/resources/getremote +[`resources.Get`]: /functions/resources/get +[`transform.Unmarshal`]: /functions/transform/unmarshal diff --git a/docs/content/en/functions/data/GetJSON.md b/docs/content/en/functions/data/GetJSON.md new file mode 100644 index 000000000..4db3c8988 --- /dev/null +++ b/docs/content/en/functions/data/GetJSON.md @@ -0,0 +1,142 @@ +--- +title: data.GetJSON +description: Returns a JSON object from a local or remote JSON file, or an error if the file does not exist. +categories: [] +keywords: [] +action: + aliases: [getJSON] + related: + - functions/data/GetCSV + - functions/resources/Get + - functions/resources/GetRemote + - methods/page/Resources + returnType: any + signatures: ['data.GetJSON INPUT... [OPTIONS]'] +toc: true +--- + +Given the following directory structure: + +```text +my-project/ +└── other-files/ + └── books.json +``` + +Access the data with either of the following: + +```go-html-template +{{ $data := getJSON "other-files/books.json" }} +{{ $data := getJSON "other-files/" "books.json" }} +``` + +{{% note %}} +When working with local data, the filepath is relative to the working directory. +{{% /note %}} + +Access remote data with either of the following: + +```go-html-template +{{ $data := getJSON "https://example.org/books.json" }} +{{ $data := getJSON "https://example.org/" "books.json" }} +``` + +The resulting data structure is a JSON object: + +```json +[ + { + "author": "Victor Hugo", + "rating": 5, + "title": "Les Misérables" + }, + { + "author": "Victor Hugo", + "rating": 4, + "title": "The Hunchback of Notre Dame" + } +] +``` + +## Options + +Add headers to the request by providing an options map: + +```go-html-template +{{ $opts := dict "Authorization" "Bearer abcd" }} +{{ $data := getJSON "https://example.org/books.json" $opts }} +``` + +Add multiple headers using a slice: + +```go-html-template +{{ $opts := dict "X-List" (slice "a" "b" "c") }} +{{ $data := getJSON "https://example.org/books.json" $opts }} +``` + +## Global resource alternative + +Consider using the [`resources.Get`] function with [`transform.Unmarshal`] when accessing a global resource. + +```text +my-project/ +└── assets/ + └── data/ + └── books.json +``` + +```go-html-template +{{ $data := "" }} +{{ $p := "data/books.json" }} +{{ with resources.Get $p }} + {{ $data = . | transform.Unmarshal }} +{{ else }} + {{ errorf "Unable to get resource %q" $p }} +{{ end }} +``` + +## Page resource alternative + +Consider using the [`Resources.Get`] method with [`transform.Unmarshal`] when accessing a page resource. + +```text +my-project/ +└── content/ + └── posts/ + └── reading-list/ + ├── books.json + └── index.md +``` + +```go-html-template +{{ $data := "" }} +{{ $p := "books.json" }} +{{ with .Resources.Get $p }} + {{ $data = . | transform.Unmarshal }} +{{ else }} + {{ errorf "Unable to get resource %q" $p }} +{{ end }} +``` + +## Remote resource alternative + +Consider using the [`resources.GetRemote`] function with [`transform.Unmarshal`] when accessing a remote resource to improve error handling and cache control. + +```go-html-template +{{ $data := "" }} +{{ $u := "https://example.org/books.json" }} +{{ with resources.GetRemote $u }} + {{ with .Err }} + {{ errorf "%s" . }} + {{ else }} + {{ $data = . | transform.Unmarshal }} + {{ end }} +{{ else }} + {{ errorf "Unable to get remote resource %q" $u }} +{{ end }} +``` + +[`Resources.Get`]: methods/page/Resources +[`resources.GetRemote`]: /functions/resources/getremote +[`resources.Get`]: /functions/resources/get +[`transform.Unmarshal`]: /functions/transform/unmarshal diff --git a/docs/content/en/functions/data/_index.md b/docs/content/en/functions/data/_index.md new file mode 100644 index 000000000..142d6b528 --- /dev/null +++ b/docs/content/en/functions/data/_index.md @@ -0,0 +1,12 @@ +--- +title: Data functions +linkTitle: data +description: Template functions to read local or remote data files. +categories: [] +keywords: [] +menu: + docs: + parent: functions +--- + +Use these functions to read local or remote data files. diff --git a/docs/content/en/functions/debug/Dump.md b/docs/content/en/functions/debug/Dump.md new file mode 100644 index 000000000..d3161605f --- /dev/null +++ b/docs/content/en/functions/debug/Dump.md @@ -0,0 +1,45 @@ +--- +title: debug.Dump +description: Returns an object dump as a string. +categories: [] +keywords: [] +action: + aliases: [] + related: [] + returnType: string + signatures: [debug.Dump VALUE] +--- + +```go-html-template +{{ $data := "" }} +{{ $p := "data/books.json" }} +{{ with resources.Get $p }} + {{ $opts := dict "delimiter" "," }} + {{ $data = . | transform.Unmarshal $opts }} +{{ else }} + {{ errorf "Unable to get resource %q" $p }} +{{ end }} +``` + +```go-html-template +<pre>{{ debug.Dump $data }}</pre> +``` + +```text +[]interface {}{ + map[string]interface {}{ + "author": "Victor Hugo", + "rating": 5.0, + "title": "Les Misérables", + }, + map[string]interface {}{ + "author": "Victor Hugo", + "rating": 4.0, + "title": "The Hunchback of Notre Dame", + }, +} +``` + +{{% note %}} +Output from this function may change from one release to the next. Use for debugging only. +{{% /note %}} diff --git a/docs/content/en/functions/debug/Timer.md b/docs/content/en/functions/debug/Timer.md new file mode 100644 index 000000000..ae6c3188f --- /dev/null +++ b/docs/content/en/functions/debug/Timer.md @@ -0,0 +1,37 @@ +--- +title: debug.Timer +description: Creates a named timer that reports elapsed time to the console. +categories: [] +keywords: [] +action: + aliases: [] + related: [] + returnType: debug.Timer + signatures: [debug.Timer NAME] +--- + +{{< new-in 0.120.0 >}} + +Use the `debug.Timer` function to determine execution time for a block of code, useful for finding performance bottle necks in templates. + +The timer starts when you instantiate it, and stops when you call its `Stop` method. + +```go-html-template +{{ $t := debug.Timer "TestSqrt" }} +{{ range seq 2000 }} + {{ $f := math.Sqrt . }} +{{ end }} +{{ $t.Stop }} +``` + +Use the `--logLevel info` command line flag when you build the site. + +```sh +hugo --logLevel info +``` + +The results are displayed in the console at the end of the build. You can have as many timers as you want and if you don't stop them, they will be stopped at the end of build. + +```text +INFO timer: name TestSqrt total 12.429355ms +``` diff --git a/docs/content/en/functions/debug/_index.md b/docs/content/en/functions/debug/_index.md new file mode 100644 index 000000000..418828515 --- /dev/null +++ b/docs/content/en/functions/debug/_index.md @@ -0,0 +1,12 @@ +--- +title: Debug functions +linkTitle: debug +description: Template functions to debug your templates. +categories: [] +keywords: [] +menu: + docs: + parent: functions +--- + +Use these functions to debug your templates. diff --git a/docs/content/en/functions/diagrams/Goat.md b/docs/content/en/functions/diagrams/Goat.md new file mode 100644 index 000000000..2b31d9824 --- /dev/null +++ b/docs/content/en/functions/diagrams/Goat.md @@ -0,0 +1,113 @@ +--- +title: diagrams.Goat +description: Converts ASCII art to an SVG diagram, returning a GoAT diagram object. +categories: [] +keywords: [] +action: + aliases: [] + related: [] + returnType: diagrams.goatDiagram + signatures: ['diagrams.Goat INPUT'] +toc: true +--- + +Useful in a code block [render hook], the `diagram.Goat` function converts ASCII art to an SVG diagram, returning a [GoAT] diagram object with the following methods: + +[GoAT]: https://github.com/blampe/goat#readme +[render hook]: https://gohugo.io/templates/render-hooks/ + +Inner +: (`template.HTML`) Returns the SVG child elements without a wrapping `svg` element, allowing you to create your own wrapper. + +Wrapped +: (`template.HTML`) Returns the SVG child elements wrapped in an `svg` element. + +Width +: (`int`) Returns the width of the rendered diagram, in pixels. + +Height +: (`int`) Returns the height of the rendered diagram, in pixels. + +## GoAT Diagrams + +Hugo natively supports [GoAT] diagrams. + +This markdown: + +```` +```goat +.---. .-. .-. .-. .---. +| A +--->| 1 |<--->| 2 |<--->| 3 |<---+ B | +'---' '-' '+' '+' '---' +``` +```` + +Is rendered to: + +```html +<div class="goat svg-container"> + <svg xmlns="http://www.w3.org/2000/svg" font-family="Menlo,Lucida Console,monospace" viewBox="0 0 352 57"> + ... + </svg> +</div> +``` + +Which appears in your browser as: + +```goat {class="mw6-ns"} +.---. .-. .-. .-. .---. +| A +--->| 1 |<--->| 2 |<--->| 3 |<---+ B | +'---' '-' '+' '+' '---' +``` + +To customize rendering, override Hugo's [built-in code block render hook] for GoAT diagrams. + +[built-in code block render hook]: https://github.com/gohugoio/hugo/blob/master/tpl/tplimpl/embedded/templates/_default/_markup/render-codeblock-goat.html + +## Code block render hook + +By way of example, let's create a code block render hook to render GoAT diagrams as `figure` elements with an optional caption. + +{{< code file=layouts/_default/_markup/render-codeblock-goat.html >}} +{{ $caption := or .Attributes.caption "" }} +{{ $class := or .Attributes.class "diagram" }} +{{ $id := or .Attributes.id (printf "diagram-%d" (add 1 .Ordinal)) }} + +<figure id="{{ $id }}"> + {{ with diagrams.Goat (trim .Inner "\n\r") }} + <svg class="{{ $class }}" width="{{ .Width }}" height="{{ .Height }}" xmlns="http://www.w3.org/2000/svg" version="1.1"> + {{ .Inner }} + </svg> + {{ end }} + <figcaption>{{ $caption }}</figcaption> +</figure> +{{< /code >}} + +This markdown: + +{{< code file=content/example.md lang=text >}} +```goat {class="foo" caption="Diagram 1: Example"} +.---. .-. .-. .-. .---. +| A +--->| 1 |<--->| 2 |<--->| 3 |<---+ B | +'---' '-' '+' '+' '---' +``` +{{< /code >}} + +Is rendered to: + +```html +<figure id="diagram-1"> + <svg class="foo" width="272" height="57" xmlns="http://www.w3.org/2000/svg" version="1.1"> + ... + </svg> + <figcaption>Diagram 1: Example</figcaption> +</figure> +``` + +Use CSS to style the SVG as needed: + +```css +svg.foo { + font-family: "Segoe UI","Noto Sans",Helvetica,Arial,sans-serif +} +``` diff --git a/docs/content/en/functions/diagrams/_index.md b/docs/content/en/functions/diagrams/_index.md new file mode 100644 index 000000000..e136b4f33 --- /dev/null +++ b/docs/content/en/functions/diagrams/_index.md @@ -0,0 +1,12 @@ +--- +title: Diagram functions +linkTitle: diagrams +description: Template functions to render diagrams. +categories: [] +keywords: [] +menu: + docs: + parent: functions +--- + +Use these functions to render diagrams. diff --git a/docs/content/en/functions/encoding/Base64Decode.md b/docs/content/en/functions/encoding/Base64Decode.md new file mode 100644 index 000000000..821ca805a --- /dev/null +++ b/docs/content/en/functions/encoding/Base64Decode.md @@ -0,0 +1,40 @@ +--- +title: encoding.Base64Decode +description: Returns the base64 decoding of the given content. +categories: [] +keywords: [] +action: + aliases: [base64Decode] + related: + - functions/encoding/Base64Encode + returnType: string + signatures: [encoding.Base64Decode INPUT] +aliases: [/functions/base64Decode] +--- + +```go-html-template +{{ "SHVnbw==" | base64Decode }} → Hugo +``` + +Use the `base64Decode` function to decode responses from APIs. For example, the result of this call to GitHub's API contains the base64-encoded representation of the repository's README file: + +```text +https://api.github.com/repos/gohugoio/hugo/readme +``` + +To retrieve and render the content: + +```go-html-template +{{ $u := "https://api.github.com/repos/gohugoio/hugo/readme" }} +{{ with resources.GetRemote $u }} + {{ with .Err }} + {{ errorf "%s" . }} + {{ else }} + {{ with . | transform.Unmarshal }} + {{ .content | base64Decode | markdownify }} + {{ end }} + {{ end }} +{{ else }} + {{ errorf "Unable to get remote resource %q" $u }} +{{ end }} +``` diff --git a/docs/content/en/functions/encoding/Base64Encode.md b/docs/content/en/functions/encoding/Base64Encode.md new file mode 100644 index 000000000..14f67a132 --- /dev/null +++ b/docs/content/en/functions/encoding/Base64Encode.md @@ -0,0 +1,17 @@ +--- +title: encoding.Base64Encode +description: Returns the base64 decoding of the given content. +categories: [] +keywords: [] +action: + aliases: [base64Encode] + related: + - functions/encoding/Base64Decode + returnType: string + signatures: [encoding.Base64Encode INPUT] +aliases: [/functions/base64, /functions/base64Encode] +--- + +```go-html-template +{{ "Hugo" | base64Encode }} → SHVnbw== +``` diff --git a/docs/content/en/functions/encoding/Jsonify.md b/docs/content/en/functions/encoding/Jsonify.md new file mode 100644 index 000000000..475f8a76a --- /dev/null +++ b/docs/content/en/functions/encoding/Jsonify.md @@ -0,0 +1,37 @@ +--- +title: encoding.Jsonify +description: Encodes the given object to JSON. +categories: [] +keywords: [] +action: + aliases: [jsonify] + returnType: template.HTML + related: + - functions/transform/Remarshal + - functions/transform/Unmarshal + signatures: + - encoding.Jsonify [OPTIONS] INPUT +aliases: [/functions/jsonify] +--- + +To customize the printing of the JSON, pass an options map as the first +argument. Supported options are "prefix" and "indent". Each JSON element in +the output will begin on a new line beginning with *prefix* followed by one or +more copies of *indent* according to the indentation nesting. + +```go-html-template +{{ dict "title" .Title "content" .Plain | jsonify }} +{{ dict "title" .Title "content" .Plain | jsonify (dict "indent" " ") }} +{{ dict "title" .Title "content" .Plain | jsonify (dict "prefix" " " "indent" " ") }} +``` + +## Options + +indent +: (`string`) Indentation to use. Default is "". + +prefix +: (`string`) Indentation prefix. Default is "". + +noHTMLEscape +: (`bool`) Disable escaping of problematic HTML characters inside JSON quoted strings. The default behavior is to escape `&`, `<`, and `>` to `\u0026`, `\u003c`, and `\u003e` to avoid certain safety problems that can arise when embedding JSON in HTML. Default is `false`. diff --git a/docs/content/en/functions/encoding/_index.md b/docs/content/en/functions/encoding/_index.md new file mode 100644 index 000000000..3c4c4519e --- /dev/null +++ b/docs/content/en/functions/encoding/_index.md @@ -0,0 +1,12 @@ +--- +title: Encoding functions +linkTitle: encoding +description: Template functions to encode and decode data. +categories: [] +keywords: [] +menu: + docs: + parent: functions +--- + +Use these functions to encode and decode data. diff --git a/docs/content/en/functions/fmt/Errorf.md b/docs/content/en/functions/fmt/Errorf.md new file mode 100644 index 000000000..bbdd62c53 --- /dev/null +++ b/docs/content/en/functions/fmt/Errorf.md @@ -0,0 +1,26 @@ +--- +title: fmt.Errorf +description: Log an ERROR from a template. +categories: [] +keywords: [] +action: + aliases: [errorf] + related: + - functions/fmt/Erroridf + - functions/fmt/Warnf + returnType: string + signatures: ['fmt.Errorf FORMAT [INPUT]'] +aliases: [/functions/errorf] +--- + +{{% include "functions/fmt/_common/fmt-layout.md" %}} + +The `errorf` function evaluates the format string, then prints the result to the ERROR log and fails the build. + +```go-html-template +{{ errorf "The %q shortcode requires a src parameter. See %s" .Name .Position }} +``` + +Use the [`erroridf`] function to allow optional suppression of specific errors. + +[`erroridf`]: /functions/fmt/erroridf diff --git a/docs/content/en/functions/fmt/Erroridf.md b/docs/content/en/functions/fmt/Erroridf.md new file mode 100644 index 000000000..9884f4935 --- /dev/null +++ b/docs/content/en/functions/fmt/Erroridf.md @@ -0,0 +1,40 @@ +--- +title: fmt.Erroridf +description: Log a suppressable ERROR from a template. +categories: [] +keywords: [] +action: + aliases: [erroridf] + related: + - functions/fmt/Errorf + - functions/fmt/Warnf + returnType: string + signatures: ['fmt.Erroridf ID FORMAT [INPUT]'] +aliases: [/functions/erroridf] +--- + +{{% include "functions/fmt/_common/fmt-layout.md" %}} + +The `erroridf` function evaluates the format string, then prints the result to the ERROR log and fails the build. Unlike the [`errorf`] function, you may suppress errors logged by the `erroridf` function by adding the message ID to the `ignoreErrors` array in your site configuration. + +This template code: + +```go-html-template +{{ erroridf "error-42" "You should consider fixing this." }} +``` + +Produces this console log: + +```text +ERROR You should consider fixing this. +You can suppress this error by adding the following to your site configuration: +ignoreErrors = ['error-42'] +``` + +To suppress this message: + +{{< code-toggle file=hugo >}} +ignoreErrors = ["error-42"] +{{< /code-toggle >}} + +[`errorf`]: /functions/fmt/errorf diff --git a/docs/content/en/functions/fmt/Print.md b/docs/content/en/functions/fmt/Print.md new file mode 100644 index 000000000..6f3128e5f --- /dev/null +++ b/docs/content/en/functions/fmt/Print.md @@ -0,0 +1,20 @@ +--- +title: fmt.Print +description: Prints the default representation of the given arguments using the standard `fmt.Print` function. +categories: [] +keywords: [] +action: + aliases: [print] + related: + - functions/fmt/Printf + - functions/fmt/Println + returnType: string + signatures: [fmt.Print INPUT] +aliases: [/functions/print] +--- + +```go-html-template +{{ print "foo" }} → foo +{{ print "foo" "bar" }} → foobar +{{ print (slice 1 2 3) }} → [1 2 3] +``` diff --git a/docs/content/en/functions/fmt/Printf.md b/docs/content/en/functions/fmt/Printf.md new file mode 100644 index 000000000..5d0127460 --- /dev/null +++ b/docs/content/en/functions/fmt/Printf.md @@ -0,0 +1,39 @@ +--- +title: fmt.Printf +description: Formats a string using the standard `fmt.Sprintf` function. +categories: [] +keywords: [] +action: + aliases: [printf] + related: + - functions/fmt/Print + - functions/fmt/Println + returnType: string + signatures: ['fmt.Printf FORMAT [INPUT]'] +aliases: [/functions/printf] +--- + +{{% include "functions/fmt/_common/fmt-layout.md" %}} + +```go-html-template +{{ $var := "world" }} +{{ printf "Hello %s." $var }} → Hello world. +``` + +```go-html-template +{{ $pi := 3.14159265 }} +{{ printf "Pi is approximately %.2f." $pi }} → 3.14 +``` + +Use the `printf` function with the `safeHTMLAttr` function: + +```go-html-template +{{ $desc := "Eat at Joe's" }} +<meta name="description" {{ printf "content=%q" $desc | safeHTMLAttr }}> +``` + +Hugo renders this to: + +```html +<meta name="description" content="Eat at Joe's"> +``` diff --git a/docs/content/en/functions/fmt/Println.md b/docs/content/en/functions/fmt/Println.md new file mode 100644 index 000000000..a4db56ffb --- /dev/null +++ b/docs/content/en/functions/fmt/Println.md @@ -0,0 +1,18 @@ +--- +title: fmt.Println +description: Prints the default representation of the given argument using the standard `fmt.Print` function and enforces a line break. +categories: [] +keywords: [] +action: + aliases: [println] + related: + - functions/fmt/Print + - functions/fmt/Printf + returnType: string + signatures: [fmt.Println INPUT] +aliases: [/functions/println] +--- + +```go-html-template +{{ println "foo" }} → foo\n +``` diff --git a/docs/content/en/functions/fmt/Warnf.md b/docs/content/en/functions/fmt/Warnf.md new file mode 100644 index 000000000..0a90251d3 --- /dev/null +++ b/docs/content/en/functions/fmt/Warnf.md @@ -0,0 +1,33 @@ +--- +title: fmt.Warnf +description: Log a WARNING from a template. +categories: [] +keywords: [] +action: + aliases: [warnf] + related: + - functions/fmt/Errorf + - functions/fmt/Erroridf + returnType: string + signatures: ['fmt.Warnf FORMAT [INPUT]'] +aliases: [/functions/warnf] +--- + +{{% include "functions/fmt/_common/fmt-layout.md" %}} + +The `warnf` function evaluates the format string, then prints the result to the WARNING log. Hugo prints each unique message once to avoid flooding the log with duplicate warnings. + +```go-html-template +{{ warnf "The %q shortcode was unable to find %s. See %s" .Name $file .Position }} +``` + +To prevent suppression of duplicate messages when using `warnf` for debugging, make each message unique with the [`math.Counter`] function. For example: + + +```go-html-template +{{ range site.RegularPages }} + {{ .Section | warnf "%#[2]v [%[1]d]" math.Counter }} +{{ end }} +``` + +[`math.Counter`]: /functions/math/counter diff --git a/docs/content/en/functions/fmt/_common/_index.md b/docs/content/en/functions/fmt/_common/_index.md new file mode 100644 index 000000000..47d5812fb --- /dev/null +++ b/docs/content/en/functions/fmt/_common/_index.md @@ -0,0 +1,13 @@ +--- +cascade: + _build: + list: never + publishResources: false + render: never +--- + +<!-- +Files within this headless branch bundle are markdown snippets. Each file must contain front matter delimiters, though front matter fields are not required. + +Include the rendered content using the "include" shortcode. +--> diff --git a/docs/content/en/functions/fmt/_common/fmt-layout.md b/docs/content/en/functions/fmt/_common/fmt-layout.md new file mode 100644 index 000000000..ff69ce5e4 --- /dev/null +++ b/docs/content/en/functions/fmt/_common/fmt-layout.md @@ -0,0 +1,7 @@ +--- +# Do not remove front matter. +--- + +The documentation for Go's [fmt] package describes the structure and content of the format string. + +[fmt]: https://pkg.go.dev/fmt diff --git a/docs/content/en/functions/fmt/_index.md b/docs/content/en/functions/fmt/_index.md new file mode 100644 index 000000000..51ef847ca --- /dev/null +++ b/docs/content/en/functions/fmt/_index.md @@ -0,0 +1,12 @@ +--- +title: Fmt functions +linkTitle: fmt +description: Template functions to print strings within a template or to print messages to the terminal +categories: [] +keywords: [] +menu: + docs: + parent: functions +--- + +Use these functions to print strings within a template or to print messages to the terminal. diff --git a/docs/content/en/functions/global/_index.md b/docs/content/en/functions/global/_index.md new file mode 100644 index 000000000..1e609b56e --- /dev/null +++ b/docs/content/en/functions/global/_index.md @@ -0,0 +1,11 @@ +--- +title: Global functions +linkTitle: global +description: Global template functions to access page and site data. +categories: [] +menu: + docs: + parent: functions +--- + +Use these global functions to access page and site data. diff --git a/docs/content/en/functions/global/page.md b/docs/content/en/functions/global/page.md new file mode 100644 index 000000000..6c96b747e --- /dev/null +++ b/docs/content/en/functions/global/page.md @@ -0,0 +1,109 @@ +--- +title: page +description: Provides global access to a Page object. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/global/site + returnType: + signatures: [page] +toc: true +aliases: [/functions/page] +--- + +{{< new-in 0.111.0 >}} + +At the top level of a template that receives a `Page` object in context, these are equivalent: + +```go-html-template +{{ .Params.foo }} +{{ .Page.Params.foo }} +{{ page.Params.foo }} +``` + +When a `Page` object is not in context, you can use the global `page` function: + +```go-html-template +{{ page.Params.foo }} +``` + +{{% note %}} +Do not use the global `page` function in shortcodes, partials called by shortcodes, or cached partials. See [warnings](#warnings) below. +{{% /note %}} + +## Explanation + +Hugo almost always passes a `Page` as the data context into the top level template (e.g., `single.html`). The one exception is the multihost sitemap template. This means that you can access the current page with the `.` variable in the template. + +But when you are deeply nested inside of a [content view], [partial], or [render hook], it is not always practical or possible to access the `Page` object. + +Use the global `page` function to access the `Page` object from anywhere in any template. + +## Warnings + +### Be aware of top-level context + +The global `page` function accesses the `Page` object passed into the top-level template. + +With this content structure: + +```text +content/ +├── posts/ +│ ├── post-1.md +│ ├── post-2.md +│ └── post-3.md +└── _index.md <-- title is "My Home Page" +``` + +And this code in the home page template: + +```go-html-template +{{ range site.Sections }} + {{ range .Pages }} + {{ page.Title }} + {{ end }} +{{ end }} +``` + +The rendered output will be: + +```text +My Home Page +My Home Page +My Home Page +``` + +In the example above, the global `page` function accesses the `Page` object passed into the home page template; it does not access the `Page` object of the iterated pages. + +### Be aware of caching + +Do not use the global `page` function in: + +- Shortcodes +- Partials called by shortcodes +- Partials cached by the [`partialCached`] function + +Hugo caches rendered shortcodes. If you use the global `page` function within a shortcode, and the page content is rendered in two or more templates, the cached shortcode may be incorrect. + +Consider this section template: + +```go-html-template +{{ range .Pages }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> + {{ .Summary }} +{{ end }} +``` + +When you call the [`Summary`] method, Hugo renders the page content including shortcodes. In this case, within a shortcode, the global `page` function accesses the `Page` object of the section page, not the content page. + +If Hugo renders the section page before a content page, the cached rendered shortcode will be incorrect. You cannot control the rendering sequence due to concurrency. + +[`Summary`]: /methods/page/summary +[`partialCached`]: /functions/partials/includecached +[content view]: /getting-started/glossary/#content-view +[partial]: /getting-started/glossary/#partial +[render hook]: /getting-started/glossary/#render-hook +[shortcode]: getting-started/glossary/#shortcode diff --git a/docs/content/en/functions/global/site.md b/docs/content/en/functions/global/site.md new file mode 100644 index 000000000..a097e471b --- /dev/null +++ b/docs/content/en/functions/global/site.md @@ -0,0 +1,30 @@ +--- +title: site +description: Provides global access to the current Site object. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/global/page + returnType: + signatures: [site] +aliases: [/functions/site] +--- + +At the top level of a template that receives the `Site` object in context, these are equivalent: + +```go-html-template +{{ .Site.Params.foo }} +{{ site.Params.foo }} +``` + +When the `Site` object is not in context, use the global `site` function: + +```go-html-template +{{ site.Params.foo }} +``` + +{{% note %}} +To simplify your templates, use the global `site` function regardless of whether the `Site` object is in context. +{{% /note %}} diff --git a/docs/content/en/functions/go-template/_common/_index.md b/docs/content/en/functions/go-template/_common/_index.md new file mode 100644 index 000000000..47d5812fb --- /dev/null +++ b/docs/content/en/functions/go-template/_common/_index.md @@ -0,0 +1,13 @@ +--- +cascade: + _build: + list: never + publishResources: false + render: never +--- + +<!-- +Files within this headless branch bundle are markdown snippets. Each file must contain front matter delimiters, though front matter fields are not required. + +Include the rendered content using the "include" shortcode. +--> diff --git a/docs/content/en/functions/go-template/_common/text-template.md b/docs/content/en/functions/go-template/_common/text-template.md new file mode 100644 index 000000000..71718c3fd --- /dev/null +++ b/docs/content/en/functions/go-template/_common/text-template.md @@ -0,0 +1,7 @@ +--- +# Do not remove front matter. +--- + +See Go's [text/template] documentation for more information. + +[text/template]: https://pkg.go.dev/text/template diff --git a/docs/content/en/functions/go-template/_common/truthy-falsy.md b/docs/content/en/functions/go-template/_common/truthy-falsy.md new file mode 100644 index 000000000..c8fc9e09e --- /dev/null +++ b/docs/content/en/functions/go-template/_common/truthy-falsy.md @@ -0,0 +1,5 @@ +--- +# Do not remove front matter. +--- + +In Go templates, the falsy values are `false`, `0`, any nil pointer or interface value, and any array, slice, map, or string of length zero. Everything else is truthy. diff --git a/docs/content/en/functions/go-template/_index.md b/docs/content/en/functions/go-template/_index.md new file mode 100644 index 000000000..9075756aa --- /dev/null +++ b/docs/content/en/functions/go-template/_index.md @@ -0,0 +1,14 @@ +--- +title: Go template functions, operators, and statements +linkTitle: go template +description: Template functions, operators, and statements provided by Go's text/template package. +categories: [] +keywords: [] +menu: + docs: + parent: functions +--- + +These are the functions, operators, and statements provided by Go's [text/template] package. + +[text/template]: https://pkg.go.dev/text/template diff --git a/docs/content/en/functions/go-template/and.md b/docs/content/en/functions/go-template/and.md new file mode 100644 index 000000000..6bc8c60a5 --- /dev/null +++ b/docs/content/en/functions/go-template/and.md @@ -0,0 +1,26 @@ +--- +title: and +description: Returns the first falsy argument. If all arguments are truthy, returns the last argument. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/go-template/not + - functions/go-template/or + returnType: any + signatures: [and VALUE...] +--- + +{{% include "functions/go-template/_common/truthy-falsy.md" %}} + +```go-html-template +{{ and 1 0 "" }} → 0 (int) +{{ and 1 false 0 }} → false (bool) + +{{ and 1 2 3 }} → 3 (int) +{{ and "a" "b" "c" }} → c (string) +{{ and "a" 1 true }} → true (bool) +``` + +{{% include "functions/go-template/_common/text-template.md" %}} diff --git a/docs/content/en/functions/go-template/block.md b/docs/content/en/functions/go-template/block.md new file mode 100644 index 000000000..f8a082037 --- /dev/null +++ b/docs/content/en/functions/go-template/block.md @@ -0,0 +1,55 @@ +--- +title: block +description: Defines a template and executes it in place. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/go-template/define + - functions/go-template/end + returnType: + signatures: [block NAME CONTEXT] +--- + +A block is shorthand for defining a template: + +```go-html-template +{{ define "name" }} T1 {{ end }} +``` + +and then executing it in place: + +```go-html-template +{{ template "name" pipeline }} +``` +The typical use is to define a set of root templates that are then customized by redefining the block templates within. + +{{< code file=layouts/_default/baseof.html >}} +<body> + <main> + {{ block "main" . }} + {{ print "default value if 'main' template is empty" }} + {{ end }} + </main> +</body> +{{< /code >}} + +{{< code file=layouts/_default/single.html >}} +{{ define "main" }} + <h1>{{ .Title }}</h1> + {{ .Content }} +{{ end }} +{{< /code >}} + +{{< code file=layouts/_default/list.html >}} +{{ define "main" }} + <h1>{{ .Title }}</h1> + {{ .Content }} + {{ range .Pages }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> + {{ end }} +{{ end }} +{{< /code >}} + +{{% include "functions/go-template/_common/text-template.md" %}} diff --git a/docs/content/en/functions/go-template/break.md b/docs/content/en/functions/go-template/break.md new file mode 100644 index 000000000..14074d7c0 --- /dev/null +++ b/docs/content/en/functions/go-template/break.md @@ -0,0 +1,33 @@ +--- +title: break +description: Used with the range statement, stops the innermost iteration and bypasses all remaining iterations. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/go-template/continue + - functions/go-template/range + returnType: + signatures: [break] +--- + +This template code: + +```go-html-template +{{ $s := slice "foo" "bar" "baz" }} +{{ range $s }} + {{ if eq . "bar" }} + {{ break }} + {{ end }} + <p>{{ . }}</p> +{{ end }} +``` + +Is rendered to: + +```html +<p>foo</p> +``` + +{{% include "functions/go-template/_common/text-template.md" %}} diff --git a/docs/content/en/functions/go-template/continue.md b/docs/content/en/functions/go-template/continue.md new file mode 100644 index 000000000..c8030b8b7 --- /dev/null +++ b/docs/content/en/functions/go-template/continue.md @@ -0,0 +1,34 @@ +--- +title: continue +description: Used with the range statement, stops the innermost iteration and continues to the next iteration. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/go-template/break + - functions/go-template/range + returnType: + signatures: [continue] +--- + +This template code: + +```go-html-template +{{ $s := slice "foo" "bar" "baz" }} +{{ range $s }} + {{ if eq . "bar" }} + {{ continue }} + {{ end }} + <p>{{ . }}</p> +{{ end }} +``` + +Is rendered to: + +```html +<p>foo</p> +<p>baz</p> +``` + +{{% include "functions/go-template/_common/text-template.md" %}} diff --git a/docs/content/en/functions/go-template/define.md b/docs/content/en/functions/go-template/define.md new file mode 100644 index 000000000..4d09c14f3 --- /dev/null +++ b/docs/content/en/functions/go-template/define.md @@ -0,0 +1,55 @@ +--- +title: define +description: Defines a template. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/go-template/block + - functions/go-template/end + - functions/go-template/template + - functions/partials/Include + - functions/partials/IncludeCached + returnType: + signatures: [define NAME] +--- + +Use with the [`block`] statement: + +```go-html-template +{{ block "main" . }} + {{ print "default value if 'main' template is empty" }} +{{ end }} + +{{ define "main" }} + <h1>{{ .Title }}</h1> + {{ .Content }} +{{ end }} +``` + +Use with the [`partial`] function: + +```go-html-template +{{ partial "inline/foo.html" (dict "answer" 42) }} + +{{ define "partials/inline/foo.html" }} + {{ printf "The answer is %v." .answer }} +{{ end }} +``` + +Use with the [`template`] function: + +```go-html-template +{{ template "foo" (dict "answer" 42) }} + +{{ define "foo" }} + {{ printf "The answer is %v." .answer }} +{{ end }} +``` + +[`block`]: /functions/go-template/block +[`template`]: /functions/go-template/block +[`partial`]: /functions/partials/include/ + +{{% include "functions/go-template/_common/text-template.md" %}} diff --git a/docs/content/en/functions/go-template/else.md b/docs/content/en/functions/go-template/else.md new file mode 100644 index 000000000..ccb8b722c --- /dev/null +++ b/docs/content/en/functions/go-template/else.md @@ -0,0 +1,69 @@ +--- +title: else +description: Begins an alternate block for if, with, and range statements. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/go-template/if + - functions/go-template/range + - functions/go-template/with + - functions/go-template/end + returnType: + signatures: [else VALUE] +--- + +Use with the [`if`] statement: + +```go-html-template +{{ $var := "foo" }} +{{ if $var }} + {{ $var }} → foo +{{ else }} + {{ print "var is falsy" }} +{{ end }} +``` + +Use with the [`with`] statement: + +```go-html-template +{{ $var := "foo" }} +{{ with $var }} + {{ . }} → foo +{{ else }} + {{ print "var is falsy" }} +{{ end }} +``` + +Use with the [`range`] statement: + +```go-html-template +{{ $var := slice 1 2 3 }} +{{ range $var }} + {{ . }} → 1 2 3 +{{ else }} + {{ print "var is falsy" }} +{{ end }} +``` + +Use `else if` to check multiple conditions. + +```go-html-template +{{ $var := 12 }} +{{ if eq $var 6 }} + {{ print "var is 6" }} +{{ else if eq $var 7 }} + {{ print "var is 7" }} +{{ else if eq $var 42 }} + {{ print "var is 42" }} +{{ else }} + {{ print "var is something else" }} +{{ end }} +``` + +{{% include "functions/go-template/_common/text-template.md" %}} + +[`if`]: /functions/go-template/if +[`with`]: /functions/go-template/with +[`range`]: /functions/go-template/range diff --git a/docs/content/en/functions/go-template/end.md b/docs/content/en/functions/go-template/end.md new file mode 100644 index 000000000..07d004de5 --- /dev/null +++ b/docs/content/en/functions/go-template/end.md @@ -0,0 +1,65 @@ +--- +title: end +description: Terminates if, with, range, block, and define statements. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/go-template/block + - functions/go-template/define + - functions/go-template/if + - functions/go-template/range + - functions/go-template/with + returnType: + signatures: [end] +--- + +Use with the [`if`] statement: + +```go-html-template +{{ $var := "foo" }} +{{ if $var }} + {{ $var }} → foo +{{ end }} +``` + +Use with the [`with`] statement: + +```go-html-template +{{ $var := "foo" }} +{{ with $var }} + {{ . }} → foo +{{ end }} +``` + +Use with the [`range`] statement: + +```go-html-template +{{ $var := slice 1 2 3 }} +{{ range $var }} + {{ . }} → 1 2 3 +{{ end }} +``` + +Use with the [`block`] statement: + +```go-html-template +{{ block "main" . }}{{ end }} +``` + +Use with the [`define`] statement: + +```go-html-template +{{ define "main" }} + {{ print "this is the main section" }} +{{ end }} +``` + +{{% include "functions/go-template/_common/text-template.md" %}} + +[`block`]: /functions/go-template/block +[`define`]: /functions/go-template/define +[`if`]: /functions/go-template/if +[`range`]: /functions/go-template/range +[`with`]: /functions/go-template/with diff --git a/docs/content/en/functions/go-template/if.md b/docs/content/en/functions/go-template/if.md new file mode 100644 index 000000000..e63c382e1 --- /dev/null +++ b/docs/content/en/functions/go-template/if.md @@ -0,0 +1,54 @@ +--- +title: if +description: Executes the block if the expression is truthy. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/go-template/with + - functions/go-template/else + - functions/go-template/end + - functions/collections/IsSet + returnType: + signatures: [if EXPR] +--- + +{{% include "functions/go-template/_common/truthy-falsy.md" %}} + +```go-html-template +{{ $var := "foo" }} +{{ if $var }} + {{ $var }} → foo +{{ end }} +``` + +Use with the [`else`] statement: + +```go-html-template +{{ $var := "foo" }} +{{ if $var }} + {{ $var }} → foo +{{ else }} + {{ print "var is falsy" }} +{{ end }} +``` + +Use `else if` to check multiple conditions. + +```go-html-template +{{ $var := 12 }} +{{ if eq $var 6 }} + {{ print "var is 6" }} +{{ else if eq $var 7 }} + {{ print "var is 7" }} +{{ else if eq $var 42 }} + {{ print "var is 42" }} +{{ else }} + {{ print "var is something else" }} +{{ end }} +``` + +{{% include "functions/go-template/_common/text-template.md" %}} + +[`else`]: /functions/go-template/else diff --git a/docs/content/en/functions/go-template/len.md b/docs/content/en/functions/go-template/len.md new file mode 100644 index 000000000..43f150a5f --- /dev/null +++ b/docs/content/en/functions/go-template/len.md @@ -0,0 +1,51 @@ +--- +title: len +description: Returns the length of a string, slice, map, or collection. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/strings/Count + - functions/strings/CountRunes + - functions/strings/CountWords + - functions/strings/RuneCount + returnType: int + signatures: [len VALUE] +aliases: [/functions/len] +--- + +With a string: + +```go-html-template +{{ "ab" | len }} → 2 +{{ "" | len }} → 0 +``` + +With a slice: + +```go-html-template +{{ slice "a" "b" | len }} → 2 +{{ slice | len }} → 0 +``` + +With a map: + +```go-html-template +{{ dict "a" 1 "b" 2 | len }} → 2 +{{ dict | len }} → 0 +``` + +With a collection: + +```go-html-template +{{ site.RegularPages | len }} → 42 +``` + +You may also determine the number of pages in a collection with: + +```go-html-template +{{ site.RegularPages.Len }} → 42 +``` + +{{% include "functions/go-template/_common/text-template.md" %}} diff --git a/docs/content/en/functions/go-template/not.md b/docs/content/en/functions/go-template/not.md new file mode 100644 index 000000000..4c7747c7b --- /dev/null +++ b/docs/content/en/functions/go-template/not.md @@ -0,0 +1,35 @@ +--- +title: not +description: Returns the boolean negation of its single argument. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/go-template/and + - functions/go-template/or + returnType: bool + signatures: [not VALUE] +--- + +Unlike the `and` and `or` operators, the `not` operator always returns a boolean value. + +```go-html-template +{{ not true }} → false +{{ not false }} → true + +{{ not 1 }} → false +{{ not 0 }} → true + +{{ not "x" }} → false +{{ not "" }} → true +``` + +Use the `not` operator, twice in succession, to cast any value to a boolean value. For example: + +```go-html-template +{{ 42 | not | not }} → true +{{ "" | not | not }} → false +``` + +{{% include "functions/go-template/_common/text-template.md" %}} diff --git a/docs/content/en/functions/go-template/or.md b/docs/content/en/functions/go-template/or.md new file mode 100644 index 000000000..0d8619608 --- /dev/null +++ b/docs/content/en/functions/go-template/or.md @@ -0,0 +1,26 @@ +--- +title: or +description: Returns the first truthy argument. If all arguments are falsy, returns the last argument. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/go-template/and + - functions/go-template/not + returnType: any + signatures: [or VALUE...] +--- + +{{% include "functions/go-template/_common/truthy-falsy.md" %}} + +```go-html-template +{{ or 0 1 2 }} → 1 +{{ or false "a" 1 }} → a +{{ or 0 true "a" }} → true + +{{ or false "" 0 }} → 0 +{{ or 0 "" false }} → false +``` + +{{% include "functions/go-template/_common/text-template.md" %}} diff --git a/docs/content/en/functions/go-template/range.md b/docs/content/en/functions/go-template/range.md new file mode 100644 index 000000000..e2f401371 --- /dev/null +++ b/docs/content/en/functions/go-template/range.md @@ -0,0 +1,199 @@ +--- +title: range +description: Iterates over a non-empty collection, binds context (the dot) to successive elements, and executes the block. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/go-template/break + - functions/go-template/continue + - functions/go-template/else + - functions/go-template/end + returnType: + signatures: [range COLLECTION] +aliases: [/functions/range] +toc: true +--- + +{{% include "functions/go-template/_common/truthy-falsy.md" %}} + +```go-html-template +{{ $s := slice "foo" "bar" "baz" }} +{{ range $s }} + {{ . }} → foo bar baz +{{ end }} +``` + +Use with the [`else`] statement: + +```go-html-template +{{ $s := slice "foo" "bar" "baz" }} +{{ range $s }} + <p>{{ . }}</p> +{{ else }} + <p>The collection is empty</p> +{{ end }} +``` + +Within a range block: + +- Use the [`continue`] statement to stop the innermost iteration and continue to the next iteration +- Use the [`break`] statement to stop the innermost iteration and bypass all remaining iterations + +## Understanding context + +At the top of a page template, the [context] (the dot) is a `Page` object. Within the `range` block, the context is bound to each successive element. + +With this contrived example that uses the [`seq`] function to generate a slice of integers: + +```go-html-template +{{ range seq 3 }} + {{ .Title }} +{{ end }} +``` + +Hugo will throw an error: + + can't evaluate field Title in type int + +The error occurs because we are trying to use the `.Title` method on an integer instead of a `Page` object. Within the `range` block, if we want to render the page title, we need to get the context passed into the template. + +{{% note %}} +Use the `$` to get the context passed into the template. +{{% /note %}} + +This template will render the page title three times: + +```go-html-template +{{ range seq 3 }} + {{ $.Title }} +{{ end }} +``` + +{{% note %}} +Gaining a thorough understanding of context is critical for anyone writing template code. +{{% /note %}} + +[`seq`]: functions/collections/seq/ +[context]: /getting-started/glossary/#context + +## Array or slice of scalars + +This template code: + +```go-html-template +{{ $s := slice "foo" "bar" "baz" }} +{{ range $s }} + <p>{{ . }}</p> +{{ end }} +``` + +Is rendered to: + +```html +<p>foo</p> +<p>bar</p> +<p>baz</p> +``` + +This template code: + +```go-html-template +{{ $s := slice "foo" "bar" "baz" }} +{{ range $v := $s }} + <p>{{ $v }}</p> +{{ end }} +``` + +Is rendered to: + +```html +<p>foo</p> +<p>bar</p> +<p>baz</p> +``` + +This template code: + +```go-html-template +{{ $s := slice "foo" "bar" "baz" }} +{{ range $k, $v := $s }} + <p>{{ $k }}: {{ $v }}</p> +{{ end }} +``` + +Is rendered to: + +```html +<p>0: foo</p> +<p>1: bar</p> +<p>2: baz</p> +``` + +## Array or slice of maps + +This template code: + +```go-html-template +{{ $m := slice + (dict "name" "John" "age" 30) + (dict "name" "Will" "age" 28) + (dict "name" "Joey" "age" 24) +}} +{{ range $m }} + <p>{{ .name }} is {{ .age }}</p> +{{ end }} +``` + +Is rendered to: + +```html +<p>John is 30</p> +<p>Will is 28</p> +<p>Joey is 24</p> +``` + +## Array or slice of pages + +This template code: + +```go-html-template +{{ range where site.RegularPages "Type" "articles" }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +``` + +Is rendered to: + +```html +<h2><a href="/articles/article-3/">Article 3</a></h2> +<h2><a href="/articles/article-2/">Article 2</a></h2> +<h2><a href="/articles/article-1/">Article 1</a></h2> +``` + +## Maps + +This template code: + +```go-html-template +{{ $m := dict "name" "John" "age" 30 }} +{{ range $k, $v := $m }} + <p>key = {{ $k }} value = {{ $v }}</p> +{{ end }} +``` + +Is rendered to: + +```go-html-template +<p>key = age value = 30</p> +<p>key = name value = John</p> +``` + +Unlike ranging over an array or slice, Hugo sorts by key when ranging over a map. + +{{% include "functions/go-template/_common/text-template.md" %}} + +[`else`]: /functions/go-template/else +[`break`]: /functions/go-template/break +[`continue`]: /functions/go-template/continue diff --git a/docs/content/en/functions/go-template/return.md b/docs/content/en/functions/go-template/return.md new file mode 100644 index 000000000..2a166c718 --- /dev/null +++ b/docs/content/en/functions/go-template/return.md @@ -0,0 +1,110 @@ +--- +title: return +description: Used within partial templates, terminates template execution and returns the given value, if any. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/partials/Include + - functions/partials/IncludeCached + returnType: any + signatures: ['return [VALUE]'] +toc: true +--- + +The `return` statement is a custom addition to Go's [text/template] package. Used within partial templates, the `return` statement terminates template execution and returns the given value, if any. + +The returned value may be of any data type including, but not limited to, [`bool`], [`float`], [`int`], [`map`], [`resource`], [`slice`], and [`string`]. + +A `return` statement without a value returns an empty string of type `template.HTML`. + +[`bool`]: /getting-started/glossary/#bool +[`float`]: /getting-started/glossary/#float +[`int`]: /getting-started/glossary/#int +[`map`]: /getting-started/glossary/#map +[`resource`]: /getting-started/glossary/#resource +[`slice`]: /getting-started/glossary/#slice +[`string`]: /getting-started/glossary/#string +[text/template]: https://pkg.go.dev/text/template + +{{% note %}} +Unlike `return` statements in other languages, Hugo executes the first occurrence of the `return` statement regardless of its position within logical blocks. See [usage](#usage) notes below. +{{% /note %}} + +## Example + +By way of example, let's create a partial template that _renders_ HTML, describing whether the given number is odd or even: + +{{< code file="layouts/partials/odd-or-even.html" >}} +{{ if math.ModBool . 2 }} + <p>{{ . }} is even</p> +{{ else }} + <p>{{ . }} is odd</p> +{{ end }} +{{< /code >}} + +When called, the partial renders HTML: + +```go-html-template +{{ partial "odd-or-even.html" 42 }} → <p>42 is even</p> +``` + +Instead of rendering HTML, let's create a partial that _returns_ a boolean value, reporting whether the given number is even: + +{{< code file="layouts/partials/is-even.html" >}} +{{ return math.ModBool . 2 }} +{{< /code >}} + +With this template: + +```go-html-template +{{ $number := 42 }} +{{ if partial "is-even.html" $number }} + <p>{{ $number }} is even</p> +{{ else }} + <p>{{ $number }} is odd</p> +{{ end }} +``` + +Hugo renders: + +```html +<p>42 is even</p> +``` + +See additional examples in the [partial templates] section. + +[partial templates]: /templates/partials/#returning-a-value-from-a-partial + +## Usage + +{{% note %}} +Unlike `return` statements in other languages, Hugo executes the first occurrence of the `return` statement regardless of its position within logical blocks +{{% /note %}} + +A partial that returns a value must contain only one `return` statement, placed at the end of the template. + +For example: + +{{< code file="layouts/partials/is-even.html" >}} +{{ $result := false }} +{{ if math.ModBool . 2 }} + {{ $result = "even" }} +{{ else }} + {{ $result = "odd" }} +{{ end }} +{{ return $result }} +{{< /code >}} + +{{% note %}} +The construct below is incorrect; it contains more than one `return` statement. +{{% /note %}} + +{{< code file="layouts/partials/do-not-do-this.html" >}} +{{ if math.ModBool . 2 }} + {{ return "even" }} +{{ else }} + {{ return "odd" }} +{{ end }} +{{< /code >}} diff --git a/docs/content/en/functions/go-template/template.md b/docs/content/en/functions/go-template/template.md new file mode 100644 index 000000000..a78ec5c65 --- /dev/null +++ b/docs/content/en/functions/go-template/template.md @@ -0,0 +1,49 @@ +--- +title: template +description: Executes the given template, optionally passing context. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/go-template/define + - functions/partials/Include + - functions/partials/IncludeCached + returnType: + signatures: ['template NAME [CONTEXT]'] +--- + +Use the `template` function to execute [internal templates]. For example: + +```go-html-template +{{ range (.Paginate .Pages).Pages }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +{{ template "_internal/pagination.html" . }} +``` + +You can also use the `template` function to execute a defined template: + +```go-html-template +{{ template "foo" (dict "answer" 42) }} + +{{ define "foo" }} + {{ printf "The answer is %v." .answer }} +{{ end }} +``` + +The example above can be rewritten using an [inline partial] template: + +```go-html-template +{{ partial "inline/foo.html" (dict "answer" 42) }} + +{{ define "partials/inline/foo.html" }} + {{ printf "The answer is %v." .answer }} +{{ end }} +``` + +{{% include "functions/go-template/_common/text-template.md" %}} + +[`partial`]: /functions/partials/include/ +[inline partial]: /templates/partials/#inline-partials +[internal templates]: /templates/internal diff --git a/docs/content/en/functions/go-template/urlquery.md b/docs/content/en/functions/go-template/urlquery.md new file mode 100644 index 000000000..946828f56 --- /dev/null +++ b/docs/content/en/functions/go-template/urlquery.md @@ -0,0 +1,28 @@ +--- +title: urlquery +description: Returns the escaped value of the textual representation of its arguments in a form suitable for embedding in a URL query. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/collections/Querify + returnType: string + signatures: ['urlquery VALUE [VALUE...]'] +aliases: [/functions/urlquery] +--- + +This template code: + +```go-html-template +{{ $u := urlquery "https://" "example.com" | safeURL }} +<a href="https://example.org?url={{ $u }}">Link</a> +``` + +Is rendered to: + +```html +<a href="https://example.org?url=https%3A%2F%2Fexample.com">Link</a> +``` + +{{% include "functions/go-template/_common/text-template.md" %}} diff --git a/docs/content/en/functions/go-template/with.md b/docs/content/en/functions/go-template/with.md new file mode 100644 index 000000000..0f3255b1a --- /dev/null +++ b/docs/content/en/functions/go-template/with.md @@ -0,0 +1,87 @@ +--- +title: with +description: Binds context (the dot) to the expression and executes the block if expression is truthy. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/go-template/if + - functions/go-template/else + - functions/go-template/end + - functions/collections/IsSet + returnType: + signatures: [with EXPR] +aliases: [/functions/with] +toc: true +--- + +{{% include "functions/go-template/_common/truthy-falsy.md" %}} + +```go-html-template +{{ $var := "foo" }} +{{ with $var }} + {{ . }} → foo +{{ end }} +``` + +Use with the [`else`] statement: + +```go-html-template +{{ $var := "foo" }} +{{ with $var }} + {{ . }} → foo +{{ else }} + {{ print "var is falsy" }} +{{ end }} +``` + +Initialize a variable, scoped to the current block: + +```go-html-template +{{ with $var := 42 }} + {{ . }} → 42 + {{ $var }} → 42 +{{ end }} +{{ $var }} → undefined +``` + +## Understanding context + +At the top of a page template, the [context] (the dot) is a `Page` object. Inside of the `with` block, the context is bound to the value passed to the `with` statement. + +With this contrived example: + +```go-html-template +{{ with 42 }} + {{ .Title }} +{{ end }} +``` + +Hugo will throw an error: + + can't evaluate field Title in type int + +The error occurs because we are trying to use the `.Title` method on an integer instead of a `Page` object. Inside of the `with` block, if we want to render the page title, we need to get the context passed into the template. + +{{% note %}} +Use the `$` to get the context passed into the template. +{{% /note %}} + +This template will render the page title as desired: + +```go-html-template +{{ with 42 }} + {{ $.Title }} +{{ end }} +``` + +{{% note %}} +Gaining a thorough understanding of context is critical for anyone writing template code. +{{% /note %}} + +[context]: /getting-started/glossary/#context + +{{% include "functions/go-template/_common/text-template.md" %}} + +[`else`]: /functions/go-template/else diff --git a/docs/content/en/functions/hugo/BuildDate.md b/docs/content/en/functions/hugo/BuildDate.md new file mode 100644 index 000000000..1fbdbeac6 --- /dev/null +++ b/docs/content/en/functions/hugo/BuildDate.md @@ -0,0 +1,19 @@ +--- +title: hugo.BuildDate +description: Returns the compile date of the Hugo binary. +categories: [] +keywords: [] +action: + aliases: [] + related: [] + returnType: string + signatures: [hugo.BuildDate] +--- + +The `hugo.BuildDate` function returns the compile date of the Hugo binary, formatted per [RFC 3339]. + +[RFC 3339]: https://datatracker.ietf.org/doc/html/rfc3339 + +```go-html-template +{{ hugo.BuildDate }} → 2023-11-01T17:57:00Z +``` diff --git a/docs/content/en/functions/hugo/CommitHash.md b/docs/content/en/functions/hugo/CommitHash.md new file mode 100644 index 000000000..cd4f2ce92 --- /dev/null +++ b/docs/content/en/functions/hugo/CommitHash.md @@ -0,0 +1,15 @@ +--- +title: hugo.CommitHash +description: Returns the Git commit hash of the Hugo binary. +categories: [] +keywords: [] +action: + aliases: [] + related: [] + returnType: string + signatures: [hugo.CommitHash] +--- + +```go-html-template +{{ hugo.CommitHash }} → a4892a07b41b7b3f1f143140ee4ec0a9a5cf3970 +``` diff --git a/docs/content/en/functions/hugo/Deps.md b/docs/content/en/functions/hugo/Deps.md new file mode 100644 index 000000000..2f3f75e65 --- /dev/null +++ b/docs/content/en/functions/hugo/Deps.md @@ -0,0 +1,66 @@ +--- +title: hugo.Deps +description: Returns a slice of project dependencies, either Hugo Modules or local theme components. +categories: [] +keywords: [] +action: + aliases: [] + related: [] + returnType: '[]hugo.Dependency' + signatures: [hugo.Deps] +--- + +The `hugo.Deps` function returns a slice of project dependencies, either Hugo Modules or local theme components. Each dependency contains: + +Owner +: (`hugo.Dependency`) In the dependency tree, this is the first module that defines this module as a dependency (e.g., `github.com/gohugoio/hugo-mod-bootstrap-scss/v5`). + +Path +: (`string`) The module path or the path below your `themes` directory (e.g., `github.com/gohugoio/hugo-mod-jslibs-dist/popperjs/v2`). + +Replace +: (`hugo.Dependency`) Replaced by this dependency. + +Time +: (`time.Time`) The time that the version was created (e.g., `2022-02-13 15:11:28 +0000 UTC`). + +Vendor +: (`bool`) Reports whether the dependency is vendored. + +Version +: (`string`) The module version (e.g., `v2.21100.20000`). + +An example table listing the dependencies: + +```go-html-template +<h2>Dependencies</h2> +<table class="table table-dark"> + <thead> + <tr> + <th scope="col">#</th> + <th scope="col">Owner</th> + <th scope="col">Path</th> + <th scope="col">Version</th> + <th scope="col">Time</th> + <th scope="col">Vendor</th> + </tr> + </thead> + <tbody> + {{ range $index, $element := hugo.Deps }} + <tr> + <th scope="row">{{ add $index 1 }}</th> + <td>{{ with $element.Owner }}{{ .Path }}{{ end }}</td> + <td> + {{ $element.Path }} + {{ with $element.Replace }} + => {{ .Path }} + {{ end }} + </td> + <td>{{ $element.Version }}</td> + <td>{{ with $element.Time }}{{ . }}{{ end }}</td> + <td>{{ $element.Vendor }}</td> + </tr> + {{ end }} + </tbody> +</table> +``` diff --git a/docs/content/en/functions/hugo/Environment.md b/docs/content/en/functions/hugo/Environment.md new file mode 100644 index 000000000..f130de787 --- /dev/null +++ b/docs/content/en/functions/hugo/Environment.md @@ -0,0 +1,30 @@ +--- +title: hugo.Environment +description: Returns the current running environment. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/hugo/IsDevelopment + - functions/hugo/IsProduction + returnType: string + signatures: [hugo.Environment] +--- + +The `hugo.Environment` function returns the current running [environment] as defined through the `--environment` command line flag. + +```go-html-template +{{ hugo.Environment }} → production +``` + +Command line examples: + +Command|Environment +:--|:-- +`hugo`|`production` +`hugo --environment staging`|`staging` +`hugo server`|`development` +`hugo server --environment staging`|`staging` + +[environment]: /getting-started/glossary/#environment diff --git a/docs/content/en/functions/hugo/Generator.md b/docs/content/en/functions/hugo/Generator.md new file mode 100644 index 000000000..907c37681 --- /dev/null +++ b/docs/content/en/functions/hugo/Generator.md @@ -0,0 +1,15 @@ +--- +title: hugo.Generator +description: Renders an HTML meta element identifying the software that generated the site. +categories: [] +keywords: [] +action: + aliases: [] + related: [] + returnType: template.HTML + signatures: [hugo.Generator] +--- + +```go-html-template +{{ hugo.Generator }} → <meta name="generator" content="Hugo 0.122.0"> +``` diff --git a/docs/content/en/functions/hugo/GoVersion.md b/docs/content/en/functions/hugo/GoVersion.md new file mode 100644 index 000000000..1640c3862 --- /dev/null +++ b/docs/content/en/functions/hugo/GoVersion.md @@ -0,0 +1,17 @@ +--- +title: hugo.GoVersion +description: Returns the Go version used to compile the Hugo binary +categories: [] +keywords: [] +action: + aliases: [] + related: [] + returnType: string + signatures: [hugo.GoVersion] +--- + +{{< new-in 0.101.0 >}} + +```go-html-template +{{ hugo.GoVersion }} → go1.21.1 +``` diff --git a/docs/content/en/functions/hugo/IsDevelopment.md b/docs/content/en/functions/hugo/IsDevelopment.md new file mode 100644 index 000000000..9926b67c9 --- /dev/null +++ b/docs/content/en/functions/hugo/IsDevelopment.md @@ -0,0 +1,19 @@ +--- +title: hugo.IsDevelopment +description: Reports whether the current running environment is "development". +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/hugo/IsProduction + - functions/hugo/Environment + returnType: bool + signatures: [hugo.IsDevelopment] +--- + +{{< new-in 0.120.0 >}} + +```go-html-template +{{ hugo.IsDevelopment }} → true/false +``` diff --git a/docs/content/en/functions/hugo/IsExtended.md b/docs/content/en/functions/hugo/IsExtended.md new file mode 100644 index 000000000..84b68e6d3 --- /dev/null +++ b/docs/content/en/functions/hugo/IsExtended.md @@ -0,0 +1,15 @@ +--- +title: hugo.IsExtended +description: Reports whether the Hugo binary is the extended version. +categories: [] +keywords: [] +action: + aliases: [] + related: [] + returnType: bool + signatures: [hugo.IsExtended] +--- + +```go-html-template +{{ hugo.IsExtended }} → true/false +``` diff --git a/docs/content/en/functions/hugo/IsProduction.md b/docs/content/en/functions/hugo/IsProduction.md new file mode 100644 index 000000000..7e9bda0e3 --- /dev/null +++ b/docs/content/en/functions/hugo/IsProduction.md @@ -0,0 +1,17 @@ +--- +title: hugo.IsProduction +description: Reports whether the current running environment is "production". +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/hugo/IsDevelopment + - functions/hugo/Environment + returnType: bool + signatures: [hugo.IsProduction] +--- + +```go-html-template +{{ hugo.IsProduction }} → true/false +``` diff --git a/docs/content/en/functions/hugo/IsServer.md b/docs/content/en/functions/hugo/IsServer.md new file mode 100644 index 000000000..942261007 --- /dev/null +++ b/docs/content/en/functions/hugo/IsServer.md @@ -0,0 +1,17 @@ +--- +title: hugo.IsServer +description: Reports whether the built-in development server is running. +categories: [] +keywords: [] +action: + aliases: [] + related: [] + returnType: bool + signatures: [hugo.IsServer] +--- + +{{< new-in 0.120.0 >}} + +```go-html-template +{{ hugo.IsServer }} → true/false +``` diff --git a/docs/content/en/functions/hugo/Version.md b/docs/content/en/functions/hugo/Version.md new file mode 100644 index 000000000..5a312e81a --- /dev/null +++ b/docs/content/en/functions/hugo/Version.md @@ -0,0 +1,15 @@ +--- +title: hugo.Version +description: Returns the current version of the Hugo binary. +categories: [] +keywords: [] +action: + aliases: [] + related: [] + returnType: hugo.VersionString + signatures: [hugo.Version] +--- + +```go-html-template +{{ hugo.Version }} → 0.122.0 +``` diff --git a/docs/content/en/functions/hugo/WorkingDir.md b/docs/content/en/functions/hugo/WorkingDir.md new file mode 100644 index 000000000..ac3835ea8 --- /dev/null +++ b/docs/content/en/functions/hugo/WorkingDir.md @@ -0,0 +1,15 @@ +--- +title: hugo.WorkingDir +description: Returns the project working directory. +categories: [] +keywords: [] +action: + aliases: [] + related: [] + returnType: string + signatures: [hugo.WorkingDir] +--- + +```go-html-template +{{ hugo.WorkingDir }} → /home/user/projects/my-hugo-site +``` diff --git a/docs/content/en/functions/hugo/_index.md b/docs/content/en/functions/hugo/_index.md new file mode 100644 index 000000000..c3ad686da --- /dev/null +++ b/docs/content/en/functions/hugo/_index.md @@ -0,0 +1,12 @@ +--- +title: Hugo functions +linkTitle: hugo +description: Template functions to access information about the Hugo application and the current environment. +categories: [] +keywords: [] +menu: + docs: + parent: functions +--- + +Use these functions to access information about the Hugo application and the current environment. diff --git a/docs/content/en/functions/images/AutoOrient.md b/docs/content/en/functions/images/AutoOrient.md new file mode 100644 index 000000000..8f27a95d8 --- /dev/null +++ b/docs/content/en/functions/images/AutoOrient.md @@ -0,0 +1,52 @@ +--- +title: images.AutoOrient +description: Returns an image filter that rotates and flips an image as needed per its EXIF orientation tag. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/images/Filter + - methods/resource/Filter + returnType: images.filter + signatures: [images.AutoOrient] +toc: true +--- + +{{< new-in 0.121.2 >}} + +## Usage + +Create the filter: + +```go-html-template +{{ $filter := images.AutoOrient }} +``` + +{{% include "functions/images/_common/apply-image-filter.md" %}} + +{{% note %}} +When using with other filters, specify `images.AutoOrient` first. +{{% /note %}} + +```go-html-template +{{ $filters := slice + images.AutoOrient + (images.Process "resize 200x") +}} +{{ with resources.Get "images/original.jpg" }} + {{ with images.Filter $filters . }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> + {{ end }} +{{ end }} +``` + +## Example + +{{< img + src="images/examples/landscape-exif-orientation-5.jpg" + alt="Zion National Park" + filter="AutoOrient" + filterArgs="" + example=true +>}} diff --git a/docs/content/en/functions/images/Brightness.md b/docs/content/en/functions/images/Brightness.md new file mode 100644 index 000000000..0001bcba8 --- /dev/null +++ b/docs/content/en/functions/images/Brightness.md @@ -0,0 +1,36 @@ +--- +title: images.Brightness +description: Returns an image filter that changes the brightness of an image. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/images/Filter + - methods/resource/Filter + returnType: images.filter + signatures: [images.Brightness PERCENTAGE] +toc: true +--- + +The percentage must be in the range [-100, 100] where 0 has no effect. A value of `-100` produces a solid black image, and a value of `100` produces a solid white image. + +## Usage + +Create the image filter: + +```go-html-template +{{ $filter := images.Brightness 12 }} +``` + +{{% include "functions/images/_common/apply-image-filter.md" %}} + +## Example + +{{< img + src="images/examples/zion-national-park.jpg" + alt="Zion National Park" + filter="Brightness" + filterArgs="12" + example=true +>}} diff --git a/docs/content/en/functions/images/ColorBalance.md b/docs/content/en/functions/images/ColorBalance.md new file mode 100644 index 000000000..29829f9e6 --- /dev/null +++ b/docs/content/en/functions/images/ColorBalance.md @@ -0,0 +1,36 @@ +--- +title: images.ColorBalance +description: Returns an image filter that changes the color balance of an image. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/images/Filter + - methods/resource/Filter + returnType: images.filter + signatures: [images.ColorBalance PCTRED PCTGREEN PCTBLUE] +toc: true +--- + +The percentage for each channel (red, green, blue) must be in the range [-100, 500]. + +## Usage + +Create the filter: + +```go-html-template +{{ $filter := images.ColorBalance -10 10 50 }} +``` + +{{% include "functions/images/_common/apply-image-filter.md" %}} + +## Example + +{{< img + src="images/examples/zion-national-park.jpg" + alt="Zion National Park" + filter="ColorBalance" + filterArgs="-10,10,50" + example=true +>}} diff --git a/docs/content/en/functions/images/Colorize.md b/docs/content/en/functions/images/Colorize.md new file mode 100644 index 000000000..c974103b9 --- /dev/null +++ b/docs/content/en/functions/images/Colorize.md @@ -0,0 +1,40 @@ +--- +title: images.Colorize +description: Returns an image filter that produces a colorized version of an image. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/images/Filter + - methods/resource/Filter + returnType: images.filter + signatures: [images.Colorize HUE SATURATION PERCENTAGE] +toc: true +--- + +The hue is the angle on the color wheel, typically in the range [0, 360]. + +The saturation must be in the range [0, 100]. + +The percentage specifies the strength of the effect, and must be in the range [0, 100]. + +## Usage + +Create the filter: + +```go-html-template +{{ $filter := images.Colorize 180 50 20 }} +``` + +{{% include "functions/images/_common/apply-image-filter.md" %}} + +## Example + +{{< img + src="images/examples/zion-national-park.jpg" + alt="Zion National Park" + filter="Colorize" + filterArgs="180,50,20" + example=true +>}} diff --git a/docs/content/en/functions/images/Config.md b/docs/content/en/functions/images/Config.md new file mode 100644 index 000000000..0a4d225bc --- /dev/null +++ b/docs/content/en/functions/images/Config.md @@ -0,0 +1,36 @@ +--- +title: images.Config +description: Returns an image.Config structure from the image at the specified path, relative to the working directory. +categories: [] +keywords: [] +action: + aliases: [] + related: [] + returnType: image.Config + signatures: [images.Config PATH] +aliases: [/functions/imageconfig] +--- + +See [image processing] for an overview of Hugo's image pipeline. + +[image processing]: /content-management/image-processing/ + +```go-html-template +{{ $ic := images.Config "/static/images/a.jpg" }} + +{{ $ic.Width }} → 600 (int) +{{ $ic.Height }} → 400 (int) +``` + +Supported image formats include GIF, JPEG, PNG, TIFF, and WebP. + +{{% note %}} +This is a legacy function, superseded by the [`Width`] and [`Height`] methods for [global], [page], and [remote] resources. See the [image processing] section for details. + +[`Width`]: /methods/resource/width +[`Height`]: /methods/resource/height +[global]: /getting-started/glossary/#global-resource +[image processing]: /content-management/image-processing +[page]: /getting-started/glossary/#page-resource +[remote]: /getting-started/glossary/#remote-resource +{{% /note %}} diff --git a/docs/content/en/functions/images/Contrast.md b/docs/content/en/functions/images/Contrast.md new file mode 100644 index 000000000..532ae8c9c --- /dev/null +++ b/docs/content/en/functions/images/Contrast.md @@ -0,0 +1,36 @@ +--- +title: images.Contrast +description: Returns an image filter that changes the contrast of an image. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/images/Filter + - methods/resource/Filter + returnType: images.filter + signatures: [images.Contrast PERCENTAGE] +toc: true +--- + +The percentage must be in the range [-100, 100] where 0 has no effect. A value of `-100` produces a solid grey image, and a value of `100` produces an over-contrasted image. + +## Usage + +Create the filter: + +```go-html-template +{{ $filter := images.Contrast -20 }} +``` + +{{% include "functions/images/_common/apply-image-filter.md" %}} + +## Example + +{{< img + src="images/examples/zion-national-park.jpg" + alt="Zion National Park" + filter="Contrast" + filterArgs="-20" + example=true +>}} diff --git a/docs/content/en/functions/images/Filter.md b/docs/content/en/functions/images/Filter.md new file mode 100644 index 000000000..450a64814 --- /dev/null +++ b/docs/content/en/functions/images/Filter.md @@ -0,0 +1,67 @@ +--- +title: images.Filter +description: Applies one or more image filters to the given image resource. +categories: [] +keywords: [] +action: + aliases: [] + related: + - methods/resource/Filter + returnType: images.ImageResource + signatures: [images.Filter FILTERS... IMAGE] +toc: true +--- + +Apply one or more [image filters](#image-filters) to the given image. + +To apply a single filter: + +```go-html-template +{{ with resources.Get "images/original.jpg" }} + {{ with images.Filter images.Grayscale . }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> + {{ end }} +{{ end }} +``` + +To apply two or more filters, executing from left to right: + +```go-html-template +{{ $filters := slice + images.Grayscale + (images.GaussianBlur 8) +}} +{{ with resources.Get "images/original.jpg" }} + {{ with images.Filter $filters . }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> + {{ end }} +{{ end }} +``` + +You can also apply image filters using the [`Filter`] method on a `Resource` object. + +[`Filter`]: /methods/resource/filter + +## Example + +```go-html-template +{{ with resources.Get "images/original.jpg" }} + {{ with images.Filter images.Grayscale . }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> + {{ end }} +{{ end }} +``` + +{{< img + src="images/examples/zion-national-park.jpg" + alt="Zion National Park" + filter="Grayscale" + filterArgs="" + example=true +>}} + +## Image filters + +Use any of these filters with the `images.Filter` function, or with the `Filter` method on a `Resource` object. + +{{< list-pages-in-section path=/functions/images filter=functions_images_no_filters filterType=exclude >}} diff --git a/docs/content/en/functions/images/Gamma.md b/docs/content/en/functions/images/Gamma.md new file mode 100644 index 000000000..affbdcfa8 --- /dev/null +++ b/docs/content/en/functions/images/Gamma.md @@ -0,0 +1,36 @@ +--- +title: images.Gamma +description: Returns an image filter that performs gamma correction on an image. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/images/Filter + - methods/resource/Filter + returnType: images.filter + signatures: [images.Gamma GAMMA] +toc: true +--- + +The gamma value must be positive. A value greater than 1 lightens the image, while a value less than 1 darkens the image. The filter has no effect when the gamma value is 1. + +## Usage + +Create the filter: + +```go-html-template +{{ $filter := images.Gamma 1.667 }} +``` + +{{% include "functions/images/_common/apply-image-filter.md" %}} + +## Example + +{{< img + src="images/examples/zion-national-park.jpg" + alt="Zion National Park" + filter="Gamma" + filterArgs="1.667" + example=true +>}} diff --git a/docs/content/en/functions/images/GaussianBlur.md b/docs/content/en/functions/images/GaussianBlur.md new file mode 100644 index 000000000..e2f49a847 --- /dev/null +++ b/docs/content/en/functions/images/GaussianBlur.md @@ -0,0 +1,36 @@ +--- +title: images.GaussianBlur +description: Returns an image filter that applies a gaussian blur to an image. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/images/Filter + - methods/resource/Filter + returnType: images.filter + signatures: [images.GaussianBlur SIGMA] +toc: true +--- + +The sigma value must be positive, and indicates how much the image will be blurred. The blur-affected radius is approximately 3 times the sigma value. + +## Usage + +Create the filter: + +```go-html-template +{{ $filter := images.GaussianBlur 5 }} +``` + +{{% include "functions/images/_common/apply-image-filter.md" %}} + +## Example + +{{< img + src="images/examples/zion-national-park.jpg" + alt="Zion National Park" + filter="GaussianBlur" + filterArgs="5" + example=true +>}} diff --git a/docs/content/en/functions/images/Grayscale.md b/docs/content/en/functions/images/Grayscale.md new file mode 100644 index 000000000..d8a89b7f2 --- /dev/null +++ b/docs/content/en/functions/images/Grayscale.md @@ -0,0 +1,34 @@ +--- +title: images.Grayscale +description: Returns an image filter that produces a grayscale version of an image. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/images/Filter + - methods/resource/Filter + returnType: images.filter + signatures: [images.Grayscale] +toc: true +--- + +## Usage + +Create the filter: + +```go-html-template +{{ $filter := images.Grayscale }} +``` + +{{% include "functions/images/_common/apply-image-filter.md" %}} + +## Example + +{{< img + src="images/examples/zion-national-park.jpg" + alt="Zion National Park" + filter="Grayscale" + filterArgs="" + example=true +>}} diff --git a/docs/content/en/functions/images/Hue.md b/docs/content/en/functions/images/Hue.md new file mode 100644 index 000000000..6eafac437 --- /dev/null +++ b/docs/content/en/functions/images/Hue.md @@ -0,0 +1,36 @@ +--- +title: images.Hue +description: Returns an image filter that rotates the hue of an image. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/images/Filter + - methods/resource/Filter + returnType: images.filter + signatures: [images.Hue SHIFT] +toc: true +--- + +The hue angle shift is typically in the range [-180, 180] where 0 has no effect. + +## Usage + +Create the filter: + +```go-html-template +{{ $filter := images.Hue -15 }} +``` + +{{% include "functions/images/_common/apply-image-filter.md" %}} + +## Example + +{{< img + src="images/examples/zion-national-park.jpg" + alt="Zion National Park" + filter="Hue" + filterArgs="-15" + example=true +>}} diff --git a/docs/content/en/functions/images/Invert.md b/docs/content/en/functions/images/Invert.md new file mode 100644 index 000000000..1ee85e514 --- /dev/null +++ b/docs/content/en/functions/images/Invert.md @@ -0,0 +1,34 @@ +--- +title: images.Invert +description: Returns an image filter that negates the colors of an image. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/images/Filter + - methods/resource/Filter + returnType: images.filter + signatures: [images.Invert] +toc: true +--- + +## Usage + +Create the filter: + +```go-html-template +{{ $filter := images.Invert }} +``` + +{{% include "functions/images/_common/apply-image-filter.md" %}} + +## Example + +{{< img + src="images/examples/zion-national-park.jpg" + alt="Zion National Park" + filter="Invert" + filterArgs="" + example=true +>}} diff --git a/docs/content/en/functions/images/Opacity.md b/docs/content/en/functions/images/Opacity.md new file mode 100644 index 000000000..6a74fd081 --- /dev/null +++ b/docs/content/en/functions/images/Opacity.md @@ -0,0 +1,52 @@ +--- +title: images.Opacity +description: Returns an image filter that changes the opacity of an image. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/images/Filter + - methods/resource/Filter + returnType: images.filter + signatures: [images.Opacity OPACITY] +toc: true +--- + +{{< new-in 0.119.0 >}} + +The opacity value must be in the range [0, 1]. A value of `0` produces a transparent image, and a value of `1` produces an opaque image (no transparency). + +## Usage + +Create the filter: + +```go-html-template +{{ $filter := images.Opacity 0.65 }} +``` + +{{% include "functions/images/_common/apply-image-filter.md" %}} + +The `images.Opacity` filter is most useful for target formats such as PNG and WebP that support transparency. If the source image does not support transparency, combine this filter with the `images.Process` filter: + +```go-html-template +{{ with resources.Get "images/original.jpg" }} + {{ $filters := slice + (images.Opacity 0.65) + (images.Process "png") + }} + {{ with . | images.Filter $filters }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> + {{ end }} +{{ end }} +``` + +## Example + +{{< img + src="images/examples/zion-national-park.jpg" + alt="Zion National Park" + filter="Opacity" + filterArgs="0.65" + example=true +>}} diff --git a/docs/content/en/functions/images/Overlay.md b/docs/content/en/functions/images/Overlay.md new file mode 100644 index 000000000..39e62b121 --- /dev/null +++ b/docs/content/en/functions/images/Overlay.md @@ -0,0 +1,52 @@ +--- +title: images.Overlay +description: Returns an image filter that overlays the source image at the given coordinates, relative to the upper left corner. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/images/Filter + - methods/resource/Filter + returnType: images.filter + signatures: [images.Overlay RESOURCE X Y] +toc: true +--- + +## Usage + +Capture the overlay image as a resource: + +```go-html-template +{{ $overlay := "" }} +{{ $path := "images/logo.png" }} +{{ with resources.Get $path }} + {{ $overlay = . }} +{{ else }} + {{ errorf "Unable to get resource %q" $path }} +{{ end }} +``` + +The overlay image can be a [global resource], a [page resource], or a [remote resource]. + +[global resource]: /getting-started/glossary/#global-resource +[page resource]: /getting-started/glossary/#page-resource +[remote resource]: /getting-started/glossary/#remote-resource + +Create the filter: + +```go-html-template +{{ $filter := images.Overlay $overlay 20 20 }} +``` + +{{% include "functions/images/_common/apply-image-filter.md" %}} + +## Example + +{{< img + src="images/examples/zion-national-park.jpg" + alt="Zion National Park" + filter="Overlay" + filterArgs="images/logos/logo-64x64.png,20,20" + example=true +>}} diff --git a/docs/content/en/functions/images/Padding.md b/docs/content/en/functions/images/Padding.md new file mode 100644 index 000000000..139626596 --- /dev/null +++ b/docs/content/en/functions/images/Padding.md @@ -0,0 +1,75 @@ +--- +title: images.Padding +description: Returns an image filter that resizes the image canvas without resizing the image. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/images/Filter + - methods/resource/Filter + returnType: images.filter + signatures: ['images.Padding V1 [V2] [V3] [V4] [COLOR]'] +toc: true +--- + +{{< new-in 0.120.0 >}} + +The last argument is the canvas color, expressed as an RGB or RGBA [hexadecimal color]. The default value is `ffffffff` (opaque white). The preceding arguments are the padding values, in pixels, using the CSS [shorthand property] syntax. Negative padding values will crop the image. + +[hexadecimal color]: https://developer.mozilla.org/en-US/docs/Web/CSS/hex-color +[shorthand property]: https://developer.mozilla.org/en-US/docs/Web/CSS/Shorthand_properties#edges_of_a_box + +## Usage + +Create the filter: + +```go-html-template +{{ $filter := images.Padding 20 40 "#976941" }} +``` + +{{% include "functions/images/_common/apply-image-filter.md" %}} + +Combine with the [`Colors`] method to create a border with one of the image's most dominant colors: + +[`Colors`]: /methods/resource/colors + +```go-html-template +{{ with resources.Get "images/original.jpg" }} + {{ $filter := images.Padding 20 40 (index .Colors 2) }} + {{ with . | images.Filter $filter }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> + {{ end }} +{{ end }} +``` + +## Example + +{{< img + src="images/examples/zion-national-park.jpg" + alt="Zion National Park" + filter="Padding" + filterArgs="20,40,20,40,#976941" + example=true +>}} + +## Other recipes + +This example resizes an image to 300px wide, converts it to the WebP format, adds 20px vertical padding and 50px horizontal padding, then sets the canvas color to dark green with 33% opacity. + +Conversion to WebP is required to support transparency. PNG and WebP images have an alpha channel; JPEG and GIF do not. + +```go-html-template +{{ $img := resources.Get "images/a.jpg" }} +{{ $filters := slice + (images.Process "resize 300x webp") + (images.Padding 20 50 "#0705") +}} +{{ $img = $img.Filter $filters }} +``` + +To add a 2px gray border to an image: + +```go-html-template +{{ $img = $img.Filter (images.Padding 2 "#777") }} +``` diff --git a/docs/content/en/functions/images/Pixelate.md b/docs/content/en/functions/images/Pixelate.md new file mode 100644 index 000000000..2016877ed --- /dev/null +++ b/docs/content/en/functions/images/Pixelate.md @@ -0,0 +1,34 @@ +--- +title: images.Pixelate +description: Returns an image filter that applies a pixelation effect to an image. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/images/Filter + - methods/resource/Filter + returnType: images.filter + signatures: [images.Pixelate SIZE] +toc: true +--- + +## Usage + +Create the filter: + +```go-html-template +{{ $filter := images.Pixelate 4 }} +``` + +{{% include "functions/images/_common/apply-image-filter.md" %}} + +## Example + +{{< img + src="images/examples/zion-national-park.jpg" + alt="Zion National Park" + filter="Pixelate" + filterArgs="4" + example=true +>}} diff --git a/docs/content/en/functions/images/Process.md b/docs/content/en/functions/images/Process.md new file mode 100644 index 000000000..a5e4d88dd --- /dev/null +++ b/docs/content/en/functions/images/Process.md @@ -0,0 +1,115 @@ +--- +title: images.Process +description: Returns an image filter that processes the given image using the given specification. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/images/Filter + - methods/resource/Filter + - methods/resource/Process + returnType: images.filter + signatures: [images.Process SPEC] +toc: true +--- + +{{< new-in 0.119.0 >}} + +This filter has the same options as the [`Process`] method on a `Resource` object, but using it as a filter may be more effective if you need to apply multiple filters to an image. + +[`Process`]: /methods/resource/process + +The process specification is a space-delimited, case-insensitive list of one or more of the following in any sequence: + +action +: Specify zero or one of `crop`, `fill`, `fit`, or `resize`. If you specify an action you must also provide dimensions. See [details](content-management/image-processing/#image-processing-methods). + +```go-html-template +{{ $filter := images.Process "resize 300x" }} +``` + +dimensions +: Required if you specify an action. Provide width _or_ height when using `resize`, else provide both width _and_ height. See [details](/content-management/image-processing/#dimensions). + +```go-html-template +{{ $filter := images.Process "crop 200x200" }} +``` + +anchor +: Use with the `crop` or `fill` action. Specify zero or one of `TopLeft`, `Top`, `TopRight`, `Left`, `Center`, `Right`, `BottomLeft`, `Bottom`, `BottomRight`, or `Smart`. Default is `Smart`. See [details](/content-management/image-processing/#anchor). + +```go-html-template +{{ $filter := images.Process "crop 200x200 center" }} +``` + +rotation +: Typically specify zero or one of `r90`, `r180`, or `r270`. Also supports arbitrary rotation angles. See [details](/content-management/image-processing/#rotation). + +```go-html-template +{{ $filter := images.Process "r90" }} +{{ $filter := images.Process "crop 200x200 center r90" }} +``` + +target format +: Specify zero or one of `gif`, `jpeg`, `png`, `tiff`, or `webp`. See [details](/content-management/image-processing/#target-format). + +```go-html-template +{{ $filter := images.Process "webp" }} +{{ $filter := images.Process "crop 200x200 center r90 webp" }} +``` + +quality +: Applicable to JPEG and WebP images. Optionally specify `qN` where `N` is an integer in the range [0, 100]. Default is `75`. See [details](/content-management/image-processing/#quality). + +```go-html-template +{{ $filter := images.Process "q50" }} +{{ $filter := images.Process "crop 200x200 center r90 webp q50" }} +``` + +hint +: Applicable to WebP images and equivalent to the `-preset` flag for the [`cwebp`] encoder. Specify zero or one of `drawing`, `icon`, `photo`, `picture`, or `text`. Default is `photo`. See [details](/content-management/image-processing/#hint). + +[`cwebp`]: https://developers.google.com/speed/webp/docs/cwebp + + +```go-html-template +{{ $filter := images.Process "webp" "icon" }} +{{ $filter := images.Process "crop 200x200 center r90 webp q50 icon" }} +``` + +background color +: When converting a PNG or WebP with transparency to a format that does not support transparency, optionally specify a background color using a 3-digit or a 6-digit hexadecimal color code. Default is `#ffffff` (white). See [details](/content-management/image-processing/#background-color). + +```go-html-template +{{ $filter := images.Process "jpeg #000" }} +{{ $filter := images.Process "crop 200x200 center r90 q50 jpeg #000" }} +``` + +resampling filter +: Typically specify zero or one of `Box`, `Lanczos`, `CatmullRom`, `MitchellNetravali`, `Linear`, or `NearestNeighbor`. Other resampling filters are available. See [details](/content-management/image-processing/#resampling-filter). + +```go-html-template +{{ $filter := images.Process "resize 300x lanczos" }} +{{ $filter := images.Process "resize 300x r90 q50 jpeg #000 lanczos" }} +``` + +## Usage + +Create a filter: + +```go-html-template +{{ $filter := images.Process "resize 256x q40 webp" }} +``` + +{{% include "functions/images/_common/apply-image-filter.md" %}} + +## Example + +{{< img + src="images/examples/zion-national-park.jpg" + alt="Zion National Park" + filter="Process" + filterArgs="resize 256x q40 webp" + example=true +>}} diff --git a/docs/content/en/functions/images/Saturation.md b/docs/content/en/functions/images/Saturation.md new file mode 100644 index 000000000..118bd0213 --- /dev/null +++ b/docs/content/en/functions/images/Saturation.md @@ -0,0 +1,36 @@ +--- +title: images.Saturation +description: Returns an image filter that changes the saturation of an image. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/images/Filter + - methods/resource/Filter + returnType: images.filter + signatures: [images.Saturation PERCENTAGE] +toc: true +--- + +The percentage must be in the range [-100, 500] where 0 has no effect. + +## Usage + +Create the filter: + +```go-html-template +{{ $filter := images.Saturation 65 }} +``` + +{{% include "functions/images/_common/apply-image-filter.md" %}} + +## Example + +{{< img + src="images/examples/zion-national-park.jpg" + alt="Zion National Park" + filter="Saturation" + filterArgs="65" + example=true +>}} diff --git a/docs/content/en/functions/images/Sepia.md b/docs/content/en/functions/images/Sepia.md new file mode 100644 index 000000000..9f0b7adfb --- /dev/null +++ b/docs/content/en/functions/images/Sepia.md @@ -0,0 +1,36 @@ +--- +title: images.Sepia +description: Returns an image filter that produces a sepia-toned version of an image. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/images/Filter + - methods/resource/Filter + returnType: images.filter + signatures: [images.Sepia PERCENTAGE] +toc: true +--- + +The percentage must be in the range [0, 100] where 0 has no effect. + +## Usage + +Create the filter: + +```go-html-template +{{ $filter := images.Sepia 75 }} +``` + +{{% include "functions/images/_common/apply-image-filter.md" %}} + +## Example + +{{< img + src="images/examples/zion-national-park.jpg" + alt="Zion National Park" + filter="Sepia" + filterArgs="75" + example=true +>}} diff --git a/docs/content/en/functions/images/Sigmoid.md b/docs/content/en/functions/images/Sigmoid.md new file mode 100644 index 000000000..32765f923 --- /dev/null +++ b/docs/content/en/functions/images/Sigmoid.md @@ -0,0 +1,40 @@ +--- +title: images.Sigmoid +description: Returns an image filter that changes the contrast of an image using a sigmoidal function. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/images/Filter + - methods/resource/Filter + returnType: images.filter + signatures: [images.Sigmoid MIDPOINT FACTOR] +toc: true +--- + +This is a non-linear contrast change useful for photo adjustments; it preserves highlight and shadow detail. + +The midpoint is the midpoint of contrast. It must be in the range [0, 1], typically 0.5. + +The factor indicates how much to increase or decrease the contrast, typically in the range [-10, 10] where 0 has no effect. A positive value increases contrast, while a negative value decrease contrast. + +## Usage + +Create the filter: + +```go-html-template +{{ $filter := images.Sigmoid 0.6 -4 }} +``` + +{{% include "functions/images/_common/apply-image-filter.md" %}} + +## Example + +{{< img + src="images/examples/zion-national-park.jpg" + alt="Zion National Park" + filter="Sigmoid" + filterArgs="0.6,-4" + example=true +>}} diff --git a/docs/content/en/functions/images/Text.md b/docs/content/en/functions/images/Text.md new file mode 100644 index 000000000..8c6670d42 --- /dev/null +++ b/docs/content/en/functions/images/Text.md @@ -0,0 +1,97 @@ +--- +title: images.Text +description: Returns an image filter that adds text to an image. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/images/Filter + - methods/resource/Filter + returnType: images.filter + signatures: ['images.Text TEXT [OPTIONS]'] +toc: true +--- + +## Options + +Although none of the options are required, at a minimum you will want to set the `size` to be some reasonable percentage of the image height. + +color +: (`string`) The font color, either a 3-digit or 6-digit hexadecimal color code. Default is `#ffffff` (white). + +font +: (`resource.Resource`) The font can be a [global resource], a [page resource], or a [remote resource]. Default is [Go Regular], a proportional sans-serif TrueType font. + +[Go Regular]: https://go.dev/blog/go-fonts#sans-serif + +linespacing +: (`int`) The number of pixels between each line. For a line height of 1.4, set the `linespacing` to 0.4 multiplied by the `size`. Default is `2`. + +size +: (`int`) The font size in pixels. Default is `20`. + +x +: (`int`) The horizontal offset, in pixels, relative to the left of the image. Default is `10`. + +y +: (`int`) The vertical offset, in pixels, relative to the top of the image. Default is `10`. + +[global resource]: /getting-started/glossary/#global-resource +[page resource]: /getting-started/glossary/#page-resource +[remote resource]: /getting-started/glossary/#remote-resource + +## Usage + +Capture the font as a resource: + +```go-html-template +{{ $font := "" }} +{{ $path := "https://github.com/google/fonts/raw/main/ofl/lato/Lato-Regular.ttf" }} +{{ with resources.GetRemote $path }} + {{ with .Err }} + {{ errorf "%s" . }} + {{ else }} + {{ $font = . }} + {{ end }} +{{ else }} + {{ errorf "Unable to get resource %q" $path }} +{{ end }} +``` + +Create the options map: + +```go-html-template +{{ $opts := dict + "color" "#fbfaf5" + "font" $font + "linespacing" 8 + "size" 40 + "x" 25 + "y" 190 +}} +``` + +Set the text: + +```go-html-template +{{ $text := "Zion National Park" }} +``` + +Create the filter: + +```go-html-template +{{ $filter := images.Text $text $opts }} +``` + +{{% include "functions/images/_common/apply-image-filter.md" %}} + +## Example + +{{< img + src="images/examples/zion-national-park.jpg" + alt="Zion National Park" + filter="Text" + filterArgs="Zion National Park,25,190,40,1.2,#fbfaf5" + example=true +>}} diff --git a/docs/content/en/functions/images/UnsharpMask.md b/docs/content/en/functions/images/UnsharpMask.md new file mode 100644 index 000000000..57a74a54a --- /dev/null +++ b/docs/content/en/functions/images/UnsharpMask.md @@ -0,0 +1,40 @@ +--- +title: images.UnsharpMask +description: Returns an image filter that sharpens an image. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/images/Filter + - methods/resource/Filter + returnType: images.filter + signatures: [images.UnsharpMask SIGMA AMOUNT THRESHOLD] +toc: true +--- + +The sigma parameter is used in a gaussian function and affects the radius of effect. Sigma must be positive. The sharpen radius is approximately 3 times the sigma value. + +The amount parameter controls how much darker and how much lighter the edge borders become. Typically between 0.5 and 1.5. + +The threshold parameter controls the minimum brightness change that will be sharpened. Typically between 0 and 0.05. + +## Usage + +Create the filter: + +```go-html-template +{{ $filter := images.UnsharpMask 10 0.4 0.03 }} +``` + +{{% include "functions/images/_common/apply-image-filter.md" %}} + +## Example + +{{< img + src="images/examples/zion-national-park.jpg" + alt="Zion National Park" + filter="UnsharpMask" + filterArgs="10,0.4,0.03" + example=true +>}} diff --git a/docs/content/en/functions/images/_common/_index.md b/docs/content/en/functions/images/_common/_index.md new file mode 100644 index 000000000..47d5812fb --- /dev/null +++ b/docs/content/en/functions/images/_common/_index.md @@ -0,0 +1,13 @@ +--- +cascade: + _build: + list: never + publishResources: false + render: never +--- + +<!-- +Files within this headless branch bundle are markdown snippets. Each file must contain front matter delimiters, though front matter fields are not required. + +Include the rendered content using the "include" shortcode. +--> diff --git a/docs/content/en/functions/images/_common/apply-image-filter.md b/docs/content/en/functions/images/_common/apply-image-filter.md new file mode 100644 index 000000000..acd3a733d --- /dev/null +++ b/docs/content/en/functions/images/_common/apply-image-filter.md @@ -0,0 +1,27 @@ +--- +# Do not remove front matter. +--- + +Apply the filter using the [`images.Filter`] function: + +[`images.Filter`]: /functions/images/filter + +```go-html-template +{{ with resources.Get "images/original.jpg" }} + {{ with . | images.Filter $filter }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> + {{ end }} +{{ end }} +``` + +You can also apply the filter using the [`Filter`] method on a `Resource` object: + +[`Filter`]: methods/resource/filter + +```go-html-template +{{ with resources.Get "images/original.jpg" }} + {{ with .Filter $filter }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> + {{ end }} +{{ end }} +``` diff --git a/docs/content/en/functions/images/_index.md b/docs/content/en/functions/images/_index.md new file mode 100644 index 000000000..13542ea73 --- /dev/null +++ b/docs/content/en/functions/images/_index.md @@ -0,0 +1,12 @@ +--- +title: Image functions +linkTitle: images +description: Use these functions to create an image filter, apply an image filter to an image, and to retrieve image information. +categories: [] +keywords: [] +menu: + docs: + parent: functions +--- + +Use these functions to create an image filter, apply an image filter to an image, and to retrieve image information. diff --git a/docs/content/en/functions/inflect/Humanize.md b/docs/content/en/functions/inflect/Humanize.md new file mode 100644 index 000000000..71b4a5fd2 --- /dev/null +++ b/docs/content/en/functions/inflect/Humanize.md @@ -0,0 +1,26 @@ +--- +title: inflect.Humanize +description: Returns the humanized version of the input with the first letter capitalized. +categories: [] +keywords: [] +action: + aliases: [humanize] + related: + - functions/inflect/Pluralize + - functions/inflect/Singularize + returnType: string + signatures: [inflect.Humanize INPUT] +aliases: [/functions/humanize] +--- + +```go-html-template +{{ humanize "my-first-post" }} → My first post +{{ humanize "myCamelPost" }} → My camel post +``` + +If the input is an integer or a string representation of an integer, humanize returns the number with the proper ordinal appended. + +```go-html-template +{{ humanize "52" }} → 52nd +{{ humanize 103 }} → 103rd +``` diff --git a/docs/content/en/functions/inflect/Pluralize.md b/docs/content/en/functions/inflect/Pluralize.md new file mode 100644 index 000000000..c25f89617 --- /dev/null +++ b/docs/content/en/functions/inflect/Pluralize.md @@ -0,0 +1,18 @@ +--- +title: inflect.Pluralize +description: Pluralizes the given word according to a set of common English pluralization rules. +categories: [] +keywords: [] +action: + aliases: [pluralize] + related: + - functions/inflect/Humanize + - functions/inflect/Singularize + returnType: string + signatures: [inflect.Pluralize INPUT] +aliases: [/functions/pluralize] +--- + +```go-html-template +{{ "cat" | pluralize }} → cats +``` diff --git a/docs/content/en/functions/inflect/Singularize.md b/docs/content/en/functions/inflect/Singularize.md new file mode 100644 index 000000000..29b543257 --- /dev/null +++ b/docs/content/en/functions/inflect/Singularize.md @@ -0,0 +1,20 @@ +--- +title: inflect.Singularize +description: Singularizes the given word according to a set of common English singularization rules. +categories: [] +keywords: [] +action: + aliases: [singularize] + related: + - functions/inflect/Humanize + - functions/inflect/Pluralize + returnType: string + signatures: [inflect.Singularize INPUT] +aliases: [/functions/singularize] +--- + +```go-html-template +{{ "cats" | singularize }} → cat +``` + +See also the `.Data.Singular` [taxonomy variable](/variables/taxonomy/) for singularizing taxonomy names. diff --git a/docs/content/en/functions/inflect/_index.md b/docs/content/en/functions/inflect/_index.md new file mode 100644 index 000000000..601b409e6 --- /dev/null +++ b/docs/content/en/functions/inflect/_index.md @@ -0,0 +1,12 @@ +--- +title: Inflect functions +linkTitle: inflect +description: Template functions to inflect English nouns. +categories: [] +keywords: [] +menu: + docs: + parent: functions +--- + +These functions provide word inflection features such as singularization and pluralization of English nouns. diff --git a/docs/content/en/functions/js/Build.md b/docs/content/en/functions/js/Build.md new file mode 100644 index 000000000..835785486 --- /dev/null +++ b/docs/content/en/functions/js/Build.md @@ -0,0 +1,184 @@ +--- +title: js.Build +description: Bundles, transpiles, tree shakes, and minifies JavaScript resources. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/resources/Babel + - functions/resources/Fingerprint + - functions/resources/Minify + returnType: resource.Resource + signatures: ['js.Build [OPTIONS] RESOURCE'] +toc: true +--- + +The `js.Build` function uses the [evanw/esbuild] package to: + +- Bundle +- Transpile (TypeScript and JSX) +- Tree shake +- Minify +- Create source maps + +[evanw/esbuild]: https://github.com/evanw/esbuild + +```go-html-template +{{ with resources.Get "js/main.js" }} + {{ if hugo.IsDevelopment }} + {{ with . | js.Build }} + <script src="{{ .RelPermalink }}"></script> + {{ end }} + {{ else }} + {{ $opts := dict "minify" true }} + {{ with . | js.Build $opts | fingerprint }} + <script src="{{ .RelPermalink }}" integrity="{{ .Data.Integrity }}" crossorigin="anonymous"></script> + {{ end }} + {{ end }} +{{ end }} +``` + +## Options + +targetPath +: (`string`) If not set, the source path will be used as the base target path. +Note that the target path's extension may change if the target MIME type is different, e.g. when the source is TypeScript. + +params +: (`map` or `slice`) Params that can be imported as JSON in your JS files, e.g. + +```go-html-template +{{ $js := resources.Get "js/main.js" | js.Build (dict "params" (dict "api" "https://example.org/api")) }} +``` +And then in your JS file: + +```js +import * as params from '@params'; +``` + +Note that this is meant for small data sets, e.g. configuration settings. For larger data, please put/mount the files into `/assets` and import them directly. + +minify +: (`bool`)Let `js.Build` handle the minification. + +inject +: (`slice`) This option allows you to automatically replace a global variable with an import from another file. The path names must be relative to `assets`. See https://esbuild.github.io/api/#inject + +shims +: (`map`) This option allows swapping out a component with another. A common use case is to load dependencies like React from a CDN (with _shims_) when in production, but running with the full bundled `node_modules` dependency during development: + +```go-html-template +{{ $shims := dict "react" "js/shims/react.js" "react-dom" "js/shims/react-dom.js" }} +{{ $js = $js | js.Build dict "shims" $shims }} +``` + +The _shim_ files may look like these: + +```js +// js/shims/react.js +module.exports = window.React; +``` + +```js +// js/shims/react-dom.js +module.exports = window.ReactDOM; +``` + +With the above, these imports should work in both scenarios: + +```js +import * as React from 'react' +import * as ReactDOM from 'react-dom'; +``` + +target +: (`string`) The language target. One of: `es5`, `es2015`, `es2016`, `es2017`, `es2018`, `es2019`, `es2020` or `esnext`. Default is `esnext`. + +externals +: (`slice`) External dependencies. Use this to trim dependencies you know will never be executed. See https://esbuild.github.io/api/#external + +defines +: (`map`) Allow to define a set of string replacement to be performed when building. Should be a map where each key is to be replaced by its value. + +```go-html-template +{{ $defines := dict "process.env.NODE_ENV" `"development"` }} +``` + +format +: (`string`) The output format. One of: `iife`, `cjs`, `esm`. Default is `iife`, a self-executing function, suitable for inclusion as a `<script>` tag. + +sourceMap +: (`string`) Whether to generate `inline` or `external` source maps from esbuild. External source maps will be written to the target with the output file name + ".map". Input source maps can be read from js.Build and node modules and combined into the output source maps. By default, source maps are not created. + +### Import JS code from /assets + +`js.Build` has full support for the virtual union file system in [Hugo Modules](/hugo-modules/). You can see some simple examples in this [test project](https://github.com/gohugoio/hugoTestProjectJSModImports), but in short this means that you can do this: + +```js +import { hello } from 'my/module'; +``` + +And it will resolve to the top-most `index.{js,ts,tsx,jsx}` inside `assets/my/module` in the layered file system. + +```js +import { hello3 } from 'my/module/hello3'; +``` + +Will resolve to `hello3.{js,ts,tsx,jsx}` inside `assets/my/module`. + +Any imports starting with `.` is resolved relative to the current file: + +```js +import { hello4 } from './lib'; +``` + +For other files (e.g. `JSON`, `CSS`) you need to use the relative path including any extension, e.g: + +```js +import * as data from 'my/module/data.json'; +``` + +Any imports in a file outside `/assets` or that does not resolve to a component inside `/assets` will be resolved by [ESBuild](https://esbuild.github.io/) with the **project directory** as the resolve directory (used as the starting point when looking for `node_modules` etc.). Also see [hugo mod npm pack](/commands/hugo_mod_npm_pack/). If you have any imported npm dependencies in your project, you need to make sure to run `npm install` before you run `hugo`. + +Also note the new `params` option that can be passed from template to your JS files, e.g.: + +```go-html-template +{{ $js := resources.Get "js/main.js" | js.Build (dict "params" (dict "api" "https://example.org/api")) }} +``` +And then in your JS file: + +```js +import * as params from '@params'; +``` + +Hugo will, by default, generate a `assets/jsconfig.json` file that maps the imports. This is useful for navigation/intellisense help inside code editors, but if you don't need/want it, you can [turn it off](/getting-started/configuration/#configure-build). + +## Node.js dependencies + +Use the `js.Build` function to include Node.js dependencies. + +Any imports in a file outside `/assets` or that does not resolve to a component inside `/assets` will be resolved by [esbuild](https://esbuild.github.io/) with the **project directory** as the resolve directory (used as the starting point when looking for `node_modules` etc.). Also see [hugo mod npm pack](/commands/hugo_mod_npm_pack/). If you have any imported npm dependencies in your project, you need to make sure to run `npm install` before you run `hugo`. + +The start directory for resolving npm packages (aka. packages that live inside a `node_modules` folder) is always the main project folder. + +{{% note %}} +If you're developing a theme/component that is supposed to be imported and depends on dependencies inside `package.json`, we recommend reading about [hugo mod npm pack](/commands/hugo_mod_npm_pack/), a tool to consolidate all the npm dependencies in a project. +{{% /note %}} + +## Examples + +```go-html-template +{{ $built := resources.Get "js/index.js" | js.Build "main.js" }} +``` + +Or with options: + +```go-html-template +{{ $externals := slice "react" "react-dom" }} +{{ $defines := dict "process.env.NODE_ENV" `"development"` }} + +{{ $opts := dict "targetPath" "main.js" "externals" $externals "defines" $defines }} +{{ $built := resources.Get "scripts/main.js" | js.Build $opts }} +<script src="{{ $built.RelPermalink }}" defer></script> +``` diff --git a/docs/content/en/functions/js/_index.md b/docs/content/en/functions/js/_index.md new file mode 100644 index 000000000..3356e7c7b --- /dev/null +++ b/docs/content/en/functions/js/_index.md @@ -0,0 +1,12 @@ +--- +title: JavaScript functions +linkTitle: js +description: Template functions to work with JavaScript and TypeScript files. +categories: [] +keywords: [] +menu: + docs: + parent: functions +--- + +Use these functions to work with JavaScript and TypeScript files. diff --git a/docs/content/en/functions/lang/FormatAccounting.md b/docs/content/en/functions/lang/FormatAccounting.md new file mode 100644 index 000000000..70365c216 --- /dev/null +++ b/docs/content/en/functions/lang/FormatAccounting.md @@ -0,0 +1,21 @@ +--- +title: lang.FormatAccounting +description: Returns a currency representation of a number for the given currency and precision for the current language and region in accounting notation. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/lang/FormatCurrency + - functions/lang/FormatNumber + - functions/lang/FormatNumberCustom + - functions/lang/FormatPercent + returnType: string + signatures: [lang.FormatAccounting PRECISION CURRENCY NUMBER] +--- + +```go-html-template +{{ 512.5032 | lang.FormatAccounting 2 "NOK" }} → NOK512.50 +``` + +{{% include "functions/_common/locales.md" %}} diff --git a/docs/content/en/functions/lang/FormatCurrency.md b/docs/content/en/functions/lang/FormatCurrency.md new file mode 100644 index 000000000..bd83c2ec5 --- /dev/null +++ b/docs/content/en/functions/lang/FormatCurrency.md @@ -0,0 +1,21 @@ +--- +title: lang.FormatCurrency +description: Returns a currency representation of a number for the given currency and precision for the current language and region. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/lang/FormatAccounting + - functions/lang/FormatNumber + - functions/lang/FormatNumberCustom + - functions/lang/FormatPercent + returnType: string + signatures: [lang.FormatCurrency PRECISION CURRENCY NUMBER] +--- + +```go-html-template +{{ 512.5032 | lang.FormatCurrency 2 "USD" }} → $512.50 +``` + +{{% include "functions/_common/locales.md" %}} diff --git a/docs/content/en/functions/lang/FormatNumber.md b/docs/content/en/functions/lang/FormatNumber.md new file mode 100644 index 000000000..597df742a --- /dev/null +++ b/docs/content/en/functions/lang/FormatNumber.md @@ -0,0 +1,21 @@ +--- +title: lang.FormatNumber +description: Returns a numeric representation of a number with the given precision for the current language and region. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/lang/FormatAccounting + - functions/lang/FormatCurrency + - functions/lang/FormatNumberCustom + - functions/lang/FormatPercent + returnType: string + signatures: [lang.FormatNumber PRECISION NUMBER] +--- + +```go-html-template +{{ 512.5032 | lang.FormatNumber 2 }} → 512.50 +``` + +{{% include "functions/_common/locales.md" %}} diff --git a/docs/content/en/functions/lang/FormatNumberCustom.md b/docs/content/en/functions/lang/FormatNumberCustom.md new file mode 100644 index 000000000..0b72f4983 --- /dev/null +++ b/docs/content/en/functions/lang/FormatNumberCustom.md @@ -0,0 +1,34 @@ +--- +title: lang.FormatNumberCustom +description: Returns a numeric representation of a number with the given precision using negative, decimal, and grouping options. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/lang/FormatAccounting + - functions/lang/FormatCurrency + - functions/lang/FormatNumber + - functions/lang/FormatPercent + returnType: string + signatures: ['lang.FormatNumberCustom PRECISION NUMBER [OPTIONS...]'] +aliases: ['/functions/numfmt/'] +--- + +This function formats a number with the given precision. The first options parameter is a space-delimited string of characters to represent negativity, the decimal point, and grouping. The default value is `- . ,`. The second options parameter defines an alternate delimiting character. + +Note that numbers are rounded up at 5 or greater. So, with precision set to 0, 1.5 becomes 2, and 1.4 becomes 1. + +For a simpler function that adapts to the current language, see [`lang.FormatNumber`]. + +```go-html-template +{{ lang.FormatNumberCustom 2 12345.6789 }} → 12,345.68 +{{ lang.FormatNumberCustom 2 12345.6789 "- , ." }} → 12.345,68 +{{ lang.FormatNumberCustom 6 -12345.6789 "- ." }} → -12345.678900 +{{ lang.FormatNumberCustom 0 -12345.6789 "- . ," }} → -12,346 +{{ lang.FormatNumberCustom 0 -12345.6789 "-|.| " "|" }} → -12 346 +``` + +{{% include "functions/_common/locales.md" %}} + +[`lang.FormatNumber`]: /functions/lang/formatnumber diff --git a/docs/content/en/functions/lang/FormatPercent.md b/docs/content/en/functions/lang/FormatPercent.md new file mode 100644 index 000000000..529ada67b --- /dev/null +++ b/docs/content/en/functions/lang/FormatPercent.md @@ -0,0 +1,21 @@ +--- +title: lang.FormatPercent +description: Returns a percentage representation of a number with the given precision for the current language and region. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/lang/FormatAccounting + - functions/lang/FormatCurrency + - functions/lang/FormatNumber + - functions/lang/FormatNumberCustom + returnType: string + signatures: [lang.FormatPercent PRECISION NUMBER] +--- + +```go-html-template +{{ 512.5032 | lang.FormatPercent 2 }} → 512.50% +``` + +{{% include "functions/_common/locales.md" %}} diff --git a/docs/content/en/functions/lang/Merge.md b/docs/content/en/functions/lang/Merge.md new file mode 100644 index 000000000..75f5cdf01 --- /dev/null +++ b/docs/content/en/functions/lang/Merge.md @@ -0,0 +1,29 @@ +--- +title: lang.Merge +description: Merge missing translations from other languages. +categories: [] +keywords: [] +action: + aliases: [] + related: [] + returnType: any + signatures: [lang.Merge FROM TO] +aliases: [/functions/lang.merge] +--- + +As an example: + +```sh +{{ $pages := .Site.RegularPages | lang.Merge $frSite.RegularPages | lang.Merge $enSite.RegularPages }} +``` + +Will "fill in the gaps" in the current site with, from left to right, content from the French site, and lastly the English. + +A more practical example is to fill in the missing translations from the other languages: + +```sh +{{ $pages := .Site.RegularPages }} +{{ range .Site.Home.Translations }} +{{ $pages = $pages | lang.Merge .Site.RegularPages }} +{{ end }} + ``` diff --git a/docs/content/en/functions/lang/Translate.md b/docs/content/en/functions/lang/Translate.md new file mode 100644 index 000000000..3366d7751 --- /dev/null +++ b/docs/content/en/functions/lang/Translate.md @@ -0,0 +1,135 @@ +--- +title: lang.Translate +description: Translates a string using the translation tables in the i18n directory. +categories: [] +keywords: [] +action: + aliases: [T, i18n] + related: [] + returnType: string + signatures: ['lang.Translate KEY [CONTEXT]'] +aliases: [/functions/i18n] +--- + +The `lang.Translate` function returns the value associated with given key as defined in the translation table for the current language. + +If the key is not found in the translation table for the current language, the `lang.Translate` function falls back to the translation table for the [`defaultContentLanguage`]. + +If the key is not found in the translation table for the `defaultContentLanguage`, the `lang.Translate` function returns an empty string. + +[`defaultContentLanguage`]: /getting-started/configuration/#defaultcontentlanguage + +{{% note %}} +To list missing and fallback translations, use the `--printI18nWarnings` flag when building your site. + +To render placeholders for missing and fallback translations, set +[`enableMissingTranslationPlaceholders`] to `true` in your site configuration. + +[`enableMissingTranslationPlaceholders`]: /getting-started/configuration/#enablemissingtranslationplaceholders +{{% /note %}} + +Let's say your multilingual site supports two languages, English and Polish. Create a translation table for each language in the `i18n` directory. + +```text +i18n/ +├── en.toml +└── pl.toml +``` + +The translation tables can contain both: + +- Simple translations +- Translations with pluralization + +The Unicode [CLDR Plural Rules chart] describes the pluralization categories for each language. + +[CLDR Plural Rules chart]: https://www.unicode.org/cldr/charts/43/supplemental/language_plural_rules.html + +The English translation table: + +{{< code-toggle file=i18n/en >}} +privacy = 'privacy' +security = 'security' + +[day] +one = 'day' +other = 'days' + +[day_with_count] +one = '{{ . }} day' +other = '{{ . }} days' +{{< /code-toggle >}} + +The Polish translation table: + +{{< code-toggle file=i18n/pl >}} +privacy = 'prywatność' +security = 'bezpieczeństwo' + +[day] +one = 'miesiąc' +few = 'miesiące' +many = 'miesięcy' +other = 'miesiąca' + +[day_with_count] +one = '{{ . }} miesiąc' +few = '{{ . }} miesiące' +many = '{{ . }} miesięcy' +other = '{{ . }} miesiąca' +{{< /code-toggle >}} + +{{% note %}} +The examples below use the `T` alias for brevity. +{{% /note %}} + +When viewing the English language site: + +```go-html-template +{{ T "privacy" }} → privacy +{{ T "security" }} → security + +{{ T "day" 0 }} → days +{{ T "day" 1 }} → day +{{ T "day" 2 }} → days +{{ T "day" 5 }} → days + +{{ T "day_with_count" 0 }} → 0 days +{{ T "day_with_count" 1 }} → 1 day +{{ T "day_with_count" 2 }} → 2 days +{{ T "day_with_count" 5 }} → 5 days +```` + +When viewing the Polish language site: + +```go-html-template +{{ T "privacy" }} → prywatność +{{ T "security" }} → bezpieczeństwo + +{{ T "day" 0 }} → miesięcy +{{ T "day" 1 }} → miesiąc +{{ T "day" 2 }} → miesiące +{{ T "day" 5 }} → miesięcy + +{{ T "day_with_count" 0 }} → 0 miesięcy +{{ T "day_with_count" 1 }} → 1 miesiąc +{{ T "day_with_count" 2 }} → 2 miesiące +{{ T "day_with_count" 5 }} → 5 miesięcy +``` + +In the pluralization examples above, we passed an integer in context (the second argument). You can also pass a map in context, providing a `count` key to control pluralization. + +Translation table: + +{{< code-toggle file=i18n/en >}} +[age] +one = '{{ .name }} is {{ .count }} year old.' +other = '{{ .name }} is {{ .count }} years old.' +{{< /code-toggle >}} + +Template code: + +```go-html-template +{{ T "age" (dict "name" "Will" "count" 1) }} → Will is 1 year old. +{{ T "age" (dict "name" "John" "count" 3) }} → John is 3 years old. +``` diff --git a/docs/content/en/functions/lang/_index.md b/docs/content/en/functions/lang/_index.md new file mode 100644 index 000000000..934d97bff --- /dev/null +++ b/docs/content/en/functions/lang/_index.md @@ -0,0 +1,12 @@ +--- +title: Lang functions +linkTitle: lang +description: Template functions to adapt your site to meet language and regional requirements. +categories: [] +keywords: [] +menu: + docs: + parent: functions +--- + +Use these functions to adapt your site to meet language and regional requirements. diff --git a/docs/content/en/functions/math/Abs.md b/docs/content/en/functions/math/Abs.md new file mode 100644 index 000000000..682b8426f --- /dev/null +++ b/docs/content/en/functions/math/Abs.md @@ -0,0 +1,17 @@ +--- +title: math.Abs +description: Returns the absolute value of the given number. +categories: [] +keywords: [] +action: + aliases: [] + related: [] + returnType: float64 + signatures: [math.Abs VALUE] +--- + +{{< new-in 0.112.0 >}} + +```go-html-template +{{ math.Abs -2.1 }} → 2.1 +``` diff --git a/docs/content/en/functions/math/Add.md b/docs/content/en/functions/math/Add.md new file mode 100644 index 000000000..afa8d48aa --- /dev/null +++ b/docs/content/en/functions/math/Add.md @@ -0,0 +1,24 @@ +--- +title: math.Add +description: Adds two or more numbers. +categories: [] +keywords: [] +action: + aliases: [add] + related: + - functions/math/Div + - functions/math/Mul + - functions/math/Product + - functions/math/Sub + - functions/math/Sum + returnType: any + signatures: [math.Add VALUE VALUE...] +--- + +If one of the numbers is a [`float`], the result is a `float`. + +```go-html-template +{{ add 12 3 2 }} → 17 +``` + +[`float`]: /getting-started/glossary/#float diff --git a/docs/content/en/functions/math/Ceil.md b/docs/content/en/functions/math/Ceil.md new file mode 100644 index 000000000..9f74991c3 --- /dev/null +++ b/docs/content/en/functions/math/Ceil.md @@ -0,0 +1,17 @@ +--- +title: math.Ceil +description: Returns the least integer value greater than or equal to the given number. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/math/Floor + - functions/math/Round + returnType: float64 + signatures: [math.Ceil VALUE] +--- + +```go-html-template +{{ math.Ceil 2.1 }} → 3 +``` diff --git a/docs/content/en/functions/math/Counter.md b/docs/content/en/functions/math/Counter.md new file mode 100644 index 000000000..7f53bdd0c --- /dev/null +++ b/docs/content/en/functions/math/Counter.md @@ -0,0 +1,35 @@ +--- +title: math.Counter +description: Increments and returns a global counter. +categories: [] +keywords: [] +action: + aliases: [] + related: [] + returnType: uint64 + signatures: [math.Counter] +--- + +The counter is global for both monolingual and multilingual sites, and its initial value for each build is 1. + +```go-html-template +{{ warnf "single.html called %d times" math.Counter }} +``` + +```sh +WARN single.html called 1 times +WARN single.html called 2 times +WARN single.html called 3 times +``` + +Use this function to: + +- Create unique warnings as shown above; the [`warnf`] function suppresses duplicate messages +- Create unique target paths for the `resources.FromString` function where the target path is also the cache key + +[`warnf`]: /functions/fmt/warnf +[`resources.FromString`]: /functions/resources/fromstring + +{{% note %}} +Due to concurrency, the value returned in a given template for a given page will vary from one build to the next. You cannot use this function to assign a static id to each page. +{{% /note %}} diff --git a/docs/content/en/functions/math/Div.md b/docs/content/en/functions/math/Div.md new file mode 100644 index 000000000..530474a78 --- /dev/null +++ b/docs/content/en/functions/math/Div.md @@ -0,0 +1,24 @@ +--- +title: math.Div +description: Divides the first number by one or more numbers. +categories: [] +keywords: [] +action: + aliases: [div] + related: + - functions/math/Add + - functions/math/Mul + - functions/math/Product + - functions/math/Sub + - functions/math/Sum + returnType: any + signatures: [math.Div VALUE VALUE...] +--- + +If one of the numbers is a [`float`], the result is a `float`. + +```go-html-template +{{ div 12 3 2 }} → 2 +``` + +[`float`]: /getting-started/glossary/#float diff --git a/docs/content/en/functions/math/Floor.md b/docs/content/en/functions/math/Floor.md new file mode 100644 index 000000000..10ad758b6 --- /dev/null +++ b/docs/content/en/functions/math/Floor.md @@ -0,0 +1,17 @@ +--- +title: math.Floor +description: Returns the greatest integer value less than or equal to the given number. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/math/Ceil + - functions/math/Round + returnType: float64 + signatures: [math.Floor VALUE] +--- + +```go-html-template +{{ math.Floor 1.9 }} → 1 +``` diff --git a/docs/content/en/functions/math/Log.md b/docs/content/en/functions/math/Log.md new file mode 100644 index 000000000..84edcb288 --- /dev/null +++ b/docs/content/en/functions/math/Log.md @@ -0,0 +1,15 @@ +--- +title: math.Log +description: Returns the natural logarithm of the given number. +categories: [] +keywords: [] +action: + aliases: [] + related: [] + returnType: float64 + signatures: [math.Log VALUE] +--- + +```go-html-template +{{ math.Log 42 }} → 3.737 +``` diff --git a/docs/content/en/functions/math/Max.md b/docs/content/en/functions/math/Max.md new file mode 100644 index 000000000..9beff5630 --- /dev/null +++ b/docs/content/en/functions/math/Max.md @@ -0,0 +1,16 @@ +--- +title: math.Max +description: Returns the greater of all numbers. Accepts scalars, slices, or both. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/math/Min + returnType: float64 + signatures: [math.Max VALUE...] +--- + +```go-html-template +{{ math.Max 1 (slice 2 3) 4 }} → 4 +``` diff --git a/docs/content/en/functions/math/Min.md b/docs/content/en/functions/math/Min.md new file mode 100644 index 000000000..79e464c74 --- /dev/null +++ b/docs/content/en/functions/math/Min.md @@ -0,0 +1,16 @@ +--- +title: math.Min +description: Returns the smaller of all numbers. Accepts scalars, slices, or both. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/math/Max + returnType: float64 + signatures: [math.Min VALUE...] +--- + +```go-html-template +{{ math.Min 1 (slice 2 3) 4 }} → 1 +``` diff --git a/docs/content/en/functions/math/Mod.md b/docs/content/en/functions/math/Mod.md new file mode 100644 index 000000000..d312730c5 --- /dev/null +++ b/docs/content/en/functions/math/Mod.md @@ -0,0 +1,16 @@ +--- +title: math.Mod +description: Returns the modulus of two integers. +categories: [] +keywords: [] +action: + aliases: [mod] + related: + - functions/math/ModBool + returnType: int64 + signatures: [math.Mod VALUE1 VALUE2] +--- + +```go-html-template +{{ mod 15 3 }} → 0 +``` diff --git a/docs/content/en/functions/math/ModBool.md b/docs/content/en/functions/math/ModBool.md new file mode 100644 index 000000000..d915ff614 --- /dev/null +++ b/docs/content/en/functions/math/ModBool.md @@ -0,0 +1,16 @@ +--- +title: math.ModBool +description: Reports whether the modulus of two integers equals 0. +categories: [] +keywords: [] +action: + aliases: [modBool] + related: + - functions/math/Mod + returnType: bool + signatures: [math.ModBool VALUE1 VALUE2] +--- + +```go-html-template +{{ modBool 15 3 }} → true +``` diff --git a/docs/content/en/functions/math/Mul.md b/docs/content/en/functions/math/Mul.md new file mode 100644 index 000000000..6824599e3 --- /dev/null +++ b/docs/content/en/functions/math/Mul.md @@ -0,0 +1,24 @@ +--- +title: math.Mul +description: Multiplies two or more numbers. +categories: [] +keywords: [] +action: + aliases: [mul] + related: + - functions/math/Add + - functions/math/Div + - functions/math/Product + - functions/math/Sub + - functions/math/Sum + returnType: any + signatures: [math.Mul VALUE VALUE...] +--- + +If one of the numbers is a [`float`], the result is a `float`. + +```go-html-template +{{ mul 12 3 2 }} → 72 +``` + +[`float`]: /getting-started/glossary/#float diff --git a/docs/content/en/functions/math/Pow.md b/docs/content/en/functions/math/Pow.md new file mode 100644 index 000000000..5a1482d73 --- /dev/null +++ b/docs/content/en/functions/math/Pow.md @@ -0,0 +1,16 @@ +--- +title: math.Pow +description: Returns the first number raised to the power of the second number. +categories: [] +keywords: [] +action: + aliases: [pow] + related: + - functions/math/Sqrt + returnType: float64 + signatures: [math.Pow VALUE1 VALUE2] +--- + +```go-html-template +{{ math.Pow 2 3 }} → 8 +``` diff --git a/docs/content/en/functions/math/Product.md b/docs/content/en/functions/math/Product.md new file mode 100644 index 000000000..d94df4f1b --- /dev/null +++ b/docs/content/en/functions/math/Product.md @@ -0,0 +1,22 @@ +--- +title: math.Product +description: Returns the product of all numbers. Accepts scalars, slices, or both. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/math/Add + - functions/math/Div + - functions/math/Mul + - functions/math/Sub + - functions/math/Sum + returnType: float64 + signatures: [math.Product VALUE...] +--- + +{{< new-in 0.114.0 >}} + +```go-html-template +{{ math.Product 1 (slice 2 3) 4 }} → 24 +``` diff --git a/docs/content/en/functions/math/Rand.md b/docs/content/en/functions/math/Rand.md new file mode 100644 index 000000000..4f71cfcdf --- /dev/null +++ b/docs/content/en/functions/math/Rand.md @@ -0,0 +1,46 @@ +--- +title: math.Rand +description: Returns a pseudo-random number in the half-open interval [0.0, 1.0). +categories: [] +keywords: [] +action: + aliases: [] + related: [] + returnType: float64 + signatures: [math.Rand] +--- + +{{< new-in 0.121.2 >}} + +The `math.Rand` function returns a pseudo-random number in the [half-open interval] [0.0, 1.0). + +```go-html-template +{{ math.Rand }} → 0.6312770459590062 +``` + +To generate a random integer in the [closed interval] [0, 5]: + +```go-html-template +{{ math.Rand | mul 6 | math.Floor }} +``` + +To generate a random integer in the closed interval [1, 6]: + +```go-html-template +{{ math.Rand | mul 6 | math.Ceil }} +``` + +To generate a random float, with one digit after the decimal point, in the closed interval [0, 4.9]: + +```go-html-template +{{ div (math.Rand | mul 50 | math.Floor) 10 }} +``` + +To generate a random float, with one digit after the decimal point, in the closed interval [0.1, 5.0]: + +```go-html-template +{{ div (math.Rand | mul 50 | math.Ceil) 10 }} +``` + +[closed interval]: /getting-started/glossary/#interval +[half-open interval]: /getting-started/glossary/#interval diff --git a/docs/content/en/functions/math/Round.md b/docs/content/en/functions/math/Round.md new file mode 100644 index 000000000..e0678eb78 --- /dev/null +++ b/docs/content/en/functions/math/Round.md @@ -0,0 +1,17 @@ +--- +title: math.Round +description: Returns the nearest integer, rounding half away from zero. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/math/Ceil + - functions/math/Floor + returnType: float64 + signatures: [math.Round VALUE] +--- + +```go-html-template +{{ math.Round 1.5 }} → 2 +``` diff --git a/docs/content/en/functions/math/Sqrt.md b/docs/content/en/functions/math/Sqrt.md new file mode 100644 index 000000000..436cb31c3 --- /dev/null +++ b/docs/content/en/functions/math/Sqrt.md @@ -0,0 +1,16 @@ +--- +title: math.Sqrt +description: Returns the square root of the given number. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/math/Pow + returnType: float64 + signatures: [math.Sqrt VALUE] +--- + +```go-html-template +{{ math.Sqrt 81 }} → 9 +``` diff --git a/docs/content/en/functions/math/Sub.md b/docs/content/en/functions/math/Sub.md new file mode 100644 index 000000000..a89d0e69d --- /dev/null +++ b/docs/content/en/functions/math/Sub.md @@ -0,0 +1,24 @@ +--- +title: math.Sub +description: Subtracts one or more numbers from the first number. +categories: [] +keywords: [] +action: + aliases: [sub] + related: + - functions/math/Add + - functions/math/Div + - functions/math/Mul + - functions/math/Product + - functions/math/Sum + returnType: any + signatures: [math.Sub VALUE VALUE...] +--- + +If one of the numbers is a [`float`], the result is a `float`. + +```go-html-template +{{ sub 12 3 2 }} → 7 +``` + +[`float`]: /getting-started/glossary/#float diff --git a/docs/content/en/functions/math/Sum.md b/docs/content/en/functions/math/Sum.md new file mode 100644 index 000000000..eba03f72d --- /dev/null +++ b/docs/content/en/functions/math/Sum.md @@ -0,0 +1,21 @@ +--- +title: math.Sum +description: Returns the sum of all numbers. Accepts scalars, slices, or both. +categories: [] +action: + aliases: [] + related: + - functions/math/Add + - functions/math/Div + - functions/math/Mul + - functions/math/Product + - functions/math/Sub + returnType: float64 + signatures: [math.Sum VALUE...] +--- + +{{< new-in 0.114.0 >}} + +```go-html-template +{{ math.Sum 1 (slice 2 3) 4 }} → 10 +``` diff --git a/docs/content/en/functions/math/_index.md b/docs/content/en/functions/math/_index.md new file mode 100644 index 000000000..76713bc99 --- /dev/null +++ b/docs/content/en/functions/math/_index.md @@ -0,0 +1,11 @@ +--- +title: Math functions +linkTitle: math +description: Template functions to perform mathematical operations. +categories: [] +menu: + docs: + parent: functions +--- + +Use these functions to perform mathematical operations. diff --git a/docs/content/en/functions/openapi3/Unmarshal.md b/docs/content/en/functions/openapi3/Unmarshal.md new file mode 100644 index 000000000..433337aef --- /dev/null +++ b/docs/content/en/functions/openapi3/Unmarshal.md @@ -0,0 +1,76 @@ +--- +title: openapi3.Unmarshal +description: Unmarshals the given resource into an OpenAPI 3 document. +categories: [] +keywords: [] +action: + aliases: [] + related: [] + returnType: openapi3.OpenAPIDocument + signatures: ['openapi3.Unmarshal RESOURCE'] +--- + +Use the `openapi3.Unmarshal` function with [global], [page], or [remote] resources. + +[global]: /getting-started/glossary/#global-resource +[page]: /getting-started/glossary/#page-resource +[remote]: /getting-started/glossary/#remote-resource +[OpenAPI]: https://www.openapis.org/ + +For example, to work with a remote [OpenAPI] definition: + +```go-html-template +{{ $url := "https://raw.githubusercontent.com/OAI/OpenAPI-Specification/main/examples/v3.0/petstore.json" }} +{{ $api := "" }} +{{ with resources.GetRemote $url }} + {{ with .Err }} + {{ errorf "%s" . }} + {{ else }} + {{ $api = . | openapi3.Unmarshal }} + {{ end }} +{{ else }} + {{ errorf "Unable to get remote resource %q" $url }} +{{ end }} +``` + +To inspect the data structure: + +```go-html-template +<pre>{{ debug.Dump $api }}</pre> +``` + +To list the GET and POST operations for each of the API paths: + +```go-html-template +{{ range $path, $details := $api.Paths }} + <p>{{ $path }}</p> + <dl> + {{ with $details.Get }} + <dt>GET</dt> + <dd>{{ .Summary }}</dd> + {{ end }} + {{ with $details.Post }} + <dt>POST</dt> + <dd>{{ .Summary }}</dd> + {{ end }} + </dl> +{{ end }} +``` + +Hugo renders this to: + + +```html +<p>/pets</p> +<dl> + <dt>GET</dt> + <dd>List all pets</dd> + <dt>POST</dt> + <dd>Create a pet</dd> +</dl> +<p>/pets/{petId}</p> +<dl> + <dt>GET</dt> + <dd>Info for a specific pet</dd> +</dl> +``` diff --git a/docs/content/en/functions/openapi3/_index.md b/docs/content/en/functions/openapi3/_index.md new file mode 100644 index 000000000..9b6aa9584 --- /dev/null +++ b/docs/content/en/functions/openapi3/_index.md @@ -0,0 +1,12 @@ +--- +title: OpenAPI functions +linkTitle: openapi3 +description: Template functions to work with OpenAPI 3 definitions. +categories: [] +keywords: [] +menu: + docs: + parent: functions +--- + +Use these functions to work with OpenAPI 3 definitions. diff --git a/docs/content/en/functions/os/FileExists.md b/docs/content/en/functions/os/FileExists.md new file mode 100644 index 000000000..b8104a066 --- /dev/null +++ b/docs/content/en/functions/os/FileExists.md @@ -0,0 +1,41 @@ +--- +title: os.FileExists +description: Reports whether the file or directory exists. +categories: [] +keywords: [] +action: + aliases: [fileExists] + related: + - functions/os/Getenv + - functions/os/ReadDir + - functions/os/ReadFile + - functions/os/Stat + returnType: bool + signatures: [os.FileExists PATH] +aliases: [/functions/fileexists] +--- + +The `os.FileExists` function attempts to resolve the path relative to the root of your project directory. If a matching file or directory is not found, it will attempt to resolve the path relative to the [`contentDir`](/getting-started/configuration#contentdir). A leading path separator (`/`) is optional. + +With this directory structure: + +```text +content/ +├── about.md +├── contact.md +└── news/ + ├── article-1.md + └── article-2.md +``` + +The function returns these values: + +```go-html-template +{{ fileExists "content" }} → true +{{ fileExists "content/news" }} → true +{{ fileExists "content/news/article-1" }} → false +{{ fileExists "content/news/article-1.md" }} → true +{{ fileExists "news" }} → true +{{ fileExists "news/article-1" }} → false +{{ fileExists "news/article-1.md" }} → true +``` diff --git a/docs/content/en/functions/os/Getenv.md b/docs/content/en/functions/os/Getenv.md new file mode 100644 index 000000000..084d498ce --- /dev/null +++ b/docs/content/en/functions/os/Getenv.md @@ -0,0 +1,61 @@ +--- +title: os.Getenv +description: Returns the value of an environment variable, or an empty string if the environment variable is not set. +categories: [] +keywords: [] +action: + aliases: [getenv] + related: + - functions/os/FileExists + - functions/os/ReadDir + - functions/os/ReadFile + - functions/os/Stat + returnType: string + signatures: [os.Getenv VARIABLE] +aliases: [/functions/getenv] +toc: true +--- + +## Security + +By default, when using the `os.Getenv` function Hugo allows access to: + +- The `CI` environment variable +- Any environment variable beginning with `HUGO_` + +To access other environment variables, adjust your site configuration. For example, to allow access to the `HOME` and `USER` environment variables: + +{{< code-toggle file=hugo >}} +[security.funcs] +getenv = ['^HUGO_', '^CI$', '^USER$', '^HOME$'] +{{< /code-toggle >}} + +Read more about Hugo's [security policy]. + +[security policy]: /about/security-model/#security-policy + +## Examples + +```go-html-template +{{ getenv "HOME" }} → /home/victor +{{ getenv "USER" }} → victor +``` + +You can pass values when building your site: + +```sh +MY_VAR1=foo MY_VAR2=bar hugo + +OR + +export MY_VAR1=foo +export MY_VAR2=bar +hugo +``` + +And then retrieve the values within a template: + +```go-html-template +{{ getenv "MY_VAR1" }} → foo +{{ getenv "MY_VAR2" }} → bar +``` diff --git a/docs/content/en/functions/os/ReadDir.md b/docs/content/en/functions/os/ReadDir.md new file mode 100644 index 000000000..63af850b7 --- /dev/null +++ b/docs/content/en/functions/os/ReadDir.md @@ -0,0 +1,51 @@ +--- +title: os.ReadDir +description: Returns an array of FileInfo structures sorted by file name, one element for each directory entry. +categories: [] +keywords: [] +action: + aliases: [readDir] + related: + - functions/os/FileExists + - functions/os/Getenv + - functions/os/ReadFile + - functions/os/Stat + returnType: os.FileInfo + signatures: [os.ReadDir PATH] +aliases: [/functions/readdir] +--- + +The `os.ReadDir` function resolves the path relative to the root of your project directory. A leading path separator (`/`) is optional. + +With this directory structure: + +```text +content/ +├── about.md +├── contact.md +└── news/ + ├── article-1.md + └── article-2.md +``` + +This template code: + +```go-html-template +{{ range readDir "content" }} + {{ .Name }} → {{ .IsDir }} +{{ end }} +``` + +Produces: + +```html +about.md → false +contact.md → false +news → true +``` + +Note that `os.ReadDir` is not recursive. + +Details of the `FileInfo` structure are available in the [Go documentation](https://pkg.go.dev/io/fs#FileInfo). + +For more information on using `readDir` and `readFile` in your templates, see [Local File Templates](/templates/files). diff --git a/docs/content/en/functions/os/ReadFile.md b/docs/content/en/functions/os/ReadFile.md new file mode 100644 index 000000000..654e300ac --- /dev/null +++ b/docs/content/en/functions/os/ReadFile.md @@ -0,0 +1,40 @@ +--- +title: os.ReadFile +description: Returns the contents of a file. +categories: [] +keywords: [] +action: + aliases: [readFile] + related: + - functions/os/FileExists + - functions/os/Getenv + - functions/os/ReadDir + - functions/os/Stat + returnType: string + signatures: [os.ReadFile PATH] +aliases: [/functions/readfile] +--- + +The `os.ReadFile` function attempts to resolve the path relative to the root of your project directory. If a matching file is not found, it will attempt to resolve the path relative to the [`contentDir`](/getting-started/configuration#contentdir). A leading path separator (`/`) is optional. + +With a file named README.md in the root of your project directory: + +```text +This is **bold** text. +``` + +This template code: + +```go-html-template +{{ readFile "README.md" }} +``` + +Produces: + +```html +This is **bold** text. +``` + +Note that `os.ReadFile` returns raw (uninterpreted) content. + +For more information on using `readDir` and `readFile` in your templates, see [Local File Templates](/templates/files). diff --git a/docs/content/en/functions/os/Stat.md b/docs/content/en/functions/os/Stat.md new file mode 100644 index 000000000..6b6f668de --- /dev/null +++ b/docs/content/en/functions/os/Stat.md @@ -0,0 +1,31 @@ +--- +title: os.Stat +description: Returns a FileInfo structure describing a file or directory. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/os/FileExists + - functions/os/Getenv + - functions/os/ReadDir + - functions/os/ReadFile + returnType: os.FileInfo + signatures: [os.Stat PATH] +aliases: [/functions/os.stat] +--- + +The `os.Stat` function attempts to resolve the path relative to the root of your project directory. If a matching file or directory is not found, it will attempt to resolve the path relative to the [`contentDir`](/getting-started/configuration#contentdir). A leading path separator (`/`) is optional. + +```go-html-template +{{ $f := os.Stat "README.md" }} +{{ $f.IsDir }} → false (bool) +{{ $f.ModTime }} → 2021-11-25 10:06:49.315429236 -0800 PST (time.Time) +{{ $f.Name }} → README.md (string) +{{ $f.Size }} → 241 (int64) + +{{ $d := os.Stat "content" }} +{{ $d.IsDir }} → true (bool) +``` + +Details of the `FileInfo` structure are available in the [Go documentation](https://pkg.go.dev/io/fs#FileInfo). diff --git a/docs/content/en/functions/os/_index.md b/docs/content/en/functions/os/_index.md new file mode 100644 index 000000000..c080d0092 --- /dev/null +++ b/docs/content/en/functions/os/_index.md @@ -0,0 +1,12 @@ +--- +title: OS functions +linkTitle: os +description: Template functions to interact with the operating system. +categories: [] +keywords: [] +menu: + docs: + parent: functions +--- + +Use these functions to interact with the operating system. diff --git a/docs/content/en/functions/partials/Include.md b/docs/content/en/functions/partials/Include.md new file mode 100644 index 000000000..e08b32fd1 --- /dev/null +++ b/docs/content/en/functions/partials/Include.md @@ -0,0 +1,85 @@ +--- +title: partials.Include +description: Executes the given partial template, optionally passing context. If the partial template contains a return statement, returns the given value, else returns the rendered output. +categories: [] +keywords: [] +action: + aliases: [partial] + related: + - functions/go-template/return + - functions/partials/IncludeCached + - functions/go-template/template + - methods/page/Render + returnType: any + signatures: ['partials.Include NAME [CONTEXT]'] +aliases: [/functions/partial] +--- + +Without a [`return`] statement, the `partial` function returns a string of type `template.HTML`. With a `return` statement, the `partial` function can return any data type. + +[`return`]: /functions/go-template/return + +In this example we have three partial templates: + +```text +layouts/ +└── partials/ + ├── average.html + ├── breadcrumbs.html + └── footer.html +``` + +The "average" partial returns the average of one or more numbers. We pass the numbers in context: + +```go-html-template +{{ $numbers := slice 1 6 7 42 }} +{{ $average := partial "average.html" $numbers }} +``` + +The "breadcrumbs" partial renders [breadcrumb navigation], and needs to receive the current page in context: + +```go-html-template +{{ partial "breadcrumbs.html" . }} +``` + +The "footer" partial renders the site footer. In this contrived example, the footer does not need access to the current page, so we can omit context: + +```go-html-template +{{ partial "breadcrumbs.html" }} +``` + +You can pass anything in context: a page, a page collection, a scalar value, a slice, or a map. For example: + +```go-html-template +{{ $student := dict + "name" "John Doe" + "major" "Finance" + "gpa" 4.0 +}} +{{ partial "render-student-info.html" $student }} +``` + +Then, within the partial template: + +```go-html-template +<p>{{ .name }} is majoring in {{ .major }}. Their grade point average is {{ .gpa }}.</p> +``` + +To return a value from a partial template, it must contain only one `return` statement, placed at the end of the template: + +```go-html-template +{{ $result := "" }} +{{ if math.ModBool . 2 }} + {{ $result = "even" }} +{{ else }} + {{ $result = "odd" }} +{{ end }} +{{ return $result }} +``` + +See [details][`return`]. + +[`return`]: /functions/go-template/return + +[breadcrumb navigation]: /content-management/sections/#ancestors-and-descendants +[details]: /functions/go-template/return diff --git a/docs/content/en/functions/partials/IncludeCached.md b/docs/content/en/functions/partials/IncludeCached.md new file mode 100644 index 000000000..66ef4a6ac --- /dev/null +++ b/docs/content/en/functions/partials/IncludeCached.md @@ -0,0 +1,65 @@ +--- +title: partials.IncludeCached +description: Executes the given template and caches the result, optionally passing context. If the partial template contains a return statement, returns the given value, else returns the rendered output. +categories: [] +keywords: [] +action: + aliases: [partialCached] + related: + - functions/go-template/return + - functions/partials/Include + - functions/go-template/template + - methods/page/Render + returnType: any + signatures: ['partials.IncludeCached LAYOUT CONTEXT [VARIANT...]'] +signatures: + - partials.IncludeCached NAME CONTEXT [VARIANT...] + - partialCached NAME CONTEXT [VARIANT...] +aliases: [/functions/partialcached] +--- + +Without a [`return`] statement, the `partialCached` function returns a string of type `template.HTML`. With a `return` statement, the `partialCached` function can return any data type. + +The `partialCached` function can offer significant performance gains for complex templates that don't need to be re-rendered on every invocation. + +{{% note %}} +Each Site (or language) has its own `partialCached` cache, so each site will execute a partial once. + +Hugo renders pages in parallel, and will render the partial more than once with concurrent calls to the `partialCached` function. After Hugo caches the rendered partial, new pages entering the build pipeline will use the cached result. +{{% /note %}} + +Here is the simplest usage: + +```go-html-template +{{ partialCached "footer.html" . }} +``` + +Pass additional arguments to `partialCached` to create variants of the cached partial. For example, if you have a complex partial that should be identical when rendered for pages within the same section, use a variant based on section so that the partial is only rendered once per section: + +{{< code file=partial-cached-example.html >}} +{{ partialCached "footer.html" . .Section }} +{{< /code >}} + +Pass additional arguments, of any data type, as needed to create unique variants: + +```go-html-template +{{ partialCached "footer.html" . .Params.country .Params.province }} +``` + +The variant arguments are not available to the underlying partial template; they are only used to create unique cache keys. + +To return a value from a partial template, it must contain only one `return` statement, placed at the end of the template: + +```go-html-template +{{ $result := "" }} +{{ if math.ModBool . 2 }} + {{ $result = "even" }} +{{ else }} + {{ $result = "odd" }} +{{ end }} +{{ return $result }} +``` + +See [details][`return`]. + +[`return`]: /functions/go-template/return diff --git a/docs/content/en/functions/partials/_index.md b/docs/content/en/functions/partials/_index.md new file mode 100644 index 000000000..0a7d4d6d0 --- /dev/null +++ b/docs/content/en/functions/partials/_index.md @@ -0,0 +1,12 @@ +--- +title: Partial functions +linkTitle: partials +description: Template functions to call partial templates. +categories: [] +keywords: [] +menu: + docs: + parent: functions +--- + +Use these functions to call partial templates. diff --git a/docs/content/en/functions/path/Base.md b/docs/content/en/functions/path/Base.md new file mode 100644 index 000000000..2071f8bea --- /dev/null +++ b/docs/content/en/functions/path/Base.md @@ -0,0 +1,26 @@ +--- +title: path.Base +description: Replaces path separators with slashes (`/`) and returns the last element of the given path. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/path/BaseName + - functions/path/Clean + - functions/path/Dir + - functions/path/Ext + - functions/path/Join + - functions/path/Split + returnType: string + signatures: [path.Base PATH] +aliases: [/functions/path.base] +--- + +```go-html-template +{{ path.Base "a/news.html" }} → news.html +{{ path.Base "news.html" }} → news.html +{{ path.Base "a/b/c" }} → c +{{ path.Base "/x/y/z/" }} → z +{{ path.Base "" }} → . +``` diff --git a/docs/content/en/functions/path/BaseName.md b/docs/content/en/functions/path/BaseName.md new file mode 100644 index 000000000..4c4340a09 --- /dev/null +++ b/docs/content/en/functions/path/BaseName.md @@ -0,0 +1,28 @@ +--- +title: path.BaseName +description: Replaces path separators with slashes (`/`) and returns the last element of the given path, removing the extension if present. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/path/Base + - functions/path/Clean + - functions/path/Dir + - functions/path/Ext + - functions/path/Join + - functions/path/Split + returnType: string + signatures: [path.BaseName PATH] +aliases: [/functions/path.basename] +--- + +{{< new-in 0.101.0 >}} + +```go-html-template +{{ path.BaseName "a/news.html" }} → news +{{ path.BaseName "news.html" }} → news +{{ path.BaseName "a/b/c" }} → c +{{ path.BaseName "/x/y/z/" }} → z +{{ path.BaseName "" }} → . +``` diff --git a/docs/content/en/functions/path/Clean.md b/docs/content/en/functions/path/Clean.md new file mode 100644 index 000000000..57a665c03 --- /dev/null +++ b/docs/content/en/functions/path/Clean.md @@ -0,0 +1,33 @@ +--- +title: path.Clean +description: Replaces path separators with slashes (`/`) and returns the shortest path name equivalent to the given path. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/path/Base + - functions/path/BaseName + - functions/path/Dir + - functions/path/Ext + - functions/path/Join + - functions/path/Split + returnType: string + signatures: [path.Clean PATH] +aliases: [/functions/path.clean] +--- + +See Go's [`path.Clean`] documentation for details. + +[`path.Clean`]: https://pkg.go.dev/path#Clean + +```go-html-template +{{ path.Clean "foo/bar" }} → foo/bar +{{ path.Clean "/foo/bar" }} → /foo/bar +{{ path.Clean "/foo/bar/" }} → /foo/bar +{{ path.Clean "/foo//bar/" }} → /foo/bar +{{ path.Clean "/foo/./bar/" }} → /foo/bar +{{ path.Clean "/foo/../bar/" }} → /bar +{{ path.Clean "/../foo/../bar/" }} → /bar +{{ path.Clean "" }} → . +``` diff --git a/docs/content/en/functions/path/Dir.md b/docs/content/en/functions/path/Dir.md new file mode 100644 index 000000000..6d5e5c975 --- /dev/null +++ b/docs/content/en/functions/path/Dir.md @@ -0,0 +1,27 @@ +--- +title: path.Dir +description: Replaces path separators with slashes (/) and returns all but the last element of the given path. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/path/Base + - functions/path/BaseName + - functions/path/Clean + - functions/path/Ext + - functions/path/Join + - functions/path/Split + returnType: string + signatures: [path.Dir PATH] +aliases: [/functions/path.dir] +--- + +```go-html-template +{{ path.Dir "a/news.html" }} → a +{{ path.Dir "news.html" }} → . +{{ path.Dir "a/b/c" }} → a/b +{{ path.Dir "/a/b/c" }} → /a/b +{{ path.Dir "/a/b/c/" }} → /a/b/c +{{ path.Dir "" }} → . +``` diff --git a/docs/content/en/functions/path/Ext.md b/docs/content/en/functions/path/Ext.md new file mode 100644 index 000000000..f3e47aecd --- /dev/null +++ b/docs/content/en/functions/path/Ext.md @@ -0,0 +1,24 @@ +--- +title: path.Ext +description: Replaces path separators with slashes (`/`) and returns the file name extension of the given path. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/path/Base + - functions/path/BaseName + - functions/path/Clean + - functions/path/Dir + - functions/path/Join + - functions/path/Split + returnType: string + signatures: [path.Ext PATH] +aliases: [/functions/path.ext] +--- + +The extension is the suffix beginning at the final dot in the final slash-separated element of path; it is empty if there is no dot. + +```go-html-template +{{ path.Ext "a/b/c/news.html" }} → .html +``` diff --git a/docs/content/en/functions/path/Join.md b/docs/content/en/functions/path/Join.md new file mode 100644 index 000000000..dc701b731 --- /dev/null +++ b/docs/content/en/functions/path/Join.md @@ -0,0 +1,36 @@ +--- +title: path.Join +description: Replaces path separators with slashes (`/`), joins the given path elements into a single path, and returns the shortest path name equivalent to the result. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/path/Base + - functions/path/BaseName + - functions/path/Clean + - functions/path/Dir + - functions/path/Ext + - functions/path/Split + - functions/urls/JoinPath + returnType: string + signatures: [path.Join ELEMENT...] +aliases: [/functions/path.join] +--- + +See Go's [`path.Join`] and [`path.Clean`] documentation for details. + +[`path.Clean`]: https://pkg.go.dev/path#Clean +[`path.Join`]: https://pkg.go.dev/path#Join + + +```go-html-template +{{ path.Join "partial" "news.html" }} → partial/news.html +{{ path.Join "partial/" "news.html" }} → partial/news.html +{{ path.Join "foo/bar" "baz" }} → foo/bar/baz +{{ path.Join "foo" "bar" "baz" }} → foo/bar/baz +{{ path.Join "foo" "" "baz" }} → foo/baz +{{ path.Join "foo" "." "baz" }} → foo/baz +{{ path.Join "foo" ".." "baz" }} → baz +{{ path.Join "/.." "foo" ".." "baz" }} → baz +``` diff --git a/docs/content/en/functions/path/Split.md b/docs/content/en/functions/path/Split.md new file mode 100644 index 000000000..329d73954 --- /dev/null +++ b/docs/content/en/functions/path/Split.md @@ -0,0 +1,34 @@ +--- +title: path.Split +description: Replaces path separators with slashes (`/`) and splits the resulting path immediately following the final slash, separating it into a directory and file name component. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/path/Base + - functions/path/BaseName + - functions/path/Clean + - functions/path/Dir + - functions/path/Ext + - functions/path/Join + returnType: paths.DirFile + signatures: [path.Split PATH] +aliases: [/functions/path.split] +--- + +If there is no slash in the given path, `path.Split` returns an empty directory, and file set to path. The returned values have the property that path = dir+file. + +```go-html-template +{{ $dirFile := path.Split "a/news.html" }} +{{ $dirFile.Dir }} → a/ +{{ $dirFile.File }} → news.html + +{{ $dirFile := path.Split "news.html" }} +{{ $dirFile.Dir }} → "" (empty string) +{{ $dirFile.File }} → news.html + +{{ $dirFile := path.Split "a/b/c" }} +{{ $dirFile.Dir }} → a/b/ +{{ $dirFile.File }} → c +``` diff --git a/docs/content/en/functions/path/_index.md b/docs/content/en/functions/path/_index.md new file mode 100644 index 000000000..2d7ce8e90 --- /dev/null +++ b/docs/content/en/functions/path/_index.md @@ -0,0 +1,12 @@ +--- +title: Path functions +linkTitle: path +description: Template functions to work with file paths. +categories: [] +keywords: [] +menu: + docs: + parent: functions +--- + +Use these functions to work with file paths. diff --git a/docs/content/en/functions/reflect/IsMap.md b/docs/content/en/functions/reflect/IsMap.md new file mode 100644 index 000000000..ada5a221d --- /dev/null +++ b/docs/content/en/functions/reflect/IsMap.md @@ -0,0 +1,18 @@ +--- +title: reflect.IsMap +description: Reports whether the given value is a map. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/reflect/IsSlice + returnType: bool + signatures: [reflect.IsMap INPUT] +aliases: [/functions/reflect.ismap] +--- + +```go-html-template +{{ reflect.IsMap (dict "key" "value") }} → true +{{ reflect.IsMap "yo" }} → false +``` diff --git a/docs/content/en/functions/reflect/IsSlice.md b/docs/content/en/functions/reflect/IsSlice.md new file mode 100644 index 000000000..cda24a5e1 --- /dev/null +++ b/docs/content/en/functions/reflect/IsSlice.md @@ -0,0 +1,18 @@ +--- +title: reflect.IsSlice +description: Reports whether the given value is a slice. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/reflect/IsMap + returnType: bool + signatures: [reflect.IsSlice INPUT] +aliases: [/functions/reflect.isslice] +--- + +```go-html-template +{{ reflect.IsSlice (slice 1 2 3) }} → true +{{ reflect.IsSlice "yo" }} → false +``` diff --git a/docs/content/en/functions/reflect/_index.md b/docs/content/en/functions/reflect/_index.md new file mode 100644 index 000000000..711908ee2 --- /dev/null +++ b/docs/content/en/functions/reflect/_index.md @@ -0,0 +1,12 @@ +--- +title: Reflect functions +linkTitle: reflect +description: Template functions to determine a value's data type. +categories: [] +keywords: [] +menu: + docs: + parent: functions +--- + +Use these functions to determine a value's data type. diff --git a/docs/content/en/functions/resources/Babel.md b/docs/content/en/functions/resources/Babel.md new file mode 100644 index 000000000..57ddb7d23 --- /dev/null +++ b/docs/content/en/functions/resources/Babel.md @@ -0,0 +1,88 @@ +--- +title: resources.Babel +description: Compiles the given JavaScript resource with Babel. +categories: [] +keywords: [] +action: + aliases: [babel] + related: + - functions/js/Build + - functions/resources/Fingerprint + - functions/resources/Minify + returnType: resource.Resource + signatures: ['resources.Babel [OPTIONS] RESOURCE'] +toc: true +--- + +```go-html-template +{{ with resources.Get "js/main.js" }} + {{ if hugo.IsDevelopment }} + {{ with . | babel }} + <script src="{{ .RelPermalink }}"></script> + {{ end }} + {{ else }} + {{ $opts := dict "minified" true }} + {{ with . | babel $opts | fingerprint }} + <script src="{{ .RelPermalink }}" integrity="{{ .Data.Integrity }}" crossorigin="anonymous"></script> + {{ end }} + {{ end }} +{{ end }} +``` + +## Setup + +Step 1 +: Install [Node.js](https://nodejs.org/en/download) + +Step 2 +: Install the required Node.js packages in the root of your project. + +```sh +npm install --save-dev @babel/core @babel/cli +``` + +Step 3 +: Add the babel executable to Hugo's `security.exec.allow` list in your site configuration: + +{{< code-toggle file=hugo >}} +[security.exec] + allow = ['^(dart-)?sass(-embedded)?$', '^go$', '^npx$', '^postcss$', '^babel$'] +{{< /code-toggle >}} + +## Configuration + +We add the main project's `node_modules` to `NODE_PATH` when running Babel and similar tools. There are some known [issues](https://github.com/babel/babel/issues/5618) with Babel in this area, so if you have a `babel.config.js` living in a Hugo Module (and not in the project itself), we recommend using `require` to load the presets/plugins, e.g.: + +```js +module.exports = { + presets: [ + [ + require("@babel/preset-env"), + { + useBuiltIns: "entry", + corejs: 3, + }, + ], + ], +}; +``` + +## Options + +config +: (`string`) Path to the Babel configuration file. Hugo will, by default, look for a `babel.config.js` in your project. More information on these configuration files can be found here: [babel configuration](https://babeljs.io/docs/en/configuration). + +minified +: (`bool`) Save as many bytes as possible when printing + +noComments +: (`bool`) Write comments to generated output (true by default) + +compact +: (`bool`) Do not include superfluous whitespace characters and line terminators. Defaults to `auto` if not set. + +verbose +: (`bool`) Log everything + +sourceMap +: (`string`) Output `inline` or `external` sourcemap from the babel compile. External sourcemaps will be written to the target with the output file name + ".map". Input sourcemaps can be read from js.Build and node modules and combined into the output sourcemaps. diff --git a/docs/content/en/functions/resources/ByType.md b/docs/content/en/functions/resources/ByType.md new file mode 100644 index 000000000..a5df3befb --- /dev/null +++ b/docs/content/en/functions/resources/ByType.md @@ -0,0 +1,34 @@ +--- +title: resources.ByType +description: Returns a collection of global resources of the given media type, or nil if none found. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/resources/Get + - functions/resources/GetMatch + - functions/resources/GetRemote + - functions/resources/Match + - methods/page/Resources + returnType: resource.Resources + signatures: [resources.ByType MEDIATYPE] +--- + +The [media type] is typically one of `image`, `text`, `audio`, `video`, or `application`. + +```go-html-template +{{ range resources.ByType "image" }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> +{{ end }} +``` + +{{% note %}} +This function operates on global resources. A global resource is a file within the assets directory, or within any directory mounted to the assets directory. + +For page resources, use the [`Resources.ByType`] method on the Page object. + +[`Resources.ByType`]: /methods/page/resources +{{% /note %}} + +[media type]: https://en.wikipedia.org/wiki/Media_type diff --git a/docs/content/en/functions/resources/Concat.md b/docs/content/en/functions/resources/Concat.md new file mode 100644 index 000000000..809ee83d0 --- /dev/null +++ b/docs/content/en/functions/resources/Concat.md @@ -0,0 +1,26 @@ +--- +title: resources.Concat +description: Returns a concatenated slice of resources. +categories: [] +keywords: [] +action: + aliases: [] + related: [] + returnType: resource.Resource + signatures: ['resources.Concat TARGETPATH [RESOURCE...]'] +--- + +The `resources.Concat` function returns a concatenated slice of resources, caching the result using the target path as its cache key. Each resource must have the same [media type]. + +Hugo publishes the resource to the target path when you call its [`Publish`], [`Permalink`], or [`RelPermalink`] methods. + +[media type]: https://en.wikipedia.org/wiki/Media_type +[`publish`]: /methods/resource/publish +[`permalink`]: /methods/resource/permalink +[`relpermalink`]: /methods/resource/relpermalink + +```go-html-template +{{ $plugins := resources.Get "js/plugins.js" }} +{{ $global := resources.Get "js/global.js" }} +{{ $js := slice $plugins $global | resources.Concat "js/bundle.js" }} +``` diff --git a/docs/content/en/functions/resources/Copy.md b/docs/content/en/functions/resources/Copy.md new file mode 100644 index 000000000..f8e962aee --- /dev/null +++ b/docs/content/en/functions/resources/Copy.md @@ -0,0 +1,32 @@ +--- +title: resources.Copy +description: Copies the given resource to the target path. +categories: [] +action: + aliases: [] + related: [] + returnType: resource.Resource + signatures: [resources.Copy TARGETPATH RESOURCE] +--- + +{{< new-in 0.100.0 >}} + +```go-html-template +{{ with resources.Get "images/a.jpg" }} + {{ with resources.Copy "img/new-image-name.jpg" . }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> + {{ end }} +{{ end }} +``` + +The relative URL of the new published resource will be: + +```text +/img/new-image-name.jpg +``` + +The target path must be different than the source path, as shown in the example above. + +{{% note %}} +Use the `resources.Copy` function with global, page, and remote resources. +{{% /note %}} diff --git a/docs/content/en/functions/resources/ExecuteAsTemplate.md b/docs/content/en/functions/resources/ExecuteAsTemplate.md new file mode 100644 index 000000000..5f7e58413 --- /dev/null +++ b/docs/content/en/functions/resources/ExecuteAsTemplate.md @@ -0,0 +1,62 @@ +--- +title: resources.ExecuteAsTemplate +description: Returns a resource created from a Go template, parsed and executed with the given context. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/resources/FromString + returnType: resource.Resource + signatures: [resources.ExecuteAsTemplate TARGETPATH CONTEXT RESOURCE] +--- + +The `resources.ExecuteAsTemplate` function returns a resource created from a Go template, parsed and executed with the given context, caching the result using the target path as its cache key. + +Hugo publishes the resource to the target path when you call its [`Publish`], [`Permalink`], or [`RelPermalink`] methods. + +[`publish`]: /methods/resource/publish +[`permalink`]: /methods/resource/permalink +[`relpermalink`]: /methods/resource/relpermalink + +Let's say you have a CSS file that you wish to populate with values from your site configuration: + +{{< code file=assets/css/template.css lang=go-html-template >}} +body { + background-color: {{ site.Params.style.bg_color }}; + color: {{ site.Params.style.text_color }}; +} +{{< /code >}} + +And your site configuration contains: + +{{< code-toggle file=hugo >}} +[params.style] +bg_color = '#fefefe' +text_color = '#222' +{{< /code-toggle >}} + +Place this in your baseof.html template: + +```go-html-template +{{ with resources.Get "css/template.css" }} + {{ with resources.ExecuteAsTemplate "css/main.css" $ . }} + <link rel="stylesheet" href="{{ .RelPermalink }}"> + {{ end }} +{{ end }} +``` + +The example above: + +1. Captures the template as a resource +2. Executes the resource as a template, passing the current page in context +3. Publishes the resource to css/main.css + +The result is: + +{{< code file=public/css/main.css >}} +body { + background-color: #fefefe; + color: #222; +} +{{< /code >}} diff --git a/docs/content/en/functions/resources/Fingerprint.md b/docs/content/en/functions/resources/Fingerprint.md new file mode 100644 index 000000000..685214f96 --- /dev/null +++ b/docs/content/en/functions/resources/Fingerprint.md @@ -0,0 +1,42 @@ +--- +title: resources.Fingerprint +description: Cryptographically hashes the content of the given resource. +categories: [] +keywords: [] +action: + aliases: [fingerprint] + related: + - functions/js/Build + - functions/resources/Babel + - functions/resources/Minify + - functions/resources/PostCSS + - functions/resources/PostProcess + - functions/resources/ToCSS + returnType: resource.Resource + signatures: ['resources.Fingerprint [ALGORITHM] RESOURCE'] +--- + +```go-html-template +{{ with resources.Get "js/main.js" }} + {{ with . | fingerprint "sha256" }} + <script src="{{ .RelPermalink }}" integrity="{{ .Data.Integrity }}" crossorigin="anonymous"></script> + {{ end }} +{{ end }} +``` + +Hugo renders this to something like: + +```html +<script src="/js/main.62e...df1.js" integrity="sha256-Yuh...rfE=" crossorigin="anonymous"></script> +``` + +Although most commonly used with CSS and JavaScript resources, you can use the `resources.Fingerprint` function with any resource type. + +The hash algorithm may be one of `md5`, `sha256` (default), `sha384`, or `sha512`. + +After cryptographically hashing the resource content: + +1. The values returned by the `.Permalink` and `.RelPermalink` methods include the hash sum +2. The resource's `.Data.Integrity` method returns a [Subresource Integrity] (SRI) value consisting of the name of the hash algorithm, one hyphen, and the base64-encoded hash sum + +[Subresource Integrity]: https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity diff --git a/docs/content/en/functions/resources/FromString.md b/docs/content/en/functions/resources/FromString.md new file mode 100644 index 000000000..d559058c3 --- /dev/null +++ b/docs/content/en/functions/resources/FromString.md @@ -0,0 +1,77 @@ +--- +title: resources.FromString +description: Returns a resource created from a string. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/resources/ExecuteAsTemplate + returnType: resource.Resource + signatures: [resources.FromString TARGETPATH STRING] +--- + +The `resources.FromString` function returns a resource created from a string, caching the result using the target path as its cache key. + +Hugo publishes the resource to the target path when you call its [`Publish`], [`Permalink`], or [`RelPermalink`] methods. + +[`publish`]: /methods/resource/publish +[`permalink`]: /methods/resource/permalink +[`relpermalink`]: /methods/resource/relpermalink + +Let's say you need to publish a file named "site.json" in the root of your public directory, containing the build date, the Hugo version used to build the site, and the date that the content was last modified. For example: + +```json +{ + "build_date": "2023-10-03T10:50:40-07:00", + "hugo_version": "0.122.0", + "last_modified": "2023-10-02T15:21:27-07:00" +} +``` + +Place this in your baseof.html template: + +```go-html-template +{{ if .IsHome }} + {{ $rfc3339 := "2006-01-02T15:04:05Z07:00" }} + {{ $m := dict + "hugo_version" hugo.Version + "build_date" (now.Format $rfc3339) + "last_modified" (site.LastChange.Format $rfc3339) + }} + {{ $json := jsonify $m }} + {{ $r := resources.FromString "site.json" $json }} + {{ $r.Publish }} +{{ end }} +``` + +The example above: + +1. Creates a map with the relevant key/value pairs using the [`dict`] function +2. Encodes the map as a JSON string using the [`jsonify`] function +3. Creates a resource from the JSON string using the `resources.FromString` function +4. Publishes the file to the root of the public directory using the resource's `.Publish` method + +Combine `resources.FromString` with [`resources.ExecuteAsTemplate`] if your string contains template actions. Rewriting the example above: + +```go-html-template +{{ if .IsHome }} + {{ $string := ` + {{ $rfc3339 := "2006-01-02T15:04:05Z07:00" }} + {{ $m := dict + "hugo_version" hugo.Version + "build_date" (now.Format $rfc3339) + "last_modified" (site.LastChange.Format $rfc3339) + }} + {{ $json := jsonify $m }} + ` + }} + {{ $r := resources.FromString "" $string }} + {{ $r = $r | resources.ExecuteAsTemplate "site.json" . }} + {{ $r.Publish }} +{{ end }} +``` + +[`dict`]: /functions/collections/dictionary +[`jsonify`]: /functions/encoding/jsonify +[`resources.ExecuteAsTemplate`]: /functions/resources/executeastemplate diff --git a/docs/content/en/functions/resources/Get.md b/docs/content/en/functions/resources/Get.md new file mode 100644 index 000000000..a8b75d52b --- /dev/null +++ b/docs/content/en/functions/resources/Get.md @@ -0,0 +1,30 @@ +--- +title: resources.Get +description: Returns a global resource from the given path, or nil if none found. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/resources/ByType + - functions/resources/GetMatch + - functions/resources/GetRemote + - functions/resources/Match + - methods/page/Resources + returnType: resource.Resource + signatures: [resources.Get PATH] +--- + +```go-html-template +{{ with resources.Get "images/a.jpg" }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> +{{ end }} +``` + +{{% note %}} +This function operates on global resources. A global resource is a file within the assets directory, or within any directory mounted to the assets directory. + +For page resources, use the [`Resources.Get`] method on the Page object. + +[`Resources.Get`]: /methods/page/resources +{{% /note %}} diff --git a/docs/content/en/functions/resources/GetMatch.md b/docs/content/en/functions/resources/GetMatch.md new file mode 100644 index 000000000..fde26c09d --- /dev/null +++ b/docs/content/en/functions/resources/GetMatch.md @@ -0,0 +1,36 @@ +--- +title: resources.GetMatch +description: Returns the first global resource from paths matching the given glob pattern, or nil if none found. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/resources/ByType + - functions/resources/Get + - functions/resources/GetRemote + - functions/resources/Match + - methods/page/Resources + returnType: resource.Resource + signatures: [resources.GetMatch PATTERN] +--- + +```go-html-template +{{ with resources.GetMatch "images/*.jpg" }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> +{{ end }} +``` + +{{% note %}} +This function operates on global resources. A global resource is a file within the assets directory, or within any directory mounted to the assets directory. + +For page resources, use the [`Resources.GetMatch`] method on the Page object. + +[`Resources.GetMatch`]: /methods/page/resources +{{% /note %}} + +Hugo determines a match using a case-insensitive [glob pattern]. + +{{% include "functions/_common/glob-patterns.md" %}} + +[glob pattern]: https://github.com/gobwas/glob#example diff --git a/docs/content/en/functions/resources/GetRemote.md b/docs/content/en/functions/resources/GetRemote.md new file mode 100644 index 000000000..0e6b91b64 --- /dev/null +++ b/docs/content/en/functions/resources/GetRemote.md @@ -0,0 +1,177 @@ +--- +title: resources.GetRemote +description: Returns a remote resource from the given URL, or nil if none found. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/data/GetCSV + - functions/data/GetJSON + - functions/resources/ByType + - functions/resources/Get + - functions/resources/GetMatch + - functions/resources/Match + - methods/page/Resources + returnType: resource.Resource + signatures: ['resources.GetRemote URL [OPTIONS]'] +toc: true +--- + +```go-html-template +{{ $url := "https://example.org/images/a.jpg" }} +{{ with resources.GetRemote $url }} + {{ with .Err }} + {{ errorf "%s" . }} + {{ else }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> + {{ end }} +{{ else }} + {{ errorf "Unable to get remote resource %q" $url }} +{{ end }} +``` + +## Options + +The `resources.GetRemote` function takes an optional map of options. + +```go-html-template +{{ $url := "https://example.org/api" }} +{{ $opts := dict + "headers" (dict "Authorization" "Bearer abcd") +}} +{{ $resource := resources.GetRemote $url $opts }} +``` + +If you need multiple values for the same header key, use a slice: + +```go-html-template +{{ $url := "https://example.org/api" }} +{{ $opts := dict + "headers" (dict "X-List" (slice "a" "b" "c")) +}} +{{ $resource := resources.GetRemote $url $opts }} +``` + +You can also change the request method and set the request body: + +```go-html-template +{{ $url := "https://example.org/api" }} +{{ $opts := dict + "method" "post" + "body" `{"complete": true}` + "headers" (dict "Content-Type" "application/json") +}} +{{ $resource := resources.GetRemote $url $opts }} +``` + +## Remote data + +When retrieving remote data, use the [`transform.Unmarshal`] function to [unmarshal] the response. + +[`transform.Unmarshal`]: /functions/transform/unmarshal +[unmarshal]: /getting-started/glossary/#unmarshal + +```go-html-template +{{ $data := "" }} +{{ $url := "https://example.org/books.json" }} +{{ with resources.GetRemote $url }} + {{ with .Err }} + {{ errorf "%s" . }} + {{ else }} + {{ $data = . | transform.Unmarshal }} + {{ end }} +{{ else }} + {{ errorf "Unable to get remote resource %q" $url }} +{{ end }} +``` + +## Error handling + +The [`Err`] method on a resource returned by the `resources.GetRemote` function returns an error message if the HTTP request fails, else nil. If you do not handle the error yourself, Hugo will fail the build. + +[`Err`]: /methods/resource/err + +```go-html-template +{{ $url := "https://broken-example.org/images/a.jpg" }} +{{ with resources.GetRemote $url }} + {{ with .Err }} + {{ errorf "%s" . }} + {{ else }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> + {{ end }} +{{ else }} + {{ errorf "Unable to get remote resource %q" $url }} +{{ end }} +``` + +To log an error as a warning instead of an error: + +```go-html-template +{{ $url := "https://broken-example.org/images/a.jpg" }} +{{ with resources.GetRemote $url }} + {{ with .Err }} + {{ warnf "%s" . }} + {{ else }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> + {{ end }} +{{ else }} + {{ errorf "Unable to get remote resource %q" $url }} +{{ end }} +``` + +## HTTP response + +The [`Data`] method on a resource returned by the `resources.GetRemote` function returns information from the HTTP response. + +[`Data`]: /methods/resource/data + +```go-html-template +{{ $url := "https://example.org/images/a.jpg" }} +{{ with resources.GetRemote $url }} + {{ with .Err }} + {{ errorf "%s" . }} + {{ else }} + {{ with .Data }} + {{ .ContentLength }} → 42764 + {{ .ContentType }} → image/jpeg + {{ .Status }} → 200 OK + {{ .StatusCode }} → 200 + {{ .TransferEncoding }} → [] + {{ end }} + {{ end }} +{{ else }} + {{ errorf "Unable to get remote resource %q" $url }} +{{ end }} +``` + +ContentLength +: (`int`) The content length in bytes. + +ContentType +: (`string`) The content type. + +Status +: (`string`) The HTTP status text. + +StatusCode +: (`int`) The HTTP status code. + +TransferEncoding +: (`string`) The transfer encoding. + +## Caching + +Resources returned from `resources.GetRemote` are cached to disk. See [configure file caches] for details. + +By default, Hugo derives the cache key from the arguments passed to the function, the URL and the options map, if any. + +Override the cache key by setting a `key` in the options map. Use this approach to have more control over how often Hugo fetches a remote resource. + +```go-html-template +{{ $url := "https://example.org/images/a.jpg" }} +{{ $cacheKey := print $url (now.Format "2006-01-02") }} +{{ $resource := resource.GetRemote $url (dict "key" $cacheKey) }} +``` + +[configure file caches]: /getting-started/configuration/#configure-file-caches diff --git a/docs/content/en/functions/resources/Match.md b/docs/content/en/functions/resources/Match.md new file mode 100644 index 000000000..0044351f1 --- /dev/null +++ b/docs/content/en/functions/resources/Match.md @@ -0,0 +1,36 @@ +--- +title: resources.Match +description: Returns a collection of global resources from paths matching the given glob pattern, or nil if none found. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/resources/ByType + - functions/resources/Get + - functions/resources/GetMatch + - functions/resources/GetRemote + - methods/page/Resources + returnType: resource.Resources + signatures: [resources.Match PATTERN] +--- + +```go-html-template +{{ range resources.Match "images/*.jpg" }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> +{{ end }} +``` + +{{% note %}} +This function operates on global resources. A global resource is a file within the assets directory, or within any directory mounted to the assets directory. + +For page resources, use the [`Resources.Match`] method on the Page object. + +[`Resources.Match`]: /methods/page/resources +{{% /note %}} + +Hugo determines a match using a case-insensitive [glob pattern]. + +{{% include "functions/_common/glob-patterns.md" %}} + +[glob pattern]: https://github.com/gobwas/glob#example diff --git a/docs/content/en/functions/resources/Minify.md b/docs/content/en/functions/resources/Minify.md new file mode 100644 index 000000000..9749df20a --- /dev/null +++ b/docs/content/en/functions/resources/Minify.md @@ -0,0 +1,23 @@ +--- +title: resources.Minify +description: Minifies the given resource. +categories: [] +keywords: [] +action: + aliases: [minify] + related: + - functions/js/Build + - functions/resources/Babel + - functions/resources/Fingerprint + - functions/resources/PostCSS + - functions/resources/ToCSS + returnType: resource.Resource + signatures: [resources.Minify RESOURCE] +--- + +```go-html-template +{{ $css := resources.Get "css/main.css" }} +{{ $style := $css | minify }} +``` + +Any CSS, JS, JSON, HTML, SVG, or XML resource can be minified using resources.Minify which takes for argument the resource object. diff --git a/docs/content/en/functions/resources/PostCSS.md b/docs/content/en/functions/resources/PostCSS.md new file mode 100644 index 000000000..a9f9ed3c8 --- /dev/null +++ b/docs/content/en/functions/resources/PostCSS.md @@ -0,0 +1,129 @@ +--- +title: resources.PostCSS +description: Processes the given resource with PostCSS using any PostCSS plugin. +categories: [] +keywords: [] +action: + aliases: [postCSS] + related: + - functions/resources/Fingerprint + - functions/resources/Minify + - functions/resources/PostProcess + - functions/resources/ToCSS + returnType: resource.Resource + signatures: ['resources.PostCSS [OPTIONS] RESOURCE'] +toc: true +--- + +```go-html-template +{{ with resources.Get "css/main.css" | postCSS }} + <link rel="stylesheet" href="{{ .RelPermalink }}"> +{{ end }} +``` + +## Setup + +Follow the steps below to transform CSS using any of the available [PostCSS plugins]. + +Step 1 +: Install [Node.js]. + +Step 2 +: Install the required Node.js packages in the root of your project. For example, to add vendor prefixes to your CSS rules: + +```sh +npm i -D postcss postcss-cli autoprefixer +``` + +Step 3 +: Create a PostCSS configuration file in the root of your project. You must name this file `postcss.config.js` or another [supported file name]. For example: + +```js +module.exports = { + plugins: [ + require('autoprefixer') + ] +}; +``` + +{{% note %}} +{{% include "functions/resources/_common/postcss-windows-warning.md" %}} +{{% /note %}} + +Step 4 +: Place your CSS file within the `assets/css` directory. + +Step 5 +: Process the resource with PostCSS: + +```go-html-template +{{ with resources.Get "css/main.css" | postCSS }} + <link rel="stylesheet" href="{{ .RelPermalink }}"> +{{ end }} +``` + +## Options + +The `resources.PostCSS` method takes an optional map of options. + +config +: (`string`) The directory that contains the PostCSS configuration file. Default is the root of the project directory. + +noMap +: (`bool`) Default is `false`. If `true`, disables inline sourcemaps. + +inlineImports +: (`bool`) Default is `false`. Enable inlining of @import statements. It does so recursively, but will only import a file once. URL imports (e.g. `@import url('https://fonts.googleapis.com/css?family=Open+Sans&display=swap');`) and imports with media queries will be ignored. Note that this import routine does not care about the CSS spec, so you can have @import anywhere in the file. Hugo will look for imports relative to the module mount and will respect theme overrides. + +skipInlineImportsNotFound +: (`bool`) Default is `false`. Before Hugo 0.99.0 when `inlineImports` was enabled and we failed to resolve an import, we logged it as a warning. We now fail the build. If you have regular CSS imports in your CSS that you want to preserve, you can either use imports with URL or media queries (Hugo does not try to resolve those) or set `skipInlineImportsNotFound` to true. + +```go-html-template +{{ $opts := dict "config" "config-directory" "noMap" true }} +{{ with resources.Get "css/main.css" | postCSS $opts }} + <link rel="stylesheet" href="{{ .RelPermalink }}"> +{{ end }} +``` + +## No configuration file + +To avoid using a PostCSS configuration file, you can specify a minimal configuration using the options map. + +use +: (`string`) A space-delimited list of PostCSS plugins to use. + +parser +: (`string`) A custom PostCSS parser. + +stringifier +: (`string`) A custom PostCSS stringifier. + +syntax +: (`string`) Custom postcss syntax. + +```go-html-template +{{ $opts := dict "use" "autoprefixer postcss-color-alpha" }} +{{ with resources.Get "css/main.css" | postCSS $opts }} + <link rel="stylesheet" href="{{ .RelPermalink }}"> +{{ end }} +``` + +## Check environment + +The current Hugo environment name (set by `--environment` or in configuration or OS environment) is available in the Node context, which allows constructs like this: + +```js +const autoprefixer = require('autoprefixer'); +const purgecss = require('@fullhuman/postcss-purgecss'); +module.exports = { + plugins: [ + autoprefixer, + process.env.HUGO_ENVIRONMENT !== 'development' ? purgecss : null + ] +} +``` + +[node.js]: https://nodejs.org/en/download +[postcss plugins]: https://www.postcss.parts/ +[supported file name]: https://github.com/postcss/postcss-load-config#usage +[transpile to CSS]: /functions/resources/tocss.md diff --git a/docs/content/en/functions/resources/PostProcess.md b/docs/content/en/functions/resources/PostProcess.md new file mode 100644 index 000000000..f765ea9af --- /dev/null +++ b/docs/content/en/functions/resources/PostProcess.md @@ -0,0 +1,160 @@ +--- +title: resources.PostProcess +description: Processes the given resource after the build. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/resources/Fingerprint + - functions/resources/Minify + - functions/resources/PostCSS + - functions/resources/ToCSS + returnType: postpub.PostPublishedResource + signatures: [resources.PostProcess RESOURCE] +toc: true +--- + +```go-html-template +{{ with resources.Get "css/main.css" }} + {{ if hugo.IsDevelopment }} + <link rel="stylesheet" href="{{ .RelPermalink }}"> + {{ else }} + {{ with . | postCSS | minify | fingerprint | resources.PostProcess }} + <link rel="stylesheet" href="{{ .RelPermalink }}" integrity="{{ .Data.Integrity }}" crossorigin="anonymous"> + {{ end }} + {{ end }} +{{ end }} +``` + +Marking a resource with `resources.PostProcess` postpones transformations until the build has finished. + +Call `resources.PostProcess` when one or more of the steps in the transformation chain depends on the result of the build. + +A prime use case for this is purging unused CSS rules using the [PurgeCSS] plugin for the PostCSS Node.js package. + +## CSS Purging + +{{% note %}} +There are several ways to set up CSS purging with PostCSS in Hugo. If you have a simple project, you should consider going the simpler route and drop the use of `resources.PostProcess` and just extract keywords from the templates. See the [Tailwind documentation](https://tailwindcss.com/docs/controlling-file-size/#app) for examples. +{{% /note %}} + +Step 1 +: Install [Node.js]. + +Step 2 +: Install the required Node.js packages in the root of your project: + +```sh +npm i -D postcss postcss-cli autoprefixer @fullhuman/postcss-purgecss +``` + +Step 3 +: Create a PostCSS configuration file in the root of your project. You must name this file `postcss.config.js` or another [supported file name]. For example: + +```js +const autoprefixer = require('autoprefixer'); +const purgecss = require('@fullhuman/postcss-purgecss')({ + content: ['./hugo_stats.json'], + defaultExtractor: content => { + const els = JSON.parse(content).htmlElements; + return [ + ...(els.tags || []), + ...(els.classes || []), + ...(els.ids || []), + ]; + }, + // https://purgecss.com/safelisting.html + safelist: [] +}); + +module.exports = { + plugins: [ + autoprefixer, + process.env.HUGO_ENVIRONMENT !== 'development' ? purgecss : null + ] +}; +``` + +{{% note %}} +{{% include "functions/resources/_common/postcss-windows-warning.md" %}} +{{% /note %}} + +Step 4 +: Enable creation of the `hugo_stats.json` file when building the site. If you are only using this for the production build, consider placing it below [config/production]. + +{{< code-toggle file=hugo >}} +[build.buildStats] +enable = true +{{< /code-toggle >}} + +See the [configure build] documentation for details and options. + +Step 5 +: Place your CSS file within the `assets/css` directory. + +Step 6 +: If the current environment is not `development`, process the resource with PostCSS: + +```go-html-template +{{ with resources.Get "css/main.css" }} + {{ if hugo.IsDevelopment }} + <link rel="stylesheet" href="{{ .RelPermalink }}"> + {{ else }} + {{ with . | postCSS | minify | fingerprint | resources.PostProcess }} + <link rel="stylesheet" href="{{ .RelPermalink }}" integrity="{{ .Data.Integrity }}" crossorigin="anonymous"> + {{ end }} + {{ end }} +{{ end }} +``` + +## Environment variables + +Hugo passes these environment variables to PostCSS, which allows you to do something like: + +```js +process.env.HUGO_ENVIRONMENT === 'production' ? [autoprefixer] : [] +``` + +PWD +: The absolute path to the project working directory. + +HUGO_ENVIRONMENT +: The current Hugo environment, set with the `--environment` command line flag. +Default is `production` for `hugo` and `development` for `hugo server`. + +HUGO_PUBLISHDIR +: The absolute path to the publish directory (the `public` directory). Note that the value will always point to a directory on disk even when running `hugo server` in memory mode. If you write to this folder from PostCSS when running the server, you could run the server with one of these flags: + +```sh +hugo server --renderToDisk +hugo server --renderStaticToDisk +``` + +Also, Hugo will add environment variables for all files mounted below `assets/_jsconfig`. A default mount will be set up with files in the project root matching this regexp: `(babel|postcss|tailwind)\.config\.js`. + +These will get environment variables named on the form `HUGO_FILE_:filename:` where `:filename:` is all upper case with periods replaced with underscore. This allows you to do something like: + +```js +let tailwindConfig = process.env.HUGO_FILE_TAILWIND_CONFIG_JS || './tailwind.config.js'; +``` + +## Limitations + +Do not use `resources.PostProcess` when running Hugo's built-in development server. The examples above specifically prevent this by verifying that the current environment is not "development". + +The `resources.PostProcess` function only works within templates that produce HTML files. + +You cannot manipulate the values returned from the resource’s methods. For example, the `strings.ToUpper` function in this example will not work as expected: + +```go-html-template +{{ $css := resources.Get "css/main.css" }} +{{ $css = $css | resources.PostCSS | minify | fingerprint | resources.PostProcess }} +{{ $css.RelPermalink | strings.ToUpper }} +``` + +[node.js]: https://nodejs.org/en/download +[supported file name]: https://github.com/postcss/postcss-load-config#usage +[config/production]: /getting-started/configuration/#configuration-directory +[configure build]: /getting-started/configuration/#configure-build +[purgecss]: https://github.com/FullHuman/purgecss#readme diff --git a/docs/content/en/functions/resources/ToCSS.md b/docs/content/en/functions/resources/ToCSS.md new file mode 100644 index 000000000..19ef33a64 --- /dev/null +++ b/docs/content/en/functions/resources/ToCSS.md @@ -0,0 +1,224 @@ +--- +title: resources.ToCSS +description: Transpiles Sass to CSS. +categories: [] +keywords: [] +action: + aliases: [toCSS] + related: + - functions/resources/Fingerprint + - functions/resources/Minify + - functions/resources/PostCSS + - functions/resources/PostProcess + returnType: resource.Resource + signatures: ['resources.ToCSS [OPTIONS] RESOURCE'] +toc: true +--- + +```go-html-template +{{ with resources.Get "sass/main.scss" }} + {{ $opts := dict "transpiler" "libsass" "targetPath" "css/style.css" }} + {{ with . | toCSS $opts }} + {{ if hugo.IsDevelopment }} + <link rel="stylesheet" href="{{ .RelPermalink }}"> + {{ else }} + {{ with . | minify | fingerprint }} + <link rel="stylesheet" href="{{ .RelPermalink }}" integrity="{{ .Data.Integrity }}" crossorigin="anonymous"> + {{ end }} + {{ end }} + {{ end }} +{{ end }} +``` + +Transpile Sass to CSS using the LibSass transpiler included in Hugo's extended edition, or [install Dart Sass](#dart-sass) to use the latest features of the Sass language. + +Sass has two forms of syntax: [SCSS] and [indented]. Hugo supports both. + +[scss]: https://sass-lang.com/documentation/syntax#scss +[indented]: https://sass-lang.com/documentation/syntax#the-indented-syntax + +## Options + +transpiler +: (`string`) The transpiler to use, either `libsass` (default) or `dartsass`. Hugo's extended edition includes the LibSass transpiler. To use the Dart Sass transpiler, see the [installation instructions](#dart-sass) below. + +targetPath +: (`string`) If not set, the transformed resource's target path will be the original path of the asset file with its extension replaced by `.css`. + +vars +: (`map`) A map of key/value pairs that will be available in the `hugo:vars` namespace. Useful for [initializing Sass variables from Hugo templates](https://discourse.gohugo.io/t/42053/). + +```scss +// LibSass +@import "hugo:vars"; + +// Dart Sass +@use "hugo:vars" as v; +``` + +outputStyle +: (`string`) Output styles available to LibSass include `nested` (default), `expanded`, `compact`, and `compressed`. Output styles available to Dart Sass include `expanded` (default) and `compressed`. + +precision +: (`int`) Precision of floating point math. Not applicable to Dart Sass. + +enableSourceMap +: (`bool`) If `true`, generates a source map. + +sourceMapIncludeSources +: (`bool`) If `true`, embeds sources in the generated source map. Not applicable to LibSass. + +includePaths +: (`slice`) A slice of paths, relative to the project root, that the transpiler will use when resolving `@use` and `@import` statements. + +```go-html-template +{{ $opts := dict + "transpiler" "dartsass" + "targetPath" "css/style.css" + "vars" site.Params.styles + "enableSourceMap" (not hugo.IsProduction) + "includePaths" (slice "node_modules/bootstrap/scss") +}} +{{ with resources.Get "sass/main.scss" | toCSS $opts | minify | fingerprint }} + <link rel="stylesheet" href="{{ .RelPermalink }}" integrity="{{ .Data.Integrity }}" crossorigin="anonymous"> +{{ end }} +``` + +## Dart Sass + +The extended version of Hugo includes [LibSass] to transpile Sass to CSS. In 2020, the Sass team deprecated LibSass in favor of [Dart Sass]. + +Use the latest features of the Sass language by installing Dart Sass in your development and production environments. + +### Installation overview + +Dart Sass is compatible with Hugo v0.114.0 and later. + +If you have been using Embedded Dart Sass[^1] with Hugo v0.113.0 and earlier, uninstall Embedded Dart Sass, then install Dart Sass. If you have installed both, Hugo will use Dart Sass. + +If you install Hugo as a [Snap package] there is no need to install Dart Sass. The Hugo Snap package includes Dart Sass. + +[^1]: In 2023, the Sass team deprecated Embedded Dart Sass in favor of Dart Sass. + +### Installing in a development environment + +When you install Dart Sass somewhere in your PATH, Hugo will find it. + +OS|Package manager|Site|Installation +:--|:--|:--|:-- +Linux|Homebrew|[brew.sh]|`brew install sass/sass/sass` +Linux|Snap|[snapcraft.io]|`sudo snap install dart-sass` +macOS|Homebrew|[brew.sh]|`brew install sass/sass/sass` +Windows|Chocolatey|[chocolatey.org]|`choco install sass` +Windows|Scoop|[scoop.sh]|`scoop install sass` + +You may also install [prebuilt binaries] for Linux, macOS, and Windows. + +Run `hugo env` to list the active transpilers. + +### Installing in a production environment + +For [CI/CD] deployments (e.g., GitHub Pages, GitLab Pages, Netlify, etc.) you must edit the workflow to install Dart Sass before Hugo builds the site[^2]. Some providers allow you to use one of the package managers above, or you can download and extract one of the prebuilt binaries. + +[^2]: You do not have to do this if (a) you have not modified the assets cache location, and (b) you have not set `useResourceCacheWhen` to `never` in your [site configuration], and (c) you add and commit your resources directory to your repository. + +#### GitHub Pages + +To install Dart Sass for your builds on GitHub Pages, add this step to the GitHub Pages workflow file: + +```yaml +- name: Install Dart Sass + run: sudo snap install dart-sass +``` + +If you are using GitHub Pages for the first time with your repository, GitHub provides a [starter workflow] for Hugo that includes Dart Sass. This is the simplest way to get started. + +#### GitLab Pages + +To install Dart Sass for your builds on GitLab Pages, the `.gitlab-ci.yml` file should look something like this: + +```yaml +variables: + HUGO_VERSION: 0.122.0 + DART_SASS_VERSION: 1.70.0 + GIT_DEPTH: 0 + GIT_STRATEGY: clone + GIT_SUBMODULE_STRATEGY: recursive + TZ: America/Los_Angeles +image: + name: golang:1.20-buster +pages: + script: + # Install Dart Sass + - curl -LJO https://github.com/sass/dart-sass/releases/download/${DART_SASS_VERSION}/dart-sass-${DART_SASS_VERSION}-linux-x64.tar.gz + - tar -xf dart-sass-${DART_SASS_VERSION}-linux-x64.tar.gz + - cp -r dart-sass/* /usr/local/bin + - rm -rf dart-sass* + # Install Hugo + - curl -LJO https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_extended_${HUGO_VERSION}_linux-amd64.deb + - apt install -y ./hugo_extended_${HUGO_VERSION}_linux-amd64.deb + - rm hugo_extended_${HUGO_VERSION}_linux-amd64.deb + # Build + - hugo --gc --minify + artifacts: + paths: + - public + rules: + - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH +``` + +#### Netlify + +To install Dart Sass for your builds on Netlify, the `netlify.toml` file should look something like this: + +```toml +[build.environment] +HUGO_VERSION = "0.122.0" +DART_SASS_VERSION = "1.70.0" +TZ = "America/Los_Angeles" + +[build] +publish = "public" +command = """\ + curl -LJO https://github.com/sass/dart-sass/releases/download/${DART_SASS_VERSION}/dart-sass-${DART_SASS_VERSION}-linux-x64.tar.gz && \ + tar -xf dart-sass-${DART_SASS_VERSION}-linux-x64.tar.gz && \ + rm dart-sass-${DART_SASS_VERSION}-linux-x64.tar.gz && \ + export PATH=/opt/build/repo/dart-sass:$PATH && \ + hugo --gc --minify \ + """ +``` + +### Example + +To transpile with Dart Sass, set `transpiler` to `dartsass` in the options map passed to `resources.ToCSS`. For example: + +```go-html-template +{{ with resources.Get "sass/main.scss" }} + {{ $opts := dict "transpiler" "dartsass" "targetPath" "css/style.css" }} + {{ with . | toCSS $opts }} + {{ if hugo.IsDevelopment }} + <link rel="stylesheet" href="{{ .RelPermalink }}"> + {{ else }} + {{ with . | minify | fingerprint }} + <link rel="stylesheet" href="{{ .RelPermalink }}" integrity="{{ .Data.Integrity }}" crossorigin="anonymous"> + {{ end }} + {{ end }} + {{ end }} +{{ end }} +``` + +### Miscellaneous + +If you build Hugo from source and run `mage test -v`, the test will fail if you install Dart Sass as a Snap package. This is due to the Snap package's strict confinement model. + +[brew.sh]: https://brew.sh/ +[chocolatey.org]: https://community.chocolatey.org/packages/sass +[ci/cd]: https://en.wikipedia.org/wiki/CI/CD +[dart sass]: https://sass-lang.com/dart-sass +[libsass]: https://sass-lang.com/libsass +[prebuilt binaries]: https://github.com/sass/dart-sass/releases/latest +[scoop.sh]: https://scoop.sh/#/apps?q=sass +[site configuration]: /getting-started/configuration/#configure-build +[snap package]: /installation/linux/#snap +[snapcraft.io]: https://snapcraft.io/dart-sass +[starter workflow]: https://github.com/actions/starter-workflows/blob/main/pages/hugo.yml diff --git a/docs/content/en/functions/resources/_common/_index.md b/docs/content/en/functions/resources/_common/_index.md new file mode 100644 index 000000000..b57b688b3 --- /dev/null +++ b/docs/content/en/functions/resources/_common/_index.md @@ -0,0 +1,12 @@ +--- +_build: + list: never + publishResources: false + render: never +--- + +<!-- +Files within this headless branch bundle are markdown snippets. Each file must contain front matter delimiters, though front matter fields are not required. + +Include the rendered content using the "include" shortcode. +--> diff --git a/docs/content/en/functions/resources/_common/postcss-windows-warning.md b/docs/content/en/functions/resources/_common/postcss-windows-warning.md new file mode 100644 index 000000000..1b72e74db --- /dev/null +++ b/docs/content/en/functions/resources/_common/postcss-windows-warning.md @@ -0,0 +1,8 @@ +--- +# Do not remove front matter. +--- + +If you are a Windows user, and the path to your project contains a space, you must place the PostCSS configuration within the package.json file. See [this example] and issue [#7333]. + +[this example]: https://github.com/postcss/postcss-load-config#packagejson +[#7333]: https://github.com/gohugoio/hugo/issues/7333 diff --git a/docs/content/en/functions/resources/_index.md b/docs/content/en/functions/resources/_index.md new file mode 100644 index 000000000..364b9448d --- /dev/null +++ b/docs/content/en/functions/resources/_index.md @@ -0,0 +1,12 @@ +--- +title: Resource functions +linkTitle: resources +description: Template functions to work with resources. +categories: [] +keywords: [] +menu: + docs: + parent: functions +--- + +Use these functions to work with resources. diff --git a/docs/content/en/functions/safe/CSS.md b/docs/content/en/functions/safe/CSS.md new file mode 100644 index 000000000..08307fb15 --- /dev/null +++ b/docs/content/en/functions/safe/CSS.md @@ -0,0 +1,33 @@ +--- +title: safe.CSS +description: Declares the given string as safe CSS string. +categories: [] +keywords: [] +action: + aliases: [safeCSS] + related: + - functions/safe/HTML + - functions/safe/HTMLAttr + - functions/safe/JS + - functions/safe/JSStr + - functions/safe/URL + returnType: template.CSS + signatures: [safe.CSS INPUT] +aliases: [/functions/safecss] +--- + +In this context, *safe* means CSS content that matches any of the following: + +1. The CSS3 stylesheet production, such as `p { color: purple }`. +2. The CSS3 rule production, such as `a[href=~"https:"].foo#bar`. +3. CSS3 declaration productions, such as `color: red; margin: 2px`. +4. The CSS3 value production, such as `rgba(0, 0, 255, 127)`. + +Example: Given `style = "color: red;"` defined in the front matter of your `.md` file: + +* `<p style="{{ .Params.style | safeCSS }}">…</p>` → `<p style="color: red;">…</p>` +* `<p style="{{ .Params.style }}">…</p>` → `<p style="ZgotmplZ">…</p>` + +{{% note %}} +`ZgotmplZ` is a special value that indicates that unsafe content reached a CSS or URL context. +{{% /note %}} diff --git a/docs/content/en/functions/safe/HTML.md b/docs/content/en/functions/safe/HTML.md new file mode 100644 index 000000000..ecc4f1346 --- /dev/null +++ b/docs/content/en/functions/safe/HTML.md @@ -0,0 +1,39 @@ +--- +title: safe.HTML +description: Declares the given string as a safeHTML string. +categories: [] +keywords: [] +action: + aliases: [safeHTML] + related: + - functions/safe/CSS + - functions/safe/HTMLAttr + - functions/safe/JS + - functions/safe/JSStr + - functions/safe/URL + returnType: template.HTML + signatures: [safe.HTML INPUT] +aliases: [/functions/safehtml] +--- + +It should not be used for HTML from a third-party, or HTML with unclosed tags or comments. + +Given a site-wide [`hugo.toml`][config] with the following `copyright` value: + +{{< code-toggle file=hugo >}} +copyright = "© 2015 Jane Doe. <a href=\"https://creativecommons.org/licenses/by/4.0/\">Some rights reserved</a>." +{{< /code-toggle >}} + +`{{ .Site.Copyright | safeHTML }}` in a template would then output: + +```html +© 2015 Jane Doe. <a href="https://creativecommons.org/licenses/by/4.0/">Some rights reserved</a>. +``` + +However, without the `safeHTML` function, html/template assumes `.Site.Copyright` to be unsafe and therefore escapes all HTML tags and renders the whole string as plain text: + +```html +<p>© 2015 Jane Doe. <a href="https://creativecommons.org/licenses by/4.0/">Some rights reserved</a>.</p> +``` + +[config]: /getting-started/configuration/ diff --git a/docs/content/en/functions/safe/HTMLAttr.md b/docs/content/en/functions/safe/HTMLAttr.md new file mode 100644 index 000000000..198fc8ff3 --- /dev/null +++ b/docs/content/en/functions/safe/HTMLAttr.md @@ -0,0 +1,55 @@ +--- +title: safe.HTMLAttr +description: Declares the given key/value pair as a safe HTML attribute. +categories: [] +keywords: [] +action: + aliases: [safeHTMLAttr] + related: + - functions/safe/CSS + - functions/safe/HTML + - functions/safe/JS + - functions/safe/JSStr + - functions/safe/URL + returnType: template.HTMLAttr + signatures: [safe.HTMLAttr INPUT] +aliases: [/functions/safehtmlattr] +--- + +Given a site configuration that contains this menu entry: + +{{< code-toggle file=hugo >}} +[[menus.main]] + name = "IRC" + url = "irc://irc.freenode.net/#golang" +{{< /code-toggle >}} + +Attempting to use the `url` value directly in an attribute: + +```go-html-template +{{ range site.Menus.main }} + <a href="{{ .URL }}">{{ .Name }}</a> +{{ end }} +``` + +Will produce: + +```html +<a href="#ZgotmplZ">IRC</a> +``` + +`ZgotmplZ` is a special value, inserted by Go's [template/html] package, that indicates that unsafe content reached a CSS or URL context. + +To indicate that the HTML attribute is safe: + +```go-html-template +{{ range site.Menus.main }} + <a {{ printf "href=%q" .URL | safeHTMLAttr }}>{{ .Name }}</a> +{{ end }} +``` + +{{% note %}} +As demonstrated above, you must pass the HTML attribute name _and_ value through the function. Applying `safeHTMLAttr` to the attribute value has no effect. +{{% /note %}} + +[template/html]: https://pkg.go.dev/html/template diff --git a/docs/content/en/functions/safe/JS.md b/docs/content/en/functions/safe/JS.md new file mode 100644 index 000000000..65279b89b --- /dev/null +++ b/docs/content/en/functions/safe/JS.md @@ -0,0 +1,26 @@ +--- +title: safe.JS +description: Declares the given string as a safe JavaScript expression. +categories: [] +keywords: [] +action: + aliases: [safeJS] + related: + - functions/safe/CSS + - functions/safe/HTML + - functions/safe/HTMLAttr + - functions/safe/JSStr + - functions/safe/URL + returnType: template.JS + signatures: [safe.JS INPUT] +aliases: [/functions/safejs] +--- + +In this context, *safe* means the string encapsulates a known safe EcmaScript5 Expression (e.g., `(x + y * z())`). + +Template authors are responsible for ensuring that typed expressions do not break the intended precedence and that there is no statement/expression ambiguity as when passing an expression like `{ foo:bar() }\n['foo']()`, which is both a valid expression and a valid program with a very different meaning. + +Example: Given `hash = "619c16f"` defined in the front matter of your `.md` file: + +* `<script>var form_{{ .Params.hash | safeJS }};…</script>` → `<script>var form_619c16f;…</script>` +* `<script>var form_{{ .Params.hash }};…</script>` → `<script>var form_"619c16f";…</script>` diff --git a/docs/content/en/functions/safe/JSStr.md b/docs/content/en/functions/safe/JSStr.md new file mode 100644 index 000000000..36d2b36fa --- /dev/null +++ b/docs/content/en/functions/safe/JSStr.md @@ -0,0 +1,55 @@ +--- +title: safe.JSStr +description: Declares the given string as a safe JavaScript string. +categories: [] +keywords: [] +action: + aliases: [safeJSStr] + related: + - functions/safe/CSS + - functions/safe/HTML + - functions/safe/HTMLAttr + - functions/safe/JS + - functions/safe/URL + returnType: template.JSStr + signatures: [safe.JSStr INPUT] +aliases: [/functions/safejsstr] +--- + +Encapsulates a sequence of characters meant to be embedded between quotes in a JavaScript expression. Use of this type presents a security risk: the encapsulated content should come from a trusted source, as it will be included verbatim in the template output. + +Without declaring a variable to be a safe JavaScript string: + +```go-html-template +{{ $title := "Lilo & Stitch" }} +<script> + const a = "Title: " + {{ $title }}; +</script> +``` + +Rendered: + +```html +<script> + const a = "Title: " + "Lilo \u0026 Stitch"; +</script> +``` + +To avoid escaping by Go's [html/template] package: + +```go-html-template +{{ $title := "Lilo & Stitch" }} +<script> + const a = "Title: " + {{ $title | safeJSStr }}; +</script> +``` + +Rendered: + +```html +<script> + const a = "Title: " + "Lilo & Stitch"; +</script> +``` + +[html/template]: https://pkg.go.dev/html/template diff --git a/docs/content/en/functions/safe/URL.md b/docs/content/en/functions/safe/URL.md new file mode 100644 index 000000000..2da6895e5 --- /dev/null +++ b/docs/content/en/functions/safe/URL.md @@ -0,0 +1,70 @@ +--- +title: safe.URL +description: Declares the given string as a safe URL or URL substring. +categories: [] +keywords: [] +action: + aliases: [safeURL] + related: + - functions/safe/CSS + - functions/safe/HTML + - functions/safe/HTMLAttr + - functions/safe/JS + - functions/safe/JSStr + returnType: template.URL + signatures: [safe.URL INPUT] +aliases: [/functions/safeurl] +--- + +`safeURL` declares the provided string as a "safe" URL or URL substring (see [RFC 3986]). A URL like `javascript:checkThatFormNotEditedBeforeLeavingPage()` from a trusted source should go in the page, but by default dynamic `javascript:` URLs are filtered out since they are a frequently exploited injection vector. + +Without `safeURL`, only the URI schemes `http:`, `https:` and `mailto:` are considered safe by Go templates. If any other URI schemes (e.g., `irc:` and `javascript:`) are detected, the whole URL will be replaced with `#ZgotmplZ`. This is to "defang" any potential attack in the URL by rendering it useless. + +The following examples use a [site `hugo.toml`][configuration] with the following [menu entry][menus]: + +{{< code-toggle file=hugo >}} +[[menus.main]] +name = "IRC: #golang at freenode" +url = "irc://irc.freenode.net/#golang" +{{< /code-toggle >}} + +The following is an example of a sidebar partial that may be used in conjunction with the preceding front matter example: + +{{< code file=layouts/partials/bad-url-sidebar-menu.html >}} +<!-- This unordered list may be part of a sidebar menu --> +<ul> + {{ range .Site.Menus.main }} + <li><a href="{{ .URL }}">{{ .Name }}</a></li> + {{ end }} +</ul> +{{< /code >}} + +This partial would produce the following HTML output: + +```html +<!-- This unordered list may be part of a sidebar menu --> +<ul> + <li><a href="#ZgotmplZ">IRC: #golang at freenode</a></li> +</ul> +``` + +The odd output can be remedied by adding ` | safeURL` to our `.URL` page variable: + +{{< code file=layouts/partials/correct-url-sidebar-menu.html >}} +<!-- This unordered list may be part of a sidebar menu --> +<ul> + <li><a href="{{ .URL | safeURL }}">{{ .Name }}</a></li> +</ul> +{{< /code >}} + +With the `.URL` page variable piped through `safeURL`, we get the desired output: + +```html +<ul class="sidebar-menu"> + <li><a href="irc://irc.freenode.net/#golang">IRC: #golang at freenode</a></li> +</ul> +``` + +[configuration]: /getting-started/configuration/ +[menus]: /content-management/menus/ +[RFC 3986]: https://tools.ietf.org/html/rfc3986 diff --git a/docs/content/en/functions/safe/_index.md b/docs/content/en/functions/safe/_index.md new file mode 100644 index 000000000..f80a2cff4 --- /dev/null +++ b/docs/content/en/functions/safe/_index.md @@ -0,0 +1,14 @@ +--- +title: Safe functions +linkTitle: safe +description: Template functions to declare a value as safe in the context of Go's html/template package. +categories: [] +keywords: [] +menu: + docs: + parent: functions +--- + +Use these functions to declare a value as safe in the context of Go's [html/template] package. + +[html/template]: https://pkg.go.dev/html/template diff --git a/docs/content/en/functions/strings/Chomp.md b/docs/content/en/functions/strings/Chomp.md new file mode 100644 index 000000000..349f1e9b7 --- /dev/null +++ b/docs/content/en/functions/strings/Chomp.md @@ -0,0 +1,27 @@ +--- +title: strings.Chomp +description: Returns the given string, removing all trailing newline characters and carriage returns. +categories: [] +keywords: [] +action: + aliases: [chomp] + related: + - functions/strings/Trim + - functions/strings/TrimLeft + - functions/strings/TrimPrefix + - functions/strings/TrimRight + - functions/strings/TrimSuffix + returnType: any + signatures: [strings.Chomp STRING] +aliases: [/functions/chomp] +--- + +If the argument is of type `template.HTML`, returns `template.HTML`, else returns a `string`. + +```go-html-template +{{ chomp | "foo\n" }} → foo +{{ chomp | "foo\n\n" }} → foo + +{{ chomp | "foo\r\n" }} → foo +{{ chomp | "foo\r\n\r\n" }} → foo +``` diff --git a/docs/content/en/functions/strings/Contains.md b/docs/content/en/functions/strings/Contains.md new file mode 100644 index 000000000..0344b2981 --- /dev/null +++ b/docs/content/en/functions/strings/Contains.md @@ -0,0 +1,27 @@ +--- +title: strings.Contains +description: Reports whether the given string contains the given substring. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/strings/ContainsAny + - functions/strings/ContainsNonSpace + - functions/strings/HasPrefix + - functions/strings/HasSuffix + - functions/collections/In + returnType: bool + signatures: [strings.Contains STRING SUBSTRING] +aliases: [/functions/strings.contains] +--- + +```go-html-template +{{ strings.Contains "Hugo" "go" }} → true +``` + +The check is case sensitive: + +```go-html-template +{{ strings.Contains "Hugo" "Go" }} → false +``` diff --git a/docs/content/en/functions/strings/ContainsAny.md b/docs/content/en/functions/strings/ContainsAny.md new file mode 100644 index 000000000..f331d09f7 --- /dev/null +++ b/docs/content/en/functions/strings/ContainsAny.md @@ -0,0 +1,27 @@ +--- +title: strings.ContainsAny +description: Reports whether the given string contains any character within the given set. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/strings/Contains + - functions/strings/ContainsNonSpace + - functions/strings/HasPrefix + - functions/strings/HasSuffix + - functions/collections/In + returnType: bool + signatures: [strings.ContainsAny STRING SET] +aliases: [/functions/strings.containsany] +--- + +```go-html-template +{{ strings.ContainsAny "Hugo" "gm" }} → true +``` + +The check is case sensitive: + +```go-html-template +{{ strings.ContainsAny "Hugo" "Gm" }} → false +``` diff --git a/docs/content/en/functions/strings/ContainsNonSpace.md b/docs/content/en/functions/strings/ContainsNonSpace.md new file mode 100644 index 000000000..188aa14ba --- /dev/null +++ b/docs/content/en/functions/strings/ContainsNonSpace.md @@ -0,0 +1,35 @@ +--- +title: strings.ContainsNonSpace +description: Reports whether the given string contains any non-space characters as defined by Unicode’s White Space property. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/strings/Contains + - functions/strings/ContainsAny + - functions/strings/HasPrefix + - functions/strings/HasSuffix + - functions/collections/In + returnType: bool + signatures: [strings.ContainsNonSpace STRING] +aliases: [/functions/strings.containsnonspace] +--- + +{{< new-in 0.111.0 >}} + +```go-html-template +{{ strings.ContainsNonSpace "\n" }} → false +{{ strings.ContainsNonSpace " " }} → false +{{ strings.ContainsNonSpace "\n abc" }} → true +``` + +Common white space characters include: + +```text +'\t', '\n', '\v', '\f', '\r', ' ' +``` + +See the [Unicode Character Database] for a complete list. + +[Unicode Character Database]: https://www.unicode.org/Public/UCD/latest/ucd/PropList.txt diff --git a/docs/content/en/functions/strings/Count.md b/docs/content/en/functions/strings/Count.md new file mode 100644 index 000000000..43b5baeff --- /dev/null +++ b/docs/content/en/functions/strings/Count.md @@ -0,0 +1,25 @@ +--- +title: strings.Count +description: Returns the number of non-overlapping instances of the given substring within the given string. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/go-template/len + - functions/strings/CountRunes + - functions/strings/CountWords + - functions/strings/RuneCount + returnType: int + signatures: [strings.Count SUBSTR STRING] +aliases: [/functions/strings.count] +--- + +If `SUBSTR` is an empty string, this function returns 1 plus the number of Unicode code points in `STRING`. + +```go-html-template +{{ "aaabaab" | strings.Count "a" }} → 5 +{{ "aaabaab" | strings.Count "aa" }} → 2 +{{ "aaabaab" | strings.Count "aaa" }} → 1 +{{ "aaabaab" | strings.Count "" }} → 8 +``` diff --git a/docs/content/en/functions/strings/CountRunes.md b/docs/content/en/functions/strings/CountRunes.md new file mode 100644 index 000000000..10788e174 --- /dev/null +++ b/docs/content/en/functions/strings/CountRunes.md @@ -0,0 +1,24 @@ +--- +title: strings.CountRunes +description: Returns the number of runes in the given string excluding whitespace. +categories: [] +keywords: [] +action: + aliases: [countrunes] + related: + - functions/go-template/len + - functions/strings/Count + - functions/strings/CountWords + - functions/strings/RuneCount + returnType: int + signatures: [strings.CountRunes INPUT] +aliases: [/functions/countrunes] +--- + +In contrast with the [`strings.RuneCount`] function, which counts every rune in a string, `strings.CountRunes` excludes whitespace. + +```go-html-template +{{ "Hello, 世界" | strings.CountRunes }} → 8 +``` + +[`strings.RuneCount`]: /functions/strings/runecount diff --git a/docs/content/en/functions/strings/CountWords.md b/docs/content/en/functions/strings/CountWords.md new file mode 100644 index 000000000..3e4ec0465 --- /dev/null +++ b/docs/content/en/functions/strings/CountWords.md @@ -0,0 +1,20 @@ +--- +title: strings.CountWords +description: Returns the number of words in the given string. +categories: [] +keywords: [] +action: + aliases: [countwords] + related: + - functions/go-template/len + - functions/strings/Count + - functions/strings/CountRunes + - functions/strings/RuneCount + returnType: int + signatures: [strings.CountWords INPUT] +aliases: [/functions/countwords] +--- + +```go-html-template +{{ "Hugo is a static site generator." | countwords }} → 6 +``` diff --git a/docs/content/en/functions/strings/FindRESubmatch.md b/docs/content/en/functions/strings/FindRESubmatch.md new file mode 100644 index 000000000..302d1d9b4 --- /dev/null +++ b/docs/content/en/functions/strings/FindRESubmatch.md @@ -0,0 +1,90 @@ +--- +title: strings.FindRESubmatch +description: Returns a slice of all successive matches of the regular expression. Each element is a slice of strings holding the text of the leftmost match of the regular expression and the matches, if any, of its subexpressions. +categories: [] +keywords: [] +action: + aliases: [findRESubmatch] + related: + - functions/strings/FindRE + - functions/strings/Replace + - functions/strings/ReplaceRE + returnType: '[][]string' + signatures: ['strings.FindRESubmatch PATTERN INPUT [LIMIT]'] +aliases: [/functions/findresubmatch] +--- + +By default, `findRESubmatch` finds all matches. You can limit the number of matches with an optional LIMIT argument. A return value of nil indicates no match. + +{{% include "functions/_common/regular-expressions.md" %}} + +## Demonstrative examples + +```go-html-template +{{ findRESubmatch `a(x*)b` "-ab-" }} → [["ab" ""]] +{{ findRESubmatch `a(x*)b` "-axxb-" }} → [["axxb" "xx"]] +{{ findRESubmatch `a(x*)b` "-ab-axb-" }} → [["ab" ""] ["axb" "x"]] +{{ findRESubmatch `a(x*)b` "-axxb-ab-" }} → [["axxb" "xx"] ["ab" ""]] +{{ findRESubmatch `a(x*)b` "-axxb-ab-" 1 }} → [["axxb" "xx"]] +``` + +## Practical example + +This markdown: + +```text +- [Example](https://example.org) +- [Hugo](https://gohugo.io) +``` + +Produces this HTML: + +```html +<ul> + <li><a href="https://example.org">Example</a></li> + <li><a href="https://gohugo.io">Hugo</a></li> +</ul> +``` + +To match the anchor elements, capturing the link destination and text: + +```go-html-template +{{ $regex := `<a\s*href="(.+?)">(.+?)</a>` }} +{{ $matches := findRESubmatch $regex .Content }} +``` + +Viewed as JSON, the data structure of `$matches` in the code above is: + +```json +[ + [ + "<a href=\"https://example.org\"></a>Example</a>", + "https://example.org", + "Example" + ], + [ + "<a href=\"https://gohugo.io\">Hugo</a>", + "https://gohugo.io", + "Hugo" + ] +] +``` + +To render the `href` attributes: + +```go-html-template +{{ range $matches }} + {{ index . 1 }} +{{ end }} +``` + +Result: + +```text +https://example.org +https://gohugo.io +``` + +{{% note %}} +You can write and test your regular expression using [regex101.com](https://regex101.com/). Be sure to select the Go flavor before you begin. +{{% /note %}} diff --git a/docs/content/en/functions/strings/FindRe.md b/docs/content/en/functions/strings/FindRe.md new file mode 100644 index 000000000..861f38a12 --- /dev/null +++ b/docs/content/en/functions/strings/FindRe.md @@ -0,0 +1,36 @@ +--- +title: strings.FindRE +description: Returns a slice of strings that match the regular expression. +categories: [] +keywords: [] +action: + aliases: [findRE] + related: + - functions/strings/FindRESubmatch + - functions/strings/Replace + - functions/strings/ReplaceRE + returnType: '[]string' + signatures: ['strings.FindRE PATTERN INPUT [LIMIT]'] +aliases: [/functions/findre] +--- +By default, `findRE` finds all matches. You can limit the number of matches with an optional LIMIT argument. + +{{% include "functions/_common/regular-expressions.md" %}} + +This example returns a slice of all second level headings (`h2` elements) within the rendered `.Content`: + +```go-html-template +{{ findRE `(?s)<h2.*?>.*?</h2>` .Content }} +``` + +The `s` flag causes `.` to match `\n` as well, allowing us to find an `h2` element that contains newlines. + +To limit the number of matches to one: + +```go-html-template +{{ findRE `(?s)<h2.*?>.*?</h2>` .Content 1 }} +``` + +{{% note %}} +You can write and test your regular expression using [regex101.com](https://regex101.com/). Be sure to select the Go flavor before you begin. +{{% /note %}} diff --git a/docs/content/en/functions/strings/FirstUpper.md b/docs/content/en/functions/strings/FirstUpper.md new file mode 100644 index 000000000..8826b4f18 --- /dev/null +++ b/docs/content/en/functions/strings/FirstUpper.md @@ -0,0 +1,19 @@ +--- +title: strings.FirstUpper +description: Returns the given string, capitalizing the first character. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/strings/Title + - functions/strings/ToLower + - functions/strings/ToUpper + returnType: string + signatures: [strings.FirstUpper STRING] +aliases: [/functions/strings.firstupper] +--- + +```go-html-template +{{ strings.FirstUpper "foo" }} → Foo +``` diff --git a/docs/content/en/functions/strings/HasPrefix.md b/docs/content/en/functions/strings/HasPrefix.md new file mode 100644 index 000000000..455de0586 --- /dev/null +++ b/docs/content/en/functions/strings/HasPrefix.md @@ -0,0 +1,21 @@ +--- +title: strings.HasPrefix +description: Reports whether the given string begins with the given prefix. +categories: [] +keywords: [] +action: + aliases: [hasPrefix] + related: + - functions/strings/Contains + - functions/strings/ContainsAny + - functions/strings/ContainsNonSpace + - functions/strings/HasSuffix + - functions/collections/In + returnType: bool + signatures: [strings.HasPrefix STRING PREFIX] +aliases: [/functions/hasprefix,/functions/strings.hasprefix] +--- + +```go-html-template +{{ hasPrefix "Hugo" "Hu" }} → true +``` diff --git a/docs/content/en/functions/strings/HasSuffix.md b/docs/content/en/functions/strings/HasSuffix.md new file mode 100644 index 000000000..8fb12c527 --- /dev/null +++ b/docs/content/en/functions/strings/HasSuffix.md @@ -0,0 +1,21 @@ +--- +title: strings.HasSuffix +description: Reports whether the given string ends with the given suffix. +categories: [] +keywords: [] +action: + aliases: [hasSuffix] + related: + - functions/strings/Contains + - functions/strings/ContainsAny + - functions/strings/ContainsNonSpace + - functions/strings/HasPrefix + - functions/collections/In + returnType: bool + signatures: [strings.HasSuffix STRING SUFFIX] +aliases: [/functions/hassuffix,/functions/strings/hassuffix] +--- + +```go-html-template +{{ hasSuffix "Hugo" "go" }} → true +``` diff --git a/docs/content/en/functions/strings/Repeat.md b/docs/content/en/functions/strings/Repeat.md new file mode 100644 index 000000000..530b0d14b --- /dev/null +++ b/docs/content/en/functions/strings/Repeat.md @@ -0,0 +1,16 @@ +--- +title: strings.Repeat +description: Returns a new string consisting of zero or more copies of another string. +categories: [] +keywords: [] +action: + aliases: [] + related: [] + returnType: string + signatures: [strings.Repeat COUNT INPUT] +aliases: [/functions/strings.repeat] +--- + +```go-html-template +{{ strings.Repeat 3 "yo" }} → yoyoyo +``` diff --git a/docs/content/en/functions/strings/Replace.md b/docs/content/en/functions/strings/Replace.md new file mode 100644 index 000000000..9add6e12b --- /dev/null +++ b/docs/content/en/functions/strings/Replace.md @@ -0,0 +1,26 @@ +--- +title: strings.Replace +description: Returns a copy of INPUT, replacing all occurrences of OLD with NEW. +categories: [] +keywords: [] +action: + aliases: [replace] + related: + - functions/strings/FindRE + - functions/strings/FindRESubmatch + - functions/strings/ReplaceRE + returnType: string + signatures: ['strings.Replace INPUT OLD NEW [LIMIT]'] +aliases: [/functions/replace] +--- + +```go-html-template +{{ $s := "Batman and Robin" }} +{{ replace $s "Robin" "Catwoman" }} → Batman and Catwoman +``` + +Limit the number of replacements using the `LIMIT` argument: + +```go-html-template +{{ replace "aabbaabb" "a" "z" 2 }} → zzbbaabb +``` diff --git a/docs/content/en/functions/strings/ReplaceRE.md b/docs/content/en/functions/strings/ReplaceRE.md new file mode 100644 index 000000000..1c32c34fb --- /dev/null +++ b/docs/content/en/functions/strings/ReplaceRE.md @@ -0,0 +1,43 @@ +--- +title: strings.ReplaceRE +description: Returns a copy of INPUT, replacing all occurrences of a regular expression with a replacement pattern. +categories: [] +keywords: [] +action: + aliases: [replaceRE] + related: + - functions/strings/FindRE + - functions/strings/FindRESubmatch + - functions/strings/Replace + returnType: string + signatures: ['strings.ReplaceRE PATTERN REPLACEMENT INPUT [LIMIT]'] +aliases: [/functions/replacere] +--- + +{{% include "functions/_common/regular-expressions.md" %}} + +```go-html-template +{{ $s := "a-b--c---d" }} +{{ replaceRE `(-{2,})` "-" $s }} → a-b-c-d +``` + +Limit the number of replacements using the LIMIT argument: + +```go-html-template +{{ $s := "a-b--c---d" }} +{{ replaceRE `(-{2,})` "-" $s 1 }} → a-b-c---d +``` + +Use `$1`, `$2`, etc. within the replacement string to insert the content of each capturing group within the regular expression: + +```go-html-template +{{ $s := "http://gohugo.io/docs" }} +{{ replaceRE "^https?://([^/]+).*" "$1" $s }} → gohugo.io +``` + +{{% note %}} +You can write and test your regular expression using [regex101.com](https://regex101.com/). Be sure to select the Go flavor before you begin. +{{% /note %}} + +[RE2]: https://github.com/google/re2/wiki/Syntax +[string literal]: https://go.dev/ref/spec#String_literals diff --git a/docs/content/en/functions/strings/RuneCount.md b/docs/content/en/functions/strings/RuneCount.md new file mode 100644 index 000000000..46fedf01f --- /dev/null +++ b/docs/content/en/functions/strings/RuneCount.md @@ -0,0 +1,24 @@ +--- +title: strings.RuneCount +description: Returns the number of runes in the given string. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/go-template/len + - functions/strings/Count + - functions/strings/CountRunes + - functions/strings/CountWords + returnType: int + signatures: [strings.RuneCount INPUT] +aliases: [/functions/strings.runecount] +--- + +In contrast with the [`strings.CountRunes`] function, which excludes whitespace, `strings.RuneCount` counts every rune in a string. + +```go-html-template +{{ "Hello, 世界" | strings.RuneCount }} → 9 +``` + +[`strings.CountRunes`]: /functions/strings/countrunes diff --git a/docs/content/en/functions/strings/SliceString.md b/docs/content/en/functions/strings/SliceString.md new file mode 100644 index 000000000..2f33f8f65 --- /dev/null +++ b/docs/content/en/functions/strings/SliceString.md @@ -0,0 +1,20 @@ +--- +title: strings.SliceString +description: Creates a slice of a half-open range, including start and end indices. +categories: [] +keywords: [] +action: + aliases: [slicestr] + related: [] + returnType: string + signatures: ['strings.SliceString STRING START [END]'] +aliases: [/functions/slicestr] +--- + +For example, 1 and 4 creates a slice including elements 1 through 3. +The `end` index can be omitted; it defaults to the string's length. + +```go-html-template +{{ slicestr "BatMan" 3 }}` → Man +{{ slicestr "BatMan" 0 3 }}` → Bat +``` diff --git a/docs/content/en/functions/strings/Split.md b/docs/content/en/functions/strings/Split.md new file mode 100644 index 000000000..a9973ea63 --- /dev/null +++ b/docs/content/en/functions/strings/Split.md @@ -0,0 +1,26 @@ +--- +title: strings.Split +description: Returns a slice of strings by splitting the given string by a delimiter. +categories: [] +keywords: [] +action: + aliases: [split] + related: + - functions/collections/Delimit + returnType: string + signatures: [strings.Split STRING DELIM] +aliases: [/functions/split] +--- + +Examples: + +```go-html-template +{{ split "tag1,tag2,tag3" "," }} → ["tag1", "tag2", "tag3"] +{{ split "abc" "" }} → ["a", "b", "c"] +``` + +{{% note %}} +The `strings.Split` function essentially does the opposite of the [`collections.Delimit`] function. While `split` creates a slice from a string, `delimit` creates a string from a slice. + +[`collections.Delimit`]: /functions/collections/delimit +{{% /note %}} diff --git a/docs/content/en/functions/strings/Substr.md b/docs/content/en/functions/strings/Substr.md new file mode 100644 index 000000000..6c1852f58 --- /dev/null +++ b/docs/content/en/functions/strings/Substr.md @@ -0,0 +1,38 @@ +--- +title: strings.Substr +description: Extracts parts of a string from a specified character's position and returns the specified number of characters. +categories: [] +keywords: [] +action: + aliases: [substr] + related: [] + returnType: string + signatures: ['strings.Substr STRING START [LENGTH]'] +aliases: [/functions/substr] +--- + +It normally takes two argument: `start` and `length`. It can also take one argument: `start`, i.e. `length` is omitted, in which case the substring starting from start until the end of the string will be returned. + +To extract characters from the end of the string, use a negative start number. + +If `length` is given and is negative, that number of characters will be omitted from the end of string. + +```go-html-template +{{ substr "abcdef" 0 }} → abcdef +{{ substr "abcdef" 1 }} → bcdef + +{{ substr "abcdef" 0 1 }} → a +{{ substr "abcdef" 1 1 }} → b + +{{ substr "abcdef" 0 -1 }} → abcde +{{ substr "abcdef" 1 -1 }} → bcde + +{{ substr "abcdef" -1 }} → f +{{ substr "abcdef" -2 }} → ef + +{{ substr "abcdef" -1 1 }} → f +{{ substr "abcdef" -2 1 }} → e + +{{ substr "abcdef" -3 -1 }} → de +{{ substr "abcdef" -3 -2 }} → d +``` diff --git a/docs/content/en/functions/strings/Title.md b/docs/content/en/functions/strings/Title.md new file mode 100644 index 000000000..b7f1f9e5c --- /dev/null +++ b/docs/content/en/functions/strings/Title.md @@ -0,0 +1,32 @@ +--- +title: strings.Title +description: Returns the given string, converting it to title case. +categories: [] +keywords: [] +action: + aliases: [title] + related: + - functions/strings/FirstUpper + - functions/strings/ToLower + - functions/strings/ToUpper + returnType: string + signatures: [strings.Title STRING] +aliases: [/functions/title] +--- + +```go-html-template +{{ title "table of contents (TOC)" }} → Table of Contents (TOC) +``` + +By default, Hugo follows the capitalization rules published in the [Associated Press Stylebook]. Change your [site configuration] if you would prefer to: + +- Follow the capitalization rules published in the [Chicago Manual of Style] +- Capitalize the first letter of every word +- Capitalize the first letter of the first word +- Disable the effects of the `title` function + +The last option is useful if your theme uses the `title` function, and you would prefer to manually capitalize strings as needed. + +[Associated Press Stylebook]: https://www.apstylebook.com/ +[Chicago Manual of Style]: https://www.chicagomanualofstyle.org/home.html +[site configuration]: /getting-started/configuration/#configure-title-case diff --git a/docs/content/en/functions/strings/ToLower.md b/docs/content/en/functions/strings/ToLower.md new file mode 100644 index 000000000..3da047ae4 --- /dev/null +++ b/docs/content/en/functions/strings/ToLower.md @@ -0,0 +1,19 @@ +--- +title: strings.ToLower +description: Returns the given string, converting all characters to lowercase. +categories: [] +keywords: [] +action: + aliases: [lower] + related: + - functions/strings/FirstUpper + - functions/strings/Title + - functions/strings/ToUpper + returnType: string + signatures: [strings.ToLower INPUT] +aliases: [/functions/lower] +--- + +```go-html-template +{{ lower "BatMan" }} → batman +``` diff --git a/docs/content/en/functions/strings/ToUpper.md b/docs/content/en/functions/strings/ToUpper.md new file mode 100644 index 000000000..617e1e68a --- /dev/null +++ b/docs/content/en/functions/strings/ToUpper.md @@ -0,0 +1,19 @@ +--- +title: strings.ToUpper +description: Returns the given string, converting all characters to uppercase. +categories: [] +keywords: [] +action: + aliases: [upper] + related: + - functions/strings/FirstUpper + - functions/strings/Title + - functions/strings/ToLower + returnType: string + signatures: [strings.ToUpper INPUT] +aliases: [/functions/upper] +--- + +```go-html-template +{{ upper "BatMan" }} → BATMAN +``` diff --git a/docs/content/en/functions/strings/Trim.md b/docs/content/en/functions/strings/Trim.md new file mode 100644 index 000000000..6dfac024b --- /dev/null +++ b/docs/content/en/functions/strings/Trim.md @@ -0,0 +1,59 @@ +--- +title: strings.Trim +description: Returns the given string, removing leading and trailing characters specified in the cutset. +categories: [] +keywords: [] +action: + aliases: [trim] + related: + - functions/strings/Chomp + - functions/strings/TrimLeft + - functions/strings/TrimPrefix + - functions/strings/TrimRight + - functions/strings/TrimSuffix + returnType: string + signatures: [strings.Trim INPUT CUTSET] +aliases: [/functions/trim] +--- + +```go-html-template +{{ trim "++foo--" "+-" }} → foo +``` + +To remove leading and trailing newline characters and carriage returns: + +```go-html-template +{{ trim "\nfoo\n" "\n\r" }} → foo +{{ trim "\n\nfoo\n\n" "\n\r" }} → foo + +{{ trim "\r\nfoo\r\n" "\n\r" }} → foo +{{ trim "\r\n\r\nfoo\r\n\r\n" "\n\r" }} → foo +``` + +The `strings.Trim` function is commonly used in shortcodes to remove leading and trailing newlines characters and carriage returns from the content within the opening and closing shortcode tags. + +For example, with this markdown: + +```text +{{</* my-shortcode */>}} +Able was I ere I saw Elba. +{{</* /my-shortcode */>}} +``` + +The value of `.Inner` in the shortcode template is: + +```text +\nAble was I ere I saw Elba.\n +``` + +If authored on a Windows system the value of `.Inner` might, depending on the editor configuration, be: + +```text +\r\nAble was I ere I saw Elba.\r\n +``` + +This construct is common in shortcode templates: + +```go-html-template +{{ trim .Inner "\n\r" }} +``` diff --git a/docs/content/en/functions/strings/TrimLeft.md b/docs/content/en/functions/strings/TrimLeft.md new file mode 100644 index 000000000..07cdf0064 --- /dev/null +++ b/docs/content/en/functions/strings/TrimLeft.md @@ -0,0 +1,28 @@ +--- +title: strings.TrimLeft +description: Returns the given string, removing leading characters specified in the cutset. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/strings/Chomp + - functions/strings/Trim + - functions/strings/TrimPrefix + - functions/strings/TrimRight + - functions/strings/TrimSuffix + returnType: string + signatures: [strings.TrimLeft CUTSET STRING] +aliases: [/functions/strings.trimleft] +--- + +```go-html-template +{{ strings.TrimLeft "a" "abba" }} → bba +``` + +The `strings.TrimLeft` function converts the arguments to strings if possible: + +```go-html-template +{{ strings.TrimLeft 21 12345 }} → 345 (string) +{{ strings.TrimLeft "rt" true }} → ue +``` diff --git a/docs/content/en/functions/strings/TrimPrefix.md b/docs/content/en/functions/strings/TrimPrefix.md new file mode 100644 index 000000000..917cf06f5 --- /dev/null +++ b/docs/content/en/functions/strings/TrimPrefix.md @@ -0,0 +1,23 @@ +--- +title: strings.TrimPrefix +description: Returns the given string, removing the prefix from the beginning of the string. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/strings/Chomp + - functions/strings/Trim + - functions/strings/TrimLeft + - functions/strings/TrimRight + - functions/strings/TrimSuffix + returnType: string + signatures: [strings.TrimPrefix PREFIX STRING] +aliases: [/functions/strings.trimprefix] +--- + +```go-html-template +{{ strings.TrimPrefix "a" "aabbaa" }} → abbaa +{{ strings.TrimPrefix "aa" "aabbaa" }} → bbaa +{{ strings.TrimPrefix "aaa" "aabbaa" }} → aabbaa +``` diff --git a/docs/content/en/functions/strings/TrimRight.md b/docs/content/en/functions/strings/TrimRight.md new file mode 100644 index 000000000..b244925ef --- /dev/null +++ b/docs/content/en/functions/strings/TrimRight.md @@ -0,0 +1,28 @@ +--- +title: strings.TrimRight +description: Returns the given string, removing trailing characters specified in the cutset. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/strings/Chomp + - functions/strings/Trim + - functions/strings/TrimLeft + - functions/strings/TrimPrefix + - functions/strings/TrimSuffix + returnType: string + signatures: [strings.TrimRight CUTSET STRING] +aliases: [/functions/strings.trimright] +--- + +```go-html-template +{{ strings.TrimRight "a" "abba" }} → abb +``` + +The `strings.TrimRight` function converts the arguments to strings if possible: + +```go-html-template +{{ strings.TrimRight 54 12345 }} → 123 (string) +{{ strings.TrimRight "eu" true }} → tr +``` diff --git a/docs/content/en/functions/strings/TrimSuffix.md b/docs/content/en/functions/strings/TrimSuffix.md new file mode 100644 index 000000000..704bbd2d2 --- /dev/null +++ b/docs/content/en/functions/strings/TrimSuffix.md @@ -0,0 +1,23 @@ +--- +title: strings.TrimSuffix +description: Returns the given string, removing the suffix from the end of the string. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/strings/Chomp + - functions/strings/Trim + - functions/strings/TrimLeft + - functions/strings/TrimPrefix + - functions/strings/TrimRight + returnType: string + signatures: [strings.TrimSuffix SUFFIX STRING] +aliases: [/functions/strings.trimsuffix] +--- + +```go-html-template +{{ strings.TrimSuffix "a" "aabbaa" }} → aabba +{{ strings.TrimSuffix "aa" "aabbaa" }} → aabb +{{ strings.TrimSuffix "aaa" "aabbaa" }} → aabbaa +``` diff --git a/docs/content/en/functions/strings/Truncate.md b/docs/content/en/functions/strings/Truncate.md new file mode 100644 index 000000000..17ae0afc6 --- /dev/null +++ b/docs/content/en/functions/strings/Truncate.md @@ -0,0 +1,24 @@ +--- +title: strings.Truncate +description: Returns the given string, truncating it to a maximum length without cutting words or leaving unclosed HTML tags. +categories: [] +keywords: [] +action: + aliases: [truncate] + related: [] + returnType: template.HTML + signatures: ['strings.Truncate SIZE [ELLIPSIS] INPUT'] +aliases: [/functions/truncate] +--- + +Since Go templates are HTML-aware, `truncate` will intelligently handle normal strings vs HTML strings: + +```go-html-template +{{ "<em>Keep my HTML</em>" | safeHTML | truncate 10 }} → <em>Keep my …</em> +``` + +{{% note %}} +If you have a raw string that contains HTML tags you want to remain treated as HTML, you will need to convert the string to HTML using the [`safeHTML`]function before sending the value to `truncate`. Otherwise, the HTML tags will be escaped when passed through the `truncate` function. + +[`safeHTML`]: /functions/safe/html +{{% /note %}} diff --git a/docs/content/en/functions/strings/_index.md b/docs/content/en/functions/strings/_index.md new file mode 100644 index 000000000..364522a3a --- /dev/null +++ b/docs/content/en/functions/strings/_index.md @@ -0,0 +1,12 @@ +--- +title: String functions +linkTitle: strings +description: Template functions to work with strings. +categories: [] +keywords: [] +menu: + docs: + parent: functions +--- + +Use these functions to work with strings. diff --git a/docs/content/en/functions/templates/Exists.md b/docs/content/en/functions/templates/Exists.md new file mode 100644 index 000000000..e57610488 --- /dev/null +++ b/docs/content/en/functions/templates/Exists.md @@ -0,0 +1,27 @@ +--- +title: templates.Exists +description: Reports whether a template file exists under the given path relative to the layouts directory. +categories: [] +keywords: [] +action: + aliases: [] + related: [] + returnType: bool + signatures: [templates.Exists PATH] +aliases: [/functions/templates.exists] +--- + +A template file is any file within the `layouts` directory of either the project or any of its theme components. + +Use the `templates.Exists` function with dynamic template paths: + +```go-html-template +{{ $partialPath := printf "headers/%s.html" .Type }} +{{ if templates.Exists ( printf "partials/%s" $partialPath ) }} + {{ partial $partialPath . }} +{{ else }} + {{ partial "headers/default.html" . }} +{{ end }} +``` + +In the example above, if a "headers" partial does not exist for the given content type, Hugo falls back to a default template. diff --git a/docs/content/en/functions/templates/_index.md b/docs/content/en/functions/templates/_index.md new file mode 100644 index 000000000..89da6c38f --- /dev/null +++ b/docs/content/en/functions/templates/_index.md @@ -0,0 +1,13 @@ +--- +title: Template functions +linkTitle: templates +description: +categories: [] +keywords: [] +menu: + docs: + identifier: templates-functions + parent: functions +--- + +Use these functions to query the template system. diff --git a/docs/content/en/functions/time/AsTime.md b/docs/content/en/functions/time/AsTime.md new file mode 100644 index 000000000..23e5304a5 --- /dev/null +++ b/docs/content/en/functions/time/AsTime.md @@ -0,0 +1,61 @@ +--- +title: time.AsTime +description: Returns the given string representation of a date/time value as a time.Time value. +categories: [] +keywords: [] +action: + aliases: [time] + related: + - functions/time/Duration + - functions/time/Format + - functions/time/Now + - functions/time/ParseDuration + returnType: time.Time + signatures: ['time.AsTime INPUT [TIMEZONE]'] +aliases: [/functions/time] +toc: true +--- + +## Overview + +Hugo provides [functions] and [methods] to format, localize, parse, compare, and manipulate date/time values. Before you can do any of these with string representations of date/time values, you must first convert them to [`time.Time`] values using the `time.AsTime` function. + +```go-html-template +{{ $t := "2023-10-15T14:20:28-07:00" }} +{{ time.AsTime $t }} → 2023-10-15 14:20:28 -0700 PDT (time.Time) +``` + +## Parsable strings + +As shown above, the first argument must be a *parsable* string representation of a date/time value. For example: + +{{% include "functions/time/_common/parsable-date-time-strings.md" %}} + +## Time zones + +When the parsable string does not contain a time zone offset, you can do either of the following to assign a time zone other than Etc/UTC: + +- Provide a second argument to the `time.AsTime` function + + ```go-html-template + {{ time.AsTime "15 Oct 2023" "America/Chicago" }} + ``` + +- Set the default time zone in your site configuration + + {{< code-toggle file=hugo >}} + timeZone = 'America/New_York' + {{< /code-toggle >}} + +The order of precedence for determining the time zone is: + +1. The time zone offset in the date/time string +2. The time zone provide as the second argument to the `time.AsTime` function +3. The time zone specified in your site configuration + +The list of valid time zones may be system dependent, but should include `UTC`, `Local`, or any location in the [IANA Time Zone database]. + +[`time.Time`]: https://pkg.go.dev/time#Time +[functions]: /functions/time/ +[iana time zone database]: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones +[methods]: /methods/time/ diff --git a/docs/content/en/functions/time/Duration.md b/docs/content/en/functions/time/Duration.md new file mode 100644 index 000000000..f9c26d294 --- /dev/null +++ b/docs/content/en/functions/time/Duration.md @@ -0,0 +1,46 @@ +--- +title: time.Duration +description: Returns a time.Duration value using the given time unit and number. +categories: [] +keywords: [] +action: + aliases: [duration] + related: + - functions/time/AsTime + - functions/time/Format + - functions/time/Now + - functions/time/ParseDuration + returnType: time.Duration + signatures: [time.Duration TIME_UNIT NUMBER] +aliases: [/functions/duration] +--- + +The `time.Duration` function returns a [`time.Duration`] value that you can use with any of the `Duration` [methods]. + +This template: + +```go-html-template +{{ $duration := time.Duration "hour" 24 }} +{{ printf "There are %.0f seconds in one day." $duration.Seconds }} +``` + +Is rendered to: + +```text +There are 86400 seconds in one day. +``` + +The time unit must be one of the following: + + +Duration|Valid time units +:--|:-- +hours|`hour`, `h` +minutes|`minute`, `m` +seconds|`second`, `s` +milliseconds|`millisecond`, `ms` +microseconds|`microsecond`, `us`, `µs` +nanoseconds|`nanosecond`, `ns` + +[`time.Duration`]: https://pkg.go.dev/time#Duration +[methods]: /methods/duration diff --git a/docs/content/en/functions/time/Format.md b/docs/content/en/functions/time/Format.md new file mode 100644 index 000000000..74384959b --- /dev/null +++ b/docs/content/en/functions/time/Format.md @@ -0,0 +1,77 @@ +--- +title: time.Format +description: Returns the given date/time as a formatted and localized string. +categories: [] +keywords: [] +action: + aliases: [dateFormat] + related: + - functions/time/AsTime + - functions/time/Duration + - functions/time/Now + - functions/time/ParseDuration + returnType: string + signatures: [time.Format LAYOUT INPUT] +aliases: [/functions/dateformat] +toc: true +--- + +Use the `time.Format` function with `time.Time` values: + +```go-html-template +{{ $t := time.AsTime "2023-02-27T23:44:58-08:00" }} +{{ time.Format "2 Jan 2006" $t }} → 27 Feb 2023 +``` + +Or use `time.Format` with a *parsable* string representation of a date/time value: + +```go-html-template +{{ $t := "27 Feb 2023" }} +{{ time.Format "January 2, 2006" $t }} → February 27, 2023 +``` + +Examples of parsable string representations: + +{{% include "functions/time/_common/parsable-date-time-strings.md" %}} + +## Layout string + +{{% include "functions/_common/time-layout-string.md" %}} + +## Localization + +Use the `time.Format` function to localize `time.Time` values for the current language and region. + +{{% include "functions/_common/locales.md" %}} + +Use the layout string as described above, or one of the tokens below. For example: + +```go-html-template +{{ .Date | time.Format ":date_medium" }} → Jan 27, 2023 +``` + +Localized to en-US: + +Token|Result +:--|:-- +`:date_full`|`Friday, January 27, 2023` +`:date_long`|`January 27, 2023` +`:date_medium`|`Jan 27, 2023` +`:date_short`|`1/27/23` +`:time_full`|`11:44:58 pm Pacific Standard Time` +`:time_long`|`11:44:58 pm PST` +`:time_medium`|`11:44:58 pm` +`:time_short`|`11:44 pm` + +Localized to de-DE: + +Token|Result +:--|:-- +`:date_full`|`Freitag, 27. Januar 2023` +`:date_long`|`27. Januar 2023` +`:date_medium`|`27.01.2023` +`:date_short`|`27.01.23` +`:time_full`|`23:44:58 Nordamerikanische Westküsten-Normalzeit` +`:time_long`|`23:44:58 PST` +`:time_medium`|`23:44:58` +`:time_short`|`23:44` diff --git a/docs/content/en/functions/time/Now.md b/docs/content/en/functions/time/Now.md new file mode 100644 index 000000000..60e45a91c --- /dev/null +++ b/docs/content/en/functions/time/Now.md @@ -0,0 +1,48 @@ +--- +title: time.Now +description: Returns the current local time. +categories: [] +keywords: [] +action: + aliases: [now] + related: + - functions/time/AsTime + - functions/time/Duration + - functions/time/Format + - functions/time/ParseDuration + returnType: time.Time + signatures: [time.Now] +aliases: [/functions/now] +--- + +For example, when building a site on October 15, 2023 in the America/Los_Angeles time zone: + +```go-html-template +{{ time.Now }} +``` + +This produces a `time.Time` value, with a string representation such as: + +```text +2023-10-15 12:59:28.337140706 -0700 PDT m=+0.041752605 +``` + +To format and [localize] the value, pass it through the [`time.Format`] function: + +```go-html-template +{{ time.Now | time.Format "Jan 2006" }} → Oct 2023 +``` + +The `time.Now` function returns a `time.Time` value, so you can chain any of the [time methods] to the resulting value. For example: + + +```go-html-template +{{ time.Now.Year }} → 2023 (int) +{{ time.Now.Weekday.String }} → Sunday +{{ time.Now.Month.String }} → October +{{ time.Now.Unix }} → 1697400955 (int64) +``` + +[`time.Format`]: /functions/time/format +[localize]: /getting-started/glossary/#localization +[time methods]: /methods/time/ diff --git a/docs/content/en/functions/time/ParseDuration.md b/docs/content/en/functions/time/ParseDuration.md new file mode 100644 index 000000000..091914132 --- /dev/null +++ b/docs/content/en/functions/time/ParseDuration.md @@ -0,0 +1,37 @@ +--- +title: time.ParseDuration +description: Returns a time.Duration value by parsing the given duration string. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/time/AsTime + - functions/time/Duration + - functions/time/Format + - functions/time/Now + returnType: time.Duration + signatures: [time.ParseDuration DURATION] +aliases: [/functions/time.parseduration] +--- + +The `time.ParseDuration` function returns a time.Duration value that you can use with any of the `Duration` [methods]. + + +A duration string is a possibly signed sequence of decimal numbers, each with optional fraction and a unit suffix, such as `300ms`, `-1.5h` or `2h45m`. Valid time units are `ns`, `us` (or `µs`), `ms`, `s`, `m`, `h`. + +This template: + +```go-html-template +{{ $duration := time.ParseDuration "24h" }} +{{ printf "There are %.0f seconds in one day." $duration.Seconds }} +``` + +Is rendered to: + +```text +There are 86400 seconds in one day. +``` + +[`time.Duration`]: https://pkg.go.dev/time#Duration +[methods]: /methods/duration diff --git a/docs/content/en/functions/time/_common/_index.md b/docs/content/en/functions/time/_common/_index.md new file mode 100644 index 000000000..47d5812fb --- /dev/null +++ b/docs/content/en/functions/time/_common/_index.md @@ -0,0 +1,13 @@ +--- +cascade: + _build: + list: never + publishResources: false + render: never +--- + +<!-- +Files within this headless branch bundle are markdown snippets. Each file must contain front matter delimiters, though front matter fields are not required. + +Include the rendered content using the "include" shortcode. +--> diff --git a/docs/content/en/functions/time/_common/parsable-date-time-strings.md b/docs/content/en/functions/time/_common/parsable-date-time-strings.md new file mode 100644 index 000000000..a38b9983e --- /dev/null +++ b/docs/content/en/functions/time/_common/parsable-date-time-strings.md @@ -0,0 +1,14 @@ +--- +# Do not remove front matter. +--- + +String representation|Time zone +:--|:-- +2023-10-15T14:20:28-07:00|America/Los_Angeles +2023-10-15T13:18:50-0700|America/Los_Angeles +2023-10-15T13:18:50Z|Etc/UTC +2023-10-15T13:18:50|Etc/UTC +2023-10-15|Etc/UTC +15 Oct 2023|Etc/UTC + +The last four examples are not fully qualified. Without a time zone offset, the time zone is set to Etc/UTC (Coordinated Universal Time). diff --git a/docs/content/en/functions/time/_index.md b/docs/content/en/functions/time/_index.md new file mode 100644 index 000000000..7e0b82f91 --- /dev/null +++ b/docs/content/en/functions/time/_index.md @@ -0,0 +1,12 @@ +--- +title: Time functions +linkTitle: time +description: Template functions to work with time values. +categories: [] +keywords: [] +menu: + docs: + parent: functions +--- + +Use these functions to work with time values. diff --git a/docs/content/en/functions/transform/CanHighlight.md b/docs/content/en/functions/transform/CanHighlight.md new file mode 100644 index 000000000..039cb12b7 --- /dev/null +++ b/docs/content/en/functions/transform/CanHighlight.md @@ -0,0 +1,18 @@ +--- +title: transform.CanHighlight +description: Reports whether the given code language is supported by the Chroma highlighter. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/transform/Highlight + - functions/transform/HighlightCodeBlock + returnType: bool + signatures: [transform.CanHighlight LANGUAGE] +--- + +```go-html-template +{{ transform.CanHighlight "go" }} → true +{{ transform.CanHighlight "klingon" }} → false +``` diff --git a/docs/content/en/functions/transform/Emojify.md b/docs/content/en/functions/transform/Emojify.md new file mode 100644 index 000000000..d9f0adf67 --- /dev/null +++ b/docs/content/en/functions/transform/Emojify.md @@ -0,0 +1,30 @@ +--- +title: transform.Emojify +description: Runs a string through the Emoji emoticons processor. +categories: [] +keywords: [] +action: + aliases: [emojify] + related: [] + returnType: template.HTML + signatures: [transform.Emojify INPUT] +aliases: [/functions/emojify] +--- + +`emojify` runs a passed string through the Emoji emoticons processor. + +See the list of [emoji shortcodes] for available emoticons. + +The `emojify` function can be called in your templates but not directly in your content files by default. For emojis in content files, set `enableEmoji` to `true` in your site's [configuration]. Then you can write emoji shorthand directly into your content files; + + +```text +I :heart: Hugo! +``` + +I :heart: Hugo! + +[configuration]: /getting-started/configuration/ +[emoji shortcodes]: /quick-reference/emojis/ +[sc]: /templates/shortcode-templates/ +[scsource]: https://github.com/gohugoio/hugo/tree/master/docs/layouts/shortcodes diff --git a/docs/content/en/functions/transform/HTMLEscape.md b/docs/content/en/functions/transform/HTMLEscape.md new file mode 100644 index 000000000..bb522769c --- /dev/null +++ b/docs/content/en/functions/transform/HTMLEscape.md @@ -0,0 +1,30 @@ +--- +title: transform.HTMLEscape +description: Returns the given string, escaping special characters by replacing them with HTML entities. +categories: [] +keywords: [] +action: + aliases: [htmlEscape] + related: + - functions/transform/HTMLUnescape + returnType: string + signatures: [transform.HTMLEscape INPUT] +aliases: [/functions/htmlescape] +--- + +The `transform.HTMLEscape` function escapes five special characters by replacing them with [HTML entities]: + +- `&` → `&` +- `<` → `<` +- `>` → `>` +- `'` → `'` +- `"` → `"` + +For example: + +```go-html-template +{{ htmlEscape "Lilo & Stitch" }} → Lilo & Stitch +{{ htmlEscape "7 > 6" }} → 7 > 6 +``` + +[html entities]: https://developer.mozilla.org/en-US/docs/Glossary/Entity diff --git a/docs/content/en/functions/transform/HTMLUnescape.md b/docs/content/en/functions/transform/HTMLUnescape.md new file mode 100644 index 000000000..180318077 --- /dev/null +++ b/docs/content/en/functions/transform/HTMLUnescape.md @@ -0,0 +1,30 @@ +--- +title: transform.HTMLUnescape +description: Returns the given string, replacing each HTML entity with its corresponding character. +categories: [] +keywords: [] +action: + aliases: [htmlUnescape] + related: + - functions/transform/HTMLEscape + returnType: string + signatures: [transform.HTMLUnescape INPUT] +aliases: [/functions/htmlunescape] +--- + +The `transform.HTMLUnescape` function replaces [HTML entities] with their corresponding characters. + +```go-html-template +{{ htmlUnescape "Lilo & Stitch" }} → Lilo & Stitch +{{ htmlUnescape "7 > 6" }} → 7 > 6 +``` + +In most contexts Go's [html/template] package will escape special characters. To bypass this behavior, pass the unescaped string through the [`safeHTML`] function. + +```go-html-template +{{ htmlUnescape "Lilo & Stitch" | safeHTML }} +``` + +[`safehtml`]: /functions/safe/html +[html entities]: https://developer.mozilla.org/en-us/docs/glossary/entity +[html/template]: https://pkg.go.dev/html/template diff --git a/docs/content/en/functions/transform/Highlight.md b/docs/content/en/functions/transform/Highlight.md new file mode 100644 index 000000000..29d0efdef --- /dev/null +++ b/docs/content/en/functions/transform/Highlight.md @@ -0,0 +1,107 @@ +--- +title: transform.Highlight +description: Renders code with a syntax highlighter. +categories: [] +keywords: [] +action: + aliases: [highlight] + related: + - functions/transform/CanHighlight + - functions/transform/HighlightCodeBlock + returnType: template.HTML + signatures: ['transform.Highlight INPUT LANG [OPTIONS]'] +aliases: [/functions/highlight] +toc: true +--- + +The `highlight` function uses the [Chroma] syntax highlighter, supporting over 200 languages with more than 40 available styles. + +## Arguments + +INPUT +: The code to highlight. + +LANG +: The language of the code to highlight. Choose from one of the [supported languages]. Case-insensitive. + +OPTIONS +: A map, or comma-separated list, of zero or more [options]. Set default values in [site configuration]. + +## Options + +lineNos +: Boolean. Default is `false`.\ +Display a number at the beginning of each line. + +lineNumbersInTable +: Boolean. Default is `true`.\ +Render the highlighted code in an HTML table with two cells. The left table cell contains the line numbers. The right table cell contains the code, allowing a user to select and copy the code without line numbers. Irrelevant if `lineNos` is `false`. + +anchorLineNos +: Boolean. Default is `false`.\ +Render each line number as an HTML anchor element, and set the `id` attribute of the surrounding `<span>` to the line number. Irrelevant if `lineNos` is `false`. + +lineAnchors +: String. Default is `""`.\ +When rendering a line number as an HTML anchor element, prepend this value to the `id` attribute of the surrounding `<span>`. This provides unique `id` attributes when a page contains two or more code blocks. Irrelevant if `lineNos` or `anchorLineNos` is `false`. + +lineNoStart +: Integer. Default is `1`.\ +The number to display at the beginning of the first line. Irrelevant if `lineNos` is `false`. + +hl_Lines +: String. Default is `""`.\ +A space-delimited list of lines to emphasize within the highlighted code. To emphasize lines 2, 3, 4, and 7, set this value to `2-4 7`. This option is independent of the `lineNoStart` option. + +hl_inline +: Boolean. Default is `false`.\ +Render the highlighted code without a wrapping container. + +style +: String. Default is `monokai`.\ +The CSS styles to apply to the highlighted code. See the [style gallery] for examples. Case-sensitive. + +noClasses +: Boolean. Default is `true`.\ +Use inline CSS styles instead of an external CSS file. To use an external CSS file, set this value to `false` and [generate the file with the hugo client][hugo client]. + +tabWidth +: Integer. Default is `4`.\ +Substitute this number of spaces for each tab character in your highlighted code. Irrelevant if `noClasses` is `false`. + +guessSyntax +: Boolean. Default is `false`.\ +If the `LANG` argument is blank or an unrecognized language, auto-detect the language if possible, otherwise use a fallback language. + +{{% note %}} +Instead of specifying both `lineNos` and `lineNumbersInTable`, you can use the following shorthand notation: + +lineNos=inline +: equivalent to `lineNos=true` and `lineNumbersInTable=false` + +lineNos=table +: equivalent to `lineNos=true` and `lineNumbersInTable=true` +{{% /note %}} + +## Examples + +```go-html-template +{{ $input := `fmt.Println("Hello World!")` }} +{{ transform.Highlight $input "go" }} + +{{ $input := `console.log('Hello World!');` }} +{{ $lang := "js" }} +{{ transform.Highlight $input $lang "lineNos=table, style=api" }} + +{{ $input := `echo "Hello World!"` }} +{{ $lang := "bash" }} +{{ $opts := dict "lineNos" "table" "style" "dracula" }} +{{ transform.Highlight $input $lang $opts }} +``` + +[Chroma]: https://github.com/alecthomas/chroma +[hugo client]: /commands/hugo_gen_chromastyles +[options]: #options +[site configuration]: /getting-started/configuration-markup#highlight +[style gallery]: https://xyproto.github.io/splash/docs/ +[supported languages]: /content-management/syntax-highlighting#list-of-chroma-highlighting-languages diff --git a/docs/content/en/functions/transform/HighlightCodeBlock.md b/docs/content/en/functions/transform/HighlightCodeBlock.md new file mode 100644 index 000000000..dc396bad0 --- /dev/null +++ b/docs/content/en/functions/transform/HighlightCodeBlock.md @@ -0,0 +1,38 @@ +--- +title: transform.HighlightCodeBlock +description: Highlights code received in context within a code block render hook. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/transform/CanHighlight + - functions/transform/Highlight + returnType: highlight.HighlightResult + signatures: ['transform.HighlightCodeBlock CONTEXT [OPTIONS]'] +--- + +This function is only useful within a code block render hook. + +Given the context passed into a code block render hook, `transform.HighlightCodeBlock` returns a `HighlightResult` object with two methods. + +.Wrapped +: (`template.HTML`) Returns highlighted code wrapped in `<div>`, `<pre>`, and `<code>` elements. This is identical to the value returned by the transform.Highlight function. + +.Inner +: (`template.HTML`) Returns highlighted code without any wrapping elements, allowing you to create your own wrapper. + +```go-html-template +{{ $result := transform.HighlightCodeBlock . }} +{{ $result.Wrapped }} +``` + +To override the default [highlighting options]: + +```go-html-template +{{ $opts := merge .Options (dict "linenos" true) }} +{{ $result := transform.HighlightCodeBlock . $opts }} +{{ $result.Wrapped }} +``` + +[highlighting options]: /functions/transform/highlight/#options diff --git a/docs/content/en/functions/transform/Markdownify.md b/docs/content/en/functions/transform/Markdownify.md new file mode 100644 index 000000000..8fb1e48ce --- /dev/null +++ b/docs/content/en/functions/transform/Markdownify.md @@ -0,0 +1,31 @@ +--- +title: transform.Markdownify +description: Renders markdown to HTML. +categories: [] +keywords: [] +action: + aliases: [markdownify] + related: + - methods/page/RenderString + - methods/page/RenderShortcodes + returnType: template.HTML + signatures: [transform.Markdownify INPUT] +aliases: [/functions/markdownify] +--- + +```go-html-template +<h2>{{ .Title | markdownify }}</h2> +``` + +If the resulting HTML is a single paragraph, Hugo removes the wrapping `p` tags to produce inline HTML as required per the example above. + +To keep the wrapping `p` tags for a single paragraph, use the [`RenderString`] method on the `Page` object, setting the `display` option to `block`. + +[`RenderString`]: /methods/page/renderstring/ + +{{% note %}} +Although the `markdownify` function honors [markdown render hooks] when rendering markdown to HTML, use the `RenderString` method instead of `markdownify` if a render hook accesses `.Page` context. See issue [#9692] for details. + +[markdown render hooks]: /templates/render-hooks/ +[#9692]: https://github.com/gohugoio/hugo/issues/9692 +{{% /note %}} diff --git a/docs/content/en/functions/transform/Plainify.md b/docs/content/en/functions/transform/Plainify.md new file mode 100644 index 000000000..040145170 --- /dev/null +++ b/docs/content/en/functions/transform/Plainify.md @@ -0,0 +1,16 @@ +--- +title: transform.Plainify +description: Returns a string with all HTML tags removed. +categories: [] +keywords: [] +action: + aliases: [plainify] + related: [] + returnType: string + signatures: [transform.Plainify INPUT] +aliases: [/functions/plainify] +--- + +```go-html-template +{{ "<b>BatMan</b>" | plainify }} → BatMan +``` diff --git a/docs/content/en/functions/transform/Remarshal.md b/docs/content/en/functions/transform/Remarshal.md new file mode 100644 index 000000000..24ef4381d --- /dev/null +++ b/docs/content/en/functions/transform/Remarshal.md @@ -0,0 +1,92 @@ +--- +title: transform.Remarshal +description: Marshals a string of serialized data, or a map, into a string of serialized data in the specified format. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/encoding/Jsonify + - functions/transform/Unmarshal + returnType: string + signatures: [transform.Remarshal FORMAT INPUT] +aliases: [/functions/transform.remarshal] +--- + +The format must be one of `json`, `toml`, `yaml`, or `xml`. If the input is a string of serialized data, it must be valid JSON, TOML, YAML, or XML. + +{{% note %}} +This function is primarily a helper for Hugo's documentation, used to convert configuration and front matter examples to JSON, TOML, and YAML. + +This is not a general purpose converter, and may change without notice if required for Hugo's documentation site. +{{% /note %}} + +Example 1 +: Convert a string of TOML to JSON. + +```go-html-template +{{ $s := ` + baseURL = 'https://example.org/' + languageCode = 'en-US' + title = 'ABC Widgets' +`}} +<pre>{{ transform.Remarshal "json" $s }}</pre> +``` + +Resulting HTML: + +```html +<pre>{ + "baseURL": "https://example.org/", + "languageCode": "en-US", + "title": "ABC Widgets" +} +</pre> +``` + +Rendered in browser: + +```text +{ + "baseURL": "https://example.org/", + "languageCode": "en-US", + "title": "ABC Widgets" +} +``` + +Example 2 +: Convert a map to YAML. + +```go-html-template +{{ $m := dict + "a" "Hugo rocks!" + "b" (dict "question" "What is 6x7?" "answer" 42) + "c" (slice "foo" "bar") +}} +<pre>{{ transform.Remarshal "yaml" $m }}</pre> +``` + +Resulting HTML: + +```html +<pre>a: Hugo rocks! +b: + answer: 42 + question: What is 6x7? +c: +- foo +- bar +</pre> +``` + +Rendered in browser: + +```text +a: Hugo rocks! +b: + answer: 42 + question: What is 6x7? +c: +- foo +- bar +``` diff --git a/docs/content/en/functions/transform/Unmarshal.md b/docs/content/en/functions/transform/Unmarshal.md new file mode 100644 index 000000000..bc2b663e3 --- /dev/null +++ b/docs/content/en/functions/transform/Unmarshal.md @@ -0,0 +1,292 @@ +--- +title: transform.Unmarshal +description: Parses serialized data and returns a map or an array. Supports CSV, JSON, TOML, YAML, and XML. +categories: [] +keywords: [] +action: + aliases: [unmarshal] + related: + - functions/transform/Remarshal + - functions/resources/Get + - functions/resources/GetRemote + - functions/encoding/Jsonify + returnType: any + signatures: ['transform.Unmarshal [OPTIONS] INPUT'] +toc: true +aliases: [/functions/transform.unmarshal] +--- + +The input can be a string or a [resource]. + +## Unmarshal a string + +```go-html-template +{{ $string := ` +title: Les Misérables +author: Victor Hugo +`}} + +{{ $book := unmarshal $string }} +{{ $book.title }} → Les Misérables +{{ $book.author }} → Victor Hugo +``` + +## Unmarshal a resource + +Use the `transform.Unmarshal` function with global, page, and remote resources. + +### Global resource + +A global resource is a file within the assets directory, or within any directory mounted to the assets directory. + +```text +assets/ +└── data/ + └── books.json +``` + +```go-html-template +{{ $data := "" }} +{{ $path := "data/books.json" }} +{{ with resources.Get $path }} + {{ with unmarshal . }} + {{ $data = . }} + {{ end }} +{{ else }} + {{ errorf "Unable to get global resource %q" $path }} +{{ end }} + +{{ range where $data "author" "Victor Hugo" }} + {{ .title }} → Les Misérables +{{ end }} +``` + +### Page resource + +A page resource is a file within a [page bundle]. + +```text +content/ +├── post/ +│ └── book-reviews/ +│ ├── books.json +│ └── index.md +└── _index.md +``` + +```go-html-template +{{ $data := "" }} +{{ $path := "books.json" }} +{{ with .Resources.Get $path }} + {{ with unmarshal . }} + {{ $data = . }} + {{ end }} +{{ else }} + {{ errorf "Unable to get page resource %q" $path }} +{{ end }} + +{{ range where $data "author" "Victor Hugo" }} + {{ .title }} → Les Misérables +{{ end }} +``` + +### Remote resource + +A remote resource is a file on a remote server, accessible via HTTP or HTTPS. + +```go-html-template +{{ $data := "" }} +{{ $url := "https://example.org/books.json" }} +{{ with resources.GetRemote $url }} + {{ with .Err }} + {{ errorf "%s" . }} + {{ else }} + {{ $data = . | transform.Unmarshal }} + {{ end }} +{{ else }} + {{ errorf "Unable to get remote resource %q" $url }} +{{ end }} + +{{ range where $data "author" "Victor Hugo" }} + {{ .title }} → Les Misérables +{{ end }} +``` + +[resource]: /getting-started/glossary/#resource +[page bundle]: /content-management/page-bundles + +## Options + +When unmarshaling a CSV file, provide an optional map of options. + +delimiter +: (`string`) The delimiter used, default is `,`. + +comment +: (`string`) The comment character used in the CSV. If set, lines beginning with the comment character without preceding whitespace are ignored. + +lazyQuotes {{< new-in 0.122.0 >}} +: (`bool`) If true, a quote may appear in an unquoted field and a non-doubled quote may appear in a quoted field. Default is `false`. + +```go-html-template +{{ $csv := "a;b;c" | transform.Unmarshal (dict "delimiter" ";") }} +``` + +## Working with XML + +When unmarshaling an XML file, do not include the root node when accessing data. For example, after unmarshaling the RSS feed below, access the feed title with `$data.channel.title`. + +```xml +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"> + <channel> + <title>Books on Example Site</title> + <link>https://example.org/books/</link> + <description>Recent content in Books on Example Site</description> + <language>en-US</language> + <atom:link href="https://example.org/books/index.xml" rel="self" type="application/rss+xml" /> + <item> + <title>The Hunchback of Notre Dame</title> + <description>Written by Victor Hugo</description> + <link>https://example.org/books/the-hunchback-of-notre-dame/</link> + <pubDate>Mon, 09 Oct 2023 09:27:12 -0700</pubDate> + <guid>https://example.org/books/the-hunchback-of-notre-dame/</guid> + </item> + <item> + <title>Les Misérables</title> + <description>Written by Victor Hugo</description> + <link>https://example.org/books/les-miserables/</link> + <pubDate>Mon, 09 Oct 2023 09:27:11 -0700</pubDate> + <guid>https://example.org/books/les-miserables/</guid> + </item> + </channel> +</rss> +``` + +Get the remote data: + +```go-html-template +{{ $data := "" }} +{{ $url := "https://example.org/books/index.xml" }} +{{ with resources.GetRemote $url }} + {{ with .Err }} + {{ errorf "%s" . }} + {{ else }} + {{ $data = . | transform.Unmarshal }} + {{ end }} +{{ else }} + {{ errorf "Unable to get remote resource %q" $url }} +{{ end }} +``` + +Inspect the data structure: + +```go-html-template +<pre>{{ jsonify (dict "indent" " ") $data }}</pre> +``` + +List the book titles: + +```go-html-template +{{ with $data.channel.item }} + <ul> + {{ range . }} + <li>{{ .title }}</li> + {{ end }} + </ul> +{{ end }} +``` + +Hugo renders this to: + +```html +<ul> + <li>The Hunchback of Notre Dame</li> + <li>Les Misérables</li> +</ul> +``` + +### XML attributes and namespaces + +Let's add a `lang` attribute to the `title` nodes of our RSS feed, and a namespaced node for the ISBN number: + +```xml +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<rss version="2.0" + xmlns:atom="http://www.w3.org/2005/Atom" + xmlns:isbn="http://schemas.isbn.org/ns/1999/basic.dtd" +> + <channel> + <title>Books on Example Site</title> + <link>https://example.org/books/</link> + <description>Recent content in Books on Example Site</description> + <language>en-US</language> + <atom:link href="https://example.org/books/index.xml" rel="self" type="application/rss+xml" /> + <item> + <title lang="fr">The Hunchback of Notre Dame</title> + <description>Written by Victor Hugo</description> + <isbn:number>9780140443530</isbn:number> + <link>https://example.org/books/the-hunchback-of-notre-dame/</link> + <pubDate>Mon, 09 Oct 2023 09:27:12 -0700</pubDate> + <guid>https://example.org/books/the-hunchback-of-notre-dame/</guid> + </item> + <item> + <title lang="en">Les Misérables</title> + <description>Written by Victor Hugo</description> + <isbn:number>9780451419439</isbn:number> + <link>https://example.org/books/les-miserables/</link> + <pubDate>Mon, 09 Oct 2023 09:27:11 -0700</pubDate> + <guid>https://example.org/books/les-miserables/</guid> + </item> + </channel> +</rss> +``` + +After retrieving the remote data, inspect the data structure: + +```go-html-template +<pre>{{ jsonify (dict "indent" " ") $data }}</pre> +``` + +Each item node looks like this: + +```json +{ + "description": "Written by Victor Hugo", + "guid": "https://example.org/books/the-hunchback-of-notre-dame/", + "link": "https://example.org/books/the-hunchback-of-notre-dame/", + "number": "9780140443530", + "pubDate": "Mon, 09 Oct 2023 09:27:12 -0700", + "title": { + "#text": "The Hunchback of Notre Dame", + "-lang": "fr" + } +} +``` + +The title keys do not begin with an underscore or a letter---they are not valid [identifiers]. Use the [`index`] function to access the values: + +```go-html-template +{{ with $data.channel.item }} + <ul> + {{ range . }} + {{ $title := index .title "#text" }} + {{ $lang := index .title "-lang" }} + {{ $ISBN := .number }} + <li>{{ $title }} ({{ $lang }}) {{ $ISBN }}</li> + {{ end }} + </ul> +{{ end }} +``` + +Hugo renders this to: + +```html +<ul> + <li>The Hunchback of Notre Dame (fr) 9780140443530</li> + <li>Les Misérables (en) 9780451419439</li> +</ul> +``` + +[`index`]: /functions/collections/indexfunction +[identifiers]: https://go.dev/ref/spec#Identifiers diff --git a/docs/content/en/functions/transform/XMLEscape.md b/docs/content/en/functions/transform/XMLEscape.md new file mode 100644 index 000000000..d0aafc4bd --- /dev/null +++ b/docs/content/en/functions/transform/XMLEscape.md @@ -0,0 +1,40 @@ +--- +title: transform.XMLEscape +description: Returns the given string, removing disallowed characters then escaping the result to its XML equivalent. +categories: [] +keywords: [] +action: + aliases: [] + related: [] + returnType: string + signatures: [transform.XMLEscape INPUT] +--- + +{{< new-in 0.121.0 >}} + +The `transform.XMLEscape` function removes [disallowed characters] as defined in the XML specification, then escapes the result by replacing the following characters with [HTML entities]: + +- `"` → `"` +- `'` → `'` +- `&` → `&` +- `<` → `<` +- `>` → `>` +- `\t` → `	` +- `\n` → `
` +- `\r` → `
` + +For example: + +```go-html-template +{{ transform.XMLEscape "<p>abc</p>" }} → <p>abc</p> +``` + +When using `transform.XMLEscape` in a template rendered by Go's [html/template] package, declare the string to be safe HTML to avoid double escaping. For example, in an RSS template: + +{{< code file="layouts/_default/rss.xml" >}} +<description>{{ .Summary | transform.XMLEscape | safeHTML }}</description> +{{< /code >}} + +[disallowed characters]: https://www.w3.org/TR/xml/#charsets +[html entities]: https://developer.mozilla.org/en-us/docs/glossary/entity +[html/template]: https://pkg.go.dev/html/template diff --git a/docs/content/en/functions/transform/_index.md b/docs/content/en/functions/transform/_index.md new file mode 100644 index 000000000..70e286b24 --- /dev/null +++ b/docs/content/en/functions/transform/_index.md @@ -0,0 +1,12 @@ +--- +title: Transform functions +linkTitle: transform +description: Template functions to transform values from one format to another. +categories: [] +keywords: [] +menu: + docs: + parent: functions +--- + +Use these functions to transform values from one format to another. diff --git a/docs/content/en/functions/urls/AbsLangURL.md b/docs/content/en/functions/urls/AbsLangURL.md new file mode 100644 index 000000000..876552bb7 --- /dev/null +++ b/docs/content/en/functions/urls/AbsLangURL.md @@ -0,0 +1,67 @@ +--- +title: urls.AbsLangURL +description: Returns an absolute URL with a language prefix, if any. +categories: [] +keywords: [] +action: + aliases: [absLangURL] + related: + - functions/urls/AbsURL + - functions/urls/RelLangURL + - functions/urls/RelURL + returnType: string + signatures: [urls.AbsLangURL INPUT] +aliases: [/functions/abslangurl] +--- + +Use this function with both monolingual and multilingual configurations. The URL returned by this function depends on: + +- Whether the input begins with a slash +- The `baseURL` in site configuration +- The language prefix, if any + +In examples that follow, the project is multilingual with content in both Español (`es`) and English (`en`). The default language is Español. The returned values are from the English site. + +### Input does not begin with a slash + +If the input does not begin with a slash, the resulting URL will be correct regardless of the `baseURL`. + +With `baseURL = https://example.org/` + +```go-html-template +{{ absLangURL "" }} → https://example.org/en/ +{{ absLangURL "articles" }} → https://example.org/en/articles +{{ absLangURL "style.css" }} → https://example.org/en/style.css +``` + +With `baseURL = https://example.org/docs/` + +```go-html-template +{{ absLangURL "" }} → https://example.org/docs/en/ +{{ absLangURL "articles" }} → https://example.org/docs/en/articles +{{ absLangURL "style.css" }} → https://example.org/docs/en/style.css +``` + +### Input begins with a slash + +If the input begins with a slash, the resulting URL will be incorrect when the `baseURL` includes a subdirectory. With a leading slash, the function returns a URL relative to the protocol+host section of the `baseURL`. + +With `baseURL = https://example.org/` + +```go-html-template +{{ absLangURL "/" }} → https://example.org/en/ +{{ absLangURL "/articles" }} → https://example.org/en/articles +{{ absLangURL "/style.css" }} → https://example.org/en/style.css +``` + +With `baseURL = https://example.org/docs/` + +```go-html-template +{{ absLangURL "/" }} → https://example.org/en/ +{{ absLangURL "/articles" }} → https://example.org/en/articles +{{ absLangURL "/style.css" }} → https://example.org/en/style.css +``` + +{{% note %}} +The last three examples are not desirable in most situations. As a best practice, never include a leading slash when using this function. +{{% /note %}} diff --git a/docs/content/en/functions/urls/AbsURL.md b/docs/content/en/functions/urls/AbsURL.md new file mode 100644 index 000000000..5b027ae84 --- /dev/null +++ b/docs/content/en/functions/urls/AbsURL.md @@ -0,0 +1,66 @@ +--- +title: urls.AbsURL +description: Returns an absolute URL. +categories: [] +keywords: [] +action: + aliases: [absURL] + related: + - functions/urls/AbsLangURL + - functions/urls/RelLangURL + - functions/urls/RelURL + returnType: string + signatures: [urls.AbsURL INPUT] +aliases: [/functions/absurl] +--- + +With multilingual configurations, use the [`absLangURL`] function instead. The URL returned by this function depends on: + +- Whether the input begins with a slash +- The `baseURL` in site configuration + +### Input does not begin with a slash + +If the input does not begin with a slash, the resulting URL will be correct regardless of the `baseURL`. + +With `baseURL = https://example.org/` + +```go-html-template +{{ absURL "" }} → https://example.org/ +{{ absURL "articles" }} → https://example.org/articles +{{ absURL "style.css" }} → https://example.org/style.css +``` + +With `baseURL = https://example.org/docs/` + +```go-html-template +{{ absURL "" }} → https://example.org/docs/ +{{ absURL "articles" }} → https://example.org/docs/articles +{{ absURL "style.css" }} → https://example.org/docs/style.css +``` + +#### Input begins with a slash + +If the input begins with a slash, the resulting URL will be incorrect when the `baseURL` includes a subdirectory. With a leading slash, the function returns a URL relative to the protocol+host section of the `baseURL`. + +With `baseURL = https://example.org/` + +```go-html-template +{{ absURL "/" }} → https://example.org/ +{{ absURL "/articles" }} → https://example.org/articles +{{ absURL "/style.css" }} → https://example.org/style.css +``` + +With `baseURL = https://example.org/docs/` + +```go-html-template +{{ absURL "/" }} → https://example.org/ +{{ absURL "/articles" }} → https://example.org/articles +{{ absURL "/style.css" }} → https://example.org/style.css +``` + +{{% note %}} +The last three examples are not desirable in most situations. As a best practice, never include a leading slash when using this function. +{{% /note %}} + +[`absLangURL`]: /functions/urls/abslangurl/ diff --git a/docs/content/en/functions/urls/Anchorize.md b/docs/content/en/functions/urls/Anchorize.md new file mode 100644 index 000000000..72b3d54a9 --- /dev/null +++ b/docs/content/en/functions/urls/Anchorize.md @@ -0,0 +1,37 @@ +--- +title: urls.Anchorize +description: Returns the given string, sanitized for usage in an HTML id attribute. +categories: [] +keywords: [] +action: + aliases: [anchorize] + related: + - functions/urls/URLize + returnType: string + signatures: [urls.Anchorize INPUT] +aliases: [/functions/anchorize] +--- + +{{% include "/functions/urls/_common/anchorize-vs-urlize.md" %}} + +## Sanitizing logic + +With the default markdown renderer, Goldmark, the sanitizing logic is controlled by your site configuration: + +{{< code-toggle file=hugo >}} +[markup.goldmark.parser] +autoHeadingIDType = 'github' +{{< /code-toggle >}} + +This controls the behavior of the `anchorize` function and the generation of heading IDs when rendering markdown to HTML. + +Set `autoHeadingIDType` to one of: + +github +: Compatible with GitHub. This is the default, and strongly recommended. + +github-ascii +: Similar to the "github" setting, but removes non-ASCII characters. + +blackfriday +: Provided for backwards compatibility with Hugo v0.59.1 and earlier. This option will be removed in a future release. diff --git a/docs/content/en/functions/urls/JoinPath.md b/docs/content/en/functions/urls/JoinPath.md new file mode 100644 index 000000000..7acecb506 --- /dev/null +++ b/docs/content/en/functions/urls/JoinPath.md @@ -0,0 +1,30 @@ +--- +title: urls.JoinPath +description: Joins the provided elements into a URL string and cleans the result of any ./ or ../ elements. If the argument list is empty, JoinPath returns an empty string. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/path/Join + returnType: string + signatures: [urls.JoinPath ELEMENT...] +aliases: [/functions/urls.joinpath] +--- + +{{< new-in 0.112.0 >}} + +```go-html-template +{{ urls.JoinPath }} → "" (empty string) +{{ urls.JoinPath "" }} → / +{{ urls.JoinPath "a" }} → a +{{ urls.JoinPath "a" "b" }} → a/b +{{ urls.JoinPath "/a" "b" }} → /a/b +{{ urls.JoinPath "https://example.org" "b" }} → https://example.org/b + +{{ urls.JoinPath (slice "a" "b") }} → a/b +``` + +Unlike the [`path.Join`] function, `urls.JoinPath` retains consecutive leading slashes. + +[`path.Join`]: /functions/path/join diff --git a/docs/content/en/functions/urls/Parse.md b/docs/content/en/functions/urls/Parse.md new file mode 100644 index 000000000..2eb4eeadf --- /dev/null +++ b/docs/content/en/functions/urls/Parse.md @@ -0,0 +1,33 @@ +--- +title: urls.Parse +description: Parses a URL into a URL structure. +categories: [] +keywords: [] +action: + aliases: [] + related: [] + returnType: url.URL + signatures: [urls.Parse URL] +aliases: [/functions/urls.parse] +--- + +The `urls.Parse` function parses a URL into a [URL structure](https://godoc.org/net/url#URL). The URL may be relative (a path, without a host) or absolute (starting with a [scheme]). Hugo throws an error when parsing an invalid URL. + +[scheme]: https://www.iana.org/assignments/uri-schemes/uri-schemes.xhtml#uri-schemes-1 + +```go-html-template +{{ $url := "https://example.org:123/foo?a=6&b=7#bar" }} +{{ $u := urls.Parse $url }} + +{{ $u.IsAbs }} → true +{{ $u.Scheme }} → https +{{ $u.Host }} → example.org:123 +{{ $u.Hostname }} → example.org +{{ $u.RequestURI }} → /foo?a=6&b=7 +{{ $u.Path }} → /foo +{{ $u.Query }} → map[a:[6] b:[7]] +{{ $u.Query.a }} → [6] +{{ $u.Query.Get "a" }} → 6 +{{ $u.Query.Has "b" }} → true +{{ $u.Fragment }} → bar +``` diff --git a/docs/content/en/functions/urls/Ref.md b/docs/content/en/functions/urls/Ref.md new file mode 100644 index 000000000..6cd97f030 --- /dev/null +++ b/docs/content/en/functions/urls/Ref.md @@ -0,0 +1,63 @@ +--- +title: urls.Ref +description: Returns the absolute permalink to a page at the given path. +categories: [] +keywords: [] +action: + aliases: [ref] + related: + - functions/urls/RelRef + - methods/page/Ref + - methods/page/RelRef + returnType: string + signatures: + - urls.Ref PAGE PATH + - urls.Ref PAGE OPTIONS +aliases: [/functions/ref] +--- + +The first argument is the context of the page from which to resolve relative paths, typically the current page. + +The second argument is a path to a page, with or without a file extension, with or without an anchor. A path without a leading `/` is first resolved relative to the given context, then to the remainder of the site. Alternatively, provide an [options map](#options) instead of a path. + +```go-html-template +{{ ref . "about" }} +{{ ref . "about#anchor" }} +{{ ref . "about.md" }} +{{ ref . "about.md#anchor" }} +{{ ref . "#anchor" }} +{{ ref . "/blog/my-post" }} +{{ ref . "/blog/my-post.md" }} +``` + +## Options + +Instead of specifying a path, you can also provide an options map: + +path +: (`string`) The path to the page, relative to the content directory. Required. + +lang +: (`string`) The language (site) to search for the page. Default is the current language. Optional. + +outputFormat +: (`string`) The output format to search for the page. Default is the current output format. Optional. + +To return the absolute permalink to another language version of a page: + +```go-html-template +{{ ref . (dict "path" "about.md" "lang" "fr") }} +``` + +To return the absolute permalink to another Output Format of a page: + +```go-html-template +{{ ref . (dict "path" "about.md" "outputFormat" "rss") }} +``` + +By default, Hugo will throw an error and fail the build if it cannot resolve the path. You can change this to a warning in your site configuration, and specify a URL to return when the path cannot be resolved. + +{{< code-toggle file=hugo >}} +refLinksErrorLevel = 'warning' +refLinksNotFoundURL = '/some/other/url' +{{< /code-toggle >}} diff --git a/docs/content/en/functions/urls/RelLangURL.md b/docs/content/en/functions/urls/RelLangURL.md new file mode 100644 index 000000000..2c1037038 --- /dev/null +++ b/docs/content/en/functions/urls/RelLangURL.md @@ -0,0 +1,67 @@ +--- +title: urls.RelLangURL +description: Returns a relative URL with a language prefix, if any. +categories: [] +keywords: [] +action: + aliases: [relLangURL] + related: + - functions/urls/AbsLangURL + - functions/urls/AbsURL + - functions/urls/RelURL + returnType: string + signatures: [urls.RelLangURL INPUT] +aliases: [/functions/rellangurl] +--- + +Use this function with both monolingual and multilingual configurations. The URL returned by this function depends on: + +- Whether the input begins with a slash +- The `baseURL` in site configuration +- The language prefix, if any + +In examples that follow, the project is multilingual with content in both Español (`es`) and English (`en`). The default language is Español. The returned values are from the English site. + +### Input does not begin with a slash + +If the input does not begin with a slash, the resulting URL will be correct regardless of the `baseURL`. + +With `baseURL = https://example.org/` + +```go-html-template +{{ relLangURL "" }} → /en/ +{{ relLangURL "articles" }} → /en/articles +{{ relLangURL "style.css" }} → /en/style.css +``` + +With `baseURL = https://example.org/docs/` + +```go-html-template +{{ relLangURL "" }} → /docs/en/ +{{ relLangURL "articles" }} → /docs/en/articles +{{ relLangURL "style.css" }} → /docs/en/style.css +``` + +#### Input begins with a slash + +If the input begins with a slash, the resulting URL will be incorrect when the `baseURL` includes a subdirectory. With a leading slash, the function returns a URL relative to the protocol+host section of the `baseURL`. + +With `baseURL = https://example.org/` + +```go-html-template +{{ relLangURL "/" }} → /en/ +{{ relLangURL "/articles" }} → /en/articles +{{ relLangURL "/style.css" }} → /en/style.css +``` + +With `baseURL = https://example.org/docs/` + +```go-html-template +{{ relLangURL "/" }} → /en/ +{{ relLangURL "/articles" }} → /en/articles +{{ relLangURL "/style.css" }} → /en/style.css +``` + +{{% note %}} +The last three examples are not desirable in most situations. As a best practice, never include a leading slash when using this function. +{{% /note %}} diff --git a/docs/content/en/functions/urls/RelRef.md b/docs/content/en/functions/urls/RelRef.md new file mode 100644 index 000000000..6b45b2131 --- /dev/null +++ b/docs/content/en/functions/urls/RelRef.md @@ -0,0 +1,70 @@ +--- +title: urls.RelRef +description: Returns the relative permalink to a page at the given path. +categories: [] +keywords: [] +action: + aliases: [relref] + related: + - functions/urls/Ref + - methods/page/Ref + - methods/page/RelRef + returnType: string + signatures: + - urls.RelRef PAGE PATH + - urls.RelRef PAGE OPTIONS +aliases: [/functions/relref] +--- + +The first argument is the context of the page from which to resolve relative paths, typically the current page. + +The second argument is a path to a page, with or without a file extension, with or without an anchor. A path without a leading `/` is first resolved relative to the given context, then to the remainder of the site. Alternatively, provide an [options map](#options) instead of a path. +. +```go-html-template +{{ relref . "about" }} +{{ relref . "about#anchor" }} +{{ relref . "about.md" }} +{{ relref . "about.md#anchor" }} +{{ relref . "#anchor" }} +{{ relref . "/blog/my-post" }} +{{ relref . "/blog/my-post.md" }} +``` + +The permalink returned is relative to the protocol+host portion of the baseURL specified in the site configuration. For example: + +Code|baseURL|Permalink +:--|:--|:-- +`{{ relref . "/about" }}`|`https://example.org/`|`/about/` +`{{ relref . "/about" }}`|`https://example.org/x/`|`/x/about/` + +## Options + +Instead of specifying a path, you can also provide an options map: + +path +: (`string`) The path to the page, relative to the content directory. Required. + +lang +: (`string`) The language (site) to search for the page. Default is the current language. Optional. + +outputFormat +: (`string`) The output format to search for the page. Default is the current output format. Optional. + +To return the relative permalink to another language version of a page: + +```go-html-template +{{ relref . (dict "path" "about.md" "lang" "fr") }} +``` + +To return the relative permalink to another Output Format of a page: + +```go-html-template +{{ relref . (dict "path" "about.md" "outputFormat" "rss") }} +``` + +By default, Hugo will throw an error and fail the build if it cannot resolve the path. You can change this to a warning in your site configuration, and specify a URL to return when the path cannot be resolved. + +{{< code-toggle file=hugo >}} +refLinksErrorLevel = 'warning' +refLinksNotFoundURL = '/some/other/url' +{{< /code-toggle >}} diff --git a/docs/content/en/functions/urls/RelURL.md b/docs/content/en/functions/urls/RelURL.md new file mode 100644 index 000000000..9320c2827 --- /dev/null +++ b/docs/content/en/functions/urls/RelURL.md @@ -0,0 +1,66 @@ +--- +title: urls.RelURL +description: Returns a relative URL. +categories: [] +keywords: [] +action: + aliases: [relURL] + related: + - functions/urls/AbsLangURL + - functions/urls/AbsURL + - functions/urls/RelLangURL + returnType: string + signatures: [urls.RelURL INPUT] +aliases: [/functions/relurl] +--- + +With multilingual configurations, use the [`relLangURL`] function instead. The URL returned by this function depends on: + +- Whether the input begins with a slash +- The `baseURL` in site configuration + +### Input does not begin with a slash + +If the input does not begin with a slash, the resulting URL will be correct regardless of the `baseURL`. + +With `baseURL = https://example.org/` + +```go-html-template +{{ relURL "" }} → / +{{ relURL "articles" }} → /articles +{{ relURL "style.css" }} → /style.css +``` + +With `baseURL = https://example.org/docs/` + +```go-html-template +{{ relURL "" }} → /docs/ +{{ relURL "articles" }} → /docs/articles +{{ relURL "style.css" }} → /docs/style.css +``` + +#### Input begins with a slash + +If the input begins with a slash, the resulting URL will be incorrect when the `baseURL` includes a subdirectory. With a leading slash, the function returns a URL relative to the protocol+host section of the `baseURL`. + +With `baseURL = https://example.org/` + +```go-html-template +{{ relURL "/" }} → / +{{ relURL "/articles" }} → /articles +{{ relURL "style.css" }} → /style.css +``` + +With `baseURL = https://example.org/docs/` + +```go-html-template +{{ relURL "/" }} → / +{{ relURL "/articles" }} → /articles +{{ relURL "/style.css" }} → /style.css +``` + +{{% note %}} +The last three examples are not desirable in most situations. As a best practice, never include a leading slash when using this function. +{{% /note %}} + +[`relLangURL`]: /functions/urls/rellangurl/ diff --git a/docs/content/en/functions/urls/URLize.md b/docs/content/en/functions/urls/URLize.md new file mode 100644 index 000000000..bf44a82d1 --- /dev/null +++ b/docs/content/en/functions/urls/URLize.md @@ -0,0 +1,63 @@ +--- +title: urls.URLize +description: Returns the given string, sanitized for usage in a URL. +categories: [] +keywords: [] +action: + aliases: [urlize] + related: + - functions/urls/Anchorize + returnType: string + signatures: [urls.URLize INPUT] +aliases: [/functions/urlize] +--- + +{{% include "/functions/urls/_common/anchorize-vs-urlize.md" %}} + +## Example + +Use the `urlize` function to create a link to a [term] page. + +Consider this site configuration: + +{{< code-toggle file=hugo >}} +[taxonomies] +author = 'authors' +{{< /code-toggle >}} + +And this front matter: + +{{< code-toggle file=content/books/les-miserables.md fm=true >}} +title = 'Les Misérables' +authors = ['Victor Hugo'] +{{< /code-toggle >}} + +The published site will have this structure: + +```text +public/ +├── authors/ +│ ├── victor-hugo/ +│ │ └── index.html +│ └── index.html +├── books/ +│ ├── les-miserables/ +│ │ └── index.html +│ └── index.html +└── index.html +``` + +To create a link to the term page: + +```go-html-template +{{ $taxonomy := "authors" }} +{{ $term := "Victor Hugo" }} +{{ with index .Site.Taxonomies $taxonomy (urlize $term) }} + <a href="{{ .Page.RelPermalink }}">{{ .Page.LinkTitle }}</a> +{{ end }} +``` + +To generate a list of term pages associated with a given content page, use the [`GetTerms`] method on a `Page` object. + +[`GetTerms`]: /methods/page/getterms/ +[term]: /getting-started/glossary/#term diff --git a/docs/content/en/functions/urls/_common/_index.md b/docs/content/en/functions/urls/_common/_index.md new file mode 100644 index 000000000..47d5812fb --- /dev/null +++ b/docs/content/en/functions/urls/_common/_index.md @@ -0,0 +1,13 @@ +--- +cascade: + _build: + list: never + publishResources: false + render: never +--- + +<!-- +Files within this headless branch bundle are markdown snippets. Each file must contain front matter delimiters, though front matter fields are not required. + +Include the rendered content using the "include" shortcode. +--> diff --git a/docs/content/en/functions/urls/_common/anchorize-vs-urlize.md b/docs/content/en/functions/urls/_common/anchorize-vs-urlize.md new file mode 100644 index 000000000..0f01bcf78 --- /dev/null +++ b/docs/content/en/functions/urls/_common/anchorize-vs-urlize.md @@ -0,0 +1,35 @@ +--- +# Do not remove front matter. +--- + +The [`anchorize`] and [`urlize`] functions are similar: + +[`anchorize`]: /functions/urls/anchorize +[`urlize`]: /functions/urls/urlize + +- Use the `anchorize` function to generate an HTML `id` attribute value +- Use the `urlize` function to sanitize a string for usage in a URL + +For example: + +```go-html-template +{{ $s := "A B C" }} +{{ $s | anchorize }} → a-b-c +{{ $s | urlize }} → a-b-c + +{{ $s := "a b c" }} +{{ $s | anchorize }} → a-b---c +{{ $s | urlize }} → a-b-c + +{{ $s := "< a, b, & c >" }} +{{ $s | anchorize }} → -a-b--c- +{{ $s | urlize }} → a-b-c + +{{ $s := "main.go" }} +{{ $s | anchorize }} → maingo +{{ $s | urlize }} → main.go + +{{ $s := "Hugö" }} +{{ $s | anchorize }} → hugö +{{ $s | urlize }} → hug%C3%B6 +``` diff --git a/docs/content/en/functions/urls/_index.md b/docs/content/en/functions/urls/_index.md new file mode 100644 index 000000000..5f16feeeb --- /dev/null +++ b/docs/content/en/functions/urls/_index.md @@ -0,0 +1,12 @@ +--- +title: URL functions +linkTitle: urls +description: Template functions to work with URLs. +categories: [] +keywords: [] +menu: + docs: + parent: functions +--- + +Use these functions to work with URLs. diff --git a/docs/content/en/getting-started/_index.md b/docs/content/en/getting-started/_index.md new file mode 100644 index 000000000..780b96a62 --- /dev/null +++ b/docs/content/en/getting-started/_index.md @@ -0,0 +1,20 @@ +--- +title: Getting started +linkTitle: Overview +description: Quick start and guides for installing Hugo on your preferred operating system. +categories: [] +keywords: [] +menu: + docs: + identifier: getting-started-overview + parent: getting-started + weight: 10 +weight: 10 +aliases: [/overview/introduction/] +--- + +If this is your first time using Hugo and you've [already installed Hugo on your machine][installed], we recommend the [quick start]. You can also use [external learning resources] to learn Hugo. + +[installed]: /installation/ +[quick start]: /getting-started/quick-start/ +[external learning resources]: /getting-started/external-learning-resources/ diff --git a/docs/content/en/getting-started/configuration-markup.md b/docs/content/en/getting-started/configuration-markup.md new file mode 100644 index 000000000..607301d3a --- /dev/null +++ b/docs/content/en/getting-started/configuration-markup.md @@ -0,0 +1,218 @@ +--- +title: Configure markup +description: Configure rendering of markup to HTML. +categories: [getting started,fundamentals] +keywords: [configuration,highlighting] +menu: + docs: + parent: getting-started + weight: 50 +weight: 50 +slug: configuration-markup +toc: true +--- + +## Default handler + +By default, Hugo uses [Goldmark] to render markdown to HTML. + +{{< code-toggle file=hugo >}} +[markup] +defaultMarkdownHandler = 'goldmark' +{{< /code-toggle >}} + +Files with the `.md` or `.markdown` extension are processed as markdown, provided that you have not specified a different [content format] using the `markup` field in front matter. + +To use a different renderer for markdown files, specify one of `asciidocext`, `org`, `pandoc`, or `rst` in your site configuration. + +defaultMarkdownHandler|Description +:--|:-- +`asciidocext`|[AsciiDoc] +`goldmark`|[Goldmark] +`org`|[Emacs Org Mode] +`pandoc`|[Pandoc] +`rst`|[reStructuredText] + +To use Asciidoc, Pandoc, or reStructuredText you must install the relevant renderer and update your [security policy]. + +{{% note %}} +Unless you need a unique capability provided by one of the alternate markdown handlers, we strongly recommend that you use the default setting. Goldmark is fast, well maintained, conforms to the [CommonMark] specification, and is compatible with [GitHub Flavored Markdown] (GFM). + +[commonmark]: https://spec.commonmark.org/0.30/ +[github flavored markdown]: https://github.github.com/gfm/ +{{% /note %}} + +[asciidoc]: https://asciidoc.org/ +[content format]: /content-management/formats/#list-of-content-formats +[emacs org mode]: https://orgmode.org/ +[goldmark]: https://github.com/yuin/goldmark/ +[pandoc]: https://pandoc.org/ +[restructuredtext]: https://docutils.sourceforge.io/rst.html +[security policy]: /about/security-model/#security-policy + +## Goldmark + +This is the default configuration for the Goldmark markdown renderer: + +{{< code-toggle config=markup.goldmark />}} + +For details on the extensions, refer to the [Goldmark documentation](https://github.com/yuin/goldmark/#built-in-extensions). + +Some settings explained: + +hardWraps +: By default, Goldmark ignores newlines within a paragraph. Set to `true` to render newlines as `<br>` elements. + +unsafe +: By default, Goldmark does not render raw HTML and potentially dangerous links. If you have lots of inline HTML and/or JavaScript, you may need to turn this on. + +typographer +: The typographer extension replaces certain character combinations with HTML entities as specified below: + +Markdown|Replaced by|Description +:--|:--|:-- +`...`|`…`|horizontal ellipsis +`'`|`’`|apostrophe +`--`|`–`|en dash +`---`|`—`|em dash +`«`|`«`|left angle quote +`“`|`“`|left double quote +`‘`|`‘`|left single quote +`»`|`»`|right angle quote +`”`|`”`|right double quote +`’`|`’`|right single quote + +attribute +: Enable custom attribute support for titles and blocks by adding attribute lists inside single curly brackets (`{.myclass class="class1 class2" }`) and placing it _after the Markdown element it decorates_, on the same line for titles and on a new line directly below for blocks. + +Hugo supports adding attributes (e.g. CSS classes) to Markdown blocks, e.g. tables, lists, paragraphs etc. + +A blockquote with a CSS class: + +```md +> foo +> bar +{.myclass} +``` + +There are some current limitations: For tables you can currently only apply it to the full table, and for lists the `ul`/`ol`-nodes only, e.g.: + +```md +* Fruit + * Apple + * Orange + * Banana + {.fruits} +* Dairy + * Milk + * Cheese + {.dairies} +{.list} +``` + +Note that attributes in [code fences](/content-management/syntax-highlighting/#highlighting-in-code-fences) must come after the opening tag, with any other highlighting processing instruction, e.g.: + +````txt +```go {.myclass linenos=table,hl_lines=[8,"15-17"],linenostart=199} +// ... code +``` +```` + +autoHeadingIDType ("github") +: The strategy used for creating auto IDs (anchor names). Available types are `github`, `github-ascii` and `blackfriday`. `github` produces GitHub-compatible IDs, `github-ascii` will drop any non-ASCII characters after accent normalization, and `blackfriday` will make the IDs compatible with Blackfriday, the default Markdown engine before Hugo 0.60. Note that if Goldmark is your default Markdown engine, this is also the strategy used in the [anchorize](/functions/urls/anchorize) template func. + +## Asciidoc + +This is the default configuration for the AsciiDoc markdown renderer: + +{{< code-toggle config=markup.asciidocExt />}} + +attributes +: (`map`) Variables to be referenced in your AsciiDoc file. This is a list of variable name/value maps. See Asciidoctor’s [attributes]. + +[attributes]: https://asciidoctor.org/docs/asciidoc-syntax-quick-reference/#attributes-and-substitutions + +backend: +: (`string`) Don’t change this unless you know what you are doing. + +extensions +: (`[]string`) Possible extensions are `asciidoctor-html5s`, `asciidoctor-bibtex`, `asciidoctor-diagram`, `asciidoctor-interdoc-reftext`, `asciidoctor-katex`, `asciidoctor-latex`, `asciidoctor-mathematical`, and `asciidoctor-question`. + +failureLevel +: (`string`) The minimum logging level that triggers a non-zero exit code (failure). + +noHeaderOrFooter +: (`bool`) Output an embeddable document, which excludes the header, the footer, and everything outside the body of the document. Don’t change this unless you know what you are doing. + +preserveTOC +: (`bool`) By default, Hugo removes the table of contents generated by Asciidoctor and provides it through the built-in variable `.TableOfContents` to enable further customization and better integration with the various Hugo themes. This option can be set to true to preserve Asciidoctor’s TOC in the generated page. + +safeMode +: (`string`) Safe mode level `unsafe`, `safe`, `server`, or `secure`. Don’t change this unless you know what you are doing. + +sectionNumbers +: (`bool`) Auto-number section titles. + +trace +: (`bool`) Include backtrace information on errors. + +verbose +: (`bool`) Verbosely print processing information and configuration file checks to stderr. + +workingFolderCurrent +: (`bool`) Sets the working directory to be the same as that of the AsciiDoc file being processed, so that [include] will work with relative paths. This setting uses the asciidoctor cli parameter --base-dir and attribute outdir=. For rendering diagrams with [asciidoctor-diagram], `workingFolderCurrent` must be set to `true`. + +[asciidoctor-diagram]: https://asciidoctor.org/docs/asciidoctor-diagram/ +[include]: https://asciidoctor.org/docs/asciidoc-syntax-quick-reference/#include-files + +Notice that for security concerns only extensions that do not have path separators (either `\`, `/` or `.`) are allowed. That means that extensions can only be invoked if they are in the Ruby's `$LOAD_PATH` (ie. most likely, the extension has been installed by the user). Any extension declared relative to the website's path will not be accepted. + +Example of how to set extensions and attributes: + +```yml +[markup.asciidocExt] + extensions = ["asciidoctor-html5s", "asciidoctor-diagram"] + workingFolderCurrent = true + [markup.asciidocExt.attributes] + my-base-url = "https://example.com/" + my-attribute-name = "my value" +``` + +In a complex Asciidoctor environment it is sometimes helpful to debug the exact call to your external helper with all +parameters. Run Hugo with `-v`. You will get an output like + +```txt +INFO 2019/12/22 09:08:48 Rendering book-as-pdf.adoc with C:\Ruby26-x64\bin\asciidoctor.bat using asciidoc args [--no-header-footer -r asciidoctor-html5s -b html5s -r asciidoctor-diagram --base-dir D:\prototypes\hugo_asciidoc_ddd\docs -a outdir=D:\prototypes\hugo_asciidoc_ddd\build -] ... +``` + +## Highlight + +This is the default `highlight` configuration. Note that some of these settings can be set per code block, see [Syntax Highlighting](/content-management/syntax-highlighting/). + +{{< code-toggle config=markup.highlight />}} + +For `style`, see these galleries: + +* [Short snippets](https://xyproto.github.io/splash/docs/all.html) +* [Long snippets](https://xyproto.github.io/splash/docs/longer/all.html) + +For CSS, see [Generate Syntax Highlighter CSS](/content-management/syntax-highlighting/#generate-syntax-highlighter-css). + +## Table of contents + +{{< code-toggle config=markup.tableOfContents />}} + +These settings only works for the Goldmark renderer: + +startLevel +: The heading level, values starting at 1 (`h1`), to start render the table of contents. + +endLevel +: The heading level, inclusive, to stop render the table of contents. + +ordered +: If `true`, generates an ordered list instead of an unordered list. + +## Render hooks + +See [Markdown Render Hooks](/templates/render-hooks/). diff --git a/docs/content/en/getting-started/configuration.md b/docs/content/en/getting-started/configuration.md new file mode 100644 index 000000000..3ce0077ba --- /dev/null +++ b/docs/content/en/getting-started/configuration.md @@ -0,0 +1,788 @@ +--- +title: Configure Hugo +linkTitle: Configuration +description: How to configure your Hugo site. +categories: [getting started,fundamentals] +keywords: [configuration,toml,yaml,json] +menu: + docs: + parent: getting-started + weight: 40 +weight: 40 +toc: true +aliases: [/overview/source-directory/,/overview/configuration/] +--- + +## Configuration file + +Create a site configuration file in the root of your project directory, naming it `hugo.toml`, `hugo.yaml`, or `hugo.json`, with that order of precedence. + +```text +my-project/ +└── hugo.toml +``` + +{{% note %}} +With v0.109.0 and earlier the basename of the site configuration file was `config` instead of `hugo`. You can use either, but should transition to the new naming convention when practical. +{{% /note %}} + +A simple example: + +{{< code-toggle file=hugo >}} +baseURL = 'https://example.org/' +languageCode = 'en-us' +title = 'ABC Widgets, Inc.' +[params] +subtitle = 'The Best Widgets on Earth' +[params.contact] +email = 'info@example.org' +phone = '+1 202-555-1212' +{{< /code-toggle >}} + +To use a different configuration file when building your site, use the `--config` flag: + +```sh +hugo --config other.toml +``` + +Combine two or more configuration files, with left-to-right precedence: + +```sh +hugo --config a.toml,b.yaml,c.json +``` + +{{% note %}} +See the specifications for each file format: [TOML], [YAML], and [JSON]. + +[TOML]: https://toml.io/en/latest +[YAML]: https://yaml.org/spec/ +[JSON]: https://datatracker.ietf.org/doc/html/rfc7159 +{{% /note %}} + +## Configuration directory + +Instead of a single site configuration file, split your configuration by [environment], root configuration key, and language. For example: + +[environment]: /getting-started/glossary/#environment + +```text +my-project/ +└── config/ + ├── _default/ + │ ├── hugo.toml + │ ├── menus.en.toml + │ ├── menus.de.toml + │ └── params.toml + ├── production/ + │ ├── hugo.toml + │ └── params.toml + └── staging/ + ├── hugo.toml + └── params.toml +``` + +The root configuration keys are `build`, `caches`, `cascade`, `deployment`, `frontmatter`, `imaging`, `languages`, `markup`, `mediatypes`, `menus`, `minify`, `module`, `outputformats`, `outputs`, `params`, `permalinks`, `privacy`, `related`, `security`, `server`, `services`, `sitemap`, and `taxonomies`. + +### Omit the root key + +When splitting the configuration by root key, omit the root key in the given file. For example, these are equivalent: + +{{< code-toggle file=hugo >}} +[params] +foo = 'bar' +{{< /code-toggle >}} + +{{< code-toggle file=params >}} +foo = 'bar' +{{< /code-toggle >}} + +### Recursive parsing + +Hugo parses the `config` directory recursively, allowing you to organize the files into subdirectories. For example: + +```text +my-project/ +└── config/ + └── _default/ + ├── navigation/ + │ ├── menus.de.toml + │ └── menus.en.toml + └── hugo.toml +``` + +### Example + +```text +my-project/ +└── config/ + ├── _default/ + │ ├── hugo.toml + │ ├── menus.en.toml + │ ├── menus.de.toml + │ └── params.toml + ├── production/ + │ ├── hugo.toml + │ └── params.toml + └── staging/ + ├── hugo.toml + └── params.toml +``` + +Considering the structure above, when running `hugo --environment staging`, Hugo will use every setting from `config/_default` and merge `staging`'s on top of those. + +Let's take an example to understand this better. Let's say you are using Google Analytics for your website. This requires you to specify a [Google tag ID] in your site configuration: + +[Google tag ID]: https://support.google.com/tagmanager/answer/12326985?hl=en + +{{< code-toggle file=hugo copy=false >}} +[services.googleAnalytics] +ID = 'G-XXXXXXXXX' +{{< /code-toggle >}} + +Now consider the following scenario: + +1. You don't want to load the analytics code when running `hugo server`. +2. You want to use different Google tag IDs for your production and staging environments. For example: + + - `G-PPPPPPPPP` for production + - `G-SSSSSSSSS` for staging + +To satisfy these requirements, configure your site as follows: + +1. `config/_default/hugo.toml` + + Exclude the `services.googleAnalytics` section. This will prevent loading of the analytics code when you run `hugo server`. + + By default, Hugo sets its `environment` to `development` when running `hugo server`. In the absence of a `config/development` directory, Hugo uses the `config/_default` directory. + +2. `config/production/hugo.toml` + + Include this section only: + + {{< code-toggle file=hugo copy=false >}} + [services.googleAnalytics] + ID = 'G-PPPPPPPPP' + {{< /code-toggle >}} + + You do not need to include other parameters in this file. Include only those parameters that are specific to your production environment. Hugo will merge these parameters with the default configuration. + + By default, Hugo sets its `environment` to `production` when running `hugo`. The analytics code will use the `G-PPPPPPPPP` tag ID. + +3. `config/staging/hugo.toml` + + Include this section only: + + {{< code-toggle file=hugo copy=false >}} + [services.googleAnalytics] + ID = 'G-SSSSSSSSS' + {{< /code-toggle >}} + + You do not need to include other parameters in this file. Include only those parameters that are specific to your staging environment. Hugo will merge these parameters with the default configuration. + + To build your staging site, run `hugo --environment staging`. The analytics code will use the `G-SSSSSSSSS` tag ID. + +## Merge configuration from themes + +The configuration value for `_merge` can be one of: + +none +: No merge. + +shallow +: Only add values for new keys. + +deep +: Add values for new keys, merge existing. + +Note that you don't need to be so verbose as in the default setup below; a `_merge` value higher up will be inherited if not set. + +{{< code-toggle file=hugo dataKey="config_helpers.mergeStrategy" skipHeader=true />}} + +## All configuration settings + +###### archetypeDir + +(`string`) The directory where Hugo finds archetype files (content templates). Default is `archetypes`. {{% module-mounts-note %}} + +###### assetDir + +(`string`) The directory where Hugo finds asset files used in [Hugo Pipes](/hugo-pipes/). Default is `assets`. {{% module-mounts-note %}} + +###### baseURL + +(`string`) The absolute URL (protocol, host, path, and trailing slash) of your published site (e.g., `https://www.example.org/docs/`). + +###### build + +See [Configure Build](#configure-build). + +###### buildDrafts + +(`bool`) Include drafts when building. Default is `false`. + +###### buildExpired + +(`bool`) Include content already expired. Default is `false`. + +###### buildFuture + +(`bool`) Include content with publishdate in the future. Default is `false`. + +###### caches + +See [Configure File Caches](#configure-file-caches). + +###### cascade + +Pass down down default configuration values (front matter) to pages in the content tree. The options in site config is the same as in page front matter, see [Front Matter Cascade](/content-management/front-matter#front-matter-cascade). + +{{% note %}} +For a website in a single language, define the `[[cascade]]` in [Front Matter](/content-management/front-matter#front-matter-cascade). For a multilingual website, define the `[[cascade]]` in [Site Config](../../getting-started/configuration/#cascade). + +To remain consistent and prevent unexpected behavior, do not mix these strategies. +{{% /note %}} + +###### canonifyURLs + +(`bool`) Enable to turn relative URLs into absolute. Default is `false`. See [details](/content-management/urls/#canonical-urls). + +###### cleanDestinationDir + +(`bool`) When building, removes files from destination not found in static directories. Default is `false`. + +###### contentDir + +(`string`) The directory from where Hugo reads content files. Default is `content`. {{% module-mounts-note %}} + +###### copyright + +(`string`) Copyright notice for your site, typically displayed in the footer. + +###### dataDir + +(`string`) The directory from where Hugo reads data files. Default is `data`. {{% module-mounts-note %}} + +###### defaultContentLanguage + +(`string`) Content without language indicator will default to this language. Default is `en`. + +###### defaultContentLanguageInSubdir + +(`bool`) Render the default content language in subdir, e.g. `content/en/`. The site root `/` will then redirect to `/en/`. Default is `false`. + +###### disableAliases + +(`bool`) Will disable generation of alias redirects. Note that even if `disableAliases` is set, the aliases themselves are preserved on the page. The motivation with this is to be able to generate 301 redirects in an `.htaccess`, a Netlify `_redirects` file or similar using a custom output format. Default is `false`. + +###### disableHugoGeneratorInject + +(`bool`) Hugo will, by default, inject a generator meta tag in the HTML head on the _home page only_. You can turn it off, but we would really appreciate if you don't, as this is a good way to watch Hugo's popularity on the rise. Default is `false`. + +###### disableKinds + +(`string slice`) Disable rendering of the specified page [kinds], any of `404`, `home`, `page`, `robotstxt`, `rss`, `section`, `sitemap`, `taxonomy`, or `term`. + +[kinds]: /getting-started/glossary/#page-kind + +###### disableLiveReload + +(`bool`) Disable automatic live reloading of browser window. Default is `false`. + +###### disablePathToLower + +(`bool`) Do not convert the url/path to lowercase. Default is `false`. + +###### enableEmoji + +(`bool`) Enable Emoji emoticons support for page content; see the [emoji shortcode quick reference guide](/quick-reference/emojis/). Default is `false`. + +###### enableGitInfo + +(`bool`) Enable `.GitInfo` object for each page (if the Hugo site is versioned by Git). This will then update the `Lastmod` parameter for each page using the last git commit date for that content file. Default is `false`. + +###### enableMissingTranslationPlaceholders + +(`bool`) Show a placeholder instead of the default value or an empty string if a translation is missing. Default is `false`. + +###### enableRobotsTXT + +(`bool`) Enable generation of `robots.txt` file. Default is `false`. + +###### frontmatter + +See [Front matter Configuration](#configure-front-matter). + +###### hasCJKLanguage + +(`bool`) If true, auto-detect Chinese/Japanese/Korean Languages in the content. This will make `.Summary` and `.WordCount` behave correctly for CJK languages. Default is `false`. + +###### imaging + +See [image processing configuration](/content-management/image-processing/#imaging-configuration). + +###### languageCode + +(`string`) A language tag as defined by [RFC 5646](https://datatracker.ietf.org/doc/html/rfc5646). This value is used to populate: + +- The `<language>` element in the internal [RSS template](https://github.com/gohugoio/hugo/blob/master/tpl/tplimpl/embedded/templates/_default/rss.xml) +- The `lang` attribute of the `<html>` element in the internal [alias template](https://github.com/gohugoio/hugo/blob/master/tpl/tplimpl/embedded/templates/alias.html) + +###### languages + +See [Configure Languages](/content-management/multilingual/#configure-languages). + +###### disableLanguages + +See [Disable a Language](/content-management/multilingual/#disable-a-language) + +###### markup + +See [Configure Markup](/getting-started/configuration-markup). + +###### mediaTypes + +See [Configure Media Types](/templates/output-formats/#media-types). + +###### menus + +See [Menus](/content-management/menus/#define-in-site-configuration). + +###### minify + +See [Configure Minify](#configure-minify). + +###### module + +Module configuration see [module configuration](/hugo-modules/configuration/). + +###### newContentEditor + +(`string`) The editor to use when creating new content. + +###### noChmod + +(`bool`) Don't sync permission mode of files. Default is `false`. + +###### noTimes + +(`bool`) Don't sync modification time of files. Default is `false`. + +###### outputFormats + +See [Configure Output Formats](#configure-additional-output-formats). + +###### paginate + +(`int`) Default number of elements per page in [pagination](/templates/pagination/). Default is `10`. + +###### paginatePath + +(`string`) The path element used during pagination (`https://example.org/page/2`). Default is `page`. + +###### permalinks + +See [Content Management](/content-management/urls/#permalinks). + +###### pluralizeListTitles + +(`bool`) Pluralize titles in lists. Default is `true`. + +###### publishDir + +(`string`) The directory to where Hugo will write the final static site (the HTML files etc.). Default is `public`. + +###### related + +See [Related Content](/content-management/related/#configure-related-content). + +###### relativeURLs + +(`bool`) Enable this to make all relative URLs relative to content root. Note that this does not affect absolute URLs. Default is `false`. See [details](/content-management/urls/#relative-urls). + +###### refLinksErrorLevel + +(`string`) When using `ref` or `relref` to resolve page links and a link cannot be resolved, it will be logged with this log level. Valid values are `ERROR` (default) or `WARNING`. Any `ERROR` will fail the build (`exit -1`). Default is `ERROR`. + +###### refLinksNotFoundURL + +(`string`) URL to be used as a placeholder when a page reference cannot be found in `ref` or `relref`. Is used as-is. + +###### removePathAccents + +(`bool`) Removes [non-spacing marks](https://www.compart.com/en/unicode/category/Mn) from [composite characters](https://en.wikipedia.org/wiki/Precomposed_character) in content paths. Default is `false`. + +```text +content/post/hügó.md → https://example.org/post/hugo/ +``` + +###### sectionPagesMenu + +See [Menus](/content-management/menus/#define-automatically). + +###### security + +See [Security Policy](/about/security-model/#security-policy). + +###### sitemap + +Default [sitemap configuration](/templates/sitemap-template/#configuration). + +###### summaryLength + +(`int`) The length of text in words to show in a [`.Summary`](/content-management/summaries/#automatic-summary-splitting). Default is `70`. + +###### taxonomies + +See [Configure Taxonomies](/content-management/taxonomies#configure-taxonomies). + +###### theme + +See [module configuration](/hugo-modules/configuration/#module-configuration-imports) for how to import a theme. + +###### themesDir + +(`string`) The directory where Hugo reads the themes from. Default is `themes`. + +###### timeout + +(`string`) Timeout for generating page contents, specified as a [duration](https://pkg.go.dev/time#Duration) or in seconds. *Note:* this is used to bail out of recursive content generation. You might need to raise this limit if your pages are slow to generate (e.g., because they require large image processing or depend on remote contents). Default is `30s`. + +###### timeZone + +(`string`) The time zone (or location), e.g. `Europe/Oslo`, used to parse front matter dates without such information and in the [`time`] function. The list of valid values may be system dependent, but should include `UTC`, `Local`, and any location in the [IANA Time Zone database](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones). + +###### title + +(`string`) Site title. + +###### titleCaseStyle + +(`string`) Default is `ap`. See [Configure Title Case](#configure-title-case). + +###### uglyURLs + +(`bool`) When enabled, creates URL of the form `/filename.html` instead of `/filename/`. Default is `false`. + +###### watch + +(`bool`) Watch filesystem for changes and recreate as needed. Default is `false`. + +{{% note %}} +If you are developing your site on a \*nix machine, here is a handy shortcut for finding a configuration option from the command line: +```txt +cd ~/sites/yourhugosite +hugo config | grep emoji +``` + +which shows output like + +```txt +enableemoji: true +``` +{{% /note %}} + +## Configure build + +The `build` configuration section contains global build-related configuration options. + +{{< code-toggle config=build />}} + +buildStats {{< new-in 0.115.1 >}} +: When enabled, creates a `hugo_stats.json` file in the root of your project. This file contains arrays of the `class` attributes, `id` attributes, and tags of every HTML element within your published site. Use this file as data source when [removing unused CSS] from your site. This process is also known as pruning, purging, or tree shaking. + +[removing unused CSS]: /hugo-pipes/postprocess/#css-purging-with-postcss + +Exclude `class` attributes, `id` attributes, or tags from `hugo_stats.json` with the `disableClasses`, `disableIDs`, and `disableTags` keys. + +{{% note %}} +With v0.115.0 and earlier this feature was enabled by setting `writeStats` to `true`. Although still functional, the `writeStats` key will be deprecated in a future release. + +Given that CSS purging is typically limited to production builds, place the `buildStats` object below [config/production]. + +[config/production]: /getting-started/configuration/#configuration-directory + +Built for speed, there may be "false positive" detections (e.g., HTML elements that are not HTML elements) while parsing the published site. These "false positives" are infrequent and inconsequential. +{{% /note %}} + +Due to the nature of partial server builds, new HTML entities are added while the server is running, but old values will not be removed until you restart the server or run a regular `hugo` build. + +cachebusters +: See [Configure Cache Busters](#configure-cache-busters) + +noJSConfigInAssets +: Turn off writing a `jsconfig.json` into your `/assets` folder with mapping of imports from running [js.Build](/hugo-pipes/js). This file is intended to help with intellisense/navigation inside code editors such as [VS Code](https://code.visualstudio.com/). Note that if you do not use `js.Build`, no file will be written. + +useResourceCacheWhen +: When to use the cached resources in `/resources/_gen` for PostCSS and ToCSS. Valid values are `never`, `always` and `fallback`. The last value means that the cache will be tried if PostCSS/extended version is not available. + +## Configure cache busters + +{{< new-in 0.112.0 >}} + +The `build.cachebusters` configuration option was added to support development using Tailwind 3.x's JIT compiler where a `build` configuration may look like this: + +{{< code-toggle file=hugo >}} +[build] + [build.buildStats] + enable = true + [[build.cachebusters]] + source = "assets/watching/hugo_stats\\.json" + target = "styles\\.css" + [[build.cachebusters]] + source = "(postcss|tailwind)\\.config\\.js" + target = "css" + [[build.cachebusters]] + source = "assets/.*\\.(js|ts|jsx|tsx)" + target = "js" + [[build.cachebusters]] + source = "assets/.*\\.(.*)$" + target = "$1" +{{< /code-toggle >}} + +When `buildStats` {{< new-in 0.115.1 >}} is enabled, Hugo writes a `hugo_stats.json` file on each build with HTML classes etc. that's used in the rendered output. Changes to this file will trigger a rebuild of the `styles.css` file. You also need to add `hugo_stats.json` to Hugo's server watcher. See [Hugo Starter Tailwind Basic](https://github.com/bep/hugo-starter-tailwind-basic) for a running example. + +source +: A regexp matching file(s) relative to one of the virtual component directories in Hugo, typically `assets/...`. + +target +: A regexp matching the keys in the resource cache that should be expired when `source` changes. You can use the matching regexp groups from `source` in the expression, e.g. `$1`. + +## Configure server + +This is only relevant when running `hugo server`, and it allows to set HTTP headers during development, which allows you to test out your Content Security Policy and similar. The configuration format matches [Netlify's](https://docs.netlify.com/routing/headers/#syntax-for-the-netlify-configuration-file) with slightly more powerful [Glob matching](https://github.com/gobwas/glob): + +{{< code-toggle file=hugo >}} +[server] +[[server.headers]] +for = "/**" + +[server.headers.values] +X-Frame-Options = "DENY" +X-XSS-Protection = "1; mode=block" +X-Content-Type-Options = "nosniff" +Referrer-Policy = "strict-origin-when-cross-origin" +Content-Security-Policy = "script-src localhost:1313" +{{< /code-toggle >}} + +Since this is "development only", it may make sense to put it below the `development` environment: + +{{< code-toggle file=config/development/server >}} +[[headers]] +for = "/**" + +[headers.values] +X-Frame-Options = "DENY" +X-XSS-Protection = "1; mode=block" +X-Content-Type-Options = "nosniff" +Referrer-Policy = "strict-origin-when-cross-origin" +Content-Security-Policy = "script-src localhost:1313" +{{< /code-toggle >}} + +You can also specify simple redirects rules for the server. The syntax is again similar to Netlify's. + +Note that a `status` code of 200 will trigger a [URL rewrite](https://docs.netlify.com/routing/redirects/rewrites-proxies/), which is what you want in SPA situations, e.g: + +{{< code-toggle file=config/development/server >}} +[[redirects]] +from = "/myspa/**" +to = "/myspa/" +status = 200 +force = false +{{< /code-toggle >}} + +Setting `force=true` will make a redirect even if there is existing content in the path. Note that before Hugo 0.76 `force` was the default behavior, but this is inline with how Netlify does it. + +## 404 server error page {#_404-server-error-page} + +{{< new-in 0.103.0 >}} + +Hugo will, by default, render all 404 errors when running `hugo server` with the `404.html` template. Note that if you have already added one or more redirects to your [server configuration](#configure-server), you need to add the 404 redirect explicitly, e.g: + +{{< code-toggle file=config/development/server >}} +[[redirects]] +from = "/**" +to = "/404.html" +status = 404 +{{< /code-toggle >}} + +## Configure title case + +By default, Hugo follows the capitalization rules published in the [Associated Press Stylebook] when creating automatic section titles, and when transforming strings with the [`strings.Title`] function. + +Change this behavior by setting `titleCaseStyle` in your site configuration to any of the values below: + +ap +: Use the capitalization rules published in the [Associated Press Stylebook]. + +chicago +: Use the capitalization rules published in the [Chicago Manual of Style]. + +go +: Capitalize the first letter of every word. + +firstupper +: Capitalize the first letter of the first word. + +none +: Disable transformation of automatic section titles, and disable the transformation performed by the `strings.Title` function. This is useful if you would prefer to manually capitalize section titles as needed, and to bypass opinionated theme usage of the `strings.Title` function. + +[`strings.Title`]: /functions/strings/title +[Associated Press Stylebook]: https://www.apstylebook.com/ +[Chicago Manual of Style]: https://www.chicagomanualofstyle.org/home.html +[site configuration]: /getting-started/configuration/#configure-title-case + +## Configuration environment variables + +HUGO_NUMWORKERMULTIPLIER +: Can be set to increase or reduce the number of workers used in parallel processing in Hugo. If not set, the number of logical CPUs will be used. + +## Configure with environment variables + +In addition to the 3 configuration options already mentioned, configuration key-values can be defined through operating system environment variables. + +For example, the following command will effectively set a website's title on Unix-like systems: + +```txt +$ env HUGO_TITLE="Some Title" hugo +``` + +This is really useful if you use a service such as Netlify to deploy your site. Look at the Hugo docs [Netlify configuration file](https://github.com/gohugoio/hugoDocs/blob/master/netlify.toml) for an example. + +{{% note %}} +Names must be prefixed with `HUGO_` and the configuration key must be set in uppercase when setting operating system environment variables. + +To set configuration parameters, prefix the name with `HUGO_PARAMS_` +{{% /note %}} + +If you are using snake_cased variable names, the above will not work. Hugo determines the delimiter to use by the first character after `HUGO`. This allows you to define environment variables on the form `HUGOxPARAMSxAPI_KEY=abcdefgh`, using any [allowed](https://stackoverflow.com/questions/2821043/allowed-characters-in-linux-environment-variable-names#:~:text=So%20names%20may%20contain%20any,not%20begin%20with%20a%20digit.) delimiter. + +## Ignore content and data files when rendering + +{{% note %}} +This works, but we recommend you use the newer and more powerful [includeFiles and excludeFiles](/hugo-modules/configuration/#module-configuration-mounts) mount options. +{{% /note %}} + +To exclude specific files from the `content`, `data`, and `i18n` directories when rendering your site, set `ignoreFiles` to one or more regular expressions to match against the absolute file path. + +To ignore files ending with `.foo` or `.boo`: + +{{< code-toggle file=hugo >}} +ignoreFiles = ['\.foo$', '\.boo$'] +{{< /code-toggle >}} + +To ignore a file using the absolute file path: + +{{< code-toggle file=hugo >}} +ignoreFiles = ['^/home/user/project/content/test\.md$'] +{{< /code-toggle >}} + +## Configure front matter + +### Configure dates + +Dates are important in Hugo, and you can configure how Hugo assigns dates to your content pages. You do this by adding a `frontmatter` section to your `hugo.toml`. + +The default configuration is: + +{{< code-toggle config=frontmatter />}} + +If you, as an example, have a non-standard date parameter in some of your content, you can override the setting for `date`: + +{{< code-toggle file=hugo >}} +[frontmatter] +date = ["myDate", ":default"] +{{< /code-toggle >}} + +The `:default` is a shortcut to the default settings. The above will set `.Date` to the date value in `myDate` if present, if not we will look in `date`,`publishDate`, `lastmod` and pick the first valid date. + +In the list to the right, values starting with ":" are date handlers with a special meaning (see below). The others are just names of date parameters (case insensitive) in your front matter configuration. Also note that Hugo have some built-in aliases to the above: `lastmod` => `modified`, `publishDate` => `pubdate`, `published` and `expiryDate` => `unpublishdate`. With that, as an example, using `pubDate` as a date in front matter, will, by default, be assigned to `.PublishDate`. + +The special date handlers are: + +`:fileModTime` +: Fetches the date from the content file's last modification timestamp. + +An example: + +{{< code-toggle file=hugo >}} +[frontmatter] +lastmod = ["lastmod", ":fileModTime", ":default"] +{{< /code-toggle >}} + +The above will try first to extract the value for `.Lastmod` starting with the `lastmod` front matter parameter, then the content file's modification timestamp. The last, `:default` should not be needed here, but Hugo will finally look for a valid date in `:git`, `date` and then `publishDate`. + +`:filename` +: Fetches the date from the content file's file name. For example, `2018-02-22-mypage.md` will extract the date `2018-02-22`. Also, if `slug` is not set, `mypage` will be used as the value for `.Slug`. + +An example: + +{{< code-toggle file=hugo >}} +[frontmatter] +date = [":filename", ":default"] +{{< /code-toggle >}} + +The above will try first to extract the value for `.Date` from the file name, then it will look in front matter parameters `date`, `publishDate` and lastly `lastmod`. + +`:git` +: This is the Git author date for the last revision of this content file. This will only be set if `--enableGitInfo` is set or `enableGitInfo = true` is set in site configuration. + +## Configure additional output formats + +Hugo v0.20 introduced the ability to render your content to multiple output formats (e.g., to JSON, AMP html, or CSV). See [Output Formats] for information on how to add these values to your Hugo project's configuration file. + +## Configure minify + +See the [tdewolff/minify] project page for details. + +[tdewolff/minify]: https://github.com/tdewolff/minify + +Default configuration: + +{{< code-toggle config=minify />}} + +## Configure file caches + +Since Hugo 0.52 you can configure more than just the `cacheDir`. This is the default configuration: + +{{< code-toggle config=caches />}} + +You can override any of these cache settings in your own `hugo.toml`. + +### The keywords explained + +cacheDir +: (`string`) See [Configure cacheDir](#configure-cachedir). + +project +: (`string`) The base directory name of the current Hugo project. This means that, in its default setting, every project will have separated file caches, which means that when you do `hugo --gc` you will not touch files related to other Hugo projects running on the same PC. + +resourceDir +: (`string`) This is the value of the `resourceDir` configuration option. + +maxAge +: (`string`) This is the duration before a cache entry will be evicted, -1 means forever and 0 effectively turns that particular cache off. Uses Go's `time.Duration`, so valid values are `"10s"` (10 seconds), `"10m"` (10 minutes) and `"10h"` (10 hours). + +dir +: (`string`) The absolute path to where the files for this cache will be stored. Allowed starting placeholders are `:cacheDir` and `:resourceDir` (see above). + +## Configure cacheDir + +This is the directory where Hugo by default will store its file caches. See [Configure File Caches](#configure-file-caches). + +This can be set using the `cacheDir` config option or via the OS env variable `HUGO_CACHEDIR`. + +If this is not set, Hugo will use, in order of preference: + +1. If running on Netlify: `/opt/build/cache/hugo_cache/`. This means that if you run your builds on Netlify, all caches configured with `:cacheDir` will be saved and restored on the next build. For other CI vendors, please read their documentation. For an CircleCI example, see [this configuration](https://github.com/bep/hugo-sass-test/blob/6c3960a8f4b90e8938228688bc49bdcdd6b2d99e/.circleci/config.yml). +1. In a `hugo_cache` directory below the OS user cache directory as defined by Go's [os.UserCacheDir](https://pkg.go.dev/os#UserCacheDir). On Unix systems, this is `$XDG_CACHE_HOME` as specified by [basedir-spec-latest](https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html) if non-empty, else `$HOME/.cache`. On MacOS, this is `$HOME/Library/Caches`. On Windows, this is`%LocalAppData%`. On Plan 9, this is `$home/lib/cache`. {{< new-in 0.116.0 >}} +1. In a `hugo_cache_$USER` directory below the OS temp dir. + +If you want to know the current value of `cacheDir`, you can run `hugo config`, e.g: `hugo config | grep cachedir`. + +[`time`]: /functions/time/astime +[`.Site.Params`]: /variables/site/ +[directory structure]: /getting-started/directory-structure +[lookup order]: /templates/lookup-order/ +[Output Formats]: /templates/output-formats/ +[templates]: /templates/ +[static-files]: /content-management/static-files/ diff --git a/docs/content/en/getting-started/directory-structure.md b/docs/content/en/getting-started/directory-structure.md new file mode 100644 index 000000000..f91849375 --- /dev/null +++ b/docs/content/en/getting-started/directory-structure.md @@ -0,0 +1,212 @@ +--- +title: Directory structure +description: Each Hugo project is a directory, with subdirectories that contribute to the content, structure, behavior, and presentation of your site. +categories: [getting started,fundamentals] +keywords: [source, organization, directories] +menu: + docs: + parent: getting-started + weight: 30 +weight: 30 +toc: true +aliases: [/overview/source-directory/] +--- + +## Site skeleton + +Hugo generates a project skeleton when you create a new site. For example, this command: + +```sh +hugo new site my-site +``` + +Creates this directory structure: + +```txt +my-site/ +├── archetypes/ +│ └── default.md +├── assets/ +├── content/ +├── data/ +├── i18n/ +├── layouts/ +├── static/ +├── themes/ +└── hugo.toml <-- site configuration +``` + +Depending on requirements, you may wish to organize your site configuration into subdirectories: + +```txt +my-site/ +├── archetypes/ +│ └── default.md +├── assets/ +├── config/ <-- site configuration +│ └── _default/ +│ └── hugo.toml +├── content/ +├── data/ +├── i18n/ +├── layouts/ +├── static/ +└── themes/ +``` + +When you build your site, Hugo creates a `public` directory, and typically a `resources` directory as well: + +```txt +my-site/ +├── archetypes/ +│ └── default.md +├── assets/ +├── config/ +│ └── _default/ +│ └── hugo.toml +├── content/ +├── data/ +├── i18n/ +├── layouts/ +├── public/ <-- created when you build your site +├── resources/ <-- created when you build your site +├── static/ +└── themes/ +``` + +## Directories + +Each of the subdirectories contributes to the content, structure, behavior, or presentation of your site. + +archetypes +: The `archetypes` directory contains templates for new content. See [details](/content-management/archetypes/). + +assets +: The `assets` directory contains global resources typically passed through an asset pipeline. This includes resources such as images, CSS, Sass, JavaScript, and TypeScript. See [details](/hugo-pipes/introduction/). + +config +: The `config` directory contains your site configuration, possibly split into multiple subdirectories and files. For projects with minimal configuration or projects that do not need to behave differently in different environments, a single configuration file named `hugo.toml` in the root of the project is sufficient. See [details](/getting-started/configuration/#configuration-directory). + +content +: The `content` directory contains the markup files (typically markdown) and page resources that comprise the content of your site. See [details](/content-management/organization/). + +data +: The `data` directory contains data files (JSON, TOML, YAML, or XML) that augment content, configuration, localization, and navigation. See [details](/templates/data-templates/). + +i18n +: The `i18n` directory contains translation tables for multilingual sites. See [details](/content-management/multilingual/). + +layouts +: The layouts directory contains templates to transform content, data, and resources into a complete website. See [details](/templates/). + +public +: The `public` directory contains the published website, generated when you run the `hugo` command. Hugo recreates this directory and its content as needed. See [details](/getting-started/usage/#build-your-site). + +resources +: The `resources` directory contains cached output from Hugo's asset pipelines, generated when you run the `hugo` or `hugo server` commands. By default this cache directory includes CSS and images. Hugo recreates this directory and its content as needed. + +static +: The `static` directory contains files that will be copied to the public directory when you build your site. For example: `favicon.ico`, `robots.txt`, and files that verify site ownership. Before the introduction of [page bundles](/getting-started/glossary/#page-bundle) and [asset pipelines](/hugo-pipes/introduction/), the `static` directory was also used for images, CSS, and JavaScript. See [details](/content-management/static-files/). + +themes +: The `themes` directory contains one or more [themes](/getting-started/glossary/#theme), each in its own subdirectory. + +## Union file system + +Hugo creates a union file system, allowing you to mount two or more directories to the same location. For example, let's say your home directory contains a Hugo project in one directory, and shared content in another: + +```text +home/ +└── user/ + ├── my-site/ + │ ├── content/ + │ │ ├── books/ + │ │ │ ├── _index.md + │ │ │ ├── book-1.md + │ │ │ └── book-2.md + │ │ └── _index.md + │ ├── themes/ + │ │ └── my-theme/ + │ └── hugo.toml + └── shared-content/ + └── films/ + ├── _index.md + ├── film-1.md + └── film-2.md +``` + +You can include the shared content when you build your site using mounts. In your site configuration: + +{{< code-toggle file=hugo >}} +[[module.mounts]] +source = 'content' +target = 'content' + +[[module.mounts]] +source = '/home/user/shared-content' +target = 'content' +{{< /code-toggle >}} + +{{% note %}} +When you overlay one directory on top of another, you must mount both directories. + +If you think you need a symbolic link in your project directory, use Hugo's union file system instead. +{{% /note %}} + +After mounting, the union file system has this structure: + +```text +home/ +└── user/ + └── my-site/ + ├── content/ + │ ├── books/ + │ │ ├── _index.md + │ │ ├── book-1.md + │ │ └── book-2.md + │ ├── films/ + │ │ ├── _index.md + │ │ ├── film-1.md + │ │ └── film-2.md + │ └── _index.md + ├── themes/ + │ └── my-theme/ + └── hugo.toml +``` + +{{% note %}} +When two or more files have the same path, the order of precedence follows the order of the mounts. For example, if the shared content directory contains `books/book-1.md`, it will be ignored because the project's content directory was mounted first. +{{% /note %}} + +You can mount directories to `archetypes`, `assets`, `content`, `data`, `i18n`, `layouts`, and `static`. See [details](/hugo-modules/configuration/#module-configuration-mounts). + +You can also mount directories from Git repositories using Hugo Modules. See [details](/hugo-modules/). + +## Theme skeleton + +Hugo generates a functional theme skeleton when you create a new theme. For example, this command: + +```text +hugo new theme my-theme +``` + +Creates this directory structure (subdirectories not shown): + +```text +my-theme/ +├── archetypes/ +├── assets/ +├── content/ +├── data/ +├── i18n/ +├── layouts/ +├── static/ +├── LICENSE +├── README.md +├── hugo.toml +└── theme.toml +``` + +Using the union file system described above, Hugo mounts each of these directories to the corresponding location in the project. When two files have the same path, the file in the project directory takes precedence. This allows you, for example, to override a theme's template by placing a copy in the same location within the project directory. + +If you are simultaneously using components from two or more themes or modules, and there's a path collision, the first mount takes precedence. diff --git a/docs/content/en/getting-started/external-learning-resources/hia.jpg b/docs/content/en/getting-started/external-learning-resources/hia.jpg Binary files differnew file mode 100644 index 000000000..601947a70 --- /dev/null +++ b/docs/content/en/getting-started/external-learning-resources/hia.jpg diff --git a/docs/content/en/getting-started/external-learning-resources/index.md b/docs/content/en/getting-started/external-learning-resources/index.md new file mode 100644 index 000000000..634439bc6 --- /dev/null +++ b/docs/content/en/getting-started/external-learning-resources/index.md @@ -0,0 +1,37 @@ +--- +title: External learning resources +description: A list of tutorials and books on Hugo. +categories: [getting started] +keywords: [books, tutorials, learning, usage] +menu: + docs: + parent: getting-started + weight: 70 +weight: 70 +--- + +## Books + +### Hugo In Action + +[](https://www.manning.com/books/hugo-in-action) + +Hugo in Action is a step-by-step guide to using Hugo to create static websites. Working with a complete example website and source code samples, you’ll learn how to build and host a low-maintenance, high-performance site that will wow your users and stay stable without relying on a third-party server. + +[Hugo In Action Home Page](https://www.manning.com/books/hugo-in-action) + +### Build Websites with Hugo + +[Build Websites with Hugo - Fast Web Development with Markdown (2020)](https://pragprog.com/titles/bhhugo/) by Brian P. Hogan. + +## Beginner tutorials + +### Hugo tutorial by CloudCannon + +[Step-by-step written tutorial](https://cloudcannon.com/community/learn/hugo-beginner-tutorial/) to teach you the basics of creating a Hugo site. + +## Video tutorials + +* Mike Dane explains the various features of Hugo via dedicated tutorials on [YouTube](https://www.youtube.com/watch?list=PLLAZ4kZ9dFpOnyRlyS-liKL5ReHDcj4G3&v=qtIqKaDlqXo). + +* [Introduction to building your first Hugo site](https://cloudcannon.com/community/learn/hugo-beginner-tutorial/) by Mike Neumegen. diff --git a/docs/content/en/getting-started/glossary.md b/docs/content/en/getting-started/glossary.md new file mode 100644 index 000000000..929feb542 --- /dev/null +++ b/docs/content/en/getting-started/glossary.md @@ -0,0 +1,389 @@ +--- +title: Glossary of terms +description: Terms commonly used throughout the documentation. +categories: [getting started] +keywords: [glossary] +menu: + docs: + parent: getting-started + weight: 60 +weight: 60 +# Use level 6 headings for each term in the glossary. +--- + +###### action + +See [template action](#template-action). + +###### archetype + +A template for new content. See [details](/content-management/archetypes/). + +###### argument + +A [scalar](#scalar), [array](#array), [slice](#slice), [map](#map), or [object](#object) passed to a [function](#function), [method](#method), or [shortcode](#shortcode). + +###### array + +A numbered sequence of elements. Unlike Go's [slice](#slice) data type, an array has a fixed length. [Elements](#element) within an array can be [scalars](#scalar), slices, [maps](#map), pages, or other arrays. See the [Go documentation](https://go.dev/ref/spec#Array_types) for details. + +###### bool + +See [boolean](#boolean). + +###### boolean + +A data type with two possible values, either `true` or `false`. + +###### branch bundle + +A [page bundle](#page-bundle) with an _index.md file and zero or more [resources](#resource). Analogous to a physical branch, a branch bundle may have descendants including regular pages, [leaf bundles](/getting-started/glossary/#leaf-bundle), and other branch bundles. See [details](/content-management/page-bundles/). + +###### build + +To generate a static site that includes HTML files and assets such as images, CSS, and JavaScript. The build process includes rendering and resource transformations. + +###### bundle + +See [page bundle](#page-bundle). + +###### cache + +A software component that stores data so that future requests for the same data are faster. + +###### chain + +Within a template, to connect one or more [identifiers](#identifier) with a dot. An identifier can represent a method, object, or field. For example, `.Site.Params.author.name` or `.Date.UTC.Hour`. + +###### collection + +An [array](#array), [slice](#slice), or [map](#map). + +###### content format + +A markup language for creating content. Typically markdown, but may also be HTML, AsciiDoc, Org, Pandoc, or reStructuredText. See [details](/content-management/formats/). + +###### content type + +A classification of content inferred from the top-level directory name or the `type` set in [front matter](#front-matter). Pages in the root of the content directory, including the home page, are of type "page". Accessed via `.Page.Type` in [templates](#template). See [details](/content-management/types/). + +###### content view + +A template called with the `.Page.Render` method. See [details](/templates/views/). + +###### context + +Represented by a dot "." within a [template action](#template-action), context is the current location in a data structure. For example, while iterating over a [collection](#collection) of pages, the context within each iteration is the page's data structure. The context received by each template depends on template type and/or how it was called. See [details](/templates/introduction/#the-dot). + +###### default sort order + +The default sort order for page collections. Hugo sorts by [weight](#weight), then by date (descending), then by link title, and then by file path. + +###### element + +A member of a slice or array. + +###### environment + +Typically one of `development`, `staging`, or `production`, each environment may exhibit different behavior depending on configuration and template logic. For example, in a production environment you might minify and fingerprint CSS, but that probably doesn't make sense in a development environment. + +When running the built-in development server with the `hugo server` command, the environment is set to `development`. When building your site with the `hugo` command, the environment is set to `production`. To override the environment value, use the `--environment` command line flag. + +To determine the current environment within a template, use the [`hugo.Environment`] function. + +[`hugo.Environment`]: /functions/hugo/environment + +###### field + +A predefined key/value pair in front matter such as `date` or `title`. See also [parameter](#parameter). + + +###### flag + +An option passed to a command-line program, beginning with one or two hyphens. See [details](/commands/hugo/). + +###### float + +See [floating point](#floating-point). + +###### floating point + +A numeric data type with a fractional component. For example, `3.14159`. + +###### fragment + +The final segment of a URL, beginning with a hash (`#`) mark, that references an `id` attribute of an HTML element on the page. + +###### front matter + +Metadata at the beginning of each content page, separated from the content by format-specific delimiters. See [details](/content-management/front-matter/). + +###### function + +Used within a [template action](#template-action), a function takes one or more [arguments](#argument) and returns a value. Unlike [methods](#method), functions are not associated with an [object](#object). See [details](/functions/). + +###### global resource + +A file within the assets directory, or within any directory [mounted](/hugo-modules/configuration/#module-configuration-mounts) to the assets directory. Capture one or more global resources using the [`resources.Get`], [`resources.GetMatch`], [`resources.Match`], or [`resources.ByType`] functions. + +[`resources.Get`]: /functions/resources/get +[`resources.GetMatch`]: /functions/resources/getmatch +[`resources.Match`]: /functions/resources/match +[`resources.ByType`]: /functions/resources/byType + +###### identifier + +A string that represents a variable, method, object, or field. It must conform to Go's [language specification](https://go.dev/ref/spec#Identifiers), beginning with a letter or underscore, followed by zero or more letters, digits, or underscores. + +###### int + +See [integer](#integer). + +###### integer + +A numeric data type without a fractional component. For example, `42`. + +###### internationalization + +Software design and development efforts that enable [localization](#localization). See the [W3C definition](https://www.w3.org/International/questions/qa-i18n). Abbreviated i18n. + +###### interval + +An [interval](https://en.wikipedia.org/wiki/Interval_(mathematics)) is a range of numbers between two endpoints: closed, open, or half-open. + +- A _closed_ interval, denoted by brackets, includes its endpoints. For example, [0, 1] is the interval where `0 <= x <= 1`. + +- An _open_ interval, denoted by parentheses, excludes its endpoints. For example, (0, 1) is the interval where `0 < x < 1`. + +- A _half-open_ interval includes only one of its endpoints. For example, (0, 1] is the _left-open_ interval where `0 < x <= 1`, while [0, 1) is the _right-open_ interval where `0 <= x < 1`. + +###### kind + +See [page kind](#page-kind). + +###### layout + +See [template](#template). + +###### leaf bundle + +A [page bundle](#page-bundle) with an index.md file and zero or more [resources](#resource). Analogous to a physical leaf, a leaf bundle is at the end of a branch. Hugo ignores content (but not resources) beneath the leaf bundle. See [details](/content-management/page-bundles/). + +###### list page + +Any [page kind](#page-kind) that receives a page [collection](#collection) in [context](#context). This includes the home page, [section pages](#section-page), [taxonomy pages](#taxonomy-page), and [term pages](#term-page). + +###### localization + +Adaptation of a site to meet language and regional requirements. This includes translations, language-specific media, date and currency formats, etc. See [details](/content-management/multilingual/) and the [W3C definition](https://www.w3.org/International/questions/qa-i18n). Abbreviated l10n. + +###### map + +An unordered group of elements, each indexed by a unique key. See the [Go documentation](https://go.dev/ref/spec#Map_types) for details. + +###### markdown attribute + +A list of attributes, containing one or more key/value pairs, separated by spaces or commas, and wrapped by braces. Apply markdown attributes to images and block-level elements including blockquotes, fenced code blocks, headings, horizontal rules, lists, paragraphs, and tables. See [details](/getting-started/configuration-markup/#goldmark). + +###### marshal + +To transform a data structure into a serialized object. For example, transforming a [map](#map) into a JSON string. See [unmarshal](#unmarshal). + +###### method + +Used within a [template action](#template-action) and associated with an [object](#object), a method takes zero or more [arguments](#argument) and either returns a value or performs an action. For example, `.IsHome` is a method on the `.Page` object which returns `true` if the current page is the home page. See also [function](#function). + +###### module + +Like a [theme](#theme), a module is a packaged combination of [archetypes](#archetype), assets, content, data, [templates](#template), translation tables, static files, or configuration settings. A module may serve as the basis for a new site, or to augment an existing site. See [details](/hugo-modules/). + +###### object + +A data structure with or without associated [methods](#method). + +###### ordered taxonomy + +Created by invoking the [`Alphabetical`] or [`ByCount`] method on a [taxonomy object](#taxonomy-object), which is a [map](#map), an ordered taxonomy is a [slice](#slice), where each element is an object that contains the [term](#term) and a slice of its [weighted pages](#weighted-page). + +[`Alphabetical`]: /methods/taxonomy/alphabetical +[`ByCount`]: /methods/taxonomy/bycount + +###### output format + +{{% include "methods/page/_common/output-format-definition.md" %}} + +###### page bundle + +A directory that encapsulates both content and associated [resources](#resource). There are two types of page bundles: [leaf bundles](#leaf-bundle) and [branch bundles](#branch-bundle). See [details](/content-management/page-bundles/). + +###### page collection + +A slice of page objects. + +###### page kind + +A classification of pages, one of `home`, `page`, `section`, `taxonomy`, or `term`. See [details](/templates/section-templates/#page-kinds). + +Note that there are also `RSS`, `sitemap`, `robotsTXT`, and `404` page kinds, but these are only available during the rendering of each of these respective page's kind and therefore *not* available in any of the `Pages` collections. + +###### page resource + +A file within a [page bundle](#page-bundle). Capture one or more page resources using any of the [`Resources`] methods on a `Page` object. + +[`Resources`]: /methods/page/resources/#methods + +###### pager + +Created during [pagination](#pagination), a pager contains a subset of a section list, and navigation links to other pagers. + +###### paginate + +To split a [section](#section) list into two or more [pagers](#pager) See [details](/templates/pagination/). + +###### pagination + +The process of [paginating](#paginate) a [section](#section) list. + +###### parameter + +Typically, a user-defined key/value pair at the site or page level, but may also refer to a configuration setting or an [argument](#argument). See also [field](#field). + +###### partial + +A [template](#template) called from any other template including [shortcodes](#shortcode), [render hooks](#render-hook), and other partials. A partial either renders something or returns something. A partial can also call itself, for example, to [walk](#walk) a data structure. + +###### permalink + +The absolute URL of a published resource or a rendered page, including scheme and host. + +###### pipe + +See [pipeline](#pipeline). + +###### pipeline + +Within a [template action](#template-action), a pipeline is a possibly chained sequence of values, [function](#function) calls, or [method](#method) calls. Functions and methods in the pipeline may take multiple [arguments](#argument). + +A pipeline may be *chained* by separating a sequence of commands with pipeline characters "|". In a chained pipeline, the result of each command is passed as the last argument to the following command. The output of the final command in the pipeline is the value of the pipeline. See the [Go documentation](https://pkg.go.dev/text/template#hdr-Pipelines) for details. + +###### publish + +See [build](#build). + +###### regular page + +Content with the "page" [page kind](#page-kind). See also [section page](#section-page). + +###### relative permalink + +The host-relative URL of a published resource or a rendered page. + +###### render hook + +A [template](#template) that overrides standard markdown rendering. See [details](/templates/render-hooks/). + +###### remote resource + +A file on a remote server, accessible via HTTP or HTTPS with the [`resources.GetRemote`](/functions/resources/getremote) function. + +###### resource + +Any file consumed by the build process to augment or generate content, structure, behavior, or presentation. For example: images, videos, content snippets, CSS, Sass, JavaScript, and data. + +Hugo supports three types of resources: [global](#global-resource), [page](#page-resource), and [remote](#remote-resource) + +###### scalar + +A single value, one of [string](#string), [integer](#integer), [floating point](#floating-point), or [boolean](#boolean). + +###### scratch pad + +Conceptually, a [map](#map) with [methods](#method) to set, get, update, and delete values. Attach the data structure to a `Page` object using the [`Scratch`] or [`Store`] methods, or created a locally scoped scratch pad using the [`newScratch`] function. + +[`Scratch`]: /methods/page/scratch +[`Store`]: /methods/page/store +[`newScratch`]: /functions/collections/newscratch + +###### section + +A top-level content directory, or any content directory with an _index.md file. A content directory with an _index.md file is also known as a [branch bundle](/getting-started/glossary/#branch-bundle). Section templates receive one or more page [collections](#collection) in [context](#context). See [details](/content-management/sections/). + +###### section page + +Content with the "section" [page kind](#page-kind). Typically a listing of [regular pages](#regular-page) and/or [section pages](#section-page) within the current [section](#section). See also [regular page](#regular-page). + +###### shortcode + +A [template](#template) called from within markdown, taking zero or more [arguments](#argument). See [details](/content-management/shortcodes/). + +###### slice + +A numbered sequence of elements. Unlike Go's [array](#array) data type, slices are dynamically sized. [Elements](#element) within a slice can be [scalars](#scalar), [arrays](#array), [maps](#map), pages, or other slices. See the [Go documentation](https://go.dev/ref/spec#Slice_types) for details. + +###### string + +A sequence of bytes. For example, `"What is 6 times 7?"` . + +###### taxonomic weight + +Defined in front matter and unique to each taxonomy, this [weight](#weight) determines the sort order of page collections contained within a [taxonomy object](#taxonomy-object). See [details](/templates/taxonomy-templates/#assign-weight). + +###### taxonomy + +A group of related [terms](#term) used to classify content. For example, a "colors" taxonomy might include the terms "red", "green", and "blue". See [details](/content-management/taxonomies/). + +###### taxonomy object + +A [map](#map) of [terms](#term) and the [weighted pages](#weighted-page) associated with each term. + +###### taxonomy page + +Content with the "taxonomy" [page kind](#page-kind). Typically a listing of [terms](#term) within a given [taxonomy](#taxonomy). + +###### template + +A file with [template actions](#template-action), located within the layouts directory of a project, theme, or module. See [details](/templates/). + +###### template action + +A data evaluation or control structure within a [template](#template), delimited by "{{" and "}}". See the [Go documentation](https://pkg.go.dev/text/template#hdr-Actions) for details. + +###### term + +A member of a [taxonomy](#taxonomy), used to classify content. See [details](/content-management/taxonomies/). + +###### term page + +Content with the "term" [page kind](#page-kind). Typically a listing of [regular pages](#regular-page) and [section pages](#section-page) with a given [term](#term). + +###### theme + +A packaged combination of [archetypes](#archetype), assets, content, data, [templates](#template), translation tables, static files, or configuration settings. A theme may serve as the basis for a new site, or to augment an existing site. See also [module](#module). + +###### token + +An identifier within a format string, beginning with a colon and replaced with a value when rendered. For example, use tokens in format strings for both [permalinks](/content-management/urls/#permalinks) and [dates](/functions/time/format/#localization). + +###### type + +See [content type](#content-type). + +###### unmarshal + +To transform a serialized object into a data structure. For example, transforming a JSON file into a [map](#map) that you can access within a template. See [marshal](#marshal). + +###### variable + +A user-defined [identifier](#identifier) prefaced with a `$` symbol, representing a value of any data type, initialized or assigned within a [template action](#template-action). For example, `$foo` and `$bar` are variables. + +###### walk + +To recursively traverse a nested data structure. For example, rendering a multilevel menu. + +###### weight + +Used to position an element within a collection sorted by weight. Assign weights using non-zero integers. Lighter items float to the top, while heavier items sink to the bottom. Unweighted or zero-weighted elements are placed at the end of the collection. Weights are typically assigned to pages, menu entries, languages, and output formats. + +###### weighted page + +Contained within a [taxonomy object](#taxonomy-object), a weighted page is a [map](#map) with two elements: a `Page` object, and its [taxonomic weight](#taxonomic-weight) as defined in front matter. Access the elements using the `Page` and `Weight` keys. diff --git a/docs/content/en/getting-started/quick-start.md b/docs/content/en/getting-started/quick-start.md new file mode 100644 index 000000000..a6c54b54c --- /dev/null +++ b/docs/content/en/getting-started/quick-start.md @@ -0,0 +1,232 @@ +--- +title: Quick start +description: Learn to create a Hugo site in minutes. +categories: [getting started] +keywords: [quick start,usage] +menu: + docs: + parent: getting-started + weight: 20 +weight: 20 +toc: true +aliases: [/quickstart/,/overview/quickstart/] +minVersion: v0.112.0 +--- + +In this tutorial you will: + +1. Create a site +2. Add content +3. Configure the site +4. Publish the site + +## Prerequisites + +Before you begin this tutorial you must: + +1. [Install Hugo] (extended edition, {{% param "minVersion" %}} or later) +1. [Install Git] + +You must also be comfortable working from the command line. + +## Create a site + +### Commands + +{{% note %}} +**If you are a Windows user:** + +- Do not use the Command Prompt +- Do not use Windows PowerShell +- Run these commands from [PowerShell] or a Linux terminal such as WSL or Git Bash + +PowerShell and Windows PowerShell [are different applications]. + +[PowerShell]: https://learn.microsoft.com/en-us/powershell/scripting/install/installing-powershell-on-windows +[are different applications]: https://learn.microsoft.com/en-us/powershell/scripting/whats-new/differences-from-windows-powershell?view=powershell-7.3 +{{% /note %}} + +Verify that you have installed Hugo {{% param "minVersion" %}} or later. + +```text +hugo version +``` + +Run these commands to create a Hugo site with the [Ananke] theme. The next section provides an explanation of each command. + +```text +hugo new site quickstart +cd quickstart +git init +git submodule add https://github.com/theNewDynamic/gohugo-theme-ananke.git themes/ananke +echo "theme = 'ananke'" >> hugo.toml +hugo server +``` + +View your site at the URL displayed in your terminal. Press `Ctrl + C` to stop Hugo's development server. + +### Explanation of commands + +Create the [directory structure] for your project in the `quickstart` directory. + +```text +hugo new site quickstart +``` + +Change the current directory to the root of your project. + +```text +cd quickstart +``` + +Initialize an empty Git repository in the current directory. + +```text +git init +``` + +Clone the [Ananke] theme into the `themes` directory, adding it to your project as a [Git submodule]. + +```text +git submodule add https://github.com/theNewDynamic/gohugo-theme-ananke.git themes/ananke +``` + +Append a line to the site configuration file, indicating the current theme. + +```text +echo "theme = 'ananke'" >> hugo.toml +``` + +Start Hugo's development server to view the site. + +```text +hugo server +``` + +Press `Ctrl + C` to stop Hugo's development server. + +## Add content + +Add a new page to your site. + +```text +hugo new content posts/my-first-post.md +``` + +Hugo created the file in the `content/posts` directory. Open the file with your editor. + +```text ++++ +title = 'My First Post' +date = 2024-01-14T07:07:07+01:00 +draft = true ++++ +``` + +Notice the `draft` value in the [front matter] is `true`. By default, Hugo does not publish draft content when you build the site. Learn more about [draft, future, and expired content]. + +Add some [markdown] to the body of the post, but do not change the `draft` value. + +[markdown]: https://commonmark.org/help/ + +```text ++++ +title = 'My First Post' +date = 2024-01-14T07:07:07+01:00 +draft = true ++++ +## Introduction + +This is **bold** text, and this is *emphasized* text. + +Visit the [Hugo](https://gohugo.io) website! +``` + +Save the file, then start Hugo’s development server to view the site. You can run either of the following commands to include draft content. + +```text +hugo server --buildDrafts +hugo server -D +``` + +View your site at the URL displayed in your terminal. Keep the development server running as you continue to add and change content. + +{{% note %}} +Hugo's rendering engine conforms to the CommonMark [specification] for markdown. The CommonMark organization provides a useful [live testing tool] powered by the reference implementation. + +[live testing tool]: https://spec.commonmark.org/dingus/ +[specification]: https://spec.commonmark.org/ +{{% /note %}} + +## Configure the site + +With your editor, open the [site configuration] file (`hugo.toml`) in the root of your project. + +```text +baseURL = 'https://example.org/' +languageCode = 'en-us' +title = 'My New Hugo Site' +theme = 'ananke' +``` + +Make the following changes: + +1. Set the `baseURL` for your production site. This value must begin with the protocol and end with a slash, as shown above. + +2. Set the `languageCode` to your language and region. + +3. Set the `title` for your production site. + +Start Hugo's development server to see your changes, remembering to include draft content. + +```text +hugo server -D +``` + +{{% note %}} +Most theme authors provide configuration guidelines and options. Make sure to visit your theme's repository or documentation site for details. + +[The New Dynamic], authors of the Ananke theme, provide [documentation] for configuration and usage. They also provide a [demonstration site]. + +[demonstration site]: https://gohugo-ananke-theme-demo.netlify.app/ +[documentation]: https://github.com/theNewDynamic/gohugo-theme-ananke#readme +[The New Dynamic]: https://www.thenewdynamic.com/ +{{% /note %}} + +## Publish the site + +In this step you will _publish_ your site, but you will not _deploy_ it. + +When you _publish_ your site, Hugo creates the entire static site in the `public` directory in the root of your project. This includes the HTML files, and assets such as images, CSS files, and JavaScript files. + +When you publish your site, you typically do _not_ want to include [draft, future, or expired content]. The command is simple. + +```text +hugo +``` + +To learn how to _deploy_ your site, see the [hosting and deployment] section. + +## Ask for help + +Hugo's [forum] is an active community of users and developers who answer questions, share knowledge, and provide examples. A quick search of over 20,000 topics will often answer your question. Please be sure to read about [requesting help] before asking your first question. + +## Other resources + +For other resources to help you learn Hugo, including books and video tutorials, see the [external learning resources](/getting-started/external-learning-resources/) page. + +[Ananke]: https://github.com/theNewDynamic/gohugo-theme-ananke +[directory structure]: /getting-started/directory-structure +[draft, future, and expired content]: /getting-started/usage/#draft-future-and-expired-content +[draft, future, or expired content]: /getting-started/usage/#draft-future-and-expired-content +[external learning resources]:/getting-started/external-learning-resources/ +[forum]: https://discourse.gohugo.io/ +[forum]: https://discourse.gohugo.io/ +[front matter]: /content-management/front-matter +[Git submodule]: https://git-scm.com/book/en/v2/Git-Tools-Submodules +[hosting and deployment]: /hosting-and-deployment/ +[Install Git]: https://git-scm.com/book/en/v2/Getting-Started-Installing-Git +[Install Hugo]: /installation/ +[Requesting Help]: https://discourse.gohugo.io/t/requesting-help/9132 +[Requesting Help]: https://discourse.gohugo.io/t/requesting-help/9132 +[site configuration]: /getting-started/configuration/ diff --git a/docs/content/en/getting-started/usage.md b/docs/content/en/getting-started/usage.md new file mode 100644 index 000000000..268aed2e4 --- /dev/null +++ b/docs/content/en/getting-started/usage.md @@ -0,0 +1,169 @@ +--- +title: Basic usage +description: Hugo's command line interface (CLI) is fully featured but simple to use, even for those with limited experience working from the command line. +categories: [getting started] +keywords: [usage,livereload,command,flags] +menu: + docs: + parent: getting-started + weight: 30 +weight: 30 +toc: true +aliases: [/overview/usage/,/extras/livereload/,/doc/usage/,/usage/] +--- + +## Test your installation + +After [installing] Hugo, test your installation by running: + +```sh +hugo version +``` + +You should see something like: + +```text +hugo v0.122.0-b9a03bd59d5f71a529acb3e33f995e0ef332b3aa+extended linux/amd64 BuildDate=2024-01-26T15:54:24Z VendorInfo=gohugoio +``` + +## Display available commands + +To see a list of the available commands and flags: + +```sh +hugo help +``` + +To get help with a subcommand, use the `--help` flag. For example: + +```sh +hugo server --help +``` + +## Build your site + +To build your site, `cd` into your project directory and run: + +```sh +hugo +``` + +The [`hugo`] command builds your site, publishing the files to the `public` directory. To publish your site to a different directory, use the [`--destination`] flag or set [`publishDir`] in your site configuration. + +{{% note %}} +Hugo does not clear the `public` directory before building your site. Existing files are overwritten, but not deleted. This behavior is intentional to prevent the inadvertent removal of files that you may have added to the `public` directory after the build. + +Depending on your needs, you may wish to manually clear the contents of the public directory before every build. +{{% /note %}} + +## Draft, future, and expired content + +Hugo allows you to set `draft`, `date`, `publishDate`, and `expiryDate` in the [front matter] of your content. By default, Hugo will not publish content when: + +- The `draft` value is `true` +- The `date` is in the future +- The `publishDate` is in the future +- The `expiryDate` is in the past + +You can override the default behavior when running `hugo` or `hugo server` with command line flags: + +```sh +hugo --buildDrafts # or -D +hugo --buildExpired # or -E +hugo --buildFuture # or -F +``` + +Although you can also set these values in your site configuration, it can lead to unwanted results unless all content authors are aware of, and understand, the settings. + +{{% note %}} +As noted above, Hugo does not clear the `public` directory before building your site. Depending on the _current_ evaluation of the four conditions above, after the build your `public` directory may contain extraneous files from a previous build. + +A common practice is to manually clear the contents of the `public` directory before each build to remove draft, expired, and future content. +{{% /note %}} + +## Develop and test your site + +To view your site while developing layouts or creating content, `cd` into your project directory and run: + +```sh +hugo server +``` + +The [`hugo server`] command builds your site into memory, and serves your pages using a minimal HTTP server. When you run `hugo server` it will display the URL of your local site: + +```text +Web Server is available at http://localhost:1313/ +``` + +While the server is running, it watches your project directory for changes to assets, configuration, content, data, layouts, translations, and static files. When it detects a change, the server rebuilds your site and refreshes your browser using [LiveReload]. + +Most Hugo builds are so fast that you may not notice the change unless you are looking directly at your browser. + +### LiveReload + +While the server is running, Hugo injects JavaScript into the generated HTML pages. The LiveReload script creates a connection from the browser to the server via web sockets. You do not need to install any software or browser plugins, nor is any configuration required. + +### Automatic redirection + +When editing content, if you want your browser to automatically redirect to the page you last modified, run: + +```sh +hugo server --navigateToChanged +``` + +## Deploy your site + +{{% note %}} +As noted above, Hugo does not clear the public directory before building your site. Manually clear the contents of the public directory before each build to remove draft, expired, and future content. +{{% /note %}} + +When you are ready to deploy your site, run: + +```sh +hugo +``` + +This builds your site, publishing the files to the public directory. The directory structure will look something like this: + +```text +public/ +├── categories/ +│ ├── index.html +│ └── index.xml <-- RSS feed for this section +├── post/ +│ ├── my-first-post/ +│ │ └── index.html +│ ├── index.html +│ └── index.xml <-- RSS feed for this section +├── tags/ +│ ├── index.html +│ └── index.xml <-- RSS feed for this section +├── index.html +├── index.xml <-- RSS feed for the site +└── sitemap.xml +``` + +In a simple hosting environment, where you typically `ftp`, `rsync`, or `scp` your files to the root of a virtual host, the contents of the `public` directory are all that you need. + +Most of our users deploy their sites using a CI/CD workflow, where a push[^1] to their GitHub or GitLab repository triggers a build and deployment. Popular providers include [AWS Amplify], [CloudCannon], [Cloudflare Pages], [GitHub Pages], [GitLab Pages], and [Netlify]. + +Learn more in the [hosting and deployment] section. + +[^1]: The Git repository contains the entire project directory, typically excluding the public directory because the site is built _after_ the push. + +[`--destination`]: /commands/hugo/#options +[`hugo server`]: /commands/hugo_server/ +[`hugo`]: /commands/hugo/ +[`publishDir`]: /getting-started/configuration/#publishdir +[AWS Amplify]: https://aws.amazon.com/amplify/ +[CloudCannon]: https://cloudcannon.com/ +[Cloudflare Pages]: https://pages.cloudflare.com/ +[commands]: /commands/ +[front matter]: /content-management/front-matter/ +[GitHub Pages]: https://pages.github.com/ +[GitLab Pages]: https://docs.gitlab.com/ee/user/project/pages/ +[hosting and deployment]: /hosting-and-deployment/ +[hosting]: /hosting-and-deployment/ +[installing]: /installation/ +[LiveReload]: https://github.com/livereload/livereload-js +[Netlify]: https://www.netlify.com/ diff --git a/docs/content/en/hosting-and-deployment/_index.md b/docs/content/en/hosting-and-deployment/_index.md new file mode 100644 index 000000000..35fd3cf05 --- /dev/null +++ b/docs/content/en/hosting-and-deployment/_index.md @@ -0,0 +1,15 @@ +--- +title: Hosting and deployment +linkTitle: Overview +description: Site builds, automated deployments, and popular hosting solutions. +categories: [] +keywords: [] +menu: + docs: + identifier: hosting-and-deployment-overview + parent: hosting-and-deployment + weight: 1 +weight: 1 +--- + +Because Hugo renders *static* websites, you can host your new Hugo website virtually anywhere. The following represent only a few of the more popular hosting and automated deployment solutions used by the Hugo community. diff --git a/docs/content/en/hosting-and-deployment/deployment-with-rclone.md b/docs/content/en/hosting-and-deployment/deployment-with-rclone.md new file mode 100644 index 000000000..410851553 --- /dev/null +++ b/docs/content/en/hosting-and-deployment/deployment-with-rclone.md @@ -0,0 +1,47 @@ +--- +title: Deploy with Rclone +description: If you have access to your web host with SFTP/FTP/SSH/HTTP(DAV), you can use rclone to incrementally deploy your entire Hugo website. +categories: [hosting and deployment] +keywords: [deployment,rclone,sftp] +menu: + docs: + parent: hosting-and-deployment +toc: true +aliases: [/tutorials/deployment-with-rclone/] +--- + +## Assumptions + +* A web host running a web server. This could be a shared hosting environment or a VPS. +* Access to your web host with any of the [protocols supported by rclone](https://rclone.org/#providers), such as SFTP. +* A functional static website built with Hugo +* Deploying from an [Rclone](https://rclone.org) compatible operating system +* You have [installed Rclone](https://rclone.org/install/). + +**NB**: You can remove ``--interactive`` in the commands below once you are comfortable with rclone, if you wish. Also, ``--gc`` and ``--minify`` are optional in the ``hugo`` commands below. + +## Getting started + +The spoiler is that you can even deploy your entire website from any compatible OS with no configuration. Using SFTP for example: + +```txt +hugo --gc --minify +rclone sync --interactive --sftp-host sftp.example.com --sftp-user www-data --sftp-ask-password public/ :sftp:www/ +``` + +## Configure Rclone for even easier usage + +The easiest way is simply to run `rclone config`. + +The [Rclone docs](https://rclone.org/docs/) provide [an example of configuring Rclone to use SFTP](https://rclone.org/sftp/). + +For the next commands, we will assume you configured a remote you named ``hugo-www`` + +The above 'spoiler' commands could become: + +```txt +hugo --gc --minify +rclone sync --interactive public/ hugo-www:www/ +``` + +After you issue the above commands (and respond to any prompts), check your website and you will see that it is deployed. diff --git a/docs/content/en/hosting-and-deployment/deployment-with-rsync.md b/docs/content/en/hosting-and-deployment/deployment-with-rsync.md new file mode 100644 index 000000000..f341ad618 --- /dev/null +++ b/docs/content/en/hosting-and-deployment/deployment-with-rsync.md @@ -0,0 +1,139 @@ +--- +title: Deploy with Rsync +description: If you have access to your web host with SSH, you can use a simple rsync one-liner to incrementally deploy your entire Hugo website. +categories: [hosting and deployment] +keywords: [deployment,rsync] +menu: + docs: + parent: hosting-and-deployment +toc: true +aliases: [/tutorials/deployment-with-rsync/] +--- + +## Assumptions + +* A web host running a web server. This could be a shared hosting environment or a VPS. +* Access to your web host with SSH +* A functional static website built with Hugo + +The spoiler is that you can deploy your entire website with a command that looks like the following: + +```txt +hugo && rsync -avz --delete public/ www-data@ftp.topologix.fr:~/www/ +``` + +As you will see, we'll put this command in a shell script file, which makes building and deployment as easy as executing `./deploy`. + +## Copy Your SSH Key to your host + +To make logging in to your server more secure and less interactive, you can upload your SSH key. If you have already installed your SSH key to your server, you can move on to the next section. + +First, install the ssh client. On Debian distributions, use the following command: + +{{< code file=install-openssh.sh >}} +sudo apt-get install openssh-client +{{< /code >}} + +Then generate your ssh key. First, create the `.ssh` directory in your home directory if it doesn't exist: + +```txt +~$ cd && mkdir .ssh & cd .ssh +``` + +Next, execute this command to generate a new keypair called `rsa_id`: + +```txt +~/.ssh/$ ssh-keygen -t rsa -q -C "For SSH" -f rsa_id +``` + +You'll be prompted for a passphrase, which is an extra layer of protection. Enter the passphrase you'd like to use, and then enter it again when prompted, or leave it blank if you don't want to have a passphrase. Not using a passphrase will let you transfer files non-interactively, as you won't be prompted for a password when you log in, but it is slightly less secure. + +To make logging in easier, add a definition for your web host to the file `~/.ssh/config` with the following command, replacing `HOST` with the IP address or hostname of your web host, and `USER` with the username you use to log in to your web host when transferring files: + +```txt +~/.ssh/$ cat >> config <<EOF +Host HOST + Hostname HOST + Port 22 + User USER + IdentityFile ~/.ssh/rsa_id +EOF +``` + +Then copy your ssh public key to the remote server with the `ssh-copy-id` command: + +```txt +~/.ssh/$ ssh-copy-id -i rsa_id.pub USER@HOST.com +``` + +Now you can easily connect to the remote server: + +```txt +~$ ssh user@host +Enter passphrase for key '/home/mylogin/.ssh/rsa_id': +``` + +Now that you can log in with your SSH key, let's create a script to automate deployment of your Hugo site. + +## Shell script + +Create a new script called `deploy` the root of your Hugo tree: + +```txt +~/websites/topologix.fr$ editor deploy +``` + +Add the following content. Replace the `USER`, `HOST`, and `DIR` values with your own values: + +```sh +#!/bin/sh +USER=my-user +HOST=my-server.com +DIR=my/directory/to/topologix.fr/ # the directory where your web site files should go + +hugo && rsync -avz --delete public/ ${USER}@${HOST}:~/${DIR} # this will delete everything on the server that's not in the local public folder + +exit 0 +``` + +Note that `DIR` is the relative path from the remote user's home. If you have to specify a full path (for instance `/var/www/mysite/`) you must change `~/${DIR}` to `${DIR}` inside the command-line. For most cases you should not have to. + +Save and close, and make the `deploy` file executable: + +```txt +~/websites/topologix.fr$ chmod +x deploy +``` + +Now you only have to enter the following command to deploy and update your website: + +```txt +~/websites/topologix.fr$ ./deploy +``` + +Your site builds and deploys: + +```txt +Started building sites ... +Built site for language en: +0 draft content +0 future content +0 expired content +5 pages created +0 non-page files copied +0 paginator pages created +0 tags created +0 categories created +total in 56 ms +sending incremental file list +404.html +index.html +index.xml +sitemap.xml +posts/ +posts/index.html + +sent 9,550 bytes received 1,708 bytes 7,505.33 bytes/sec +total size is 966,557 speedup is 85.86 +``` + +You can incorporate other processing tasks into this deployment script as well. diff --git a/docs/content/en/hosting-and-deployment/hosting-on-21yunbox.md b/docs/content/en/hosting-and-deployment/hosting-on-21yunbox.md new file mode 100644 index 000000000..2ab0a1964 --- /dev/null +++ b/docs/content/en/hosting-and-deployment/hosting-on-21yunbox.md @@ -0,0 +1,56 @@ +--- +title: Host on 21YunBox +description: Host your Hugo site with 21YunBox's blazing fast Chinese CDN, fully-managed SSL and auto deploys from Gitee. +categories: [hosting and deployment] +keywords: [hosting,21yunbox] +menu: + docs: + parent: hosting-and-deployment +toc: true +--- + +[21YunBox](https://www.21yunbox.com) is a fully-managed cloud platform dedicated to make web deployment easy within the Chinese Great Firewall where you can host static sites, backend APIs, databases, cron jobs, and all your other apps in one place. It provides blazing fast Chinese CDN, continuous deployment, one-click HTTPS and [other services like managed databases and backend web services](https://www.21yunbox.com/docs/), providing an avenue to launch web projects in China. + +21YunBox includes the following features: + +- Continuous, automatic builds & deploys from GitHub and Gitee +- Automatic SSL certificates through [Let's Encrypt](https://letsencrypt.org) +- Instant cache invalidation with a blazing fast, Chinese CDN +- Unlimited [custom domains](https://www.21yunbox.com/docs/#/custom-domains) +- Automatic [Brotli compression](https://en.wikipedia.org/wiki/Brotli) for faster sites +- Native HTTP/2 support +- Automatic HTTP → HTTPS redirects +- Custom URL redirects and rewrites + +## Prerequisites + +This guide assumes you already have a Hugo project to deploy. If you need a project, use the [Quick Start](/getting-started/quick-start/) to get started or fork 21YunBox's [Hugo Example](https://gitee.com/eryiyunbox-examples/hello-hugo) before continuing. + +## Setup + +You can set up a Hugo site on 21YunBox in two quick steps: + +1. Create a new web service on 21YunBox, and give 21YunBox permission to access your GitHub or Gitee repo. +2. Use the following values during creation: + + | Field | Value | + | --------------------- | ------------------------------------------------ | + | **Environment** | `Static Site` | + | **Build Command** | `hugo --gc --minify` (or your own build command) | + | **Publish Directory** | `./public` (or your own output directory) | + +That's it! Your site will be live on your 21YunBox URL (which looks like `yoursite.21yunbox.com`) as soon as the build is done. + +## Continuous deploys + +Now that 21YunBox is connected to your repo, it will automatically build and publish your site any time you push to GitHub. + +Every deploy automatically and instantly invalidates the CDN cache, so your users can always access the latest content on your site. + +## Custom domains + +Add your own domains to your site easily using 21YunBox's [custom domains](https://www.21yunbox.com/docs/#/custom-domains) guide. + +## Support + +Click [here](https://www.21yunbox.com/docs/#/contact) to contact with 21YunBox' experts if you need help. diff --git a/docs/content/en/hosting-and-deployment/hosting-on-aws-amplify.md b/docs/content/en/hosting-and-deployment/hosting-on-aws-amplify.md new file mode 100644 index 000000000..43d75312a --- /dev/null +++ b/docs/content/en/hosting-and-deployment/hosting-on-aws-amplify.md @@ -0,0 +1,46 @@ +--- +title: Host on AWS Amplify +description: Develop and deploy a cloud-powered web app with AWS Amplify. +categories: [hosting and deployment] +keywords: [hosting,amplify] +menu: + docs: + parent: hosting-and-deployment +toc: true +--- + +In this guide we'll walk through how to deploy and host your Hugo site using the [AWS Amplify Console](https://console.amplify.aws). + +AWS Amplify is a combination of client library, CLI toolchain, and a Console for continuous deployment and hosting. The Amplify CLI and library allow developers to get up & running with full-stack cloud-powered applications with features like authentication, storage, serverless GraphQL or REST APIs, analytics, Lambda functions, & more. The Amplify Console provides continuous deployment and hosting for modern web apps (single page apps and static site generators). Continuous deployment allows developers to deploy updates to their web app on every code commit to their Git repository. Hosting includes features such as globally available CDNs, easy custom domain setup + HTTPS, feature branch deployments, and password protection. + +## Pre-requisites + +* [Sign up for an AWS Account](https://portal.aws.amazon.com/billing/signup?redirect_url=https%3A%2F%2Faws.amazon.com%2Fregistration-confirmation). There are no upfront charges or any term commitments to create an AWS account and signing up gives you immediate access to the AWS Free Tier. +* You have an account with GitHub, GitLab, or Bitbucket. +* You have completed the [Quick Start] or have a Hugo website you are ready to deploy and share with the world. + +## Hosting + +1. Log in to the [AWS Amplify Console](https://console.aws.amazon.com/amplify/home) and choose Get Started under Deploy. +  + +1. Connect a branch from your GitHub, Bitbucket, GitLab, or AWS CodeCommit repository. Connecting your repository allows Amplify to deploy updates on every code commit to a branch. +  + +1. Accept the default build settings. The Amplify Console automatically detects your Hugo build settings and output directory. +  + +1. Review your changes and then choose **Save and deploy**. The Amplify Console will pull code from your repository, build changes to the backend and frontend, and deploy your build artifacts at `https://master.unique-id.amplifyapp.com`. Bonus: Screenshots of your app on different devices to find layout issues. + +## Using a newer version of Hugo + +If you need to use a different, perhaps newer, version of Hugo than the version currently supported by AWS Amplify: + +1. Visit the [AWS Amplify Console](https://console.aws.amazon.com/amplify/home), and click the app you would like to modify +1. In the side navigation bar, Under App Settings, click **Build settings** +1. On the Build settings page, near the bottom, there is a section called **Build image settings**. Click **Edit** +1. Under **Live package updates**, click **Add package version override** +1. From the selection, click **Hugo** and ensure the version field says `latest` +1. Click **Save** to save the changes. + +[Quick Start]: /getting-started/quick-start/ diff --git a/docs/content/en/hosting-and-deployment/hosting-on-azure-static-web-apps.md b/docs/content/en/hosting-and-deployment/hosting-on-azure-static-web-apps.md new file mode 100644 index 000000000..922cbfef2 --- /dev/null +++ b/docs/content/en/hosting-and-deployment/hosting-on-azure-static-web-apps.md @@ -0,0 +1,14 @@ +--- +title: Host on Azure Static Web Apps +description: Publish a Hugo site to Azure Static Web Apps. +categories: [hosting and deployment] +keywords: [hosting,azure] +menu: + docs: + parent: hosting-and-deployment +toc: true +--- + +You can create and deploy a Hugo web application to Azure Static Web Apps. The final result is a new Azure Static Web App with associated GitHub Actions that give you control over how the app is built and published. You'll learn how to create a Hugo app, set up an Azure Static Web App and deploy the Hugo app to Azure. + +Here's the tutorial on how to [Publish a Hugo site to Azure Static Web Apps](https://docs.microsoft.com/en-us/azure/static-web-apps/publish-hugo). diff --git a/docs/content/en/hosting-and-deployment/hosting-on-cloudflare-pages.md b/docs/content/en/hosting-and-deployment/hosting-on-cloudflare-pages.md new file mode 100644 index 000000000..e50143db7 --- /dev/null +++ b/docs/content/en/hosting-and-deployment/hosting-on-cloudflare-pages.md @@ -0,0 +1,14 @@ +--- +title: Host on Cloudflare Pages +description: Cloudflare Pages can host your Hugo site with CDN, continuous deployment, 1-click HTTPS, an admin GUI, and its own environment variables. +categories: [hosting and deployment] +keywords: [hosting,cloudflare] +menu: + docs: + parent: hosting-and-deployment +toc: true +--- + +[Cloudflare Pages](https://developers.cloudflare.com/pages/) are super fast, always up-to-date, and deployed directly from your [Git provider](https://developers.cloudflare.com/pages/get-started/#connect-your-git-provider-to-pages). + +Cloudflare Pages docs have a detailed tutorial on [how to deploy a Hugo site](https://developers.cloudflare.com/pages/framework-guides/deploy-a-hugo-site/). diff --git a/docs/content/en/hosting-and-deployment/hosting-on-firebase.md b/docs/content/en/hosting-and-deployment/hosting-on-firebase.md new file mode 100644 index 000000000..028964bcf --- /dev/null +++ b/docs/content/en/hosting-and-deployment/hosting-on-firebase.md @@ -0,0 +1,110 @@ +--- +title: Host on Firebase +description: You can use Firebase's free tier to host your static website; this also gives you access to Firebase's NoSQL API. +categories: [hosting and deployment] +keywords: [hosting,firebase] +menu: + docs: + parent: hosting-and-deployment +toc: true +--- + +## Assumptions + +1. You have an account with [Firebase][signup]. (If you don't, you can sign up for free using your Google account.) +2. You have completed the [Quick Start] or have a completed Hugo website ready for deployment. + +## Initial setup + +Go to the [Firebase console][console] and create a new project (unless you already have a project). You will need to globally install `firebase-tools` (node.js): + +```sh +npm install -g firebase-tools +``` + +Log in to Firebase (setup on your local machine) using `firebase login`, which opens a browser where you can select your account. Use `firebase logout` in case you are already logged in but to the wrong account. + +```sh +firebase login +``` + +In the root of your Hugo project, initialize the Firebase project with the `firebase init` command: + +```sh +firebase init +``` + +From here: + +1. Choose Hosting in the feature question +2. Choose the project you just set up +3. Accept the default for your database rules file +4. Accept the default for the publish directory, which is `public` +5. Choose "No" in the question if you are deploying a single-page app + +## Using Firebase & GitHub CI/CD + +In new versions of Firebase, some other questions apply: + +6. Set up automatic builds and deploys with GitHub? + +Here you will be redirected to login in your GitHub account to get permissions. Confirm. + +7. For which GitHub repository would you like to set up a GitHub workflow? (format: user/repository) + +Include the repository you will use in the format above (Account/Repo) +Firebase script with retrieve credentials, create a service account you can later manage in your GitHub settings. + +8. Set up the workflow to run a build script before every deploy? + +Here is your opportunity to include some commands before you run the deploy. + +9. Set up automatic deployment to your site's live channel when a PR is merged? + +You can let in the default option (main) + +After that Firebase has been set in your project with CI/CD. After that run: + +```sh +hugo && firebase deploy +``` + +With this you will have the app initialized manually. After that you can manage and fix your GitHub workflow from: https://github.com/your-account/your-repo/actions + +Don't forget to update your static pages before push! + +## Manual deploy + +To deploy your Hugo site, execute the `firebase deploy` command, and your site will be up in no time: + +```sh +hugo && firebase deploy +``` + +## CI setup (other tools) + +You can generate a deploy token using + +```sh +firebase login:ci +``` + +You can also set up your CI and add the token to a private variable like `$FIREBASE_DEPLOY_TOKEN`. + +{{% note %}} +This is a private secret and it should not appear in a public repository. Make sure you understand your chosen CI and that it's not visible to others. +{{% /note %}} + +You can then add a step in your build to do the deployment using the token: + +```sh +firebase deploy --token $FIREBASE_DEPLOY_TOKEN +``` + +## Reference links + +* [Firebase CLI Reference](https://firebase.google.com/docs/cli/#administrative_commands) + +[console]: https://console.firebase.google.com/ +[Quick Start]: /getting-started/quick-start/ +[signup]: https://console.firebase.google.com/ diff --git a/docs/content/en/hosting-and-deployment/hosting-on-github/gh-pages-1.png b/docs/content/en/hosting-and-deployment/hosting-on-github/gh-pages-1.png Binary files differnew file mode 100644 index 000000000..29912f25c --- /dev/null +++ b/docs/content/en/hosting-and-deployment/hosting-on-github/gh-pages-1.png diff --git a/docs/content/en/hosting-and-deployment/hosting-on-github/gh-pages-2.png b/docs/content/en/hosting-and-deployment/hosting-on-github/gh-pages-2.png Binary files differnew file mode 100644 index 000000000..0050d33e2 --- /dev/null +++ b/docs/content/en/hosting-and-deployment/hosting-on-github/gh-pages-2.png diff --git a/docs/content/en/hosting-and-deployment/hosting-on-github/gh-pages-3.png b/docs/content/en/hosting-and-deployment/hosting-on-github/gh-pages-3.png Binary files differnew file mode 100644 index 000000000..d2904cae1 --- /dev/null +++ b/docs/content/en/hosting-and-deployment/hosting-on-github/gh-pages-3.png diff --git a/docs/content/en/hosting-and-deployment/hosting-on-github/gh-pages-4.png b/docs/content/en/hosting-and-deployment/hosting-on-github/gh-pages-4.png Binary files differnew file mode 100644 index 000000000..75774462b --- /dev/null +++ b/docs/content/en/hosting-and-deployment/hosting-on-github/gh-pages-4.png diff --git a/docs/content/en/hosting-and-deployment/hosting-on-github/gh-pages-5.png b/docs/content/en/hosting-and-deployment/hosting-on-github/gh-pages-5.png Binary files differnew file mode 100644 index 000000000..efe26129a --- /dev/null +++ b/docs/content/en/hosting-and-deployment/hosting-on-github/gh-pages-5.png diff --git a/docs/content/en/hosting-and-deployment/hosting-on-github/index.md b/docs/content/en/hosting-and-deployment/hosting-on-github/index.md new file mode 100644 index 000000000..c3da5ba3e --- /dev/null +++ b/docs/content/en/hosting-and-deployment/hosting-on-github/index.md @@ -0,0 +1,190 @@ +--- +title: Host on GitHub Pages +description: Deploy Hugo as a GitHub Pages project or personal/organizational site and automate the whole process with GitHub Actions +categories: [hosting and deployment] +keywords: [hosting,github] +menu: + docs: + parent: hosting-and-deployment +toc: true +aliases: [/tutorials/github-pages-blog/] +--- + +GitHub provides free and fast static hosting over SSL for personal, organization, or project pages directly from a GitHub repository via its GitHub Pages service and automating development workflows and build with GitHub Actions. + +## Prerequisites + +1. [Create a GitHub account] +2. [Install Git] +3. [Create a Hugo site] and test it locally with `hugo server`. + +[Create a GitHub account]: https://github.com/signup +[Install Git]: https://git-scm.com/book/en/v2/Getting-Started-Installing-Git +[Create a Hugo site]: /getting-started/quick-start/ + +## Types of sites + +There are three types of GitHub Pages sites: project, user, and organization. Project sites are connected to a specific project hosted on GitHub. User and organization sites are connected to a specific account on GitHub.com. + +{{% note %}} +See the [GitHub Pages documentation] to understand the requirements for repository ownership and naming. + +[GitHub Pages documentation]: https://docs.github.com/en/pages/getting-started-with-github-pages/about-github-pages#types-of-github-pages-sites +{{% /note %}} + +[GitHub Pages documentation]: https://docs.github.com/en/pages/getting-started-with-github-pages/about-github-pages#types-of-github-pages-sites + +## Procedure + +Step 1 +: Create a GitHub repository. + +Step 2 +: Push your local repository to GitHub. + +Step 3 +: Visit your GitHub repository. From the main menu choose **Settings** > **Pages**. In the center of your screen you will see this: + + +{style="max-width: 280px"} + +Step 4 +: Change the **Source** to `GitHub Actions`. The change is immediate; you do not have to press a Save button. + + +{style="max-width: 280px"} + +Step 5 +: Create an empty file in your local repository. + +```text +.github/workflows/hugo.yaml +``` + +Step 6 +: Copy and paste the YAML below into the file you created. Change the branch name and Hugo version as needed. + +{{< code file=.github/workflows/hugo.yaml copy=true >}} +# Sample workflow for building and deploying a Hugo site to GitHub Pages +name: Deploy Hugo site to Pages + +on: + # Runs on pushes targeting the default branch + push: + branches: + - main + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages +permissions: + contents: read + pages: write + id-token: write + +# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. +# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete. +concurrency: + group: "pages" + cancel-in-progress: false + +# Default to bash +defaults: + run: + shell: bash + +jobs: + # Build job + build: + runs-on: ubuntu-latest + env: + HUGO_VERSION: 0.122.0 + steps: + - name: Install Hugo CLI + run: | + wget -O ${{ runner.temp }}/hugo.deb https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_extended_${HUGO_VERSION}_linux-amd64.deb \ + && sudo dpkg -i ${{ runner.temp }}/hugo.deb + - name: Install Dart Sass + run: sudo snap install dart-sass + - name: Checkout + uses: actions/checkout@v4 + with: + submodules: recursive + fetch-depth: 0 + - name: Setup Pages + id: pages + uses: actions/configure-pages@v4 + - name: Install Node.js dependencies + run: "[[ -f package-lock.json || -f npm-shrinkwrap.json ]] && npm ci || true" + - name: Build with Hugo + env: + # For maximum backward compatibility with Hugo modules + HUGO_ENVIRONMENT: production + HUGO_ENV: production + run: | + hugo \ + --gc \ + --minify \ + --baseURL "${{ steps.pages.outputs.base_url }}/" + - name: Upload artifact + uses: actions/upload-pages-artifact@v2 + with: + path: ./public + + # Deployment job + deploy: + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + runs-on: ubuntu-latest + needs: build + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v3 +{{< /code >}} + +Step 7 +: Commit the change to your local repository with a commit message of something like "Add workflow", and push to GitHub. + +Step 8 +: From GitHub's main menu, choose **Actions**. You will see something like this: + + +{style="max-width: 350px"} + +Step 9 +: When GitHub has finished building and deploying your site, the color of the status indicator will change to green. + + +{style="max-width: 350px"} + +Step 10 +: Click on the commit message as shown above. You will see this: + + +{style="max-width: 611px"} + +Under the deploy step, you will see a link to your live site. + +In the future, whenever you push a change from your local repository, GitHub will rebuild your site and deploy the changes. + +## Customize the workflow + +The example workflow above includes this step, which typically takes 10‑15 seconds: + +```yaml +- name: Install Dart Sass + run: sudo snap install dart-sass +``` + +You may remove this step if your site, themes, and modules do not transpile Sass to CSS using the [Dart Sass] transpiler. + +[Dart Sass]: /hugo-pipes/transpile-sass-to-css/#dart-sass + +## Additional resources + +- [Learn more about GitHub Actions](https://docs.github.com/en/actions) +- [Caching dependencies to speed up workflows](https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows) +- [Manage a custom domain for your GitHub Pages site](https://docs.github.com/en/pages/configuring-a-custom-domain-for-your-github-pages-site/about-custom-domains-and-github-pages) diff --git a/docs/content/en/hosting-and-deployment/hosting-on-gitlab.md b/docs/content/en/hosting-and-deployment/hosting-on-gitlab.md new file mode 100644 index 000000000..87c764f00 --- /dev/null +++ b/docs/content/en/hosting-and-deployment/hosting-on-gitlab.md @@ -0,0 +1,101 @@ +--- +title: Host on GitLab Pages +description: GitLab makes it easy to build, deploy, and host your Hugo website via their free GitLab Pages service, which provides native support for Hugo. +categories: [hosting and deployment] +keywords: [hosting,gitlab] +menu: + docs: + parent: hosting-and-deployment +toc: true +aliases: [/tutorials/hosting-on-gitlab/] +--- + +## Assumptions + +* Working familiarity with Git for version control +* Completion of the Hugo [Quick Start] +* A [GitLab account](https://gitlab.com/users/sign_in) +* A Hugo website on your local machine that you are ready to publish + +## BaseURL + +The `baseURL` in your [site configuration](/getting-started/configuration/) must reflect the full URL of your GitLab pages repository if you are using the default GitLab Pages URL (e.g., `https://<YourUsername>.gitlab.io/<your-hugo-site>/`) and not a custom domain. + +## Configure GitLab CI/CD + +Define your [CI/CD](https://docs.gitlab.com/ee/ci/quick_start/) jobs by creating a `.gitlab-ci.yml` file in the root of your project. + +{{< code file=.gitlab-ci.yml copy=true >}} +variables: + DART_SASS_VERSION: 1.70.0 + HUGO_VERSION: 0.122.0 + NODE_VERSION: 20.x + GIT_DEPTH: 0 + GIT_STRATEGY: clone + GIT_SUBMODULE_STRATEGY: recursive + TZ: America/Los_Angeles + +image: + name: golang:1.20.6-bookworm + +pages: + script: + # Install brotli + - apt-get update + - apt-get install -y brotli + # Install Dart Sass + - curl -LJO https://github.com/sass/dart-sass/releases/download/${DART_SASS_VERSION}/dart-sass-${DART_SASS_VERSION}-linux-x64.tar.gz + - tar -xf dart-sass-${DART_SASS_VERSION}-linux-x64.tar.gz + - cp -r dart-sass/ /usr/local/bin + - rm -rf dart-sass* + - export PATH=/usr/local/bin/dart-sass:$PATH + # Install Hugo + - curl -LJO https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_extended_${HUGO_VERSION}_linux-amd64.deb + - apt-get install -y ./hugo_extended_${HUGO_VERSION}_linux-amd64.deb + - rm hugo_extended_${HUGO_VERSION}_linux-amd64.deb + # Install Node.js + - curl -fsSL https://deb.nodesource.com/setup_${NODE_VERSION} | bash - + - apt-get install -y nodejs + # Install Node.js dependencies + - "[[ -f package-lock.json || -f npm-shrinkwrap.json ]] && npm ci || true" + # Build + - hugo --gc --minify + # Compress + - find public -type f -regex '.*\.\(css\|html\|js\|txt\|xml\)$' -exec gzip -f -k {} \; + - find public -type f -regex '.*\.\(css\|html\|js\|txt\|xml\)$' -exec brotli -f -k {} \; + artifacts: + paths: + - public + rules: + - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH +{{% /code %}} + +## Push your Hugo website to GitLab + +Next, create a new repository on GitLab. It is *not* necessary to make the repository public. In addition, you might want to add `/public` to your .gitignore file, as there is no need to push compiled assets to GitLab or keep your output website in version control. + +```sh +# initialize new git repository +git init + +# add /public directory to our .gitignore file +echo "/public" >> .gitignore + +# commit and push code to master branch +git add . +git commit -m "Initial commit" +git remote add origin https://gitlab.com/YourUsername/your-hugo-site.git +git push -u origin master +``` + +## Wait for your page to build + +That's it! You can now follow the CI agent building your page at `https://gitlab.com/<YourUsername>/<your-hugo-site>/pipelines`. + +After the build has passed, your new website is available at `https://<YourUsername>.gitlab.io/<your-hugo-site>/`. + +## Next steps + +GitLab supports using custom CNAME's and TLS certificates. For more details on GitLab Pages, see the [GitLab Pages setup documentation](https://about.gitlab.com/2016/04/07/gitlab-pages-setup/). + +[Quick Start]: /getting-started/quick-start/ diff --git a/docs/content/en/hosting-and-deployment/hosting-on-keycdn.md b/docs/content/en/hosting-and-deployment/hosting-on-keycdn.md new file mode 100644 index 000000000..e81129981 --- /dev/null +++ b/docs/content/en/hosting-and-deployment/hosting-on-keycdn.md @@ -0,0 +1,88 @@ +--- +title: Host on KeyCDN +description: "Accelerate your Hugo site globally with a KeyCDN integration. This tutorial shows you how to set up your static site as a GitLab page behind a KeyCDN pull zone." +categories: [hosting and deployment] +keywords: [hosting,keycdn] +menu: + docs: + parent: hosting-and-deployment +--- + +[KeyCDN](https://www.keycdn.com/) provides a multitude of features to help accelerate and secure your Hugo site globally including Brotli compression, Let's Encrypt support, Origin Shield, and more. + +## Assumptions + +- You already have a Hugo page configured +- You have a GitLab account +- You have a KeyCDN account + +## Create a KeyCDN Pull Zone + +The first step will be to log in to your KeyCDN account and create a new zone. Name this whatever you like and select the [Pull Zone](https://www.keycdn.com/support/create-a-pull-zone/) option. As for the origin URL, your site will be running on [GitLab Pages](https://docs.gitlab.com/ee/user/project/pages/getting_started_part_one.html) with a URL of `https://youruser.gitlab.io/reponame/`. Use this as the Origin URL. + + + +While the origin location doesn’t exist yet, you will need to use your new Zone URL address (or [Zone Alias](https://www.keycdn.com/support/create-a-zone-alias/)) in the `.gitlab-ci.yml` file that will be uploaded to your GitLab project. + +Ensure that you use your Zone URL or Zone alias as the `BASEURL` variable in the example below. This will be the user-visible website address. + +## Configure Your .gitlab-ci.yml File + +Your `.gitlab-ci.yml` file should look similar to the example below. Be sure to modify any variables that are specific to your setup. + +```yml +image: alpine:latest + +variables: + BASEURL: "https://cipull-7bb7.kxcdn.com/" + HUGO_VERSION: "0.26" + HUGO_CHECKSUM: "67e4ba5ec2a02c8164b6846e30a17cc765b0165a5b183d5e480149baf54e1a50" + KEYCDN_ZONE_ID: "75544" + +before_script: + - apk update + - apk add curl + +pages: + stage: deploy + script: + - apk add git + - git submodule update --init + - curl -sSL https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_${HUGO_VERSION}_Linux-64bit.tar.gz -o /tmp/hugo.tar.gz + - echo "${HUGO_CHECKSUM} /tmp/hugo.tar.gz" | sha256sum -c + - tar xf /tmp/hugo.tar.gz hugo -C /tmp/ && cp /tmp/hugo /usr/bin + - hugo --baseURL ${BASEURL} + - curl "https://api.keycdn.com/zones/purge/${KEYCDN_ZONE_ID}.json" -u "${KEYCDN_API_KEY}:" + artifacts: + paths: + - public + only: + - master +``` + +Using this integration method, you will have to specify the Zone ID and your [KeyCDN API](https://www.keycdn.com/api) key as secret variables. To do this, navigate to the top-left menu bar in GitLab and select Projects. Then, select your project and click on the Settings page. Finally, select Pipelines from the sub-menu and scroll down to the Secret Variable section. + +The Secret Variable for your Zone ID should look similar to: + + + +While the Secret Variable for your API Key will look similar to: + + + +The Zone ID and API key are used to purge your zone – it’s not strictly needed but otherwise, the CDN might deliver older versions of your assets for quite a while. + +## Push your changes to GitLab + +Now it’s time to push the newly created repository to GitLab: + +```sh +git remote add origin git@gitlab.com:youruser/ci-example.git +git push -u origin master +``` + +You can watch the progress and CI job output in your GitLab project under “Pipelines”. + +After verifying your CI job ran without issues, first check that your GitLab page shows up under `https://youruser.gitlab.io/reponame/` (it might look broken depending on your browser settings as all links point to your KeyCDN zone – don’t worry about that) and then by heading to whatever Zone alias / Zone URL you defined. + +To learn more about Hugo hosting options with KeyCDN, check out the complete [Hugo hosting with KeyCDN integration guide](https://www.keycdn.com/support/hugo-hosting/). diff --git a/docs/content/en/hosting-and-deployment/hosting-on-netlify.md b/docs/content/en/hosting-and-deployment/hosting-on-netlify.md new file mode 100644 index 000000000..2dcdd95f5 --- /dev/null +++ b/docs/content/en/hosting-and-deployment/hosting-on-netlify.md @@ -0,0 +1,145 @@ +--- +title: Host on Netlify +description: Netlify can host your Hugo site with CDN, continuous deployment, 1-click HTTPS, an admin GUI, and its own CLI. +categories: [hosting and deployment] +keywords: [hosting,netlify] +menu: + docs: + parent: hosting-and-deployment +toc: true +--- + +[Netlify][netlify] provides continuous deployment services, global CDN, ultra-fast DNS, atomic deploys, instant cache invalidation, one-click SSL, a browser-based interface, a CLI, and many other features for managing your Hugo website. + +## Assumptions + +* You have an account with GitHub, GitLab, or Bitbucket. +* You have completed the [Quick Start] or have a Hugo website you are ready to deploy and share with the world. +* You do not already have a Netlify account. + +## Create a Netlify account + +Go to [app.netlify.com] and select your preferred sign up method. This will likely be a hosted Git provider, although you also have the option to sign up with an email address. + +The following examples use GitHub, but other git providers will follow a similar process. + + + +Selecting GitHub will bring up an authorization modal for authentication. Select "Authorize application." + + + +## Create a new site with continuous deployment + +You're now already a Netlify member and should be brought to your new dashboard. Select "New site from git." + + + +Netlify will then start walking you through the steps necessary for continuous deployment. First, you'll need to select your git provider again, but this time you are giving Netlify added permissions to your repositories. + + + +And then again with the GitHub authorization modal: + + + +Select the repo you want to use for continuous deployment. If you have a large number of repositories, you can filter through them in real time using repo search: + + + +Once selected, you'll be brought to a screen for basic setup. Here you can select the branch you want to publish, your [build command], and your publish (i.e. deploy) directory. The publish directory should mirror that of what you've set in your [site configuration], the default of which is `public`. The following steps assume you are publishing from the `master` branch. + +## Configure Hugo version in Netlify + +You can [set Hugo version](https://www.netlify.com/blog/2017/04/11/netlify-plus-hugo-0.20-and-beyond/) for your environments in `netlify.toml` file or set `HUGO_VERSION` as a build environment variable in the Netlify console. + +For production: + +{{< code file=netlify.toml >}} +[context.production.environment] + HUGO_VERSION = "0.122.0" +{{< /code >}} + +For testing: + +{{< code file=netlify.toml >}} +[context.deploy-preview.environment] + HUGO_VERSION = "0.122.0" +{{< /code >}} + +The Netlify configuration file can be a little hard to understand and get right for the different environment, and you may get some inspiration and tips from this site's `netlify.toml`: + +{{< readfile file=netlify.toml highlight=toml >}} + +## Build and deploy site + +In the Netlify console, selecting "Deploy site" will immediately take you to a terminal for your build:. + + + +Once the build is finished---this should only take a few seconds--you should now see a "Hero Card" at the top of your screen letting you know the deployment is successful. The Hero Card is the first element that you see in most pages. It allows you to see a quick summary of the page and gives access to the most common/pertinent actions and information. You'll see that the URL is automatically generated by Netlify. You can update the URL in "Settings." + + + + + +[Visit the live site][visit]. + +Now every time you push changes to your hosted git repository, Netlify will rebuild and redeploy your site. + +See [this blog post](https://www.netlify.com/blog/2017/04/11/netlify-plus-hugo-0.20-and-beyond/) for more details about how Netlify handles Hugo versions. + +## Use Hugo themes with Netlify + +The `git clone` method for installing themes is not supported by Netlify. If you were to use `git clone`, it would require you to recursively remove the `.git` subdirectory from the theme folder and would therefore prevent compatibility with future versions of the theme. + +A *better* approach is to install a theme as a proper git submodule. You can [read the GitHub documentation for submodules][ghsm] or those found on [Git's website][gitsm] for more information, but the command is similar to that of `git clone`: + +```txt +cd themes +git submodule add https://github.com/<THEMECREATOR>/<THEMENAME> +``` + +It is recommended to only use stable versions of a theme (if it’s versioned) and always check the changelog. This can be done by checking out a specific release within the theme's directory. + +Switch to the theme's directory and list all available versions: + +```txt +cd themes/<theme> +git tag +# exit with q +``` + +You can checkout a specific version as follows: + +```txt +git checkout tags/<version-name> +``` + +You can update a theme to the latest version by executing the following command in the *root* directory of your project: + +```txt +git submodule update --rebase --remote +``` + +## Next steps + +You now have a live website served over HTTPS, distributed through CDN, and configured for continuous deployment. Dig deeper into the Netlify documentation: + +1. [Using a Custom Domain] +2. [Setting up HTTPS on Custom Domains][httpscustom] +3. [Redirects and Rewrite Rules] + +[app.netlify.com]: https://app.netlify.com +[build command]: /getting-started/usage/#build-your-site +[site configuration]: /getting-started/configuration/ +[ghsm]: https://github.com/blog/2104-working-with-submodules +[gitsm]: https://git-scm.com/book/en/v2/Git-Tools-Submodules +[httpscustom]: https://www.netlify.com/docs/ssl/ +[hugoversions]: https://github.com/netlify/build-image/blob/master/Dockerfile#L216 +[netlify]: https://www.netlify.com/ +[netlifysignup]: https://app.netlify.com/signup +[Quick Start]: /getting-started/quick-start/ +[Redirects and Rewrite Rules]: https://www.netlify.com/docs/redirects/ +[Using a Custom Domain]: https://www.netlify.com/docs/custom-domains/ +[visit]: https://hugo-netlify-example.netlify.com diff --git a/docs/content/en/hosting-and-deployment/hosting-on-render.md b/docs/content/en/hosting-and-deployment/hosting-on-render.md new file mode 100644 index 000000000..b43261c8d --- /dev/null +++ b/docs/content/en/hosting-and-deployment/hosting-on-render.md @@ -0,0 +1,81 @@ +--- +title: Host on Render +description: Host your Hugo site for free with Render's global CDN, fully-managed SSL and auto deploys from GitHub. +categories: [hosting and deployment] +keywords: [hosting] +menu: + docs: + parent: hosting-and-deployment +toc: true +--- + +## Introduction + +[Render](https://render.com) is a fully-managed cloud platform where you can host static sites, backend APIs, databases, cron jobs, and all your other apps in one place. + +Static sites are **completely free** on Render and include the following: + +- Continuous, automatic builds & deploys from [GitHub](https://render.com/docs/github) and [GitLab](https://render.com/docs/gitlab). +- Automatic SSL certificates through [Let's Encrypt](https://letsencrypt.org). +- Instant cache invalidation with a lightning fast, global CDN. +- Unlimited collaborators. +- Unlimited [custom domains](https://render.com/docs/custom-domains). +- Automatic [Brotli compression](https://en.wikipedia.org/wiki/Brotli) for faster sites. +- Native HTTP/2 support. +- [Pull Request Previews](https://render.com/docs/pull-request-previews). +- Automatic HTTP → HTTPS redirects. +- Custom URL redirects and rewrites. + +## Assumptions + +- You have an account with GitHub or GitLab. +- You have completed the [Quick Start] or have a Hugo website you are ready to deploy and share with the world. +- You have a Render account. You can sign up at https://render.com/register. + +## Deployment + +You can set up a Hugo site on Render in two quick steps: + +1. Create a new **Static Site** on Render, and give Render permission to access your GitHub/GitLab repo. +2. Use the following values during creation: + + Field | Value + ------------------- | ------------------- + **Build Command** | `hugo --gc --minify` (or your own build command) + **Publish Directory** | `public` (or your own output directory) + +That's it! Your site will be live on your Render URL (which looks like `yoursite.onrender.com`) as soon as the build is done. + +## Continuous deploys + +Now that Render is connected to your repo, it will **automatically build and publish your site** any time you push to your GitHub/GitLab. + +You can choose to disable auto deploys under the **Settings** section for your site and deploy it manually from the Render dashboard. + +## CDN and cache invalidation + +Render hosts your site on a global, lightning fast CDN which ensures the fastest possible download times for all your users across the globe. + +Every deploy automatically and instantly invalidates the CDN cache, so your users can always access the latest content on your site. + +## Custom domains + +Add your own domains to your site easily using Render's [custom domains](https://render.com/docs/custom-domains) guide. + +## Pull Request previews + +With Pull Request (PR) previews, you can visualize changes introduced in a pull request instead of simply relying on code reviews. + +Once enabled, every PR for your site will automatically generate a new static site based on the code in the PR. It will have its own URL, and it will be deleted automatically when the PR is closed. + +Read more about [Pull Request Previews](https://render.com/docs/pull-request-previews) on Render. + +## Hugo themes + +Render automatically downloads all Git submodules defined in your Git repo on every build. This way Hugo themes added as submodules work as expected. + +## Support + +Chat with Render developers at https://render.com/chat or email `support@render.com` if you need help. + +[Quick Start]: /getting-started/quick-start/ diff --git a/docs/content/en/hosting-and-deployment/hugo-deploy.md b/docs/content/en/hosting-and-deployment/hugo-deploy.md new file mode 100644 index 000000000..45b917f1e --- /dev/null +++ b/docs/content/en/hosting-and-deployment/hugo-deploy.md @@ -0,0 +1,249 @@ +--- +title: Hugo Deploy +description: Upload your site to GCS, S3, or Azure +categories: [hosting and deployment] +keywords: [deployment,s3,gcs,azure] +menu: + docs: + parent: hosting-and-deployment + weight: 20 +weight: 20 +toc: true +--- + +You can use the "hugo deploy" command to upload your site directly to a Google Cloud Storage (GCS) bucket, an AWS S3 bucket, and/or an Azure Storage container. + + +## Assumptions + +* You have completed the [Quick Start] or have a Hugo website you are ready to deploy and share with the world. +* You have an account with the service provider ([Google Cloud](https://cloud.google.com/), [AWS](https://aws.amazon.com), or [Azure](https://azure.microsoft.com)) that you want to deploy to. +* You have authenticated. + * Google Cloud: [Install the CLI](https://cloud.google.com/sdk) and run [`gcloud auth login`](https://cloud.google.com/sdk/gcloud/reference/auth/login). + * AWS: [Install the CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-install.html) and run [`aws configure`](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-configure.html). + * Azure: [Install the CLI](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli) and run [`az login`](https://docs.microsoft.com/en-us/cli/azure/authenticate-azure-cli). + * NOTE: Each service supports alternatives for authentication, including using environment variables. See [here](https://gocloud.dev/howto/blob/#services) for more details. +* You have created a bucket to deploy to. If you want your site to be + public, be sure to configure the bucket to be publicly readable as a static website. + * Google Cloud: [create a bucket](https://cloud.google.com/storage/docs/creating-buckets) and [host a static website](https://cloud.google.com/storage/docs/hosting-static-website) + * Amazon S3: [create a bucket](https://docs.aws.amazon.com/AmazonS3/latest/gsg/CreatingABucket.html) and [host a static website](https://docs.aws.amazon.com/AmazonS3/latest/userguide/WebsiteHosting.html) + * Microsoft Azure: [create a storage container](https://docs.microsoft.com/en-us/azure/storage/blobs/storage-quickstart-blobs-portal) and [host a static website](https://learn.microsoft.com/en-us/azure/storage/blobs/storage-blob-static-website) + + +## Configuring your first deployment + +In the configuration file for your site, add a `[deployment]` section +and a `[[deployment.targets]]` subsection. The only required parameters are +the name and URL: + +```toml +[deployment] + +[[deployment.targets]] +# An arbitrary name for this target. +name = "production" + +# URL specifies the Go Cloud Development Kit URL to deploy to. Examples: +URL = "<FILL ME IN>" + +# Google Cloud Storage -- see https://gocloud.dev/howto/blob/#gcs +#URL = "gs://<Bucket Name>" + +# Amazon Web Services S3; see https://gocloud.dev/howto/blob/#s3 +# For S3-compatible endpoints, see https://gocloud.dev/howto/blob/#s3-compatible +#URL = "s3://<Bucket Name>?region=<AWS region>" + +# Microsoft Azure Blob Storage; see https://gocloud.dev/howto/blob/#azure +#URL = "azblob://$web" + +``` + +## Deploy + +To deploy to a target: + +```bash +hugo deploy [--target=<target name>] +``` + +The deploy process recursively walks through your local publish directory +(`public` by default) and syncs it to the destination bucket, to ensure +that the local and remote contents match. + +If you don't specify a target, Hugo will deploy to the first target in your +configuration. + +See `hugo help deploy` or [the deploy command-line documentation][commandline] for more command-line options. + + +### How the file list works + +The first thing `hugo deploy` does is create file lists for local and remote by +traversing the local publish directory and remote bucket. + +For both local and remote, the file list includes and excludes files according to +the [deployment target's configuration][config] -- +* If the configuration specifies an `include` pattern, all files + are skipped by default except those matching the pattern. +* If the configuration specifies an `exclude` pattern, files matching the + pattern are skipped. + + +{{% note %}} +When creating the local file list, a few additional skips apply: first, Hugo always +skips files named `.DS_Store`. + +Second, Hugo always skips local hidden directories +(directories with names starting with a period, e.g. `.git`) and does not +traverse into them, except for the special [hidden directory named +`.well-known`](https://en.wikipedia.org/wiki/Well-known_URI), which is +traversed if it exists. +{{% /note %}} + + + +### How the local and remote file lists are compared + +In the second step, Hugo compares the two file lists to figure out what changes +actually need to be made on the remote. File names are compared first; if the +local and remote files both exist then the sizes and md5sums are compared. Any +difference means that the file will be (re-)uploaded. + +Specifying the `--force` flag will ensure all files are re-uploaded even +if Hugo cannot detect any differences between local and remote. + +Files are deleted from the remote bucket if they are not present in the local +file list. + +{{% note %}} +If a remote file is excluded from the file list generation using the +exclude/include configs, then the comparison step will not know to delete the +file -- so it will remain on the remote even if it isn't present locally. +{{% /note %}} + +If the [`--confirm` or `--dryRun` flags][commandline] are given, Hugo displays +what differences it has found and either pauses or stops here. + +### How synchronization works + +Hugo applies the list of changes to the remote storage bucket. Missing and/or +changed files are uploaded, and files missing locally but present remotely are +deleted. As files are uploaded, their headers are also configured on the remote +according to the matchers configuration. + +{{% note %}} +As a safety measure to help prevent accidents, if there are more than 256 files +to delete, Hugo won't delete any files from the remote. Use the `--maxDeletes` +command line flag to override this. +{{% /note %}} + +## Advanced configuration + +Here's a full example deployment configuration: + +```toml +[deployment] + +# By default, files are uploaded in an arbitrary order. +# If you specify an `order` list, files that match regular expressions +# in this list will be uploaded first, in the specified order. +order = [".jpg$", ".gif$"] + +[[deployment.targets]] +# Define one or more targets, e.g., staging and production. +# Each target gets its own [[deployment.targets]] section. + +# An arbitrary name for this target. +name = "mydeployment" +# The Go Cloud Development Kit URL to deploy to. Examples: +URL = "<FILL ME IN>" + +# GCS; see https://gocloud.dev/howto/blob/#gcs +#URL = "gs://<Bucket Name>" + +# S3; see https://gocloud.dev/howto/blob/#s3 +# For S3-compatible endpoints, see https://gocloud.dev/howto/blob/#s3-compatible +#URL = "s3://<Bucket Name>?region=<AWS region>" + +# Azure Blob Storage; see https://gocloud.dev/howto/blob/#azure +#URL = "azblob://$web" + +# You can use a "prefix=" query parameter to target a subfolder of the bucket: +#URL = "gs://<Bucket Name>?prefix=a/subfolder/" + +# If you are using a CloudFront CDN, deploy will invalidate the cache as needed. +#cloudFrontDistributionID = "<FILL ME IN>" + +# Include or exclude specific files when deploying to this target: +# If exclude is non-empty, and a local or remote file's path matches it, that file is not synced. +# If include is non-empty, and a local or remote file's path does not match it, that file is not synced. +# Note: local files that don't pass the include/exclude filters are not uploaded to remote, +# and remote files that don't pass the include/exclude filters are not deleted. +# +# The pattern syntax is documented here: https://godoc.org/github.com/gobwas/glob#Glob +# Patterns should be written with forward slashes as separator. +# +#include = "**.html" # would only include files with ".html" suffix +#exclude = "**.{jpg, png}" # would exclude files with ".jpg" or ".png" suffix + + +####################### +[[deployment.matchers]] +# Matchers enable special caching, content type and compression behavior for +# specified file types. You can include any number of matcher blocks; the first one +# matching a given file pattern will be used. + +# See https://golang.org/pkg/regexp/syntax/ for pattern syntax. +# Pattern searching is stopped on first match. +pattern = "<FILL ME IN>" + +# If true, Hugo will gzip the file before uploading it to the bucket. +# With many storage services, this will save on storage and bandwidth costs +# for uncompressed file types. +#gzip = false + +# If true, Hugo always re-uploads this file even if size and md5 match. +# This is useful if Hugo isn't reliably able to determine whether to re-upload +# the file on its own. +#force = false + +# Content-type header to configure for this file when served. +# By default this can be determined from the file extension. +#contentType = "" + +# Cache-control header to configure for this file when served. +# The default is the empty string. +#cacheControl = "" + +# Content-encoding header to configure for this file when served. +# By default, if gzip is True, this will be filled with "gzip". +#contentEncoding = "" + + +# Samples: + +[[deployment.matchers]] +# Cache static assets for 1 year. +pattern = "^.+\\.(js|css|svg|ttf)$" +cacheControl = "max-age=31536000, no-transform, public" +gzip = true + +[[deployment.matchers]] +pattern = "^.+\\.(png|jpg)$" +cacheControl = "max-age=31536000, no-transform, public" +gzip = false + +[[deployment.matchers]] +# Set custom content type for /sitemap.xml +pattern = "^sitemap\\.xml$" +contentType = "application/xml" +gzip = true + +[[deployment.matchers]] +pattern = "^.+\\.(html|xml|json)$" +gzip = true +``` + +[Quick Start]: /getting-started/quick-start/ +[commandline]: /commands/hugo_deploy/ +[config]: #advanced-configuration diff --git a/docs/content/en/hugo-modules/_index.md b/docs/content/en/hugo-modules/_index.md new file mode 100644 index 000000000..cbff13ad0 --- /dev/null +++ b/docs/content/en/hugo-modules/_index.md @@ -0,0 +1,29 @@ +--- +title: Hugo Modules +linkTitle: Overview +description: How to use Hugo Modules. +categories: [] +keywords: [] +menu: + docs: + identifier: hugo-modules-overview + parent: modules + weight: 10 +weight: 10 +toc: true +aliases: [/themes/overview/,/themes/] +--- + +**Hugo Modules** are the core building blocks in Hugo. A _module_ can be your main project or a smaller module providing one or more of the 7 component types defined in Hugo: **static**, **content**, **layouts**, **data**, **assets**, **i18n**, and **archetypes**. + +You can combine modules in any combination you like, and even mount directories from non-Hugo projects, forming a big, virtual union file system. + +Hugo Modules are powered by Go Modules. For more information about Go Modules, see: + +- [https://github.com/golang/go/wiki/Modules](https://github.com/golang/go/wiki/Modules) +- [https://go.dev/blog/using-go-modules](https://go.dev/blog/using-go-modules) + +Some example projects: + +- [https://github.com/bep/docuapi](https://github.com/bep/docuapi) is a theme that has been ported to Hugo Modules while testing this feature. It is a good example of a non-Hugo-project mounted into Hugo’s folder structure. It even shows a JS Bundler implementation in regular Go templates. +- [https://github.com/bep/my-modular-site](https://github.com/bep/my-modular-site) is a very simple site used for testing. diff --git a/docs/content/en/hugo-modules/configuration.md b/docs/content/en/hugo-modules/configuration.md new file mode 100644 index 000000000..ce9e97d81 --- /dev/null +++ b/docs/content/en/hugo-modules/configuration.md @@ -0,0 +1,181 @@ +--- +title: Configure Hugo modules +description: This page describes the configuration options for a module. +categories: [hugo modules] +keywords: [modules,themes] +menu: + docs: + parent: modules + weight: 20 +weight: 20 +toc: true +--- + +## Module configuration: top level + +{{< code-toggle file=hugo >}} +[module] +noProxy = 'none' +noVendor = '' +private = '*.*' +proxy = 'direct' +replacements = '' +vendorClosest = false +workspace = 'off' +{{< /code-toggle >}} + +noProxy +: Comma separated glob list matching paths that should not use the proxy configured above. + +noVendor +: A optional Glob pattern matching module paths to skip when vendoring, e.g. "github.com/**" + +private +: Comma separated glob list matching paths that should be treated as private. + +proxy +: Defines the proxy server to use to download remote modules. Default is `direct`, which means "git clone" and similar. + +vendorClosest +: When enabled, we will pick the vendored module closest to the module using it. The default behavior is to pick the first. Note that there can still be only one dependency of a given module path, so once it is in use it cannot be redefined. + +workspace +: The workspace file to use. This enables Go workspace mode. Note that this can also be set via OS env, e.g. `export HUGO_MODULE_WORKSPACE=/my/hugo.work` This only works with Go 1.18+. In Hugo `v0.109.0` we changed the default to `off` and we now resolve any relative work file names relative to the working directory. + +replacements +: A comma-separated list of mappings from module paths to directories, e.g. `github.com/bep/my-theme -> ../..,github.com/bep/shortcodes -> /some/path`. This is mostly useful for temporary local development of a module, in which case you might want to save it as an environment variable, e.g: `env HUGO_MODULE_REPLACEMENTS="github.com/bep/my-theme -> ../.."`. Relative paths are relative to [themesDir](/getting-started/configuration/#all-configuration-settings). Absolute paths are allowed. + +Note that the above terms maps directly to their counterparts in Go Modules. Some of these setting may be natural to set as OS environment variables. To set the proxy server to use, as an example: + +```txt +env HUGO_MODULE_PROXY=https://proxy.example.org hugo +``` + +{{< gomodules-info >}} + +## Module configuration: hugoVersion + +If your module requires a particular version of Hugo to work, you can indicate that in the `module` section and the user will be warned if using a too old/new version. + +{{< code-toggle file=hugo >}} +[module] +[module.hugoVersion] + min = "" + max = "" + extended = false + +{{< /code-toggle >}} + +Any of the above can be omitted. + +min +: The minimum Hugo version supported, e.g. `0.55.0` + +max +: The maximum Hugo version supported, e.g. `0.55.0` + +extended +: Whether the extended version of Hugo is required. + +## Module configuration: imports + +{{< code-toggle file=hugo >}} +[module] +[[module.imports]] + path = "github.com/gohugoio/hugoTestModules1_linux/modh1_2_1v" + ignoreConfig = false + ignoreImports = false + disable = false +[[module.imports]] + path = "my-shortcodes" +{{< /code-toggle >}} + +path +: Can be either a valid Go Module module path, e.g. `github.com/gohugoio/myShortcodes`, or the directory name for the module as stored in your themes folder. + +ignoreConfig +: If enabled, any module configuration file, e.g. `hugo.toml`, will not be loaded. Note that this will also stop the loading of any transitive module dependencies. + +ignoreImports +: If enabled, module imports will not be followed. + +disable +: Set to `true` to disable the module while keeping any version info in the `go.*` files. + +noMounts +: Do not mount any folder in this import. + +noVendor +: Never vendor this import (only allowed in main project). + +{{< gomodules-info >}} + +## Module configuration: mounts + +{{% note %}} +When the `mounts` configuration was introduced in Hugo 0.56.0, we were careful to preserve the existing `contentDir`, `staticDir`, and similar configuration to make sure all existing sites just continued to work. But you should not have both: if you add a `mounts` section you should remove the old `contentDir`, `staticDir`, etc. settings. +{{% /note %}} + +{{% note %}} +When you add a mount, the default mount for the concerned target root is ignored: be sure to explicitly add it. +{{% /note %}} + +**Default mounts** +{{< code-toggle file=hugo >}} +[module] +[[module.mounts]] + source="content" + target="content" +[[module.mounts]] + source="static" + target="static" +[[module.mounts]] + source="layouts" + target="layouts" +[[module.mounts]] + source="data" + target="data" +[[module.mounts]] + source="assets" + target="assets" +[[module.mounts]] + source="i18n" + target="i18n" +[[module.mounts]] + source="archetypes" + target="archetypes" +{{< /code-toggle >}} + +source +: The source directory of the mount. For the main project, this can be either project-relative or absolute and even a symbolic link. For other modules it must be project-relative. + +target +: Where it should be mounted into Hugo's virtual filesystem. It must start with one of Hugo's component folders: `static`, `content`, `layouts`, `data`, `assets`, `i18n`, or `archetypes`. E.g. `content/blog`. + +lang +: The language code, e.g. "en". Only relevant for `content` mounts, and `static` mounts when in multihost mode. + +includeFiles (string or slice) +: One or more [glob](https://github.com/gobwas/glob) patterns matching files or directories to include. If `excludeFiles` is not set, the files matching `includeFiles` will be the files mounted. + +The glob patterns are matched to the file names starting from the `source` root, they should have Unix styled slashes even on Windows, `/` matches the mount root and `**` can be used as a super-asterisk to match recursively down all directories, e.g `/posts/**.jpg`. + +The search is case-insensitive. + +excludeFiles (string or slice) +: One or more glob patterns matching files to exclude. + +**Example** +{{< code-toggle file=hugo >}} +[module] +[[module.mounts]] + source="content" + target="content" + excludeFiles="docs/*" +[[module.mounts]] + source="node_modules" + target="assets" +[[module.mounts]] + source="assets" + target="assets" +{{< /code-toggle >}} diff --git a/docs/content/en/hugo-modules/theme-components.md b/docs/content/en/hugo-modules/theme-components.md new file mode 100644 index 000000000..947a0ff79 --- /dev/null +++ b/docs/content/en/hugo-modules/theme-components.md @@ -0,0 +1,45 @@ +--- +title: Theme components +description: Hugo provides advanced theming support with Theme Components. +categories: [hugo modules] +keywords: [modules,themes] +menu: + docs: + parent: modules + weight: 40 +weight: 40 +aliases: [/themes/customize/,/themes/customizing/] +toc: true +--- + +{{% note %}} +This section contain information that may be outdated and is in the process of being rewritten. +{{% /note %}} +Since Hugo `0.42` a project can configure a theme as a composite of as many theme components you need: + +{{< code-toggle file=hugo >}} +theme = ["my-shortcodes", "base-theme", "hyde"] +{{< /code-toggle >}} + +You can even nest this, and have the theme component itself include theme components in its own `hugo.toml` (theme inheritance).[^1] + +The theme definition example above in `hugo.toml` creates a theme with 3 theme components with precedence from left to right. + +For any given file, data entry, etc., Hugo will look first in the project and then in `my-shortcodes`, `base-theme`, and lastly `hyde`. + +Hugo uses two different algorithms to merge the file systems, depending on the file type: + +* For `i18n` and `data` files, Hugo merges deeply using the translation ID and data key inside the files. +* For `static`, `layouts` (templates), and `archetypes` files, these are merged on file level. So the left-most file will be chosen. + +The name used in the `theme` definition above must match a folder in `/your-site/themes`, e.g. `/your-site/themes/my-shortcodes`. There are plans to improve on this and get a URL scheme so this can be resolved automatically. + +Also note that a component that is part of a theme can have its own configuration file, e.g. `hugo.toml`. There are currently some restrictions to what a theme component can configure: + +* `params` (global and per language) +* `menu` (global and per language) +* `outputformats` and `mediatypes` + +The same rules apply here: The left-most parameter/menu etc. with the same ID will win. There are some hidden and experimental namespace support in the above, which we will work to improve in the future, but theme authors are encouraged to create their own namespaces to avoid naming conflicts. + +[^1]: For themes hosted on the [Hugo Themes Showcase](https://themes.gohugo.io/) components need to be added as git submodules that point to the directory `exampleSite/themes` diff --git a/docs/content/en/hugo-modules/use-modules.md b/docs/content/en/hugo-modules/use-modules.md new file mode 100644 index 000000000..295ff2061 --- /dev/null +++ b/docs/content/en/hugo-modules/use-modules.md @@ -0,0 +1,161 @@ +--- +title: Use Hugo Modules +description: How to use Hugo Modules to build and manage your site. +categories: [hugo modules] +keywords: [modules,themes] +menu: + docs: + parent: modules + weight: 30 +weight: 30 +aliases: [/themes/usage/,/themes/installing/,/installing-and-using-themes/] +toc: true +--- + +## Prerequisite + +{{< gomodules-info >}} + +## Initialize a new module + +Use `hugo mod init` to initialize a new Hugo Module. If it fails to guess the module path, you must provide it as an argument, e.g.: + +```sh +hugo mod init github.com/gohugoio/myShortcodes +``` + +Also see the [CLI Doc](/commands/hugo_mod_init/). + +## Use a module for a theme + +The easiest way to use a Module for a theme is to import it in the configuration. + +1. Initialize the hugo module system: `hugo mod init github.com/<your_user>/<your_project>` +2. Import the theme: + +{{< code-toggle file=hugo >}} +[module] + [[module.imports]] + path = "github.com/spf13/hyde" +{{< /code-toggle >}} + +## Update modules + +Modules will be downloaded and added when you add them as imports to your configuration, see [Module Imports](/hugo-modules/configuration/#module-configuration-imports). + +To update or manage versions, you can use `hugo mod get`. + +Some examples: + +### Update all modules + +```sh +hugo mod get -u +``` + +### Update all modules recursively + +```sh +hugo mod get -u ./... +``` + +### Update one module + +```sh +hugo mod get -u github.com/gohugoio/myShortcodes +``` + +### Get a specific version + +```sh +hugo mod get github.com/gohugoio/myShortcodes@v1.0.7 +``` + +Also see the [CLI Doc](/commands/hugo_mod_get/). + +## Make and test changes in a module + +One way to do local development of a module imported in a project is to add a replace directive to a local directory with the source in `go.mod`: + +```sh +replace github.com/bep/hugotestmods/mypartials => /Users/bep/hugotestmods/mypartials +``` + +If you have the `hugo server` running, the configuration will be reloaded and `/Users/bep/hugotestmods/mypartials` put on the watch list. + +Instead of modifying the `go.mod` files, you can also use the modules configuration [`replacements`](/hugo-modules/configuration/#module-configuration-top-level) option. + +## Print dependency graph + +Use `hugo mod graph` from the relevant module directory and it will print the dependency graph, including vendoring, module replacement or disabled status. + +E.g.: + +```txt +hugo mod graph + +github.com/bep/my-modular-site github.com/bep/hugotestmods/mymounts@v1.2.0 +github.com/bep/my-modular-site github.com/bep/hugotestmods/mypartials@v1.0.7 +github.com/bep/hugotestmods/mypartials@v1.0.7 github.com/bep/hugotestmods/myassets@v1.0.4 +github.com/bep/hugotestmods/mypartials@v1.0.7 github.com/bep/hugotestmods/myv2@v1.0.0 +DISABLED github.com/bep/my-modular-site github.com/spf13/hyde@v0.0.0-20190427180251-e36f5799b396 +github.com/bep/my-modular-site github.com/bep/hugo-fresh@v1.0.1 +github.com/bep/my-modular-site in-themesdir +``` + +Also see the [CLI Doc](/commands/hugo_mod_graph/). + +## Vendor your modules + +`hugo mod vendor` will write all the module dependencies to a `_vendor` folder, which will then be used for all subsequent builds. + +Note that: + +* You can run `hugo mod vendor` on any level in the module tree. +* Vendoring will not store modules stored in your `themes` folder. +* Most commands accept a `--ignoreVendorPaths` flag, which will then not use the vendored modules in `_vendor` for the module paths matching the [Glob](https://github.com/gobwas/glob) pattern given. + +Also see the [CLI Doc](/commands/hugo_mod_vendor/). + +## Tidy go.mod, go.sum + +Run `hugo mod tidy` to remove unused entries in `go.mod` and `go.sum`. + +Also see the [CLI Doc](/commands/hugo_mod_clean/). + +## Clean module cache + +Run `hugo mod clean` to delete the entire modules cache. + +Note that you can also configure the `modules` cache with a `maxAge`, see [File Caches](/getting-started/configuration/#configure-file-caches). + +Also see the [CLI Doc](/commands/hugo_mod_clean/). + +## Module workspaces + +{{< new-in 0.109.0 >}} + +Workspace support was added in [Go 1.18](https://go.dev/blog/get-familiar-with-workspaces) and Hugo got solid support for it in the `v0.109.0` version. + +A common use case for a workspace is to simplify local development of a site with its theme modules. + +A workspace can be configured in a `*.work` file and activated with the [module.workspace](/hugo-modules/configuration/) setting, which for this use is commonly controlled via the `HUGO_MODULE_WORKSPACE` OS environment variable. + +See the [hugo.work](https://github.com/gohugoio/hugo/blob/master/docs/hugo.work) file in the Hugo Docs repo for an example: + +```text +go 1.20 + +use . +use ../gohugoioTheme +``` + +Using the `use` directive, list all the modules you want to work on, pointing to its relative location. As in the example above, it's recommended to always include the main project (the ".") in the list. + +With that you can start the Hugo server with that workspace enabled: + +```sh +HUGO_MODULE_WORKSPACE=hugo.work hugo server --ignoreVendorPaths "**" +``` + +The `--ignoreVendorPaths` flag is added above to ignore any of the vendored dependencies inside `_vendor`. If you don't use vendoring, you don't need that flag. But now the server is set up watching the files and directories in the workspace and you can see your local edits reloaded. diff --git a/docs/content/en/hugo-pipes/_index.md b/docs/content/en/hugo-pipes/_index.md new file mode 100755 index 000000000..edc41b7a2 --- /dev/null +++ b/docs/content/en/hugo-pipes/_index.md @@ -0,0 +1,12 @@ +--- +title: Hugo Pipes +linkTitle: Overview +categories: [] +keywords: [] +menu: + docs: + identifier: hugo-pipes-overview + parent: hugo-pipes + weight: 10 +weight: 10 +--- diff --git a/docs/content/en/hugo-pipes/babel.md b/docs/content/en/hugo-pipes/babel.md new file mode 100755 index 000000000..c447983a9 --- /dev/null +++ b/docs/content/en/hugo-pipes/babel.md @@ -0,0 +1,76 @@ +--- +title: Babel +description: Hugo Pipes can process JS files with Babel. +categories: [asset management] +keywords: [] +menu: + docs: + parent: hugo-pipes + weight: 70 +weight: 70 +function: + aliases: [babel] + returnType: resource.Resource + signatures: ['resources.Babel [OPTIONS] RESOURCE'] +--- + +## Usage + +Any JavaScript resource file can be transpiled to another JavaScript version using `resources.Babel` which takes for argument the resource object and an optional dict of options listed below. Babel uses the [babel cli](https://babeljs.io/docs/en/babel-cli). + +{{% note %}} +Hugo Pipe's Babel requires the `@babel/cli` and `@babel/core` JavaScript packages to be installed in the project or globally (`npm install -g @babel/cli @babel/core`) along with any Babel plugin(s) or preset(s) used (e.g., `npm install @babel/preset-env --save-dev`). + +If you are using the Hugo Snap package, Babel and plugin(s) need to be installed locally within your Hugo site directory, e.g., `npm install @babel/cli @babel/core --save-dev` without the `-g` flag. +{{% /note %}} + +## Configuration + +We add the main project's `node_modules` to `NODE_PATH` when running Babel and similar tools. There are some known [issues](https://github.com/babel/babel/issues/5618) with Babel in this area, so if you have a `babel.config.js` living in a Hugo Module (and not in the project itself), we recommend using `require` to load the presets/plugins, e.g.: + +```js +module.exports = { + presets: [ + [ + require("@babel/preset-env"), + { + useBuiltIns: "entry", + corejs: 3, + }, + ], + ], +}; +``` + +## Options + +config +: (`string`) Path to the Babel configuration file. Hugo will, by default, look for a `babel.config.js` in your project. More information on these configuration files can be found here: [babel configuration](https://babeljs.io/docs/en/configuration). + +minified +: (`bool`) Save as many bytes as possible when printing + +noComments +: (`bool`) Write comments to generated output (true by default) + +compact +: (`bool`) Do not include superfluous whitespace characters and line terminators. Defaults to `auto` if not set. + +verbose +: (`bool`) Log everything + +sourceMap +: (`string`) Output `inline` or `external` sourcemap from the babel compile. External sourcemaps will be written to the target with the output file name + ".map". Input sourcemaps can be read from js.Build and node modules and combined into the output sourcemaps. + +## Examples + +```go-html-template +{{- $transpiled := resources.Get "scripts/main.js" | babel -}} +``` + +Or with options: + +```go-html-template +{{ $opts := dict "noComments" true }} +{{- $transpiled := resources.Get "scripts/main.js" | babel $opts -}} +``` diff --git a/docs/content/en/hugo-pipes/bundling.md b/docs/content/en/hugo-pipes/bundling.md new file mode 100755 index 000000000..7fc9fc9df --- /dev/null +++ b/docs/content/en/hugo-pipes/bundling.md @@ -0,0 +1,26 @@ +--- +title: Concat +linkTitle: Concatenating assets +description: Bundle any number of assets into one resource. +categories: [asset management] +keywords: [] +menu: + docs: + parent: hugo-pipes + weight: 90 +weight: 90 +action: + aliases: [] + returnType: resource.Resource + signatures: ['resources.Concat TARGETPATH [RESOURCE...]'] +--- + +## Usage + +Asset files of the same MIME type can be bundled into one resource using `resources.Concat` which takes two arguments, the target path for the created resource bundle and a slice of resource objects to be concatenated. + +```go-html-template +{{ $plugins := resources.Get "js/plugins.js" }} +{{ $global := resources.Get "js/global.js" }} +{{ $js := slice $plugins $global | resources.Concat "js/bundle.js" }} +``` diff --git a/docs/content/en/hugo-pipes/fingerprint.md b/docs/content/en/hugo-pipes/fingerprint.md new file mode 100755 index 000000000..68e41acd1 --- /dev/null +++ b/docs/content/en/hugo-pipes/fingerprint.md @@ -0,0 +1,30 @@ +--- +title: Fingerprint +linkTitle: Fingerprinting and SRI hashing +description: Process a given resource, adding a hash string of the resource's content. +categories: [asset management] +keywords: [] +menu: + docs: + parent: hugo-pipes + weight: 100 +weight: 100 +action: + aliases: [fingerprint] + returnType: resource.Resource + signatures: ['resources.Fingerprint [ALGORITHM] RESOURCE'] +--- + +## Usage + +Fingerprinting and [SRI](https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity) can be applied to any asset file using `resources.Fingerprint` which takes two arguments, the resource object and an optional [hash algorithm](https://en.wikipedia.org/wiki/Secure_Hash_Algorithms). + +The default hash algorithm is `sha256`. Other available algorithms are `sha384` and (as of Hugo `0.55`) `sha512` and `md5`. + +Any so processed asset will bear a `.Data.Integrity` property containing an integrity string, which is made up of the name of the hash algorithm, one hyphen and the base64-encoded hash sum. + +```go-html-template +{{ $js := resources.Get "js/global.js" }} +{{ $secureJS := $js | resources.Fingerprint "sha512" }} +<script src="{{ $secureJS.Permalink }}" integrity="{{ $secureJS.Data.Integrity }}"></script> +``` diff --git a/docs/content/en/hugo-pipes/introduction.md b/docs/content/en/hugo-pipes/introduction.md new file mode 100755 index 000000000..c993377f8 --- /dev/null +++ b/docs/content/en/hugo-pipes/introduction.md @@ -0,0 +1,79 @@ +--- +title: Hugo Pipes +linkTitle: Introduction +description: Hugo Pipes is Hugo's asset processing set of functions. +categories: [asset management] +keywords: [] +menu: + docs: + parent: hugo-pipes + weight: 20 +weight: 20 +toc: true +aliases: [/assets/] +--- + +## Find resources in assets + +This is about global and remote resources. + +global resource +: A file within the assets directory, or within any directory [mounted] to the assets directory. + +remote resource +: A file on a remote server, accessible via HTTP or HTTPS. + +For `.Page` scoped resources, see the [page resources] section. + +[mounted]: /hugo-modules/configuration/#module-configuration-mounts +[page resources]: /content-management/page-resources/ + +## Get a resource + +In order to process an asset with Hugo Pipes, it must be retrieved as a resource. + +For global resources, use: + +- [`resources.ByType`](/functions/resources/bytype/) +- [`resources.Get`](/functions/resources/get/) +- [`resources.GetMatch`](/functions/resources/getmatch/) +- [`resources.Match`](/functions/resources/match/) + +For remote resources, use: + +- [`resources.GetRemote`](/functions/resources/getremote/) + +See the [GoDoc Page](https://pkg.go.dev/github.com/gohugoio/hugo/tpl/resources) for the `resources` package for an up to date overview of all template functions in this namespace. + +## Copy a resource + +See the [`resources.Copy`](/functions/resources/copy/) function. + +## Asset directory + +Asset files must be stored in the asset directory. This is `/assets` by default, but can be configured via the configuration file's `assetDir` key. + +## Asset publishing + +Hugo publishes assets to the `publishDir` (typically `public`) when you invoke `.Permalink`, `.RelPermalink`, or `.Publish`. You can use `.Content` to inline the asset. + +## Go Pipes + +For improved readability, the Hugo Pipes examples of this documentation will be written using [Go Pipes](/templates/introduction/#pipes): + +```go-html-template +{{ $style := resources.Get "sass/main.scss" | resources.ToCSS | resources.Minify | resources.Fingerprint }} +<link rel="stylesheet" href="{{ $style.Permalink }}"> +``` + +## Caching + +Hugo Pipes invocations are cached based on the entire *pipe chain*. + +An example of a pipe chain is: + +```go-html-template +{{ $mainJs := resources.Get "js/main.js" | js.Build "main.js" | minify | fingerprint }} +``` + +The pipe chain is only invoked the first time it is encountered in a site build, and results are otherwise loaded from cache. As such, Hugo Pipes can be used in templates which are executed thousands or millions of times without negatively impacting the build performance. diff --git a/docs/content/en/hugo-pipes/js.md b/docs/content/en/hugo-pipes/js.md new file mode 100644 index 000000000..9d2bbbd82 --- /dev/null +++ b/docs/content/en/hugo-pipes/js.md @@ -0,0 +1,166 @@ +--- +title: js.Build +linkTitle: JavaScript building +description: Bundle, transpile, tree shake, and minify JavaScript resources. +categories: [asset management] +keywords: [] +menu: + docs: + parent: hugo-pipes + weight: 60 +weight: 60 +action: + aliases: [] + returnType: resource.Resource + signatures: ['js.Build [OPTIONS] RESOURCE'] +--- + +## Usage + +Any JavaScript resource file can be transpiled and "tree shaken" using `js.Build` which takes for argument either a string for the filepath or a dict of options listed below. + +### Options + +targetPath +: (`string`) If not set, the source path will be used as the base target path. +Note that the target path's extension may change if the target MIME type is different, e.g. when the source is TypeScript. + +params {{< new-in "0.96.0" >}} +: (`map` or `slice`) Params that can be imported as JSON in your JS files, e.g.: + +```go-html-template +{{ $js := resources.Get "js/main.js" | js.Build (dict "params" (dict "api" "https://example.org/api")) }} +``` +And then in your JS file: + +```js +import * as params from '@params'; +``` + +Note that this is meant for small data sets, e.g. configuration settings. For larger data, please put/mount the files into `/assets` and import them directly. + +minify +: (`bool`) Let `js.Build` handle the minification. + +inject +: (`slice`) This option allows you to automatically replace a global variable with an import from another file. The path names must be relative to `assets`. See https://esbuild.github.io/api/#inject + +shims +: (`map`) This option allows swapping out a component with another. A common use case is to load dependencies like React from a CDN (with _shims_) when in production, but running with the full bundled `node_modules` dependency during development: + +```go-html-template +{{ $shims := dict "react" "js/shims/react.js" "react-dom" "js/shims/react-dom.js" }} +{{ $js = $js | js.Build dict "shims" $shims }} +``` + +The _shim_ files may look like these: + +```js +// js/shims/react.js +module.exports = window.React; +``` + +```js +// js/shims/react-dom.js +module.exports = window.ReactDOM; +``` + +With the above, these imports should work in both scenarios: + +```js +import * as React from 'react' +import * as ReactDOM from 'react-dom'; +``` + +target +: (`string`) The language target. + One of: `es5`, `es2015`, `es2016`, `es2017`, `es2018`, `es2019`, `es2020` or `esnext`. + Default is `esnext`. + +externals +: (`slice`) External dependencies. Use this to trim dependencies you know will never be executed. See https://esbuild.github.io/api/#external + +defines +: (`map`) Allow to define a set of string replacement to be performed when building. Should be a map where each key is to be replaced by its value. + +```go-html-template +{{ $defines := dict "process.env.NODE_ENV" `"development"` }} +``` + +format +: (`string`) The output format. + One of: `iife`, `cjs`, `esm`. + Default is `iife`, a self-executing function, suitable for inclusion as a `<script>` tag. + +sourceMap +: (`string`) Whether to generate `inline` or `external` source maps from esbuild. External source maps will be written to the target with the output file name + ".map". Input source maps can be read from js.Build and node modules and combined into the output source maps. By default, source maps are not created. + +### Import JS code from /assets + +`js.Build` has full support for the virtual union file system in [Hugo Modules](/hugo-modules/). You can see some simple examples in this [test project](https://github.com/gohugoio/hugoTestProjectJSModImports), but in short this means that you can do this: + +```js +import { hello } from 'my/module'; +``` + +And it will resolve to the top-most `index.{js,ts,tsx,jsx}` inside `assets/my/module` in the layered file system. + +```js +import { hello3 } from 'my/module/hello3'; +``` + +Will resolve to `hello3.{js,ts,tsx,jsx}` inside `assets/my/module`. + +Any imports starting with `.` is resolved relative to the current file: + +```js +import { hello4 } from './lib'; +``` + +For other files (e.g. `JSON`, `CSS`) you need to use the relative path including any extension, e.g: + +```js +import * as data from 'my/module/data.json'; +``` + +Any imports in a file outside `/assets` or that does not resolve to a component inside `/assets` will be resolved by [ESBuild](https://esbuild.github.io/) with the **project directory** as the resolve directory (used as the starting point when looking for `node_modules` etc.). Also see [hugo mod npm pack](/commands/hugo_mod_npm_pack/). If you have any imported npm dependencies in your project, you need to make sure to run `npm install` before you run `hugo`. + +Also note the new `params` option that can be passed from template to your JS files, e.g.: + +```go-html-template +{{ $js := resources.Get "js/main.js" | js.Build (dict "params" (dict "api" "https://example.org/api")) }} +``` +And then in your JS file: + +```js +import * as params from '@params'; +``` + +Hugo will, by default, generate a `assets/jsconfig.json` file that maps the imports. This is useful for navigation/intellisense help inside code editors, but if you don't need/want it, you can [turn it off](/getting-started/configuration/#configure-build). + +### Include dependencies In package.json / node_modules + +Any imports in a file outside `/assets` or that does not resolve to a component inside `/assets` will be resolved by [ESBuild](https://esbuild.github.io/) with the **project directory** as the resolve directory (used as the starting point when looking for `node_modules` etc.). Also see [hugo mod npm pack](/commands/hugo_mod_npm_pack/). If you have any imported npm dependencies in your project, you need to make sure to run `npm install` before you run `hugo`. + +The start directory for resolving npm packages (aka. packages that live inside a `node_modules` folder) is always the main project folder. + +{{% note %}} +If you're developing a theme/component that is supposed to be imported and depends on dependencies inside `package.json`, we recommend reading about [hugo mod npm pack](/commands/hugo_mod_npm_pack/), a tool to consolidate all the npm dependencies in a project. +{{% /note %}} + +### Examples + +```go-html-template +{{ $built := resources.Get "js/index.js" | js.Build "main.js" }} +``` + +Or with options: + +```go-html-template +{{ $externals := slice "react" "react-dom" }} +{{ $defines := dict "process.env.NODE_ENV" `"development"` }} + +{{ $opts := dict "targetPath" "main.js" "externals" $externals "defines" $defines }} +{{ $built := resources.Get "scripts/main.js" | js.Build $opts }} +<script src="{{ $built.RelPermalink }}" defer></script> +``` diff --git a/docs/content/en/hugo-pipes/minification.md b/docs/content/en/hugo-pipes/minification.md new file mode 100755 index 000000000..a5d4724f9 --- /dev/null +++ b/docs/content/en/hugo-pipes/minification.md @@ -0,0 +1,27 @@ +--- +title: Minify +linkTitle: Asset minification +description: Minifies a given resource. +categories: [asset management] +keywords: [] +menu: + docs: + parent: hugo-pipes + weight: 80 +weight: 80 +action: + aliases: [minify] + returnType: resource.Resource + signatures: [resources.Minify RESOURCE] +--- + +## Usage + +Any CSS, JS, JSON, HTML, SVG, or XML resource can be minified using `resources.Minify` which takes for argument the resource object. + +```go-html-template +{{ $css := resources.Get "css/main.css" }} +{{ $style := $css | resources.Minify }} +``` + +Note that you can also minify the final HTML output to `/public` by running `hugo --minify`. diff --git a/docs/content/en/hugo-pipes/postcss.md b/docs/content/en/hugo-pipes/postcss.md new file mode 100755 index 000000000..148b30a7e --- /dev/null +++ b/docs/content/en/hugo-pipes/postcss.md @@ -0,0 +1,131 @@ +--- +title: PostCSS +description: Process CSS files with PostCSS, using any of the available plugins. +categories: [asset management] +keywords: [] +menu: + docs: + parent: hugo-pipes + weight: 40 +weight: 40 +toc: true +action: + aliases: [postCSS] + returnType: resource.Resource + signatures: ['resources.PostCSS [OPTIONS] RESOURCE'] +--- + +## Setup + +Follow the steps below to transform CSS using any of the [available PostCSS plugins](https://www.postcss.parts/). + +Step 1 +: Install [Node.js](https://nodejs.org/en/download). + +Step 2 +: Install the required Node.js packages in the root of your project. For example, to add vendor prefixes to CSS rules: + +```sh +npm i -D postcss postcss-cli autoprefixer +``` + +Step 3 +: Create a PostCSS configuration file in the root of your project. You must name this file `postcss.config.js` or one of the other [supported file names]. For example: + +[supported file names]: https://github.com/postcss/postcss-load-config#usage + +{{< code file=postcss.config.js >}} +module.exports = { + plugins: [ + require('autoprefixer') + ] +}; +{{< /code >}} + +{{% note %}} +If you are a Windows user, and the path to your project contains a space, you must place the PostCSS configuration within the package.json file. See [this example](https://github.com/postcss/postcss-load-config#packagejson) and issue [#7333](https://github.com/gohugoio/hugo/issues/7333). +{{% /note %}} + +Step 4 +: Place your CSS file within the `assets` directory. + +Step 5 +: Capture the CSS file as a resource and pipe it through `resources.PostCSS` (alias `postCSS`): + +{{< code file=layouts/partials/css.html >}} +{{ with resources.Get "css/main.css" | postCSS }} + <link rel="stylesheet" href="{{ .RelPermalink }}"> +{{ end }} +{{< /code >}} + +If starting with a Sass file within the `assets` directory: + +{{< code file=layouts/partials/css.html >}} +{{ with resources.Get "sass/main.scss" | toCSS | postCSS }} + <link rel="stylesheet" href="{{ .RelPermalink }}"> +{{ end }} +{{< /code >}} + +## Options + +The `resources.PostCSS` method takes an optional map of options. + +config +: (`string`) The directory that contains the PostCSS configuration file. Default is the root of the project directory. + +noMap +: (`bool`) Default is `false`. If `true`, disables inline sourcemaps. + +inlineImports +: (`bool`) Default is `false`. Enable inlining of @import statements. It does so recursively, but will only import a file once. +URL imports (e.g. `@import url('https://fonts.googleapis.com/css?family=Open+Sans&display=swap');`) and imports with media queries will be ignored. +Note that this import routine does not care about the CSS spec, so you can have @import anywhere in the file. +Hugo will look for imports relative to the module mount and will respect theme overrides. + +skipInlineImportsNotFound {{< new-in 0.99.0 >}} +: (`bool`) Default is `false`. Before Hugo 0.99.0 when `inlineImports` was enabled and we failed to resolve an import, we logged it as a warning. We now fail the build. If you have regular CSS imports in your CSS that you want to preserve, you can either use imports with URL or media queries (Hugo does not try to resolve those) or set `skipInlineImportsNotFound` to true. + +{{< code file=layouts/partials/css.html >}} +{{ $opts := dict "config" "config-directory" "noMap" true }} +{{ with resources.Get "css/main.css" | postCSS $opts }} + <link rel="stylesheet" href="{{ .RelPermalink }}"> +{{ end }} +{{< /code >}} + +## No configuration file + +To avoid using a PostCSS configuration file, you can specify a minimal configuration using the options map. + +use +: (`string`) A space-delimited list of PostCSS plugins to use. + +parser +: (`string`) A custom PostCSS parser. + +stringifier +: (`string`) A custom PostCSS stringifier. + +syntax +: (`string`) Custom postcss syntax. + +{{< code file=layouts/partials/css.html >}} +{{ $opts := dict "use" "autoprefixer postcss-color-alpha" }} +{{ with resources.Get "css/main.css" | postCSS $opts }} + <link rel="stylesheet" href="{{ .RelPermalink }}"> +{{ end }} +{{< /code >}} + +## Check Hugo environment + +The current Hugo environment name (set by `--environment` or in configuration or OS environment) is available in the Node context, which allows constructs like this: + +{{< code file=postcss.config.js >}} +module.exports = { + plugins: [ + require('autoprefixer'), + ...process.env.HUGO_ENVIRONMENT === 'production' + ? [purgecss] + : [] + ] +} +{{< /code >}} diff --git a/docs/content/en/hugo-pipes/postprocess.md b/docs/content/en/hugo-pipes/postprocess.md new file mode 100755 index 000000000..e84c6d72d --- /dev/null +++ b/docs/content/en/hugo-pipes/postprocess.md @@ -0,0 +1,104 @@ +--- +title: PostProcess +description: Allows delaying of resource transformations to after the build. +categories: [asset management] +keywords: [] +menu: + docs: + parent: hugo-pipes + weight: 50 +weight: 50 +action: + aliases: [] + returnType: postpub.PostPublishedResource + signatures: [resources.PostProcess RESOURCE] +--- + +## Usage + +Marking a resource with `resources.PostProcess` delays any transformations to after the build, typically because one or more of the steps in the transformation chain depends on the result of the build (e.g. files in `public`). + +A prime use case for this is [CSS purging with PostCSS](#css-purging-with-postcss). + +There are currently two limitations to this: + +1. This only works in `*.html` templates (i.e. templates that produces HTML files). +2. You cannot manipulate the values returned from the resource's methods. E.g. the `upper` in this example will not work as expected: + + ```go-html-template + {{ $css := resources.Get "css/main.css" }} + {{ $css = $css | resources.PostCSS | minify | fingerprint | resources.PostProcess }} + {{ $css.RelPermalink | upper }} + ``` + +## CSS purging with PostCSS + +{{% note %}} +There are several ways to set up CSS purging with PostCSS in Hugo. If you have a simple project, you should consider going the simpler route and drop the use of `resources.PostProcess` and just extract keywords from the templates. See the [Tailwind documentation](https://tailwindcss.com/docs/controlling-file-size/#app) for some examples. +{{% /note %}} + +The below configuration will write a `hugo_stats.json` file to the project root as part of the build. If you're only using this for the production build, you should consider placing it below [config/production](/getting-started/configuration/#configuration-directory). + +{{< code-toggle file=hugo >}} +[build.buildStats] + enable = true +{{< /code-toggle >}} + +See the [configure build] documentation for details and options. + +[configure build]: /getting-started/configuration/#configure-build + +`postcss.config.js` + +```js +const purgecss = require('@fullhuman/postcss-purgecss')({ + content: [ './hugo_stats.json' ], + defaultExtractor: (content) => { + let els = JSON.parse(content).htmlElements; + return els.tags.concat(els.classes, els.ids); + } +}); + +module.exports = { + plugins: [ + ...(process.env.HUGO_ENVIRONMENT === 'production' ? [ purgecss ] : []) + ] + }; +``` + +Note that in the example above, the "CSS purge step" will only be applied to the production build. This means that you need to do something like this in your head template to build and include your CSS: + +```go-html-template +{{ $css := resources.Get "css/main.css" }} +{{ $css = $css | resources.PostCSS }} +{{ if hugo.IsProduction }} +{{ $css = $css | minify | fingerprint | resources.PostProcess }} +{{ end }} +<link href="{{ $css.RelPermalink }}" rel="stylesheet" /> +``` + +## Hugo environment variables available in PostCSS + +These are the environment variables Hugo passes down to PostCSS (and Babel), which allows you do do `process.env.HUGO_ENVIRONMENT === 'production' ? [autoprefixer] : []` and similar: + +PWD +: The absolute path to the project working directory. + +HUGO_ENVIRONMENT +: The value e.g. set with `hugo -e production` (defaults to `production` for `hugo` and `development` for `hugo server`). + +HUGO_PUBLISHDIR +: {{< new-in 0.109.0 >}} The absolute path to the publish directory (the `public` directory). Note that the value will always point to a directory on disk even when running `hugo server` in memory mode. If you write to this folder from PostCSS when running the server, you could run the server with one of these flags: + +```sh +hugo server --renderToDisk +hugo server --renderStaticToDisk +``` + +Also, Hugo will add environment variables for all files mounted below `assets/_jsconfig`. A default mount will be set up with files in the project root matching this regexp: `(babel|postcss|tailwind)\.config\.js`. + +These will get environment variables named on the form `HUGO_FILE_:filename:` where `:filename:` is all upper case with periods replaced with underscore. This allows you to do this and similar: + +```js +let tailwindConfig = process.env.HUGO_FILE_TAILWIND_CONFIG_JS || './tailwind.config.js'; +``` diff --git a/docs/content/en/hugo-pipes/resource-from-string.md b/docs/content/en/hugo-pipes/resource-from-string.md new file mode 100755 index 000000000..53bcfff74 --- /dev/null +++ b/docs/content/en/hugo-pipes/resource-from-string.md @@ -0,0 +1,34 @@ +--- +title: FromString +linkTitle: Resource from string +description: Creates a resource from a string. +categories: [asset management] +keywords: [] +menu: + docs: + parent: hugo-pipes + weight: 110 +weight: 110 +action: + aliases: [] + returnType: resource.Resource + signatures: [resources.FromString TARGETPATH STRING] +--- + +## Usage + +It is possible to create a resource directly from the template using `resources.FromString` which takes two arguments, the target path for the created resource and the given content string. + +The result is cached using the target path as the cache key. + +The following example creates a resource file containing localized variables for every project's languages. + +```go-html-template +{{ $string := (printf "var rootURL = '%s'; var apiURL = '%s';" (absURL "/") (.Param "API_URL")) }} +{{ $targetPath := "js/vars.js" }} +{{ $vars := $string | resources.FromString $targetPath }} +{{ $global := resources.Get "js/global.js" | resources.Minify }} + +<script src="{{ $vars.Permalink }}"></script> +<script src="{{ $global.Permalink }}"></script> +``` diff --git a/docs/content/en/hugo-pipes/resource-from-template.md b/docs/content/en/hugo-pipes/resource-from-template.md new file mode 100755 index 000000000..1627fa7d4 --- /dev/null +++ b/docs/content/en/hugo-pipes/resource-from-template.md @@ -0,0 +1,38 @@ +--- +title: ExecuteAsTemplate +linkTitle: Resource from template +description: Creates a resource from a template +categories: [asset management] +keywords: [] +menu: + docs: + parent: hugo-pipes + weight: 120 +weight: 120 +action: + aliases: [] + returnType: resource.Resource + signatures: [resources.ExecuteAsTemplate TARGETPATH CONTEXT RESOURCE] +--- + +## Usage + +In order to use Hugo Pipes function on an asset file containing Go Template magic the function `resources.ExecuteAsTemplate` must be used. + +The function takes three arguments: the target path for the created resource, the template context, and the resource object. The target path is used to cache the result. + +```go-html-template +// assets/sass/template.scss +$backgroundColor: {{ .Param "backgroundColor" }}; +$textColor: {{ .Param "textColor" }}; +body{ + background-color:$backgroundColor; + color: $textColor; +} +// [...] +``` + +```go-html-template +{{ $sassTemplate := resources.Get "sass/template.scss" }} +{{ $style := $sassTemplate | resources.ExecuteAsTemplate "main.scss" . | resources.ToCSS }} +``` diff --git a/docs/content/en/hugo-pipes/transpile-sass-to-css.md b/docs/content/en/hugo-pipes/transpile-sass-to-css.md new file mode 100644 index 000000000..998adad82 --- /dev/null +++ b/docs/content/en/hugo-pipes/transpile-sass-to-css.md @@ -0,0 +1,213 @@ +--- +title: ToCSS +linkTitle: Transpile Sass to CSS +description: Transpile Sass to CSS. +categories: [asset management] +keywords: [] +menu: + docs: + parent: hugo-pipes + returnType: resource.Resource + weight: 30 +weight: 30 +action: + aliases: [toCSS] + returnType: resource.Resource + signatures: ['resources.ToCSS [OPTIONS] RESOURCE'] +toc: true +aliases: [/hugo-pipes/transform-to-css/] +--- + +## Usage + +Transpile Sass to CSS using the LibSass transpiler included in Hugo's extended edition, or [install Dart Sass](#dart-sass) to use the latest features of the Sass language. + +```go-html-template +{{ $opts := dict "transpiler" "libsass" "targetPath" "css/style.css" }} +{{ with resources.Get "sass/main.scss" | toCSS $opts | minify | fingerprint }} + <link rel="stylesheet" href="{{ .RelPermalink }}" integrity="{{ .Data.Integrity }}" crossorigin="anonymous"> +{{ end }} +``` + +Sass has two forms of syntax: [SCSS] and [indented]. Hugo supports both. + +[scss]: https://sass-lang.com/documentation/syntax#scss +[indented]: https://sass-lang.com/documentation/syntax#the-indented-syntax + +## Options + +transpiler +: (`string`) The transpiler to use, either `libsass` (default) or `dartsass`. Hugo's extended edition includes the LibSass transpiler. To use the Dart Sass transpiler, see the [installation instructions](#dart-sass) below. + +targetPath +: (`string`) If not set, the transformed resource's target path will be the original path of the asset file with its extension replaced by `.css`. + +vars {{< new-in 0.109.0 >}} +: (`map`) A map of key/value pairs that will be available in the `hugo:vars` namespace. Useful for [initializing Sass variables from Hugo templates](https://discourse.gohugo.io/t/42053/). + +```scss +// LibSass +@import "hugo:vars"; + +// Dart Sass +@use "hugo:vars" as v; +``` + +outputStyle +: (`string`) Output styles available to LibSass include `nested` (default), `expanded`, `compact`, and `compressed`. Output styles available to Dart Sass include `expanded` (default) and `compressed`. + +precision +: (`int`) Precision of floating point math. Not applicable to Dart Sass. + +enableSourceMap +: (`bool`) If `true`, generates a source map. + +sourceMapIncludeSources {{< new-in 0.108.0 >}} +: (`bool`) If `true`, embeds sources in the generated source map. Not applicable to LibSass. + +includePaths +: (`slice`) A slice of paths, relative to the project root, that the transpiler will use when resolving `@use` and `@import` statements. + +```go-html-template +{{ $opts := dict + "transpiler" "dartsass" + "targetPath" "css/style.css" + "vars" site.Params.styles + "enableSourceMap" (not hugo.IsProduction) + "includePaths" (slice "node_modules/bootstrap/scss") +}} +{{ with resources.Get "sass/main.scss" | toCSS $opts | minify | fingerprint }} + <link rel="stylesheet" href="{{ .RelPermalink }}" integrity="{{ .Data.Integrity }}" crossorigin="anonymous"> +{{ end }} +``` + +## Dart Sass + +The extended version of Hugo includes [LibSass] to transpile Sass to CSS. In 2020, the Sass team deprecated LibSass in favor of [Dart Sass]. + +Use the latest features of the Sass language by installing Dart Sass in your development and production environments. + +### Installation overview + +Dart Sass is compatible with Hugo v0.114.0 and later. + +If you have been using Embedded Dart Sass[^1] with Hugo v0.113.0 and earlier, uninstall Embedded Dart Sass, then install Dart Sass. If you have installed both, Hugo will use Dart Sass. + +If you install Hugo as a [Snap package] there is no need to install Dart Sass. The Hugo Snap package includes Dart Sass. + +[^1]: In 2023, the Sass team deprecated Embedded Dart Sass in favor of Dart Sass. + +### Installing in a development environment + +When you install Dart Sass somewhere in your PATH, Hugo will find it. + +OS|Package manager|Site|Installation +:--|:--|:--|:-- +Linux|Homebrew|[brew.sh]|`brew install sass/sass/sass` +Linux|Snap|[snapcraft.io]|`sudo snap install dart-sass` +macOS|Homebrew|[brew.sh]|`brew install sass/sass/sass` +Windows|Chocolatey|[chocolatey.org]|`choco install sass` +Windows|Scoop|[scoop.sh]|`scoop install sass` + +You may also install [prebuilt binaries] for Linux, macOS, and Windows. + +Run `hugo env` to list the active transpilers. + +### Installing in a production environment + +For [CI/CD] deployments (e.g., GitHub Pages, GitLab Pages, Netlify, etc.) you must edit the workflow to install Dart Sass before Hugo builds the site[^2]. Some providers allow you to use one of the package managers above, or you can download and extract one of the prebuilt binaries. + +[^2]: You do not have to do this if (a) you have not modified the assets cache location, and (b) you have not set `useResourceCacheWhen` to `never` in your [site configuration], and (c) you add and commit your resources directory to your repository. + +#### GitHub Pages + +To install Dart Sass for your builds on GitHub Pages, add this step to the GitHub Pages workflow file: + +```yaml +- name: Install Dart Sass + run: sudo snap install dart-sass +``` + +If you are using GitHub Pages for the first time with your repository, GitHub provides a [starter workflow] for Hugo that includes Dart Sass. This is the simplest way to get started. + +#### GitLab Pages + +To install Dart Sass for your builds on GitLab Pages, the `.gitlab-ci.yml` file should look something like this: + +```yaml +variables: + HUGO_VERSION: 0.122.0 + DART_SASS_VERSION: 1.70.0 + GIT_DEPTH: 0 + GIT_STRATEGY: clone + GIT_SUBMODULE_STRATEGY: recursive + TZ: America/Los_Angeles +image: + name: golang:1.20-buster +pages: + script: + # Install Dart Sass + - curl -LJO https://github.com/sass/dart-sass/releases/download/${DART_SASS_VERSION}/dart-sass-${DART_SASS_VERSION}-linux-x64.tar.gz + - tar -xf dart-sass-${DART_SASS_VERSION}-linux-x64.tar.gz + - cp -r dart-sass/* /usr/local/bin + - rm -rf dart-sass* + # Install Hugo + - curl -LJO https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_extended_${HUGO_VERSION}_linux-amd64.deb + - apt install -y ./hugo_extended_${HUGO_VERSION}_linux-amd64.deb + - rm hugo_extended_${HUGO_VERSION}_linux-amd64.deb + # Build + - hugo --gc --minify + artifacts: + paths: + - public + rules: + - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH +``` + +#### Netlify + +To install Dart Sass for your builds on Netlify, the `netlify.toml` file should look something like this: + +```toml +[build.environment] +HUGO_VERSION = "0.122.2" +DART_SASS_VERSION = "1.70.0" +TZ = "America/Los_Angeles" + +[build] +publish = "public" +command = """\ + curl -LJO https://github.com/sass/dart-sass/releases/download/${DART_SASS_VERSION}/dart-sass-${DART_SASS_VERSION}-linux-x64.tar.gz && \ + tar -xf dart-sass-${DART_SASS_VERSION}-linux-x64.tar.gz && \ + rm dart-sass-${DART_SASS_VERSION}-linux-x64.tar.gz && \ + export PATH=/opt/build/repo/dart-sass:$PATH && \ + hugo --gc --minify \ + """ +``` + +### Example + +To transpile with Dart Sass, set `transpiler` to `dartsass` in the options map passed to `resources.ToCSS`. For example: + +```go-html-template +{{ $opts := dict "transpiler" "dartsass" "targetPath" "css/style.css" }} +{{ with resources.Get "sass/main.scss" | toCSS $opts | minify | fingerprint }} + <link rel="stylesheet" href="{{ .RelPermalink }}" integrity="{{ .Data.Integrity }}" crossorigin="anonymous"> +{{ end }} +``` + +### Miscellaneous + +If you build Hugo from source and run `mage test -v`, the test will fail if you install Dart Sass as a Snap package. This is due to the Snap package's strict confinement model. + +[brew.sh]: https://brew.sh/ +[chocolatey.org]: https://community.chocolatey.org/packages/sass +[ci/cd]: https://en.wikipedia.org/wiki/CI/CD +[dart sass]: https://sass-lang.com/dart-sass +[libsass]: https://sass-lang.com/libsass +[prebuilt binaries]: https://github.com/sass/dart-sass/releases/latest +[scoop.sh]: https://scoop.sh/#/apps?q=sass +[site configuration]: /getting-started/configuration/#configure-build +[snap package]: /installation/linux/#snap +[snapcraft.io]: https://snapcraft.io/dart-sass +[starter workflow]: https://github.com/actions/starter-workflows/blob/main/pages/hugo.yml diff --git a/docs/content/en/installation/_common/01-editions.md b/docs/content/en/installation/_common/01-editions.md new file mode 100644 index 000000000..deec8cc83 --- /dev/null +++ b/docs/content/en/installation/_common/01-editions.md @@ -0,0 +1,16 @@ +--- +# Do not remove front matter. +--- + +## Editions + +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. + +We recommend that you install the extended edition. + +[dart sass]: /hugo-pipes/transpile-sass-to-css/#dart-sass +[processing images]: /content-management/image-processing/ +[transpile sass to css]: /hugo-pipes/transpile-sass-to-css/ diff --git a/docs/content/en/installation/_common/02-prerequisites.md b/docs/content/en/installation/_common/02-prerequisites.md new file mode 100644 index 000000000..ea6eaa8fe --- /dev/null +++ b/docs/content/en/installation/_common/02-prerequisites.md @@ -0,0 +1,40 @@ +--- +# Do not remove front matter. +--- + +## Prerequisites + +Although not required in all cases, [Git], [Go], and [Dart Sass] are commonly used when working with Hugo. + +Git is required to: + +- Build Hugo from source +- Use the [Hugo Modules] feature +- Install a theme as a Git submodule +- Access [commit information] from a local Git repository +- Host your site with services such as [CloudCannon], [Cloudflare Pages], [GitHub Pages], [GitLab Pages], and [Netlify] + +Go is required to: + +- Build Hugo from source +- Use the Hugo Modules feature + +Dart Sass is required to transpile Sass to CSS when using the latest features of the Sass language. + +Please refer to the relevant documentation for installation instructions: + +- [Git][git install] +- [Go][go install] +- [Dart Sass][dart sass install] + +[cloudcannon]: https://cloudcannon.com/ +[cloudflare pages]: https://pages.cloudflare.com/ +[dart sass install]: /hugo-pipes/transpile-sass-to-css/#dart-sass +[dart sass]: https://sass-lang.com/dart-sass +[git install]: https://git-scm.com/book/en/v2/Getting-Started-Installing-Git +[git]: https://git-scm.com/ +[github pages]: https://pages.github.com/ +[gitlab pages]: https://docs.gitlab.com/ee/user/project/pages/ +[go install]: https://go.dev/doc/install +[go]: https://go.dev/ +[netlify]: https://www.netlify.com/ diff --git a/docs/content/en/installation/_common/03-prebuilt-binaries.md b/docs/content/en/installation/_common/03-prebuilt-binaries.md new file mode 100644 index 000000000..d3465fa5d --- /dev/null +++ b/docs/content/en/installation/_common/03-prebuilt-binaries.md @@ -0,0 +1,23 @@ +--- +# Do not remove front matter. +--- + +## Prebuilt binaries + +Prebuilt binaries are available for a variety of operating systems and architectures. Visit the [latest release] page, and scroll down to the Assets section. + +1. Download the archive for the desired edition, operating system, and architecture +1. Extract the archive +1. Move the executable to the desired directory +1. Add this directory to the PATH environment variable +1. Verify that you have _execute_ permission on the file + +Please consult your operating system documentation if you need help setting file permissions or modifying your PATH environment variable. + +If you do not see a prebuilt binary for the desired edition, operating system, and architecture, install Hugo using one of the methods described below. + +[commit information]: /variables/git +[Git]: https://git-scm.com/ +[Go]: https://go.dev/ +[Hugo Modules]: /hugo-modules/ +[latest release]: https://github.com/gohugoio/hugo/releases/latest diff --git a/docs/content/en/installation/_common/04-build-from-source.md b/docs/content/en/installation/_common/04-build-from-source.md new file mode 100644 index 000000000..63be3e456 --- /dev/null +++ b/docs/content/en/installation/_common/04-build-from-source.md @@ -0,0 +1,27 @@ +--- +# Do not remove front matter. +--- + +## Build from source + +To build the extended edition of Hugo from source you must: + +1. Install [Git] +1. Install [Go] version 1.20 or later +1. Install a C compiler, either [GCC] or [Clang] +1. Update your `PATH` environment variable as described in the [Go documentation] + +> The install directory is controlled by the `GOPATH` and `GOBIN` environment variables. If `GOBIN` is set, binaries are installed to that directory. If `GOPATH` is set, binaries are installed to the bin subdirectory of the first directory in the `GOPATH` list. Otherwise, binaries are installed to the bin subdirectory of the default `GOPATH` (`$HOME/go` or `%USERPROFILE%\go`). + +Then build and test: + +```sh +CGO_ENABLED=1 go install -tags extended github.com/gohugoio/hugo@latest +hugo version +``` + +[Clang]: https://clang.llvm.org/ +[GCC]: https://gcc.gnu.org/ +[Git]: https://git-scm.com/book/en/v2/Getting-Started-Installing-Git +[Go documentation]: https://go.dev/doc/code#Command +[Go]: https://go.dev/doc/install diff --git a/docs/content/en/installation/_common/_index.md b/docs/content/en/installation/_common/_index.md new file mode 100644 index 000000000..47d5812fb --- /dev/null +++ b/docs/content/en/installation/_common/_index.md @@ -0,0 +1,13 @@ +--- +cascade: + _build: + list: never + publishResources: false + render: never +--- + +<!-- +Files within this headless branch bundle are markdown snippets. Each file must contain front matter delimiters, though front matter fields are not required. + +Include the rendered content using the "include" shortcode. +--> diff --git a/docs/content/en/installation/_common/homebrew.md b/docs/content/en/installation/_common/homebrew.md new file mode 100644 index 000000000..6cd7a524f --- /dev/null +++ b/docs/content/en/installation/_common/homebrew.md @@ -0,0 +1,13 @@ +--- +# Do not remove front matter. +--- + +### Homebrew + +[Homebrew] is a free and open-source package manager for macOS and Linux. To install the extended edition of Hugo: + +```sh +brew install hugo +``` + +[Homebrew]: https://brew.sh/ diff --git a/docs/content/en/installation/_index.md b/docs/content/en/installation/_index.md new file mode 100644 index 000000000..ca405b755 --- /dev/null +++ b/docs/content/en/installation/_index.md @@ -0,0 +1,16 @@ +--- +title: Installation +linkTitle: Overview +description: Install Hugo on macOS, Linux, Windows, BSD, and on any machine that can run the Go compiler tool chain. +aliases: [/getting-started/installing/] +categories: [] +keywords: [] +menu: + docs: + identifier: installation-overview + parent: installation + weight: 10 +weight: 10 +--- + +Install Hugo on macOS, Linux, Windows, BSD, and on any machine that can run the Go compiler tool chain. diff --git a/docs/content/en/installation/bsd.md b/docs/content/en/installation/bsd.md new file mode 100644 index 000000000..6d00b8b98 --- /dev/null +++ b/docs/content/en/installation/bsd.md @@ -0,0 +1,75 @@ +--- +title: BSD +description: Install Hugo on BSD derivatives. +categories: [installation] +keywords: [] +menu: + docs: + parent: installation + weight: 50 +weight: 50 +toc: true +--- +{{% include "installation/_common/01-editions.md" %}} + +{{% include "installation/_common/02-prerequisites.md" %}} + +{{% include "installation/_common/03-prebuilt-binaries.md" %}} + +## Repository packages + +Most BSD derivatives maintain a repository for commonly installed applications. Please note that these repositories may not contain the [latest release]. + +[latest release]: https://github.com/gohugoio/hugo/releases/latest + +### DragonFly BSD + +[DragonFly BSD] includes Hugo in its package repository. To install the extended edition of Hugo: + +```sh +sudo pkg install gohugo +``` + +[DragonFly BSD]: https://www.dragonflybsd.org/ + +### FreeBSD + +[FreeBSD] includes Hugo in its package repository. To install the extended edition of Hugo: + +```sh +sudo pkg install gohugo +``` + +[FreeBSD]: https://www.freebsd.org/ + +### NetBSD + +[NetBSD] includes Hugo in its package repository. To install the extended edition of Hugo: + +```sh +sudo pkgin install go-hugo +``` + +[NetBSD]: https://www.netbsd.org/ + +### OpenBSD + +[OpenBSD] includes Hugo in its package repository. This will prompt you to select which edition of Hugo to install: + +```sh +doas pkg_add hugo +``` + +[OpenBSD]: https://www.openbsd.org/ + +{{% include "installation/_common/04-build-from-source.md" %}} + +## Comparison + +||Prebuilt binaries|Repository packages|Build from source +:--|:--:|:--:|:--: +Easy to install?|:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark: +Easy to upgrade?|:heavy_check_mark:|varies|:heavy_check_mark: +Easy to downgrade?|:heavy_check_mark:|varies|:heavy_check_mark: +Automatic updates?|:x:|varies|:x: +Latest version available?|:heavy_check_mark:|varies|:heavy_check_mark: diff --git a/docs/content/en/installation/linux.md b/docs/content/en/installation/linux.md new file mode 100644 index 000000000..7b75f149b --- /dev/null +++ b/docs/content/en/installation/linux.md @@ -0,0 +1,176 @@ +--- +title: Linux +description: Install Hugo on Linux. +categories: [installation] +keywords: [] +menu: + docs: + parent: installation + weight: 30 +weight: 30 +toc: true +--- +{{% include "installation/_common/01-editions.md" %}} + +{{% include "installation/_common/02-prerequisites.md" %}} + +{{% include "installation/_common/03-prebuilt-binaries.md" %}} + +## Package managers + +### Snap + +[Snap] is a free and open-source package manager for Linux. Available for [most distributions], snap packages are simple to install and are automatically updated. + +The Hugo snap package is [strictly confined]. Strictly confined snaps run in complete isolation, up to a minimal access level that’s deemed always safe. The sites you create and build must be located within your home directory, or on removable media. + +To install the extended edition of Hugo: + +```sh +sudo snap install hugo +``` + +To enable or revoke access to removable media: + +```sh +sudo snap connect hugo:removable-media +sudo snap disconnect hugo:removable-media +``` + +To enable or revoke access to SSH keys: + +```sh +sudo snap connect hugo:ssh-keys +sudo snap disconnect hugo:ssh-keys +``` + +[most distributions]: https://snapcraft.io/docs/installing-snapd +[strictly confined]: https://snapcraft.io/docs/snap-confinement +[Snap]: https://snapcraft.io/ + +{{% include "installation/_common/homebrew.md" %}} + +## Repository packages + +Most Linux distributions maintain a repository for commonly installed applications. + +{{% note %}} +The Hugo version available in package repositories varies based on Linux distribution and release, and in some cases will not be the [latest version]. + +Use one of the other installation methods if your package repository does not provide the desired version. + +[latest version]: https://github.com/gohugoio/hugo/releases/latest +{{% /note %}} + +### Alpine Linux + +To install the extended edition of Hugo on [Alpine Linux]: + +```sh +doas apk add --no-cache --repository=https://dl-cdn.alpinelinux.org/alpine/edge/community hugo +``` + +[Alpine Linux]: https://alpinelinux.org/ + +### Arch Linux + +Derivatives of the [Arch Linux] distribution of Linux include [EndeavourOS], [Garuda Linux], [Manjaro], and others. To install the extended edition of Hugo: + +```sh +sudo pacman -S hugo +``` + +[Arch Linux]: https://archlinux.org/ +[EndeavourOS]: https://endeavouros.com/ +[Manjaro]: https://manjaro.org/ +[Garuda Linux]: https://garudalinux.org/ + +### Debian + +Derivatives of the [Debian] distribution of Linux include [elementary OS], [KDE neon], [Linux Lite], [Linux Mint], [MX Linux], [Pop!_OS], [Ubuntu], [Zorin OS], and others. To install the extended edition of Hugo: + +```sh +sudo apt install hugo +``` + +You can also download Debian packages from the [latest release] page. + +[Debian]: https://www.debian.org/ +[elementary OS]: https://elementary.io/ +[KDE neon]: https://neon.kde.org/ +[Linux Lite]: https://www.linuxliteos.com/ +[Linux Mint]: https://linuxmint.com/ +[MX Linux]: https://mxlinux.org/ +[Pop!_OS]: https://pop.system76.com/ +[Ubuntu]: https://ubuntu.com/ +[Zorin OS]: https://zorin.com/os/ + +### Fedora + +Derivatives of the [Fedora] distribution of Linux include [CentOS], [Red Hat Enterprise Linux], and others. To install the extended edition of Hugo: + +```sh +sudo dnf install hugo +``` + +[CentOS]: https://www.centos.org/ +[Fedora]: https://getfedora.org/ +[Red Hat Enterprise Linux]: https://www.redhat.com/ + +### Gentoo + +Derivatives of the [Gentoo] distribution of Linux include [Calculate Linux], [Funtoo], and others. Follow the instructions below to install the extended edition of Hugo: + +1. Specify the `extended` [USE] flag in /etc/portage/package.use/hugo: + + ```text + www-apps/hugo extended + ``` + +2. Build using the Portage package manager: + + ```sh + sudo emerge www-apps/hugo + ``` + +[Calculate Linux]: https://www.calculate-linux.org/ +[Funtoo]: https://www.funtoo.org/ +[Gentoo]: https://www.gentoo.org/ +[USE]: https://packages.gentoo.org/packages/www-apps/hugo + +### openSUSE + +Derivatives of the [openSUSE] distribution of Linux include [GeckoLinux], [Linux Karmada], and others. To install the extended edition of Hugo: + +```sh +sudo zypper install hugo +``` + +[GeckoLinux]: https://geckolinux.github.io/ +[Linux Karmada]: https://linuxkamarada.com/ +[openSUSE]: https://www.opensuse.org/ + +### Solus + +The [Solus] distribution of Linux includes Hugo in its package repository. To install the extended edition of Hugo: + +```sh +sudo eopkg install hugo +``` + +[Solus]: https://getsol.us/ + +{{% include "installation/_common/04-build-from-source.md" %}} + +## Comparison + +||Prebuilt binaries|Package managers|Repository packages|Build from source +:--|:--:|:--:|:--:|:--: +Easy to install?|:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark: +Easy to upgrade?|:heavy_check_mark:|:heavy_check_mark:|varies|:heavy_check_mark: +Easy to downgrade?|:heavy_check_mark:|:heavy_check_mark: [^1]|varies|:heavy_check_mark: +Automatic updates?|:x:|varies [^2]|:x:|:x: +Latest version available?|:heavy_check_mark:|:heavy_check_mark:|varies|:heavy_check_mark: + +[^1]: Easy if a previous version is still installed. +[^2]: Snap packages are automatically updated. Homebrew requires advanced configuration. diff --git a/docs/content/en/installation/macos.md b/docs/content/en/installation/macos.md new file mode 100644 index 000000000..fa6029679 --- /dev/null +++ b/docs/content/en/installation/macos.md @@ -0,0 +1,46 @@ +--- +title: macOS +description: Install Hugo on macOS. +categories: [installation] +keywords: [] +menu: + docs: + parent: installation + weight: 20 +weight: 20 +toc: true +--- +{{% include "installation/_common/01-editions.md" %}} + +{{% include "installation/_common/02-prerequisites.md" %}} + +{{% include "installation/_common/03-prebuilt-binaries.md" %}} + +## Package managers + +{{% include "installation/_common/homebrew.md" %}} + +### MacPorts + +[MacPorts] is a free and open-source package manager for macOS. To install the extended edition of Hugo: + +```sh +sudo port install hugo +``` + +[MacPorts]: https://www.macports.org/ + +{{% include "installation/_common/04-build-from-source.md" %}} + +## Comparison + +||Prebuilt binaries|Package managers|Build from source +:--|:--:|:--:|:--: +Easy to install?|:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark:| +Easy to upgrade?|:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark: +Easy to downgrade?|:heavy_check_mark:|:heavy_check_mark: [^1]|:heavy_check_mark: +Automatic updates?|:x:|:x: [^2]|:x: +Latest version available?|:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark: + +[^1]: Easy if a previous version is still installed. +[^2]: Possible but requires advanced configuration. diff --git a/docs/content/en/installation/windows.md b/docs/content/en/installation/windows.md new file mode 100644 index 000000000..719264550 --- /dev/null +++ b/docs/content/en/installation/windows.md @@ -0,0 +1,73 @@ +--- +title: Windows +description: Install Hugo on Windows. +categories: [installation] +keywords: [] +menu: + docs: + parent: installation + weight: 40 +weight: 40 +toc: true +--- + +{{% note %}} +Hugo v0.121.1 and later require at least Windows 10 or Windows Server 2016. +{{% /note %}} + +{{% include "installation/_common/01-editions.md" %}} + +{{% include "installation/_common/02-prerequisites.md" %}} + +{{% include "installation/_common/03-prebuilt-binaries.md" %}} + +## Package managers + +### Chocolatey + +[Chocolatey] is a free and open-source package manager for Windows. To install the extended edition of Hugo: + +```sh +choco install hugo-extended +``` + +[Chocolatey]: https://chocolatey.org/ + +### Scoop + +[Scoop] is a free and open-source package manager for Windows. To install the extended edition of Hugo: + +```sh +scoop install hugo-extended +``` + +[Scoop]: https://scoop.sh/ + +### Winget + +[Winget] is Microsoft's official free and open-source package manager for Windows. To install the extended edition of Hugo: + +```sh +winget install Hugo.Hugo.Extended +``` + +[Winget]: https://learn.microsoft.com/en-us/windows/package-manager/ + +{{% include "installation/_common/04-build-from-source.md" %}} + +{{% note %}} +See these [detailed instructions](https://discourse.gohugo.io/t/41370) to install GCC on Windows. +{{% /note %}} + +## Comparison + +||Prebuilt binaries|Package managers|Build from source +:--|:--:|:--:|:--: +Easy to install?|:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark:| +Easy to upgrade?|:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark: +Easy to downgrade?|:heavy_check_mark:|:heavy_check_mark: [^2]|:heavy_check_mark: +Automatic updates?|:x:|:x: [^1]|:x: +Latest version available?|:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark: + +[^1]: Possible but requires advanced configuration. +[^2]: Easy if a previous version is still installed. diff --git a/docs/content/en/maintenance/_index.md b/docs/content/en/maintenance/_index.md new file mode 100644 index 000000000..aaee3987d --- /dev/null +++ b/docs/content/en/maintenance/_index.md @@ -0,0 +1,10 @@ +--- +title: Maintenance +description: Some lists useful for the maintenance of the Hugo docs site. +categories: [] +keywords: [] +menu: + docs: + weight: 200 +toc: true +--- diff --git a/docs/content/en/methods/_common/_index.md b/docs/content/en/methods/_common/_index.md new file mode 100644 index 000000000..47d5812fb --- /dev/null +++ b/docs/content/en/methods/_common/_index.md @@ -0,0 +1,13 @@ +--- +cascade: + _build: + list: never + publishResources: false + render: never +--- + +<!-- +Files within this headless branch bundle are markdown snippets. Each file must contain front matter delimiters, though front matter fields are not required. + +Include the rendered content using the "include" shortcode. +--> diff --git a/docs/content/en/methods/_common/next-prev-on-page-vs-next-prev-on-pages.md b/docs/content/en/methods/_common/next-prev-on-page-vs-next-prev-on-pages.md new file mode 100644 index 000000000..4ae3a0f39 --- /dev/null +++ b/docs/content/en/methods/_common/next-prev-on-page-vs-next-prev-on-pages.md @@ -0,0 +1,37 @@ +--- +# Do not remove front matter. +--- + +The `Next` and `Prev` methods on a `Pages` object are more flexible than the `Next` and `Prev` methods on a `Page` object. + +||Page collection|Custom sort order +:--|:--|:-: +[`PAGES.Next`] and [`PAGES.Prev`]|locally defined|✔️ +[`PAGE.Next`] and [`PAGE.Prev`]|globally defined|❌ + +[`PAGES.Next`]: /methods/pages/next +[`PAGES.Prev`]: /methods/pages/prev +[`PAGE.Next`]: /methods/page/next +[`PAGE.Prev`]: /methods/page/prev + +locally defined +: Build the page collection every time you call `PAGES.Next` and `PAGES.Prev`. Navigation between pages is relative to the current page's position within the local collection, independent of the global collection. + +With a local collection, the navigation sort order is the same as the collection sort order. + +globally defined +: Build the page collection once, on a list page. Navigation between pages is relative to the current page's position within the global collection. + +With a global collection, the navigation sort order is fixed, using Hugo's default sort order. In order of precedence: + +1. Page [weight] +2. Page [date] (descending) +3. Page [linkTitle], falling back to page [title] +4. Page file path if the page is backed by a file + +For example, with a global collection sorted by title, the navigation sort order will use Hugo's default sort order. This is probably not what you want or expect. For this reason, the `Next` and `Prev` methods on a `Pages` object are generally a better choice. + +[date]: /methods/page/date +[weight]: /methods/page/weight +[linkTitle]: /methods/page/linktitle +[title]: /methods/page/title diff --git a/docs/content/en/methods/_index.md b/docs/content/en/methods/_index.md new file mode 100644 index 000000000..c12bd9d4d --- /dev/null +++ b/docs/content/en/methods/_index.md @@ -0,0 +1,16 @@ +--- +title: Methods +linkTitle: Overview +description: A list of Hugo template methods including examples. +categories: [] +keywords: [] +menu: + docs: + identifier: methods-overview + parent: methods + weight: 10 +weight: 10 +showSectionMenu: true +--- + +Use these methods within your templates. diff --git a/docs/content/en/methods/duration/Abs.md b/docs/content/en/methods/duration/Abs.md new file mode 100644 index 000000000..d035f97b6 --- /dev/null +++ b/docs/content/en/methods/duration/Abs.md @@ -0,0 +1,17 @@ +--- +title: Abs +description: Returns the absolute value of the given time.Duration value. +categories: [] +keywords: [] +action: + related: + - functions/time/Duration + - functions/time/ParseDuration + returnType: time.Duration + signatures: [DURATION.Abs] +--- + +```go-html-template +{{ $d = time.ParseDuration "-3h" }} +{{ $d.Abs }} → 3h0m0s +``` diff --git a/docs/content/en/methods/duration/Hours.md b/docs/content/en/methods/duration/Hours.md new file mode 100644 index 000000000..5b2d893b9 --- /dev/null +++ b/docs/content/en/methods/duration/Hours.md @@ -0,0 +1,17 @@ +--- +title: Hours +description: Returns the time.Duration value as a floating point number of hours. +categories: [] +keywords: [] +action: + related: + - functions/time/Duration + - functions/time/ParseDuration + returnType: float64 + signatures: [DURATION.Hours] +--- + +```go-html-template +{{ $d = time.ParseDuration "3.5h2.5m1.5s" }} +{{ $d.Hours }} → 3.5420833333333333 +``` diff --git a/docs/content/en/methods/duration/Microseconds.md b/docs/content/en/methods/duration/Microseconds.md new file mode 100644 index 000000000..c8b210c94 --- /dev/null +++ b/docs/content/en/methods/duration/Microseconds.md @@ -0,0 +1,17 @@ +--- +title: Microseconds +description: Returns the time.Duration value as an integer microsecond count. +categories: [] +keywords: [] +action: + related: + - functions/time/Duration + - functions/time/ParseDuration + returnType: int64 + signatures: [DURATION.Microseconds] +--- + +```go-html-template +{{ $d = time.ParseDuration "3.5h2.5m1.5s" }} +{{ $d.Microseconds }} → 12751500000 +``` diff --git a/docs/content/en/methods/duration/Milliseconds.md b/docs/content/en/methods/duration/Milliseconds.md new file mode 100644 index 000000000..32809027a --- /dev/null +++ b/docs/content/en/methods/duration/Milliseconds.md @@ -0,0 +1,17 @@ +--- +title: Milliseconds +description: Returns the time.Duration value as an integer millisecond count. +categories: [] +keywords: [] +action: + related: + - functions/time/Duration + - functions/time/ParseDuration + returnType: int64 + signatures: [DURATION.Milliseconds] +--- + +```go-html-template +{{ $d = time.ParseDuration "3.5h2.5m1.5s" }} +{{ $d.Milliseconds }} → 12751500 +``` diff --git a/docs/content/en/methods/duration/Minutes.md b/docs/content/en/methods/duration/Minutes.md new file mode 100644 index 000000000..d3e57fba5 --- /dev/null +++ b/docs/content/en/methods/duration/Minutes.md @@ -0,0 +1,17 @@ +--- +title: Minutes +description: Returns the time.Duration value as a floating point number of minutes. +categories: [] +keywords: [] +action: + related: + - functions/time/Duration + - functions/time/ParseDuration + returnType: float64 + signatures: [DURATION.Minutes] +--- + +```go-html-template +{{ $d = time.ParseDuration "3.5h2.5m1.5s" }} +{{ $d.Minutes }} → 212.525 +``` diff --git a/docs/content/en/methods/duration/Nanoseconds.md b/docs/content/en/methods/duration/Nanoseconds.md new file mode 100644 index 000000000..66d2981f2 --- /dev/null +++ b/docs/content/en/methods/duration/Nanoseconds.md @@ -0,0 +1,17 @@ +--- +title: Nanoseconds +description: Returns the time.Duration value as an integer nanosecond count. +categories: [] +keywords: [] +action: + related: + - functions/time/Duration + - functions/time/ParseDuration + returnType: int64 + signatures: [DURATION.Nanoseconds] +--- + +```go-html-template +{{ $d = time.ParseDuration "3.5h2.5m1.5s" }} +{{ $d.Nanoseconds }} → 12751500000000 +``` diff --git a/docs/content/en/methods/duration/Round.md b/docs/content/en/methods/duration/Round.md new file mode 100644 index 000000000..0722a6076 --- /dev/null +++ b/docs/content/en/methods/duration/Round.md @@ -0,0 +1,20 @@ +--- +title: Round +description: Returns the result of rounding DURATION1 to the nearest multiple of DURATION2. +categories: [] +keywords: [] +action: + related: + - functions/time/Duration + - functions/time/ParseDuration + returnType: + signatures: [DURATION1.Round DURATION2] +--- + +```go-html-template +{{ $d = time.ParseDuration "3.5h2.5m1.5s" }} + +{{ $d.Round (time.ParseDuration "2h") }} → 4h0m0s +{{ $d.Round (time.ParseDuration "3m") }} → 3h33m0s +{{ $d.Round (time.ParseDuration "4s") }} → 3h32m32s +``` diff --git a/docs/content/en/methods/duration/Seconds.md b/docs/content/en/methods/duration/Seconds.md new file mode 100644 index 000000000..d23d5ec15 --- /dev/null +++ b/docs/content/en/methods/duration/Seconds.md @@ -0,0 +1,17 @@ +--- +title: Seconds +description: Returns the time.Duration value as a floating point number of seconds. +categories: [] +keywords: [] +action: + related: + - functions/time/Duration + - functions/time/ParseDuration + returnType: float64 + signatures: [DURATION.Seconds] +--- + +```go-html-template +{{ $d = time.ParseDuration "3.5h2.5m1.5s" }} +{{ $d.Seconds }} → 12751.5 +``` diff --git a/docs/content/en/methods/duration/Truncate.md b/docs/content/en/methods/duration/Truncate.md new file mode 100644 index 000000000..795fcad76 --- /dev/null +++ b/docs/content/en/methods/duration/Truncate.md @@ -0,0 +1,21 @@ +--- +title: Truncate +description: Returns the result of rounding DURATION1 toward zero to a multiple of DURATION2. +categories: [] +keywords: [] +action: + related: + related: + - functions/time/Duration + - functions/time/ParseDuration + returnType: time.Duration + signatures: [DURATION1.Truncate DURATION2] +--- + +```go-html-template +{{ $d = time.ParseDuration "3.5h2.5m1.5s" }} + +{{ $d.Truncate (time.ParseDuration "2h") }} → 2h0m0s +{{ $d.Truncate (time.ParseDuration "3m") }} → 3h30m0s +{{ $d.Truncate (time.ParseDuration "4s") }} → 3h32m28s +``` diff --git a/docs/content/en/methods/duration/_index.md b/docs/content/en/methods/duration/_index.md new file mode 100644 index 000000000..9fc4f814c --- /dev/null +++ b/docs/content/en/methods/duration/_index.md @@ -0,0 +1,12 @@ +--- +title: Duration methods +linkTitle: Duration +description: Use these methods with time.Duration values. +categories: [] +keywords: [] +menu: + docs: + parent: methods +--- + +Use these methods with time.Duration values. diff --git a/docs/content/en/methods/menu-entry/Children.md b/docs/content/en/methods/menu-entry/Children.md new file mode 100644 index 000000000..ad671b2d0 --- /dev/null +++ b/docs/content/en/methods/menu-entry/Children.md @@ -0,0 +1,67 @@ +--- +title: Children +description: Returns a collection of child menu entries, if any, under the given menu entry. +categories: [] +keywords: [] +action: + related: + - methods/menu-entry/HasChildren + returnType: navigation.Menu + signatures: [MENUENTRY.Children] +--- + +Use the `Children` method when rendering a nested menu. + +With this site configuration: + +{{< code-toggle file=hugo >}} +[[menus.main]] +name = 'Products' +pageRef = '/product' +weight = 10 + +[[menus.main]] +name = 'Product 1' +pageRef = '/products/product-1' +parent = 'Products' +weight = 1 + +[[menus.main]] +name = 'Product 2' +pageRef = '/products/product-2' +parent = 'Products' +weight = 2 +{{< /code-toggle >}} + +And this template: + +```go-html-template +<ul> + {{ range .Site.Menus.main }} + <li> + <a href="{{ .URL }}">{{ .Name }}</a> + {{ if .HasChildren }} + <ul> + {{ range .Children }} + <li><a href="{{ .URL }}">{{ .Name }}</a></li> + {{ end }} + </ul> + {{ end }} + </li> + {{ end }} +</ul> +``` + +Hugo renders this HTML: + +```html +<ul> + <li> + <a href="/products/">Products</a> + <ul> + <li><a href="/products/product-1/">Product 1</a></li> + <li><a href="/products/product-2/">Product 2</a></li> + </ul> + </li> +</ul> +``` diff --git a/docs/content/en/methods/menu-entry/HasChildren.md b/docs/content/en/methods/menu-entry/HasChildren.md new file mode 100644 index 000000000..fac03b7ae --- /dev/null +++ b/docs/content/en/methods/menu-entry/HasChildren.md @@ -0,0 +1,67 @@ +--- +title: HasChildren +description: Reports whether the given menu entry has child menu entries. +categories: [] +keywords: [] +action: + related: + - methods/menu-entry/Children + returnType: bool + signatures: [MENUENTRY.HasChildren] +--- + +Use the `HasChildren` method when rendering a nested menu. + +With this site configuration: + +{{< code-toggle file=hugo >}} +[[menus.main]] +name = 'Products' +pageRef = '/product' +weight = 10 + +[[menus.main]] +name = 'Product 1' +pageRef = '/products/product-1' +parent = 'Products' +weight = 1 + +[[menus.main]] +name = 'Product 2' +pageRef = '/products/product-2' +parent = 'Products' +weight = 2 +{{< /code-toggle >}} + +And this template: + +```go-html-template +<ul> + {{ range .Site.Menus.main }} + <li> + <a href="{{ .URL }}">{{ .Name }}</a> + {{ if .HasChildren }} + <ul> + {{ range .Children }} + <li><a href="{{ .URL }}">{{ .Name }}</a></li> + {{ end }} + </ul> + {{ end }} + </li> + {{ end }} +</ul> +``` + +Hugo renders this HTML: + +```html +<ul> + <li> + <a href="/products/">Products</a> + <ul> + <li><a href="/products/product-1/">Product 1</a></li> + <li><a href="/products/product-2/">Product 2</a></li> + </ul> + </li> +</ul> +``` diff --git a/docs/content/en/methods/menu-entry/Identifier.md b/docs/content/en/methods/menu-entry/Identifier.md new file mode 100644 index 000000000..ba8b77ece --- /dev/null +++ b/docs/content/en/methods/menu-entry/Identifier.md @@ -0,0 +1,44 @@ +--- +title: Identifier +description: Returns the `identifier` property of the given menu entry. +categories: [] +keywords: [] +action: + related: [] + returnType: string + signatures: [MENUENTRY.Identifier] +--- + +The `Identifier` method returns the `identifier` property of the menu entry. If you define the menu entry [automatically], it returns the page's section. + +[automatically]: /content-management/menus/#define-automatically + +{{< code-toggle file=hugo >}} +[[menus.main]] +identifier = 'about' +name = 'About' +pageRef = '/about' +weight = 10 + +[[menus.main]] +identifier = 'contact' +name = 'Contact' +pageRef = '/contact' +weight = 20 +{{< /code-toggle >}} + +This example uses the `Identifier` method when querying the translation table on a multilingual site, falling back the `name` property if a matching key in the translation table does not exist: + +```go-html-template +<ul> + {{ range .Site.Menus.main }} + <li><a href="{{ .URL }}">{{ or (T .Identifier) .Name }}</a></li> + {{ end }} +</ul> +``` + +{{% note %}} +In the menu definition above, note that the `identifier` property is only required when two or more menu entries have the same name, or when localizing the name using translation tables. + +[details]: /content-management/menus/#properties-front-matter +{{% /note %}} diff --git a/docs/content/en/methods/menu-entry/KeyName.md b/docs/content/en/methods/menu-entry/KeyName.md new file mode 100644 index 000000000..4b43596b0 --- /dev/null +++ b/docs/content/en/methods/menu-entry/KeyName.md @@ -0,0 +1,39 @@ +--- +title: KeyName +description: Returns the `identifier` property of the given menu entry, falling back to its `name` property. +categories: [] +keywords: [] +action: + related: [] + returnType: string + signatures: [MENUENTRY.KeyName] +--- + +In this menu definition, the second entry does not contain an `identifier`, so the `Identifier` method returns its `name` property instead: + +{{< code-toggle file=hugo >}} +[[menus.main]] +identifier = 'about' +name = 'About' +pageRef = '/about' +weight = 10 + +[[menus.main]] +name = 'Contact' +pageRef = '/contact' +weight = 20 +{{< /code-toggle >}} + +This example uses the `KeyName` method when querying the translation table on a multilingual site, falling back the `name` property if a matching key in the translation table does not exist: + +```go-html-template +<ul> + {{ range .Site.Menus.main }} + <li><a href="{{ .URL }}">{{ or (T (.KeyName | lower)) .Name }}</a></li> + {{ end }} +</ul> +``` + +In the example above, we need to pass the value returned by `.KeyName` through the [`lower`] function because the keys in the translation table are lowercase. + +[`lower`]: functions/strings/tolower diff --git a/docs/content/en/methods/menu-entry/Menu.md b/docs/content/en/methods/menu-entry/Menu.md new file mode 100644 index 000000000..6827519bd --- /dev/null +++ b/docs/content/en/methods/menu-entry/Menu.md @@ -0,0 +1,24 @@ +--- +title: Menu +description: Returns the identifier of the menu that contains the given menu entry. +categories: [] +keywords: [] +action: + related: + - methods/page/IsMenuCurrent + - methods/page/HasMenuCurrent + returnType: string + signatures: [MENUENTRY.Menu] +--- + +```go-html-template +{{ range .Site.Menus.main }} + {{ .Menu }} → main +{{ end }} +``` + +Use this method with the [`IsMenuCurrent`] and [`HasMenuCurrent`] methods on a `Page` object to set "active" and "ancestor" classes on a rendered entry. See [this example]. + +[`HasMenuCurrent`]: /methods/page/hasmenucurrent +[`IsMenuCurrent`]: /methods/page/ismenucurrent +[this example]: /templates/menu-templates/#example diff --git a/docs/content/en/methods/menu-entry/Name.md b/docs/content/en/methods/menu-entry/Name.md new file mode 100644 index 000000000..d722da07c --- /dev/null +++ b/docs/content/en/methods/menu-entry/Name.md @@ -0,0 +1,28 @@ +--- +title: Name +description: Returns the `name` property of the given menu entry. +categories: [] +keywords: [] +action: + related: [] + returnType: string + signatures: [MENUENTRY.Name] +--- + +If you define the menu entry [automatically], the `Name` method returns the page’s [`LinkTitle`], falling back to its [`Title`]. + +If you define the menu entry [in front matter] or [in site configuration], the `Name` method returns the `name` property, falling back to the page’s `LinkTitle`, then to its `Title`. + +[`LinkTitle`]: /methods/page/linktitle +[`Title`]: /methods/page/title +[automatically]: /content-management/menus/#define-automatically +[in front matter]: /content-management/menus/#define-in-front-matter +[in site configuration]: /content-management/menus/#define-in-site-configuration + +```go-html-template +<ul> + {{ range .Site.Menus.main }} + <li><a href="{{ .URL }}">{{ .Name }}</a></li> + {{ end }} +</ul> +``` diff --git a/docs/content/en/methods/menu-entry/Page.md b/docs/content/en/methods/menu-entry/Page.md new file mode 100644 index 000000000..b75e4af55 --- /dev/null +++ b/docs/content/en/methods/menu-entry/Page.md @@ -0,0 +1,53 @@ +--- +title: Page +description: Returns the Page object associated with the given menu entry. +categories: [] +keywords: [] +action: + related: [] + returnType: page.Page + signatures: [MENUENTRY.Page] +--- + +Regardless of how you [define menu entries], an entry associated with a page has access to its [methods]. + +In this menu definition, the first two entries are associated with a page, the last entry is not: + +{{< code-toggle file=hugo >}} +[[menus.main]] +pageRef = '/about' +weight = 10 + +[[menus.main]] +pageRef = '/contact' +weight = 20 + +[[menus.main]] +name = 'Hugo' +url = 'https://gohugo.io' +weight = 30 +{{< /code-toggle >}} + +In this example, if the menu entry is associated with a page, we use page's [`RelPermalink`] and [`LinkTitle`] when rendering the anchor element. + +If the entry is not associated with a page, we use its `url` and `name` properties. + +```go-html-template +<ul> + {{ range .Site.Menus.main }} + {{ with .Page }} + <li><a href="{{ .RelPermalink }}">{{ .Title }}</a></li> + {{ else }} + <li><a href="{{ .URL }}">{{ .Name }}</a></li> + {{ end }} + {{ end }} +</ul> +``` + +See the [menu templates] section for more information. + +[`LinkTitle`]: /methods/page/linktitle +[`RelPermalink`]: /methods/page/relpermalink +[define menu entries]: /content-management/menus/ +[menu templates]: /templates/menu-templates/#page-references +[methods]: /methods/page diff --git a/docs/content/en/methods/menu-entry/Params.md b/docs/content/en/methods/menu-entry/Params.md new file mode 100644 index 000000000..8af3f0637 --- /dev/null +++ b/docs/content/en/methods/menu-entry/Params.md @@ -0,0 +1,62 @@ +--- +title: Params +description: Returns the `params` property of the given menu entry. +categories: [] +keywords: [] +action: + related: [] + returnType: maps.Params + signatures: [MENUENTRY.Params] +--- + +When you define menu entries [in site configuration] or [in front matter], you can include a `params` key to attach additional information to the entry. For example: + +{{< code-toggle file=hugo >}} +[[menus.main]] +name = 'About' +pageRef = '/about' +weight = 10 + +[[menus.main]] +name = 'Contact' +pageRef = '/contact' +weight = 20 + +[[menus.main]] +name = 'Hugo' +url = 'https://gohugo.io' +weight = 30 +[menus.main.params] + rel = 'external' +{{< /code-toggle >}} + +With this template: + + +```go-html-template +<ul> + {{ range .Site.Menus.main }} + <li> + <a href="{{ .URL }}" {{ with .Params.rel }}rel="{{ . }}"{{ end }}> + {{ .Name }} + </a> + </li> + {{ end }} +</ul> +``` + +Hugo renders: + +```html +<ul> + <li><a href="/about/">About</a></li> + <li><a href="/contact/">Contact</a></li> + <li><a href="https://gohugo.io" rel="external">Hugo</a></li> +</ul> +``` + +See the [menu templates] section for more information. + +[menu templates]: /templates/menu-templates/#menu-entry-parameters +[in front matter]: /content-management/menus/#define-in-front-matter +[in site configuration]: /content-management/menus/ diff --git a/docs/content/en/methods/menu-entry/Parent.md b/docs/content/en/methods/menu-entry/Parent.md new file mode 100644 index 000000000..af1b4afe6 --- /dev/null +++ b/docs/content/en/methods/menu-entry/Parent.md @@ -0,0 +1,50 @@ +--- +title: Parent +description: Returns the `parent` property of the given menu entry. +categories: [] +keywords: [] +action: + related: [] + returnType: string + signatures: [MENUENTRY.Parent] +--- + +With this menu definition: + +{{< code-toggle file=hugo >}} +[[menus.main]] +name = 'Products' +pageRef = '/product' +weight = 10 + +[[menus.main]] +name = 'Product 1' +pageRef = '/products/product-1' +parent = 'Products' +weight = 1 + +[[menus.main]] +name = 'Product 2' +pageRef = '/products/product-2' +parent = 'Products' +weight = 2 +{{< /code-toggle >}} + +This template renders the nested menu, listing the `parent` property next each of the child entries: + +```go-html-template +<ul> + {{ range .Site.Menus.main }} + <li> + <a href="{{ .URL }}">{{ .Name }}</a> + {{ if .HasChildren }} + <ul> + {{ range .Children }} + <li><a href="{{ .URL }}">{{ .Name }}</a> ({{ .Parent }})</li> + {{ end }} + </ul> + {{ end }} + </li> + {{ end }} +</ul> +``` diff --git a/docs/content/en/methods/menu-entry/Post.md b/docs/content/en/methods/menu-entry/Post.md new file mode 100644 index 000000000..b2fa2da5b --- /dev/null +++ b/docs/content/en/methods/menu-entry/Post.md @@ -0,0 +1,13 @@ +--- +title: Post +description: Returns the `post` property of the given menu entry. +categories: [] +keywords: [] +action: + related: + - methods/menu-entry/Pre + returnType: template.HTML + signatures: [MENUENTRY.Post] +--- + +{{% include "methods/menu-entry/_common/pre-post.md" %}} diff --git a/docs/content/en/methods/menu-entry/Pre.md b/docs/content/en/methods/menu-entry/Pre.md new file mode 100644 index 000000000..df7c8f16e --- /dev/null +++ b/docs/content/en/methods/menu-entry/Pre.md @@ -0,0 +1,13 @@ +--- +title: Pre +description: Returns the `pre` property of the given menu entry. +categories: [] +keywords: [] +action: + related: + - methods/menu-entry/Post + returnType: template.HTML + signatures: [MENUENTRY.Pre] +--- + +{{% include "methods/menu-entry/_common/pre-post.md" %}} diff --git a/docs/content/en/methods/menu-entry/Title.md b/docs/content/en/methods/menu-entry/Title.md new file mode 100644 index 000000000..c1eec2cc0 --- /dev/null +++ b/docs/content/en/methods/menu-entry/Title.md @@ -0,0 +1,28 @@ +--- +title: Title +description: Returns the `title` property of the given menu entry. +categories: [] +keywords: [] +action: + related: [] + returnType: string + signatures: [MENUENTRY.Title] +--- + +If you define the menu entry [automatically], the `Title` method returns the page’s [`LinkTitle`], falling back to its [`Title`]. + +If you define the menu entry [in front matter] or [in site configuration], the `Name` method returns the `title` property, falling back to the page’s `LinkTitle`, then to its `Title`. + +[`LinkTitle`]: /methods/page/linktitle +[`Title`]: /methods/page/title +[automatically]: /content-management/menus/#define-automatically +[in front matter]: /content-management/menus/#define-in-front-matter +[in site configuration]: /content-management/menus/#define-in-site-configuration + +```go-html-template +<ul> + {{ range .Site.Menus.main }} + <li><a href="{{ .URL }}">{{ .Title }}</a></li> + {{ end }} +</ul> +``` diff --git a/docs/content/en/methods/menu-entry/URL.md b/docs/content/en/methods/menu-entry/URL.md new file mode 100644 index 000000000..c2b314b58 --- /dev/null +++ b/docs/content/en/methods/menu-entry/URL.md @@ -0,0 +1,23 @@ +--- +title: URL +description: Returns the relative permalink of the page associated with the given menu entry, else its `url` property. +categories: [] +keywords: [] +action: + related: [] + returnType: string + signatures: [MENUENTRY.URL] +--- + +For menu entries associated with a page, the `URL` method returns the page's [`RelPermalink`], otherwise it returns the entry's `url` property. + + +```go-html-template +<ul> + {{ range .Site.Menus.main }} + <li><a href="{{ .URL }}">{{ .Name }}</a></li> + {{ end }} +</ul> +``` + +[`RelPermalink`]: /methods/page/relpermalink diff --git a/docs/content/en/methods/menu-entry/Weight.md b/docs/content/en/methods/menu-entry/Weight.md new file mode 100644 index 000000000..7b0c24ae8 --- /dev/null +++ b/docs/content/en/methods/menu-entry/Weight.md @@ -0,0 +1,31 @@ +--- +title: Weight +description: Returns the `weight` property of the given menu entry. +categories: [] +keywords: [] +action: + related: [] + returnType: int + signatures: [MENUENTRY.Weight] +--- + +If you define the menu entry [automatically], the `Weight` method returns the page’s [`Weight`]. + +If you define the menu entry [in front matter] or [in site configuration], the `Weight` method returns the `weight` property, falling back to the page’s `Weight`. + +[`Weight`]: /methods/page/weight +[automatically]: /content-management/menus/#define-automatically +[in front matter]: /content-management/menus/#define-in-front-matter +[in site configuration]: /content-management/menus/#define-in-site-configuration + +In this contrived example, we limit the number of menu entries based on weight: + +```go-html-template +<ul> + {{ range .Site.Menus.main }} + {{ if le .Weight 42 }} + <li><a href="{{ .URL }}">{{ .Name }}</a></li> + {{ end }} + {{ end }} +</ul> +``` diff --git a/docs/content/en/methods/menu-entry/_common/_index.md b/docs/content/en/methods/menu-entry/_common/_index.md new file mode 100644 index 000000000..47d5812fb --- /dev/null +++ b/docs/content/en/methods/menu-entry/_common/_index.md @@ -0,0 +1,13 @@ +--- +cascade: + _build: + list: never + publishResources: false + render: never +--- + +<!-- +Files within this headless branch bundle are markdown snippets. Each file must contain front matter delimiters, though front matter fields are not required. + +Include the rendered content using the "include" shortcode. +--> diff --git a/docs/content/en/methods/menu-entry/_common/pre-post.md b/docs/content/en/methods/menu-entry/_common/pre-post.md new file mode 100644 index 000000000..fbfce062a --- /dev/null +++ b/docs/content/en/methods/menu-entry/_common/pre-post.md @@ -0,0 +1,39 @@ +--- +# Do not remove front matter. +--- + +In this site configuration we enable rendering of [emoji shortcodes], and add emoji shortcodes before (pre) and after (post) each menu entry: + +{{< code-toggle file=hugo >}} +enableEmoji = true + +[[menus.main]] +name = 'About' +pageRef = '/about' +post = ':point_left:' +pre = ':point_right:' +weight = 10 + +[[menus.main]] +name = 'Contact' +pageRef = '/contact' +post = ':arrow_left:' +pre = ':arrow_right:' +weight = 20 +{{< /code-toggle >}} + +To render the menu: + +```go-html-template +<ul> + {{ range .Site.Menus.main }} + <li> + {{ .Pre | markdownify }} + <a href="{{ .URL }}">{{ .Name }}</a> + {{ .Post | markdownify }} + </li> + {{ end }} +</ul> +``` + +[emoji shortcodes]: /quick-reference/emojis/ diff --git a/docs/content/en/methods/menu-entry/_index.md b/docs/content/en/methods/menu-entry/_index.md new file mode 100644 index 000000000..d89663593 --- /dev/null +++ b/docs/content/en/methods/menu-entry/_index.md @@ -0,0 +1,12 @@ +--- +title: Menu entry methods +linkTitle: Menu entry +description: Use these methods in your menu templates. +categories: [] +keywords: [] +menu: + docs: + parent: methods +--- + +Use these methods in your menu templates. diff --git a/docs/content/en/methods/menu/ByName.md b/docs/content/en/methods/menu/ByName.md new file mode 100644 index 000000000..04f25c22d --- /dev/null +++ b/docs/content/en/methods/menu/ByName.md @@ -0,0 +1,65 @@ +--- +title: ByName +description: Returns the given menu with its entries sorted by name. +categories: [] +keywords: [] +action: + related: [] + returnType: navigation.Menu + signatures: [MENU.ByName] +--- + +The `Sort` method returns the given menu with its entries sorted by `name`. + +Consider this menu definition: + +{{< code-toggle file=hugo >}} +[[menus.main]] +name = 'Services' +pageRef = '/services' +weight = 10 + +[[menus.main]] +name = 'About' +pageRef = '/about' +weight = 20 + +[[menus.main]] +name = 'Contact' +pageRef = '/contact' +weight = 30 +{{< /code-toggle >}} + +To sort the entries by `name`: + +```go-html-template +<ul> + {{ range .Site.Menus.main.ByName }} + <li><a href="{{ .URL }}">{{ .Name }}</a></li> + {{ end }} +</ul> +``` + +Hugo renders this to: + +```html +<ul> + <li><a href="/about/">About</a></li> + <li><a href="/contact">Contact</a></li> + <li><a href="/services/">Services</a></li> +</ul> +``` + +You can also sort menu entries using the [`sort`] function. For example, to sort by `name` in descending order: + +```go-html-template +<ul> + {{ range sort .Site.Menus.main "Name" "desc" }} + <li><a href="{{ .URL }}">{{ .Name }}</a></li> + {{ end }} +</ul> +``` + +When using the sort function with menu entries, specify any of the following keys: `Identifier`, `Name`, `Parent`, `Post`, `Pre`, `Title`, `URL`, or `Weight`. + +[`sort`]: /functions/collections/sort diff --git a/docs/content/en/methods/menu/ByWeight.md b/docs/content/en/methods/menu/ByWeight.md new file mode 100644 index 000000000..d5cb0444b --- /dev/null +++ b/docs/content/en/methods/menu/ByWeight.md @@ -0,0 +1,76 @@ +--- +title: ByWeight +description: Returns the given menu with its entries sorted by weight, then by name, then by identifier. +categories: [] +keywords: [] +action: + related: [] + returnType: navigation.Menu + signatures: [MENU.ByWeight] +--- + +The `ByWeight` method returns the given menu with its entries sorted by [`weight`], then by `name`, then by `identifier`. This is the default sort order. + +[`weight`]: /getting-started/glossary/#weight + +Consider this menu definition: + +{{< code-toggle file=hugo >}} +[[menus.main]] +identifier = 'about' +name = 'About' +pageRef = '/about' +weight = 20 + +[[menus.main]] +identifier = 'services' +name = 'Services' +pageRef = '/services' +weight = 10 + +[[menus.main]] +identifier = 'contact' +name = 'Contact' +pageRef = '/contact' +weight = 30 +{{< /code-toggle >}} + +To sort the entries by `weight`, then by `name`, then by `identifier`: + +```go-html-template +<ul> + {{ range .Site.Menus.main.ByWeight }} + <li><a href="{{ .URL }}">{{ .Name }}</a></li> + {{ end }} +</ul> +``` + +Hugo renders this to: + +```html +<ul> + <li><a href="/services/">Services</a></li> + <li><a href="/about/">About</a></li> + <li><a href="/contact">Contact</a></li> +</ul> +``` + +{{% note %}} +In the menu definition above, note that the `identifier` property is only required when two or more menu entries have the same name, or when localizing the name using translation tables. + +[details]: /content-management/menus/#properties-front-matter +{{% /note %}} + +You can also sort menu entries using the [`sort`] function. For example, to sort by `weight` in descending order: + +```go-html-template +<ul> + {{ range sort .Site.Menus.main "Weight" "desc" }} + <li><a href="{{ .URL }}">{{ .Name }}</a></li> + {{ end }} +</ul> +``` + +When using the sort function with menu entries, specify any of the following keys: `Identifier`, `Name`, `Parent`, `Post`, `Pre`, `Title`, `URL`, or `Weight`. + +[`sort`]: /functions/collections/sort diff --git a/docs/content/en/methods/menu/Limit.md b/docs/content/en/methods/menu/Limit.md new file mode 100644 index 000000000..23a523dbd --- /dev/null +++ b/docs/content/en/methods/menu/Limit.md @@ -0,0 +1,50 @@ +--- +title: Limit +description: Returns the given menu, limited to the first N entries. +categories: [] +keywords: [] +action: + related: [] + returnType: navigation.Menu + signatures: [MENU.Limit N] +--- + +The `Limit` method returns the given menu, limited to the first N entries. + +Consider this menu definition: + +{{< code-toggle file=hugo >}} +[[menus.main]] +name = 'Services' +pageRef = '/services' +weight = 10 + +[[menus.main]] +name = 'About' +pageRef = '/about' +weight = 20 + +[[menus.main]] +name = 'Contact' +pageRef = '/contact' +weight = 30 +{{< /code-toggle >}} + +To sort the entries by name, and limit to the first 2 entries: + +```go-html-template +<ul> + {{ range .Site.Menus.main.ByName.Limit 2 }} + <li><a href="{{ .URL }}">{{ .Name }}</a></li> + {{ end }} +</ul> +``` + +Hugo renders this to: + +```html +<ul> + <li><a href="/about/">About</a></li> + <li><a href="/contact">Contact</a></li> +</ul> +``` diff --git a/docs/content/en/methods/menu/Reverse.md b/docs/content/en/methods/menu/Reverse.md new file mode 100644 index 000000000..a3fe09dce --- /dev/null +++ b/docs/content/en/methods/menu/Reverse.md @@ -0,0 +1,51 @@ +--- +title: Reverse +description: Returns the given menu, reversing the sort order of its entries. +categories: [] +keywords: [] +action: + related: [] + returnType: navigation.Menu + signatures: [MENU.Reverse] +--- + +The `Reverse` method returns the given menu, reversing the sort order of its entries. + +Consider this menu definition: + +{{< code-toggle file=hugo >}} +[[menus.main]] +name = 'Services' +pageRef = '/services' +weight = 10 + +[[menus.main]] +name = 'About' +pageRef = '/about' +weight = 20 + +[[menus.main]] +name = 'Contact' +pageRef = '/contact' +weight = 30 +{{< /code-toggle >}} + +To sort the entries by name in descending order: + +```go-html-template +<ul> + {{ range .Site.Menus.main.ByName.Reverse }} + <li><a href="{{ .URL }}">{{ .Name }}</a></li> + {{ end }} +</ul> +``` + +Hugo renders this to: + +```html +<ul> + <li><a href="/services/">Services</a></li> + <li><a href="/contact">Contact</a></li> + <li><a href="/about/">About</a></li> +</ul> +``` diff --git a/docs/content/en/methods/menu/_index.md b/docs/content/en/methods/menu/_index.md new file mode 100644 index 000000000..f5b925fd6 --- /dev/null +++ b/docs/content/en/methods/menu/_index.md @@ -0,0 +1,12 @@ +--- +title: Menu methods +linkTitle: Menu +description: Use these methods when ranging through menu entries. +categories: [] +keywords: [] +menu: + docs: + parent: methods +--- + +Use these methods when ranging through menu entries. diff --git a/docs/content/en/methods/page/Aliases.md b/docs/content/en/methods/page/Aliases.md new file mode 100644 index 000000000..15e73384b --- /dev/null +++ b/docs/content/en/methods/page/Aliases.md @@ -0,0 +1,29 @@ +--- +title: Aliases +description: Returns the URL aliases as defined in front matter. +categories: [] +keywords: [] +action: + related: [] + returnType: '[]string' + signatures: [PAGE.Aliases] +--- + +The `Aliases` method on a `Page` object returns the URL [aliases] as defined in front matter. + +For example: + +{{< code-toggle file=content/about.md fm=true >}} +title = 'About' +aliases = ['/old-url','/really-old-url'] +{{< /code-toggle >}} + +To list the aliases: + +```go-html-template +{{ range .Aliases }} + {{ . }} +{{ end }} +``` + +[aliases]: /content-management/urls/#aliases diff --git a/docs/content/en/methods/page/AllTranslations.md b/docs/content/en/methods/page/AllTranslations.md new file mode 100644 index 000000000..b8cc65179 --- /dev/null +++ b/docs/content/en/methods/page/AllTranslations.md @@ -0,0 +1,91 @@ +--- +title: AllTranslations +description: Returns all translation of the given page, including the given page. +categories: [] +keywords: [] +action: + related: + - methods/page/Translations + - methods/page/IsTranslated + - methods/page/TranslationKey + returnType: page.Pages + signatures: [PAGE.AllTranslations] +--- + +With this site configuration: + +{{< code-toggle file=hugo >}} +defaultContentLanguage = 'en' + +[languages.en] +contentDir = 'content/en' +languageCode = 'en-US' +languageName = 'English' +weight = 1 + +[languages.de] +contentDir = 'content/de' +languageCode = 'de-DE' +languageName = 'Deutsch' +weight = 2 + +[languages.fr] +contentDir = 'content/fr' +languageCode = 'fr-FR' +languageName = 'Français' +weight = 3 +{{< /code-toggle >}} + +And this content: + +```text +content/ +├── de/ +│ ├── books/ +│ │ ├── book-1.md +│ │ └── book-2.md +│ └── _index.md +├── en/ +│ ├── books/ +│ │ ├── book-1.md +│ │ └── book-2.md +│ └── _index.md +├── fr/ +│ ├── books/ +│ │ └── book-1.md +│ └── _index.md +└── _index.md +``` + +And this template: + +```go-html-template +{{ with .AllTranslations }} + <ul> + {{ range . }} + {{ $langName := or .Language.LanguageName .Language.Lang }} + {{ $langCode := or .Language.LanguageCode .Language.Lang }} + <li><a href="{{ .RelPermalink }}" hreflang="{{ $langCode }}">{{ .LinkTitle }} ({{ $langName }})</a></li> + {{ end }} + </ul> +{{ end }} +``` + +Hugo will render this list on the "Book 1" page of each site: + +```html +<ul> + <li><a href="/books/book-1/" hreflang="en-US">Book 1 (English)</a></li> + <li><a href="/de/books/book-1/" hreflang="de-DE">Book 1 (Deutsch)</a></li> + <li><a href="/fr/books/book-1/" hreflang="fr-FR">Book 1 (Français)</a></li> +</ul> +``` + +On the "Book 2" page of the English and German sites, Hugo will render this: + +```html +<ul> + <li><a href="/books/book-1/" hreflang="en-US">Book 1 (English)</a></li> + <li><a href="/de/books/book-1/" hreflang="de-DE">Book 1 (Deutsch)</a></li> +</ul> +``` diff --git a/docs/content/en/methods/page/AlternativeOutputFormats.md b/docs/content/en/methods/page/AlternativeOutputFormats.md new file mode 100644 index 000000000..b48d1adf4 --- /dev/null +++ b/docs/content/en/methods/page/AlternativeOutputFormats.md @@ -0,0 +1,43 @@ +--- +title: AlternativeOutputFormats +description: Returns a slice of OutputFormat objects, excluding the current output format, each representing one of the output formats enabled for the given page. +categories: [] +keywords: [] +action: + related: + - methods/page/OutputFormats + returnType: page.OutputFormats + signatures: [PAGE.AlternativeOutputFormats] +--- + +{{% include "methods/page/_common/output-format-definition.md" %}} + +The `AlternativeOutputFormats` method on a `Page` object returns a slice of `OutputFormat` objects, excluding the current output format, each representing one of the output formats enabled for the given page.. See [details](/templates/output-formats/). + +## Methods + +{{% include "methods/page/_common/output-format-methods.md" %}} + +## Example + +Generate a `link` element in the `<head>` of each page for each of the alternative output formats: + +```go-html-template +<head> + ... + {{ $title := printf "%s | %s" .Title site.Title }} + {{ if .IsHome }} + {{ $title = site.Title }} + {{ end }} + {{ range .AlternativeOutputFormats -}} + {{ printf `<link rel=%q type=%q href=%q title=%q>` .Rel .MediaType.Type .Permalink $title | safeHTML }} + {{ end }} + ... +</head> +``` + +On the site's home page, Hugo renders this to: + +```html +<link rel="alternate" type="application/rss+xml" href="https://example.org/index.xml" title="ABC Widgets, Inc."> +``` diff --git a/docs/content/en/methods/page/Ancestors.md b/docs/content/en/methods/page/Ancestors.md new file mode 100644 index 000000000..3bf36d9aa --- /dev/null +++ b/docs/content/en/methods/page/Ancestors.md @@ -0,0 +1,87 @@ +--- +title: Ancestors +description: Returns a collection of Page objects, one for each ancestor section of the given page. +categories: [] +keywords: [] +action: + related: + - methods/page/CurrentSection + - methods/page/FirstSection + - methods/page/InSection + - methods/page/IsAncestor + - methods/page/IsDescendant + - methods/page/Parent + - methods/page/Sections + returnType: page.Pages + signatures: [PAGE.Ancestors] +--- + +{{< new-in 0.109.0 >}} + +{{% include "methods/page/_common/definition-of-section.md" %}} + +With this content structure: + +```text +content/ +├── auctions/ +│ ├── 2023-11/ +│ │ ├── _index.md <-- front matter: weight = 202311 +│ │ ├── auction-1.md +│ │ └── auction-2.md +│ ├── 2023-12/ +│ │ ├── _index.md <-- front matter: weight = 202312 +│ │ ├── auction-3.md +│ │ └── auction-4.md +│ ├── _index.md <-- front matter: weight = 30 +│ ├── bidding.md +│ └── payment.md +├── books/ +│ ├── _index.md <-- front matter: weight = 10 +│ ├── book-1.md +│ └── book-2.md +├── films/ +│ ├── _index.md <-- front matter: weight = 20 +│ ├── film-1.md +│ └── film-2.md +└── _index.md +``` + +And this template: + +```go-html-template +{{ range .Ancestors }} + <a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a> +{{ end }} +``` + +On the November 2023 auctions page, Hugo renders: + +```html +<a href="/auctions/2023-11/">Auctions in November 2023</a> +<a href="/auctions/">Auctions</a> +<a href="/">Home</a> +``` + +In the example above, notice that Hugo orders the ancestors from closest to furthest. This makes breadcrumb navigation simple: + +```go-html-template +<nav aria-label="breadcrumb" class="breadcrumb"> + <ol> + {{ range .Ancestors.Reverse }} + <li> + <a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a> + </li> + {{ end }} + <li class="active"> + <a aria-current="page" href="{{ .RelPermalink }}">{{ .LinkTitle }}</a> + </li> + </ol> +</nav> +``` + +With some CSS, the code above renders something like this, where each breadcrumb links to its page: + +```text +Home > Auctions > Auctions in November 2023 > Auction 1 +``` diff --git a/docs/content/en/methods/page/BundleType.md b/docs/content/en/methods/page/BundleType.md new file mode 100644 index 000000000..77d1d72eb --- /dev/null +++ b/docs/content/en/methods/page/BundleType.md @@ -0,0 +1,37 @@ +--- +title: BundleType +description: Returns the bundle type of the given page, or an empty string if the page is not a page bundle. +categories: [] +keywords: [] +action: + related: [] + returnType: files.ContentClass + signatures: [PAGE.BundleType] +--- + +A page bundle is a directory that encapsulates both content and associated [resources]. There are two types of page bundles: [leaf bundles] and [branch bundles]. See [details](/content-management/page-bundles/). + +The `BundleType` method on a `Page` object returns `branch` for branch bundles, `leaf` for leaf bundles, and an empty string if the page is not a page bundle. + +```text +content/ +├── films/ +│ ├── film-1/ +│ │ ├── a.jpg +│ │ └── index.md <-- leaf bundle +│ ├── _index.md <-- branch bundle +│ ├── b.jpg +│ ├── film-2.md +│ └── film-3.md +└── _index.md <-- branch bundle +``` + +To get the value within a template: + +```go-html-template +{{ .BundleType }} +``` + +[resources]: /getting-started/glossary/#resource +[leaf bundles]: /getting-started/glossary/#leaf-bundle +[branch bundles]: /getting-started/glossary/#branch-bundle diff --git a/docs/content/en/methods/page/CodeOwners.md b/docs/content/en/methods/page/CodeOwners.md new file mode 100644 index 000000000..068c4591f --- /dev/null +++ b/docs/content/en/methods/page/CodeOwners.md @@ -0,0 +1,66 @@ +--- +title: CodeOwners +description: Returns of slice of code owners for the given page, derived from the CODEOWNERS file in the root of the project directory. +categories: [] +keywords: [] +action: + related: + - methods/page/GitInfo + returnType: '[]string' + signatures: [PAGE.CodeOwners] +--- + +GitHub and GitLab support CODEOWNERS files. This file specifies the users responsible for developing and maintaining software and documentation. This definition can apply to the entire repository, specific directories, or to individual files. To learn more: + +- [GitHub CODEOWNERS documentation] +- [GitLab CODEOWNERS documentation] + +Use the `CodeOwners` method on a `Page` object to determine the code owners for the given page. + +[GitHub CODEOWNERS documentation]: https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners +[GitLab CODEOWNERS documentation]: https://docs.gitlab.com/ee/user/project/code_owners.html + +To use the `CodeOwners` method you must enable access to your local Git repository: + +{{< code-toggle file=hugo >}} +enableGitInfo = true +{{< /code-toggle >}} + +Consider this project structure: + +```text +my-project/ +├── content/ +│ ├── books/ +│ │ └── les-miserables.md +│ └── films/ +│ └── the-hunchback-of-notre-dame.md +└── CODEOWNERS +``` + +And this CODEOWNERS file: + +```text +* @jdoe +/content/books/ @tjones +/content/films/ @mrichards @rsmith +``` + +The table below shows the slice of code owners returned for each file: + +Path|Code owners +:--|:-- +`books/les-miserables.md`|`[@tjones]` +`films/the-hunchback-of-notre-dame.md`|`[@mrichards @rsmith]` + +Render the code owners for each content page: + +```go-html-template +{{ range .CodeOwners }} + {{ . }} +{{ end }} +``` + +Combine this method with [`resources.GetRemote`] to retrieve names and avatars from your Git provider by querying their API. + +[`resources.GetRemote`]: functions/resources/getremote diff --git a/docs/content/en/methods/page/Content.md b/docs/content/en/methods/page/Content.md new file mode 100644 index 000000000..40a057f02 --- /dev/null +++ b/docs/content/en/methods/page/Content.md @@ -0,0 +1,22 @@ +--- +title: Content +description: Returns the rendered content of the given page. +categories: [] +keywords: [] +action: + related: + - methods/page/RawContent + - methods/page/Plain + - methods/page/PlainWords + - methods/page/RenderShortcodes + returnType: template.HTML + signatures: [PAGE.Content] +--- + +The `Content` method on a `Page` object renders markdown and shortcodes to HTML. The content does not include front matter. + +[shortcodes]: /getting-started/glossary/#shortcode + +```go-html-template +{{ .Content }} +``` diff --git a/docs/content/en/methods/page/CurrentSection.md b/docs/content/en/methods/page/CurrentSection.md new file mode 100644 index 000000000..7049feb47 --- /dev/null +++ b/docs/content/en/methods/page/CurrentSection.md @@ -0,0 +1,60 @@ +--- +title: CurrentSection +description: Returns the Page object of the section in which the given page resides. +categories: [] +keywords: [] +action: + related: + - methods/page/Ancestors + - methods/page/FirstSection + - methods/page/InSection + - methods/page/IsAncestor + - methods/page/IsDescendant + - methods/page/Parent + - methods/page/Sections + returnType: page.Page + signatures: [PAGE.CurrentSection] +--- + +{{% include "methods/page/_common/definition-of-section.md" %}} + +{{% note %}} +The current section of a [section] page, [taxonomy] page, [term] page, or the home page, is itself. + +[section]: /getting-started/glossary/#section +[taxonomy]: /getting-started/glossary/#taxonomy +[term]: /getting-started/glossary/#term +{{% /note %}} + +Consider this content structure: + +```text +content/ +├── auctions/ +│ ├── 2023-11/ +│ │ ├── _index.md <-- current section: 2023-11 +│ │ ├── auction-1.md +│ │ └── auction-2.md <-- current section: 2023-11 +│ ├── 2023-12/ +│ │ ├── _index.md +│ │ ├── auction-3.md +│ │ └── auction-4.md +│ ├── _index.md <-- current section: auctions +│ ├── bidding.md +│ └── payment.md <-- current section: auctions +├── books/ +│ ├── _index.md <-- current section: books +│ ├── book-1.md +│ └── book-2.md <-- current section: books +├── films/ +│ ├── _index.md <-- current section: films +│ ├── film-1.md +│ └── film-2.md <-- current section: films +└── _index.md <-- current section: home +``` + +To create a link to the current section page: + +```go-html-template +<a href="{{ .CurrentSection.RelPermalink }}">{{ .CurrentSection.LinkTitle }}</a> +``` diff --git a/docs/content/en/methods/page/Data.md b/docs/content/en/methods/page/Data.md new file mode 100644 index 000000000..4eccde6ff --- /dev/null +++ b/docs/content/en/methods/page/Data.md @@ -0,0 +1,111 @@ +--- +title: Data +description: Returns a unique data object for each page kind. +categories: [] +keywords: [] +action: + related: [] + returnType: page.Data + signatures: [PAGE.Data] +toc: true +--- + +The `Data` method on a `Page` object returns a unique data object for each [page kind]. + +[page kind]: /getting-started/glossary/#page-kind + +{{% note %}} +The `Data` method is only useful within [taxonomy] and [term] templates. + +Themes that are not actively maintained may still use `.Data.Pages` in list templates. Although that syntax remains functional, use one of these methods instead: [`Pages`], [`RegularPages`], or [`RegularPagesRecursive`] + +[`Pages`]: /methods/page/pages/ +[`RegularPages`]: /methods/page/regularpages/ +[`RegularPagesRecursive`]: /methods/page/regularpagesrecursive/ +[term]: /getting-started/glossary/#term +[taxonomy]: /getting-started/glossary/#taxonomy +{{% /note %}} + +The examples that follow are based on this site configuration: + +{{< code-toggle file=hugo >}} +[taxonomies] +genre = 'genres' +author = 'authors' +{{< /code-toggle >}} + +And this content structure: + +```text +content/ +├── books/ +│ ├── and-then-there-were-none.md --> genres: suspense +│ ├── death-on-the-nile.md --> genres: suspense +│ └── jamaica-inn.md --> genres: suspense, romance +│ └── pride-and-prejudice.md --> genres: romance +└── _index.md +``` + +## In a taxonomy template + +Use these methods on the `Data` object within a taxonomy template. + +Singular +: (`string`) Returns the singular name of the taxonomy. + +```go-html-template +{{ .Data.Singular }} → genre +``` + +Plural +: (`string`) Returns the plural name of the taxonomy. + +```go-html-template +{{ .Data.Plural }} → genres +``` + +Terms +: (`page.Taxonomy`) Returns the taxonomy object, consisting of a map of terms and the [weighted pages] associated with each term. + +```go-html-template +{{ $taxonomyObject := .Data.Terms }} +``` + +{{% note %}} +Once you have captured the taxonomy object, use any of the [taxonomy methods] to sort, count, or capture a subset of its weighted pages. + +[taxonomy methods]: /methods/taxonomy +{{% /note %}} + +Learn more about [taxonomy templates]. + +## In a term template + +Use these methods on the `Data` object within a term template. + +Singular +: (`string`) Returns the singular name of the taxonomy. + +```go-html-template +{{ .Data.Singular }} → genre +``` + +Plural +: (`string`) Returns the plural name of the taxonomy. + +```go-html-template +{{ .Data.Plural }} → genres +``` + +Term +: (`string`) Returns the name of the term. + +```go-html-template +{{ .Data.Term }} → suspense +``` + +Learn more about [term templates]. + +[taxonomy templates]: /templates/taxonomy-templates/ +[term templates]: /templates/taxonomy-templates/ +[weighted pages]: /getting-started/glossary/#weighted-page diff --git a/docs/content/en/methods/page/Date.md b/docs/content/en/methods/page/Date.md new file mode 100644 index 000000000..83192f94c --- /dev/null +++ b/docs/content/en/methods/page/Date.md @@ -0,0 +1,39 @@ +--- +title: Date +description: Returns the date of the given page. +categories: [] +keywords: [] +action: + related: + - methods/page/ExpiryDate + - methods/page/LastMod + - methods/page/PublishDate + returnType: time.Time + signatures: [PAGE.Date] +--- + +Set the date in front matter: + +{{< code-toggle file=content/news/article-1.md fm=true >}} +title = 'Article 1' +date = 2023-10-19T00:40:04-07:00 +{{< /code-toggle >}} + +{{% note %}} +The date field in front matter is often considered to be the creation date, You can change its meaning, and its effect on your site, in the site configuration. See [details]. + +[details]: /getting-started/configuration/#configure-dates +{{% /note %}} + +The date is a [time.Time] value. Format and localize the value with the [`time.Format`] function, or use it with any of the [time methods]. + +```go-html-template +{{ .Date | time.Format ":date_medium" }} → Oct 19, 2023 +``` + +In the example above we explicitly set the date in front matter. With Hugo's default configuration, the `Date` method returns the front matter value. This behavior is configurable, allowing you to set fallback values if the date is not defined in front matter. See [details]. + +[`time.Format`]: /functions/time/format +[details]: /getting-started/configuration/#configure-dates +[time methods]: /methods/time +[time.Time]: https://pkg.go.dev/time#Time diff --git a/docs/content/en/methods/page/Description.md b/docs/content/en/methods/page/Description.md new file mode 100644 index 000000000..fbb43b8b5 --- /dev/null +++ b/docs/content/en/methods/page/Description.md @@ -0,0 +1,28 @@ +--- +title: Description +description: Returns the description of the given page as defined in front matter. +categories: [] +keywords: [] +action: + related: + - methods/page/Summary + returnType: string + signatures: [PAGE.Description] +--- + +Conceptually different that a [content summary], a page description is typically used in metadata about the page. + +{{< code-toggle file=content/recipes/sushi.md fm=true >}} +title = 'How to make spicy tuna hand rolls' +description = 'Instructions for making spicy tuna hand rolls.' +{{< /code-toggle >}} + +{{< code file=layouts/baseof.html >}} +<head> + ... + <meta name="description" content="{{ .Description }}"> + ... +</head> +{{< /code >}} + +[content summary]: /content-management/summaries diff --git a/docs/content/en/methods/page/Draft.md b/docs/content/en/methods/page/Draft.md new file mode 100644 index 000000000..fd55a9bc9 --- /dev/null +++ b/docs/content/en/methods/page/Draft.md @@ -0,0 +1,21 @@ +--- +title: Draft +description: Reports whether the given page is a draft as defined in front matter. +categories: [] +keywords: [] +action: + related: [] + returnType: bool + signatures: [PAGE.Draft] +--- + +By default, Hugo does not publish draft pages when you build your site. To include draft pages when you build your site, use the `--buildDrafts` command line flag. + +{{< code-toggle file=content/posts/post-1.md fm=true >}} +title = 'Post 1' +draft = true +{{< /code-toggle >}} + +```go-html-template +{{ .Draft }} → true +``` diff --git a/docs/content/en/methods/page/Eq.md b/docs/content/en/methods/page/Eq.md new file mode 100644 index 000000000..1be416295 --- /dev/null +++ b/docs/content/en/methods/page/Eq.md @@ -0,0 +1,21 @@ +--- +title: Eq +description: Reports whether two Page objects are equal. +categories: [] +keywords: [] +action: + related: [] + returnType: bool + signatures: [PAGE1.Eq PAGE2] +--- + +In this contrived example from a single page template, we list all pages in the current section except for the current page. + +```go-html-template +{{ $currentPage := . }} +{{ range .CurrentSection.Pages }} + {{ if not (.Eq $currentPage) }} + <a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a> + {{ end }} +{{ end }} +``` diff --git a/docs/content/en/methods/page/ExpiryDate.md b/docs/content/en/methods/page/ExpiryDate.md new file mode 100644 index 000000000..353546449 --- /dev/null +++ b/docs/content/en/methods/page/ExpiryDate.md @@ -0,0 +1,35 @@ +--- +title: ExpiryDate +description: Returns the expiry date of the given page. +categories: [] +keywords: [] +action: + related: + - methods/page/Date + - methods/page/LastMod + - methods/page/PublishDate + returnType: time.Time + signatures: [PAGE.ExpiryDate] +--- + +By default, Hugo excludes expired pages when building your site. To include expired pages, use the `--buildExpired` command line flag. + +Set the expiry date in front matter: + +{{< code-toggle file=content/news/article-1.md fm=true >}} +title = 'Article 1' +expiryDate = 2024-10-19T00:32:13-07:00 +{{< /code-toggle >}} + +The expiry date is a [time.Time] value. Format and localize the value with the [`time.Format`] function, or use it with any of the [time methods]. + +```go-html-template +{{ .ExpiryDate | time.Format ":date_medium" }} → Oct 19, 2024 +``` + +In the example above we explicitly set the expiry date in front matter. With Hugo's default configuration, the `ExpiryDate` method returns the front matter value. This behavior is configurable, allowing you to set fallback values if the expiry date is not defined in front matter. See [details]. + +[`time.Format`]: /functions/time/format +[details]: /getting-started/configuration/#configure-dates +[time methods]: /methods/time +[time.Time]: https://pkg.go.dev/time#Time diff --git a/docs/content/en/methods/page/File.md b/docs/content/en/methods/page/File.md new file mode 100644 index 000000000..44b752215 --- /dev/null +++ b/docs/content/en/methods/page/File.md @@ -0,0 +1,190 @@ +--- +title: File +description: For pages backed by a file, returns file information for the given page. +categories: [] +keywords: [] +action: + related: [] + returnType: hugolib.fileInfo + signatures: [PAGE.File] +toc: true +--- + +By default, not all pages are backed by a file, including top level [section] pages, [taxonomy] pages, and [term] pages. By definition, you cannot retrieve file information when the file does not exist. + +To back one of the pages above with a file, create an _index.md file in the corresponding directory. For example: + +```text +content/ +└── books/ + ├── _index.md <-- the top level section page + ├── book-1.md + └── book-2.md +``` + +Code defensively by verifying file existence as shown in each of the examples below. + +## Methods + +{{% note %}} +The path separators (slash or backslash) in `Path`, `Dir`, and `Filename` depend on the operating system. +{{% /note %}} + +###### BaseFileName + +(`string`) The file name, excluding the extension. + +```go-html-template +{{ with .File }} + {{ .BaseFileName }} +{{ end }} +``` + +###### ContentBaseName + +(`string`) If the page is a branch or leaf bundle, the name of the containing directory, else the `TranslationBaseName`. + +```go-html-template +{{ with .File }} + {{ .ContentBaseName }} +{{ end }} +``` + +###### Dir + +(`string`) The file path, excluding the file name, relative to the `content` directory. + +```go-html-template +{{ with .File }} + {{ .Dir }} +{{ end }} +``` + +###### Ext + +(`string`) The file extension. + +```go-html-template +{{ with .File }} + {{ .Ext }} +{{ end }} +``` + +###### Filename + +(`string`) The absolute file path. + +```go-html-template +{{ with .File }} + {{ .Filename }} +{{ end }} +``` + +###### Lang + +(`string`) The language associated with the given file. + +```go-html-template +{{ with .File }} + {{ .Lang }} +{{ end }} +``` + +###### LogicalName + +(`string`) The file name. + +```go-html-template +{{ with .File }} + {{ .LogicalName }} +{{ end }} +``` + +###### Path + +(`string`) The file path, relative to the `content` directory. + +```go-html-template +{{ with .File }} + {{ .Path }} +{{ end }} +``` + +###### TranslationBaseName + +(`string`) The file name, excluding the extension and language identifier. + +```go-html-template +{{ with .File }} + {{ .TranslationBaseName }} +{{ end }} +``` + +###### UniqueID + +(`string`) The MD5 hash of `.File.Path`. + +```go-html-template +{{ with .File }} + {{ .UniqueID }} +{{ end }} +``` + +## Examples + +Consider this content structure in a multilingual project: + +```text +content/ +├── news/ +│ ├── b/ +│ │ ├── index.de.md <-- leaf bundle +│ │ └── index.en.md <-- leaf bundle +│ ├── a.de.md <-- regular content +│ ├── a.en.md <-- regular content +│ ├── _index.de.md <-- branch bundle +│ └── _index.en.md <-- branch bundle +├── _index.de.md +└── _index.en.md +``` + +With the English language site: + + |regular content|leaf bundle|branch bundle +:--|:--|:--|:-- +BaseFileName|a.en|index.en|_index.en +ContentBaseName|a|b|news +Dir|news/|news/b/|news/ +Ext|md|md|md +Filename|/home/user/...|/home/user/...|/home/user/... +Lang|en|en|en +LogicalName|a.en.md|index.en.md|_index.en.md +Path|news/a.en.md|news/b/index.en.md|news/_index.en.md +TranslationBaseName|a|index|_index +UniqueID|15be14b...|186868f...|7d9159d... + +## Defensive coding + +Some of the pages on a site may not be backed by a file. For example: + +- Top level section pages +- Taxonomy pages +- Term pages + +Without a backing file, Hugo will throw a warning if you attempt to access a `.File` property. For example: + +```text +WARN .File.ContentBaseName on zero object. Wrap it in if or with... +``` + +To code defensively, first check for file existence: + +```go-html-template +{{ with .File }} + {{ .ContentBaseName }} +{{ end }} +``` + +[section]: /getting-started/glossary/#section +[taxonomy]: /getting-started/glossary/#taxonomy +[term]: /getting-started/glossary/#term diff --git a/docs/content/en/methods/page/FirstSection.md b/docs/content/en/methods/page/FirstSection.md new file mode 100644 index 000000000..b3ae4c04a --- /dev/null +++ b/docs/content/en/methods/page/FirstSection.md @@ -0,0 +1,56 @@ +--- +title: FirstSection +description: Returns the Page object of the top level section of which the given page is a descendant. +categories: [] +keywords: [] +action: + related: + - methods/page/Ancestors + - methods/page/CurrentSection + - methods/page/InSection + - methods/page/IsAncestor + - methods/page/IsDescendant + - methods/page/Parent + - methods/page/Sections + returnType: page.Page + signatures: [PAGE.FirstSection] +--- + +{{% include "methods/page/_common/definition-of-section.md" %}} + +{{% note %}} +When called on the home page, the `FirstSection` method returns the `Page` object of the home page itself. +{{% /note %}} + +Consider this content structure: + +```text +content/ +├── auctions/ +│ ├── 2023-11/ +│ │ ├── _index.md <-- first section: auctions +│ │ ├── auction-1.md +│ │ └── auction-2.md <-- first section: auctions +│ ├── 2023-12/ +│ │ ├── _index.md +│ │ ├── auction-3.md +│ │ └── auction-4.md +│ ├── _index.md <-- first section: auctions +│ ├── bidding.md +│ └── payment.md <-- first section: auctions +├── books/ +│ ├── _index.md <-- first section: books +│ ├── book-1.md +│ └── book-2.md <-- first section: books +├── films/ +│ ├── _index.md <-- first section: films +│ ├── film-1.md +│ └── film-2.md <-- first section: films +└── _index.md <-- first section: home +``` + +To link to the top level section of which the current page is a descendant: + +```go-html-template +<a href="{{ .FirstSection.RelPermalink }}">{{ .FirstSection.LinkTitle }}</a> +``` diff --git a/docs/content/en/methods/page/Fragments.md b/docs/content/en/methods/page/Fragments.md new file mode 100644 index 000000000..89f82d2ce --- /dev/null +++ b/docs/content/en/methods/page/Fragments.md @@ -0,0 +1,106 @@ +--- +title: Fragments +description: Returns a data structure of the fragments in the given page. +categories: [] +keywords: [] +action: + related: + - methods/page/TableOfContents + returnType: tableofcontents.Fragments + signatures: [PAGE.Fragments] +toc: true +--- + +{{< new-in 0.111.0 >}} + +In a URL, whether absolute or relative, the [fragment] links to an `id` attribute of an HTML element on the page. + +```text +/articles/article-1#section-2 +------------------- --------- + path fragment +``` + +Hugo assigns an `id` attribute to each markdown [ATX] and [setext] heading within the page content. You can override the `id` with a [markdown attribute] as needed. This creates the relationship between an entry in the [table of contents] (TOC) and a heading on the page. + +Use the `Fragments` method on a `Page` object to create a table of contents with the `Fragments.ToHTML` method, or by [walking] the `Fragments.Map` data structure. + +## Methods + +Headings +: (`map`) A nested map of all headings on the page. Each map contains the following keys: `ID`, `Level`, `Title` and `Headings`. To inspect the data structure: + +```go-html-template +<pre>{{ .Fragments.Headings | jsonify (dict "indent" " ") }}</pre> +``` + +HeadingsMap +: (`slice`) A slice of maps of all headings on the page, with first-level keys for each heading. Each map contains the following keys: `ID`, `Level`, `Title` and `Headings`. To inspect the data structure: + +```go-html-template +<pre>{{ .Fragments.HeadingsMap | jsonify (dict "indent" " ") }}</pre> +``` + +Identifiers +: (`slice`) A slice containing the `id` of each heading on the page. To inspect the data structure: + +```go-html-template +<pre>{{ .Fragments.Identifiers | jsonify (dict "indent" " ") }}</pre> +``` + +Identifiers.Contains ID +: (`bool`) Reports whether one or more headings on the page has the given `id` attribute, useful for validating fragments within a link [render hook]. + +```go-html-template +{{ .Fragments.Identifiers.Contains "section-2" }} → true +``` + +Identifiers.Count ID +: (`int`) The number of headings on a page with the given `id` attribute, useful for detecting duplicates. + +```go-html-template +{{ .Fragments.Identifiers.Count "section-2" }} → 1 +``` + +ToHTML +: (`template.HTML`) Returns a TOC as a nested list, either ordered or unordered, identical to the HTML returned by the [`TableOfContents`] method. This method take three arguments: the start level (`int`), the end level (`int`), and a boolean (`true` to return an ordered list, `false` to return an unordered list). + +Use this method when you want to control the start level, end level, or list type independently from the table of contents settings in your site configuration. + +```go-html-template +{{ $startLevel := 2 }} +{{ $endLevel := 3 }} +{{ $ordered := true }} +{{ .Fragments.ToHTML $startLevel $endLevel $ordered }} +``` + +Hugo renders this to: + +```html +<nav id="TableOfContents"> + <ol> + <li><a href="#section-1">Section 1</a> + <ol> + <li><a href="#section-11">Section 1.1</a></li> + <li><a href="#section-12">Section 1.2</a></li> + </ol> + </li> + <li><a href="#section-2">Section 2</a></li> + </ol> +</nav> +``` + +{{% note %}} +It is safe to use the `Fragments` methods within a render hook, even for the current page. + +When using the `Fragments` methods within a shortcode, call the shortcode using the `{{</* */>}}` notation. If you use the `{{%/* */%}}` notation, the rendered shortcode is included in the creation of the fragments map, resulting in a circular loop. +{{% /note %}} + +[atx]: https://spec.commonmark.org/0.30/#atx-headings +[fragment]: /getting-started/glossary/#fragment +[markdown attribute]: /getting-started/glossary/#markdown-attribute +[setext]: https://spec.commonmark.org/0.30/#setext-headings +[table of contents]: /methods/page/tableofcontents +[walking]: /getting-started/glossary/#walk +[`tableofcontents`]: /methods/page/tableofcontents +[render hook]: /getting-started/glossary/#render-hook diff --git a/docs/content/en/methods/page/FuzzyWordCount.md b/docs/content/en/methods/page/FuzzyWordCount.md new file mode 100644 index 000000000..600ad48d5 --- /dev/null +++ b/docs/content/en/methods/page/FuzzyWordCount.md @@ -0,0 +1,20 @@ +--- +title: FuzzyWordCount +description: Returns the number of words in the content of the given page, rounded up to the nearest multiple of 100. +categories: [] +keywords: [] +action: + related: + - methods/page/WordCount + - methods/page/ReadingTime + returnType: int + signatures: [PAGE.FuzzyWordCount] +--- + +```go-html-template +{{ .FuzzyWordCount }} → 200 +``` + +To get the exact word count, use the [`WordCount`] method. + +[`WordCount`]: /methods/page/wordcount diff --git a/docs/content/en/methods/page/GetPage.md b/docs/content/en/methods/page/GetPage.md new file mode 100644 index 000000000..b1f192d58 --- /dev/null +++ b/docs/content/en/methods/page/GetPage.md @@ -0,0 +1,65 @@ +--- +title: GetPage +description: Returns a Page object from the given path. +categories: [] +keywords: [] +action: + related: + - methods/site/GetPage + returnType: page.Page + signatures: [PAGE.GetPage PATH] +aliases: [/functions/getpage] +--- + +The `GetPage` method is also available on a `Site` object. See [details]. + +[details]: /methods/site/getpage + +When using the `GetPage` method on the `Page` object, specify a path relative to the current directory or relative to the content directory. + +If Hugo cannot resolve the path to a page, the method returns nil. If the path is ambiguous, Hugo throws an error and fails the build. + +Consider this content structure: + +```text +content/ +├── works/ +│ ├── paintings/ +│ │ ├── _index.md +│ │ ├── starry-night.md +│ │ └── the-mona-lisa.md +│ ├── sculptures/ +│ │ ├── _index.md +│ │ ├── david.md +│ │ └── the-thinker.md +│ └── _index.md +└── _index.md +``` + +The examples below depict the result of rendering works/paintings/the-mona-list.md with a single page template: + +```go-html-template +{{ with .GetPage "starry-night" }} + {{ .Title }} → Starry Night +{{ end }} + +{{ with .GetPage "./starry-night" }} + {{ .Title }} → Starry Night +{{ end }} + +{{ with .GetPage "../paintings/starry-night" }} + {{ .Title }} → Starry Night +{{ end }} + +{{ with .GetPage "/works/paintings/starry-night" }} + {{ .Title }} → Starry Night +{{ end }} + +{{ with .GetPage "../sculptures/david" }} + {{ .Title }} → David +{{ end }} + +{{ with .GetPage "/works/sculptures/david" }} + {{ .Title }} → David +{{ end }} +``` diff --git a/docs/content/en/methods/page/GetTerms.md b/docs/content/en/methods/page/GetTerms.md new file mode 100644 index 000000000..3020e4c2e --- /dev/null +++ b/docs/content/en/methods/page/GetTerms.md @@ -0,0 +1,41 @@ +--- +title: GetTerms +description: Returns a collection of term pages for terms defined on the given page in the given taxonomy, ordered according to the sequence in which they appear in front matter. +categories: [] +keywords: [] +action: + related: [] + returnType: page.Pages + signatures: [PAGE.GetTerms TAXONOMY] +--- + +Given this front matter: + +{{< code-toggle file=content/books/les-miserables.md fm=true >}} +title = 'Les Misérables' +tags = ['historical','classic','fiction'] +{{< /code-toggle >}} + +This template code: + +```go-html-template +{{ with .GetTerms "tags" }} + <p>Tags</p> + <ul> + {{ range . }} + <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li> + {{ end }} + </ul> +{{ end }} +``` + +Is rendered to: + +```html +<p>Tags</p> +<ul> + <li><a href="/tags/historical/">historical</a></li> + <li><a href="/tags/classic/">classic</a></li> + <li><a href="/tags/fiction/">fiction</a></li> +</ul> +``` diff --git a/docs/content/en/methods/page/GitInfo.md b/docs/content/en/methods/page/GitInfo.md new file mode 100644 index 000000000..9dba2a2b2 --- /dev/null +++ b/docs/content/en/methods/page/GitInfo.md @@ -0,0 +1,146 @@ +--- +title: GitInfo +description: Returns Git information related to the last commit of the given page. +categories: [] +keywords: [] +action: + related: + - methods/page/CodeOwners + returnType: source.GitInfo + signatures: [PAGE.GitInfo] +toc: true +--- + +The `GitInfo` method on a `Page` object returns an object with additional methods. + +{{% note %}} +Hugo's Git integration is performant, but may increase build times on large sites. +{{% /note %}} + +## Prerequisites + +Install [Git], create a repository, and commit your project files. + +You must also allow Hugo to access your repository. In your site configuration: + +{{< code-toggle file=hugo >}} +enableGitInfo = true +{{< /code-toggle >}} + +Alternatively, use the command line flag when building your site: + +```sh +hugo --enableGitInfo +``` + +{{% note %}} +When you set `enableGitInfo` to `true`, or enable the feature with the command line flag, the last modification date for each content page will be the Author Date of the last commit for that file. + +This is configurable. See [details]. + +[details]: /getting-started/configuration/#configure-dates +{{% /note %}} + +## Methods + +###### AbbreviatedHash + +(`string`) The abbreviated commit hash. + +```go-html-template +{{ with .GitInfo }} + {{ .AbbreviatedHash }} → aab9ec0b3 +{{ end }} +``` + +###### AuthorDate + +(`time.Time`) The author date. + +```go-html-template +{{ with .GitInfo }} + {{ .AuthorDate.Format "2006-01-02" }} → 2023-10-09 +{{ end }} +``` + +###### AuthorEmail + +(`string`) The author's email address, respecting [gitmailmap]. + +```go-html-template +{{ with .GitInfo }} + {{ .AuthorEmail }} → jsmith@example.org +{{ end }} +``` + +###### AuthorName + +(`string`) The author's name, respecting [gitmailmap]. + +```go-html-template +{{ with .GitInfo }} + {{ .AuthorName }} → John Smith +{{ end }} +``` + +###### CommitDate + +(`time.Time`) The commit date. + +```go-html-template +{{ with .GitInfo }} + {{ .CommitDate.Format "2006-01-02" }} → 2023-10-09 +{{ end }} +``` + +###### Hash + +(`string`) The commit hash. + +```go-html-template +{{ with .GitInfo }} + {{ .Hash }} → aab9ec0b31ebac916a1468c4c9c305f2bebf78d4 +{{ end }} +``` + +###### Subject + +(`string`) The commit message subject. + +```go-html-template +{{ with .GitInfo }} + {{ .Subject }} → Add tutorials +{{ end }} +``` + +## Last modified date + +By default, when `enableGitInfo` is `true`, the `Lastmod` method on a `Page` object returns the Git AuthorDate of the last commit that included the file. + +You can change this behavior in your [site configuration]. + +[git]: https://git-scm.com/book/en/v2/Getting-Started-Installing-Git +[gitmailmap]: https://git-scm.com/docs/gitmailmap +[site configuration]: /getting-started/configuration/#configure-front-matter + +## Hosting considerations + +When hosting your site in a CI/CD environment, the step that clones your project repository must perform a deep clone. If the clone is shallow, the Git information for a given file may not be accurate---it may reflect the most recent repository commit, not the commit that last modified the file. + +Some providers perform deep clones by default, others allow you to configure the clone depth, and some providers only perform shallow clones. + +Hosting service | Default clone depth | Configurable +:-- | :-- | :-- +Cloudflare Pages | Shallow | Yes [^CFP] +DigitalOcean App Platform | Deep | N/A +GitHub Pages | Shallow | Yes [^GHP] +GitLab Pages | Shallow | Yes [^GLP] +Netlify | Deep | N/A +Render | Shallow | No +Vercel | Shallow | No + +[^CFP]: To configure a Cloudflare Pages site for deep cloning, preface the site's normal Hugo build command with `git fetch --unshallow &&` (*e.g.*, `git fetch --unshallow && hugo`). + +[^GHP]: You can configure the GitHub Action to do a deep clone by specifying `fetch-depth: 0` in the applicable "checkout" step of your workflow file, as shown in the Hugo documentation's [example workflow file](/hosting-and-deployment/hosting-on-github/#procedure). + +[^GLP]: You can configure the GitLab Runner's clone depth [as explained in the GitLab documentation](https://docs.gitlab.com/ee/ci/large_repositories/#shallow-cloning); see also the Hugo documentation's [example workflow file](/hosting-and-deployment/hosting-on-gitlab/#configure-gitlab-cicd). diff --git a/docs/content/en/methods/page/HasMenuCurrent.md b/docs/content/en/methods/page/HasMenuCurrent.md new file mode 100644 index 000000000..68b645905 --- /dev/null +++ b/docs/content/en/methods/page/HasMenuCurrent.md @@ -0,0 +1,31 @@ +--- +title: HasMenuCurrent +description: Reports whether the given page object matches the page object associated with one of the child menu entries under the given menu entry in the given menu. +categories: [] +keywords: [] +action: + related: + - methods/page/IsMenuCurrent + returnType: bool + signatures: [PAGE.HasMenuCurrent MENU MENUENTRY] +aliases: [/functions/hasmenucurrent] +--- + +If the page object associated with the menu entry is a section, this method also returns `true` for any descendant of that section. + +```go-html-template +{{ $currentPage := . }} +{{ range site.Menus.main }} + {{ if $currentPage.IsMenuCurrent .Menu . }} + <a class="active" aria-current="page" href="{{ .URL }}">{{ .Name }}</a> + {{ else if $currentPage.HasMenuCurrent .Menu . }} + <a class="ancestor" aria-current="true" href="{{ .URL }}">{{ .Name }}</a> + {{ else }} + <a href="{{ .URL }}">{{ .Name }}</a> + {{ end }} +{{ end }} +``` + +See [menu templates] for a complete example. + +[menu templates]: /templates/menu-templates/#example diff --git a/docs/content/en/methods/page/HasShortcode.md b/docs/content/en/methods/page/HasShortcode.md new file mode 100644 index 000000000..2846e9535 --- /dev/null +++ b/docs/content/en/methods/page/HasShortcode.md @@ -0,0 +1,50 @@ +--- +title: HasShortcode +description: Reports whether the given shortcode is called by the given page. +categories: [] +keywords: [] +action: + related: [] + returnType: bool + signatures: [PAGE.HasShortcode NAME] +--- + +By example, let's use [Plotly] to render a chart: + +[Plotly]: https://plotly.com/javascript/ + +{{< code file=contents/example.md lang=markdown >}} +{{</* plotly */>}} +{ + "data": [ + { + "x": ["giraffes", "orangutans", "monkeys"], + "y": [20, 14, 23], + "type": "bar" + } + ], +} +{{</* /plotly */>}} +{{< /code >}} + +The shortcode is simple: + +{{< code file=layouts/shortcodes/plotly.html >}} +{{ $id := printf "plotly-%02d" .Ordinal }} +<div id="{{ $id }}"></div> +<script> + Plotly.newPlot(document.getElementById({{ $id }}), {{ .Inner | safeJS }}); +</script> +{{< /code >}} + +Now we can selectively load the required JavaScript on pages that call the "plotly" shortcode: + +{{< code file=layouts/baseof.html >}} +<head> + ... + {{ if .HasShortcode "plotly" }} + <script src="https://cdn.plot.ly/plotly-2.28.0.min.js"></script> + {{ end }} + ... +</head> +{{< /code >}} diff --git a/docs/content/en/methods/page/HeadingsFiltered.md b/docs/content/en/methods/page/HeadingsFiltered.md new file mode 100644 index 000000000..a39c48da1 --- /dev/null +++ b/docs/content/en/methods/page/HeadingsFiltered.md @@ -0,0 +1,18 @@ +--- +title: HeadingsFiltered +description: Returns a slice of headings for each page related to the given page. +categories: [] +keywords: [] +action: + related: + - methods/pages/Related + - methods/page/Fragments + returnType: tableofcontents.Headings + signatures: [PAGE.HeadingsFiltered] +--- + +Use in conjunction with the [`Related`] method on a [`Pages`] object. See [details]. + +[`Pages`]: /methods/pages/ +[`Related`]: /methods/pages/related +[details]: /content-management/related/#index-content-headings-in-related-content diff --git a/docs/content/en/methods/page/InSection.md b/docs/content/en/methods/page/InSection.md new file mode 100644 index 000000000..b98fbc808 --- /dev/null +++ b/docs/content/en/methods/page/InSection.md @@ -0,0 +1,102 @@ +--- +title: InSection +description: Reports whether the given page is in the given section. +categories: [] +keywords: [] +action: + related: + - methods/page/Ancestors + - methods/page/CurrentSection + - methods/page/FirstSection + - methods/page/IsAncestor + - methods/page/IsDescendant + - methods/page/Parent + - methods/page/Sections + returnType: bool + signatures: [PAGE.InSection SECTION] +toc: true +--- + +The `InSection` method on a page object reports whether the given page is in the given section. Note that the method returns `true` when comparing a page to a sibling. + +{{% include "methods/page/_common/definition-of-section.md" %}} + +With this content structure: + +```text +content/ +├── auctions/ +│ ├── 2023-11/ +│ │ ├── _index.md +│ │ ├── auction-1.md +│ │ └── auction-2.md +│ ├── 2023-12/ +│ │ ├── _index.md +│ │ ├── auction-3.md +│ │ └── auction-4.md +│ ├── _index.md +│ ├── bidding.md +│ └── payment.md +└── _index.md +``` + +When rendering the "auction-1" page: + +```go-html-template +{{ with .Site.GetPage "/" }} + {{ $.InSection . }} → false +{{ end }} + +{{ with .Site.GetPage "/auctions" }} + {{ $.InSection . }} → false +{{ end }} + +{{ with .Site.GetPage "/auctions/2023-11" }} + {{ $.InSection . }} → true +{{ end }} + +{{ with .Site.GetPage "/auctions/2023-11/auction-2" }} + {{ $.InSection . }} → true +{{ end }} +``` + +In the examples above we are coding defensively using the [`with`] statement, returning nothing if the page does not exist. By adding an [`else`] clause we can do some error reporting: + +```go-html-template +{{ $path := "/auctions/2023-11" }} +{{ with .Site.GetPage $path }} + {{ $.InSection . }} → true +{{ else }} + {{ errorf "Unable to find the section with path %s" $path }} +{{ end }} + ``` + +## Understanding context + +Inside of the `with` block, the [context] (the dot) is the section `Page` object, not the `Page` object passed into the template. If we were to use this syntax: + +```go-html-template +{{ with .Site.GetPage "/auctions" }} + {{ .InSection . }} → true +{{ end }} +``` + +The result would be wrong when rendering the "auction-1" page because we are comparing the section page to itself. + +{{% note %}} +Use the `$` to get the context passed into the template. +{{% /note %}} + +```go-html-template +{{ with .Site.GetPage "/auctions" }} + {{ $.InSection . }} → true +{{ end }} +``` + +{{% note %}} +Gaining a thorough understanding of context is critical for anyone writing template code. +{{% /note %}} + +[context]: /getting-started/glossary/#context +[`with`]: /functions/go-template/with +[`else`]: /functions/go-template/else diff --git a/docs/content/en/methods/page/IsAncestor.md b/docs/content/en/methods/page/IsAncestor.md new file mode 100644 index 000000000..ca23c0868 --- /dev/null +++ b/docs/content/en/methods/page/IsAncestor.md @@ -0,0 +1,100 @@ +--- +title: IsAncestor +description: Reports whether PAGE1 in an ancestor of PAGE2. +categories: [] +keywords: [] +action: + related: + - methods/page/Ancestors + - methods/page/CurrentSection + - methods/page/FirstSection + - methods/page/InSection + - methods/page/IsDescendant + - methods/page/Parent + - methods/page/Sections + returnType: bool + signatures: [PAGE1.IsAncestor PAGE2] +toc: true +--- + +{{% include "methods/page/_common/definition-of-section.md" %}} + +With this content structure: + +```text +content/ +├── auctions/ +│ ├── 2023-11/ +│ │ ├── _index.md +│ │ ├── auction-1.md +│ │ └── auction-2.md +│ ├── 2023-12/ +│ │ ├── _index.md +│ │ ├── auction-3.md +│ │ └── auction-4.md +│ ├── _index.md +│ ├── bidding.md +│ └── payment.md +└── _index.md +``` + +When rendering the "auctions" page: + +```go-html-template +{{ with .Site.GetPage "/" }} + {{ $.IsAncestor . }} → false +{{ end }} + +{{ with .Site.GetPage "/auctions" }} + {{ $.IsAncestor . }} → false +{{ end }} + +{{ with .Site.GetPage "/auctions/2023-11" }} + {{ $.IsAncestor . }} → true +{{ end }} + +{{ with .Site.GetPage "/auctions/2023-11/auction-2" }} + {{ $.IsAncestor . }} → true +{{ end }} +``` + +In the examples above we are coding defensively using the [`with`] statement, returning nothing if the page does not exist. By adding an [`else`] clause we can do some error reporting: + +```go-html-template +{{ $path := "/auctions/2023-11" }} +{{ with .Site.GetPage $path }} + {{ $.IsAncestor . }} → true +{{ else }} + {{ errorf "Unable to find the section with path %s" $path }} +{{ end }} + ``` + +## Understanding context + +Inside of the `with` block, the [context] (the dot) is the section `Page` object, not the `Page` object passed into the template. If we were to use this syntax: + +```go-html-template +{{ with .Site.GetPage "/auctions" }} + {{ .IsAncestor . }} → true +{{ end }} +``` + +The result would be wrong when rendering the "auction-1" page because we are comparing the section page to itself. + +{{% note %}} +Use the `$` to get the context passed into the template. +{{% /note %}} + +```go-html-template +{{ with .Site.GetPage "/auctions" }} + {{ $.IsAncestor . }} → true +{{ end }} +``` + +{{% note %}} +Gaining a thorough understanding of context is critical for anyone writing template code. +{{% /note %}} + +[context]: /getting-started/glossary/#context +[`with`]: /functions/go-template/with +[`else`]: /functions/go-template/else diff --git a/docs/content/en/methods/page/IsDescendant.md b/docs/content/en/methods/page/IsDescendant.md new file mode 100644 index 000000000..f1042564e --- /dev/null +++ b/docs/content/en/methods/page/IsDescendant.md @@ -0,0 +1,99 @@ +--- +title: IsDescendant +description: Reports whether PAGE1 in a descendant of PAGE2. +categories: [] +keywords: [] +action: + related: + - methods/page/Ancestors + - methods/page/CurrentSection + - methods/page/FirstSection + - methods/page/InSection + - methods/page/IsAncestor + - methods/page/Parent + - methods/page/Sections + returnType: bool + signatures: [PAGE1.IsDescendant PAGE2] +--- + +{{% include "methods/page/_common/definition-of-section.md" %}} + +With this content structure: + +```text +content/ +├── auctions/ +│ ├── 2023-11/ +│ │ ├── _index.md +│ │ ├── auction-1.md +│ │ └── auction-2.md +│ ├── 2023-12/ +│ │ ├── _index.md +│ │ ├── auction-3.md +│ │ └── auction-4.md +│ ├── _index.md +│ ├── bidding.md +│ └── payment.md +└── _index.md +``` + +When rendering the "auctions" page: + +```go-html-template +{{ with .Site.GetPage "/" }} + {{ $.IsDescendant . }} → true +{{ end }} + +{{ with .Site.GetPage "/auctions" }} + {{ $.IsDescendant . }} → false +{{ end }} + +{{ with .Site.GetPage "/auctions/2023-11" }} + {{ $.IsDescendant . }} → false +{{ end }} + +{{ with .Site.GetPage "/auctions/2023-11/auction-2" }} + {{ $.IsDescendant . }} → false +{{ end }} +``` + +In the examples above we are coding defensively using the [`with`] statement, returning nothing if the page does not exist. By adding an [`else`] clause we can do some error reporting: + +```go-html-template +{{ $path := "/auctions/2023-11" }} +{{ with .Site.GetPage $path }} + {{ $.IsDescendant . }} → true +{{ else }} + {{ errorf "Unable to find the section with path %s" $path }} +{{ end }} + ``` + +## Understanding context + +Inside of the `with` block, the [context] (the dot) is the section `Page` object, not the `Page` object passed into the template. If we were to use this syntax: + +```go-html-template +{{ with .Site.GetPage "/auctions" }} + {{ .IsDescendant . }} → true +{{ end }} +``` + +The result would be wrong when rendering the "auction-1" page because we are comparing the section page to itself. + +{{% note %}} +Use the `$` to get the context passed into the template. +{{% /note %}} + +```go-html-template +{{ with .Site.GetPage "/auctions" }} + {{ $.IsDescendant . }} → true +{{ end }} +``` + +{{% note %}} +Gaining a thorough understanding of context is critical for anyone writing template code. +{{% /note %}} + +[context]: /getting-started/glossary/#context +[`with`]: /functions/go-template/with +[`else`]: /functions/go-template/else diff --git a/docs/content/en/methods/page/IsHome.md b/docs/content/en/methods/page/IsHome.md new file mode 100644 index 000000000..b688f88c0 --- /dev/null +++ b/docs/content/en/methods/page/IsHome.md @@ -0,0 +1,31 @@ +--- +title: IsHome +description: Reports whether the given page is the home page. +categories: [] +keywords: [] +action: + related: + - methods/page/IsNode + - methods/page/IsPage + - methods/page/IsSection + returnType: bool + signatures: [PAGE.IsHome] +--- + +The `IsHome` method on a `Page` object returns `true` if the [page kind] is `home`. + +```text +content/ +├── books/ +│ ├── book-1/ +│ │ └── index.md <-- kind = page +│ ├── book-2.md <-- kind = page +│ └── _index.md <-- kind = section +└── _index.md <-- kind = home +``` + +```go-html-template +{{ .IsHome }} +``` + +[page kind]: /getting-started/glossary/#page-kind diff --git a/docs/content/en/methods/page/IsMenuCurrent.md b/docs/content/en/methods/page/IsMenuCurrent.md new file mode 100644 index 000000000..61283fd8b --- /dev/null +++ b/docs/content/en/methods/page/IsMenuCurrent.md @@ -0,0 +1,29 @@ +--- +title: IsMenuCurrent +description: Reports whether the given page object matches the page object associated with the given menu entry in the given menu. +categories: [] +keywords: [] +action: + related: + - methods/page/HasMenuCurrent + returnType: bool + signatures: [PAGE.IsMenuCurrent MENU MENUENTRY] +aliases: [/functions/ismenucurrent] +--- + +```go-html-template +{{ $currentPage := . }} +{{ range site.Menus.main }} + {{ if $currentPage.IsMenuCurrent .Menu . }} + <a class="active" aria-current="page" href="{{ .URL }}">{{ .Name }}</a> + {{ else if $currentPage.HasMenuCurrent .Menu . }} + <a class="ancestor" aria-current="true" href="{{ .URL }}">{{ .Name }}</a> + {{ else }} + <a href="{{ .URL }}">{{ .Name }}</a> + {{ end }} +{{ end }} +``` + +See [menu templates] for a complete example. + +[menu templates]: /templates/menu-templates/#example diff --git a/docs/content/en/methods/page/IsNode.md b/docs/content/en/methods/page/IsNode.md new file mode 100644 index 000000000..dfdf435c5 --- /dev/null +++ b/docs/content/en/methods/page/IsNode.md @@ -0,0 +1,36 @@ +--- +title: IsNode +description: Reports whether the given page is a node. +categories: [] +keywords: [] +action: + related: + - methods/page/IsHome + - methods/page/IsPage + - methods/page/IsSection + returnType: bool + signatures: [PAGE.IsNode] +--- + +The `IsNode` method on a `Page` object returns `true` if the [page kind] is `home`, `section`, `taxonomy`, or `term`. + +It returns `false` is the page kind is `page`. + +```text +content/ +├── books/ +│ ├── book-1/ +│ │ └── index.md <-- kind = page, node = false +│ ├── book-2.md <-- kind = page, node = false +│ └── _index.md <-- kind = section, node = true +├── tags/ +│ ├── fiction/ +│ │ └── _index.md <-- kind = term, node = true +│ └── _index.md <-- kind = taxonomy, node = true +└── _index.md <-- kind = home, node = true +``` + +```go-html-template +{{ .IsNode }} +``` +[page kind]: /getting-started/glossary/#page-kind diff --git a/docs/content/en/methods/page/IsPage.md b/docs/content/en/methods/page/IsPage.md new file mode 100644 index 000000000..672ee61f4 --- /dev/null +++ b/docs/content/en/methods/page/IsPage.md @@ -0,0 +1,31 @@ +--- +title: IsPage +description: Reports whether the given page is a regular page. +categories: [] +keywords: [] +action: + related: + - methods/page/IsHome + - methods/page/IsNode + - methods/page/IsSection + returnType: bool + signatures: [PAGE.IsPage] +--- + +The `IsPage` method on a `Page` object returns `true` if the [page kind] is `page`. + +```text +content/ +├── books/ +│ ├── book-1/ +│ │ └── index.md <-- kind = page +│ ├── book-2.md <-- kind = page +│ └── _index.md <-- kind = section +└── _index.md <-- kind = home +``` + +```go-html-template +{{ .IsPage }} +``` + +[page kind]: /getting-started/glossary/#page-kind diff --git a/docs/content/en/methods/page/IsSection.md b/docs/content/en/methods/page/IsSection.md new file mode 100644 index 000000000..b02e58a45 --- /dev/null +++ b/docs/content/en/methods/page/IsSection.md @@ -0,0 +1,31 @@ +--- +title: IsSection +description: Reports whether the given page is a section page. +categories: [] +keywords: [] +action: + related: + - methods/page/IsHome + - methods/page/IsNode + - methods/page/IsPage + returnType: bool + signatures: [PAGE.IsSection] +--- + +The `IsSection` method on a `Page` object returns `true` if the [page kind] is `section`. + +```text +content/ +├── books/ +│ ├── book-1/ +│ │ └── index.md <-- kind = page +│ ├── book-2.md <-- kind = page +│ └── _index.md <-- kind = section +└── _index.md <-- kind = home +``` + +```go-html-template +{{ .IsSection }} +``` + +[page kind]: /getting-started/glossary/#page-kind diff --git a/docs/content/en/methods/page/IsTranslated.md b/docs/content/en/methods/page/IsTranslated.md new file mode 100644 index 000000000..6a8f3f69e --- /dev/null +++ b/docs/content/en/methods/page/IsTranslated.md @@ -0,0 +1,59 @@ +--- +title: IsTranslated +description: Reports whether the given page has one or more translations. +categories: [] +keywords: [] +action: + related: + - methods/page/Translations + - methods/page/AllTranslations + - methods/page/TranslationKey + returnType: bool + signatures: [PAGE.IsTranslated] +--- + +With this site configuration: + +{{< code-toggle file=hugo >}} +defaultContentLanguage = 'en' + +[languages.en] +contentDir = 'content/en' +languageCode = 'en-US' +languageName = 'English' +weight = 1 + +[languages.de] +contentDir = 'content/de' +languageCode = 'de-DE' +languageName = 'Deutsch' +weight = 2 +{{< /code-toggle >}} + +And this content: + +```text +content/ +├── de/ +│ ├── books/ +│ │ └── book-1.md +│ └── _index.md +├── en/ +│ ├── books/ +│ │ ├── book-1.md +│ │ └── book-2.md +│ └── _index.md +└── _index.md +``` + +When rendering content/en/books/book-1.md: + +```go-html-template +{{ .IsTranslated }} → true +``` + +When rendering content/en/books/book-2.md: + +```go-html-template +{{ .IsTranslated }} → false +``` diff --git a/docs/content/en/methods/page/Keywords.md b/docs/content/en/methods/page/Keywords.md new file mode 100644 index 000000000..5ad37ce51 --- /dev/null +++ b/docs/content/en/methods/page/Keywords.md @@ -0,0 +1,46 @@ +--- +title: Keywords +description: Returns a slice of keywords as defined in front matter. +categories: [] +keywords: [] +action: + related: [] + returnType: '[]string' + signatures: [PAGE.Keywords] +--- + +By default, Hugo evaluates the keywords when creating collections of [related content]. + +[related content]: /content-management/related + +{{< code-toggle file=content/recipes/sushi.md fm=true >}} +title = 'How to make spicy tuna hand rolls' +keywords = ['tuna','sriracha','nori','rice'] +{{< /code-toggle >}} + +To list the keywords within a template: + +```go-html-template +{{ range .Keywords }} + {{ . }} +{{ end }} +``` + +Or use the [delimit] function: + +```go-html-template +{{ delimit .Keywords ", " ", and " }} → tuna, sriracha, nori, and rice +``` + +[delimit]: /functions/collections/delimit + +Keywords are also a useful [taxonomy]: + +{{< code-toggle file=hugo >}} +[taxonomies] +tag = 'tags' +keyword = 'keywords' +category = 'categories' +{{< /code-toggle >}} + +[taxonomy]: /content-management/taxonomies diff --git a/docs/content/en/methods/page/Kind.md b/docs/content/en/methods/page/Kind.md new file mode 100644 index 000000000..d901e9a7d --- /dev/null +++ b/docs/content/en/methods/page/Kind.md @@ -0,0 +1,35 @@ +--- +title: Kind +description: Returns the kind of the given page. +categories: [] +keywords: [] +action: + related: + - methods/page/Type + returnType: string + signatures: [PAGE.Kind] +--- + +The [page kind] is one of `home`, `page`, `section`, `taxonomy`, or `term`. + +```text +content/ +├── books/ +│ ├── book-1/ +│ │ └── index.md <-- kind = page +│ ├── book-2.md <-- kind = page +│ └── _index.md <-- kind = section +├── tags/ +│ ├── fiction/ +│ │ └── _index.md <-- kind = term +│ └── _index.md <-- kind = taxonomy +└── _index.md <-- kind = home +``` + +To get the value within a template: + +```go-html-template +{{ .Kind }} +``` + +[page kind]: /getting-started/glossary/#page-kind diff --git a/docs/content/en/methods/page/Language.md b/docs/content/en/methods/page/Language.md new file mode 100644 index 000000000..4e65107da --- /dev/null +++ b/docs/content/en/methods/page/Language.md @@ -0,0 +1,65 @@ +--- +title: Language +description: Returns the language object for the given page. +categories: [] +keywords: [] +action: + related: + - methods/site/Language + returnType: langs.Language + signatures: [PAGE.Language] +--- + +The `Language` method on a `Page` object returns the language object for the given page. The language object points to the language definition in the site configuration. + +You can also use the `Language` method on a `Site` object. See [details]. + +## Methods + +The examples below assume the following in your site configuration: + +{{< code-toggle file=hugo >}} +[languages.de] +languageCode = 'de-DE' +languageDirection = 'ltr' +languageName = 'Deutsch' +weight = 2 +{{< /code-toggle >}} + +Lang +: (`string`) The language tag as defined by [RFC 5646]. + +```go-html-template +{{ .Language.Lang }} → de +``` + +LanguageCode +: (`string`) The language code from the site configuration. + +```go-html-template +{{ .Language.LanguageCode }} → de-DE +``` + +LanguageDirection +: (`string`) The language direction from the site configuration, either `ltr` or `rtl`. + +```go-html-template +{{ .Language.LanguageDirection }} → ltr +``` + +LanguageName +: (`string`) The language name from the site configuration. + +```go-html-template +{{ .Language.LanguageName }} → Deutsch +``` + +Weight +: (`int`) The language weight from the site configuration which determines its order in the slice of languages returned by the `Languages` method on a `Site` object. + +```go-html-template +{{ .Language.Weight }} → 2 +``` + +[details]: /methods/site/language +[RFC 5646]: https://datatracker.ietf.org/doc/html/rfc5646 diff --git a/docs/content/en/methods/page/Lastmod.md b/docs/content/en/methods/page/Lastmod.md new file mode 100644 index 000000000..c1692233d --- /dev/null +++ b/docs/content/en/methods/page/Lastmod.md @@ -0,0 +1,40 @@ +--- +title: Lastmod +description: Returns the last modification date of the given page. +categories: [] +keywords: [] +action: + related: + - methods/page/Date + - methods/page/ExpiryDate + - methods/page/PublishDate + - methods/page/GitInfo + returnType: time.Time + signatures: [PAGE.Lastmod] +--- + +Set the last modification date in front matter: + +{{< code-toggle file=content/news/article-1.md fm=true >}} +title = 'Article 1' +lastmod = 2023-10-19T00:40:04-07:00 +{{< /code-toggle >}} + +The last modification date is a [time.Time] value. Format and localize the value with the [`time.Format`] function, or use it with any of the [time methods]. + +```go-html-template +{{ .Lastmod | time.Format ":date_medium" }} → Oct 19, 2023 +``` + +In the example above we explicitly set the last modification date in front matter. With Hugo's default configuration, the `Lastmod` method returns the front matter value. This behavior is configurable, allowing you to: + +- Set the last modification date to the Author Date of the last Git commit for that file. See [`GitInfo`] for details. +- Set fallback values if the last modification date is not defined in front matter. + +Learn more about [date configuration]. + +[`gitinfo`]: /methods/page/gitinfo +[`time.format`]: /functions/time/format +[date configuration]: /getting-started/configuration/#configure-dates +[time methods]: /methods/time +[time.time]: https://pkg.go.dev/time#time diff --git a/docs/content/en/methods/page/Layout.md b/docs/content/en/methods/page/Layout.md new file mode 100644 index 000000000..3d0cdc437 --- /dev/null +++ b/docs/content/en/methods/page/Layout.md @@ -0,0 +1,40 @@ +--- +title: Layout +description: Returns the layout for the given page as defined in front matter. +categories: [] +keywords: [] +action: + related: + - methods/page/Type + returnType: string + signatures: [PAGE.Layout] +--- + +Specify the `layout` field in front matter to target a particular template. See [details]. + +[details]: /templates/lookup-order/#target-a-template + +{{< code-toggle file=content/contact.md >}} +title = 'Contact' +layout = 'contact' +{{< /code-toggle >}} + +Hugo will render the page using contact.html. + +```text +layouts/ +└── _default/ + ├── baseof.html + ├── contact.html + ├── home.html + ├── list.html + └── single.html +``` + +Although rarely used within a template, you can access the value with: + +```go-html-template +{{ .Layout }} +``` + +The `Layout` method returns an empty string if the `layout` field in front matter is not defined. diff --git a/docs/content/en/methods/page/Len.md b/docs/content/en/methods/page/Len.md new file mode 100644 index 000000000..d4270bda3 --- /dev/null +++ b/docs/content/en/methods/page/Len.md @@ -0,0 +1,15 @@ +--- +title: Len +description: Returns the length, in bytes, of the rendered content of the given page. +categories: [] +keywords: [] +action: + related: + - methods/page/Content + returnType: int + signatures: [PAGE.Len] +--- + +```go-html-template +{{ .Len }} → 42 +``` diff --git a/docs/content/en/methods/page/LinkTitle.md b/docs/content/en/methods/page/LinkTitle.md new file mode 100644 index 000000000..746e433bb --- /dev/null +++ b/docs/content/en/methods/page/LinkTitle.md @@ -0,0 +1,30 @@ +--- +title: LinkTitle +description: Returns the link title of the given page. +categories: [] +keywords: [] +action: + related: + - methods/page/Title + returnType: string + signatures: [PAGE.LinkTitle] +--- + +The `LinkTitle` method returns the `linkTitle` field as defined in front matter, falling back to the value returned by the [`Title`] method. + +[`Title`]: /methods/page/title + +{{< code-toggle file=content/articles/healthy-desserts.md fm=true >}} +title = 'Seventeen delightful recipes for healthy desserts' +linkTitle = 'Dessert recipes' +{{< /code-toggle >}} + +```go-html-template +{{ .LinkTitle }} → Dessert recipes +``` + +As demonstrated above, defining a link title in front matter is advantageous when the page title is long. Use it when generating anchor elements in your templates: + +```go-html-template +<a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a> +``` diff --git a/docs/content/en/methods/page/Next.md b/docs/content/en/methods/page/Next.md new file mode 100644 index 000000000..57fc1f2f8 --- /dev/null +++ b/docs/content/en/methods/page/Next.md @@ -0,0 +1,53 @@ +--- +title: Next +description: Returns the next page in a global page collection, relative to the given page. +categories: [] +keywords: [] +action: + related: + - methods/page/Prev + - methods/page/NextInSection + - methods/page/PrevInSection + - methods/pages/Next + - methods/pages/Prev + returnType: page.Page + signatures: [PAGE.Next] +toc: true +--- + +The behavior of the `Prev` and `Next` methods on a `Page` object is probably the reverse of what you expect. + +With this content structure: + +```text +content/ +├── pages/ +│ ├── _index.md +│ ├── page-1.md <-- front matter: weight = 10 +│ ├── page-2.md <-- front matter: weight = 20 +│ └── page-3.md <-- front matter: weight = 30 +└── _index.md +``` + +When you visit page-2: + +- The `Prev` method points to page-3 +- The `Next` method points to page-1 + +{{% note %}} +Use the opposite label in your navigation links as shown in the example below. +{{% /note %}} + +```go-html-template +{{ with .Next }} + <a href="{{ .RelPermalink }}">Prev</a> +{{ end }} + +{{ with .Prev }} + <a href="{{ .RelPermalink }}">Next</a> +{{ end }} +``` + +## Compare to Pages methods + +{{% include "methods/_common/next-prev-on-page-vs-next-prev-on-pages.md" %}} diff --git a/docs/content/en/methods/page/NextInSection.md b/docs/content/en/methods/page/NextInSection.md new file mode 100644 index 000000000..73f82d754 --- /dev/null +++ b/docs/content/en/methods/page/NextInSection.md @@ -0,0 +1,71 @@ +--- +title: NextInSection +description: Returns the next page within a section, relative to the given page. +categories: [] +keywords: [] +action: + related: + - methods/page/PrevInSection + - methods/page/Next + - methods/page/Prev + - methods/pages/Next + - methods/pages/Prev + returnType: page.Page + signatures: [PAGE.NextInSection] +--- + +The behavior of the `PrevInSection` and `NextInSection` methods on a `Page` object is probably the reverse of what you expect. + +With this content structure: + +```text +content/ +├── books/ +│ ├── _index.md +│ ├── book-1.md +│ ├── book-2.md +│ └── book-3.md +├── films/ +│ ├── _index.md +│ ├── film-1.md +│ ├── film-2.md +│ └── film-3.md +└── _index.md +``` + +When you visit book-2: + +- The `PrevInSection` method points to book-3 +- The `NextInSection` method points to book-1 + +{{% note %}} +Use the opposite label in your navigation links as shown in the example below. +{{% /note %}} + +```go-html-template +{{ with .NextInSection }} + <a href="{{ .RelPermalink }}">Previous in section</a> +{{ end }} + +{{ with .PrevInSection }} + <a href="{{ .RelPermalink }}">Next in section</a> +{{ end }} +``` + +{{% note %}} +The navigation sort order may be different than the page collection sort order. +{{% /note %}} + +With the `PrevInSection` and `NextInSection` methods, the navigation sort order is fixed, using Hugo’s default sort order. In order of precedence: + +1. Page [weight] +2. Page [date] (descending) +3. Page [linkTitle], falling back to page [title] +4. Page file path if the page is backed by a file + +For example, with a page collection sorted by title, the navigation sort order will use Hugo’s default sort order. This is probably not what you want or expect. For this reason, the Next and Prev methods on a Pages object are generally a better choice. + +[date]: /methods/page/date +[weight]: /methods/page/weight +[linkTitle]: /methods/page/linktitle +[title]: /methods/page/title diff --git a/docs/content/en/methods/page/OutputFormats.md b/docs/content/en/methods/page/OutputFormats.md new file mode 100644 index 000000000..03343cf8c --- /dev/null +++ b/docs/content/en/methods/page/OutputFormats.md @@ -0,0 +1,40 @@ +--- +title: OutputFormats +description: Returns a slice of OutputFormat objects, each representing one of the output formats enabled for the given page. +categories: [] +keywords: [] +action: + related: + - methods/page/AlternativeOutputFormats + returnType: '[]OutputFormat' + signatures: [PAGE.OutputFormats] +toc: true +--- + +{{% include "methods/page/_common/output-format-definition.md" %}} + +The `OutputFormats` method on a `Page` object returns a slice of `OutputFormat` objects, each representing one of the output formats enabled for the given page. See [details](/templates/output-formats/). + +## Methods + +{{% include "methods/page/_common/output-format-methods.md" %}} + +## Example + +To link to the RSS feed for the current page: + +```go-html-template +{{ with .OutputFormats.Get "rss" -}} + <a href="{{ .RelPermalink }}">RSS Feed</a> +{{ end }} +``` + +On the site's home page, Hugo renders this to: + +```html +<a href="/index.xml">RSS Feed</a> +``` + +Please see the [link to output formats] section to understand the importance of the construct above. + +[link to output formats]: /templates/output-formats/#link-to-output-formats diff --git a/docs/content/en/methods/page/Page.md b/docs/content/en/methods/page/Page.md new file mode 100644 index 000000000..4d81c04ef --- /dev/null +++ b/docs/content/en/methods/page/Page.md @@ -0,0 +1,40 @@ +--- +title: Page +description: Returns the Page object of the given page. +categories: [] +keywords: [] +action: + related: [] + returnType: page.Page + signatures: [PAGE.Page] +--- + +This is a convenience method, useful within partial templates that are called from both [shortcodes] and page templates. + +{{< code file=layouts/shortcodes/foo.html >}} +{{ partial "my-partial.html" . }} +{{< /code >}} + +When the shortcode calls the partial, it passes the current [context] (the dot). The context includes identifiers such as `Page`, `Params`, `Inner`, and `Name`. + +{{< code file=layouts/_default/single.html >}} +{{ partial "my-partial.html" . }} +{{< /code >}} + +When the page template calls the partial, it also passes the current context (the dot). But in this case, the dot _is_ the `Page` object. + +{{< code file=layouts/partials/my-partial.html >}} +The page title is: {{ .Page.Title }} +{{< /code >}} + +To handle both scenarios, the partial template must be able to access the `Page` object with `Page.Page`. + +{{% note %}} +And yes, that means you can do `.Page.Page.Page.Page.Title` too. + +But don't. +{{% /note %}} + + +[context]: getting-started/glossary/#context +[shortcodes]: /getting-started/glossary/#shortcode diff --git a/docs/content/en/methods/page/Pages.md b/docs/content/en/methods/page/Pages.md new file mode 100644 index 000000000..2f329eeec --- /dev/null +++ b/docs/content/en/methods/page/Pages.md @@ -0,0 +1,90 @@ +--- +title: Pages +description: Returns a collection of regular pages within the current section, and section pages of immediate descendant sections. +categories: [] +keywords: [] +action: + related: + - methods/page/RegularPages + - methods/page/RegularPagesRecursive + returnType: page.Pages + signatures: [PAGE.Pages] +--- + +The `Pages` method on a `Page` object is available to these [page kinds]: `home`, `section`, `taxonomy`, and `term`. The templates for these page kinds receive a page [collection] in [context]. + +Range through the page collection in your template: + +```go-html-template +{{ range .Pages.ByTitle }} + <h2><a href="{{ .RelPermalink }}">{{ .Title }}</a></h2> +{{ end }} +``` + +Consider this content structure: + +```text +content/ +├── lessons/ +│ ├── lesson-1/ +│ │ ├── _index.md +│ │ ├── part-1.md +│ │ └── part-2.md +│ ├── lesson-2/ +│ │ ├── resources/ +│ │ │ ├── task-list.md +│ │ │ └── worksheet.md +│ │ ├── _index.md +│ │ ├── part-1.md +│ │ └── part-2.md +│ ├── _index.md +│ ├── grading-policy.md +│ └── lesson-plan.md +├── _index.md +├── contact.md +└── legal.md +``` + +When rendering the home page, the `Pages` method returns: + + contact.md + legal.md + lessons/_index.md + +When rendering the lessons page, the `Pages` method returns: + + lessons/grading-policy.md + lessons/lesson-plan.md + lessons/lesson-1/_index.md + lessons/lesson-2/_index.md + +When rendering lesson-1, the `Pages` method returns: + + lessons/lesson-1/part-1.md + lessons/lesson-1/part-2.md + +When rendering lesson-2, the `Pages` method returns: + + lessons/lesson-2/part-1.md + lessons/lesson-2/part-2.md + lessons/lesson-2/resources/task-list.md + lessons/lesson-2/resources/worksheet.md + +In the last example, the collection includes pages in the resources subdirectory. That directory is not a [section]---it does not contain an _index.md file. Its contents are part of the lesson-2 section. + +{{% note %}} +When used with a `Site` object, the `Pages` method recursively returns all pages within the site. See [details]. + +[details]: /methods/site/pages +{{% /note %}} + +```go-html-template +{{ range .Site.Pages.ByTitle }} + <h2><a href="{{ .RelPermalink }}">{{ .Title }}</a></h2> +{{ end }} +``` + +[collection]: /getting-started/glossary/#collection +[context]: /getting-started/glossary/#context +[page kinds]: /getting-started/glossary/#page-kind +[section]: /getting-started/glossary/#section diff --git a/docs/content/en/methods/page/Paginate.md b/docs/content/en/methods/page/Paginate.md new file mode 100644 index 000000000..6b43b99dd --- /dev/null +++ b/docs/content/en/methods/page/Paginate.md @@ -0,0 +1,50 @@ +--- +title: Paginate +description: Paginates a collection of pages. +categories: [] +keywords: [] +action: + related: + - methods/page/Paginator + returnType: page.Pager + signatures: ['PAGE.Paginate COLLECTION [N]'] +--- + +[Pagination] is the process of splitting a list page into two or more pagers, where each pager contains a subset of the page collection and navigation links to other pagers. + +By default, the number of elements on each pager is determined by the value of the `paginate` setting in your site configuration. The default value is `10`. Override the value in your site configuration by providing a second argument, an integer, when calling the `Paginate` method. + +{{% note %}} +There is also a `Paginator` method on `Page` objects, but it can neither filter nor sort the page collection. + +The `Paginate` method is more flexible. +{{% /note %}} + +You can invoke pagination on the home page template, [`section`] templates, [`taxonomy`] templates, and [`term`] templates. + +{{< code file=layouts/_default/list.html >}} +{{ $pages := where .Site.RegularPages "Section" "articles" }} +{{ $pages = $pages.ByTitle }} +{{ range (.Paginate $pages 7).Pages }} + <h2><a href="{{ .RelPermalink }}">{{ .Title }}</a></h2> +{{ end }} +{{ template "_internal/pagination.html" . }} +{{< /code >}} + +In the example above, we: + +1. Build a page collection +2. Sort the collection by title +3. Paginate the collection, with 7 elements per pager +4. Range over the paginated page collection, rendering a link to each page +5. Call the internal "pagination" template to create the navigation links between pagers. + +{{% note %}} +Please note that the results of pagination are cached. Once you have invoked either the `Paginator` or `Paginate` method, the paginated collection is immutable. Additional invocations of these methods will have no effect. +{{% /note %}} + +[context]: /getting-started/glossary/#context +[pagination]: /templates/pagination/ +[`section`]: /getting-started/glossary/#section +[`taxonomy`]: /getting-started/glossary/#taxonomy +[`term`]: /getting-started/glossary/#term diff --git a/docs/content/en/methods/page/Paginator.md b/docs/content/en/methods/page/Paginator.md new file mode 100644 index 000000000..b1540286a --- /dev/null +++ b/docs/content/en/methods/page/Paginator.md @@ -0,0 +1,42 @@ +--- +title: Paginator +description: Paginates the collection of regular pages received in context. +categories: [] +keywords: [] +action: + related: + - methods/page/Paginate + returnType: page.Pager + signatures: [PAGE.Paginator] +--- + +[Pagination] is the process of splitting a list page into two or more pagers, where each pager contains a subset of the page collection and navigation links to other pagers. The number of elements on each pager is determined by the value of the `paginate` setting in your site configuration. The default value is `10`. + +You can invoke pagination on the home page template, [`section`] templates, [`taxonomy`] templates, and [`term`] templates. Each of these receive a collection of regular pages in [context]. When you invoke the `Paginator` method, it paginates the page collection received in context. + +{{< code file=layouts/_default/list.html >}} +{{ range .Paginator.Pages }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +{{ template "_internal/pagination.html" . }} +{{< /code >}} + +In the example above, the internal "pagination" template creates the navigation links between pagers. + +{{% note %}} +Although simple to invoke, with the `Paginator` method you can neither filter nor sort the page collection. It acts upon the page collection received in context. + +The [`Paginate`] method is more flexible, and strongly recommended. + +[`paginate`]: /methods/page/paginate +{{% /note %}} + +{{% note %}} +Please note that the results of pagination are cached. Once you have invoked either the `Paginator` or `Paginate` method, the paginated collection is immutable. Additional invocations of these methods will have no effect. +{{% /note %}} + +[context]: /getting-started/glossary/#context +[pagination]: /templates/pagination/ +[`section`]: /getting-started/glossary/#section +[`taxonomy`]: /getting-started/glossary/#taxonomy +[`term`]: /getting-started/glossary/#term diff --git a/docs/content/en/methods/page/Param.md b/docs/content/en/methods/page/Param.md new file mode 100644 index 000000000..b2932d981 --- /dev/null +++ b/docs/content/en/methods/page/Param.md @@ -0,0 +1,47 @@ +--- +title: Param +description: Returns a page parameter with the given key, falling back to a site parameter if present. +categories: [] +keywords: [] +action: + related: [] + returnType: any + signatures: [PAGE.Param KEY] +aliases: [/functions/param] +--- + +The `Param` method on a `Page` object looks for the given `KEY` in page parameters, and returns the corresponding value. If it cannot find the `KEY` in page parameters, it looks for the `KEY` in site parameters. If it cannot find the `KEY` in either location, the `Param` method returns `nil`. + +Site and theme developers commonly set parameters at the site level, allowing content authors to override those parameters at the page level. + +For example, to show a table of contents on every page, but allow authors to hide the table of contents as needed: + +Configuration: + +{{< code-toggle file=hugo >}} +[params] +display_toc = true +{{< /code-toggle >}} + +Content: + +{{< code-toggle file=content/example.md fm=true >}} +title = 'Example' +date = 2023-01-01 +draft = false +display_toc = false +{{< /code-toggle >}} + +Template: + +```go-html-template +{{ if .Param "display_toc" }} + {{ .TableOfContents }} +{{ end }} +``` + +The `Param` method returns the value associated with the given `KEY`, regardless of whether the value is truthy or falsy. If you need to ignore falsy values, use this construct instead: + +```go-html-template +{{ or .Params.foo site.Params.foo }} +``` diff --git a/docs/content/en/methods/page/Params.md b/docs/content/en/methods/page/Params.md new file mode 100644 index 000000000..3d79d15c5 --- /dev/null +++ b/docs/content/en/methods/page/Params.md @@ -0,0 +1,43 @@ +--- +title: Params +description: Returns a map of custom parameters as defined in the front matter of the given page. +categories: [] +keywords: [] +action: + related: + - functions/collections/IndexFunction + - methods/site/Params + - methods/page/Param + returnType: maps.Params + signatures: [PAGE.Params] +--- + +With this front matter: + +{{< code-toggle file=content/news/annual-conference.md >}} +title = 'Annual conference' +date = 2023-10-17T15:11:37-07:00 +display_related = true +[params.author] + email = 'jsmith@example.org' + name = 'John Smith' +{{< /code-toggle >}} + +The `title` and `date` fields are standard parameters---the other fields are user-defined. + +Access the custom parameters by [chaining] the [identifiers]: + +```go-html-template +{{ .Params.display_related }} → true +{{ .Params.author.name }} → John Smith +``` + +In the template example above, each of the keys is a valid identifier. For example, none of the keys contains a hyphen. To access a key that is not a valid identifier, use the [`index`] function: + +```go-html-template +{{ index .Params "key-with-hyphens" }} → 2023 +``` + +[`index`]: /functions/collections/indexfunction +[chaining]: /getting-started/glossary/#chain +[identifiers]: /getting-started/glossary/#identifier diff --git a/docs/content/en/methods/page/Parent.md b/docs/content/en/methods/page/Parent.md new file mode 100644 index 000000000..9d9ed7ea3 --- /dev/null +++ b/docs/content/en/methods/page/Parent.md @@ -0,0 +1,60 @@ +--- +title: Parent +description: Returns the Page object of the parent section of the given page. +categories: [] +keywords: [] +action: + related: + - methods/page/Ancestors + - methods/page/CurrentSection + - methods/page/FirstSection + - methods/page/InSection + - methods/page/IsAncestor + - methods/page/IsDescendant + - methods/page/Sections + returnType: page.Page + signatures: [PAGE.Parent] +--- + +{{% include "methods/page/_common/definition-of-section.md" %}} + +{{% note %}} +The parent section of a regular page is the [current section]. + +[current section]: /methods/page/currentsection +{{% /note %}} + +Consider this content structure: + +```text +content/ +├── auctions/ +│ ├── 2023-11/ +│ │ ├── _index.md <-- parent: auctions +│ │ ├── auction-1.md +│ │ └── auction-2.md <-- parent: 2023-11 +│ ├── 2023-12/ +│ │ ├── _index.md +│ │ ├── auction-3.md +│ │ └── auction-4.md +│ ├── _index.md <-- parent: home +│ ├── bidding.md +│ └── payment.md <-- parent: auctions +├── books/ +│ ├── _index.md <-- parent: home +│ ├── book-1.md +│ └── book-2.md <-- parent: books +├── films/ +│ ├── _index.md <-- parent: home +│ ├── film-1.md +│ └── film-2.md <-- parent: films +└── _index.md <-- parent: nil +``` + +In the example above, note the parent section of the home page is nil. Code defensively by verifying existence of the parent section before calling methods on its `Page` object. To create a link to the parent section page of the current page: + +```go-html-template +{{ with .Parent }} + <a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a> +{{ end }} +``` diff --git a/docs/content/en/methods/page/Permalink.md b/docs/content/en/methods/page/Permalink.md new file mode 100644 index 000000000..d8416df86 --- /dev/null +++ b/docs/content/en/methods/page/Permalink.md @@ -0,0 +1,25 @@ +--- +title: Permalink +description: Returns the permalink of the given page. +categories: [] +keywords: [] +action: + related: + - methods/page/RelPermalink + returnType: string + signatures: [PAGE.Permalink] +--- + +Site configuration: + +{{< code-toggle file=hugo >}} +title = 'Documentation' +baseURL = 'https://example.org/docs/' +{{< /code-toggle >}} + +Template: + +```go-html-template +{{ $page := .Site.GetPage "/about" }} +{{ $page.Permalink }} → https://example.org/docs/about/ +``` diff --git a/docs/content/en/methods/page/Plain.md b/docs/content/en/methods/page/Plain.md new file mode 100644 index 000000000..6fdf60b62 --- /dev/null +++ b/docs/content/en/methods/page/Plain.md @@ -0,0 +1,28 @@ +--- +title: Plain +description: Returns the rendered content of the given page, removing all HTML tags. +categories: [] +keywords: [] +action: + related: + - methods/page/Content + - methods/page/RawContent + - methods/page/PlainWords + - methods/page/RenderShortcodes + returnType: string + signatures: [PAGE.Plain] +--- + +The `Plain` method on a `Page` object renders markdown and [shortcodes] to HTML, then strips the HTML [tags]. It does not strip HTML [entities]. The plain content does not include front matter. + +To prevent Go's [html/template] package from escaping HTML entities, pass the result through the [`htmlUnescape`] function. + +```go-html-template +{{ .Plain | htmlUnescape }} +``` + +[shortcodes]: /getting-started/glossary/#shortcode +[html/template]: https://pkg.go.dev/html/template +[entities]: https://developer.mozilla.org/en-US/docs/Glossary/Entity +[tags]: https://developer.mozilla.org/en-US/docs/Glossary/Tag +[`htmlUnescape`]: /functions/ diff --git a/docs/content/en/methods/page/PlainWords.md b/docs/content/en/methods/page/PlainWords.md new file mode 100644 index 000000000..4bc79d241 --- /dev/null +++ b/docs/content/en/methods/page/PlainWords.md @@ -0,0 +1,36 @@ +--- +title: PlainWords +description: Calls the Plain method, splits the result into a slice of words, and returns the slice. +categories: [] +keywords: [] +action: + related: + - methods/page/Content + - methods/page/RawContent + - methods/page/Plain + returnType: '[]string' + signatures: [PAGE.PlainWords] +--- + +The `PlainWords` method on a `Page` object calls the [`Plain`] method, then uses Go's [`strings.Fields`] function to split the result into words. + +{{% note %}} +_Fields splits the string s around each instance of one or more consecutive white space characters, as defined by [`unicode.IsSpace`], returning a slice of substrings of s or an empty slice if s contains only white space._ + +[`unicode.IsSpace`]: https://pkg.go.dev/unicode#IsSpace +{{% /note %}} + +As a result, elements within the slice may contain leading or trailing punctuation. + +```go-html-template +{{ .PlainWords }} +``` + +To determine the approximate number of unique words on a page: + +```go-html-template +{{ .PlainWords | uniq }} → 42 +``` + +[`Plain`]: /methods/page/plain +[`strings.Fields`]: https://pkg.go.dev/strings#Fields diff --git a/docs/content/en/methods/page/Prev.md b/docs/content/en/methods/page/Prev.md new file mode 100644 index 000000000..b1a503af5 --- /dev/null +++ b/docs/content/en/methods/page/Prev.md @@ -0,0 +1,53 @@ +--- +title: Prev +description: Returns the previous page in a global page collection, relative to the given page. +categories: [] +keywords: [] +action: + related: + - methods/page/Next + - methods/page/PrevInSection + - methods/page/NextInSection + - methods/pages/Prev + - methods/pages/Next + returnType: page.Page + signatures: [PAGE.Prev] +toc: true +--- + +The behavior of the `Prev` and `Next` methods on a `Page` object is probably the reverse of what you expect. + +With this content structure: + +```text +content/ +├── pages/ +│ ├── _index.md +│ ├── page-1.md <-- front matter: weight = 10 +│ ├── page-2.md <-- front matter: weight = 20 +│ └── page-3.md <-- front matter: weight = 30 +└── _index.md +``` + +When you visit page-2: + +- The `Prev` method points to page-3 +- The `Next` method points to page-1 + +{{% note %}} +Use the opposite label in your navigation links as shown in the example below. +{{% /note %}} + +```go-html-template +{{ with .Next }} + <a href="{{ .RelPermalink }}">Prev</a> +{{ end }} + +{{ with .Prev }} + <a href="{{ .RelPermalink }}">Next</a> +{{ end }} +``` + +## Compare to Pages methods + +{{% include "methods/_common/next-prev-on-page-vs-next-prev-on-pages.md" %}} diff --git a/docs/content/en/methods/page/PrevInSection.md b/docs/content/en/methods/page/PrevInSection.md new file mode 100644 index 000000000..c09e4580f --- /dev/null +++ b/docs/content/en/methods/page/PrevInSection.md @@ -0,0 +1,72 @@ +--- +title: PrevInSection +description: Returns the previous page within a section, relative to the given page. +categories: [] +keywords: [] +action: + related: + - methods/page/NextInSection + - methods/page/Next + - methods/pages/Next + - methods/page/Prev + - methods/pages/Prev + returnType: page.Page + signatures: [PAGE.PrevInSection] +--- + + +The behavior of the `PrevInSection` and `NextInSection` methods on a `Page` object is probably the reverse of what you expect. + +With this content structure: + +```text +content/ +├── books/ +│ ├── _index.md +│ ├── book-1.md +│ ├── book-2.md +│ └── book-3.md +├── films/ +│ ├── _index.md +│ ├── film-1.md +│ ├── film-2.md +│ └── film-3.md +└── _index.md +``` + +When you visit book-2: + +- The `PrevInSection` method points to book-3 +- The `NextInSection` method points to book-1 + +{{% note %}} +Use the opposite label in your navigation links as shown in the example below. +{{% /note %}} + +```go-html-template +{{ with .NextInSection }} + <a href="{{ .RelPermalink }}">Previous in section</a> +{{ end }} + +{{ with .PrevInSection }} + <a href="{{ .RelPermalink }}">Next in section</a> +{{ end }} +``` + +{{% note %}} +The navigation sort order may be different than the page collection sort order. +{{% /note %}} + +With the `PrevInSection` and `NextInSection` methods, the navigation sort order is fixed, using Hugo’s default sort order. In order of precedence: + +1. Page [weight] +2. Page [date] (descending) +3. Page [linkTitle], falling back to page [title] +4. Page file path if the page is backed by a file + +For example, with a page collection sorted by title, the navigation sort order will use Hugo’s default sort order. This is probably not what you want or expect. For this reason, the Next and Prev methods on a Pages object are generally a better choice. + +[date]: /methods/page/date +[weight]: /methods/page/weight +[linkTitle]: /methods/page/linktitle +[title]: /methods/page/title diff --git a/docs/content/en/methods/page/PublishDate.md b/docs/content/en/methods/page/PublishDate.md new file mode 100644 index 000000000..b1c0717a9 --- /dev/null +++ b/docs/content/en/methods/page/PublishDate.md @@ -0,0 +1,35 @@ +--- +title: PublishDate +description: Returns the publish date of the given page. +categories: [] +keywords: [] +action: + related: + - methods/page/Date + - methods/page/ExpiryDate + - methods/page/LastMod + returnType: time.Time + signatures: [PAGE.PublishDate] +--- + +By default, Hugo excludes pages with future publish dates when building your site. To include future pages, use the `--buildFuture` command line flag. + +Set the publish date in front matter: + +{{< code-toggle file=content/news/article-1.md fm=true >}} +title = 'Article 1' +publishDate = 2023-10-19T00:40:04-07:00 +{{< /code-toggle >}} + +The publish date is a [time.Time] value. Format and localize the value with the [`time.Format`] function, or use it with any of the [time methods]. + +```go-html-template +{{ .PublishDate | time.Format ":date_medium" }} → Oct 19, 2023 +``` + +In the example above we explicitly set the publish date in front matter. With Hugo's default configuration, the `PublishDate` method returns the front matter value. This behavior is configurable, allowing you to set fallback values if the publish date is not defined in front matter. See [details]. + +[`time.Format`]: /functions/time/format +[details]: /getting-started/configuration/#configure-dates +[time methods]: /methods/time +[time.Time]: https://pkg.go.dev/time#Time diff --git a/docs/content/en/methods/page/RawContent.md b/docs/content/en/methods/page/RawContent.md new file mode 100644 index 000000000..258a294d0 --- /dev/null +++ b/docs/content/en/methods/page/RawContent.md @@ -0,0 +1,31 @@ +--- +title: RawContent +description: Returns the raw content of the given page. +categories: [] +keywords: [] +action: + related: + - methods/page/Content + - methods/page/Plain + - methods/page/PlainWords + - methods/page/RenderShortcodes + returnType: string + signatures: [PAGE.RawContent] +--- + +The `RawContent` method on a `Page` object returns the raw content. The raw content does not include front matter. + +```go-html-template +{{ .RawContent }} +``` + +This is useful when rendering a page in a plain text [output format]. + +{{% note %}} +[Shortcodes] within the content are not rendered. To get the raw content with shortcodes rendered, use the [`RenderShortcodes`] method on a `Page` object. + +[shortcodes]: /getting-started/glossary/#shortcode +[`RenderShortcodes`]: /methods/page/rendershortcodes +{{% /note %}} + +[output format]: /templates/output-formats diff --git a/docs/content/en/methods/page/ReadingTime.md b/docs/content/en/methods/page/ReadingTime.md new file mode 100644 index 000000000..531824b9b --- /dev/null +++ b/docs/content/en/methods/page/ReadingTime.md @@ -0,0 +1,49 @@ +--- +title: ReadingTime +description: Returns the estimated reading time, in minutes, for the given page. +categories: [] +keywords: [] +action: + related: + - methods/page/WordCount + - methods/page/FuzzyWordCount + returnType: int + signatures: [PAGE.ReadingTime] +--- + +The estimated reading time is calculated by dividing the number of words in the content by the reading speed. + +By default, Hugo assumes a reading speed of 212 words per minute. For CJK languages, it assumes 500 words per minute. + +```go-html-template +{{ printf "Estimated reading time: %d minutes" .ReadingTime }} +``` + +Reading speed varies by language. Create language-specific estimated reading times on your multilingual site using site parameters. + +{{< code-toggle file=hugo >}} +[languages] + [languages.de] + contentDir = 'content/de' + languageCode = 'de-DE' + languageName = 'Deutsch' + weight = 2 + [languages.de.params] + reading_speed = 179 + [languages.en] + contentDir = 'content/en' + languageCode = 'en-US' + languageName = 'English' + weight = 1 + [languages.en.params] + reading_speed = 228 +{{< /code-toggle >}} + +Then in your template: + +```go-html-template +{{ $readingTime := div (float .WordCount) .Site.Params.reading_speed }} +{{ $readingTime = math.Ceil $readingTime }} +``` + +We cast the `.WordCount` to a float to obtain a float when we divide by the reading speed. Then round up to the nearest integer. diff --git a/docs/content/en/methods/page/Ref.md b/docs/content/en/methods/page/Ref.md new file mode 100644 index 000000000..e3c5569a4 --- /dev/null +++ b/docs/content/en/methods/page/Ref.md @@ -0,0 +1,44 @@ +--- +title: Ref +description: Returns the absolute URL of the page with the given path, language, and output format. +categories: [] +keywords: [] +action: + related: + - methods/page/RelRef + - functions/urls/RelRef + - functions/urls/Ref + returnType: string + signatures: [PAGE.Ref OPTIONS] +--- + +The map of option contains: + +path +: (`string`) The path to the page, relative to the content directory. Required. + +lang +: (`string`) The language (site) to search for the page. Default is the current language. Optional. + +outputFormat +: (`string`) The output format to search for the page. Default is the current output format. Optional. + +The examples below show the rendered output when visiting a page on the English language version of the site: + +```go-html-template +{{ $opts := dict "path" "/books/book-1" }} +{{ .Ref $opts }} → https://example.org/en/books/book-1/ + +{{ $opts := dict "path" "/books/book-1" "lang" "de" }} +{{ .Ref $opts }} → https://example.org/de/books/book-1/ + +{{ $opts := dict "path" "/books/book-1" "lang" "de" "outputFormat" "json" }} +{{ .Ref $opts }} → https://example.org/de/books/book-1/index.json +``` + +By default, Hugo will throw an error and fail the build if it cannot resolve the path. You can change this to a warning in your site configuration, and specify a URL to return when the path cannot be resolved. + +{{< code-toggle file=hugo >}} +refLinksErrorLevel = 'warning' +refLinksNotFoundURL = '/some/other/url' +{{< /code-toggle >}} diff --git a/docs/content/en/methods/page/RegularPages.md b/docs/content/en/methods/page/RegularPages.md new file mode 100644 index 000000000..b0ca7b1e1 --- /dev/null +++ b/docs/content/en/methods/page/RegularPages.md @@ -0,0 +1,87 @@ +--- +title: RegularPages +description: Returns a collection of regular pages within the current section. +categories: [] +keywords: [] +action: + related: + - methods/page/Pages + - methods/page/RegularPagesRecursive + returnType: page.Pages + signatures: [PAGE.RegularPages] +--- + +The `RegularPages` method on a `Page` object is available to these [page kinds]: `home`, `section`, `taxonomy`, and `term`. The templates for these page kinds receive a page [collection] in [context]. + +Range through the page collection in your template: + +```go-html-template +{{ range .RegularPages.ByTitle }} + <h2><a href="{{ .RelPermalink }}">{{ .Title }}</a></h2> +{{ end }} +``` + +Consider this content structure: + +```text +content/ +├── lessons/ +│ ├── lesson-1/ +│ │ ├── _index.md +│ │ ├── part-1.md +│ │ └── part-2.md +│ ├── lesson-2/ +│ │ ├── resources/ +│ │ │ ├── task-list.md +│ │ │ └── worksheet.md +│ │ ├── _index.md +│ │ ├── part-1.md +│ │ └── part-2.md +│ ├── _index.md +│ ├── grading-policy.md +│ └── lesson-plan.md +├── _index.md +├── contact.md +└── legal.md +``` + +When rendering the home page, the `RegularPages` method returns: + + contact.md + legal.md + +When rendering the lessons page, the `RegularPages` method returns: + + lessons/grading-policy.md + lessons/lesson-plan.md + +When rendering lesson-1, the `RegularPages` method returns: + + lessons/lesson-1/part-1.md + lessons/lesson-1/part-2.md + +When rendering lesson-2, the `RegularPages` method returns: + + lessons/lesson-2/part-1.md + lessons/lesson-2/part-2.md + lessons/lesson-2/resources/task-list.md + lessons/lesson-2/resources/worksheet.md + +In the last example, the collection includes pages in the resources subdirectory. That directory is not a [section]---it does not contain an _index.md file. Its contents are part of the lesson-2 section. + +{{% note %}} +When used with the `Site` object, the `RegularPages` method recursively returns all regular pages within the site. See [details]. + +[details]: /methods/site/regularpages +{{% /note %}} + +```go-html-template +{{ range .Site.RegularPages.ByTitle }} + <h2><a href="{{ .RelPermalink }}">{{ .Title }}</a></h2> +{{ end }} +``` + +[collection]: /getting-started/glossary/#collection +[context]: /getting-started/glossary/#context +[page kinds]: /getting-started/glossary/#page-kind +[section]: /getting-started/glossary/#section diff --git a/docs/content/en/methods/page/RegularPagesRecursive.md b/docs/content/en/methods/page/RegularPagesRecursive.md new file mode 100644 index 000000000..3dac8c85e --- /dev/null +++ b/docs/content/en/methods/page/RegularPagesRecursive.md @@ -0,0 +1,90 @@ +--- +title: RegularPagesRecursive +description: Returns a collection of regular pages within the current section, and regular pages within all descendant sections. +categories: [] +keywords: [] +action: + related: + - methods/page/Pages + - methods/page/RegularPages + returnType: page.Pages + signatures: [PAGE.RegularPagesRecursive] +--- + +The `RegularPagesRecursive` method on a `Page` object is available to these [page kinds]: `home`, `section`, `taxonomy`, and `term`. The templates for these page kinds receive a page [collection] in [context]. + +Range through the page collection in your template: + +```go-html-template +{{ range .RegularPagesRecursive.ByTitle }} + <h2><a href="{{ .RelPermalink }}">{{ .Title }}</a></h2> +{{ end }} +``` + +Consider this content structure: + +```text +content/ +├── lessons/ +│ ├── lesson-1/ +│ │ ├── _index.md +│ │ ├── part-1.md +│ │ └── part-2.md +│ ├── lesson-2/ +│ │ ├── resources/ +│ │ │ ├── task-list.md +│ │ │ └── worksheet.md +│ │ ├── _index.md +│ │ ├── part-1.md +│ │ └── part-2.md +│ ├── _index.md +│ ├── grading-policy.md +│ └── lesson-plan.md +├── _index.md +├── contact.md +└── legal.md +``` + +When rendering the home page, the `RegularPagesRecursive` method returns: + + contact.md + lessons/grading-policy.md + legal.md + lessons/lesson-plan.md + lessons/lesson-2/part-1.md + lessons/lesson-1/part-1.md + lessons/lesson-2/part-2.md + lessons/lesson-1/part-2.md + lessons/lesson-2/resources/task-list.md + lessons/lesson-2/resources/worksheet.md + +When rendering the lessons page, the `RegularPagesRecursive` method returns: + + lessons/grading-policy.md + lessons/lesson-plan.md + lessons/lesson-2/part-1.md + lessons/lesson-1/part-1.md + lessons/lesson-2/part-2.md + lessons/lesson-1/part-2.md + lessons/lesson-2/resources/task-list.md + lessons/lesson-2/resources/worksheet.md + +When rendering lesson-1, the `RegularPagesRecursive` method returns: + + lessons/lesson-1/part-1.md + lessons/lesson-1/part-2.md + +When rendering lesson-2, the `RegularPagesRecursive` method returns: + + lessons/lesson-2/part-1.md + lessons/lesson-2/part-2.md + lessons/lesson-2/resources/task-list.md + lessons/lesson-2/resources/worksheet.md + +{{% note %}} +The `RegularPagesRecursive` method in not available on a `Site` object. +{{% /note %}} + +[collection]: /getting-started/glossary/#collection +[context]: /getting-started/glossary/#context +[page kinds]: /getting-started/glossary/#page-kind diff --git a/docs/content/en/methods/page/RelPermalink.md b/docs/content/en/methods/page/RelPermalink.md new file mode 100644 index 000000000..817e3c862 --- /dev/null +++ b/docs/content/en/methods/page/RelPermalink.md @@ -0,0 +1,25 @@ +--- +title: RelPermalink +description: Returns the relative permalink of the given page. +categories: [] +keywords: [] +action: + related: + - methods/page/Permalink + returnType: string + signatures: [PAGE.RelPermalink] +--- + +Site configuration: + +{{< code-toggle file=hugo >}} +title = 'Documentation' +baseURL = 'https://example.org/docs/' +{{< /code-toggle >}} + +Template: + +```go-html-template +{{ $page := .Site.GetPage "/about" }} +{{ $page.RelPermalink }} → /docs/about/ +``` diff --git a/docs/content/en/methods/page/RelRef.md b/docs/content/en/methods/page/RelRef.md new file mode 100644 index 000000000..4c635e0e2 --- /dev/null +++ b/docs/content/en/methods/page/RelRef.md @@ -0,0 +1,44 @@ +--- +title: RelRef +description: Returns the relative URL of the page with the given path, language, and output format. +categories: [] +keywords: [] +action: + related: + - methods/page/Ref + - functions/urls/Ref + - functions/urls/RelRef + returnType: string + signatures: [PAGE.RelRef OPTIONS] +--- + +The map of option contains: + +path +: (`string`) The path to the page, relative to the content directory. Required. + +lang +: (`string`) The language (site) to search for the page. Default is the current language. Optional. + +outputFormat +: (`string`) The output format to search for the page. Default is the current output format. Optional. + +The examples below show the rendered output when visiting a page on the English language version of the site: + +```go-html-template +{{ $opts := dict "path" "/books/book-1" }} +{{ .RelRef $opts }} → /en/books/book-1/ + +{{ $opts := dict "path" "/books/book-1" "lang" "de" }} +{{ .RelRef $opts }} → /de/books/book-1/ + +{{ $opts := dict "path" "/books/book-1" "lang" "de" "outputFormat" "json" }} +{{ .RelRef $opts }} → /de/books/book-1/index.json +``` + +By default, Hugo will throw an error and fail the build if it cannot resolve the path. You can change this to a warning in your site configuration, and specify a URL to return when the path cannot be resolved. + +{{< code-toggle file=hugo >}} +refLinksErrorLevel = 'warning' +refLinksNotFoundURL = '/some/other/url' +{{< /code-toggle >}} diff --git a/docs/content/en/methods/page/Render.md b/docs/content/en/methods/page/Render.md new file mode 100644 index 000000000..bc3f58352 --- /dev/null +++ b/docs/content/en/methods/page/Render.md @@ -0,0 +1,75 @@ +--- +title: Render +description: Renders the given template with the given page as context. +categories: [] +keywords: [] +action: + related: + - functions/partials/Include + - functions/partials/IncludeCached + returnType: template.HTML + signatures: [PAGE.Render NAME] +aliases: [/functions/render] +--- + +Typically used when ranging over a page collection, the `Render` method on a `Page` object renders the given template, passing the given page as context. + +```go-html-template +{{ range site.RegularPages }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> + {{ .Render "summary" }} +{{ end }} +``` + +In the example above, note that the template ("summary") is identified by its file name without directory or extension. + +Although similar to the [`partial`] function, there are key differences. + +`Render` method|`partial` function| +:--|:-- +The `Page` object is automatically passed to the given template. You cannot pass additional context.| You must specify the context, allowing you to pass a combination of objects, slices, maps, and scalars. +The path to the template is determined by the [content type].|You must specify the path to the template, relative to the layouts/partials directory. + +Consider this layout structure: + +```text +layouts/ +├── _default/ +│ ├── baseof.html +│ ├── home.html +│ ├── li.html <-- used for other content types +│ ├── list.html +│ ├── single.html +│ └── summary.html +└── books/ + ├── li.html <-- used when content type is "books" + └── summary.html +``` + +And this template: + +```go-html-template +<ul> + {{ range site.RegularPages.ByDate }} + {{ .Render "li" }} + {{ end }} +</ul> +``` + +When rendering content of type "books" the `Render` method calls: + +```text +layouts/books/li.html +``` + +For all other content types the `Render` methods calls: + +```text +layouts/_default/li.html +``` + +See [content views] for more examples. + +[content views]: /templates/views +[`partial`]: /functions/partials/include +[content type]: /getting-started/glossary/#content-type diff --git a/docs/content/en/methods/page/RenderShortcodes.md b/docs/content/en/methods/page/RenderShortcodes.md new file mode 100644 index 000000000..4636bf8f5 --- /dev/null +++ b/docs/content/en/methods/page/RenderShortcodes.md @@ -0,0 +1,78 @@ +--- +title: RenderShortcodes +description: Renders all shortcodes in the content of the given page, preserving the surrounding markup. +categories: [] +keywords: [] +action: + related: + - methods/page/RenderString + - methods/page/Content + - methods/page/RawContent + - methods/page/Plain + - methods/page/PlainWords + returnType: template.HTML + signatures: [PAGE.RenderShortcodes] +toc: true +--- + +{{< new-in 0.117.0 >}} + +Use this method in shortcode templates to compose a page from multiple content files, while preserving a global context for footnotes and the table of contents. + +For example: + +{{< code file=layouts/shortcodes/include.html >}} +{{ $p := site.GetPage (.Get 0) }} +{{ $p.RenderShortcodes }} +{{< /code >}} + +Then in your markdown: + +{{< code file=content/about.md lang=md >}} +{{%/* include "/snippets/services.md" */%}} +{{%/* include "/snippets/values.md" */%}} +{{%/* include "/snippets/leadership.md" */%}} +{{< /code >}} + +Each of the included markdown files can contain calls to other shortcodes. + +## Shortcode notation + +In the example above it's important to understand the difference between the two delimiters used when calling a shortcode: + +- `{{</* myshortcode */>}}` tells Hugo that the rendered shortcode does not need further processing. For example, the shortcode content is HTML. +- `{{%/* myshortcode */%}}` tells Hugo that the rendered shortcode needs further processing. For example, the shortcode content is markdown. + +Use the latter for the "include" shortcode described above. + +## Further explanation + +To understand what is returned by the `RenderShortcodes` method, consider this content file + +{{< code file=content/about.md lang=text >}} ++++ +title = 'About' +date = 2023-10-07T12:28:33-07:00 ++++ + +{{</* ref "privacy" */>}} + +An *emphasized* word. +{{< /code >}} + +With this template code: + +```go-html-template +{{ $p := site.GetPage "/about" }} +{{ $p.RenderShortcodes }} +``` + +Hugo renders this:; + +```html +https://example.org/privacy/ + +An *emphasized* word. +``` + +Note that the shortcode within the content file was rendered, but the surrounding markdown was preserved. diff --git a/docs/content/en/methods/page/RenderString.md b/docs/content/en/methods/page/RenderString.md new file mode 100644 index 000000000..5782cd2b1 --- /dev/null +++ b/docs/content/en/methods/page/RenderString.md @@ -0,0 +1,51 @@ +--- +title: RenderString +description: Renders markup to HTML. +categories: [] +keywords: [] +action: + related: + - methods/page/RenderShortcodes + - functions/transform/Markdownify + returnType: template.HTML + signatures: ['PAGE.RenderString [OPTIONS] MARKUP'] +aliases: [/functions/renderstring] +--- + +```go-html-template +{{ $s := "An *emphasized* word" }} +{{ $s | .RenderString }} → An <em>emphasized</em> word +``` + +This method takes an optional map of options: + +display +: (`string`) Specify either `inline` or `block`. If `inline`, removes surrounding `p` tags from short snippets. Default is `inline`. + +markup +: (`string`) Specify a [markup identifier] for the provided markup. Default is the `markup` front matter value, falling back to the value derived from the page's file extension. + +Render with the default markup renderer: + +```go-html-template +{{ $s := "An *emphasized* word" }} +{{ $s | .RenderString }} → An <em>emphasized</em> word + +{{ $opts := dict "display" "block" }} +{{ $s | .RenderString $opts }} → <p>An <em>emphasized</em> word</p> +``` + +Render with [Pandoc]: + +```go-html-template +{{ $s := "H~2~O" }} + +{{ $opts := dict "markup" "pandoc" }} +{{ $s | .RenderString $opts }} → H<sub>2</sub>O + +{{ $opts := dict "display" "block" "markup" "pandoc" }} +{{ .RenderString $opts $s }} → <p>H<sub>2</sub>O</p> +``` + +[markup identifier]: /content-management/formats/#list-of-content-formats +[pandoc]: https://www.pandoc.org/ diff --git a/docs/content/en/methods/page/Resources.md b/docs/content/en/methods/page/Resources.md new file mode 100644 index 000000000..140b50020 --- /dev/null +++ b/docs/content/en/methods/page/Resources.md @@ -0,0 +1,85 @@ +--- +title: Resources +description: Returns a collection of page resources. +categories: [] +keywords: [] +action: + related: + - functions/resources/ByType + - functions/resources/Get + - functions/resources/GetMatch + - functions/resources/GetRemote + - functions/resources/Match + returnType: resource.Resources + signatures: [PAGE.Resources] +toc: true +--- + +The `Resources` method on a `Page` object returns a collection of page resources. A page resource is a file within a [page bundle]. + +To work with global or remote resources, see the [`resources`] functions. + +## Methods + +###### ByType + +(`resource.Resources`) Returns a collection of page resources of the given [media type], or nil if none found. The media type is typically one of `image`, `text`, `audio`, `video`, or `application`. + +```go-html-template +{{ range .Resources.ByType "image" }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> +{{ end }} +``` + +When working with global resources instead of page resources, use the [`resources.ByType`] function. + +###### Get + +(`resource.Resource`) Returns a page resource from the given path, or nil if none found. + +```go-html-template +{{ with .Resources.Get "images/a.jpg" }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> +{{ end }} +``` + +When working with global resources instead of page resources, use the [`resources.Get`] function. + +###### GetMatch + +(`resource.Resource`) Returns the first page resource from paths matching the given [glob pattern], or nil if none found. + +```go-html-template +{{ with .Resources.GetMatch "images/*.jpg" }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> +{{ end }} +``` + +When working with global resources instead of page resources, use the [`resources.GetMatch`] function. + +###### Match + +(`resource.Resources`) Returns a collection of page resources from paths matching the given [glob pattern], or nil if none found. + +```go-html-template +{{ range .Resources.Match "images/*.jpg" }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> +{{ end }} +``` + +When working with global resources instead of page resources, use the [`resources.Match`] function. + +## Pattern matching + +With the `GetMatch` and `Match` methods, Hugo determines a match using a case-insensitive [glob pattern]. + +{{% include "functions/_common/glob-patterns.md" %}} + +[`resources.ByType`]: /functions/resources/ByType +[`resources.GetMatch`]: /functions/resources/ByType +[`resources.Get`]: /functions/resources/ByType +[`resources.Match`]: /functions/resources/ByType +[`resources`]: /functions/resources +[glob pattern]: https://github.com/gobwas/glob#example +[media type]: https://en.wikipedia.org/wiki/Media_type +[page bundle]: /getting-started/glossary/#page-bundle diff --git a/docs/content/en/methods/page/Scratch.md b/docs/content/en/methods/page/Scratch.md new file mode 100644 index 000000000..f9ce7f7fb --- /dev/null +++ b/docs/content/en/methods/page/Scratch.md @@ -0,0 +1,23 @@ +--- +title: Scratch +description: Creates a "scratch pad" on the given page to store and manipulate data. +categories: [] +keywords: [] +action: + related: + - methods/page/Store + - functions/collections/NewScratch + returnType: maps.Scratch + signatures: [PAGE.Scratch] +aliases: [/extras/scratch/,/doc/scratch/,/functions/scratch] +--- + +The `Scratch` method on a `Page` object creates a [scratch pad] to store and manipulate data. To create a scratch pad that is not reset on server rebuilds, use the [`Store`] method instead. + +To create a locally scoped scratch pad that is not attached to a `Page` object, use the [`newScratch`] function. + +[`Store`]: /methods/page/store +[`newScratch`]: functions/collections/newscratch +[scratch pad]: /getting-started/glossary/#scratch-pad + +{{% include "methods/page/_common/scratch-methods.md" %}} diff --git a/docs/content/en/methods/page/Section.md b/docs/content/en/methods/page/Section.md new file mode 100644 index 000000000..30c8a9837 --- /dev/null +++ b/docs/content/en/methods/page/Section.md @@ -0,0 +1,54 @@ +--- +title: Section +description: Returns the name of the top level section in which the given page resides. +categories: [] +keywords: [] +action: + related: + - methods/page/Type + returnType: string + signatures: [PAGE.Section] +--- + +With this content structure: + +```text +content/ +├── lessons/ +│ ├── math/ +│ │ ├── _index.md +│ │ ├── lesson-1.md +│ │ └── lesson-2.md +│ └── _index.md +└── _index.md +``` + +When rendering lesson-1.md: + +```go-html-template +{{ .Section }} → lessons +``` + +In the example above "lessons" is the top level section. + +The `Section` method is often used with the [`where`] function to build a page collection. + +```go-html-template +{{ range where .Site.RegularPages "Section" "lessons" }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +``` + +This is similar to using the [`Type`] method with the `where` function + +```go-html-template +{{ range where .Site.RegularPages "Type" "lessons" }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +``` + +However, if the `type` field in front matter has been defined on one or more pages, the page collection based on `Type` will be different than the page collection based on `Section`. + + +[`where`]: /functions/collections/where +[`Type`]: /methods/page/type diff --git a/docs/content/en/methods/page/Sections.md b/docs/content/en/methods/page/Sections.md new file mode 100644 index 000000000..d64440038 --- /dev/null +++ b/docs/content/en/methods/page/Sections.md @@ -0,0 +1,69 @@ +--- +title: Sections +description: Returns a collection of section pages, one for each immediate descendant section of the given page. +categories: [] +keywords: [] +action: + related: + - methods/page/Ancestors + - methods/page/CurrentSection + - methods/page/FirstSection + - methods/page/InSection + - methods/page/IsAncestor + - methods/page/IsDescendant + - methods/page/Parent + returnType: page.Pages + signatures: [PAGE.Sections] +--- + +{{% include "methods/page/_common/definition-of-section.md" %}} + +With this content structure: + +```text +content/ +├── auctions/ +│ ├── 2023-11/ +│ │ ├── _index.md <-- front matter: weight = 202311 +│ │ ├── auction-1.md +│ │ └── auction-2.md +│ ├── 2023-12/ +│ │ ├── _index.md <-- front matter: weight = 202312 +│ │ ├── auction-3.md +│ │ └── auction-4.md +│ ├── _index.md <-- front matter: weight = 30 +│ ├── bidding.md +│ └── payment.md +├── books/ +│ ├── _index.md <-- front matter: weight = 10 +│ ├── book-1.md +│ └── book-2.md +├── films/ +│ ├── _index.md <-- front matter: weight = 20 +│ ├── film-1.md +│ └── film-2.md +└── _index.md +``` + +And this template: + +```go-html-template +{{ range .Sections.ByWeight }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +``` + +On the home page, Hugo renders: + +```html +<h2><a href="/films/">Films</a></h2> +<h2><a href="/books/">Books</a></h2> +<h2><a href="/auctions/">Auctions</a></h2> +``` + +On the auctions page, Hugo renders: + +```html +<h2><a href="/auctions/2023-11/">Auctions in November 2023</a></h2> +<h2><a href="/auctions/2023-12/">Auctions in December 2023</a></h2> +``` diff --git a/docs/content/en/methods/page/Site.md b/docs/content/en/methods/page/Site.md new file mode 100644 index 000000000..34748facd --- /dev/null +++ b/docs/content/en/methods/page/Site.md @@ -0,0 +1,19 @@ +--- +title: Site +description: Returns the Site object. +categories: [] +keywords: [] +action: + related: + - methods/page/Sites + returnType: page.siteWrapper + signatures: [PAGE.Site] +--- + +See [Site methods]. + +[Site methods]: /methods/site + +```go-html-template +{{ .Site.Title }} +``` diff --git a/docs/content/en/methods/page/Sitemap.md b/docs/content/en/methods/page/Sitemap.md new file mode 100644 index 000000000..08ff3f5d0 --- /dev/null +++ b/docs/content/en/methods/page/Sitemap.md @@ -0,0 +1,70 @@ +--- +title: Sitemap +description: Returns the sitemap settings for the given page as defined in front matter, falling back to the sitemap settings as defined in the site configuration. +categories: [] +keywords: [] +action: + related: [] + returnType: config.SitemapConfig + signatures: [PAGE.Sitemap] +toc: true +--- + +Access to the `Sitemap` method on a `Page` object is restricted to [sitemap templates]. + +## Methods + +ChangeFreq +: (`string`) How frequently a page is likely to change. Valid values are `always`, `hourly`, `daily`, `weekly`, `monthly`, `yearly`, and `never`. Default is "" (change frequency omitted from rendered sitemap). + +```go-html-template +{{ .Sitemap.ChangeFreq }} +``` + +Priority +: (`float`) The priority of a page relative to any other page on the site. Valid values range from 0.0 to 1.0. Default is -1 (priority omitted from rendered sitemap). + +```go-html-template +{{ .Sitemap.Priority }} +``` + +## Example + +With this site configuration: + +{{< code-toggle file=hugo >}} +[sitemap] +changeFreq = 'monthly' +{{< /code-toggle >}} + +And this content: + +{{< code-toggle file=content/news.md fm=true >}} +title = 'News' +[sitemap] +changeFreq = 'hourly' +{{< /code-toggle >}} + +And this simplistic sitemap template: + +{{< code file=layouts/_default/sitemap.xml >}} +{{ printf "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>" | safeHTML }} +<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" + xmlns:xhtml="http://www.w3.org/1999/xhtml"> + {{ range .Pages }} + <url> + <loc>{{ .Permalink }}</loc> + {{ if not .Lastmod.IsZero }} + <lastmod>{{ .Lastmod.Format "2006-01-02T15:04:05-07:00" | safeHTML }}</lastmod> + {{ end }} + {{ with .Sitemap.ChangeFreq }} + <changefreq>{{ . }}</changefreq> + {{ end }} + </url> + {{ end }} +</urlset> +{{< /code >}} + +The change frequency will be `hourly` for the news page, and `monthly` for other pages. + +[sitemap templates]: /templates/sitemap-template/ diff --git a/docs/content/en/methods/page/Sites.md b/docs/content/en/methods/page/Sites.md new file mode 100644 index 000000000..1fbdfcdcd --- /dev/null +++ b/docs/content/en/methods/page/Sites.md @@ -0,0 +1,69 @@ +--- +title: Sites +description: Returns a collection of all Site objects, one for each language, ordered by language weight. +categories: [] +keywords: [] +action: + related: + - methods/page/Site + returnType: page.Sites + signatures: [PAGE.Sites] +--- + +This is a convenience method to access `.Site.Sites`. + +With this site configuration: + +{{< code-toggle file=hugo >}} +defaultContentLanguage = 'de' +defaultContentLanguageInSubdir = false + +[languages.de] +languageCode = 'de-DE' +languageDirection = 'ltr' +languageName = 'Deutsch' +title = 'Projekt Dokumentation' +weight = 1 + +[languages.en] +languageCode = 'en-US' +languageDirection = 'ltr' +languageName = 'English' +title = 'Project Documentation' +weight = 2 +{{< /code-toggle >}} + +This template: + +```go-html-template +<ul> + {{ range .Sites }} + <li><a href="{{ .Home.Permalink }}">{{ .Title }}</a></li> + {{ end }} +</ul> +``` + +Produces a list of links to each home page: + +```html +<ul> + <li><a href="https://example.org/de/">Projekt Dokumentation</a></li> + <li><a href="https://example.org/en/">Project Documentation</a></li> +</ul> +``` + +To render a link to home page of the primary (first) language: + +```go-html-template +{{ with .Sites.First }} + <a href="{{ .Home.Permalink }}">{{ .Title }}</a> +{{ end }} +``` + +This is equivalent to: + +```go-html-template +{{ with index .Sites 0 }} + <a href="{{ .Home.Permalink }}">{{ .Title }}</a> +{{ end }} +``` diff --git a/docs/content/en/methods/page/Slug.md b/docs/content/en/methods/page/Slug.md new file mode 100644 index 000000000..9fdb09b57 --- /dev/null +++ b/docs/content/en/methods/page/Slug.md @@ -0,0 +1,25 @@ +--- +title: Slug +description: Returns the URL slug of the given page as defined in front matter. +categories: [] +keywords: [] +action: + related: [] + returnType: string + signatures: [PAGE.Slug] +--- + +{{< code-toggle file=content/recipes/spicy-tuna-hand-rolls.md fm=true >}} +title = 'How to make spicy tuna hand rolls' +slug = 'sushi' +{{< /code-toggle >}} + +This page will be served from: + + https://example.org/recipes/sushi + +To get the slug value within a template: + +```go-html-template +{{ .Slug }} → sushi +``` diff --git a/docs/content/en/methods/page/Store.md b/docs/content/en/methods/page/Store.md new file mode 100644 index 000000000..8bc16034b --- /dev/null +++ b/docs/content/en/methods/page/Store.md @@ -0,0 +1,104 @@ +--- +title: Store +description: Creates a persistent "scratch pad" on the given page to store and manipulate data. +categories: [] +keywords: [] +action: + related: + - methods/page/scratch + - functions/collections/NewScratch + returnType: maps.Scratch + signatures: [PAGE.Store] +aliases: [/functions/store] +--- + +The `Store` method on a `Page` object creates a persistent [scratch pad] to store and manipulate data. In contrast with the [`Scratch`] method, the scratch pad created by the `Store` method is not reset on server rebuilds. + +To create a locally scoped scratch pad that is not attached to a `Page` object, use the [`newScratch`] function. + +[`Scratch`]: /methods/page/scratch +[`newScratch`]: functions/collections/newscratch +[scratch pad]: /getting-started/glossary/#scratch-pad + +## Methods + +###### Set + +Sets the value of a given key. + +```go-html-template +{{ .Store.Set "greeting" "Hello" }} +``` + +###### Get + +Gets the value of a given key. + +```go-html-template +{{ .Store.Set "greeting" "Hello" }} +{{ .Store.Get "greeting" }} → Hello +``` + +###### Add + +Adds a given value to existing value(s) of the given key. + +For single values, `Add` accepts values that support Go's `+` operator. If the first `Add` for a key is an array or slice, the following adds will be appended to that list. + +```go-html-template +{{ .Store.Set "greeting" "Hello" }} +{{ .Store.Add "greeting" "Welcome" }} +{{ .Store.Get "greeting" }} → HelloWelcome +``` + +```go-html-template +{{ .Store.Set "total" 3 }} +{{ .Store.Add "total" 7 }} +{{ .Store.Get "total" }} → 10 +``` + +```go-html-template +{{ .Store.Set "greetings" (slice "Hello") }} +{{ .Store.Add "greetings" (slice "Welcome" "Cheers") }} +{{ .Store.Get "greetings" }} → [Hello Welcome Cheers] +``` + +###### SetInMap + +Takes a `key`, `mapKey` and `value` and adds a map of `mapKey` and `value` to the given `key`. + +```go-html-template +{{ .Store.SetInMap "greetings" "english" "Hello" }} +{{ .Store.SetInMap "greetings" "french" "Bonjour" }} +{{ .Store.Get "greetings" }} → map[english:Hello french:Bonjour] +``` + +###### DeleteInMap + +Takes a `key` and `mapKey` and removes the map of `mapKey` from the given `key`. + +```go-html-template +{{ .Store.SetInMap "greetings" "english" "Hello" }} +{{ .Store.SetInMap "greetings" "french" "Bonjour" }} +{{ .Store.DeleteInMap "greetings" "english" }} +{{ .Store.Get "greetings" }} → map[french:Bonjour] +``` + +###### GetSortedMapValues + +Returns an array of values from `key` sorted by `mapKey`. + +```go-html-template +{{ .Store.SetInMap "greetings" "english" "Hello" }} +{{ .Store.SetInMap "greetings" "french" "Bonjour" }} +{{ .Store.GetSortedMapValues "greetings" }} → [Hello Bonjour] +``` + +###### Delete + +Removes the given key. + +```go-html-template +{{ .Store.Set "greeting" "Hello" }} +{{ .Store.Delete "greeting" }} +``` diff --git a/docs/content/en/methods/page/Summary.md b/docs/content/en/methods/page/Summary.md new file mode 100644 index 000000000..37ce86589 --- /dev/null +++ b/docs/content/en/methods/page/Summary.md @@ -0,0 +1,29 @@ +--- +title: Summary +description: Returns the content summary of the given page. +categories: [] +keywords: [] +action: + related: + - methods/page/Truncated + - methods/page/Description + returnType: template.HTML + signatures: [PAGE.Summary] +--- + +There are three ways to define the [content summary]: + +1. Let Hugo create the summary based on the first 70 words. You can change the number of words by setting the `summaryLength` in your site configuration. +2. Manually split the content with a `<--more-->` tag in markdown. Everything before the tag is included in the summary. +3. Create a `summary` field in front matter. + +To list the pages in a section with a summary beneath each link: + +```go-html-template +{{ range .Pages }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> + {{ .Summary }} +{{ end }} +``` + +[content summary]: /content-management/summaries diff --git a/docs/content/en/methods/page/TableOfContents.md b/docs/content/en/methods/page/TableOfContents.md new file mode 100644 index 000000000..2ab182e8c --- /dev/null +++ b/docs/content/en/methods/page/TableOfContents.md @@ -0,0 +1,47 @@ +--- +title: TableOfContents +description: Returns a table of contents for the given page. +categories: [] +keywords: [] +action: + related: + - methods/page/Fragments + returnType: template.HTML + signatures: [PAGE.TableOfContents] +--- + +The `TableOfContents` method on a `Page` object returns an ordered or unordered list of the markdown [ATX] and [setext] headings within the page content. + +[atx]: https://spec.commonmark.org/0.30/#atx-headings +[setext]: https://spec.commonmark.org/0.30/#setext-headings + +This template code: + +```go-html-template +{{ .TableOfContents }} +``` + +Produces this HTML: + +```html +<nav id="TableOfContents"> + <ul> + <li><a href="#section-1">Section 1</a> + <ul> + <li><a href="#section-11">Section 1.1</a></li> + <li><a href="#section-12">Section 1.2</a></li> + </ul> + </li> + <li><a href="#section-2">Section 2</a></li> + </ul> +</nav> +``` + +By default, the `TableOfContents` method returns an unordered list of level 2 and level 3 headings. You can adjust this in your site configuration: + +{{< code-toggle file=hugo >}} +[markup.tableOfContents] +endLevel = 3 +ordered = false +startLevel = 2 +{{< /code-toggle >}} diff --git a/docs/content/en/methods/page/Title.md b/docs/content/en/methods/page/Title.md new file mode 100644 index 000000000..52e46ff44 --- /dev/null +++ b/docs/content/en/methods/page/Title.md @@ -0,0 +1,38 @@ +--- +title: Title +description: Returns the title of the given page. +categories: [] +keywords: [] +action: + related: + - methods/page/LinkTitle + returnType: string + signatures: [PAGE.Title] +--- + +With pages backed by a file, the `Title` method returns the `title` field as defined in front matter: + +{{< code-toggle file=content/about.md fm=true >}} +title = 'About us' +{{< /code-toggle >}} + +```go-html-template +{{ .Title }} → About us +``` + +With section pages not backed by a file, the `Title` method returns the section name, pluralized and converted to title case. + +To disable [pluralization]: + +{{< code-toggle file=hugo >}} +pluralizeListTitles = false +{{< /code-toggle >}} + +To change the [title case style], specify one of `ap`, `chicago`, `go`, `firstupper`, or `none`: + +{{< code-toggle file=hugo >}} +titleCaseStyle = "ap" +{{< /code-toggle >}} + +[pluralization]: /functions/inflect/pluralize +[title case style]: /getting-started/configuration/#configure-title-case diff --git a/docs/content/en/methods/page/TranslationKey.md b/docs/content/en/methods/page/TranslationKey.md new file mode 100644 index 000000000..a9e4b97e9 --- /dev/null +++ b/docs/content/en/methods/page/TranslationKey.md @@ -0,0 +1,74 @@ +--- +title: TranslationKey +description: Returns the translation key of the given page. +categories: [] +keywords: [] +action: + related: + - methods/page/Translations + - methods/page/AllTranslations + - methods/page/IsTranslated + returnType: string + signatures: [PAGE.TranslationKey] +--- + +The translation key creates a relationship between all translations of a given page. The translation key is derived from the file path, or from the `translationKey` parameter if defined in front matter. + +With this site configuration: + +{{< code-toggle file=hugo >}} +defaultContentLanguage = 'en' + +[languages.en] +contentDir = 'content/en' +languageCode = 'en-US' +languageName = 'English' +weight = 1 + +[languages.de] +contentDir = 'content/de' +languageCode = 'de-DE' +languageName = 'Deutsch' +weight = 2 +{{< /code-toggle >}} + +And this content: + +```text +content/ +├── de/ +│ ├── books/ +│ │ ├── buch-1.md +│ │ └── book-2.md +│ └── _index.md +├── en/ +│ ├── books/ +│ │ ├── book-1.md +│ │ └── book-2.md +│ └── _index.md +└── _index.md +``` + +And this front matter: + +{{< code-toggle file=content/en/books/book-1.md fm=true >}} +title = 'Book 1' +translationKey = 'foo' +{{< /code-toggle >}} + +{{< code-toggle file=content/de/books/buch-1.md fm=true >}} +title = 'Buch 1' +translationKey = 'foo' +{{< /code-toggle >}} + +When rendering either either of the pages above: + +```go-html-template +{{ .TranslationKey }} → page/foo +``` + +If the front matter of Book 2, in both languages, does not include a translation key: + +```go-html-template +{{ .TranslationKey }} → page/books/book-2 +``` diff --git a/docs/content/en/methods/page/Translations.md b/docs/content/en/methods/page/Translations.md new file mode 100644 index 000000000..1ed256630 --- /dev/null +++ b/docs/content/en/methods/page/Translations.md @@ -0,0 +1,89 @@ +--- +title: Translations +description: Returns all translation of the given page, excluding the current language. +categories: [] +keywords: [] +action: + related: + - methods/page/AllTranslations + - methods/page/IsTranslated + - methods/page/TranslationKey + returnType: page.Pages + signatures: [PAGE.Translations] +--- + +With this site configuration: + +{{< code-toggle file=hugo >}} +defaultContentLanguage = 'en' + +[languages.en] +contentDir = 'content/en' +languageCode = 'en-US' +languageName = 'English' +weight = 1 + +[languages.de] +contentDir = 'content/de' +languageCode = 'de-DE' +languageName = 'Deutsch' +weight = 2 + +[languages.fr] +contentDir = 'content/fr' +languageCode = 'fr-FR' +languageName = 'Français' +weight = 3 +{{< /code-toggle >}} + +And this content: + +```text +content/ +├── de/ +│ ├── books/ +│ │ ├── book-1.md +│ │ └── book-2.md +│ └── _index.md +├── en/ +│ ├── books/ +│ │ ├── book-1.md +│ │ └── book-2.md +│ └── _index.md +├── fr/ +│ ├── books/ +│ │ └── book-1.md +│ └── _index.md +└── _index.md +``` + +And this template: + +```go-html-template +{{ with .Translations }} + <ul> + {{ range . }} + {{ $langName := or .Language.LanguageName .Language.Lang }} + {{ $langCode := or .Language.LanguageCode .Language.Lang }} + <li><a href="{{ .RelPermalink }}" hreflang="{{ $langCode }}">{{ .LinkTitle }} ({{ $langName }})</a></li> + {{ end }} + </ul> +{{ end }} +``` + +Hugo will render this list on the "Book 1" page of the English site: + +```html +<ul> + <li><a href="/de/books/book-1/" hreflang="de-DE">Book 1 (Deutsch)</a></li> + <li><a href="/fr/books/book-1/" hreflang="fr-FR">Book 1 (Français)</a></li> +</ul> +``` + +Hugo will render this list on the "Book 2" page of the English site: + +```html +<ul> + <li><a href="/de/books/book-1/" hreflang="de-DE">Book 1 (Deutsch)</a></li> +</ul> +``` diff --git a/docs/content/en/methods/page/Truncated.md b/docs/content/en/methods/page/Truncated.md new file mode 100644 index 000000000..e6051f0cd --- /dev/null +++ b/docs/content/en/methods/page/Truncated.md @@ -0,0 +1,35 @@ +--- +title: Truncated +description: Reports whether the content length exceeds the summary length. +categories: [] +keywords: [] +action: + related: + - methods/page/Summary + returnType: bool + signatures: [PAGE.Truncated] +--- + +There are three ways to define the [content summary]: + +1. Let Hugo create the summary based on the first 70 words. You can change the number of words by setting the `summaryLength` in your site configuration. +2. Manually split the content with a `<--more-->` tag in markdown. Everything before the tag is included in the summary. +3. Create a `summary` field in front matter. + +{{% note %}} +The `Truncated` method returns `false` if you define the summary in front matter. +{{% /note %}} + +The `Truncated` method returns `true` if the content length exceeds the summary length. This is useful for rendering a "read more" link: + +```go-html-template +{{ range .Pages }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> + {{ .Summary }} + {{ if .Truncated }} + <a href="{{ .RelPermalink }}">Read more...</a> + {{ end }} +{{ end }} +``` + +[content summary]: /content-management/summaries diff --git a/docs/content/en/methods/page/Type.md b/docs/content/en/methods/page/Type.md new file mode 100644 index 000000000..b7c62372b --- /dev/null +++ b/docs/content/en/methods/page/Type.md @@ -0,0 +1,56 @@ +--- +title: Type +description: Returns the content type of the given page. +categories: [] +keywords: [] +action: + related: + - methods/page/Kind + - methods/page/Layout + - methods/page/Type + returnType: string + signatures: [PAGE.Type] +--- + +The `Type` method on a `Page` object returns the [content type] of the given page. The content type is defined by the `type` field in front matter, or inferred from the top-level directory name if the `type` field in front matter is not defined. + +With this content structure: + +```text +content/ +├── auction/ +│ ├── _index.md +│ ├── item-1.md +│ └── item-2.md <-- front matter: type = books +├── books/ +│ ├── _index.md +│ ├── book-1.md +│ └── book-2.md +├── films/ +│ ├── _index.md +│ ├── film-1.md +│ └── film-2.md +└── _index.md +``` + +To list the books, regardless of [section]: + +```go-html-template +{{ range where .Site.RegularPages.ByTitle "Type" "books" }} + <h2><a href="{{ .RelPermalink }}">{{ .Title }}</a></h2> +{{ end }} +``` + +Hugo renders this to; + +```html +<h2><a href="/books/book-1/">Book 1</a></h2> +<h2><a href="/books/book-2/">Book 2</a></h2> +<h2><a href="/auction/item-2/">Item 2</a></h2> +``` + +The `type` field in front matter is also useful for targeting a template. See [details]. + +[content type]: /getting-started/glossary/#content-type +[details]: /templates/lookup-order/#target-a-template +[section]: /getting-started/glossary/#section diff --git a/docs/content/en/methods/page/Weight.md b/docs/content/en/methods/page/Weight.md new file mode 100644 index 000000000..75c75db86 --- /dev/null +++ b/docs/content/en/methods/page/Weight.md @@ -0,0 +1,27 @@ +--- +title: Weight +description: Returns the weight of the given page as defined in front matter. +categories: [] +keywords: [] +action: + related: [] + returnType: int + signatures: [PAGE.Weight] +--- + +The `Weight` method on a `Page` object returns the [weight] of the given page as defined in front matter. + +[weight]: /getting-started/glossary/#weight + +{{< code-toggle file=content/recipes/sushi.md fm=true >}} +title = 'How to make spicy tuna hand rolls' +weight = 42 +{{< /code-toggle >}} + +Page weight controls the position of a page within a collection that is sorted by weight. Assign weights using non-zero integers. Lighter items float to the top, while heavier items sink to the bottom. Unweighted or zero-weighted elements are placed at the end of the collection. + +Although rarely used within a template, you can access the value with: + +```go-html-template +{{ .Weight }} → 42 +``` diff --git a/docs/content/en/methods/page/WordCount.md b/docs/content/en/methods/page/WordCount.md new file mode 100644 index 000000000..bb1fdcf94 --- /dev/null +++ b/docs/content/en/methods/page/WordCount.md @@ -0,0 +1,20 @@ +--- +title: WordCount +description: Returns the number of words in the content of the given page. +categories: [] +keywords: [] +action: + related: + - methods/page/FuzzyWordCount + - methods/page/ReadingTime + returnType: int + signatures: [PAGE.WordCount] +--- + +```go-html-template +{{ .WordCount }} → 103 +``` + +To round up to nearest multiple of 100, use the [`FuzzyWordCount`] method. + +[`FuzzyWordCount`]: /methods/page/fuzzywordcount diff --git a/docs/content/en/methods/page/_common/_index.md b/docs/content/en/methods/page/_common/_index.md new file mode 100644 index 000000000..47d5812fb --- /dev/null +++ b/docs/content/en/methods/page/_common/_index.md @@ -0,0 +1,13 @@ +--- +cascade: + _build: + list: never + publishResources: false + render: never +--- + +<!-- +Files within this headless branch bundle are markdown snippets. Each file must contain front matter delimiters, though front matter fields are not required. + +Include the rendered content using the "include" shortcode. +--> diff --git a/docs/content/en/methods/page/_common/definition-of-section.md b/docs/content/en/methods/page/_common/definition-of-section.md new file mode 100644 index 000000000..7dc600789 --- /dev/null +++ b/docs/content/en/methods/page/_common/definition-of-section.md @@ -0,0 +1,5 @@ +--- +# Do not remove front matter. +--- + +A _section_ is a top-level content directory, or any content directory with an _index.md file. diff --git a/docs/content/en/methods/page/_common/output-format-definition.md b/docs/content/en/methods/page/_common/output-format-definition.md new file mode 100644 index 000000000..25944464a --- /dev/null +++ b/docs/content/en/methods/page/_common/output-format-definition.md @@ -0,0 +1,11 @@ +--- +# Do not remove front matter. +--- + +Hugo generates one or more files per page when building a site. For example, when rendering home, [section], [taxonomy], and [term] pages, Hugo generates an HTML file and an RSS file. Both HTML and RSS are built-in _output formats_. Create multiple output formats, and control generation based on [page kind], or by enabling one or more output formats for one or more pages. See [details]. + +[section]: /getting-started/glossary/#section +[taxonomy]: /getting-started/glossary/#taxonomy +[term]: /getting-started/glossary/#term +[page kind]: /getting-started/glossary/#page-kind +[details]: /templates/output-formats diff --git a/docs/content/en/methods/page/_common/output-format-methods.md b/docs/content/en/methods/page/_common/output-format-methods.md new file mode 100644 index 000000000..5e7111fe5 --- /dev/null +++ b/docs/content/en/methods/page/_common/output-format-methods.md @@ -0,0 +1,27 @@ +--- +# Do not remove front matter. +--- + +Get IDENTIFIER +: (`any`) Returns the `OutputFormat` object with the given identifier. + +MediaType +: (`media.Type`) Returns the media type of the output format. + +MediaType.MainType +: (`string`) Returns the main type of the output format's media type. + +MediaType.SubType +: (`string`) Returns the subtype of the current format's media type. + +Name +: (`string`) Returns the output identifier of the output format. + +Permalink +: (`string`) Returns the permalink of the page generated by the current output format. + +Rel +: (`string`) Returns the `rel` value of the output format, either the default or as defined in the site configuration. + +RelPermalink +: (`string`) Returns the relative permalink of the page generated by the current output format. diff --git a/docs/content/en/methods/page/_common/scratch-methods.md b/docs/content/en/methods/page/_common/scratch-methods.md new file mode 100644 index 000000000..b2650cdde --- /dev/null +++ b/docs/content/en/methods/page/_common/scratch-methods.md @@ -0,0 +1,86 @@ +--- +# Do not remove front matter. +--- + +## Methods + +###### Set + +Sets the value of a given key. + +```go-html-template +{{ .Scratch.Set "greeting" "Hello" }} +``` + +###### Get + +Gets the value of a given key. + +```go-html-template +{{ .Scratch.Set "greeting" "Hello" }} +{{ .Scratch.Get "greeting" }} → Hello +``` + +###### Add + +Adds a given value to existing value(s) of the given key. + +For single values, `Add` accepts values that support Go's `+` operator. If the first `Add` for a key is an array or slice, the following adds will be appended to that list. + +```go-html-template +{{ .Scratch.Set "greeting" "Hello" }} +{{ .Scratch.Add "greeting" "Welcome" }} +{{ .Scratch.Get "greeting" }} → HelloWelcome +``` + +```go-html-template +{{ .Scratch.Set "total" 3 }} +{{ .Scratch.Add "total" 7 }} +{{ .Scratch.Get "total" }} → 10 +``` + +```go-html-template +{{ .Scratch.Set "greetings" (slice "Hello") }} +{{ .Scratch.Add "greetings" (slice "Welcome" "Cheers") }} +{{ .Scratch.Get "greetings" }} → [Hello Welcome Cheers] +``` + +###### SetInMap + +Takes a `key`, `mapKey` and `value` and adds a map of `mapKey` and `value` to the given `key`. + +```go-html-template +{{ .Scratch.SetInMap "greetings" "english" "Hello" }} +{{ .Scratch.SetInMap "greetings" "french" "Bonjour" }} +{{ .Scratch.Get "greetings" }} → map[english:Hello french:Bonjour] +``` + +###### DeleteInMap + +Takes a `key` and `mapKey` and removes the map of `mapKey` from the given `key`. + +```go-html-template +{{ .Scratch.SetInMap "greetings" "english" "Hello" }} +{{ .Scratch.SetInMap "greetings" "french" "Bonjour" }} +{{ .Scratch.DeleteInMap "greetings" "english" }} +{{ .Scratch.Get "greetings" }} → map[french:Bonjour] +``` + +###### GetSortedMapValues + +Returns an array of values from `key` sorted by `mapKey`. + +```go-html-template +{{ .Scratch.SetInMap "greetings" "english" "Hello" }} +{{ .Scratch.SetInMap "greetings" "french" "Bonjour" }} +{{ .Scratch.GetSortedMapValues "greetings" }} → [Hello Bonjour] +``` + +###### Delete + +Removes the given key. + +```go-html-template +{{ .Scratch.Set "greeting" "Hello" }} +{{ .Scratch.Delete "greeting" }} +``` diff --git a/docs/content/en/methods/page/_index.md b/docs/content/en/methods/page/_index.md new file mode 100644 index 000000000..278541c5a --- /dev/null +++ b/docs/content/en/methods/page/_index.md @@ -0,0 +1,12 @@ +--- +title: Page methods +linkTitle: Page +description: Use these methods with a Page object. +categories: [] +keywords: [] +menu: + docs: + parent: methods +--- + +Use these methods with a Page object. diff --git a/docs/content/en/methods/pages/ByDate.md b/docs/content/en/methods/pages/ByDate.md new file mode 100644 index 000000000..eb4e86535 --- /dev/null +++ b/docs/content/en/methods/pages/ByDate.md @@ -0,0 +1,31 @@ +--- +title: ByDate +description: Returns the given page collection sorted by date in ascending order. +categories: [] +keywords: [] +action: + related: + - methods/pages/ByExpiryDate + - methods/pages/ByLastMod + - methods/pages/ByPublishDate + returnType: page.Pages + signatures: [PAGES.ByDate] +--- + +When sorting by date, the value is determined by your [site configuration], defaulting to the `date` field in front matter. + +[site configuration]: /getting-started/configuration/#configure-dates + +```go-html-template +{{ range .Pages.ByDate }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +``` + +To sort in descending order: + +```go-html-template +{{ range .Pages.ByDate.Reverse }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +``` diff --git a/docs/content/en/methods/pages/ByExpiryDate.md b/docs/content/en/methods/pages/ByExpiryDate.md new file mode 100644 index 000000000..41753c340 --- /dev/null +++ b/docs/content/en/methods/pages/ByExpiryDate.md @@ -0,0 +1,31 @@ +--- +title: ByExpiryDate +description: Returns the given page collection sorted by expiration date in ascending order. +categories: [] +keywords: [] +action: + related: + - methods/pages/ByDate + - methods/pages/ByLastMod + - methods/pages/ByPublishDate + returnType: page.Pages + signatures: [PAGES.ByExpiryDate] +--- + +When sorting by expiration date, the value is determined by your [site configuration], defaulting to the `expiryDate` field in front matter. + +[site configuration]: /getting-started/configuration/#configure-dates + +```go-html-template +{{ range .Pages.ByExpiryDate }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +``` + +To sort in descending order: + +```go-html-template +{{ range .Pages.ByExpiryDate.Reverse }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +``` diff --git a/docs/content/en/methods/pages/ByLanguage.md b/docs/content/en/methods/pages/ByLanguage.md new file mode 100644 index 000000000..30d87f954 --- /dev/null +++ b/docs/content/en/methods/pages/ByLanguage.md @@ -0,0 +1,24 @@ +--- +title: ByLanguage +description: Returns the given page collection sorted by language in ascending order. +categories: [] +keywords: [] +action: + related: [] + returnType: page.Pages + signatures: [PAGES.ByLanguage] +--- + +```go-html-template +{{ range .Site.AllPages.ByLanguage }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +``` + +To sort in descending order: + +```go-html-template +{{ range .Site.AllPages.ByLanguage.Reverse }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +``` diff --git a/docs/content/en/methods/pages/ByLastmod.md b/docs/content/en/methods/pages/ByLastmod.md new file mode 100644 index 000000000..385093134 --- /dev/null +++ b/docs/content/en/methods/pages/ByLastmod.md @@ -0,0 +1,31 @@ +--- +title: ByLastmod +description: Returns the given page collection sorted by last modification date in ascending order. +categories: [] +keywords: [] +action: + related: + - methods/pages/ByDate + - methods/pages/ByExpiryDate + - methods/pages/ByPublishDate + returnType: page.Pages + signatures: [PAGES.ByLastmod] +--- + +When sorting by last modification date, the value is determined by your [site configuration], defaulting to the `lastmod` field in front matter. + +[site configuration]: /getting-started/configuration/#configure-dates + +```go-html-template +{{ range .Pages.ByLastmod }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +``` + +To sort in descending order: + +```go-html-template +{{ range .Pages.ByLastmod.Reverse }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +``` diff --git a/docs/content/en/methods/pages/ByLength.md b/docs/content/en/methods/pages/ByLength.md new file mode 100644 index 000000000..602b548c2 --- /dev/null +++ b/docs/content/en/methods/pages/ByLength.md @@ -0,0 +1,24 @@ +--- +title: ByLength +description: Returns the given page collection sorted by content length in ascending order. +categories: [] +keywords: [] +action: + related: [] + returnType: page.Pages + signatures: [PAGES.ByLength] +--- + +```go-html-template +{{ range .Pages.ByLength }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +``` + +To sort in descending order: + +```go-html-template +{{ range .Pages.ByLength.Reverse }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +``` diff --git a/docs/content/en/methods/pages/ByLinkTitle.md b/docs/content/en/methods/pages/ByLinkTitle.md new file mode 100644 index 000000000..073b1e1ba --- /dev/null +++ b/docs/content/en/methods/pages/ByLinkTitle.md @@ -0,0 +1,26 @@ +--- +title: ByLinkTitle +description: Returns the given page collection sorted by link title in ascending order, falling back to title if link title is not defined. +categories: [] +keywords: [] +action: + related: + - methods/pages/ByTitle + - methods/pages/ByParam + returnType: page.Pages + signatures: [PAGES.ByLinkTitle] +--- + +```go-html-template +{{ range .Pages.ByLinkTitle }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +``` + +To sort in descending order: + +```go-html-template +{{ range .Pages.ByLinkTitle.Reverse }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +``` diff --git a/docs/content/en/methods/pages/ByParam.md b/docs/content/en/methods/pages/ByParam.md new file mode 100644 index 000000000..9a919cc88 --- /dev/null +++ b/docs/content/en/methods/pages/ByParam.md @@ -0,0 +1,36 @@ +--- +title: ByParam +description: Returns the given page collection sorted by the given parameter in ascending order. +categories: [] +keywords: [] +action: + related: + - methods/pages/ByTitle + - methods/pages/ByLinkTitle + returnType: page.Pages + signatures: [PAGES.ByParam PARAM] +--- + +If the given parameter is not present in front matter, Hugo will use the matching parameter in your site configuration if present. + +```go-html-template +{{ range .Pages.ByParam "author" }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +``` + +To sort in descending order: + +```go-html-template +{{ range (.Pages.ByParam "author").Reverse }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +``` + +If the targeted parameter is nested, access the field using dot notation: + +```go-html-template +{{ range .Pages.ByParam "author.last_name" }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +``` diff --git a/docs/content/en/methods/pages/ByPublishDate.md b/docs/content/en/methods/pages/ByPublishDate.md new file mode 100644 index 000000000..e622636a2 --- /dev/null +++ b/docs/content/en/methods/pages/ByPublishDate.md @@ -0,0 +1,31 @@ +--- +title: ByPublishDate +description: Returns the given page collection sorted by publish date in ascending order. +categories: [] +keywords: [] +action: + related: + - methods/pages/ByDate + - methods/pages/ByExpiryDate + - methods/pages/ByLastMod + returnType: page.Pages + signatures: [PAGES.ByPublishDate] +--- + +When sorting by publish date, the value is determined by your [site configuration], defaulting to the `publishDate` field in front matter. + +[site configuration]: /getting-started/configuration/#configure-dates + +```go-html-template +{{ range .Pages.ByPublishDate }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +``` + +To sort in descending order: + +```go-html-template +{{ range .Pages.ByPublishDate.Reverse }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +``` diff --git a/docs/content/en/methods/pages/ByTitle.md b/docs/content/en/methods/pages/ByTitle.md new file mode 100644 index 000000000..ee54d5cda --- /dev/null +++ b/docs/content/en/methods/pages/ByTitle.md @@ -0,0 +1,26 @@ +--- +title: ByTitle +description: Returns the given page collection sorted by title in ascending order. +categories: [] +keywords: [] +action: + related: + - methods/pages/ByLinkTitle + - methods/pages/ByParam + returnType: page.Pages + signatures: [PAGES.ByTitle] +--- + +```go-html-template +{{ range .Pages.ByTitle }} + <h2><a href="{{ .RelPermalink }}">{{ .Title }}</a></h2> +{{ end }} +``` + +To sort in descending order: + +```go-html-template +{{ range .Pages.ByTitle.Reverse }} + <h2><a href="{{ .RelPermalink }}">{{ .Title }}</a></h2> +{{ end }} +``` diff --git a/docs/content/en/methods/pages/ByWeight.md b/docs/content/en/methods/pages/ByWeight.md new file mode 100644 index 000000000..4eafee11f --- /dev/null +++ b/docs/content/en/methods/pages/ByWeight.md @@ -0,0 +1,28 @@ +--- +title: ByWeight +description: Returns the given page collection sorted by weight in ascending order. +categories: [] +keywords: [] +action: + related: [] + returnType: page.Pages + signatures: [PAGES.ByWeight] +--- + +Assign a [weight] to a page using the `weight` field in front matter. The weight must be a non-zero integer. Lighter items float to the top, while heavier items sink to the bottom. Unweighted or zero-weighted pages are placed at the end of the collection. + +[weight]: /getting-started/glossary/#weight + +```go-html-template +{{ range .Pages.ByWeight }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +``` + +To sort in descending order: + +```go-html-template +{{ range .Pages.ByWeight.Reverse }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +``` diff --git a/docs/content/en/methods/pages/GroupBy.md b/docs/content/en/methods/pages/GroupBy.md new file mode 100644 index 000000000..b46a39bdf --- /dev/null +++ b/docs/content/en/methods/pages/GroupBy.md @@ -0,0 +1,36 @@ +--- +title: GroupBy +description: Returns the given page collection grouped by the given field in ascending order. +categories: [] +keywords: [] +action: + related: [] + returnType: page.PagesGroup + signatures: ['PAGES.GroupBy FIELD [SORT]'] +--- + +{{% include "methods/pages/_common/group-sort-order.md" %}} + +```go-html-template +{{ range .Pages.GroupBy "Section" }} + <p>{{ .Key }}</p> + <ul> + {{ range .Pages }} + <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li> + {{ end }} + </ul> +{{ end }} +``` + +To sort the groups in descending order: + +```go-html-template +{{ range .Pages.GroupBy "Section" "desc" }} + <p>{{ .Key }}</p> + <ul> + {{ range .Pages }} + <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li> + {{ end }} + </ul> +{{ end }} +``` diff --git a/docs/content/en/methods/pages/GroupByDate.md b/docs/content/en/methods/pages/GroupByDate.md new file mode 100644 index 000000000..8b5fcd6f1 --- /dev/null +++ b/docs/content/en/methods/pages/GroupByDate.md @@ -0,0 +1,68 @@ +--- +title: GroupByDate +description: Returns the given page collection grouped by date in descending order. +categories: [] +keywords: [] +action: + related: + - methods/pages/GroupByExpiryDate + - methods/pages/GroupByLastMod + - methods/pages/GroupByParamDate + - methods/pages/GroupByPublishDate + returnType: page.PagesGroup + signatures: ['PAGES.GroupByDate LAYOUT [SORT]'] +--- + +When grouping by date, the value is determined by your [site configuration], defaulting to the `date` field in front matter. + +The [layout string] has the same format as the layout string for the [`time.Format`] function. The resulting group key is [localized] for language and region. + +[`time.Format`]: /functions/time/format/ +[layout string]: #layout-string +[localized]: /getting-started/glossary/#localization +[site configuration]: /getting-started/configuration/#configure-dates + +{{% include "methods/pages/_common/group-sort-order.md" %}} + +To group content by year and month: + +```go-html-template +{{ range .Pages.GroupByDate "January 2006" }} + <p>{{ .Key }}</p> + <ul> + {{ range .Pages }} + <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li> + {{ end }} + </ul> +{{ end }} +``` + +To sort the groups in ascending order: + +```go-html-template +{{ range .Pages.GroupByDate "January 2006" "asc" }} + <p>{{ .Key }}</p> + <ul> + {{ range .Pages }} + <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li> + {{ end }} + </ul> +{{ end }} +``` + +The pages within each group will also be sorted by date, either ascending or descending depending on the grouping option. To sort the pages within each group, use one of the sorting methods. For example, to sort the pages within each group by title: + +```go-html-template +{{ range .Pages.GroupByDate "January 2006" }} + <p>{{ .Key }}</p> + <ul> + {{ range .Pages.ByTitle }} + <li><a href="{{ .RelPermalink }}">{{ .Title }}</a></li> + {{ end }} + </ul> +{{ end }} +``` + +## Layout string + +{{% include "functions/_common/time-layout-string.md" %}} diff --git a/docs/content/en/methods/pages/GroupByExpiryDate.md b/docs/content/en/methods/pages/GroupByExpiryDate.md new file mode 100644 index 000000000..a9b248297 --- /dev/null +++ b/docs/content/en/methods/pages/GroupByExpiryDate.md @@ -0,0 +1,68 @@ +--- +title: GroupByExpiryDate +description: Returns the given page collection grouped by expiration date in descending order. +categories: [] +keywords: [] +action: + related: + - methods/pages/GroupByDate + - methods/pages/GroupByLastMod + - methods/pages/GroupByParamDate + - methods/pages/GroupByPublishDate + returnType: page.PagesGroup + signatures: ['PAGES.GroupByExpiryDate LAYOUT [SORT]'] +--- + +When grouping by expiration date, the value is determined by your [site configuration], defaulting to the `expiryDate` field in front matter. + +The [layout string] has the same format as the layout string for the [`time.Format`] function. The resulting group key is [localized] for language and region. + +[`time.Format`]: /functions/time/format/ +[layout string]: #layout-string +[localized]: /getting-started/glossary/#localization +[site configuration]: /getting-started/configuration/#configure-dates + +{{% include "methods/pages/_common/group-sort-order.md" %}} + +To group content by year and month: + +```go-html-template +{{ range .Pages.GroupByExpiryDate "January 2006" }} + <p>{{ .Key }}</p> + <ul> + {{ range .Pages }} + <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li> + {{ end }} + </ul> +{{ end }} +``` + +To sort the groups in ascending order: + +```go-html-template +{{ range .Pages.GroupByExpiryDate "January 2006" "asc" }} + <p>{{ .Key }}</p> + <ul> + {{ range .Pages }} + <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li> + {{ end }} + </ul> +{{ end }} +``` + +The pages within each group will also be sorted by expiration date, either ascending or descending depending on your grouping option. To sort the pages within each group, use one of the sorting methods. For example, to sort the pages within each group by title: + +```go-html-template +{{ range .Pages.GroupByExpiryDate "January 2006" }} + <p>{{ .Key }}</p> + <ul> + {{ range .Pages.ByTitle }} + <li><a href="{{ .RelPermalink }}">{{ .Title }}</a></li> + {{ end }} + </ul> +{{ end }} +``` + +## Layout string + +{{% include "functions/_common/time-layout-string.md" %}} diff --git a/docs/content/en/methods/pages/GroupByLastmod.md b/docs/content/en/methods/pages/GroupByLastmod.md new file mode 100644 index 000000000..877692521 --- /dev/null +++ b/docs/content/en/methods/pages/GroupByLastmod.md @@ -0,0 +1,68 @@ +--- +title: GroupByLastmod +description: Returns the given page collection grouped by last modification date in descending order. +categories: [] +keywords: [] +action: + related: + - methods/pages/GroupByDate + - methods/pages/GroupByExpiryDate + - methods/pages/GroupByParamDate + - methods/pages/GroupByPublishDate + returnType: page.PagesGroup + signatures: ['PAGES.GroupByLastmod LAYOUT [SORT]'] +--- + +When grouping by last modification date, the value is determined by your [site configuration], defaulting to the `lastmod` field in front matter. + +The [layout string] has the same format as the layout string for the [`time.Format`] function. The resulting group key is [localized] for language and region. + +[`time.Format`]: /functions/time/format/ +[layout string]: #layout-string +[localized]: /getting-started/glossary/#localization +[site configuration]: /getting-started/configuration/#configure-dates + +{{% include "methods/pages/_common/group-sort-order.md" %}} + +To group content by year and month: + +```go-html-template +{{ range .Pages.GroupByLastmod "January 2006" }} + <p>{{ .Key }}</p> + <ul> + {{ range .Pages }} + <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li> + {{ end }} + </ul> +{{ end }} +``` + +To sort the groups in ascending order: + +```go-html-template +{{ range .Pages.GroupByLastmod "January 2006" "asc" }} + <p>{{ .Key }}</p> + <ul> + {{ range .Pages }} + <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li> + {{ end }} + </ul> +{{ end }} +``` + +The pages within each group will also be sorted by last modification date, either ascending or descending depending on your grouping option. To sort the pages within each group, use one of the sorting methods. For example, to sort the pages within each group by title: + +```go-html-template +{{ range .Pages.GroupByLastmod "January 2006" }} + <p>{{ .Key }}</p> + <ul> + {{ range .Pages.ByTitle }} + <li><a href="{{ .RelPermalink }}">{{ .Title }}</a></li> + {{ end }} + </ul> +{{ end }} +``` + +## Layout string + +{{% include "functions/_common/time-layout-string.md" %}} diff --git a/docs/content/en/methods/pages/GroupByParam.md b/docs/content/en/methods/pages/GroupByParam.md new file mode 100644 index 000000000..9c63ab902 --- /dev/null +++ b/docs/content/en/methods/pages/GroupByParam.md @@ -0,0 +1,36 @@ +--- +title: GroupByParam +description: Returns the given page collection grouped by the given parameter in ascending order. +categories: [] +keywords: [] +action: + related: [] + returnType: page.PagesGroup + signatures: ['PAGES.GroupByParam PARAM [SORT]'] +--- + +{{% include "methods/pages/_common/group-sort-order.md" %}} + +```go-html-template +{{ range .Pages.GroupByParam "color" }} + <p>{{ .Key | title }}</p> + <ul> + {{ range .Pages }} + <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li> + {{ end }} + </ul> +{{ end }} +``` + +To sort the groups in descending order: + +```go-html-template +{{ range .Pages.GroupByParam "color" "desc" }} + <p>{{ .Key | title }}</p> + <ul> + {{ range .Pages }} + <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li> + {{ end }} + </ul> +{{ end }} +``` diff --git a/docs/content/en/methods/pages/GroupByParamDate.md b/docs/content/en/methods/pages/GroupByParamDate.md new file mode 100644 index 000000000..c7fedbb1a --- /dev/null +++ b/docs/content/en/methods/pages/GroupByParamDate.md @@ -0,0 +1,65 @@ +--- +title: GroupByParamDate +description: Returns the given page collection grouped by the given date parameter in descending order. +categories: [] +keywords: [] +action: + related: + - methods/pages/GroupByDate + - methods/pages/GroupByExpiryDate + - methods/pages/GroupByLastMod + - methods/pages/GroupByPublishDate + returnType: page.PagesGroup + signatures: ['PAGES.GroupByParamDate PARAM LAYOUT [SORT]'] +--- + +The [layout string] has the same format as the layout string for the [`time.Format`] function. The resulting group key is [localized] for language and region. + +[`time.Format`]: /functions/time/format/ +[layout string]: #layout-string +[localized]: /getting-started/glossary/#localization + +{{% include "methods/pages/_common/group-sort-order.md" %}} + +To group content by year and month: + +```go-html-template +{{ range .Pages.GroupByParamDate "eventDate" "January 2006" }} + <p>{{ .Key }}</p> + <ul> + {{ range .Pages }} + <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li> + {{ end }} + </ul> +{{ end }} +``` + +To sort the groups in ascending order: + +```go-html-template +{{ range .Pages.GroupByParamDate "eventDate" "January 2006" "asc" }} + <p>{{ .Key }}</p> + <ul> + {{ range .Pages }} + <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li> + {{ end }} + </ul> +{{ end }} +``` + +The pages within each group will also be sorted by the parameter date, either ascending or descending depending on your grouping option. To sort the pages within each group, use one of the sorting methods. For example, to sort the pages within each group by title: + +```go-html-template +{{ range .Pages.GroupByParamDate "eventDate" "January 2006" }} + <p>{{ .Key }}</p> + <ul> + {{ range .Pages.ByTitle }} + <li><a href="{{ .RelPermalink }}">{{ .Title }}</a></li> + {{ end }} + </ul> +{{ end }} +``` + +## Layout string + +{{% include "functions/_common/time-layout-string.md" %}} diff --git a/docs/content/en/methods/pages/GroupByPublishDate.md b/docs/content/en/methods/pages/GroupByPublishDate.md new file mode 100644 index 000000000..f6603e858 --- /dev/null +++ b/docs/content/en/methods/pages/GroupByPublishDate.md @@ -0,0 +1,68 @@ +--- +title: GroupByPublishDate +description: Returns the given page collection grouped by publish date in descending order. +categories: [] +keywords: [] +action: + related: + - methods/pages/GroupByDate + - methods/pages/GroupByExpiryDate + - methods/pages/GroupByLastMod + - methods/pages/GroupByParamDate + returnType: page.PagesGroup + signatures: ['PAGES.GroupByPublishDate LAYOUT [SORT]'] +--- + +When grouping by publish date, the value is determined by your [site configuration], defaulting to the `publishDate` field in front matter. + +The [layout string] has the same format as the layout string for the [`time.Format`] function. The resulting group key is [localized] for language and region. + +[`time.Format`]: /functions/time/format/ +[layout string]: #layout-string +[localized]: /getting-started/glossary/#localization +[site configuration]: /getting-started/configuration/#configure-dates + +{{% include "methods/pages/_common/group-sort-order.md" %}} + +To group content by year and month: + +```go-html-template +{{ range .Pages.GroupByPublishDate "January 2006" }} + <p>{{ .Key }}</p> + <ul> + {{ range .Pages }} + <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li> + {{ end }} + </ul> +{{ end }} +``` + +To sort the groups in ascending order: + +```go-html-template +{{ range .Pages.GroupByPublishDate "January 2006" "asc" }} + <p>{{ .Key }}</p> + <ul> + {{ range .Pages }} + <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li> + {{ end }} + </ul> +{{ end }} +``` + +The pages within each group will also be sorted by publish date, either ascending or descending depending on your grouping option. To sort the pages within each group, use one of the sorting methods. For example, to sort the pages within each group by title: + +```go-html-template +{{ range .Pages.GroupByPublishDate "January 2006" }} + <p>{{ .Key }}</p> + <ul> + {{ range .Pages.ByTitle }} + <li><a href="{{ .RelPermalink }}">{{ .Title }}</a></li> + {{ end }} + </ul> +{{ end }} +``` + +## Layout string + +{{% include "functions/_common/time-layout-string.md" %}} diff --git a/docs/content/en/methods/pages/Len.md b/docs/content/en/methods/pages/Len.md new file mode 100644 index 000000000..0a5989a1a --- /dev/null +++ b/docs/content/en/methods/pages/Len.md @@ -0,0 +1,14 @@ +--- +title: Len +description: Returns the number of pages in the given page collection. +categories: [] +keywords: [] +action: + related: [] + returnType: int + signatures: [PAGES.Len] +--- + +```go-html-template +{{ .Pages.Len }} → 42 +``` diff --git a/docs/content/en/methods/pages/Limit.md b/docs/content/en/methods/pages/Limit.md new file mode 100644 index 000000000..bf889fd7e --- /dev/null +++ b/docs/content/en/methods/pages/Limit.md @@ -0,0 +1,16 @@ +--- +title: Limit +description: Returns the first N pages from the given page collection. +categories: [] +keywords: [] +action: + related: [] + returnType: page.Pages + signatures: [PAGES.Limit NUMBER] +--- + +```go-html-template +{{ range .Pages.Limit 3 }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +``` diff --git a/docs/content/en/methods/pages/Next.md b/docs/content/en/methods/pages/Next.md new file mode 100644 index 000000000..b7284609f --- /dev/null +++ b/docs/content/en/methods/pages/Next.md @@ -0,0 +1,55 @@ +--- +title: Next +description: Returns the next page in a local page collection, relative to the given page. +categories: [] +keywords: [] +action: + related: + - methods/pages/Prev + - methods/page/Next + - methods/page/NextInSection + - methods/page/Prev + - methods/page/PrevInSection + returnType: page.Page + signatures: [PAGES.Next PAGE] +toc: true +--- + +The behavior of the `Prev` and `Next` methods on a `Pages` objects is probably the reverse of what you expect. + +With this content structure and the page collection sorted by weight in ascending order: + +```text +content/ +├── pages/ +│ ├── _index.md +│ ├── page-1.md <-- front matter: weight = 10 +│ ├── page-2.md <-- front matter: weight = 20 +│ └── page-3.md <-- front matter: weight = 30 +└── _index.md +``` + +When you visit page-2: + +- The `Prev` method points to page-3 +- The `Next` method points to page-1 + +{{% note %}} +Use the opposite label in your navigation links as shown in the example below. +{{% /note %}} + +```go-html-template +{{ $pages := where .Site.RegularPages.ByWeight "Section" "pages" }} + +{{ with $pages.Next . }} + <a href="{{ .RelPermalink }}">Previous</a> +{{ end }} + +{{ with $pages.Prev . }} + <a href="{{ .RelPermalink }}">Next</a> +{{ end }} +``` + +## Compare to Page methods + +{{% include "methods/_common/next-prev-on-page-vs-next-prev-on-pages.md" %}} diff --git a/docs/content/en/methods/pages/Prev.md b/docs/content/en/methods/pages/Prev.md new file mode 100644 index 000000000..b9ef27a45 --- /dev/null +++ b/docs/content/en/methods/pages/Prev.md @@ -0,0 +1,55 @@ +--- +title: Prev +description: Returns the previous page in a local page collection, relative to the given page. +categories: [] +keywords: [] +action: + related: + - methods/pages/Next + - methods/page/Next + - methods/page/NextInSection + - methods/page/Prev + - methods/page/PrevInSection + returnType: page.Pages + signatures: [PAGES.Prev PAGE] +toc: true +--- + +The behavior of the `Prev` and `Next` methods on a `Pages` objects is probably the reverse of what you expect. + +With this content structure and the page collection sorted by weight in ascending order: + +```text +content/ +├── pages/ +│ ├── _index.md +│ ├── page-1.md <-- front matter: weight = 10 +│ ├── page-2.md <-- front matter: weight = 20 +│ └── page-3.md <-- front matter: weight = 30 +└── _index.md +``` + +When you visit page-2: + +- The `Prev` method points to page-3 +- The `Next` method points to page-1 + +{{% note %}} +Use the opposite label in your navigation links as shown in the example below. +{{% /note %}} + +```go-html-template +{{ $pages := where .Site.RegularPages.ByWeight "Section" "pages" }} + +{{ with $pages.Next . }} + <a href="{{ .RelPermalink }}">Previous</a> +{{ end }} + +{{ with $pages.Prev . }} + <a href="{{ .RelPermalink }}">Next</a> +{{ end }} +``` + +## Compare to Page methods + +{{% include "methods/_common/next-prev-on-page-vs-next-prev-on-pages.md" %}} diff --git a/docs/content/en/methods/pages/Related.md b/docs/content/en/methods/pages/Related.md new file mode 100644 index 000000000..1cee88745 --- /dev/null +++ b/docs/content/en/methods/pages/Related.md @@ -0,0 +1,79 @@ +--- +title: Related +description: Returns a collection of pages related to the given page. +categories: [] +keywords: [] +action: + related: + - methods/page/HeadingsFiltered + - functions/collections/KeyVals + returnType: page.Pages + signatures: + - PAGES.Related PAGE + - PAGES.Related OPTIONS +--- + +Based on front matter, Hugo uses several factors to identify content related to the given page. Use the default [related content configuration], or tune the results to the desired indices and parameters. See [details]. + +The argument passed to the `Related` method may be a `Page` or an options map. For example, to pass the current page: + +{{< code file=layouts/_default/single.html >}} +{{ with .Site.RegularPages.Related . | first 5 }} + <p>Related pages:</p> + <ul> + {{ range . }} + <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li> + {{ end }} + </ul> +{{ end }} +{{< /code >}} + +To pass an options map: + +{{< code file=layouts/_default/single.html >}} +{{ $opts := dict + "document" . + "indices" (slice "tags" "keywords") +}} +{{ with .Site.RegularPages.Related $opts | first 5 }} + <p>Related pages:</p> + <ul> + {{ range . }} + <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li> + {{ end }} + </ul> +{{ end }} +{{< /code >}} + + +## Options + +indices +: (`slice`) The indices to search within. + +document +: (`page`) The page for which to find related content. Required when specifying an options map. + +namedSlices +: (`slice`) The keywords to search for, expressed as a slice of `KeyValues` using the [`keyVals`] function. + +[`keyVals`]: /functions/collections/keyvals/ + +fragments +: (`slice`) A list of special keywords that is used for indices configured as type "fragments". This will match the [fragment] identifiers of the documents. + +A contrived example using all of the above: + +```go-html-template +{{ $page := . }} +{{ $opts := dict + "indices" (slice "tags" "keywords") + "document" $page + "namedSlices" (slice (keyVals "tags" "hugo" "rocks") (keyVals "date" $page.Date)) + "fragments" (slice "heading-1" "heading-2") +}} +``` + +[details]: /content-management/related/ +[fragment]: /getting-started/glossary/#fragment +[related content configuration]: /content-management/related/ diff --git a/docs/content/en/methods/pages/Reverse.md b/docs/content/en/methods/pages/Reverse.md new file mode 100644 index 000000000..e03e0ea47 --- /dev/null +++ b/docs/content/en/methods/pages/Reverse.md @@ -0,0 +1,16 @@ +--- +title: Reverse +description: Returns the given page collection in reverse order. +categories: [] +keywords: [] +action: + related: [] + returnType: page.Pages + signatures: [PAGES.Reverse] +--- + +```go-html-template +{{ range .Pages.ByDate.Reverse }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +``` diff --git a/docs/content/en/methods/pages/_common/_index.md b/docs/content/en/methods/pages/_common/_index.md new file mode 100644 index 000000000..47d5812fb --- /dev/null +++ b/docs/content/en/methods/pages/_common/_index.md @@ -0,0 +1,13 @@ +--- +cascade: + _build: + list: never + publishResources: false + render: never +--- + +<!-- +Files within this headless branch bundle are markdown snippets. Each file must contain front matter delimiters, though front matter fields are not required. + +Include the rendered content using the "include" shortcode. +--> diff --git a/docs/content/en/methods/pages/_common/group-sort-order.md b/docs/content/en/methods/pages/_common/group-sort-order.md new file mode 100644 index 000000000..bb5be82f6 --- /dev/null +++ b/docs/content/en/methods/pages/_common/group-sort-order.md @@ -0,0 +1,5 @@ +--- +# Do not remove front matter. +--- + +For the optional sort order, specify either `asc` for ascending order, or `desc` for descending order. diff --git a/docs/content/en/methods/pages/_index.md b/docs/content/en/methods/pages/_index.md new file mode 100644 index 000000000..d8a64f5d5 --- /dev/null +++ b/docs/content/en/methods/pages/_index.md @@ -0,0 +1,13 @@ +--- +title: Pages methods +linkTitle: Pages +description: Use these methods with a collection of Page objects. +categories: [] +keywords: [] +menu: + docs: + parent: methods +aliases: [/variables/pages] +--- + +Use these methods with a collection of Page objects. diff --git a/docs/content/en/methods/resource/Colors.md b/docs/content/en/methods/resource/Colors.md new file mode 100644 index 000000000..1452d558f --- /dev/null +++ b/docs/content/en/methods/resource/Colors.md @@ -0,0 +1,22 @@ +--- +title: Colors +description: Applicable to images, returns a slice of the most dominant colors using a simple histogram method. +categories: [] +keywords: [] +action: + related: [] + returnType: '[]string' + signatures: [RESOURCE.Colors] +--- + +{{< new-in 0.104.0 >}} + +```go-html-template +{{ with resources.Get "images/a.jpg" }} + {{ .Colors }} → [#bebebd #514947 #768a9a #647789 #90725e #a48974] +{{ end }} +``` + +This method is fast, but if you also scale down your images, it would be good for performance to extract the colors from the scaled image. + +{{% include "methods/resource/_common/global-page-remote-resources.md" %}} diff --git a/docs/content/en/methods/resource/Content.md b/docs/content/en/methods/resource/Content.md new file mode 100644 index 000000000..a5945ff65 --- /dev/null +++ b/docs/content/en/methods/resource/Content.md @@ -0,0 +1,61 @@ +--- +title: Content +description: Returns the content of the given resource. +categories: [] +keywords: [] +action: + related: [] + returnType: any + signatures: [RESOURCE.Content] +toc: +--- + +The `Content` method on a `Resource` object returns `template.HTML` when the resource type is `page`, otherwise it returns a `string`. + +[resource type]: /methods/resource/resourcetype + +{{< code file=assets/quotations/kipling.txt >}} +He travels the fastest who travels alone. +{{< /code >}} + +To get the content: + +```go-html-template +{{ with resources.Get "quotations/kipling.txt" }} + {{ .Content }} → He travels the fastest who travels alone. +{{ end }} +``` + +To get the size in bytes: + +```go-html-template +{{ with resources.Get "quotations/kipling.txt" }} + {{ .Content | len }} → 42 +{{ end }} +``` + +To create an inline image: + +```go-html-template +{{ with resources.Get "images/a.jpg" }} + <img src="data:{{ .MediaType.Type }};base64,{{ .Content | base64Encode }}"> +{{ end }} +``` + +To create inline CSS: + +```go-html-template +{{ with resources.Get "css/style.css" }} + <style>{{ .Content | safeCSS }}</style> +{{ end }} +``` + +To create inline JavaScript: + +```go-html-template +{{ with resources.Get "js/script.js" }} + <script>{{ .Content | safeJS }}</script> +{{ end }} +``` + +{{% include "methods/resource/_common/global-page-remote-resources.md" %}} diff --git a/docs/content/en/methods/resource/Crop.md b/docs/content/en/methods/resource/Crop.md new file mode 100644 index 000000000..711fc07b0 --- /dev/null +++ b/docs/content/en/methods/resource/Crop.md @@ -0,0 +1,48 @@ +--- +title: Crop +description: Applicable to images, returns an image resource cropped to the given dimensions without resizing. +categories: [] +keywords: [] +action: + related: + - methods/resource/Fit + - methods/resource/Fill + - methods/resource/Resize + - methods/resource/Process + - functions/images/Process + returnType: images.ImageResource + signatures: [RESOURCE.Crop SPEC] +toc: true +--- + +Crop an image to match the given dimensions without resizing. You must provide both width and height. + +```go-html-template +{{ with resources.Get "images/original.jpg" }} + {{ with .Crop "200x200" }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> + {{ end }} +{{ end }} +``` + +{{% include "methods/resource/_common/global-page-remote-resources.md" %}} + +{{% include "/methods/resource/_common/processing-spec.md" %}} + +## Example + +```go-html-template +{{ with resources.Get "images/original.jpg" }} + {{ with .Crop "200x200 topright webp q85 lanczos" }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> + {{ end }} +{{ end }} +``` + +{{< img + src="images/examples/zion-national-park.jpg" + alt="Zion National Park" + filter="Process" + filterArgs="crop 200x200 topright webp q85 lanczos" + example=true +>}} diff --git a/docs/content/en/methods/resource/Data.md b/docs/content/en/methods/resource/Data.md new file mode 100644 index 000000000..0fbaf6199 --- /dev/null +++ b/docs/content/en/methods/resource/Data.md @@ -0,0 +1,53 @@ +--- +title: Data +description: Applicable to resources returned by the resources.GetRemote function, returns information from the HTTP response. +categories: [] +keywords: [] +action: + related: + - functions/resources/GetRemote + - methods/resource/Err + returnType: map + signatures: [RESOURCE.Data] +--- + +The `Data` method on a resource returned by the [`resources.GetRemote`] function returns information from the HTTP response. + +[`resources.GetRemote`]: functions/resources/getremote + +```go-html-template +{{ $url := "https://example.org/images/a.jpg" }} +{{ with resources.GetRemote $url }} + {{ with .Err }} + {{ errorf "%s" . }} + {{ else }} + {{ with .Data }} + {{ .ContentLength }} → 42764 + {{ .ContentType }} → image/jpeg + {{ .Status }} → 200 OK + {{ .StatusCode }} → 200 + {{ .TransferEncoding }} → [] + {{ end }} + {{ end }} +{{ else }} + {{ errorf "Unable to get remote resource %q" $url }} +{{ end }} +``` + +ContentLength +: (`int`) The content length in bytes. + +ContentType +: (`string`) The content type. + +Status +: (`string`) The HTTP status text. + +StatusCode +: (`int`) The HTTP status code. + +TransferEncoding +: (`string`) The transfer encoding. + + +[`resources.GetRemote`]: functions/resources/getremote diff --git a/docs/content/en/methods/resource/Err.md b/docs/content/en/methods/resource/Err.md new file mode 100644 index 000000000..f4b410aa7 --- /dev/null +++ b/docs/content/en/methods/resource/Err.md @@ -0,0 +1,56 @@ +--- +title: Err +description: Applicable to resources returned by the resources.GetRemote function, returns an error message if the HTTP request fails, else nil. +categories: [] +keywords: [] +action: + related: + - functions/resources/GetRemote + - methods/resource/Data + returnType: resource.resourceError + signatures: [RESOURCE.Err] +--- + +The `Err` method on a resource returned by the [`resources.GetRemote`] function returns an error message if the HTTP request fails, else nil. If you do not handle the error yourself, Hugo will fail the build. + +[`resources.GetRemote`]: functions/resources/getremote + +In this example we send an HTTP request to a nonexistent domain: + +```go-html-template +{{ $url := "https://broken-example.org/images/a.jpg" }} +{{ with resources.GetRemote $url }} + {{ with .Err }} + {{ errorf "%s" . }} + {{ else }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> + {{ end }} +{{ else }} + {{ errorf "Unable to get remote resource %q" $url }} +{{ end }} +``` + +The code above captures the error from the HTTP request, then fails the build: + +```text +ERROR error calling resources.GetRemote: Get "https://broken-example.org/images/a.jpg": dial tcp: lookup broken-example.org on 127.0.0.53:53: no such host +``` + +To log an error as a warning instead of an error: + +```go-html-template +{{ $url := "https://broken-example.org/images/a.jpg" }} +{{ with resources.GetRemote $url }} + {{ with .Err }} + {{ warnf "%s" . }} + {{ else }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> + {{ end }} +{{ else }} + {{ errorf "Unable to get remote resource %q" $url }} +{{ end }} +``` + +{{% note %}} +An HTTP response with a 404 status code is not an HTTP request error. To handle 404 status codes, code defensively using the nested `with-else-end` construct as shown above. +{{% /note %}} diff --git a/docs/content/en/methods/resource/Exif.md b/docs/content/en/methods/resource/Exif.md new file mode 100644 index 000000000..765b4c92f --- /dev/null +++ b/docs/content/en/methods/resource/Exif.md @@ -0,0 +1,78 @@ +--- +title: Exif +description: Applicable to JPEG and TIFF images, returns an EXIF object containing image metadata. +categories: [] +keywords: [] +action: + related: [] + returnType: exif.ExifInfo + signatures: [RESOURCE.Exif] +toc: true +--- + +Applicable to JPEG and TIFF images, the `Exif` method on an image `Resource` object returns an [EXIF] object containing image metadata. + +## Methods + +Date +: (`time.Time`) Returns the image creation date/time. Format with the [`time.Format`]function. + +Lat +: (`float64`) Returns the GPS latitude in degrees. + +Long +: (`float64`) Returns the GPS longitude in degrees. + +Tags +: (`exif.Tags`) Returns a collection of the available EXIF tags for this image. You may include or exclude specific tags from this collection in the [site configuration]. + +## Examples + +To list the creation date, location, and EXIF tags: + +```go-html-template +{{ with resources.Get "images/a.jpg" }} + {{ with .Exif }} + <p>Date: {{ .Date }}</p> + <p>Lat/Long: {{ .Lat }}/{{ .Long }}</p> + {{ with .Tags }} + <p>Tags</p> + <table> + <thead> + <tr><th>Tag</th><th>Value</th></tr> + </thead> + <tbody> + {{ range $k, $v := . }} + <tr><td>{{ $k }}</td><td>{{ $v }}</td></tr> + {{ end }} + </tbody> + </table> + {{ end }} + {{ end }} +{{ end }} +``` + +To list specific values: + +```go-html-template +{{ with resources.Get "images/a.jpg" }} + {{ with .Exif }} + <ul> + {{ with .Date }}<li>Date: {{ .Format "January 02, 2006" }}</li>{{ end }} + {{ with .Tags.ApertureValue }}<li>Aperture: {{ lang.FormatNumber 2 . }}</li>{{ end }} + {{ with .Tags.BrightnessValue }}<li>Brightness: {{ lang.FormatNumber 2 . }}</li>{{ end }} + {{ with .Tags.ExposureTime }}<li>Exposure Time: {{ . }}</li>{{ end }} + {{ with .Tags.FNumber }}<li>F Number: {{ . }}</li>{{ end }} + {{ with .Tags.FocalLength }}<li>Focal Length: {{ . }}</li>{{ end }} + {{ with .Tags.ISOSpeedRatings }}<li>ISO Speed Ratings: {{ . }}</li>{{ end }} + {{ with .Tags.LensModel }}<li>Lens Model: {{ . }}</li>{{ end }} + </ul> + {{ end }} +{{ end }} +``` + +{{% include "methods/resource/_common/global-page-remote-resources.md" %}} + +[exif]: https://en.wikipedia.org/wiki/Exif +[site configuration]: /content-management/image-processing/#exif-data +[`time.Format`]: /functions/time/format diff --git a/docs/content/en/methods/resource/Fill.md b/docs/content/en/methods/resource/Fill.md new file mode 100644 index 000000000..8bbaf93ee --- /dev/null +++ b/docs/content/en/methods/resource/Fill.md @@ -0,0 +1,48 @@ +--- +title: Fill +description: Applicable to images, returns an image resource cropped and resized to the given dimensions. +categories: [] +keywords: [] +action: + related: + - methods/resource/Crop + - methods/resource/Fit + - methods/resource/Resize + - methods/resource/Process + - functions/images/Process + returnType: images.ImageResource + signatures: [RESOURCE.Fill SPEC] +toc: true +--- + +Crop and resize an image to match the given dimensions. You must provide both width and height. + +```go-html-template +{{ with resources.Get "images/original.jpg" }} + {{ with .Fill "200x200" }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> + {{ end }} +{{ end }} +``` + +{{% include "methods/resource/_common/global-page-remote-resources.md" %}} + +{{% include "/methods/resource/_common/processing-spec.md" %}} + +## Example + +```go-html-template +{{ with resources.Get "images/original.jpg" }} + {{ with .Fill "200x200 top webp q85 lanczos" }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> + {{ end }} +{{ end }} +``` + +{{< img + src="images/examples/zion-national-park.jpg" + alt="Zion National Park" + filter="Process" + filterArgs="fill 200x200 top webp q85 lanczos" + example=true +>}} diff --git a/docs/content/en/methods/resource/Filter.md b/docs/content/en/methods/resource/Filter.md new file mode 100644 index 000000000..329168da7 --- /dev/null +++ b/docs/content/en/methods/resource/Filter.md @@ -0,0 +1,68 @@ +--- +title: Filter +description: Applicable to images, applies one or more image filters to the given image resource. +categories: [] +keywords: [] +action: + related: + - functions/images/Filter + returnType: resources.resourceAdapter + signatures: [RESOURCE.Filter FILTER...] +toc: true +--- + +Apply one or more [image filters](#image-filters) to the given image. + +To apply a single filter: + +```go-html-template +{{ with resources.Get "images/original.jpg" }} + {{ with .Filter images.Grayscale }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> + {{ end }} +{{ end }} +``` + +To apply two or more filters, executing from left to right: + +```go-html-template +{{ $filters := slice + images.Grayscale + (images.GaussianBlur 8) +}} +{{ with resources.Get "images/original.jpg" }} + {{ with .Filter $filters }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> + {{ end }} +{{ end }} +``` + +You can also apply image filters using the [`images.Filter`] function. + +[`images.Filter`]: /functions/images/filter + +{{% include "methods/resource/_common/global-page-remote-resources.md" %}} + +## Example + +```go-html-template +{{ with resources.Get "images/original.jpg" }} + {{ with .Filter images.Grayscale }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> + {{ end }} +{{ end }} +``` + +{{< img + src="images/examples/zion-national-park.jpg" + alt="Zion National Park" + filter="Grayscale" + filterArgs="" + example=true +>}} + +## Image filters + +Use any of these filters with the `Filter` method. + +{{< list-pages-in-section path=/functions/images filter=functions_images_no_filters filterType=exclude >}} diff --git a/docs/content/en/methods/resource/Fit.md b/docs/content/en/methods/resource/Fit.md new file mode 100644 index 000000000..13354fe5a --- /dev/null +++ b/docs/content/en/methods/resource/Fit.md @@ -0,0 +1,48 @@ +--- +title: Fit +description: Applicable to images, returns an image resource downscaled to fit the given dimensions while maintaining aspect ratio. +categories: [] +keywords: [] +action: + related: + - methods/resource/Crop + - methods/resource/Fill + - methods/resource/Resize + - methods/resource/Process + - functions/images/Process + returnType: images.ImageResource + signatures: [RESOURCE.Fit SPEC] +toc: true +--- + +Downscale an image to fit the given dimensions while maintaining aspect ratio. You must provide both width and height. + +```go-html-template +{{ with resources.Get "images/original.jpg" }} + {{ with .Fit "200x200" }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> + {{ end }} +{{ end }} +``` + +{{% include "methods/resource/_common/global-page-remote-resources.md" %}} + +{{% include "/methods/resource/_common/processing-spec.md" %}} + +## Example + +```go-html-template +{{ with resources.Get "images/original.jpg" }} + {{ with .Fit "300x175 webp q85 lanczos" }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> + {{ end }} +{{ end }} +``` + +{{< img + src="images/examples/zion-national-park.jpg" + alt="Zion National Park" + filter="Process" + filterArgs="fit 300x175 webp q85 lanczos" + example=true +>}} diff --git a/docs/content/en/methods/resource/Height.md b/docs/content/en/methods/resource/Height.md new file mode 100644 index 000000000..dcaf6c514 --- /dev/null +++ b/docs/content/en/methods/resource/Height.md @@ -0,0 +1,27 @@ +--- +title: Height +description: Applicable to images, returns the height of the given resource. +categories: [] +keywords: [] +action: + related: + - methods/resource/Width + returnType: int + signatures: [RESOURCE.Height] +--- + +```go-html-template +{{ with resources.Get "images/a.jpg" }} + {{ .Height }} → 400 +{{ end }} +``` + +Use the `Width` and `Height` methods together when rendering an `img` element: + +```go-html-template +{{ with resources.Get "images/a.jpg" }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}"> +{{ end }} +``` + +{{% include "methods/resource/_common/global-page-remote-resources.md" %}} diff --git a/docs/content/en/methods/resource/Key.md b/docs/content/en/methods/resource/Key.md new file mode 100644 index 000000000..15927aea9 --- /dev/null +++ b/docs/content/en/methods/resource/Key.md @@ -0,0 +1,45 @@ +--- +title: Key +description: Returns the unique key for the given resource, equivalent to its publishing path. +categories: [] +keywords: [] +action: + related: + - methods/resource/Permalink + - methods/resource/RelPermalink + - methods/resource/Publish + returnType: string + signatures: [RESOURCE.Key] +--- + +By way of example, consider this site configuration: + +{{< code-toggle file=hugo >}} +baseURL = 'https://example.org/docs/' +{{< /code-toggle >}} + +And this template: + +```go-html-template + {{ with resources.Get "images/a.jpg" }} + {{ with resources.Copy "foo/bar/b.jpg" . }} + {{ .Key }} → foo/bar/b.jpg + + {{ .Name }} → images/a.jpg + {{ .Title }} → images/a.jpg + + {{ .RelPermalink }} → /docs/foo/bar/b.jpg + {{ end }} + {{ end }} +``` + +We used the [`resources.Copy`] function to change the publishing path. The `Key` method returns the updated path, but note that it is different than the value returned by [`RelPermalink`]. The `RelPermalink` value includes the subdirectory segment of the `baseURL` in the site configuration. + +The `Key` method is useful if you need to get the resource's publishing path without publishing the resource. Unlike the `Permalink`, `RelPermalink`, or `Publish` methods, calling `Key` will not publish the resource. + + +{{% include "methods/resource/_common/global-page-remote-resources.md" %}} + +[`Permalink`]: /methods/resource/permalink +[`RelPermalink`]: /methods/resource/relpermalink +[`resources.Copy`]: /functions/resources/copy diff --git a/docs/content/en/methods/resource/MediaType.md b/docs/content/en/methods/resource/MediaType.md new file mode 100644 index 000000000..6dea8706c --- /dev/null +++ b/docs/content/en/methods/resource/MediaType.md @@ -0,0 +1,52 @@ +--- +title: MediaType +description: Returns a media type object for the given resource. +categories: [] +keywords: [] +action: + related: [] + returnType: media.Type + signatures: [RESOURCE.MediaType] +--- + +The `MediaType` method on a `Resource` object returns an object with additional methods. + +## Methods + +Type +: (`string`) The resource's media type. + +```go-html-template +{{ with resources.Get "images/a.jpg" }} + {{ .MediaType.Type }} → image/jpeg +{{ end }} +``` + +MainType +: (`string`) The main type of the resource’s media type. + +```go-html-template +{{ with resources.Get "images/a.jpg" }} + {{ .MediaType.MainType }} → image +{{ end }} +``` + +SubType +: (`string`) The subtype of the resource’s media type. This may or may not correspond to the file suffix. + +```go-html-template +{{ with resources.Get "images/a.jpg" }} + {{ .MediaType.SubType }} → jpeg +{{ end }} +``` + +Suffixes +: (`slice`) A slice of possible file suffixes for the resource’s media type. + +```go-html-template +{{ with resources.Get "images/a.jpg" }} + {{ .MediaType.Suffixes }} → [jpg jpeg jpe jif jfif] +{{ end }} +``` + +{{% include "methods/resource/_common/global-page-remote-resources.md" %}} diff --git a/docs/content/en/methods/resource/Name.md b/docs/content/en/methods/resource/Name.md new file mode 100644 index 000000000..01b75e5b2 --- /dev/null +++ b/docs/content/en/methods/resource/Name.md @@ -0,0 +1,82 @@ +--- +title: Name +description: Returns the name of the given resource as optionally defined in front matter, falling back to a relative path or hashed file name depending on resource type. +categories: [] +keywords: [] +action: + related: + - methods/resource/Title + returnType: string + signatures: [RESOURCE.Name] +toc: true +--- + +The value returned by the `Name` method on a `Resource` object depends on the resource type. + +## Global resource + +With a [global resource], the `Name` method returns the path to the resource, relative to the assets directory. + +```text +assets/ +└── images/ + └── a.jpg +``` + +```go-html-template +{{ with resources.Get "images/a.jpg" }} + {{ .Name }} → images/a.jpg +{{ end }} +``` + +## Page resource + +With a [page resource], the `Name` method returns the path to the resource, relative to the page bundle. + +```text +content/ +├── posts/ +│ ├── post-1/ +│ │ ├── images/ +│ │ │ └── a.jpg +│ │ └── index.md +│ └── _index.md +└── _index.md +``` + +```go-html-template +{{ with .Resources.Get "images/a.jpg" }} + {{ .Name }} → images/a.jpg +{{ end }} +``` + +If you create an element in the `resources` array in front matter, the `Name` method returns the value of the `name` parameter: + +{{< code-toggle file=content/posts/post-1.md fm=true >}} +title = 'Post 1' +[[resources]] +src = 'images/a.jpg' +name = 'cat' +title = 'Felix the cat' +[resources.params] +temperament = 'malicious' +{{< /code-toggle >}} + +```go-html-template +{{ with .Resources.Get "cat" }} + {{ .Name }} → cat +{{ end }} +``` +## Remote resource + +With a [remote resource], the `Name` method returns a hashed file name. + +```go-html-template +{{ with resources.GetRemote "https://example.org/images/a.jpg" }} + {{ .Name }} → a_18432433023265451104.jpg +{{ end }} +``` + +[global resource]: /getting-started/glossary/#global-resource +[page resource]: /getting-started/glossary/#page-resource +[remote resource]: /getting-started/glossary/#remote-resource diff --git a/docs/content/en/methods/resource/Params.md b/docs/content/en/methods/resource/Params.md new file mode 100644 index 000000000..275182c46 --- /dev/null +++ b/docs/content/en/methods/resource/Params.md @@ -0,0 +1,65 @@ +--- +title: Params +description: Returns a map of resource parameters as defined in front matter. +categories: [] +keywords: [] +action: + related: [] + returnType: map + signatures: [RESOURCE.Params] +--- + +Use the `Params` method with [page resources]. It is not applicable to either [global] or [remote] resources. + +[global]: /getting-started/glossary/#global-resource +[page resources]: /getting-started/glossary/#page-resource +[remote]: /getting-started/glossary/#remote-resource + +With this content structure: + +```text +content/ +├── posts/ +│ ├── cats/ +│ │ ├── images/ +│ │ │ └── a.jpg +│ │ └── index.md +│ └── _index.md +└── _index.md +``` + +And this front matter: + +{{< code-toggle file=content/posts/cats.md fm=true >}} +title = 'Cats' +[[resources]] + src = 'images/a.jpg' + title = 'Felix the cat' + [resources.params] + alt = 'Photograph of black cat' + temperament = 'vicious' +{{< /code-toggle >}} + +And this template: + +```go-html-template +{{ with .Resources.Get "images/a.jpg" }} + <figure> + <img alt="{{ .Params.alt }}" src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}"> + <figcaption>{{ .Title }} is {{ .Params.temperament }}</figcaption> + </figure> +{{ end }} +``` + +Hugo renders: + +```html +<figure> + <img alt="Photograph of black cat" src="/posts/post-1/images/a.jpg" width="600" height="400"> + <figcaption>Felix the cat is vicious</figcaption> +</figure> +``` + +See the [page resources] section for more information. + +[page resources]: /content-management/page-resources diff --git a/docs/content/en/methods/resource/Permalink.md b/docs/content/en/methods/resource/Permalink.md new file mode 100644 index 000000000..ab0ad41b0 --- /dev/null +++ b/docs/content/en/methods/resource/Permalink.md @@ -0,0 +1,25 @@ +--- +title: Permalink +description: Publishes the given resource and returns its permalink. +categories: [] +keywords: [] +action: + related: + - methods/resource/RelPermalink + - methods/resource/Publish + - methods/resource/Key + returnType: string + signatures: [RESOURCE.Permalink] +--- + +The `Permalink` method on a `Resource` object writes the resource to the publish directory, typically `public`, and returns its [permalink]. + +[permalink]: /getting-started/glossary/#permalink + +```go-html-template +{{ with resources.Get "images/a.jpg" }} + {{ .Permalink }} → https://example.org/images/a.jpg +{{ end }} +``` + +{{% include "methods/resource/_common/global-page-remote-resources.md" %}} diff --git a/docs/content/en/methods/resource/Process.md b/docs/content/en/methods/resource/Process.md new file mode 100644 index 000000000..3c88492df --- /dev/null +++ b/docs/content/en/methods/resource/Process.md @@ -0,0 +1,66 @@ +--- +title: Process +description: Applicable to images, returns an image resource processed with the given specification. +categories: [] +keywords: [] +action: + related: + - methods/resource/Crop + - methods/resource/Fit + - methods/resource/Fill + - methods/resource/Resize + - functions/images/Process + returnType: images.ImageResource + signatures: [RESOURCE.Process SPEC] +toc: true +--- + +Process an image with the given specification. The specification can contain an optional action, one of `crop`, `fill`, `fit`, or `resize`. This means that you can use this method instead of [`Crop`], [`Fill`], [`Fit`], or [`Resize`]. + +```go-html-template +{{ with resources.Get "images/original.jpg" }} + {{ with .Process "crop 200x200" }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> + {{ end }} +{{ end }} +``` + +You can also use this method to apply simple transformations such as rotation and conversion: + +```go-html-template +{{/* Rotate 90 degrees counter-clockwise. */}} +{{ $image := $image.Process "r90" }} + +{{/* Convert to WebP. */}} +{{ $image := $image.Process "webp" }} +``` + +The `Process` method is also available as a filter, which is more effective if you need to apply multiple filters to an image. See [`images.Process`]. + +{{% include "methods/resource/_common/global-page-remote-resources.md" %}} + +{{% include "/methods/resource/_common/processing-spec.md" %}} + +## Example + +```go-html-template +{{ with resources.Get "images/original.jpg" }} + {{ with .Process "crop 200x200 topright webp q85 lanczos" }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> + {{ end }} +{{ end }} +``` + +{{< img + src="images/examples/zion-national-park.jpg" + alt="Zion National Park" + filter="Process" + filterArgs="crop 200x200 topright webp q85 lanczos" + example=true +>}} + +[`Crop`]: /methods/resource/crop +[`Fill`]: /methods/resource/fill +[`Fit`]: /methods/resource/fit +[`Resize`]: /methods/resource/resize +[`images.Process`]: /functions/images/process diff --git a/docs/content/en/methods/resource/Publish.md b/docs/content/en/methods/resource/Publish.md new file mode 100644 index 000000000..b090bfe5a --- /dev/null +++ b/docs/content/en/methods/resource/Publish.md @@ -0,0 +1,35 @@ +--- +title: Publish +description: Publishes the given resource. +categories: [] +keywords: [] +action: + related: + - methods/resource/Permalink + - methods/resource/RelPermalink + - methods/resource/Key + returnType: nil + signatures: [RESOURCE.Publish] +--- + +The `Publish` method on a `Resource` object writes the resource to the publish directory, typically `public`. + +```go-html-template +{{ with resources.Get "images/a.jpg" }} + {{ .Publish }} +{{ end }} +``` + +The `Permalink` and `RelPermalink` methods also publish a resource. `Publish` is a convenience method for publishing without a return value. For example, this: + +```go-html-template +{{ $resource.Publish }} +``` + +Instead of this: + +```go-html-template +{{ $noop := $resource.Permalink }} +``` + +{{% include "methods/resource/_common/global-page-remote-resources.md" %}} diff --git a/docs/content/en/methods/resource/RelPermalink.md b/docs/content/en/methods/resource/RelPermalink.md new file mode 100644 index 000000000..2b96c35d7 --- /dev/null +++ b/docs/content/en/methods/resource/RelPermalink.md @@ -0,0 +1,25 @@ +--- +title: RelPermalink +description: Publishes the given resource and returns its relative permalink. +categories: [] +keywords: [] +action: + related: + - methods/resource/Permalink + - methods/resource/Publish + - methods/resource/Key + returnType: string + signatures: [RESOURCE.RelPermalink] +--- + +The `Permalink` method on a `Resource` object writes the resource to the publish directory, typically `public`, and returns its [relative permalink]. + +[relative permalink]: /getting-started/glossary/#relative-permalink + +```go-html-template +{{ with resources.Get "images/a.jpg" }} + {{ .RelPermalink }} → /images/a.jpg +{{ end }} +``` + +{{% include "methods/resource/_common/global-page-remote-resources.md" %}} diff --git a/docs/content/en/methods/resource/Resize.md b/docs/content/en/methods/resource/Resize.md new file mode 100644 index 000000000..4ba054bb5 --- /dev/null +++ b/docs/content/en/methods/resource/Resize.md @@ -0,0 +1,49 @@ +--- +title: Resize +description: Applicable to images, returns an image resource resized to the given width and/or height. +categories: [] +keywords: [] +action: + related: + - methods/resource/Crop + - methods/resource/Fit + - methods/resource/Fill + - methods/resource/Process + - functions/images/Process + returnType: images.ImageResource + signatures: [RESOURCE.Resize SPEC] +--- + +Resize an image to the given width and/or height. + +If you specify both width and height, the resulting image will be disproportionally scaled unless the original image has the same aspect ratio. + +```go-html-template +{{ with resources.Get "images/original.jpg" }} + {{ with .Resize "300x" }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> + {{ end }} +{{ end }} +``` + +{{% include "methods/resource/_common/global-page-remote-resources.md" %}} + +{{% include "/methods/resource/_common/processing-spec.md" %}} + +## Example + +```go-html-template +{{ with resources.Get "images/original.jpg" }} + {{ with .Resize "300x webp q85 lanczos" }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> + {{ end }} +{{ end }} +``` + +{{< img + src="images/examples/zion-national-park.jpg" + alt="Zion National Park" + filter="Process" + filterArgs="resize 300x webp q85 lanczos" + example=true +>}} diff --git a/docs/content/en/methods/resource/ResourceType.md b/docs/content/en/methods/resource/ResourceType.md new file mode 100644 index 000000000..db52e7b10 --- /dev/null +++ b/docs/content/en/methods/resource/ResourceType.md @@ -0,0 +1,43 @@ +--- +title: ResourceType +description: Returns the main type of the given resource's media type. +categories: [] +keywords: [] +action: + related: [] + returnType: string + signatures: [RESOURCE.ResourceType] +--- + +Common resource types include `audio`, `image`, `text`, and `video`. + +```go-html-template +{{ with resources.Get "image/a.jpg" }} + {{ .ResourceType }} → image + {{ .MediaType.MainType }} → image +{{ end }} +``` + +When working with content files, the resource type is `page`. + +```text +content/ +├── lessons/ +│ ├── lesson-1/ +│ │ ├── _objectives.md <-- resource type = page +│ │ ├── _topics.md <-- resource type = page +│ │ ├── _example.jpg <-- resource type = image +│ │ └── index.md +│ └── _index.md +└── _index.md +``` + +With the structure above, we can range through page resources of type `page` to build content: + +{{< code file=layouts/lessons/single.html >}} +{{ range .Resources.ByType "page" }} + {{ .Content }} +{{ end }} +{{< /code >}} + +{{% include "methods/resource/_common/global-page-remote-resources.md" %}} diff --git a/docs/content/en/methods/resource/Title.md b/docs/content/en/methods/resource/Title.md new file mode 100644 index 000000000..e30f86d2e --- /dev/null +++ b/docs/content/en/methods/resource/Title.md @@ -0,0 +1,95 @@ +--- +title: Title +description: Returns the title of the given resource as optionally defined in front matter, falling back to a relative path or hashed file name depending on resource type. +categories: [] +keywords: [] +action: + related: + - methods/resource/Name + returnType: string + signatures: [RESOURCE.Title] +toc: true +--- + +The value returned by the `Title` method on a `Resource` object depends on the resource type. + +## Global resource + +With a [global resource], the `Title` method returns the path to the resource, relative to the assets directory. + +```text +assets/ +└── images/ + └── a.jpg +``` + +```go-html-template +{{ with resources.Get "images/a.jpg" }} + {{ .Title }} → images/a.jpg +{{ end }} +``` + +## Page resource + +With a [page resource], the `Title` method returns the path to the resource, relative to the page bundle. + +```text +content/ +├── posts/ +│ ├── post-1/ +│ │ ├── images/ +│ │ │ └── a.jpg +│ │ └── index.md +│ └── _index.md +└── _index.md +``` + +```go-html-template +{{ with .Resources.Get "images/a.jpg" }} + {{ .Title }} → images/a.jpg +{{ end }} +``` + +If you create an element in the `resources` array in front matter, the `Title` method returns the value of the `title` parameter: + +{{< code-toggle file=content/posts/post-1.md fm=true >}} +title = 'Post 1' +[[resources]] +src = 'images/a.jpg' +name = 'cat' +title = 'Felix the cat' +[resources.params] +temperament = 'malicious' +{{< /code-toggle >}} + +```go-html-template +{{ with .Resources.Get "cat" }} + {{ .Title }} → Felix the cat +{{ end }} +``` + +If the page resource is a content file, the `Title` methods return the `title` field as defined in front matter. + +```text +content/ +├── lessons/ +│ ├── lesson-1/ +│ │ ├── _objectives.md <-- resource type = page +│ │ └── index.md +│ └── _index.md +└── _index.md +``` + +## Remote resource + +With a [remote resource], the `Title` method returns a hashed file name. + +```go-html-template +{{ with resources.GetRemote "https://example.org/images/a.jpg" }} + {{ .Title }} → a_18432433023265451104.jpg +{{ end }} +``` + +[global resource]: /getting-started/glossary/#global-resource +[page resource]: /getting-started/glossary/#page-resource +[remote resource]: /getting-started/glossary/#remote-resource diff --git a/docs/content/en/methods/resource/Width.md b/docs/content/en/methods/resource/Width.md new file mode 100644 index 000000000..8b96c95e8 --- /dev/null +++ b/docs/content/en/methods/resource/Width.md @@ -0,0 +1,27 @@ +--- +title: Width +description: Applicable to images, returns the width of the given resource. +categories: [] +keywords: [] +action: + related: + - methods/resource/Height + returnType: int + signatures: [RESOURCE.Width] +--- + +```go-html-template +{{ with resources.Get "images/a.jpg" }} + {{ .Width }} → 600 +{{ end }} +``` + +Use the `Width` and `Height` methods together when rendering an `img` element: + +```go-html-template +{{ with resources.Get "images/a.jpg" }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}"> +{{ end }} +``` + +{{% include "methods/resource/_common/global-page-remote-resources.md" %}} diff --git a/docs/content/en/methods/resource/_common/_index.md b/docs/content/en/methods/resource/_common/_index.md new file mode 100644 index 000000000..47d5812fb --- /dev/null +++ b/docs/content/en/methods/resource/_common/_index.md @@ -0,0 +1,13 @@ +--- +cascade: + _build: + list: never + publishResources: false + render: never +--- + +<!-- +Files within this headless branch bundle are markdown snippets. Each file must contain front matter delimiters, though front matter fields are not required. + +Include the rendered content using the "include" shortcode. +--> diff --git a/docs/content/en/methods/resource/_common/global-page-remote-resources.md b/docs/content/en/methods/resource/_common/global-page-remote-resources.md new file mode 100644 index 000000000..4ea4d1b87 --- /dev/null +++ b/docs/content/en/methods/resource/_common/global-page-remote-resources.md @@ -0,0 +1,13 @@ +--- +# Do not remove front matter. +--- + +{{% note %}} + +Use this method with [global], [page], or [remote] resources. + +[global]: /getting-started/glossary/#global-resource +[page]: /getting-started/glossary/#page-resource +[remote]: /getting-started/glossary/#remote-resource + +{{% /note %}} diff --git a/docs/content/en/methods/resource/_common/processing-spec.md b/docs/content/en/methods/resource/_common/processing-spec.md new file mode 100644 index 000000000..b12a21d3a --- /dev/null +++ b/docs/content/en/methods/resource/_common/processing-spec.md @@ -0,0 +1,36 @@ +--- +# Do not remove front matter. +--- + +## Process specification + +The process specification is a space-delimited, case-insensitive list of one or more of the following in any sequence: + +action +: Applicable to the [`Process`](/methods/resource/process) method only. Specify zero or one of `crop`, `fill`, `fit`, or `resize`. If you specify an action you must also provide dimensions. + +dimensions +: Provide width _or_ height when using the [`Resize`](/methods/resource/resize) method, else provide both width _and_ height. See [details](/content-management/image-processing/#dimensions). + +anchor +: Use with the [`Crop`](/methods/resource/crop) and [`Fill`](/methods/resource/fill) methods. Specify zero or one of `TopLeft`, `Top`, `TopRight`, `Left`, `Center`, `Right`, `BottomLeft`, `Bottom`, `BottomRight`, or `Smart`. Default is `Smart`. See [details](/content-management/image-processing/#anchor). + +rotation +: Typically specify zero or one of `r90`, `r180`, or `r270`. Also supports arbitrary rotation angles. See [details](/content-management/image-processing/#rotation). + +target format +: Specify zero or one of `gif`, `jpeg`, `png`, `tiff`, or `webp`. See [details](/content-management/image-processing/#target-format). + +quality +: Applicable to JPEG and WebP images. Optionally specify `qN` where `N` is an integer in the range [0, 100]. Default is `75`. See [details](/content-management/image-processing/#quality). + +hint +: Applicable to WebP images and equivalent to the `-preset` flag for the [`cwebp`] encoder. Specify zero or one of `drawing`, `icon`, `photo`, `picture`, or `text`. Default is `photo`. See [details](/content-management/image-processing/#hint). + +[`cwebp`]: https://developers.google.com/speed/webp/docs/cwebp + +background color +: When converting a PNG or WebP with transparency to a format that does not support transparency, optionally specify a background color using a 3-digit or a 6-digit hexadecimal color code. Default is `#ffffff` (white). See [details](/content-management/image-processing/#background-color). + +resampling filter +: Typically specify zero or one of `Box`, `Lanczos`, `CatmullRom`, `MitchellNetravali`, `Linear`, or `NearestNeighbor`. Other resampling filters are available. See [details](/content-management/image-processing/#resampling-filter). diff --git a/docs/content/en/methods/resource/_index.md b/docs/content/en/methods/resource/_index.md new file mode 100644 index 000000000..e9426e1a5 --- /dev/null +++ b/docs/content/en/methods/resource/_index.md @@ -0,0 +1,12 @@ +--- +title: Resource methods +linkTitle: Resource +description: Use these methods with global, page, and remote Resource objects. +categories: [] +keywords: [] +menu: + docs: + parent: methods +--- + +Use these methods with global, page, and remote Resource objects. diff --git a/docs/content/en/methods/shortcode/Get.md b/docs/content/en/methods/shortcode/Get.md new file mode 100644 index 000000000..cd674614f --- /dev/null +++ b/docs/content/en/methods/shortcode/Get.md @@ -0,0 +1,51 @@ +--- +title: Get +description: Returns the value of the given parameter. +categories: [] +keywords: [] +action: + related: + - methods/shortcode/IsNamedParams + - methods/shortcode/Params + returnType: any + signatures: [SHORTCODE.Get PARAM] +toc: true +--- + +Specify the parameter by position or by name. When calling a shortcode within markdown, use either positional or named parameters, but not both. + +{{% note %}} +Some shortcodes support positional parameters, some support named parameters, and others support both. Refer to the shortcode's documentation for usage details. +{{% /note %}} + +## Positional parameters + +This shortcode call uses positional parameters: + +{{< code file=content/about.md lang=md >}} +{{</* myshortcode "Hello" "world" */>}} +{{< /code >}} + +To retrieve parameters by position: + +{{< code file=layouts/shortcodes/myshortcode.html >}} +{{ printf "%s %s." (.Get 0) (.Get 1) }} → Hello world. +{{< /code >}} + +## Named parameters + +This shortcode call uses named parameters: + +{{< code file=content/about.md lang=md >}} +{{</* myshortcode greeting="Hello" firstName="world" */>}} +{{< /code >}} + +To retrieve parameters by name: + +{{< code file=layouts/shortcodes/myshortcode.html >}} +{{ printf "%s %s." (.Get "greeting") (.Get "firstName") }} → Hello world. +{{< /code >}} + +{{% note %}} +Parameter names are case-sensitive. +{{% /note %}} diff --git a/docs/content/en/methods/shortcode/Inner.md b/docs/content/en/methods/shortcode/Inner.md new file mode 100644 index 000000000..de7c284cb --- /dev/null +++ b/docs/content/en/methods/shortcode/Inner.md @@ -0,0 +1,153 @@ +--- +title: Inner +description: Returns the content between opening and closing shortcode tags, applicable when the shortcode call includes a closing tag. +categories: [] +keywords: [] +action: + related: + - functions/strings/Trim + - methods/page/RenderString + - functions/transform/Markdownify + - methods/shortcode/InnerDeindent + returnType: template.HTML + signatures: [SHORTCODE.Inner] +--- + +This content: + +{{< code file=content/services.md lang=md >}} +{{</* card title="Product Design" */>}} +We design the **best** widgets in the world. +{{</* /card */>}} +{{< /code >}} + +With this shortcode: + +{{< code file=layouts/shortcodes/card.html >}} +<div class="card"> + {{ with .Get "title" }} + <div class="card-title">{{ . }}</div> + {{ end }} + <div class="card-content"> + {{ trim .Inner "\r\n" }} + </div> +</div> +{{< /code >}} + +Is rendered to: + +```html +<div class="card"> + <div class="card-title">Product Design</div> + <div class="card-content"> + We design the **best** widgets in the world. + </div> +</div> +``` + +{{% note %}} +Content between opening and closing shortcode tags may include leading and/or trailing newlines, depending on placement within the markdown. Use the [`trim`] function as shown above to remove both carriage returns and newlines. + +[`trim`]: /functions/strings/trim +{{% /note %}} + +{{% note %}} +In the example above, the value returned by `Inner` is markdown, but it was rendered as plain text. Use either of the following approaches to render markdown to HTML. +{{% /note %}} + + +## Use the RenderString method + +Let's modify the example above to pass the value returned by `Inner` through the [`RenderString`] method on the `Page` object: + +[`RenderString`]: /methods/page/renderstring + +{{< code file=layouts/shortcodes/card.html >}} +<div class="card"> + {{ with .Get "title" }} + <div class="card-title">{{ . }}</div> + {{ end }} + <div class="card-content"> + {{ trim .Inner "\r\n" | .Page.RenderString }} + </div> +</div> +{{< /code >}} + +Hugo renders this to: + +```html +<div class="card"> + <div class="card-title">Product design</div> + <div class="card-content"> + We produce the <strong>best</strong> widgets in the world. + </div> +</div> +``` + +You can use the [`markdownify`] function instead of the `RenderString` method, but the latter is more flexible. See [details]. + +[details]: /methods/page/renderstring +[`markdownify`]: /functions/transform/markdownify + +## Use alternate notation + +Instead of calling the shortcode with the `{{</* */>}}` notation, use the `{{%/* */%}}` notation: + +{{< code file=content/services.md lang=md >}} +{{%/* card title="Product Design" */%}} +We design the **best** widgets in the world. +{{%/* /card */%}} +{{< /code >}} + +When you use the `{{%/* */%}}` notation, Hugo renders the entire shortcode as markdown, requiring the following changes. + +First, configure the renderer to allow raw HTML within markdown: + +{{< code-toggle file=hugo >}} +[markup.goldmark.renderer] +unsafe = true +{{< /code-toggle >}} + +This configuration is not unsafe if _you_ control the content. Read more about Hugo's [security model]. + +Second, because we are rendering the entire shortcode as markdown, we must adhere to the rules governing [indentation] and inclusion of [raw HTML blocks] as provided in the [CommonMark] specification. + +{{< code file=layouts/shortcodes/card.html >}} +<div class="card"> + {{ with .Get "title" }} + <div class="card-title">{{ . }}</div> + {{ end }} + <div class="card-content"> + + {{ trim .Inner "\r\n" }} + </div> +</div> +{{< /code >}} + +The difference between this and the previous example is subtle but required. Note the change in indentation, the addition of a blank line, and removal of the `RenderString` method. + +```diff +--- layouts/shortcodes/a.html ++++ layouts/shortcodes/b.html +@@ -1,8 +1,9 @@ + <div class="card"> + {{ with .Get "title" }} +- <div class="card-title">{{ . }}</div> ++ <div class="card-title">{{ . }}</div> + {{ end }} + <div class="card-content"> +- {{ trim .Inner "\r\n" | .Page.RenderString }} ++ ++ {{ trim .Inner "\r\n" }} + </div> + </div> +``` + +{{% note %}} +When using the `{{%/* */%}}` notation, do not pass the value returned by `Inner` through the `RenderString` method or the `markdownify` function. +{{% /note %}} + +[commonmark]: https://commonmark.org/ +[indentation]: https://spec.commonmark.org/0.30/#indented-code-blocks +[raw html blocks]: https://spec.commonmark.org/0.30/#html-blocks +[security model]: /about/security-model/ diff --git a/docs/content/en/methods/shortcode/InnerDeindent.md b/docs/content/en/methods/shortcode/InnerDeindent.md new file mode 100644 index 000000000..136412bc7 --- /dev/null +++ b/docs/content/en/methods/shortcode/InnerDeindent.md @@ -0,0 +1,99 @@ +--- +title: InnerDeindent +description: Returns the content between opening and closing shortcode tags, with indentation removed, applicable when the shortcode call includes a closing tag. +categories: [] +keywords: [] +action: + related: + - methods/shortcode/Inner + returnType: template.HTML + signatures: [SHORTCODE.InnerDeindent] +--- + +Similar to the [`Inner`] method, `InnerDeindent` returns the content between opening and closing shortcode tags. However, with `InnerDeindent`, indentation before the content is removed. + +This allows us to effectively bypass the rules governing [indentation] as provided in the [CommonMark] specification. + +Consider this markdown, an unordered list with a small gallery of thumbnail images within each list item: + +{{< code file=content/about.md lang=md >}} +- Gallery one + + {{</* gallery */>}} +  +  + {{</* /gallery */>}} + +- Gallery two + + {{</* gallery */>}} +  +  + {{</* /gallery */>}} +{{< /code >}} + +In the example above, notice that the content between the opening and closing shortcode tags is indented by four spaces. Per the CommonMark specification, this is treated as an indented code block. + +With this shortcode, calling `Inner` instead of `InnerDeindent`: + +{{< code file=layouts/shortcodes/gallery.html >}} +<div class="gallery"> + {{ trim .Inner "\r\n" | .Page.RenderString }} +</div> +{{< /code >}} + +Hugo renders the markdown to: + +```html +<ul> + <li> + <p>Gallery one</p> + <div class="gallery"> + <pre><code> +  + </code></pre> + </div> + </li> + <li> + <p>Gallery two</p> + <div class="gallery"> + <pre><code> +  + </code></pre> + </div> + </li> +</ul> +``` + +Although technically correct per the CommonMark specification, this is not what we want. If we remove the indentation using the `InnerDeindent` method: + +{{< code file=layouts/shortcodes/gallery.html >}} +<div class="gallery"> + {{ trim .InnerDeindent "\r\n" | .Page.RenderString }} +</div> +{{< /code >}} + +Hugo renders the markdown to: + +```html +<ul> + <li> + <p>Gallery one</p> + <div class="gallery"> + <img src="images/a.jpg" alt="kitten a"> + <img src="images/b.jpg" alt="kitten b"> + </div> + </li> + <li> + <p>Gallery two</p> + <div class="gallery"> + <img src="images/c.jpg" alt="kitten c"> + <img src="images/d.jpg" alt="kitten d"> + </div> + </li> +</ul> +``` + +[commonmark]: https://commonmark.org/ +[indentation]: https://spec.commonmark.org/0.30/#indented-code-blocks +[`Inner`]: /methods/shortcode/inner diff --git a/docs/content/en/methods/shortcode/IsNamedParams.md b/docs/content/en/methods/shortcode/IsNamedParams.md new file mode 100644 index 000000000..83eeb2f74 --- /dev/null +++ b/docs/content/en/methods/shortcode/IsNamedParams.md @@ -0,0 +1,30 @@ +--- +title: IsNamedParams +description: Reports whether the shortcode call uses named parameters. +categories: [] +keywords: [] +action: + related: + - methods/shortcode/Get + returnType: bool + signatures: [SHORTCODE.IsNamedParams] +--- + +To support both positional and named parameters when calling a shortcode, use the `IsNamedParams` method to determine how the shortcode was called. + +With this shortcode template: + +{{< code file=layouts/shortcodes/myshortcode.html >}} +{{ if .IsNamedParams }} + {{ printf "%s %s." (.Get "greeting") (.Get "firstName") }} +{{ else }} + {{ printf "%s %s." (.Get 0) (.Get 1) }} +{{ end }} +{{< /code >}} + +Both of these calls return the same value: + +{{< code file=content/about.md lang=md >}} +{{</* myshortcode greeting="Hello" firstName="world" */>}} +{{</* myshortcode "Hello" "world" */>}} +{{< /code >}} diff --git a/docs/content/en/methods/shortcode/Name.md b/docs/content/en/methods/shortcode/Name.md new file mode 100644 index 000000000..18bddfe1f --- /dev/null +++ b/docs/content/en/methods/shortcode/Name.md @@ -0,0 +1,29 @@ +--- +title: Name +description: Returns the shortcode file name, excluding the file extension. +categories: [] +keywords: [] +action: + related: + - methods/shortcode/Position + - functions/fmt/Errorf + returnType: string + signatures: [SHORTCODE.Name] +--- + +The `Name` method is useful for error reporting. For example, if your shortcode requires a "greeting" parameter: + +{{< code file=layouts/shortcodes/myshortcode.html >}} +{{ $greeting := "" }} +{{ with .Get "greeting" }} + {{ $greeting = . }} +{{ else }} + {{ errorf "The %q shortcode requires a 'greeting' parameter. See %s" .Name .Position }} +{{ end }} +{{< /code >}} + +In the absence of a "greeting" parameter, Hugo will throw an error message and fail the build: + +```text +ERROR The "myshortcode" shortcode requires a 'greeting' parameter. See "/home/user/project/content/about.md:11:1" +``` diff --git a/docs/content/en/methods/shortcode/Ordinal.md b/docs/content/en/methods/shortcode/Ordinal.md new file mode 100644 index 000000000..954940258 --- /dev/null +++ b/docs/content/en/methods/shortcode/Ordinal.md @@ -0,0 +1,50 @@ +--- +title: Ordinal +description: Returns the zero-based ordinal of the shortcode in relation to its parent. +categories: [] +keywords: [] +action: + related: [] + returnType: int + signatures: [SHORTCODE.Ordinal] +--- + +The `Ordinal` method returns the zero-based ordinal of the shortcode in relation to its parent. If the parent is the page itself, the ordinal represents the position of this shortcode in the page content. + +This method is useful for, among other things, assigning unique element IDs when a shortcode is called two or more times from the same page. For example: + +{{< code file=content/about.md lang=md >}} +{{</* img src="images/a.jpg" */>}} + +{{</* img src="images/b.jpg" */>}} +{{< /code >}} + +This shortcode performs error checking, then renders an HTML `img` element with a unique `id` attribute: + +{{< code file=layouts/shortcodes/img.html >}} +{{ $src := "" }} +{{ with .Get "src" }} + {{ $src = . }} + {{ with resources.Get $src }} + {{ $id := printf "img-%03d" $.Ordinal }} + <img id="{{ $id }}" src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> + {{ else }} + {{ errorf "The %q shortcode was unable to find %s. See %s" $.Name $src $.Position }} + {{ end }} +{{ else }} + {{ errorf "The %q shortcode requires a 'src' parameter. See %s" .Name .Position }} +{{ end }} +{{< /code >}} + +Hugo renders the page to: + +```html +<img id="img-000" src="/images/a.jpg" width="600" height="400" alt=""> +<img id="img-001" src="/images/b.jpg" width="600" height="400" alt=""> +``` + +{{% note %}} +In the shortcode template above, the [`with`] statement is used to create conditional blocks. Remember that the `with` statement binds context (the dot) to its expression. Inside of a `with` block, preface shortcode method calls with a `$` to access the top level context passed into the template. + +[`with`]: /functions/go-template/with +{{% /note %}} diff --git a/docs/content/en/methods/shortcode/Page.md b/docs/content/en/methods/shortcode/Page.md new file mode 100644 index 000000000..8bb58fa18 --- /dev/null +++ b/docs/content/en/methods/shortcode/Page.md @@ -0,0 +1,36 @@ +--- +title: Page +description: Returns the Page object from which the shortcode was called. +categories: [] +keywords: [] +action: + related: [] + returnType: hugolib.pageForShortcode + signatures: [SHORTCODE.Page] +--- + +With this content: + +{{< code-toggle file=content/books/les-miserables.md fm=true >}} +title = 'Les Misérables' +author = 'Victor Hugo' +publication_year = 1862 +isbn = '978-0451419439' +{{< /code-toggle >}} + +Calling this shortcode: + +```text +{{</* book-details */>}} +``` + +We can access the front matter values using the `Page` method: + +{{< code file=layouts/shortcodes/book-details.html >}} +<ul> + <li>Title: {{ .Page.Title }}</li> + <li>Author: {{ .Page.Params.author }}</li> + <li>Published: {{ .Page.Params.publication_year }}</li> + <li>ISBN: {{ .Page.Params.isbn }}</li> +</ul> +{{< /code >}} diff --git a/docs/content/en/methods/shortcode/Params.md b/docs/content/en/methods/shortcode/Params.md new file mode 100644 index 000000000..63df768a6 --- /dev/null +++ b/docs/content/en/methods/shortcode/Params.md @@ -0,0 +1,33 @@ +--- +title: Params +description: Returns a collection of the shortcode parameters. +categories: [] +keywords: [] +action: + related: + - methods/shortcode/Get + returnType: any + signatures: [SHORTCODE.Params] +--- + +When you call a shortcode using positional parameters, the `Params` method returns a slice. + +{{< code file=content/about.md lang=md >}} +{{</* myshortcode "Hello" "world" */>}} +{{< /code >}} + +{{< code file=layouts/shortcodes/myshortcode.html >}} +{{ index .Params 0 }} → Hello +{{ index .Params 1 }} → world +{{< /code >}} + +When you call a shortcode using named parameters, the `Params` method returns a map. + +{{< code file=content/about.md lang=md >}} +{{</* myshortcode greeting="Hello" name="world" */>}} +{{< /code >}} + +{{< code file=layouts/shortcodes/myshortcode.html >}} +{{ .Params.greeting }} → Hello +{{ .Params.name }} → world +{{< /code >}} diff --git a/docs/content/en/methods/shortcode/Parent.md b/docs/content/en/methods/shortcode/Parent.md new file mode 100644 index 000000000..50ae521da --- /dev/null +++ b/docs/content/en/methods/shortcode/Parent.md @@ -0,0 +1,50 @@ +--- +title: Parent +description: Returns the parent shortcode context in nested shortcodes. +categories: [] +keywords: [] +action: + related: [] + returnType: hugolib.ShortcodeWithPage + signatures: [SHORTCODE.Parent] +--- + +This is useful for inheritance of common shortcode parameters from the root. + +In this contrived example, the "greeting" shortcode is the parent, and the "now" shortcode is child. + +{{< code file=content/welcome.md lang=md >}} +{{</* greeting dateFormat="Jan 2, 2006" */>}} +Welcome. Today is {{</* now */>}}. +{{</* /greeting */>}} +{{< /code >}} + +{{< code file=layouts/shortcodes/greeting.html >}} +<div class="greeting"> + {{ trim .Inner "\r\n" | .Page.RenderString }} +</div> +{{< /code >}} + +{{< code file=layouts/shortcodes/now.html >}} +{{- $dateFormat := "January 2, 2006 15:04:05" }} + +{{- with .Params }} + {{- with .dateFormat }} + {{- $dateFormat = . }} + {{- end }} +{{- else }} + {{- with .Parent.Params }} + {{- with .dateFormat }} + {{- $dateFormat = . }} + {{- end }} + {{- end }} +{{- end }} + +{{- now | time.Format $dateFormat -}} +{{< /code >}} + +The "now" shortcode formats the current time using: + +1. The `dateFormat` parameter passed to the "now" shortcode, if present +2. The `dateFormat` parameter passed to the "greeting" shortcode, if present +3. The default layout string defined at the top of the shortcode diff --git a/docs/content/en/methods/shortcode/Position.md b/docs/content/en/methods/shortcode/Position.md new file mode 100644 index 000000000..565a158bf --- /dev/null +++ b/docs/content/en/methods/shortcode/Position.md @@ -0,0 +1,33 @@ +--- +title: Position +description: Returns the filename and position from which the shortcode was called. +categories: [] +keywords: [] +action: + related: + - methods/shortcode/Name + - functions/fmt/Errorf + returnType: text.Position + signatures: [SHORTCODE.Position] +--- + +The `Position` method is useful for error reporting. For example, if your shortcode requires a "greeting" parameter: + +{{< code file=layouts/shortcodes/myshortcode.html >}} +{{ $greeting := "" }} +{{ with .Get "greeting" }} + {{ $greeting = . }} +{{ else }} + {{ errorf "The %q shortcode requires a 'greeting' parameter. See %s" .Name .Position }} +{{ end }} +{{< /code >}} + +In the absence of a "greeting" parameter, Hugo will throw an error message and fail the build: + +```text +ERROR The "myshortcode" shortcode requires a 'greeting' parameter. See "/home/user/project/content/about.md:11:1" +``` + +{{% note %}} +The position can be expensive to calculate. Limit its use to error reporting. +{{% /note %}} diff --git a/docs/content/en/methods/shortcode/Ref.md b/docs/content/en/methods/shortcode/Ref.md new file mode 100644 index 000000000..293c772d9 --- /dev/null +++ b/docs/content/en/methods/shortcode/Ref.md @@ -0,0 +1,44 @@ +--- +title: Ref +description: Returns the absolute URL of the page with the given path, language, and output format. +categories: [] +keywords: [] +action: + related: + - methods/shortcode/RelRef + - functions/urls/RelRef + - functions/urls/Ref + returnType: string + signatures: [SHORTCODE.Ref OPTIONS] +--- + +The map of option contains: + +path +: (`string`) The path to the page, relative to the content directory. Required. + +lang +: (`string`) The language (site) to search for the page. Default is the current language. Optional. + +outputFormat +: (`string`) The output format to search for the page. Default is the current output format. Optional. + +The examples below show the rendered output when visiting a page on the English language version of the site: + +```go-html-template +{{ $opts := dict "path" "/books/book-1" }} +{{ .Ref $opts }} → https://example.org/en/books/book-1/ + +{{ $opts := dict "path" "/books/book-1" "lang" "de" }} +{{ .Ref $opts }} → https://example.org/de/books/book-1/ + +{{ $opts := dict "path" "/books/book-1" "lang" "de" "outputFormat" "json" }} +{{ .Ref $opts }} → https://example.org/de/books/book-1/index.json +``` + +By default, Hugo will throw an error and fail the build if it cannot resolve the path. You can change this to a warning in your site configuration, and specify a URL to return when the path cannot be resolved. + +{{< code-toggle file=hugo >}} +refLinksErrorLevel = 'warning' +refLinksNotFoundURL = '/some/other/url' +{{< /code-toggle >}} diff --git a/docs/content/en/methods/shortcode/RelRef.md b/docs/content/en/methods/shortcode/RelRef.md new file mode 100644 index 000000000..07f221a99 --- /dev/null +++ b/docs/content/en/methods/shortcode/RelRef.md @@ -0,0 +1,44 @@ +--- +title: RelRef +description: Returns the relative URL of the page with the given path, language, and output format. +categories: [] +keywords: [] +action: + related: + - methods/shortcode/Ref + - functions/urls/Ref + - functions/urls/RelRef + returnType: string + signatures: [SHORTCODE.RelRef OPTIONS] +--- + +The map of option contains: + +path +: (`string`) The path to the page, relative to the content directory. Required. + +lang +: (`string`) The language (site) to search for the page. Default is the current language. Optional. + +outputFormat +: (`string`) The output format to search for the page. Default is the current output format. Optional. + +The examples below show the rendered output when visiting a page on the English language version of the site: + +```go-html-template +{{ $opts := dict "path" "/books/book-1" }} +{{ .RelRef $opts }} → /en/books/book-1/ + +{{ $opts := dict "path" "/books/book-1" "lang" "de" }} +{{ .RelRef $opts }} → /de/books/book-1/ + +{{ $opts := dict "path" "/books/book-1" "lang" "de" "outputFormat" "json" }} +{{ .RelRef $opts }} → /de/books/book-1/index.json +``` + +By default, Hugo will throw an error and fail the build if it cannot resolve the path. You can change this to a warning in your site configuration, and specify a URL to return when the path cannot be resolved. + +{{< code-toggle file=hugo >}} +refLinksErrorLevel = 'warning' +refLinksNotFoundURL = '/some/other/url' +{{< /code-toggle >}} diff --git a/docs/content/en/methods/shortcode/Scratch.md b/docs/content/en/methods/shortcode/Scratch.md new file mode 100644 index 000000000..3ab195a3f --- /dev/null +++ b/docs/content/en/methods/shortcode/Scratch.md @@ -0,0 +1,24 @@ +--- +title: Scratch +description: Creates a "scratch pad" scoped to the shortcode to store and manipulate data. +categories: [] +keywords: [] +action: + related: + - functions/collections/NewScratch + returnType: maps.Scratch + signatures: [SHORTCODE.Scratch] +--- + +The `Scratch` method within a shortcode creates a [scratch pad] to store and manipulate data. The scratch pad is scoped to the shortcode, and is reset on server rebuilds. + +{{% note %}} +With the introduction of the [`newScratch`] function, and the ability to [assign values to template variables] after initialization, the `Scratch` method within a shortcode is obsolete. + +[assign values to template variables]: https://go.dev/doc/go1.11#text/template +[`newScratch`]: functions/collections/newscratch +{{% /note %}} + +[scratch pad]: /getting-started/glossary/#scratch-pad + +{{% include "methods/page/_common/scratch-methods.md" %}} diff --git a/docs/content/en/methods/shortcode/Site.md b/docs/content/en/methods/shortcode/Site.md new file mode 100644 index 000000000..fa2d274de --- /dev/null +++ b/docs/content/en/methods/shortcode/Site.md @@ -0,0 +1,19 @@ +--- +title: Site +description: Returns the Site object. +categories: [] +keywords: [] +action: + related: + - methods/page/Sites + returnType: page.siteWrapper + signatures: [SHORTCODE.Site] +--- + +See [Site methods]. + +[Site methods]: /methods/site + +```go-html-template +{{ .Site.Title }} +``` diff --git a/docs/content/en/methods/shortcode/_index.md b/docs/content/en/methods/shortcode/_index.md new file mode 100644 index 000000000..d26366844 --- /dev/null +++ b/docs/content/en/methods/shortcode/_index.md @@ -0,0 +1,12 @@ +--- +title: Shortcode methods +linkTitle: Shortcode +description: Use these methods in your shortcode templates. +categories: [] +keywords: [] +menu: + docs: + parent: methods +--- + +Use these methods in your shortcode templates. diff --git a/docs/content/en/methods/site/AllPages.md b/docs/content/en/methods/site/AllPages.md new file mode 100644 index 000000000..8df6348f9 --- /dev/null +++ b/docs/content/en/methods/site/AllPages.md @@ -0,0 +1,26 @@ +--- +title: AllPages +description: Returns a collection of all pages in all languages. +categories: [] +keywords: [] +action: + related: + - methods/site/Pages + - methods/site/RegularPages + - methods/site/Sections + returnType: page.Pages + signatures: [SITE.AllPages] +--- + +This method returns all page [kinds] in all languages. That includes the home page, section pages, taxonomy pages, term pages, and regular pages. + +In most cases you should use the [`RegularPages`] method instead. + +[`RegularPages`]: methods/site/regularpages +[kinds]: /getting-started/glossary/#page-kind + +```go-html-template +{{ range .Site.AllPages }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +``` diff --git a/docs/content/en/methods/site/BaseURL.md b/docs/content/en/methods/site/BaseURL.md new file mode 100644 index 000000000..f9c43bca3 --- /dev/null +++ b/docs/content/en/methods/site/BaseURL.md @@ -0,0 +1,37 @@ +--- +title: BaseURL +description: Returns the base URL as defined in the site configuration. +categories: [] +keywords: [] +action: + related: + - functions/urls/AbsURL + - functions/urls/AbsLangURL + - functions/urls/RelURL + - functions/urls/RelLangURL + returnType: string + signatures: [SITE.BaseURL] +--- + +Site configuration: + +{{< code-toggle file=hugo >}} +baseURL = 'https://example.org/docs/' +{{< /code-toggle >}} + +Template: + +```go-html-template +{{ .Site.BaseURL }} → https://example.org/docs/ +``` + +{{% note %}} +There is almost never a good reason to use this method in your templates. Its usage tends to be fragile due to misconfiguration. + +Use the [`absURL`], [`absLangURL`], [`relURL`], or [`relLangURL`] functions instead. + +[`absURL`]: /functions/urls/absURL +[`absLangURL`]: /functions/urls/absLangURL +[`relURL`]: /functions/urls/relURL +[`relLangURL`]: /functions/urls/relLangURL +{{% /note %}} diff --git a/docs/content/en/methods/site/BuildDrafts.md b/docs/content/en/methods/site/BuildDrafts.md new file mode 100644 index 000000000..0d85c78fd --- /dev/null +++ b/docs/content/en/methods/site/BuildDrafts.md @@ -0,0 +1,28 @@ +--- +title: BuildDrafts +description: Reports whether the current build includes draft pages. +categories: [] +keywords: [] +action: + related: [] + returnType: bool + signatures: [SITE.BuildDrafts] +--- + +By default, draft pages are not published when building a site. You can change this behavior with a command line flag: + +```sh +hugo --buildDrafts +``` + +Or by setting `buildDrafts` to `true` in your site configuration: + +{{< code-toggle file=hugo >}} +buildDrafts = true +{{< /code-toggle >}} + +Use the `BuildDrafts` method on a `Site` object to determine the current configuration: + +```go-html-template +{{ .Site.BuildDrafts }} → true +``` diff --git a/docs/content/en/methods/site/Config.md b/docs/content/en/methods/site/Config.md new file mode 100644 index 000000000..0ff4cddec --- /dev/null +++ b/docs/content/en/methods/site/Config.md @@ -0,0 +1,57 @@ +--- +title: Config +description: Returns a subset of the site configuration. +categories: [] +keywords: [] +action: + related: [] + returnType: page.SiteConfig + signatures: [SITE.Config] +toc: true +--- + +The `Config` method on a `Site` object provides access to a subset of the site configuration, specifically the `services` and `privacy` keys. + +## Services + +These are the default service settings, typically used by Hugo's built-in templates and shortcodes. + +{{< code-toggle config=services />}} + +For example, to use Hugo's built-in Google Analytics template you must add a [Google tag ID]: + +[Google tag ID]: https://support.google.com/tagmanager/answer/12326985?hl=en + +{{< code-toggle file=hugo >}} +[services.googleAnalytics] +id = 'G-XXXXXXXXX' +{{< /code-toggle >}} + +To access this value from a template: + +```go-html-template +{{ .Site.Config.Services.GoogleAnalytics.ID }} → G-XXXXXXXXX +``` + +You must capitalize each identifier as shown above. + +## Privacy + +These are the default privacy settings, typically used by Hugo's built-in templates and shortcodes: + +{{< code-toggle config=privacy />}} + +For example, to disable usage of the built-in YouTube shortcode: + +{{< code-toggle file=hugo >}} +[privacy.youtube] +disable = true +{{< /code-toggle >}} + +To access this value from a template: + +```go-html-template +{{ .Site.Config.Privacy.YouTube.Disable }} → true +``` + +You must capitalize each identifier as shown above. diff --git a/docs/content/en/methods/site/Copyright.md b/docs/content/en/methods/site/Copyright.md new file mode 100644 index 000000000..e2ae7d2a5 --- /dev/null +++ b/docs/content/en/methods/site/Copyright.md @@ -0,0 +1,22 @@ +--- +title: Copyright +description: Returns the copyright notice as defined in the site configuration. +categories: [] +keywords: [] +action: + related: [] + returnType: string + signatures: [SITE.Copyright] +--- + +Site configuration: + +{{< code-toggle file=hugo >}} +copyright = '© 2023 ABC Widgets, Inc.' +{{< /code-toggle >}} + +Template: + +```go-html-template +{{ .Site.Copyright }} → © 2023 ABC Widgets, Inc. +``` diff --git a/docs/content/en/methods/site/Data.md b/docs/content/en/methods/site/Data.md new file mode 100644 index 000000000..b78caddec --- /dev/null +++ b/docs/content/en/methods/site/Data.md @@ -0,0 +1,108 @@ +--- +title: Data +description: Returns a data structure composed from the files in the data directory. +categories: [] +keywords: [] +action: + related: + - functions/collections/IndexFunction + - functions/transform/Unmarshal + - functions/collections/Where + - functions/collections/Sort + returnType: map + signatures: [SITE.Data] +--- + +Use the `Data` method on a `Site` object to access data within the data directory, or within any directory [mounted] to the data directory. Supported data formats include JSON, TOML, YAML, and XML. + +[mounted]: /hugo-modules/configuration/#module-configuration-mounts + +{{% note %}} +Although Hugo can unmarshal CSV files with the [`transform.Unmarshal`] function, do not place CSV files in the data directory. You cannot access data within CSV files using this method. + +[`transform.Unmarshal`]: /functions/transform/unmarshal +{{% /note %}} + +Consider this data directory: + +```text +data/ +├── books/ +│ ├── fiction.yaml +│ └── nonfiction.yaml +├── films.json +├── paintings.xml +└── sculptures.toml +``` + +And these data files: + +{{< code file=data/books/fiction.yaml lang=yaml >}} +- title: The Hunchback of Notre Dame + author: Victor Hugo + isbn: 978-0140443530 +- title: Les Misérables + author: Victor Hugo + isbn: 978-0451419439 +{{< /code >}} + +{{< code file=data/books/nonfiction.yaml lang=yaml >}} +- title: The Ancien Régime and the Revolution + author: Alexis de Tocqueville + isbn: 978-0141441641 +- title: Interpreting the French Revolution + author: François Furet + isbn: 978-0521280495 +{{< /code >}} + +Access the data by [chaining] the [identifiers]: + +```go-html-template +{{ range $category, $books := .Site.Data.books }} + <p>{{ $category | title }}</p> + <ul> + {{ range $books }} + <li>{{ .title }} ({{ .isbn }})</li> + {{ end }} + </ul> +{{ end }} +``` + +Hugo renders this to: + +```html +<p>Fiction</p> +<ul> + <li>The Hunchback of Notre Dame (978-0140443530)</li> + <li>Les Misérables (978-0451419439)</li> +</ul> +<p>Nonfiction</p> +<ul> + <li>The Ancien Régime and the Revolution (978-0141441641)</li> + <li>Interpreting the French Revolution (978-0521280495)</li> +</ul> +``` + +To limit the listing to fiction, and sort by title: + +```go-html-template +<ul> + {{ range sort .Site.Data.books.fiction "title" }} + <li>{{ .title }} ({{ .author }})</li> + {{ end }} +</ul> +``` + +To find a fiction book by ISBN: + +```go-html-template +{{ range where .Site.Data.books.fiction "isbn" "978-0140443530" }} + <li>{{ .title }} ({{ .author }})</li> +{{ end }} +``` + +In the template examples above, each of the keys is a valid identifier. For example, none of the keys contains a hyphen. To access a key that is not a valid identifier, use the [`index`] function: + +[`index`]: /functions/collections/indexfunction +[chaining]: /getting-started/glossary/#chain +[identifiers]: /getting-started/glossary/#identifier diff --git a/docs/content/en/methods/site/DisqusShortname.md b/docs/content/en/methods/site/DisqusShortname.md new file mode 100644 index 000000000..2d4447485 --- /dev/null +++ b/docs/content/en/methods/site/DisqusShortname.md @@ -0,0 +1,17 @@ +--- +title: DisqusShortname +description: Returns the Disqus shortname as defined in the site configuration. +categories: [] +keywords: [] +action: + related: [] + returnType: string + signatures: [SITE.DisqusShortname] +expiryDate: 2024-10-30 # deprecated 2023-10-30 +--- + +{{% deprecated-in 0.120.0 %}} +Use [`Site.Config.Services.Disqus.Shortname`] instead. + +[`Site.Config.Services.Disqus.Shortname`]: /methods/site/config +{{% /deprecated-in %}} diff --git a/docs/content/en/methods/site/GetPage.md b/docs/content/en/methods/site/GetPage.md new file mode 100644 index 000000000..b7d4b8f32 --- /dev/null +++ b/docs/content/en/methods/site/GetPage.md @@ -0,0 +1,109 @@ +--- +title: GetPage +description: Returns a Page object from the given path. +categories: [] +keywords: [] +action: + related: + - methods/page/GetPage + returnType: page.Page + signatures: [SITE.GetPage PATH] +toc: true +--- + +The `GetPage` method is also available on `Page` objects, allowing you to specify a path relative to the current page. See [details]. + +[details]: /methods/page/getpage + +When using the `GetPage` method on a `Site` object, specify a path relative to the content directory. + +If Hugo cannot resolve the path to a page, the method returns nil. + +Consider this content structure: + +```text +content/ +├── works/ +│ ├── paintings/ +│ │ ├── _index.md +│ │ ├── starry-night.md +│ │ └── the-mona-lisa.md +│ ├── sculptures/ +│ │ ├── _index.md +│ │ ├── david.md +│ │ └── the-thinker.md +│ └── _index.md +└── _index.md +``` + +This home page template: + +```go-html-template +{{ with .Site.GetPage "/works/paintings" }} + <ul> + {{ range .Pages }} + <li>{{ .Title }} by {{ .Params.artist }}</li> + {{ end }} + </ul> +{{ end }} +``` + +Is rendered to: + +```html +<ul> + <li>Starry Night by Vincent van Gogh</li> + <li>The Mona Lisa by Leonardo da Vinci</li> +</ul> +``` + +To get a regular page instead of a section page: + +```go-html-template +{{ with .Site.GetPage "/works/paintings/starry-night" }} + {{ .Title }} → Starry Night + {{ .Params.artist }} → Vincent van Gogh +{{ end }} +``` + +## Multilingual projects + +With multilingual projects, the `GetPage` method on a `Site` object resolves the given path to a page in the current language. + +To get a page from a different language, query the `Sites` object: + +```go-html-template +{{ with where .Site.Sites "Language.Lang" "eq" "de" }} + {{ with index . 0 }} + {{ with .GetPage "/works/paintings/starry-night" }} + {{ .Title }} → Sternenklare Nacht + {{ end }} + {{ end }} +{{ end }} +``` + +## Page bundles + +Consider this content structure: + +```text +content/ +├── headless/ +│ ├── a.jpg +│ ├── b.jpg +│ ├── c.jpg +│ └── index.md <-- front matter: headless = true +└── _index.md +``` + +In the home page template, use the `GetPage` method on a `Site` object to render all the images in the headless [page bundle]: + +```go-html-template +{{ with .Site.GetPage "/headless" }} + {{ range .Resources.ByType "image" }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> + {{ end }} +{{ end }} +``` + +[page bundle]: /getting-started/glossary/#page-bundle diff --git a/docs/content/en/methods/site/GoogleAnalytics.md b/docs/content/en/methods/site/GoogleAnalytics.md new file mode 100644 index 000000000..50f479b49 --- /dev/null +++ b/docs/content/en/methods/site/GoogleAnalytics.md @@ -0,0 +1,17 @@ +--- +title: GoogleAnalytics +description: Returns the Google Analytics tracking ID as defined in the site configuration. +categories: [] +keywords: [] +action: + related: [] + returnType: string + signatures: [SITE.GoogleAnalytics] +expiryDate: 2024-10-30 # deprecated 2023-10-30 +--- + +{{% deprecated-in 0.120.0 %}} +Use [`Site.Config.Services.GoogleAnalytics.ID`] instead. + +[`Site.Config.Services.GoogleAnalytics.ID`]: /methods/site/config +{{% /deprecated-in %}} diff --git a/docs/content/en/methods/site/Home.md b/docs/content/en/methods/site/Home.md new file mode 100644 index 000000000..a25491a8e --- /dev/null +++ b/docs/content/en/methods/site/Home.md @@ -0,0 +1,25 @@ +--- +title: Home +description: Returns the home Page object for the given site. +categories: [] +keywords: [] +action: + related: [] + returnType: page.Page + signatures: [SITE.Home] +--- + +This method is useful for obtaining a link to the home page. + +Site configuration: + +{{< code-toggle file=hugo >}} +baseURL = 'https://example.org/docs/' +{{< /code-toggle >}} + +Template: + +```go-html-template +{{ .Site.Home.Permalink }} → https://example.org/docs/ +{{ .Site.Home.RelPermalink }} → /docs/ +``` diff --git a/docs/content/en/methods/site/IsDevelopment.md b/docs/content/en/methods/site/IsDevelopment.md new file mode 100644 index 000000000..c009ba0de --- /dev/null +++ b/docs/content/en/methods/site/IsDevelopment.md @@ -0,0 +1,21 @@ +--- +title: IsDevelopment +description: Reports whether the current running environment is “development”. +categories: [] +keywords: [] +action: + related: [] + returnType: bool + signatures: [SITE.IsDevelopment] +expiryDate: 2024-10-30 # deprecated 2023-10-30 +--- + +{{% deprecated-in 0.120.0 %}} +Use [`hugo.IsDevelopment`] instead. + +[`hugo.IsDevelopment`]: /functions/hugo/isdevelopment +{{% /deprecated-in %}} + +```go-html-template +{{ .Site.IsDevelopment }} → true/false +``` diff --git a/docs/content/en/methods/site/IsMultiLingual.md b/docs/content/en/methods/site/IsMultiLingual.md new file mode 100644 index 000000000..61cc5e462 --- /dev/null +++ b/docs/content/en/methods/site/IsMultiLingual.md @@ -0,0 +1,34 @@ +--- +title: IsMultiLingual +description: Reports whether the site is multilingual. +categories: [] +keywords: [] +action: + related: [] + returnType: bool + signatures: [SITE.IsMultiLingual] +--- + +Site configuration: + +{{< code-toggle file=hugo >}} +defaultContentLanguage = 'de' +defaultContentLanguageInSubdir = true +[languages] + [languages.de] + languageCode = 'de-DE' + languageName = 'Deutsch' + title = 'Projekt Dokumentation' + weight = 1 + [languages.en] + languageCode = 'en-US' + languageName = 'English' + title = 'Project Documentation' + weight = 2 +{{< /code-toggle >}} + +Template: + +```go-html-template +{{ .Site.IsMultiLingual }} → true +``` diff --git a/docs/content/en/methods/site/IsServer.md b/docs/content/en/methods/site/IsServer.md new file mode 100644 index 000000000..3d5ce41b5 --- /dev/null +++ b/docs/content/en/methods/site/IsServer.md @@ -0,0 +1,21 @@ +--- +title: IsServer +description: Reports whether the built-in development server is running. +categories: [] +keywords: [] +action: + related: [] + returnType: bool + signatures: [SITE.IsServer] +expiryDate: 2024-10-30 # deprecated 2023-10-30 +--- + +{{% deprecated-in 0.120.0 %}} +Use [`hugo.IsServer`] instead. + +[`hugo.IsServer`]: /functions/hugo/isserver +{{% /deprecated-in %}} + +```go-html-template +{{ .Site.IsServer }} → true/false +``` diff --git a/docs/content/en/methods/site/Language.md b/docs/content/en/methods/site/Language.md new file mode 100644 index 000000000..1babc099b --- /dev/null +++ b/docs/content/en/methods/site/Language.md @@ -0,0 +1,83 @@ +--- +title: Language +description: Returns the language object for the given site. +categories: [] +keywords: [] +action: + related: + - methods/page/language + returnType: langs.Language + signatures: [SITE.Language] +toc: true +--- + +The `Language` method on a `Site` object returns the language object for the given site. The language object points to the language definition in the site configuration. + +You can also use the `Language` method on a `Page` object. See [details]. + +## Methods + +The examples below assume the following in your site configuration: + +{{< code-toggle file=hugo >}} +[languages.de] +languageCode = 'de-DE' +languageDirection = 'ltr' +languageName = 'Deutsch' +weight = 1 +{{< /code-toggle >}} + +Lang +: (`string`) The language tag as defined by [RFC 5646]. + +```go-html-template +{{ .Site.Language.Lang }} → de +``` + +LanguageCode +: (`string`) The language code from the site configuration. + +```go-html-template +{{ .Site.Language.LanguageCode }} → de-DE +``` + +LanguageDirection +: (`string`) The language direction from the site configuration, either `ltr` or `rtl`. + +```go-html-template +{{ .Site.Language.LanguageDirection }} → ltr +``` + +LanguageName +: (`string`) The language name from the site configuration. + +```go-html-template +{{ .Site.Language.LanguageName }} → Deutsch +``` + +Weight +: (`int`) The language weight from the site configuration which determines its order in the slice of languages returned by the `Languages` method on a `Site` object. + +```go-html-template +{{ .Site.Language.Weight }} → 1 +``` + +## Example + +Some of the methods above are commonly used in a base template as attributes for the `html` element. + +```go-html-template +<html + lang="{{ or site.Language.LanguageCode site.Language.Lang }}" + dir="{{ or site.Language.LanguageDirection `ltr` }} +> +``` + +The example above uses the global [`site`] function instead of accessing the `Site` object via the `.Site` notation. + +Also note that each attribute has a fallback value assigned via the [`or`] operator. + +[details]: /methods/page/language +[RFC 5646]: https://datatracker.ietf.org/doc/html/rfc5646 +[`or`]: /functions/go-template/or +[`site`]: /functions/global/site diff --git a/docs/content/en/methods/site/LanguagePrefix.md b/docs/content/en/methods/site/LanguagePrefix.md new file mode 100644 index 000000000..88808eda0 --- /dev/null +++ b/docs/content/en/methods/site/LanguagePrefix.md @@ -0,0 +1,53 @@ +--- +title: LanguagePrefix +description: Returns the URL language prefix, if any, for the given site. +categories: [] +keywords: [] +action: + related: + - functions/urls/AbsLangURL + - functions/urls/RelLangURL + returnType: string + signatures: [SITE.LanguagePrefix] +--- + +Consider this site configuration: + +{{< code-toggle file=hugo >}} +defaultContentLanguage = 'de' +defaultContentLanguageInSubdir = false + +[languages.de] +languageCode = 'de-DE' +languageDirection = 'ltr' +languageName = 'Deutsch' +title = 'Projekt Dokumentation' +weight = 1 + +[languages.en] +languageCode = 'en-US' +languageDirection = 'ltr' +languageName = 'English' +title = 'Project Documentation' +weight = 2 +{{< /code-toggle >}} + +When visiting the German language site: + +```go-html-template +{{ .Site.LanguagePrefix }} → "" +``` + +When visiting the English language site: + +```go-html-template +{{ .Site.LanguagePrefix }} → /en +``` + +If you change `defaultContentLanguageInSubdir` to `true`, when visiting the German language site: + +```go-html-template +{{ .Site.LanguagePrefix }} → /de +``` + +You may use the `LanguagePrefix` method with both monolingual and multilingual sites. diff --git a/docs/content/en/methods/site/Languages.md b/docs/content/en/methods/site/Languages.md new file mode 100644 index 000000000..26bdefc21 --- /dev/null +++ b/docs/content/en/methods/site/Languages.md @@ -0,0 +1,59 @@ +--- +title: Languages +description: Returns a collection of language objects for all sites, ordered by language weight. +categories: [] +keywords: [] +action: + related: + - methods/site/Language + returnType: langs.Languages + signatures: [SITE.Languages] +--- + +The `Languages` method on a `Site` object returns a collection of language objects for all sites, ordered by language weight. Each language object points to its language definition in the site configuration. + +To view the data structure: + +```go-html-template +<pre>{{ jsonify (dict "indent" " ") .Site.Languages }}</pre> +``` + +With this site configuration: + +{{< code-toggle file=hugo >}} +defaultContentLanguage = 'de' +defaultContentLanguageInSubdir = false + +[languages.de] +languageCode = 'de-DE' +languageDirection = 'ltr' +languageName = 'Deutsch' +title = 'Projekt Dokumentation' +weight = 1 + +[languages.en] +languageCode = 'en-US' +languageDirection = 'ltr' +languageName = 'English' +title = 'Project Documentation' +weight = 2 +{{< /code-toggle >}} + +This template: + +```go-html-template +<ul> + {{ range .Site.Languages }} + <li>{{ .Title }} ({{ .LanguageName }})</li> + {{ end }} +</ul> +``` + +Is rendered to: + +```html +<ul> + <li>Projekt Dokumentation (Deutsch)</li> + <li>Project Documentation (English)</li> +</ul> +``` diff --git a/docs/content/en/methods/site/LastChange.md b/docs/content/en/methods/site/LastChange.md new file mode 100644 index 000000000..aceee691d --- /dev/null +++ b/docs/content/en/methods/site/LastChange.md @@ -0,0 +1,21 @@ +--- +title: LastChange +description: Returns the last modification date of site content. +categories: [] +keywords: [] +action: + related: [] + returnType: time.Time + signatures: [SITE.LastChange] +--- + +The `LastChange` method on a `Site` object returns a [`time.Time`] value. Use this with time [functions] and [methods]. For example: + +```go-html-template +{{ .Site.LastChange | time.Format ":date_long" }} → October 16, 2023 + +``` + +[`time.Time`]: https://pkg.go.dev/time#Time +[functions]: /functions/time +[methods]: /methods/time diff --git a/docs/content/en/methods/site/MainSections.md b/docs/content/en/methods/site/MainSections.md new file mode 100644 index 000000000..251fe1a97 --- /dev/null +++ b/docs/content/en/methods/site/MainSections.md @@ -0,0 +1,55 @@ +--- +title: MainSections +description: Returns a slice of the main section names as defined in the site configuration, falling back to the top level section with the most pages. +categories: [] +keywords: [] +action: + related: [] + returnType: '[]string' + signatures: [SITE.MainSections] +--- + +Site configuration: + +{{< code-toggle file=hugo >}} +[params] +mainSections = ['books','films'] +{{< /code-toggle >}} + +Template: + +```go-html-template +{{ .Site.MainSections }} → [books films] +``` + +If `params.mainSections` is not defined in the site configuration, this method returns a slice with one element---the top level section with the most pages. + +With this content structure, the "films" section has the most pages: + +```text +content/ +├── books/ +│ ├── book-1.md +│ └── book-2.md +├── films/ +│ ├── film-1.md +│ ├── film-2.md +│ └── film-3.md +└── _index.md +``` + +Template: + +```go-html-template +{{ .Site.MainSections }} → [films] +``` + +When creating a theme, instead of hardcoding section names when listing the most relevant pages on the front page, instruct site authors to set `params.mainSections` in their site configuration. + +Then your home page template can do something like this: + +```go-html-template +{{ range where .Site.RegularPages "Section" "in" .Site.MainSections }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +``` diff --git a/docs/content/en/methods/site/Menus.md b/docs/content/en/methods/site/Menus.md new file mode 100644 index 000000000..c204fe97b --- /dev/null +++ b/docs/content/en/methods/site/Menus.md @@ -0,0 +1,94 @@ +--- +title: Menus +description: Returns a collection of menu objects for the given site. +categories: [] +keywords: [] +action: + related: + - methods/page/IsMenuCurrent + - methods/page/HasMenuCurrent + returnType: navigation.Menus + signatures: [SITE.Menus] +--- + +The `Menus` method on a `Site` object returns a collection of menus, where each menu contains one or more entries, either flat or nested. Each entry points to a page within the site, or to an external resource. + +{{% note %}} +Menus can be defined and localized in several ways. Please see the [menus] section for a complete explanation and examples. + +[menus]: /content-management/menus/ +{{% /note %}} + +A site can have multiple menus. For example, a main menu and a footer menu: + +{{< code-toggle file=hugo >}} +[[menus.main]] +name = 'Home' +pageRef = '/' +weight = 10 + +[[menus.main]] +name = 'Books' +pageRef = '/books' +weight = 20 + +[[menus.main]] +name = 'Films' +pageRef = '/films' +weight = 30 + +[[menus.footer]] +name = 'Legal' +pageRef = '/legal' +weight = 10 + +[[menus.footer]] +name = 'Privacy' +pageRef = '/privacy' +weight = 20 +{{< /code-toggle >}} + +This template renders the main menu: + +```go-html-template +{{ with site.Menus.main }} + <nav class="menu"> + {{ range . }} + {{ if $.IsMenuCurrent .Menu . }} + <a class="active" aria-current="page" href="{{ .URL }}">{{ .Name }}</a> + {{ else }} + <a href="{{ .URL }}">{{ .Name }}</a> + {{ end }} + {{ end }} + </nav> +{{ end }} +``` + +When viewing the home page, the result is: + +```html +<nav class="menu"> + <a class="active" aria-current="page" href="/">Home</a> + <a href="/books/">Books</a> + <a href="/films/">Films</a> +</nav> +``` + +When viewing the "books" page, the result is: + +```html +<nav class="menu"> + <a href="/">Home</a> + <a class="active" aria-current="page" href="/books/">Books</a> + <a href="/films/">Films</a> +</nav> +``` + +You will typically render a menu using a partial template. As the active menu entry will be different on each page, use the [`partial`] function to call the template. Do not use the [`partialCached`] function. + +The example above is simplistic. Please see the [menu templates] section for more information. + +[menu templates]: /templates/menu-templates + +[`partial`]: /functions/partials/include +[`partialCached`]: /functions/partials/includecached diff --git a/docs/content/en/methods/site/Pages.md b/docs/content/en/methods/site/Pages.md new file mode 100644 index 000000000..583e98c11 --- /dev/null +++ b/docs/content/en/methods/site/Pages.md @@ -0,0 +1,26 @@ +--- +title: Pages +description: Returns a collection of all pages. +categories: [] +keywords: [] +action: + related: + - methods/site/AllPages + - methods/site/RegularPages + - methods/site/Sections + returnType: page.Pages + signatures: [SITE.Pages] +--- + +This method returns all page [kinds] in the current language. That includes the home page, section pages, taxonomy pages, term pages, and regular pages. + +In most cases you should use the [`RegularPages`] method instead. + +[`RegularPages`]: methods/site/regularpages +[kinds]: /getting-started/glossary/#page-kind + +```go-html-template +{{ range .Site.Pages }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +``` diff --git a/docs/content/en/methods/site/Param.md b/docs/content/en/methods/site/Param.md new file mode 100644 index 000000000..b699ef2d4 --- /dev/null +++ b/docs/content/en/methods/site/Param.md @@ -0,0 +1,29 @@ +--- +title: Param +description: Returns the site parameter with the given key. +categories: [] +keywords: [] +action: + related: [] + returnType: any + signatures: [SITE.Param KEY] +--- + +The `Param` method on a `Site` object is a convenience method to return the value of a user-defined parameter in the site configuration. + +{{< code-toggle file=hugo >}} +[params] +display_toc = true +{{< /code-toggle >}} + + +```go-html-template +{{ .Site.Param "display_toc" }} → true +``` + +The above is equivalent to either of these: + +```go-html-template +{{ .Site.Params.display_toc }} +{{ index .Site.Params "display_toc" }} +``` diff --git a/docs/content/en/methods/site/Params.md b/docs/content/en/methods/site/Params.md new file mode 100644 index 000000000..518d93bf3 --- /dev/null +++ b/docs/content/en/methods/site/Params.md @@ -0,0 +1,47 @@ +--- +title: Params +description: Returns a map of custom parameters as defined in the site configuration. +categories: [] +keywords: [] +action: + related: + - functions/collections/indexFunction + - methods/page/Params + - methods/page/Param + returnType: maps.Params + signatures: [SITE.Params] +--- + +With this site configuration: + +{{< code-toggle file=hugo >}} +[params] + subtitle = 'The Best Widgets on Earth' + copyright-year = '2023' + [params.author] + email = 'jsmith@example.org' + name = 'John Smith' + [params.layouts] + rfc_1123 = 'Mon, 02 Jan 2006 15:04:05 MST' + rfc_3339 = '2006-01-02T15:04:05-07:00' +{{< /code-toggle >}} + +Access the custom parameters by [chaining] the [identifiers]: + +```go-html-template +{{ .Site.Params.subtitle }} → The Best Widgets on Earth +{{ .Site.Params.author.name }} → John Smith + +{{ $layout := .Site.Params.layouts.rfc_1123 }} +{{ .Site.LastChange.Format $layout }} → Tue, 17 Oct 2023 13:21:02 PDT +``` + +In the template example above, each of the keys is a valid identifier. For example, none of the keys contains a hyphen. To access a key that is not a valid identifier, use the [`index`] function: + +```go-html-template +{{ index .Site.Params "copyright-year" }} → 2023 +``` + +[`index`]: /functions/collections/indexfunction +[chaining]: /getting-started/glossary/#chain +[identifiers]: /getting-started/glossary/#identifier diff --git a/docs/content/en/methods/site/RegularPages.md b/docs/content/en/methods/site/RegularPages.md new file mode 100644 index 000000000..b163ad919 --- /dev/null +++ b/docs/content/en/methods/site/RegularPages.md @@ -0,0 +1,38 @@ +--- +title: RegularPages +description: Returns a collection of all regular pages. +categories: [] +keywords: [] +action: + related: + - methods/site/AllPages + - methods/site/RegularPages + - methods/site/Sections + returnType: page.Pages + signatures: [SITE.RegularPages] +--- + +```go-html-template +{{ range .Site.RegularPages }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +``` + +By default, Hugo sorts page collections by: + +1. The page `weight` as defined in front matter +1. The page `date` as defined in front matter +1. The page `linkTitle` as defined in front matter +1. The file path + +If the `linkTitle` is not defined, Hugo evaluates the `title` instead. + +To change the sort order, use any of the `Pages` [sorting methods]. For example: + +```go-html-template +{{ range .Site.RegularPages.ByTitle }} + <h2><a href="{{ .RelPermalink }}">{{ .Title }}</a></h2> +{{ end }} +``` + +[sorting methods]: /methods/pages/ diff --git a/docs/content/en/methods/site/Sections.md b/docs/content/en/methods/site/Sections.md new file mode 100644 index 000000000..a397c5926 --- /dev/null +++ b/docs/content/en/methods/site/Sections.md @@ -0,0 +1,41 @@ +--- +title: Sections +description: Returns a collection of first level section pages. +categories: [] +keywords: [] +action: + related: + - methods/site/AllPages + - methods/site/Pages + - methods/site/RegularPages + returnType: page.Pages + signatures: [SITE.Sections] +--- + +Given this content structure: + +```text +content/ +├── books/ +│ ├── book-1.md +│ └── book-2.md +├── films/ +│ ├── film-1.md +│ └── film-2.md +└── _index.md +``` + +This template: + +```go-html-template +{{ range .Site.Sections }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +``` + +Is rendered to: + +```html +<h2><a href="/books/">Books</a></h2> +<h2><a href="/films/">Films</a></h2> +``` diff --git a/docs/content/en/methods/site/Sites.md b/docs/content/en/methods/site/Sites.md new file mode 100644 index 000000000..f7bafd3ed --- /dev/null +++ b/docs/content/en/methods/site/Sites.md @@ -0,0 +1,66 @@ +--- +title: Sites +description: Returns a collection of all Site objects, one for each language, ordered by language weight. +categories: [] +keywords: [] +action: + related: [] + returnType: page.Sites + signatures: [SITE.Sites] +--- + +With this site configuration: + +{{< code-toggle file=hugo >}} +defaultContentLanguage = 'de' +defaultContentLanguageInSubdir = false + +[languages.de] +languageCode = 'de-DE' +languageDirection = 'ltr' +languageName = 'Deutsch' +title = 'Projekt Dokumentation' +weight = 1 + +[languages.en] +languageCode = 'en-US' +languageDirection = 'ltr' +languageName = 'English' +title = 'Project Documentation' +weight = 2 +{{< /code-toggle >}} + +This template: + +```go-html-template +<ul> + {{ range .Site.Sites }} + <li><a href="{{ .Home.Permalink }}">{{ .Title }}</a></li> + {{ end }} +</ul> +``` + +Produces a list of links to each home page: + +```html +<ul> + <li><a href="https://example.org/de/">Projekt Dokumentation</a></li> + <li><a href="https://example.org/en/">Project Documentation</a></li> +</ul> +``` + +To render a link to home page of the primary (first) language: + +```go-html-template +{{ with .Site.Sites.First }} + <a href="{{ .Home.Permalink }}">{{ .Title }}</a> +{{ end }} +``` + +This is equivalent to: + +```go-html-template +{{ with index .Site.Sites 0 }} + <a href="{{ .Home.Permalink }}">{{ .Title }}</a> +{{ end }} +``` diff --git a/docs/content/en/methods/site/Taxonomies.md b/docs/content/en/methods/site/Taxonomies.md new file mode 100644 index 000000000..72bfc75d5 --- /dev/null +++ b/docs/content/en/methods/site/Taxonomies.md @@ -0,0 +1,99 @@ +--- +title: Taxonomies +description: Returns a data structure containing the site's taxonomy objects, the terms within each taxonomy object, and the pages to which the terms are assigned. +categories: [] +keywords: [] +action: + related: [] + returnType: page.TaxonomyList + signatures: [SITE.Taxonomies] +--- + +Conceptually, the `Taxonomies` method on a `Site` object returns a data structure such as: + +{{< code-toggle >}} +taxonomy a: + - term 1: + - page 1 + - page 2 + - term 2: + - page 1 +taxonomy b: + - term 1: + - page 2 + - term 2: + - page 1 + - page 2 +{{< /code-toggle >}} + +For example, on a book review site you might create two taxonomies; one for genres and another for authors. + +With this site configuration: + +{{< code-toggle file=hugo >}} +[taxonomies] +genre = 'genres' +author = 'authors' +{{< /code-toggle >}} + +And this content structure: + +```text +content/ +├── books/ +│ ├── and-then-there-were-none.md --> genres: suspense +│ ├── death-on-the-nile.md --> genres: suspense +│ └── jamaica-inn.md --> genres: suspense, romance +│ └── pride-and-prejudice.md --> genres: romance +└── _index.md +``` + +Conceptually, the taxonomies data structure looks like: + +{{< code-toggle >}} +genres: + - suspense: + - And Then There Were None + - Death on the Nile + - Jamaica Inn + - romance: + - Jamaica Inn + - Pride and Prejudice +authors: + - achristie: + - And Then There Were None + - Death on the Nile + - ddmaurier: + - Jamaica Inn + - jausten: + - Pride and Prejudice +{{< /code-toggle >}} + + +To list the "suspense" books: + +```go-html-template +<ul> + {{ range .Site.Taxonomies.genres.suspense }} + <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li> + {{ end }} +</ul> +``` + +Hugo renders this to: + +```html +<ul> + <li><a href="/books/and-then-there-were-none/">And Then There Were None</a></li> + <li><a href="/books/death-on-the-nile/">Death on the Nile</a></li> + <li><a href="/books/jamaica-inn/">Jamaica Inn</a></li> +</ul> +``` + +{{% note %}} +Hugo's taxonomy system is powerful, allowing you to classify content and create relationships between pages. + +Please see the [taxonomies] section for a complete explanation and examples. + +[taxonomies]: content-management/taxonomies/ +{{% /note %}} diff --git a/docs/content/en/methods/site/Title.md b/docs/content/en/methods/site/Title.md new file mode 100644 index 000000000..a357286c1 --- /dev/null +++ b/docs/content/en/methods/site/Title.md @@ -0,0 +1,22 @@ +--- +title: Title +description: Returns the title as defined in the site configuration. +categories: [] +keywords: [] +action: + related: [] + returnType: string + signatures: [SITE.Title] +--- + +Site configuration: + +{{< code-toggle file=hugo >}} +title = 'My Documentation Site' +{{< /code-toggle >}} + +Template: + +```go-html-template +{{ .Site.Title }} → My Documentation Site +``` diff --git a/docs/content/en/methods/site/_index.md b/docs/content/en/methods/site/_index.md new file mode 100644 index 000000000..39f66f308 --- /dev/null +++ b/docs/content/en/methods/site/_index.md @@ -0,0 +1,12 @@ +--- +title: Site methods +linkTitle: Site +description: Use these methods with Site objects. +categories: [] +keywords: [] +menu: + docs: + parent: methods +--- + +Use these methods with Site objects. A multilingual project will have two or more sites, one for each language. diff --git a/docs/content/en/methods/taxonomy/Alphabetical.md b/docs/content/en/methods/taxonomy/Alphabetical.md new file mode 100644 index 000000000..7845dbf3d --- /dev/null +++ b/docs/content/en/methods/taxonomy/Alphabetical.md @@ -0,0 +1,78 @@ +--- +title: Alphabetical +description: Returns an ordered taxonomy, sorted alphabetically by term. +categories: [] +keywords: [] +action: + related: + - methods/taxonomy/ByCount + returnType: page.OrderedTaxonomy + signatures: [TAXONOMY.Alphabetical] +toc: true +--- + +The `Alphabetical` method on a `Taxonomy` object returns an [ordered taxonomy], sorted alphabetically by [term]. + +While a `Taxonomy` object is a [map], an ordered taxonomy is a [slice], where each element is an object that contains the term and a slice of its [weighted pages]. + +{{% include "methods/taxonomy/_common/get-a-taxonomy-object.md" %}} + +## Get the ordered taxonomy + +Now that we have captured the “genres” Taxonomy object, let’s get the ordered taxonomy sorted alphabetically by term: + +```go-html-template +{{ $taxonomyObject.Alphabetical }} +``` + +To reverse the sort order: + +```go-html-template +{{ $taxonomyObject.Alphabetical.Reverse }} +``` + +To inspect the data structure: + +```go-html-template +<pre>{{ jsonify (dict "indent" " ") $taxonomyObject.Alphabetical }}</pre> +``` + +{{% include "methods/taxonomy/_common/ordered-taxonomy-element-methods.md" %}} + +## Example + +With this template: + +```go-html-template +{{ range $taxonomyObject.Alphabetical }} + <h2><a href="{{ .Page.RelPermalink }}">{{ .Page.LinkTitle }}</a> ({{ .Count }})</h2> + <ul> + {{ range .Pages.ByTitle }} + <li><a href="{{ .RelPermalink }}">{{ .Title }}</a></li> + {{ end }} + </ul> +{{ end }} +``` + +Hugo renders: + +```html +<h2><a href="/genres/romance/">romance</a> (2)</h2> +<ul> + <li><a href="/books/jamaica-inn/">Jamaica inn</a></li> + <li><a href="/books/pride-and-prejudice/">Pride and prejudice</a></li> +</ul> +<h2><a href="/genres/suspense/">suspense</a> (3)</h2> +<ul> + <li><a href="/books/and-then-there-were-none/">And then there were none</a></li> + <li><a href="/books/death-on-the-nile/">Death on the nile</a></li> + <li><a href="/books/jamaica-inn/">Jamaica inn</a></li> +</ul> +``` + +[ordered taxonomy]: /getting-started/glossary/#ordered-taxonomy +[term]: /getting-started/glossary/#term +[map]: /getting-started/glossary/#map +[slice]: /getting-started/glossary/#slice +[term]: /getting-started/glossary/#term +[weighted pages]: /getting-started/glossary/#weighted-page diff --git a/docs/content/en/methods/taxonomy/ByCount.md b/docs/content/en/methods/taxonomy/ByCount.md new file mode 100644 index 000000000..40f58420a --- /dev/null +++ b/docs/content/en/methods/taxonomy/ByCount.md @@ -0,0 +1,78 @@ +--- +title: ByCount +description: Returns an ordered taxonomy, sorted by the number of pages associated with each term. +categories: [] +keywords: [] +action: + related: + - methods/taxonomy/Alphabetical + returnType: page.OrderedTaxonomy + signatures: [TAXONOMY.ByCount] +toc: true +--- + +The `ByCount` method on a `Taxonomy` object returns an [ordered taxonomy], sorted by the number of pages associated with each [term]. + +While a `Taxonomy` object is a [map], an ordered taxonomy is a [slice], where each element is an object that contains the term and a slice of its [weighted pages]. + +{{% include "methods/taxonomy/_common/get-a-taxonomy-object.md" %}} + +## Get the ordered taxonomy + +Now that we have captured the “genres” Taxonomy object, let’s get the ordered taxonomy sorted by the number of pages associated with each term: + +```go-html-template +{{ $taxonomyObject.ByCount }} +``` + +To reverse the sort order: + +```go-html-template +{{ $taxonomyObject.ByCount.Reverse }} +``` + +To inspect the data structure: + +```go-html-template +<pre>{{ jsonify (dict "indent" " ") $taxonomyObject.ByCount }}</pre> +``` + +{{% include "methods/taxonomy/_common/ordered-taxonomy-element-methods.md" %}} + +## Example + +With this template: + +```go-html-template +{{ range $taxonomyObject.ByCount }} + <h2><a href="{{ .Page.RelPermalink }}">{{ .Page.LinkTitle }}</a> ({{ .Count }})</h2> + <ul> + {{ range .Pages.ByTitle }} + <li><a href="{{ .RelPermalink }}">{{ .Title }}</a></li> + {{ end }} + </ul> +{{ end }} +``` + +Hugo renders: + +```html +<h2><a href="/genres/suspense/">suspense</a> (3)</h2> +<ul> + <li><a href="/books/and-then-there-were-none/">And then there were none</a></li> + <li><a href="/books/death-on-the-nile/">Death on the nile</a></li> + <li><a href="/books/jamaica-inn/">Jamaica inn</a></li> +</ul> +<h2><a href="/genres/romance/">romance</a> (2)</h2> +<ul> + <li><a href="/books/jamaica-inn/">Jamaica inn</a></li> + <li><a href="/books/pride-and-prejudice/">Pride and prejudice</a></li> +</ul> +``` + +[ordered taxonomy]: /getting-started/glossary/#ordered-taxonomy +[term]: /getting-started/glossary/#term +[map]: /getting-started/glossary/#map +[slice]: /getting-started/glossary/#slice +[term]: /getting-started/glossary/#term +[weighted pages]: /getting-started/glossary/#weighted-page diff --git a/docs/content/en/methods/taxonomy/Count.md b/docs/content/en/methods/taxonomy/Count.md new file mode 100644 index 000000000..50f705ec9 --- /dev/null +++ b/docs/content/en/methods/taxonomy/Count.md @@ -0,0 +1,26 @@ +--- +title: Count +description: Returns the number of number of weighted pages to which the given term has been assigned. +categories: [] +keywords: [] +action: + related: [] + returnType: int + signatures: [TAXONOMY.Count TERM] +toc: true +--- + +The `Count` method on a `Taxonomy` object returns the number of number of [weighted pages] to which the given [term] has been assigned. + +{{% include "methods/taxonomy/_common/get-a-taxonomy-object.md" %}} + +## Count the weighted pages + +Now that we have captured the "genres" `Taxonomy` object, let's count the number of weighted pages to which the "suspense" term has been assigned: + +```go-html-template +{{ $taxonomyObject.Count "suspense" }} → 3 +``` + +[weighted pages]: /getting-started/glossary/#weighted-page +[term]: /getting-started/glossary/#term diff --git a/docs/content/en/methods/taxonomy/Get.md b/docs/content/en/methods/taxonomy/Get.md new file mode 100644 index 000000000..3bac86f08 --- /dev/null +++ b/docs/content/en/methods/taxonomy/Get.md @@ -0,0 +1,72 @@ +--- +title: Get +description: Returns a slice of weighted pages to which the given term has been assigned. +categories: [] +keywords: [] +action: + related: [] + returnType: page.WeightedPages + signatures: [TAXONOMY.Get TERM] +toc: true +--- + +The `Get` method on a `Taxonomy` object returns a slice of [weighted pages] to which the given [term] has been assigned. + +{{% include "methods/taxonomy/_common/get-a-taxonomy-object.md" %}} + +## Get the weighted pages + +Now that we have captured the "genres" `Taxonomy` object, let's get the weighted pages to which the "suspense" term has been assigned: + +```go-html-template +{{ $weightedPages := $taxonomyObject.Get "suspense" }} +``` + +The above is equivalent to: + +```go-html-template +{{ $weightedPages := $taxonomyObject.suspense }} +``` + +But, if the term is not a valid [identifier], you cannot use the [chaining] syntax. For example, this will throw an error because the identifier contains a hyphen: + +```go-html-template +{{ $weightedPages := $taxonomyObject.my-genre }} +``` + +You could also use the [`index`] function, but the syntax is more verbose: + +```go-html-template +{{ $weightedPages := index $taxonomyObject "my-genre" }} +``` + +To inspect the data structure: + +```go-html-template +<pre>{{ jsonify (dict "indent" " ") $weightedPages }}</pre> +``` + +## Example + +With this template: + +```go-html-template +{{ $weightedPages := $taxonomyObject.Get "suspense" }} +{{ range $weightedPages }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +``` + +Hugo renders: + +```html +<h2><a href="/books/jamaica-inn/">Jamaica inn</a></h2> +<h2><a href="/books/death-on-the-nile/">Death on the nile</a></h2> +<h2><a href="/books/and-then-there-were-none/">And then there were none</a></h2> +``` + +[chaining]: /getting-started/glossary/#chain +[`index`]: /functions/collections/indexfunction +[identifier]: /getting-started/glossary/#identifier +[term]: /getting-started/glossary/#term +[weighted pages]: /getting-started/glossary/#weighted-page diff --git a/docs/content/en/methods/taxonomy/_common/_index.md b/docs/content/en/methods/taxonomy/_common/_index.md new file mode 100644 index 000000000..47d5812fb --- /dev/null +++ b/docs/content/en/methods/taxonomy/_common/_index.md @@ -0,0 +1,13 @@ +--- +cascade: + _build: + list: never + publishResources: false + render: never +--- + +<!-- +Files within this headless branch bundle are markdown snippets. Each file must contain front matter delimiters, though front matter fields are not required. + +Include the rendered content using the "include" shortcode. +--> diff --git a/docs/content/en/methods/taxonomy/_common/get-a-taxonomy-object.md b/docs/content/en/methods/taxonomy/_common/get-a-taxonomy-object.md new file mode 100644 index 000000000..4c4fc42c9 --- /dev/null +++ b/docs/content/en/methods/taxonomy/_common/get-a-taxonomy-object.md @@ -0,0 +1,68 @@ +--- +# Do not remove front matter. +--- + +Before we can use a `Taxonomy` method, we need to capture a `Taxonomy` object. + +## Capture a taxonomy object + +Consider this site configuration: + +{{< code-toggle file=hugo >}} +[taxonomies] +genre = 'genres' +author = 'authors' +{{< /code-toggle >}} + +And this content structure: + +```text +content/ +├── books/ +│ ├── and-then-there-were-none.md --> genres: suspense +│ ├── death-on-the-nile.md --> genres: suspense +│ └── jamaica-inn.md --> genres: suspense, romance +│ └── pride-and-prejudice.md --> genres: romance +└── _index.md +``` + +To capture the "genres" taxonomy object from within any template, use the [`Taxonomies`] method on a `Site` object. + +```go-html-template +{{ $taxonomyObject := .Site.Taxonomies.genres }} +``` + +To capture the "genres" taxonomy object when rendering its page with a taxonomy template, use the [`Terms`] method on the page's [`Data`] object: + +{{< code file=layouts/_default/taxonomy.html >}} +{{ $taxonomyObject := .Data.Terms }} +{{< /code >}} + +To inspect the data structure: + +```go-html-template +<pre>{{ jsonify (dict "indent" " ") $taxonomyObject }}</pre> +``` + +Although the [`Alphabetical`] and [`ByCount`] methods provide a better data structure for ranging through the taxonomy, you can render the weighted pages by term directly from the `Taxonomy` object: + +```go-html-template +{{ range $term, $weightedPages := $taxonomyObject }} + <h2><a href="{{ .Page.RelPermalink }}">{{ .Page.LinkTitle }}</a></h2> + <ul> + {{ range $weightedPages }} + <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li> + {{ end }} + </ul> +{{ end }} +``` + +In the example above, the first anchor element is a link to the term page. + + +[`Alphabetical`]: /methods/taxonomy/alphabetical +[`ByCount`]: /methods/taxonomy/bycount + +[`data`]: /methods/page/data +[`terms`]: /methods/page/data/#in-a-taxonomy-template +[`taxonomies`]: /methods/site/taxonomies diff --git a/docs/content/en/methods/taxonomy/_common/ordered-taxonomy-element-methods.md b/docs/content/en/methods/taxonomy/_common/ordered-taxonomy-element-methods.md new file mode 100644 index 000000000..9c94729ba --- /dev/null +++ b/docs/content/en/methods/taxonomy/_common/ordered-taxonomy-element-methods.md @@ -0,0 +1,25 @@ +--- +# Do not remove front matter. +--- + +An ordered taxonomy is a slice, where each element is an object that contains the term and a slice of its weighted pages. + +Each element of the slice provides these methods: + +Count +: (`int`) Returns the number of pages to which the term is assigned. + +Page +: (`page.Page`) Returns the term's `Page` object, useful for linking to the term page. + +Pages +: (`page.Pages`) Returns a `Pages` object containing the `Page` objects to which the term is assigned, sorted by [taxonomic weight]. To sort or group, use any of the [methods] available to the `Pages` object. For example, sort by the last modification date. + +Term +: (`string`) Returns the term name. + +WeightedPages +: (`page.WeightedPages`) Returns a slice of weighted pages to which the term is assigned, sorted by [taxonomic weight]. The `Pages` method above is more flexible, allowing you to sort and group. + +[methods]: /methods/pages +[taxonomic weight]: /getting-started/glossary/#taxonomic-weight diff --git a/docs/content/en/methods/taxonomy/_index.md b/docs/content/en/methods/taxonomy/_index.md new file mode 100644 index 000000000..e7eb57834 --- /dev/null +++ b/docs/content/en/methods/taxonomy/_index.md @@ -0,0 +1,12 @@ +--- +title: Taxonomy methods +linkTitle: Taxonomy +description: Use these methods with Taxonomy objects. +keywords: [] +menu: + docs: + identifier: + parent: methods +--- + +Use these methods with Taxonomy objects. diff --git a/docs/content/en/methods/time/Add.md b/docs/content/en/methods/time/Add.md new file mode 100644 index 000000000..8fd755244 --- /dev/null +++ b/docs/content/en/methods/time/Add.md @@ -0,0 +1,23 @@ +--- +title: Add +description: Returns the given time plus the given duration. +categories: [] +keywords: [] +action: + related: + - functions/time/AsTime + - functions/time/Duration + - functions/time/ParseDuration + returnType: time.Time + signatures: [TIME.Add DURATION] +--- + +```go-html-template +{{ $t := time.AsTime "2023-01-27T23:44:58-08:00" }} + +{{ $d1 = time.ParseDuration "3h20m10s" }} +{{ $d2 = time.ParseDuration "-3h20m10s" }} + +{{ $t.Add $d1 }} → 2023-01-28 03:05:08 -0800 PST +{{ $t.Add $d2 }} → 2023-01-27 20:24:48 -0800 PST +``` diff --git a/docs/content/en/methods/time/AddDate.md b/docs/content/en/methods/time/AddDate.md new file mode 100644 index 000000000..8537d6e25 --- /dev/null +++ b/docs/content/en/methods/time/AddDate.md @@ -0,0 +1,39 @@ +--- +title: AddDate +description: Returns the time corresponding to adding the given number of years, months, and days to the given time.Time value. +categories: [] +keywords: [] +action: + aliases: [] + related: [] + returnType: time.Time + signatures: [TIME.AddDate YEARS MONTHS DAYS] +aliases: [/functions/adddate] +--- + +```go-html-template +{{ $d := "2022-01-01" | time.AsTime }} + +{{ $d.AddDate 0 0 1 | time.Format "2006-01-02" }} → 2022-01-02 +{{ $d.AddDate 0 1 1 | time.Format "2006-01-02" }} → 2022-02-02 +{{ $d.AddDate 1 1 1 | time.Format "2006-01-02" }} → 2023-02-02 + +{{ $d.AddDate -1 -1 -1 | time.Format "2006-01-02" }} → 2020-11-30 +``` + +{{% note %}} +When adding months or years, Hugo normalizes the final `time.Time` value if the resulting day does not exist. For example, adding one month to 31 January produces 2 March or 3 March, depending on the year. + +See [this explanation](https://github.com/golang/go/issues/31145#issuecomment-479067967) from the Go team. +{{% /note %}} + +```go-html-template +{{ $d := "2023-01-31" | time.AsTime }} +{{ $d.AddDate 0 1 0 | time.Format "2006-01-02" }} → 2023-03-03 + +{{ $d := "2024-01-31" | time.AsTime }} +{{ $d.AddDate 0 1 0 | time.Format "2006-01-02" }} → 2024-03-02 + +{{ $d := "2024-02-29" | time.AsTime }} +{{ $d.AddDate 1 0 0 | time.Format "2006-01-02" }} → 2025-03-01 +``` diff --git a/docs/content/en/methods/time/After.md b/docs/content/en/methods/time/After.md new file mode 100644 index 000000000..0aeeb38d8 --- /dev/null +++ b/docs/content/en/methods/time/After.md @@ -0,0 +1,20 @@ +--- +title: After +description: Reports whether TIME1 is after TIME2. +categories: [] +keywords: [] +action: + related: + - methods/time/Before + - methods/time/After + - functions/time/AsTime + returnType: bool + signatures: [TIME1.After TIME2] +--- + +```go-html-template +{{ $t1 := time.AsTime "2023-01-01T17:00:00-08:00" }} +{{ $t2 := time.AsTime "2010-01-01T17:00:00-08:00" }} + +{{ $t1.After $t2 }} → true +``` diff --git a/docs/content/en/methods/time/Before.md b/docs/content/en/methods/time/Before.md new file mode 100644 index 000000000..c3d582860 --- /dev/null +++ b/docs/content/en/methods/time/Before.md @@ -0,0 +1,19 @@ +--- +title: Before +description: Reports whether TIME1 is before TIME2. +categories: [] +keywords: [] +action: + related: + - methods/time/After + - methods/time/Equal + - functions/time/AsTime + returnType: bool + signatures: [TIME1.Before TIME2] +--- + +```go-html-template +{{ $t1 := time.AsTime "2023-01-01T17:00:00-08:00" }} +{{ $t2 := time.AsTime "2030-01-01T17:00:00-08:00" }} + +{{ $t1.Before $t2 }} → true diff --git a/docs/content/en/methods/time/Day.md b/docs/content/en/methods/time/Day.md new file mode 100644 index 000000000..1173b8489 --- /dev/null +++ b/docs/content/en/methods/time/Day.md @@ -0,0 +1,21 @@ +--- +title: Day +description: Returns the day of the month of the given time.Time value. +categories: [] +keywords: [] +action: + related: + - methods/time/Year + - methods/time/Month + - methods/time/Hour + - methods/time/Minute + - methods/time/Second + - functions/time/AsTime + returnType: int + signatures: [TIME.Day] +--- + +```go-html-template +{{ $t := time.AsTime "2023-01-27T23:44:58-08:00" }} +{{ $t.Day }} → 27 +``` diff --git a/docs/content/en/methods/time/Equal.md b/docs/content/en/methods/time/Equal.md new file mode 100644 index 000000000..4d45a3ada --- /dev/null +++ b/docs/content/en/methods/time/Equal.md @@ -0,0 +1,20 @@ +--- +title: Equal +description: Reports whether TIME1 is equal to TIME2. +categories: [] +keywords: [] +action: + related: + - methods/time/After + - methods/time/Before + - functions/time/AsTime + returnType: bool + signatures: [TIME1.Equal TIME2] +--- + +```go-html-template +{{ $t1 := time.AsTime "2023-01-01T17:00:00-08:00" }} +{{ $t2 := time.AsTime "2023-01-01T20:00:00-05:00" }} + +{{ $t1.Equal $t2 }} → true +``` diff --git a/docs/content/en/methods/time/Format.md b/docs/content/en/methods/time/Format.md new file mode 100644 index 000000000..fc3e2635c --- /dev/null +++ b/docs/content/en/methods/time/Format.md @@ -0,0 +1,98 @@ +--- +title: Format +description: Returns a textual representation of the time.Time value formatted according to the layout string. +categories: [] +keywords: [] +action: + aliases: [] + related: + - functions/time/AsTime + - methods/time/UTC + - methods/time/Local + returnType: string + signatures: [TIME.Format LAYOUT] +toc: true +aliases: [/methods/time/format] +--- + +```go-template +{{ $t := "2023-01-27T23:44:58-08:00" }} +{{ $t = time.AsTime $t }} +{{ $format := "2 Jan 2006" }} + +{{ $t.Format $format }} → 27 Jan 2023 +``` + +{{% note %}} +To [localize] the return value, use the [`time.Format`] function instead. + +[localize]: /getting-started/glossary/#localization +[`time.Format`]: /functions/time/format +{{% /note %}} + +Use the `Format` method with any `time.Time` value, including the four predefined front matter dates: + +```go-html-template +{{ $format := "2 Jan 2006" }} + +{{ .Date.Format $format }} +{{ .PublishDate.Format $format }} +{{ .ExpiryDate.Format $format }} +{{ .Lastmod.Format $format }} +``` + +{{% note %}} +Use the [`time.Format`] function to format string representations of dates, and to format raw TOML dates that exclude time and time zone offset. + +[`time.Format`]: /functions/time/format +{{% /note %}} + +## Layout string + +{{% include "functions/_common/time-layout-string.md" %}} + +## Examples + +Given this front matter: + +{{< code-toggle fm=true >}} +title = "About time" +date = 2023-01-27T23:44:58-08:00 +{{< /code-toggle >}} + +The examples below were rendered in the `America/Los_Angeles` time zone: + +Format string|Result +:--|:-- +`Monday, January 2, 2006`|`Friday, January 27, 2023` +`Mon Jan 2 2006`|`Fri Jan 27 2023` +`January 2006`|`January 2023` +`2006-01-02`|`2023-01-27` +`Monday`|`Friday` +`02 Jan 06 15:04 MST`|`27 Jan 23 23:44 PST` +`Mon, 02 Jan 2006 15:04:05 MST`|`Fri, 27 Jan 2023 23:44:58 PST` +`Mon, 02 Jan 2006 15:04:05 -0700`|`Fri, 27 Jan 2023 23:44:58 -0800` + +## UTC and local time + +Convert and format any `time.Time` value to either Coordinated Universal Time (UTC) or local time. + +```go-html-template +{{ $t := "2023-01-27T23:44:58-08:00" }} +{{ $t = time.AsTime $t }} +{{ $format := "2 Jan 2006 3:04:05 PM MST" }} + +{{ $t.UTC.Format $format }} → 28 Jan 2023 7:44:58 AM UTC +{{ $t.Local.Format $format }} → 27 Jan 2023 11:44:58 PM PST +``` + +## Ordinal representation + +Use the [`humanize`](/functions/inflect/humanize) function to render the day of the month as an ordinal number: + +```go-html-template +{{ $t := "2023-01-27T23:44:58-08:00" }} +{{ $t = time.AsTime $t }} + +{{ humanize $t.Day }} of {{ $t.Format "January 2006" }} → 27th of January 2023 +``` diff --git a/docs/content/en/methods/time/Hour.md b/docs/content/en/methods/time/Hour.md new file mode 100644 index 000000000..58ed00260 --- /dev/null +++ b/docs/content/en/methods/time/Hour.md @@ -0,0 +1,21 @@ +--- +title: Hour +description: Returns the hour within the day of the given time.Time value, in the range [0, 23]. +categories: [] +keywords: [] +action: + related: + - methods/time/Year + - methods/time/Month + - methods/time/Day + - methods/time/Minute + - methods/time/Second + - functions/time/AsTime + returnType: int + signatures: [TIME.Hour] +--- + +```go-html-template +{{ $t := time.AsTime "2023-01-27T23:44:58-08:00" }} +{{ $t.Hour }} → 23 +``` diff --git a/docs/content/en/methods/time/IsDST.md b/docs/content/en/methods/time/IsDST.md new file mode 100644 index 000000000..df2b84cae --- /dev/null +++ b/docs/content/en/methods/time/IsDST.md @@ -0,0 +1,19 @@ +--- +title: IsDST +description: Reports whether the given time.Time value is in Daylight Savings Time. +categories: [] +keywords: [] +action: + related: + - functions/time/AsTime + returnType: bool + signatures: [TIME.IsDST] +--- + +```go-html-template +{{ $t1 := time.AsTime "2023-01-01T00:00:00-08:00" }} +{{ $t2 := time.AsTime "2023-07-01T00:00:00-07:00" }} + +{{ $t1.IsDST }} → false +{{ $t2.IsDST }} → true +``` diff --git a/docs/content/en/methods/time/IsZero.md b/docs/content/en/methods/time/IsZero.md new file mode 100644 index 000000000..2026f3b2e --- /dev/null +++ b/docs/content/en/methods/time/IsZero.md @@ -0,0 +1,19 @@ +--- +title: IsZero +description: Reports whether the given time.Time value represents the zero time instant, January 1, year 1, 00:00:00 UTC. +categories: [] +keywords: [] +action: + related: + - functions/time/AsTime + returnType: bool + signatures: [TIME.IsZero] +--- + +````go-html-template +{{ $t1 := time.AsTime "2023-01-01T00:00:00-08:00" }} +{{ $t2 := time.AsTime "0001-01-01T00:00:00-00:00" }} + +{{ $t1.IsZero }} → false +{{ $t2.IsZero }} → true +``` diff --git a/docs/content/en/methods/time/Local.md b/docs/content/en/methods/time/Local.md new file mode 100644 index 000000000..bd40e3a44 --- /dev/null +++ b/docs/content/en/methods/time/Local.md @@ -0,0 +1,17 @@ +--- +title: Local +description: Returns the given time.Time value with the location set to local time. +categories: [] +keywords: [] +action: + related: + - methods/time/UTC + - functions/time/AsTime + returnType: time.Time + signatures: [TIME.Local] +--- + +```go-html-template +{{ $t := time.AsTime "2023-01-28T07:44:58+00:00" }} +{{ $t.Local }} → 2023-01-27 23:44:58 -0800 PST +``` diff --git a/docs/content/en/methods/time/Minute.md b/docs/content/en/methods/time/Minute.md new file mode 100644 index 000000000..d482fab5d --- /dev/null +++ b/docs/content/en/methods/time/Minute.md @@ -0,0 +1,21 @@ +--- +title: Minute +description: Returns the minute offset within the hour of the given time.Time value, in the range [0, 59]. +categories: [] +keywords: [] +action: + related: + - methods/time/Year + - methods/time/Month + - methods/time/Day + - methods/time/Hour + - methods/time/Second + - functions/time/AsTime + returnType: int + signatures: [TIME.Minute] +--- + +```go-html-template +{{ $t := time.AsTime "2023-01-27T23:44:58-08:00" }} +{{ $t.Minute }} → 44 +``` diff --git a/docs/content/en/methods/time/Month.md b/docs/content/en/methods/time/Month.md new file mode 100644 index 000000000..0a01d1a70 --- /dev/null +++ b/docs/content/en/methods/time/Month.md @@ -0,0 +1,30 @@ +--- +title: Month +description: Returns the month of the year of the given time.Time value. +categories: [] +keywords: [] +action: + related: + - methods/time/Year + - methods/time/Day + - methods/time/Hour + - methods/time/Minute + - methods/time/Second + - functions/time/AsTime + returnType: time.Month + signatures: [TIME.Month] +--- + +To convert the `time.Month` value to a string: + +```go-html-template +{{ $t := time.AsTime "2023-01-27T23:44:58-08:00" }} +{{ $t.Month.String }} → January +``` + +To convert the `time.Month` value to an integer. + +```go-html-template +{{ $t := time.AsTime "2023-01-27T23:44:58-08:00" }} +{{ $t.Month | int }} → 1 +``` diff --git a/docs/content/en/methods/time/Nanosecond.md b/docs/content/en/methods/time/Nanosecond.md new file mode 100644 index 000000000..606143139 --- /dev/null +++ b/docs/content/en/methods/time/Nanosecond.md @@ -0,0 +1,16 @@ +--- +title: Nanosecond +description: Returns the nanosecond offset within the second of the given time.Time value, in the range [0, 999999999]. +categories: [] +keywords: [] +action: + related: + - functions/time/AsTime + returnType: int + signatures: [TIME.Nanosecond] +--- + +```go-html-template +{{ $t := time.AsTime "2023-01-27T23:44:58-08:00" }} +{{ $t.Nanosecond }} → 0 +``` diff --git a/docs/content/en/methods/time/Second.md b/docs/content/en/methods/time/Second.md new file mode 100644 index 000000000..e326c64bc --- /dev/null +++ b/docs/content/en/methods/time/Second.md @@ -0,0 +1,21 @@ +--- +title: Second +description: Returns the second offset within the minute of the given time.Time value, in the range [0, 59]. +categories: [] +keywords: [] +action: + related: + - methods/time/Year + - methods/time/Month + - methods/time/Day + - methods/time/Hour + - methods/time/Minute + - functions/time/AsTime + returnType: int + signatures: [TIME.Second] +--- + +```go-html-template +{{ $t := time.AsTime "2023-01-27T23:44:58-08:00" }} +{{ $t.Second }} → 58 +``` diff --git a/docs/content/en/methods/time/Sub.md b/docs/content/en/methods/time/Sub.md new file mode 100644 index 000000000..9678365eb --- /dev/null +++ b/docs/content/en/methods/time/Sub.md @@ -0,0 +1,18 @@ +--- +title: Sub +description: Returns the duration computed by subtracting TIME2 from TIME1. +categories: [] +keywords: [] +action: + related: + - functions/time/AsTime + returnType: time.Duration + signatures: [TIME1.Sub TIME2] +--- + +```go-html-template +{{ $t1 := time.AsTime "2023-01-27T23:44:58-08:00" }} +{{ $t2 := time.AsTime "2023-01-26T22:34:38-08:00" }} + +{{ $t1.Sub $t2 }} → 25h10m20s +``` diff --git a/docs/content/en/methods/time/UTC.md b/docs/content/en/methods/time/UTC.md new file mode 100644 index 000000000..6fd7b526d --- /dev/null +++ b/docs/content/en/methods/time/UTC.md @@ -0,0 +1,16 @@ +--- +title: UTC +description: Returns the given time.Time value with the location set to UTC. +categories: [] +keywords: [] +action: + related: + - methods/time/Local + - functions/time/AsTime + returnType: time.Time + signatures: [TIME.UTC] +--- + +```go-html-template +{{ $t := time.AsTime "2023-01-27T23:44:58-08:00" }} +{{ $t.UTC }} → 2023-01-28 07:44:58 +0000 UTC diff --git a/docs/content/en/methods/time/Unix.md b/docs/content/en/methods/time/Unix.md new file mode 100644 index 000000000..fcfc661fe --- /dev/null +++ b/docs/content/en/methods/time/Unix.md @@ -0,0 +1,21 @@ +--- +title: Unix +description: Returns the given time.Time value expressed as the number of seconds elapsed since January 1, 1970 UTC. +categories: [] +action: + related: + - methods/time/UnixMilli + - methods/time/UnixMicro + - methods/time/UnixNano + - functions/time/AsTime + returnType: int64 + signatures: [TIME.Unix] +aliases: [/functions/unix] +--- + +See [Unix epoch](https://en.wikipedia.org/wiki/Unix_time). + +```go-html-template +{{ $t := time.AsTime "2023-01-27T23:44:58-08:00" }} +{{ $t.Unix }} → 1674891898 +``` diff --git a/docs/content/en/methods/time/UnixMicro.md b/docs/content/en/methods/time/UnixMicro.md new file mode 100644 index 000000000..150497cd3 --- /dev/null +++ b/docs/content/en/methods/time/UnixMicro.md @@ -0,0 +1,21 @@ +--- +title: UnixMicro +description: Returns the given time.Time value expressed as the number of microseconds elapsed since January 1, 1970 UTC. +categories: [] +keywords: [] +action: + related: + - methods/time/Unix + - methods/time/UnixMilli + - methods/time/UnixNano + - functions/time/AsTime + returnType: int64 + signatures: [TIME.UnixMicro] +--- + +See [Unix epoch](https://en.wikipedia.org/wiki/Unix_time). + +```go-html-template +{{ $t := time.AsTime "2023-01-27T23:44:58-08:00" }} +{{ $t.UnixMicro }} → 1674891898000000 +``` diff --git a/docs/content/en/methods/time/UnixMilli.md b/docs/content/en/methods/time/UnixMilli.md new file mode 100644 index 000000000..e5e90ba25 --- /dev/null +++ b/docs/content/en/methods/time/UnixMilli.md @@ -0,0 +1,21 @@ +--- +title: UnixMilli +description: Returns the given time.Time value expressed as the number of milliseconds elapsed since January 1, 1970 UTC. +categories: [] +keywords: [] +action: + related: + - methods/time/Unix + - methods/time/UnixMicro + - methods/time/UnixNano + - functions/time/AsTime + returnType: int64 + signatures: [TIME.UnixMilli] +--- + +See [Unix epoch](https://en.wikipedia.org/wiki/Unix_time). + +```go-html-template +{{ $t := time.AsTime "2023-01-27T23:44:58-08:00" }} +{{ $t.UnixMilli }} → 1674891898000 +``` diff --git a/docs/content/en/methods/time/UnixNano.md b/docs/content/en/methods/time/UnixNano.md new file mode 100644 index 000000000..63db320a3 --- /dev/null +++ b/docs/content/en/methods/time/UnixNano.md @@ -0,0 +1,21 @@ +--- +title: UnixNano +description: Returns the given time.Time value expressed as the number of nanoseconds elapsed since January 1, 1970 UTC. +categories: [] +keywords: [] +action: + related: + - methods/time/Unix + - methods/time/UnixMilli + - methods/time/UnixMicro + - functions/time/AsTime + returnType: int64 + signatures: [TIME.UnixNano] +--- + +See [Unix epoch](https://en.wikipedia.org/wiki/Unix_time). + +```go-html-template +{{ $t := time.AsTime "2023-01-27T23:44:58-08:00" }} +{{ $t.UnixNano }} → 1674891898000000000 +``` diff --git a/docs/content/en/methods/time/Weekday.md b/docs/content/en/methods/time/Weekday.md new file mode 100644 index 000000000..b2a95fe9c --- /dev/null +++ b/docs/content/en/methods/time/Weekday.md @@ -0,0 +1,24 @@ +--- +title: Weekday +description: Returns the day of the week of the given time.Time value. +categories: [] +keywords: [] +action: + related: + - functions/time/AsTime + returnType: time.Weekday + signatures: [TIME.Weekday] +--- + +To convert the `time.Weekday` value to a string: + +```go-html-template +{{ $t := time.AsTime "2023-01-27T23:44:58-08:00" }} +{{ $t.Weekday.String }} → Friday +``` + +To convert the `time.Weekday` value to an integer. + +```go-html-template +{{ $t := time.AsTime "2023-01-27T23:44:58-08:00" }} +{{ $t.Weekday | int }} → 5 diff --git a/docs/content/en/methods/time/Year.md b/docs/content/en/methods/time/Year.md new file mode 100644 index 000000000..b046896f4 --- /dev/null +++ b/docs/content/en/methods/time/Year.md @@ -0,0 +1,21 @@ +--- +title: Year +description: Returns the year of the given time.Time value. +categories: [] +keywords: [] +action: + related: + - methods/time/Month + - methods/time/Day + - methods/time/Hour + - methods/time/Minute + - methods/time/Second + - functions/time/AsTime + returnType: int + signatures: [TIME.Year] +--- + +```go-html-template +{{ $t := time.AsTime "2023-01-27T23:44:58-08:00" }} +{{ $t.Year }} → 2023 +``` diff --git a/docs/content/en/methods/time/YearDay.md b/docs/content/en/methods/time/YearDay.md new file mode 100644 index 000000000..40d7d6aab --- /dev/null +++ b/docs/content/en/methods/time/YearDay.md @@ -0,0 +1,15 @@ +--- +title: YearDay +description: Returns the day of the year of the given time.Time value, in the range [1, 365] for non-leap years, and [1,366] in leap years. +categories: [] +keywords: [] +action: + related: [] + returnType: int + signatures: [TIME.YearDay] +--- + +```go-html-template +{{ $t := time.AsTime "2023-01-27T23:44:58-08:00" }} +{{ $t.YearDay }} → 27 +``` diff --git a/docs/content/en/methods/time/_index.md b/docs/content/en/methods/time/_index.md new file mode 100644 index 000000000..81d4690e0 --- /dev/null +++ b/docs/content/en/methods/time/_index.md @@ -0,0 +1,13 @@ +--- +title: Time methods +linkTitle: Time +description: Use these methods with time.Time values. +categories: [] +keywords: [] +menu: + docs: + identifier: time-methods + parent: methods +--- + +Use these methods with time.Time values. diff --git a/docs/content/en/myshowcase/bio.md b/docs/content/en/myshowcase/bio.md new file mode 100644 index 000000000..6b8f7e1a9 --- /dev/null +++ b/docs/content/en/myshowcase/bio.md @@ -0,0 +1,7 @@ + +Add some **general info** about Myshowcase here. + +The site is built by: + +* [Person 1](https://example.org) +* [Person 1](https://example.org) diff --git a/docs/content/en/myshowcase/featured.png b/docs/content/en/myshowcase/featured.png Binary files differnew file mode 100644 index 000000000..4f390132e --- /dev/null +++ b/docs/content/en/myshowcase/featured.png diff --git a/docs/content/en/myshowcase/index.md b/docs/content/en/myshowcase/index.md new file mode 100644 index 000000000..08ea1e55f --- /dev/null +++ b/docs/content/en/myshowcase/index.md @@ -0,0 +1,37 @@ +--- + +title: Myshowcase +date: 2021-01-14 + +description: "A short description of this page." + +# The URL to the site on the internet. +siteURL: https://gohugo.io/ + +# Link to the site's Hugo source code if public and you can/want to share. +# Remove or leave blank if not needed/wanted. +siteSource: https://github.com/gohugoio/hugoDocs + +# Add credit to the article author. Leave blank or remove if not needed/wanted. +byline: "[bep](https://github.com/bep), Hugo Lead" + +--- + +To complete this showcase: + +1. Write the story about your site in this file. +2. Add a summary to the `bio.md` file in this folder. +3. Replace the `featured-template.png` with a screenshot of your site. You can rename it, but it must contain the word `featured`. +4. Create a new pull request in https://github.com/gohugoio/hugoDocs/pulls + +The content of this bundle explained: + +index.md +: The main content file. Fill in required front matter metadata and write your story. I does not have to be a novel. It can even be self-promotional, but it should include Hugo in some form. + +bio.md +: A short summary of the website. Site credits (who built it) fits nicely here. + +featured.png +: A reasonably sized screenshot of your website. It can be named anything, but the name must start with "featured". The sample image is `1500x750` (2:1 aspect ratio). + diff --git a/docs/content/en/news/_index.md b/docs/content/en/news/_index.md new file mode 100644 index 000000000..e37c33a3c --- /dev/null +++ b/docs/content/en/news/_index.md @@ -0,0 +1,4 @@ +--- +title: Hugo News +aliases: [/release-notes/] +--- diff --git a/docs/content/en/quick-reference/_index.md b/docs/content/en/quick-reference/_index.md new file mode 100644 index 000000000..492cfa09b --- /dev/null +++ b/docs/content/en/quick-reference/_index.md @@ -0,0 +1,16 @@ +--- +title: Quick reference guides +linkTitle: Overview +description: Quick reference guides to Hugo's features, functions, and methods. +categories: [] +keywords: [] +menu: + docs: + identifier: quick-reference-overview + parent: quick-reference + weight: 10 +weight: 10 +showSectionMenu: false +--- + +Quick reference guides to Hugo's features, functions, and methods. diff --git a/docs/content/en/quick-reference/emojis.md b/docs/content/en/quick-reference/emojis.md new file mode 100644 index 000000000..e6b1ed415 --- /dev/null +++ b/docs/content/en/quick-reference/emojis.md @@ -0,0 +1,1624 @@ +--- +title: Emojis +description: Include emoji shortcodes in your markdown or templates. +categories: [quick reference] +keywords: [emoji] +menu: + docs: + parent: quick-reference + weight: 20 +weight: 20 +toc: true +--- + +Configure Hugo to enable emoji processing in markdown: + +{{< code-toggle file=hugo >}} +enableEmoji = true +{{< /code-toggle >}} + +With emoji processing enabled, this markdown: + +```md +Hello! :wave: +``` + +Is rendered to: + +```html +Hello! 👋 +``` + +And in your browser... Hello! :wave: + +To process an emoji shortcode from within a template, use the [`emojify`] function or pass the string through the [`RenderString`] method on a `Page` object: + +```go-html-template +{{ "Hello! :wave:" | .RenderString }} +``` + +[`emojify`]: /functions/transform/emojify +[`RenderString`]: /methods/page/renderstring + +## Introduction + +This quick reference guide was automatically generated from [GitHub Emoji API] and [Unicode Full Emoji List]. Specials thanks to [@ikatyang] for making [this list] available to the open-source community. + +GitHub [custom emoji] are not supported. + +[custom emoji]: #github-custom-emoji +[@ikatyang]: https://github.com/ikatyang +[github emoji api]: https://api.github.com/emojis +[unicode full emoji list]: https://unicode.org/emoji/charts/full-emoji-list.html +[this list]: https://github.com/ikatyang/emoji-cheat-sheet/#readme + +## Smileys & Emotion + +- [Face Smiling](#face-smiling) +- [Face Affection](#face-affection) +- [Face Tongue](#face-tongue) +- [Face Hand](#face-hand) +- [Face Neutral Skeptical](#face-neutral-skeptical) +- [Face Sleepy](#face-sleepy) +- [Face Unwell](#face-unwell) +- [Face Hat](#face-hat) +- [Face Glasses](#face-glasses) +- [Face Concerned](#face-concerned) +- [Face Negative](#face-negative) +- [Face Costume](#face-costume) +- [Cat Face](#cat-face) +- [Monkey Face](#monkey-face) +- [Heart](#heart) +- [Emotion](#emotion) + +### Face Smiling + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#introduction) | :grinning: | `:grinning:` | :smiley: | `:smiley:` | [top](#introduction) | +| [top](#introduction) | :smile: | `:smile:` | :grin: | `:grin:` | [top](#introduction) | +| [top](#introduction) | :laughing: | `:laughing:` `:satisfied:` | :sweat_smile: | `:sweat_smile:` | [top](#introduction) | +| [top](#introduction) | :rofl: | `:rofl:` | :joy: | `:joy:` | [top](#introduction) | +| [top](#introduction) | :slightly_smiling_face: | `:slightly_smiling_face:` | :upside_down_face: | `:upside_down_face:` | [top](#introduction) | +| [top](#introduction) | :wink: | `:wink:` | :blush: | `:blush:` | [top](#introduction) | +| [top](#introduction) | :innocent: | `:innocent:` | | | [top](#introduction) | + +### Face Affection + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#introduction) | :smiling_face_with_three_hearts: | `:smiling_face_with_three_hearts:` | :heart_eyes: | `:heart_eyes:` | [top](#introduction) | +| [top](#introduction) | :star_struck: | `:star_struck:` | :kissing_heart: | `:kissing_heart:` | [top](#introduction) | +| [top](#introduction) | :kissing: | `:kissing:` | :relaxed: | `:relaxed:` | [top](#introduction) | +| [top](#introduction) | :kissing_closed_eyes: | `:kissing_closed_eyes:` | :kissing_smiling_eyes: | `:kissing_smiling_eyes:` | [top](#introduction) | +| [top](#introduction) | :smiling_face_with_tear: | `:smiling_face_with_tear:` | | | [top](#introduction) | + +### Face Tongue + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#introduction) | :yum: | `:yum:` | :stuck_out_tongue: | `:stuck_out_tongue:` | [top](#introduction) | +| [top](#introduction) | :stuck_out_tongue_winking_eye: | `:stuck_out_tongue_winking_eye:` | :zany_face: | `:zany_face:` | [top](#introduction) | +| [top](#introduction) | :stuck_out_tongue_closed_eyes: | `:stuck_out_tongue_closed_eyes:` | :money_mouth_face: | `:money_mouth_face:` | [top](#introduction) | + +### Face Hand + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#introduction) | :hugs: | `:hugs:` | :hand_over_mouth: | `:hand_over_mouth:` | [top](#introduction) | +| [top](#introduction) | :shushing_face: | `:shushing_face:` | :thinking: | `:thinking:` | [top](#introduction) | + +### Face Neutral Skeptical + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#introduction) | :zipper_mouth_face: | `:zipper_mouth_face:` | :raised_eyebrow: | `:raised_eyebrow:` | [top](#introduction) | +| [top](#introduction) | :neutral_face: | `:neutral_face:` | :expressionless: | `:expressionless:` | [top](#introduction) | +| [top](#introduction) | :no_mouth: | `:no_mouth:` | :face_in_clouds: | `:face_in_clouds:` | [top](#introduction) | +| [top](#introduction) | :smirk: | `:smirk:` | :unamused: | `:unamused:` | [top](#introduction) | +| [top](#introduction) | :roll_eyes: | `:roll_eyes:` | :grimacing: | `:grimacing:` | [top](#introduction) | +| [top](#introduction) | :face_exhaling: | `:face_exhaling:` | :lying_face: | `:lying_face:` | [top](#introduction) | + +### Face Sleepy + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#introduction) | :relieved: | `:relieved:` | :pensive: | `:pensive:` | [top](#introduction) | +| [top](#introduction) | :sleepy: | `:sleepy:` | :drooling_face: | `:drooling_face:` | [top](#introduction) | +| [top](#introduction) | :sleeping: | `:sleeping:` | | | [top](#introduction) | + +### Face Unwell + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#introduction) | :mask: | `:mask:` | :face_with_thermometer: | `:face_with_thermometer:` | [top](#introduction) | +| [top](#introduction) | :face_with_head_bandage: | `:face_with_head_bandage:` | :nauseated_face: | `:nauseated_face:` | [top](#introduction) | +| [top](#introduction) | :vomiting_face: | `:vomiting_face:` | :sneezing_face: | `:sneezing_face:` | [top](#introduction) | +| [top](#introduction) | :hot_face: | `:hot_face:` | :cold_face: | `:cold_face:` | [top](#introduction) | +| [top](#introduction) | :woozy_face: | `:woozy_face:` | :dizzy_face: | `:dizzy_face:` | [top](#introduction) | +| [top](#introduction) | :face_with_spiral_eyes: | `:face_with_spiral_eyes:` | :exploding_head: | `:exploding_head:` | [top](#introduction) | + +### Face Hat + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#introduction) | :cowboy_hat_face: | `:cowboy_hat_face:` | :partying_face: | `:partying_face:` | [top](#introduction) | +| [top](#introduction) | :disguised_face: | `:disguised_face:` | | | [top](#introduction) | + +### Face Glasses + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#introduction) | :sunglasses: | `:sunglasses:` | :nerd_face: | `:nerd_face:` | [top](#introduction) | +| [top](#introduction) | :monocle_face: | `:monocle_face:` | | | [top](#introduction) | + +### Face Concerned + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#introduction) | :confused: | `:confused:` | :worried: | `:worried:` | [top](#introduction) | +| [top](#introduction) | :slightly_frowning_face: | `:slightly_frowning_face:` | :frowning_face: | `:frowning_face:` | [top](#introduction) | +| [top](#introduction) | :open_mouth: | `:open_mouth:` | :hushed: | `:hushed:` | [top](#introduction) | +| [top](#introduction) | :astonished: | `:astonished:` | :flushed: | `:flushed:` | [top](#introduction) | +| [top](#introduction) | :pleading_face: | `:pleading_face:` | :frowning: | `:frowning:` | [top](#introduction) | +| [top](#introduction) | :anguished: | `:anguished:` | :fearful: | `:fearful:` | [top](#introduction) | +| [top](#introduction) | :cold_sweat: | `:cold_sweat:` | :disappointed_relieved: | `:disappointed_relieved:` | [top](#introduction) | +| [top](#introduction) | :cry: | `:cry:` | :sob: | `:sob:` | [top](#introduction) | +| [top](#introduction) | :scream: | `:scream:` | :confounded: | `:confounded:` | [top](#introduction) | +| [top](#introduction) | :persevere: | `:persevere:` | :disappointed: | `:disappointed:` | [top](#introduction) | +| [top](#introduction) | :sweat: | `:sweat:` | :weary: | `:weary:` | [top](#introduction) | +| [top](#introduction) | :tired_face: | `:tired_face:` | :yawning_face: | `:yawning_face:` | [top](#introduction) | + +### Face Negative + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#introduction) | :triumph: | `:triumph:` | :pout: | `:pout:` `:rage:` | [top](#introduction) | +| [top](#introduction) | :angry: | `:angry:` | :cursing_face: | `:cursing_face:` | [top](#introduction) | +| [top](#introduction) | :smiling_imp: | `:smiling_imp:` | :imp: | `:imp:` | [top](#introduction) | +| [top](#introduction) | :skull: | `:skull:` | :skull_and_crossbones: | `:skull_and_crossbones:` | [top](#introduction) | + +### Face Costume + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#introduction) | :hankey: | `:hankey:` `:poop:` `:shit:` | :clown_face: | `:clown_face:` | [top](#introduction) | +| [top](#introduction) | :japanese_ogre: | `:japanese_ogre:` | :japanese_goblin: | `:japanese_goblin:` | [top](#introduction) | +| [top](#introduction) | :ghost: | `:ghost:` | :alien: | `:alien:` | [top](#introduction) | +| [top](#introduction) | :space_invader: | `:space_invader:` | :robot: | `:robot:` | [top](#introduction) | + +### Cat Face + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#introduction) | :smiley_cat: | `:smiley_cat:` | :smile_cat: | `:smile_cat:` | [top](#introduction) | +| [top](#introduction) | :joy_cat: | `:joy_cat:` | :heart_eyes_cat: | `:heart_eyes_cat:` | [top](#introduction) | +| [top](#introduction) | :smirk_cat: | `:smirk_cat:` | :kissing_cat: | `:kissing_cat:` | [top](#introduction) | +| [top](#introduction) | :scream_cat: | `:scream_cat:` | :crying_cat_face: | `:crying_cat_face:` | [top](#introduction) | +| [top](#introduction) | :pouting_cat: | `:pouting_cat:` | | | [top](#introduction) | + +### Monkey Face + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#introduction) | :see_no_evil: | `:see_no_evil:` | :hear_no_evil: | `:hear_no_evil:` | [top](#introduction) | +| [top](#introduction) | :speak_no_evil: | `:speak_no_evil:` | | | [top](#introduction) | + +### Heart + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#introduction) | :love_letter: | `:love_letter:` | :cupid: | `:cupid:` | [top](#introduction) | +| [top](#introduction) | :gift_heart: | `:gift_heart:` | :sparkling_heart: | `:sparkling_heart:` | [top](#introduction) | +| [top](#introduction) | :heartpulse: | `:heartpulse:` | :heartbeat: | `:heartbeat:` | [top](#introduction) | +| [top](#introduction) | :revolving_hearts: | `:revolving_hearts:` | :two_hearts: | `:two_hearts:` | [top](#introduction) | +| [top](#introduction) | :heart_decoration: | `:heart_decoration:` | :heavy_heart_exclamation: | `:heavy_heart_exclamation:` | [top](#introduction) | +| [top](#introduction) | :broken_heart: | `:broken_heart:` | :heart_on_fire: | `:heart_on_fire:` | [top](#introduction) | +| [top](#introduction) | :mending_heart: | `:mending_heart:` | :heart: | `:heart:` | [top](#introduction) | +| [top](#introduction) | :orange_heart: | `:orange_heart:` | :yellow_heart: | `:yellow_heart:` | [top](#introduction) | +| [top](#introduction) | :green_heart: | `:green_heart:` | :blue_heart: | `:blue_heart:` | [top](#introduction) | +| [top](#introduction) | :purple_heart: | `:purple_heart:` | :brown_heart: | `:brown_heart:` | [top](#introduction) | +| [top](#introduction) | :black_heart: | `:black_heart:` | :white_heart: | `:white_heart:` | [top](#introduction) | + +### Emotion + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#introduction) | :kiss: | `:kiss:` | :100: | `:100:` | [top](#introduction) | +| [top](#introduction) | :anger: | `:anger:` | :boom: | `:boom:` `:collision:` | [top](#introduction) | +| [top](#introduction) | :dizzy: | `:dizzy:` | :sweat_drops: | `:sweat_drops:` | [top](#introduction) | +| [top](#introduction) | :dash: | `:dash:` | :hole: | `:hole:` | [top](#introduction) | +| [top](#introduction) | :speech_balloon: | `:speech_balloon:` | :eye_speech_bubble: | `:eye_speech_bubble:` | [top](#introduction) | +| [top](#introduction) | :left_speech_bubble: | `:left_speech_bubble:` | :right_anger_bubble: | `:right_anger_bubble:` | [top](#introduction) | +| [top](#introduction) | :thought_balloon: | `:thought_balloon:` | :zzz: | `:zzz:` | [top](#introduction) | + +## People & Body + +- [Hand Fingers Open](#hand-fingers-open) +- [Hand Fingers Partial](#hand-fingers-partial) +- [Hand Single Finger](#hand-single-finger) +- [Hand Fingers Closed](#hand-fingers-closed) +- [Hands](#hands) +- [Hand Prop](#hand-prop) +- [Body Parts](#body-parts) +- [Person](#person) +- [Person Gesture](#person-gesture) +- [Person Role](#person-role) +- [Person Fantasy](#person-fantasy) +- [Person Activity](#person-activity) +- [Person Sport](#person-sport) +- [Person Resting](#person-resting) +- [Family](#family) +- [Person Symbol](#person-symbol) + +### Hand Fingers Open + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#people--body) | :wave: | `:wave:` | :raised_back_of_hand: | `:raised_back_of_hand:` | [top](#introduction) | +| [top](#people--body) | :raised_hand_with_fingers_splayed: | `:raised_hand_with_fingers_splayed:` | :hand: | `:hand:` `:raised_hand:` | [top](#introduction) | +| [top](#people--body) | :vulcan_salute: | `:vulcan_salute:` | | | [top](#introduction) | + +### Hand Fingers Partial + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#people--body) | :ok_hand: | `:ok_hand:` | :pinched_fingers: | `:pinched_fingers:` | [top](#introduction) | +| [top](#people--body) | :pinching_hand: | `:pinching_hand:` | :v: | `:v:` | [top](#introduction) | +| [top](#people--body) | :crossed_fingers: | `:crossed_fingers:` | :love_you_gesture: | `:love_you_gesture:` | [top](#introduction) | +| [top](#people--body) | :metal: | `:metal:` | :call_me_hand: | `:call_me_hand:` | [top](#introduction) | + +### Hand Single Finger + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#people--body) | :point_left: | `:point_left:` | :point_right: | `:point_right:` | [top](#introduction) | +| [top](#people--body) | :point_up_2: | `:point_up_2:` | :fu: | `:fu:` `:middle_finger:` | [top](#introduction) | +| [top](#people--body) | :point_down: | `:point_down:` | :point_up: | `:point_up:` | [top](#introduction) | + +### Hand Fingers Closed + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#people--body) | :+1: | `:+1:` `:thumbsup:` | :-1: | `:-1:` `:thumbsdown:` | [top](#introduction) | +| [top](#people--body) | :fist: | `:fist:` `:fist_raised:` | :facepunch: | `:facepunch:` `:fist_oncoming:` `:punch:` | [top](#introduction) | +| [top](#people--body) | :fist_left: | `:fist_left:` | :fist_right: | `:fist_right:` | [top](#introduction) | + +### Hands + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#people--body) | :clap: | `:clap:` | :raised_hands: | `:raised_hands:` | [top](#introduction) | +| [top](#people--body) | :open_hands: | `:open_hands:` | :palms_up_together: | `:palms_up_together:` | [top](#introduction) | +| [top](#people--body) | :handshake: | `:handshake:` | :pray: | `:pray:` | [top](#introduction) | + +### Hand Prop + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#people--body) | :writing_hand: | `:writing_hand:` | :nail_care: | `:nail_care:` | [top](#introduction) | +| [top](#people--body) | :selfie: | `:selfie:` | | | [top](#introduction) | + +### Body Parts + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#people--body) | :muscle: | `:muscle:` | :mechanical_arm: | `:mechanical_arm:` | [top](#introduction) | +| [top](#people--body) | :mechanical_leg: | `:mechanical_leg:` | :leg: | `:leg:` | [top](#introduction) | +| [top](#people--body) | :foot: | `:foot:` | :ear: | `:ear:` | [top](#introduction) | +| [top](#people--body) | :ear_with_hearing_aid: | `:ear_with_hearing_aid:` | :nose: | `:nose:` | [top](#introduction) | +| [top](#people--body) | :brain: | `:brain:` | :anatomical_heart: | `:anatomical_heart:` | [top](#introduction) | +| [top](#people--body) | :lungs: | `:lungs:` | :tooth: | `:tooth:` | [top](#introduction) | +| [top](#people--body) | :bone: | `:bone:` | :eyes: | `:eyes:` | [top](#introduction) | +| [top](#people--body) | :eye: | `:eye:` | :tongue: | `:tongue:` | [top](#introduction) | +| [top](#people--body) | :lips: | `:lips:` | | | [top](#introduction) | + +### Person + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#people--body) | :baby: | `:baby:` | :child: | `:child:` | [top](#introduction) | +| [top](#people--body) | :boy: | `:boy:` | :girl: | `:girl:` | [top](#introduction) | +| [top](#people--body) | :adult: | `:adult:` | :blond_haired_person: | `:blond_haired_person:` | [top](#introduction) | +| [top](#people--body) | :man: | `:man:` | :bearded_person: | `:bearded_person:` | [top](#introduction) | +| [top](#people--body) | :man_beard: | `:man_beard:` | :woman_beard: | `:woman_beard:` | [top](#introduction) | +| [top](#people--body) | :red_haired_man: | `:red_haired_man:` | :curly_haired_man: | `:curly_haired_man:` | [top](#introduction) | +| [top](#people--body) | :white_haired_man: | `:white_haired_man:` | :bald_man: | `:bald_man:` | [top](#introduction) | +| [top](#people--body) | :woman: | `:woman:` | :red_haired_woman: | `:red_haired_woman:` | [top](#introduction) | +| [top](#people--body) | :person_red_hair: | `:person_red_hair:` | :curly_haired_woman: | `:curly_haired_woman:` | [top](#introduction) | +| [top](#people--body) | :person_curly_hair: | `:person_curly_hair:` | :white_haired_woman: | `:white_haired_woman:` | [top](#introduction) | +| [top](#people--body) | :person_white_hair: | `:person_white_hair:` | :bald_woman: | `:bald_woman:` | [top](#introduction) | +| [top](#people--body) | :person_bald: | `:person_bald:` | :blond_haired_woman: | `:blond_haired_woman:` `:blonde_woman:` | [top](#introduction) | +| [top](#people--body) | :blond_haired_man: | `:blond_haired_man:` | :older_adult: | `:older_adult:` | [top](#introduction) | +| [top](#people--body) | :older_man: | `:older_man:` | :older_woman: | `:older_woman:` | [top](#introduction) | + +### Person Gesture + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#people--body) | :frowning_person: | `:frowning_person:` | :frowning_man: | `:frowning_man:` | [top](#introduction) | +| [top](#people--body) | :frowning_woman: | `:frowning_woman:` | :pouting_face: | `:pouting_face:` | [top](#introduction) | +| [top](#people--body) | :pouting_man: | `:pouting_man:` | :pouting_woman: | `:pouting_woman:` | [top](#introduction) | +| [top](#people--body) | :no_good: | `:no_good:` | :ng_man: | `:ng_man:` `:no_good_man:` | [top](#introduction) | +| [top](#people--body) | :ng_woman: | `:ng_woman:` `:no_good_woman:` | :ok_person: | `:ok_person:` | [top](#introduction) | +| [top](#people--body) | :ok_man: | `:ok_man:` | :ok_woman: | `:ok_woman:` | [top](#introduction) | +| [top](#people--body) | :information_desk_person: | `:information_desk_person:` `:tipping_hand_person:` | :sassy_man: | `:sassy_man:` `:tipping_hand_man:` | [top](#introduction) | +| [top](#people--body) | :sassy_woman: | `:sassy_woman:` `:tipping_hand_woman:` | :raising_hand: | `:raising_hand:` | [top](#introduction) | +| [top](#people--body) | :raising_hand_man: | `:raising_hand_man:` | :raising_hand_woman: | `:raising_hand_woman:` | [top](#introduction) | +| [top](#people--body) | :deaf_person: | `:deaf_person:` | :deaf_man: | `:deaf_man:` | [top](#introduction) | +| [top](#people--body) | :deaf_woman: | `:deaf_woman:` | :bow: | `:bow:` | [top](#introduction) | +| [top](#people--body) | :bowing_man: | `:bowing_man:` | :bowing_woman: | `:bowing_woman:` | [top](#introduction) | +| [top](#people--body) | :facepalm: | `:facepalm:` | :man_facepalming: | `:man_facepalming:` | [top](#introduction) | +| [top](#people--body) | :woman_facepalming: | `:woman_facepalming:` | :shrug: | `:shrug:` | [top](#introduction) | +| [top](#people--body) | :man_shrugging: | `:man_shrugging:` | :woman_shrugging: | `:woman_shrugging:` | [top](#introduction) | + +### Person Role + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#people--body) | :health_worker: | `:health_worker:` | :man_health_worker: | `:man_health_worker:` | [top](#introduction) | +| [top](#people--body) | :woman_health_worker: | `:woman_health_worker:` | :student: | `:student:` | [top](#introduction) | +| [top](#people--body) | :man_student: | `:man_student:` | :woman_student: | `:woman_student:` | [top](#introduction) | +| [top](#people--body) | :teacher: | `:teacher:` | :man_teacher: | `:man_teacher:` | [top](#introduction) | +| [top](#people--body) | :woman_teacher: | `:woman_teacher:` | :judge: | `:judge:` | [top](#introduction) | +| [top](#people--body) | :man_judge: | `:man_judge:` | :woman_judge: | `:woman_judge:` | [top](#introduction) | +| [top](#people--body) | :farmer: | `:farmer:` | :man_farmer: | `:man_farmer:` | [top](#introduction) | +| [top](#people--body) | :woman_farmer: | `:woman_farmer:` | :cook: | `:cook:` | [top](#introduction) | +| [top](#people--body) | :man_cook: | `:man_cook:` | :woman_cook: | `:woman_cook:` | [top](#introduction) | +| [top](#people--body) | :mechanic: | `:mechanic:` | :man_mechanic: | `:man_mechanic:` | [top](#introduction) | +| [top](#people--body) | :woman_mechanic: | `:woman_mechanic:` | :factory_worker: | `:factory_worker:` | [top](#introduction) | +| [top](#people--body) | :man_factory_worker: | `:man_factory_worker:` | :woman_factory_worker: | `:woman_factory_worker:` | [top](#introduction) | +| [top](#people--body) | :office_worker: | `:office_worker:` | :man_office_worker: | `:man_office_worker:` | [top](#introduction) | +| [top](#people--body) | :woman_office_worker: | `:woman_office_worker:` | :scientist: | `:scientist:` | [top](#introduction) | +| [top](#people--body) | :man_scientist: | `:man_scientist:` | :woman_scientist: | `:woman_scientist:` | [top](#introduction) | +| [top](#people--body) | :technologist: | `:technologist:` | :man_technologist: | `:man_technologist:` | [top](#introduction) | +| [top](#people--body) | :woman_technologist: | `:woman_technologist:` | :singer: | `:singer:` | [top](#introduction) | +| [top](#people--body) | :man_singer: | `:man_singer:` | :woman_singer: | `:woman_singer:` | [top](#introduction) | +| [top](#people--body) | :artist: | `:artist:` | :man_artist: | `:man_artist:` | [top](#introduction) | +| [top](#people--body) | :woman_artist: | `:woman_artist:` | :pilot: | `:pilot:` | [top](#introduction) | +| [top](#people--body) | :man_pilot: | `:man_pilot:` | :woman_pilot: | `:woman_pilot:` | [top](#introduction) | +| [top](#people--body) | :astronaut: | `:astronaut:` | :man_astronaut: | `:man_astronaut:` | [top](#introduction) | +| [top](#people--body) | :woman_astronaut: | `:woman_astronaut:` | :firefighter: | `:firefighter:` | [top](#introduction) | +| [top](#people--body) | :man_firefighter: | `:man_firefighter:` | :woman_firefighter: | `:woman_firefighter:` | [top](#introduction) | +| [top](#people--body) | :cop: | `:cop:` `:police_officer:` | :policeman: | `:policeman:` | [top](#introduction) | +| [top](#people--body) | :policewoman: | `:policewoman:` | :detective: | `:detective:` | [top](#introduction) | +| [top](#people--body) | :male_detective: | `:male_detective:` | :female_detective: | `:female_detective:` | [top](#introduction) | +| [top](#people--body) | :guard: | `:guard:` | :guardsman: | `:guardsman:` | [top](#introduction) | +| [top](#people--body) | :guardswoman: | `:guardswoman:` | :ninja: | `:ninja:` | [top](#introduction) | +| [top](#people--body) | :construction_worker: | `:construction_worker:` | :construction_worker_man: | `:construction_worker_man:` | [top](#introduction) | +| [top](#people--body) | :construction_worker_woman: | `:construction_worker_woman:` | :prince: | `:prince:` | [top](#introduction) | +| [top](#people--body) | :princess: | `:princess:` | :person_with_turban: | `:person_with_turban:` | [top](#introduction) | +| [top](#people--body) | :man_with_turban: | `:man_with_turban:` | :woman_with_turban: | `:woman_with_turban:` | [top](#introduction) | +| [top](#people--body) | :man_with_gua_pi_mao: | `:man_with_gua_pi_mao:` | :woman_with_headscarf: | `:woman_with_headscarf:` | [top](#introduction) | +| [top](#people--body) | :person_in_tuxedo: | `:person_in_tuxedo:` | :man_in_tuxedo: | `:man_in_tuxedo:` | [top](#introduction) | +| [top](#people--body) | :woman_in_tuxedo: | `:woman_in_tuxedo:` | :person_with_veil: | `:person_with_veil:` | [top](#introduction) | +| [top](#people--body) | :man_with_veil: | `:man_with_veil:` | :bride_with_veil: | `:bride_with_veil:` `:woman_with_veil:` | [top](#introduction) | +| [top](#people--body) | :pregnant_woman: | `:pregnant_woman:` | :breast_feeding: | `:breast_feeding:` | [top](#introduction) | +| [top](#people--body) | :woman_feeding_baby: | `:woman_feeding_baby:` | :man_feeding_baby: | `:man_feeding_baby:` | [top](#introduction) | +| [top](#people--body) | :person_feeding_baby: | `:person_feeding_baby:` | | | [top](#introduction) | + +### Person Fantasy + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#people--body) | :angel: | `:angel:` | :santa: | `:santa:` | [top](#introduction) | +| [top](#people--body) | :mrs_claus: | `:mrs_claus:` | :mx_claus: | `:mx_claus:` | [top](#introduction) | +| [top](#people--body) | :superhero: | `:superhero:` | :superhero_man: | `:superhero_man:` | [top](#introduction) | +| [top](#people--body) | :superhero_woman: | `:superhero_woman:` | :supervillain: | `:supervillain:` | [top](#introduction) | +| [top](#people--body) | :supervillain_man: | `:supervillain_man:` | :supervillain_woman: | `:supervillain_woman:` | [top](#introduction) | +| [top](#people--body) | :mage: | `:mage:` | :mage_man: | `:mage_man:` | [top](#introduction) | +| [top](#people--body) | :mage_woman: | `:mage_woman:` | :fairy: | `:fairy:` | [top](#introduction) | +| [top](#people--body) | :fairy_man: | `:fairy_man:` | :fairy_woman: | `:fairy_woman:` | [top](#introduction) | +| [top](#people--body) | :vampire: | `:vampire:` | :vampire_man: | `:vampire_man:` | [top](#introduction) | +| [top](#people--body) | :vampire_woman: | `:vampire_woman:` | :merperson: | `:merperson:` | [top](#introduction) | +| [top](#people--body) | :merman: | `:merman:` | :mermaid: | `:mermaid:` | [top](#introduction) | +| [top](#people--body) | :elf: | `:elf:` | :elf_man: | `:elf_man:` | [top](#introduction) | +| [top](#people--body) | :elf_woman: | `:elf_woman:` | :genie: | `:genie:` | [top](#introduction) | +| [top](#people--body) | :genie_man: | `:genie_man:` | :genie_woman: | `:genie_woman:` | [top](#introduction) | +| [top](#people--body) | :zombie: | `:zombie:` | :zombie_man: | `:zombie_man:` | [top](#introduction) | +| [top](#people--body) | :zombie_woman: | `:zombie_woman:` | | | [top](#introduction) | + +### Person Activity + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#people--body) | :massage: | `:massage:` | :massage_man: | `:massage_man:` | [top](#introduction) | +| [top](#people--body) | :massage_woman: | `:massage_woman:` | :haircut: | `:haircut:` | [top](#introduction) | +| [top](#people--body) | :haircut_man: | `:haircut_man:` | :haircut_woman: | `:haircut_woman:` | [top](#introduction) | +| [top](#people--body) | :walking: | `:walking:` | :walking_man: | `:walking_man:` | [top](#introduction) | +| [top](#people--body) | :walking_woman: | `:walking_woman:` | :standing_person: | `:standing_person:` | [top](#introduction) | +| [top](#people--body) | :standing_man: | `:standing_man:` | :standing_woman: | `:standing_woman:` | [top](#introduction) | +| [top](#people--body) | :kneeling_person: | `:kneeling_person:` | :kneeling_man: | `:kneeling_man:` | [top](#introduction) | +| [top](#people--body) | :kneeling_woman: | `:kneeling_woman:` | :person_with_probing_cane: | `:person_with_probing_cane:` | [top](#introduction) | +| [top](#people--body) | :man_with_probing_cane: | `:man_with_probing_cane:` | :woman_with_probing_cane: | `:woman_with_probing_cane:` | [top](#introduction) | +| [top](#people--body) | :person_in_motorized_wheelchair: | `:person_in_motorized_wheelchair:` | :man_in_motorized_wheelchair: | `:man_in_motorized_wheelchair:` | [top](#introduction) | +| [top](#people--body) | :woman_in_motorized_wheelchair: | `:woman_in_motorized_wheelchair:` | :person_in_manual_wheelchair: | `:person_in_manual_wheelchair:` | [top](#introduction) | +| [top](#people--body) | :man_in_manual_wheelchair: | `:man_in_manual_wheelchair:` | :woman_in_manual_wheelchair: | `:woman_in_manual_wheelchair:` | [top](#introduction) | +| [top](#people--body) | :runner: | `:runner:` `:running:` | :running_man: | `:running_man:` | [top](#introduction) | +| [top](#people--body) | :running_woman: | `:running_woman:` | :dancer: | `:dancer:` `:woman_dancing:` | [top](#introduction) | +| [top](#people--body) | :man_dancing: | `:man_dancing:` | :business_suit_levitating: | `:business_suit_levitating:` | [top](#introduction) | +| [top](#people--body) | :dancers: | `:dancers:` | :dancing_men: | `:dancing_men:` | [top](#introduction) | +| [top](#people--body) | :dancing_women: | `:dancing_women:` | :sauna_person: | `:sauna_person:` | [top](#introduction) | +| [top](#people--body) | :sauna_man: | `:sauna_man:` | :sauna_woman: | `:sauna_woman:` | [top](#introduction) | +| [top](#people--body) | :climbing: | `:climbing:` | :climbing_man: | `:climbing_man:` | [top](#introduction) | +| [top](#people--body) | :climbing_woman: | `:climbing_woman:` | | | [top](#introduction) | + +### Person Sport + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#people--body) | :person_fencing: | `:person_fencing:` | :horse_racing: | `:horse_racing:` | [top](#introduction) | +| [top](#people--body) | :skier: | `:skier:` | :snowboarder: | `:snowboarder:` | [top](#introduction) | +| [top](#people--body) | :golfing: | `:golfing:` | :golfing_man: | `:golfing_man:` | [top](#introduction) | +| [top](#people--body) | :golfing_woman: | `:golfing_woman:` | :surfer: | `:surfer:` | [top](#introduction) | +| [top](#people--body) | :surfing_man: | `:surfing_man:` | :surfing_woman: | `:surfing_woman:` | [top](#introduction) | +| [top](#people--body) | :rowboat: | `:rowboat:` | :rowing_man: | `:rowing_man:` | [top](#introduction) | +| [top](#people--body) | :rowing_woman: | `:rowing_woman:` | :swimmer: | `:swimmer:` | [top](#introduction) | +| [top](#people--body) | :swimming_man: | `:swimming_man:` | :swimming_woman: | `:swimming_woman:` | [top](#introduction) | +| [top](#people--body) | :bouncing_ball_person: | `:bouncing_ball_person:` | :basketball_man: | `:basketball_man:` `:bouncing_ball_man:` | [top](#introduction) | +| [top](#people--body) | :basketball_woman: | `:basketball_woman:` `:bouncing_ball_woman:` | :weight_lifting: | `:weight_lifting:` | [top](#introduction) | +| [top](#people--body) | :weight_lifting_man: | `:weight_lifting_man:` | :weight_lifting_woman: | `:weight_lifting_woman:` | [top](#introduction) | +| [top](#people--body) | :bicyclist: | `:bicyclist:` | :biking_man: | `:biking_man:` | [top](#introduction) | +| [top](#people--body) | :biking_woman: | `:biking_woman:` | :mountain_bicyclist: | `:mountain_bicyclist:` | [top](#introduction) | +| [top](#people--body) | :mountain_biking_man: | `:mountain_biking_man:` | :mountain_biking_woman: | `:mountain_biking_woman:` | [top](#introduction) | +| [top](#people--body) | :cartwheeling: | `:cartwheeling:` | :man_cartwheeling: | `:man_cartwheeling:` | [top](#introduction) | +| [top](#people--body) | :woman_cartwheeling: | `:woman_cartwheeling:` | :wrestling: | `:wrestling:` | [top](#introduction) | +| [top](#people--body) | :men_wrestling: | `:men_wrestling:` | :women_wrestling: | `:women_wrestling:` | [top](#introduction) | +| [top](#people--body) | :water_polo: | `:water_polo:` | :man_playing_water_polo: | `:man_playing_water_polo:` | [top](#introduction) | +| [top](#people--body) | :woman_playing_water_polo: | `:woman_playing_water_polo:` | :handball_person: | `:handball_person:` | [top](#introduction) | +| [top](#people--body) | :man_playing_handball: | `:man_playing_handball:` | :woman_playing_handball: | `:woman_playing_handball:` | [top](#introduction) | +| [top](#people--body) | :juggling_person: | `:juggling_person:` | :man_juggling: | `:man_juggling:` | [top](#introduction) | +| [top](#people--body) | :woman_juggling: | `:woman_juggling:` | | | [top](#introduction) | + +### Person Resting + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#people--body) | :lotus_position: | `:lotus_position:` | :lotus_position_man: | `:lotus_position_man:` | [top](#introduction) | +| [top](#people--body) | :lotus_position_woman: | `:lotus_position_woman:` | :bath: | `:bath:` | [top](#introduction) | +| [top](#people--body) | :sleeping_bed: | `:sleeping_bed:` | | | [top](#introduction) | + +### Family + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#people--body) | :people_holding_hands: | `:people_holding_hands:` | :two_women_holding_hands: | `:two_women_holding_hands:` | [top](#introduction) | +| [top](#people--body) | :couple: | `:couple:` | :two_men_holding_hands: | `:two_men_holding_hands:` | [top](#introduction) | +| [top](#people--body) | :couplekiss: | `:couplekiss:` | :couplekiss_man_woman: | `:couplekiss_man_woman:` | [top](#introduction) | +| [top](#people--body) | :couplekiss_man_man: | `:couplekiss_man_man:` | :couplekiss_woman_woman: | `:couplekiss_woman_woman:` | [top](#introduction) | +| [top](#people--body) | :couple_with_heart: | `:couple_with_heart:` | :couple_with_heart_woman_man: | `:couple_with_heart_woman_man:` | [top](#introduction) | +| [top](#people--body) | :couple_with_heart_man_man: | `:couple_with_heart_man_man:` | :couple_with_heart_woman_woman: | `:couple_with_heart_woman_woman:` | [top](#introduction) | +| [top](#people--body) | :family_man_woman_boy: | `:family_man_woman_boy:` | :family_man_woman_girl: | `:family_man_woman_girl:` | [top](#introduction) | +| [top](#people--body) | :family_man_woman_girl_boy: | `:family_man_woman_girl_boy:` | :family_man_woman_boy_boy: | `:family_man_woman_boy_boy:` | [top](#introduction) | +| [top](#people--body) | :family_man_woman_girl_girl: | `:family_man_woman_girl_girl:` | :family_man_man_boy: | `:family_man_man_boy:` | [top](#introduction) | +| [top](#people--body) | :family_man_man_girl: | `:family_man_man_girl:` | :family_man_man_girl_boy: | `:family_man_man_girl_boy:` | [top](#introduction) | +| [top](#people--body) | :family_man_man_boy_boy: | `:family_man_man_boy_boy:` | :family_man_man_girl_girl: | `:family_man_man_girl_girl:` | [top](#introduction) | +| [top](#people--body) | :family_woman_woman_boy: | `:family_woman_woman_boy:` | :family_woman_woman_girl: | `:family_woman_woman_girl:` | [top](#introduction) | +| [top](#people--body) | :family_woman_woman_girl_boy: | `:family_woman_woman_girl_boy:` | :family_woman_woman_boy_boy: | `:family_woman_woman_boy_boy:` | [top](#introduction) | +| [top](#people--body) | :family_woman_woman_girl_girl: | `:family_woman_woman_girl_girl:` | :family_man_boy: | `:family_man_boy:` | [top](#introduction) | +| [top](#people--body) | :family_man_boy_boy: | `:family_man_boy_boy:` | :family_man_girl: | `:family_man_girl:` | [top](#introduction) | +| [top](#people--body) | :family_man_girl_boy: | `:family_man_girl_boy:` | :family_man_girl_girl: | `:family_man_girl_girl:` | [top](#introduction) | +| [top](#people--body) | :family_woman_boy: | `:family_woman_boy:` | :family_woman_boy_boy: | `:family_woman_boy_boy:` | [top](#introduction) | +| [top](#people--body) | :family_woman_girl: | `:family_woman_girl:` | :family_woman_girl_boy: | `:family_woman_girl_boy:` | [top](#introduction) | +| [top](#people--body) | :family_woman_girl_girl: | `:family_woman_girl_girl:` | | | [top](#introduction) | + +### Person Symbol + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#people--body) | :speaking_head: | `:speaking_head:` | :bust_in_silhouette: | `:bust_in_silhouette:` | [top](#introduction) | +| [top](#people--body) | :busts_in_silhouette: | `:busts_in_silhouette:` | :people_hugging: | `:people_hugging:` | [top](#introduction) | +| [top](#people--body) | :family: | `:family:` | :footprints: | `:footprints:` | [top](#introduction) | + +## Animals & Nature + +- [Animal Mammal](#animal-mammal) +- [Animal Bird](#animal-bird) +- [Animal Amphibian](#animal-amphibian) +- [Animal Reptile](#animal-reptile) +- [Animal Marine](#animal-marine) +- [Animal Bug](#animal-bug) +- [Plant Flower](#plant-flower) +- [Plant Other](#plant-other) + +### Animal Mammal + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#animals--nature) | :monkey_face: | `:monkey_face:` | :monkey: | `:monkey:` | [top](#introduction) | +| [top](#animals--nature) | :gorilla: | `:gorilla:` | :orangutan: | `:orangutan:` | [top](#introduction) | +| [top](#animals--nature) | :dog: | `:dog:` | :dog2: | `:dog2:` | [top](#introduction) | +| [top](#animals--nature) | :guide_dog: | `:guide_dog:` | :service_dog: | `:service_dog:` | [top](#introduction) | +| [top](#animals--nature) | :poodle: | `:poodle:` | :wolf: | `:wolf:` | [top](#introduction) | +| [top](#animals--nature) | :fox_face: | `:fox_face:` | :raccoon: | `:raccoon:` | [top](#introduction) | +| [top](#animals--nature) | :cat: | `:cat:` | :cat2: | `:cat2:` | [top](#introduction) | +| [top](#animals--nature) | :black_cat: | `:black_cat:` | :lion: | `:lion:` | [top](#introduction) | +| [top](#animals--nature) | :tiger: | `:tiger:` | :tiger2: | `:tiger2:` | [top](#introduction) | +| [top](#animals--nature) | :leopard: | `:leopard:` | :horse: | `:horse:` | [top](#introduction) | +| [top](#animals--nature) | :racehorse: | `:racehorse:` | :unicorn: | `:unicorn:` | [top](#introduction) | +| [top](#animals--nature) | :zebra: | `:zebra:` | :deer: | `:deer:` | [top](#introduction) | +| [top](#animals--nature) | :bison: | `:bison:` | :cow: | `:cow:` | [top](#introduction) | +| [top](#animals--nature) | :ox: | `:ox:` | :water_buffalo: | `:water_buffalo:` | [top](#introduction) | +| [top](#animals--nature) | :cow2: | `:cow2:` | :pig: | `:pig:` | [top](#introduction) | +| [top](#animals--nature) | :pig2: | `:pig2:` | :boar: | `:boar:` | [top](#introduction) | +| [top](#animals--nature) | :pig_nose: | `:pig_nose:` | :ram: | `:ram:` | [top](#introduction) | +| [top](#animals--nature) | :sheep: | `:sheep:` | :goat: | `:goat:` | [top](#introduction) | +| [top](#animals--nature) | :dromedary_camel: | `:dromedary_camel:` | :camel: | `:camel:` | [top](#introduction) | +| [top](#animals--nature) | :llama: | `:llama:` | :giraffe: | `:giraffe:` | [top](#introduction) | +| [top](#animals--nature) | :elephant: | `:elephant:` | :mammoth: | `:mammoth:` | [top](#introduction) | +| [top](#animals--nature) | :rhinoceros: | `:rhinoceros:` | :hippopotamus: | `:hippopotamus:` | [top](#introduction) | +| [top](#animals--nature) | :mouse: | `:mouse:` | :mouse2: | `:mouse2:` | [top](#introduction) | +| [top](#animals--nature) | :rat: | `:rat:` | :hamster: | `:hamster:` | [top](#introduction) | +| [top](#animals--nature) | :rabbit: | `:rabbit:` | :rabbit2: | `:rabbit2:` | [top](#introduction) | +| [top](#animals--nature) | :chipmunk: | `:chipmunk:` | :beaver: | `:beaver:` | [top](#introduction) | +| [top](#animals--nature) | :hedgehog: | `:hedgehog:` | :bat: | `:bat:` | [top](#introduction) | +| [top](#animals--nature) | :bear: | `:bear:` | :polar_bear: | `:polar_bear:` | [top](#introduction) | +| [top](#animals--nature) | :koala: | `:koala:` | :panda_face: | `:panda_face:` | [top](#introduction) | +| [top](#animals--nature) | :sloth: | `:sloth:` | :otter: | `:otter:` | [top](#introduction) | +| [top](#animals--nature) | :skunk: | `:skunk:` | :kangaroo: | `:kangaroo:` | [top](#introduction) | +| [top](#animals--nature) | :badger: | `:badger:` | :feet: | `:feet:` `:paw_prints:` | [top](#introduction) | + +### Animal Bird + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#animals--nature) | :turkey: | `:turkey:` | :chicken: | `:chicken:` | [top](#introduction) | +| [top](#animals--nature) | :rooster: | `:rooster:` | :hatching_chick: | `:hatching_chick:` | [top](#introduction) | +| [top](#animals--nature) | :baby_chick: | `:baby_chick:` | :hatched_chick: | `:hatched_chick:` | [top](#introduction) | +| [top](#animals--nature) | :bird: | `:bird:` | :penguin: | `:penguin:` | [top](#introduction) | +| [top](#animals--nature) | :dove: | `:dove:` | :eagle: | `:eagle:` | [top](#introduction) | +| [top](#animals--nature) | :duck: | `:duck:` | :swan: | `:swan:` | [top](#introduction) | +| [top](#animals--nature) | :owl: | `:owl:` | :dodo: | `:dodo:` | [top](#introduction) | +| [top](#animals--nature) | :feather: | `:feather:` | :flamingo: | `:flamingo:` | [top](#introduction) | +| [top](#animals--nature) | :peacock: | `:peacock:` | :parrot: | `:parrot:` | [top](#introduction) | + +### Animal Amphibian + +| | ico | shortcode | | +| - | :-: | - | - | +| [top](#animals--nature) | :frog: | `:frog:` | [top](#introduction) | + +### Animal Reptile + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#animals--nature) | :crocodile: | `:crocodile:` | :turtle: | `:turtle:` | [top](#introduction) | +| [top](#animals--nature) | :lizard: | `:lizard:` | :snake: | `:snake:` | [top](#introduction) | +| [top](#animals--nature) | :dragon_face: | `:dragon_face:` | :dragon: | `:dragon:` | [top](#introduction) | +| [top](#animals--nature) | :sauropod: | `:sauropod:` | :t-rex: | `:t-rex:` | [top](#introduction) | + +### Animal Marine + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#animals--nature) | :whale: | `:whale:` | :whale2: | `:whale2:` | [top](#introduction) | +| [top](#animals--nature) | :dolphin: | `:dolphin:` `:flipper:` | :seal: | `:seal:` | [top](#introduction) | +| [top](#animals--nature) | :fish: | `:fish:` | :tropical_fish: | `:tropical_fish:` | [top](#introduction) | +| [top](#animals--nature) | :blowfish: | `:blowfish:` | :shark: | `:shark:` | [top](#introduction) | +| [top](#animals--nature) | :octopus: | `:octopus:` | :shell: | `:shell:` | [top](#introduction) | + +### Animal Bug + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#animals--nature) | :snail: | `:snail:` | :butterfly: | `:butterfly:` | [top](#introduction) | +| [top](#animals--nature) | :bug: | `:bug:` | :ant: | `:ant:` | [top](#introduction) | +| [top](#animals--nature) | :bee: | `:bee:` `:honeybee:` | :beetle: | `:beetle:` | [top](#introduction) | +| [top](#animals--nature) | :lady_beetle: | `:lady_beetle:` | :cricket: | `:cricket:` | [top](#introduction) | +| [top](#animals--nature) | :cockroach: | `:cockroach:` | :spider: | `:spider:` | [top](#introduction) | +| [top](#animals--nature) | :spider_web: | `:spider_web:` | :scorpion: | `:scorpion:` | [top](#introduction) | +| [top](#animals--nature) | :mosquito: | `:mosquito:` | :fly: | `:fly:` | [top](#introduction) | +| [top](#animals--nature) | :worm: | `:worm:` | :microbe: | `:microbe:` | [top](#introduction) | + +### Plant Flower + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#animals--nature) | :bouquet: | `:bouquet:` | :cherry_blossom: | `:cherry_blossom:` | [top](#introduction) | +| [top](#animals--nature) | :white_flower: | `:white_flower:` | :rosette: | `:rosette:` | [top](#introduction) | +| [top](#animals--nature) | :rose: | `:rose:` | :wilted_flower: | `:wilted_flower:` | [top](#introduction) | +| [top](#animals--nature) | :hibiscus: | `:hibiscus:` | :sunflower: | `:sunflower:` | [top](#introduction) | +| [top](#animals--nature) | :blossom: | `:blossom:` | :tulip: | `:tulip:` | [top](#introduction) | + +### Plant Other + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#animals--nature) | :seedling: | `:seedling:` | :potted_plant: | `:potted_plant:` | [top](#introduction) | +| [top](#animals--nature) | :evergreen_tree: | `:evergreen_tree:` | :deciduous_tree: | `:deciduous_tree:` | [top](#introduction) | +| [top](#animals--nature) | :palm_tree: | `:palm_tree:` | :cactus: | `:cactus:` | [top](#introduction) | +| [top](#animals--nature) | :ear_of_rice: | `:ear_of_rice:` | :herb: | `:herb:` | [top](#introduction) | +| [top](#animals--nature) | :shamrock: | `:shamrock:` | :four_leaf_clover: | `:four_leaf_clover:` | [top](#introduction) | +| [top](#animals--nature) | :maple_leaf: | `:maple_leaf:` | :fallen_leaf: | `:fallen_leaf:` | [top](#introduction) | +| [top](#animals--nature) | :leaves: | `:leaves:` | :mushroom: | `:mushroom:` | [top](#introduction) | + +## Food & Drink + +- [Food Fruit](#food-fruit) +- [Food Vegetable](#food-vegetable) +- [Food Prepared](#food-prepared) +- [Food Asian](#food-asian) +- [Food Marine](#food-marine) +- [Food Sweet](#food-sweet) +- [Drink](#drink) +- [Dishware](#dishware) + +### Food Fruit + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#food--drink) | :grapes: | `:grapes:` | :melon: | `:melon:` | [top](#introduction) | +| [top](#food--drink) | :watermelon: | `:watermelon:` | :mandarin: | `:mandarin:` `:orange:` `:tangerine:` | [top](#introduction) | +| [top](#food--drink) | :lemon: | `:lemon:` | :banana: | `:banana:` | [top](#introduction) | +| [top](#food--drink) | :pineapple: | `:pineapple:` | :mango: | `:mango:` | [top](#introduction) | +| [top](#food--drink) | :apple: | `:apple:` | :green_apple: | `:green_apple:` | [top](#introduction) | +| [top](#food--drink) | :pear: | `:pear:` | :peach: | `:peach:` | [top](#introduction) | +| [top](#food--drink) | :cherries: | `:cherries:` | :strawberry: | `:strawberry:` | [top](#introduction) | +| [top](#food--drink) | :blueberries: | `:blueberries:` | :kiwi_fruit: | `:kiwi_fruit:` | [top](#introduction) | +| [top](#food--drink) | :tomato: | `:tomato:` | :olive: | `:olive:` | [top](#introduction) | +| [top](#food--drink) | :coconut: | `:coconut:` | | | [top](#introduction) | + +### Food Vegetable + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#food--drink) | :avocado: | `:avocado:` | :eggplant: | `:eggplant:` | [top](#introduction) | +| [top](#food--drink) | :potato: | `:potato:` | :carrot: | `:carrot:` | [top](#introduction) | +| [top](#food--drink) | :corn: | `:corn:` | :hot_pepper: | `:hot_pepper:` | [top](#introduction) | +| [top](#food--drink) | :bell_pepper: | `:bell_pepper:` | :cucumber: | `:cucumber:` | [top](#introduction) | +| [top](#food--drink) | :leafy_green: | `:leafy_green:` | :broccoli: | `:broccoli:` | [top](#introduction) | +| [top](#food--drink) | :garlic: | `:garlic:` | :onion: | `:onion:` | [top](#introduction) | +| [top](#food--drink) | :peanuts: | `:peanuts:` | :chestnut: | `:chestnut:` | [top](#introduction) | + +### Food Prepared + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#food--drink) | :bread: | `:bread:` | :croissant: | `:croissant:` | [top](#introduction) | +| [top](#food--drink) | :baguette_bread: | `:baguette_bread:` | :flatbread: | `:flatbread:` | [top](#introduction) | +| [top](#food--drink) | :pretzel: | `:pretzel:` | :bagel: | `:bagel:` | [top](#introduction) | +| [top](#food--drink) | :pancakes: | `:pancakes:` | :waffle: | `:waffle:` | [top](#introduction) | +| [top](#food--drink) | :cheese: | `:cheese:` | :meat_on_bone: | `:meat_on_bone:` | [top](#introduction) | +| [top](#food--drink) | :poultry_leg: | `:poultry_leg:` | :cut_of_meat: | `:cut_of_meat:` | [top](#introduction) | +| [top](#food--drink) | :bacon: | `:bacon:` | :hamburger: | `:hamburger:` | [top](#introduction) | +| [top](#food--drink) | :fries: | `:fries:` | :pizza: | `:pizza:` | [top](#introduction) | +| [top](#food--drink) | :hotdog: | `:hotdog:` | :sandwich: | `:sandwich:` | [top](#introduction) | +| [top](#food--drink) | :taco: | `:taco:` | :burrito: | `:burrito:` | [top](#introduction) | +| [top](#food--drink) | :tamale: | `:tamale:` | :stuffed_flatbread: | `:stuffed_flatbread:` | [top](#introduction) | +| [top](#food--drink) | :falafel: | `:falafel:` | :egg: | `:egg:` | [top](#introduction) | +| [top](#food--drink) | :fried_egg: | `:fried_egg:` | :shallow_pan_of_food: | `:shallow_pan_of_food:` | [top](#introduction) | +| [top](#food--drink) | :stew: | `:stew:` | :fondue: | `:fondue:` | [top](#introduction) | +| [top](#food--drink) | :bowl_with_spoon: | `:bowl_with_spoon:` | :green_salad: | `:green_salad:` | [top](#introduction) | +| [top](#food--drink) | :popcorn: | `:popcorn:` | :butter: | `:butter:` | [top](#introduction) | +| [top](#food--drink) | :salt: | `:salt:` | :canned_food: | `:canned_food:` | [top](#introduction) | + +### Food Asian + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#food--drink) | :bento: | `:bento:` | :rice_cracker: | `:rice_cracker:` | [top](#introduction) | +| [top](#food--drink) | :rice_ball: | `:rice_ball:` | :rice: | `:rice:` | [top](#introduction) | +| [top](#food--drink) | :curry: | `:curry:` | :ramen: | `:ramen:` | [top](#introduction) | +| [top](#food--drink) | :spaghetti: | `:spaghetti:` | :sweet_potato: | `:sweet_potato:` | [top](#introduction) | +| [top](#food--drink) | :oden: | `:oden:` | :sushi: | `:sushi:` | [top](#introduction) | +| [top](#food--drink) | :fried_shrimp: | `:fried_shrimp:` | :fish_cake: | `:fish_cake:` | [top](#introduction) | +| [top](#food--drink) | :moon_cake: | `:moon_cake:` | :dango: | `:dango:` | [top](#introduction) | +| [top](#food--drink) | :dumpling: | `:dumpling:` | :fortune_cookie: | `:fortune_cookie:` | [top](#introduction) | +| [top](#food--drink) | :takeout_box: | `:takeout_box:` | | | [top](#introduction) | + +### Food Marine + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#food--drink) | :crab: | `:crab:` | :lobster: | `:lobster:` | [top](#introduction) | +| [top](#food--drink) | :shrimp: | `:shrimp:` | :squid: | `:squid:` | [top](#introduction) | +| [top](#food--drink) | :oyster: | `:oyster:` | | | [top](#introduction) | + +### Food Sweet + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#food--drink) | :icecream: | `:icecream:` | :shaved_ice: | `:shaved_ice:` | [top](#introduction) | +| [top](#food--drink) | :ice_cream: | `:ice_cream:` | :doughnut: | `:doughnut:` | [top](#introduction) | +| [top](#food--drink) | :cookie: | `:cookie:` | :birthday: | `:birthday:` | [top](#introduction) | +| [top](#food--drink) | :cake: | `:cake:` | :cupcake: | `:cupcake:` | [top](#introduction) | +| [top](#food--drink) | :pie: | `:pie:` | :chocolate_bar: | `:chocolate_bar:` | [top](#introduction) | +| [top](#food--drink) | :candy: | `:candy:` | :lollipop: | `:lollipop:` | [top](#introduction) | +| [top](#food--drink) | :custard: | `:custard:` | :honey_pot: | `:honey_pot:` | [top](#introduction) | + +### Drink + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#food--drink) | :baby_bottle: | `:baby_bottle:` | :milk_glass: | `:milk_glass:` | [top](#introduction) | +| [top](#food--drink) | :coffee: | `:coffee:` | :teapot: | `:teapot:` | [top](#introduction) | +| [top](#food--drink) | :tea: | `:tea:` | :sake: | `:sake:` | [top](#introduction) | +| [top](#food--drink) | :champagne: | `:champagne:` | :wine_glass: | `:wine_glass:` | [top](#introduction) | +| [top](#food--drink) | :cocktail: | `:cocktail:` | :tropical_drink: | `:tropical_drink:` | [top](#introduction) | +| [top](#food--drink) | :beer: | `:beer:` | :beers: | `:beers:` | [top](#introduction) | +| [top](#food--drink) | :clinking_glasses: | `:clinking_glasses:` | :tumbler_glass: | `:tumbler_glass:` | [top](#introduction) | +| [top](#food--drink) | :cup_with_straw: | `:cup_with_straw:` | :bubble_tea: | `:bubble_tea:` | [top](#introduction) | +| [top](#food--drink) | :beverage_box: | `:beverage_box:` | :mate: | `:mate:` | [top](#introduction) | +| [top](#food--drink) | :ice_cube: | `:ice_cube:` | | | [top](#introduction) | + +### Dishware + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#food--drink) | :chopsticks: | `:chopsticks:` | :plate_with_cutlery: | `:plate_with_cutlery:` | [top](#introduction) | +| [top](#food--drink) | :fork_and_knife: | `:fork_and_knife:` | :spoon: | `:spoon:` | [top](#introduction) | +| [top](#food--drink) | :hocho: | `:hocho:` `:knife:` | :amphora: | `:amphora:` | [top](#introduction) | + +## Travel & Places + +- [Place Map](#place-map) +- [Place Geographic](#place-geographic) +- [Place Building](#place-building) +- [Place Religious](#place-religious) +- [Place Other](#place-other) +- [Transport Ground](#transport-ground) +- [Transport Water](#transport-water) +- [Transport Air](#transport-air) +- [Hotel](#hotel) +- [Time](#time) +- [Sky & Weather](#sky--weather) + +### Place Map + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#travel--places) | :earth_africa: | `:earth_africa:` | :earth_americas: | `:earth_americas:` | [top](#introduction) | +| [top](#travel--places) | :earth_asia: | `:earth_asia:` | :globe_with_meridians: | `:globe_with_meridians:` | [top](#introduction) | +| [top](#travel--places) | :world_map: | `:world_map:` | :japan: | `:japan:` | [top](#introduction) | +| [top](#travel--places) | :compass: | `:compass:` | | | [top](#introduction) | + +### Place Geographic + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#travel--places) | :mountain_snow: | `:mountain_snow:` | :mountain: | `:mountain:` | [top](#introduction) | +| [top](#travel--places) | :volcano: | `:volcano:` | :mount_fuji: | `:mount_fuji:` | [top](#introduction) | +| [top](#travel--places) | :camping: | `:camping:` | :beach_umbrella: | `:beach_umbrella:` | [top](#introduction) | +| [top](#travel--places) | :desert: | `:desert:` | :desert_island: | `:desert_island:` | [top](#introduction) | +| [top](#travel--places) | :national_park: | `:national_park:` | | | [top](#introduction) | + +### Place Building + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#travel--places) | :stadium: | `:stadium:` | :classical_building: | `:classical_building:` | [top](#introduction) | +| [top](#travel--places) | :building_construction: | `:building_construction:` | :bricks: | `:bricks:` | [top](#introduction) | +| [top](#travel--places) | :rock: | `:rock:` | :wood: | `:wood:` | [top](#introduction) | +| [top](#travel--places) | :hut: | `:hut:` | :houses: | `:houses:` | [top](#introduction) | +| [top](#travel--places) | :derelict_house: | `:derelict_house:` | :house: | `:house:` | [top](#introduction) | +| [top](#travel--places) | :house_with_garden: | `:house_with_garden:` | :office: | `:office:` | [top](#introduction) | +| [top](#travel--places) | :post_office: | `:post_office:` | :european_post_office: | `:european_post_office:` | [top](#introduction) | +| [top](#travel--places) | :hospital: | `:hospital:` | :bank: | `:bank:` | [top](#introduction) | +| [top](#travel--places) | :hotel: | `:hotel:` | :love_hotel: | `:love_hotel:` | [top](#introduction) | +| [top](#travel--places) | :convenience_store: | `:convenience_store:` | :school: | `:school:` | [top](#introduction) | +| [top](#travel--places) | :department_store: | `:department_store:` | :factory: | `:factory:` | [top](#introduction) | +| [top](#travel--places) | :japanese_castle: | `:japanese_castle:` | :european_castle: | `:european_castle:` | [top](#introduction) | +| [top](#travel--places) | :wedding: | `:wedding:` | :tokyo_tower: | `:tokyo_tower:` | [top](#introduction) | +| [top](#travel--places) | :statue_of_liberty: | `:statue_of_liberty:` | | | [top](#introduction) | + +### Place Religious + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#travel--places) | :church: | `:church:` | :mosque: | `:mosque:` | [top](#introduction) | +| [top](#travel--places) | :hindu_temple: | `:hindu_temple:` | :synagogue: | `:synagogue:` | [top](#introduction) | +| [top](#travel--places) | :shinto_shrine: | `:shinto_shrine:` | :kaaba: | `:kaaba:` | [top](#introduction) | + +### Place Other + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#travel--places) | :fountain: | `:fountain:` | :tent: | `:tent:` | [top](#introduction) | +| [top](#travel--places) | :foggy: | `:foggy:` | :night_with_stars: | `:night_with_stars:` | [top](#introduction) | +| [top](#travel--places) | :cityscape: | `:cityscape:` | :sunrise_over_mountains: | `:sunrise_over_mountains:` | [top](#introduction) | +| [top](#travel--places) | :sunrise: | `:sunrise:` | :city_sunset: | `:city_sunset:` | [top](#introduction) | +| [top](#travel--places) | :city_sunrise: | `:city_sunrise:` | :bridge_at_night: | `:bridge_at_night:` | [top](#introduction) | +| [top](#travel--places) | :hotsprings: | `:hotsprings:` | :carousel_horse: | `:carousel_horse:` | [top](#introduction) | +| [top](#travel--places) | :ferris_wheel: | `:ferris_wheel:` | :roller_coaster: | `:roller_coaster:` | [top](#introduction) | +| [top](#travel--places) | :barber: | `:barber:` | :circus_tent: | `:circus_tent:` | [top](#introduction) | + +### Transport Ground + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#travel--places) | :steam_locomotive: | `:steam_locomotive:` | :railway_car: | `:railway_car:` | [top](#introduction) | +| [top](#travel--places) | :bullettrain_side: | `:bullettrain_side:` | :bullettrain_front: | `:bullettrain_front:` | [top](#introduction) | +| [top](#travel--places) | :train2: | `:train2:` | :metro: | `:metro:` | [top](#introduction) | +| [top](#travel--places) | :light_rail: | `:light_rail:` | :station: | `:station:` | [top](#introduction) | +| [top](#travel--places) | :tram: | `:tram:` | :monorail: | `:monorail:` | [top](#introduction) | +| [top](#travel--places) | :mountain_railway: | `:mountain_railway:` | :train: | `:train:` | [top](#introduction) | +| [top](#travel--places) | :bus: | `:bus:` | :oncoming_bus: | `:oncoming_bus:` | [top](#introduction) | +| [top](#travel--places) | :trolleybus: | `:trolleybus:` | :minibus: | `:minibus:` | [top](#introduction) | +| [top](#travel--places) | :ambulance: | `:ambulance:` | :fire_engine: | `:fire_engine:` | [top](#introduction) | +| [top](#travel--places) | :police_car: | `:police_car:` | :oncoming_police_car: | `:oncoming_police_car:` | [top](#introduction) | +| [top](#travel--places) | :taxi: | `:taxi:` | :oncoming_taxi: | `:oncoming_taxi:` | [top](#introduction) | +| [top](#travel--places) | :car: | `:car:` `:red_car:` | :oncoming_automobile: | `:oncoming_automobile:` | [top](#introduction) | +| [top](#travel--places) | :blue_car: | `:blue_car:` | :pickup_truck: | `:pickup_truck:` | [top](#introduction) | +| [top](#travel--places) | :truck: | `:truck:` | :articulated_lorry: | `:articulated_lorry:` | [top](#introduction) | +| [top](#travel--places) | :tractor: | `:tractor:` | :racing_car: | `:racing_car:` | [top](#introduction) | +| [top](#travel--places) | :motorcycle: | `:motorcycle:` | :motor_scooter: | `:motor_scooter:` | [top](#introduction) | +| [top](#travel--places) | :manual_wheelchair: | `:manual_wheelchair:` | :motorized_wheelchair: | `:motorized_wheelchair:` | [top](#introduction) | +| [top](#travel--places) | :auto_rickshaw: | `:auto_rickshaw:` | :bike: | `:bike:` | [top](#introduction) | +| [top](#travel--places) | :kick_scooter: | `:kick_scooter:` | :skateboard: | `:skateboard:` | [top](#introduction) | +| [top](#travel--places) | :roller_skate: | `:roller_skate:` | :busstop: | `:busstop:` | [top](#introduction) | +| [top](#travel--places) | :motorway: | `:motorway:` | :railway_track: | `:railway_track:` | [top](#introduction) | +| [top](#travel--places) | :oil_drum: | `:oil_drum:` | :fuelpump: | `:fuelpump:` | [top](#introduction) | +| [top](#travel--places) | :rotating_light: | `:rotating_light:` | :traffic_light: | `:traffic_light:` | [top](#introduction) | +| [top](#travel--places) | :vertical_traffic_light: | `:vertical_traffic_light:` | :stop_sign: | `:stop_sign:` | [top](#introduction) | +| [top](#travel--places) | :construction: | `:construction:` | | | [top](#introduction) | + +### Transport Water + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#travel--places) | :anchor: | `:anchor:` | :boat: | `:boat:` `:sailboat:` | [top](#introduction) | +| [top](#travel--places) | :canoe: | `:canoe:` | :speedboat: | `:speedboat:` | [top](#introduction) | +| [top](#travel--places) | :passenger_ship: | `:passenger_ship:` | :ferry: | `:ferry:` | [top](#introduction) | +| [top](#travel--places) | :motor_boat: | `:motor_boat:` | :ship: | `:ship:` | [top](#introduction) | + +### Transport Air + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#travel--places) | :airplane: | `:airplane:` | :small_airplane: | `:small_airplane:` | [top](#introduction) | +| [top](#travel--places) | :flight_departure: | `:flight_departure:` | :flight_arrival: | `:flight_arrival:` | [top](#introduction) | +| [top](#travel--places) | :parachute: | `:parachute:` | :seat: | `:seat:` | [top](#introduction) | +| [top](#travel--places) | :helicopter: | `:helicopter:` | :suspension_railway: | `:suspension_railway:` | [top](#introduction) | +| [top](#travel--places) | :mountain_cableway: | `:mountain_cableway:` | :aerial_tramway: | `:aerial_tramway:` | [top](#introduction) | +| [top](#travel--places) | :artificial_satellite: | `:artificial_satellite:` | :rocket: | `:rocket:` | [top](#introduction) | +| [top](#travel--places) | :flying_saucer: | `:flying_saucer:` | | | [top](#introduction) | + +### Hotel + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#travel--places) | :bellhop_bell: | `:bellhop_bell:` | :luggage: | `:luggage:` | [top](#introduction) | + +### Time + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#travel--places) | :hourglass: | `:hourglass:` | :hourglass_flowing_sand: | `:hourglass_flowing_sand:` | [top](#introduction) | +| [top](#travel--places) | :watch: | `:watch:` | :alarm_clock: | `:alarm_clock:` | [top](#introduction) | +| [top](#travel--places) | :stopwatch: | `:stopwatch:` | :timer_clock: | `:timer_clock:` | [top](#introduction) | +| [top](#travel--places) | :mantelpiece_clock: | `:mantelpiece_clock:` | :clock12: | `:clock12:` | [top](#introduction) | +| [top](#travel--places) | :clock1230: | `:clock1230:` | :clock1: | `:clock1:` | [top](#introduction) | +| [top](#travel--places) | :clock130: | `:clock130:` | :clock2: | `:clock2:` | [top](#introduction) | +| [top](#travel--places) | :clock230: | `:clock230:` | :clock3: | `:clock3:` | [top](#introduction) | +| [top](#travel--places) | :clock330: | `:clock330:` | :clock4: | `:clock4:` | [top](#introduction) | +| [top](#travel--places) | :clock430: | `:clock430:` | :clock5: | `:clock5:` | [top](#introduction) | +| [top](#travel--places) | :clock530: | `:clock530:` | :clock6: | `:clock6:` | [top](#introduction) | +| [top](#travel--places) | :clock630: | `:clock630:` | :clock7: | `:clock7:` | [top](#introduction) | +| [top](#travel--places) | :clock730: | `:clock730:` | :clock8: | `:clock8:` | [top](#introduction) | +| [top](#travel--places) | :clock830: | `:clock830:` | :clock9: | `:clock9:` | [top](#introduction) | +| [top](#travel--places) | :clock930: | `:clock930:` | :clock10: | `:clock10:` | [top](#introduction) | +| [top](#travel--places) | :clock1030: | `:clock1030:` | :clock11: | `:clock11:` | [top](#introduction) | +| [top](#travel--places) | :clock1130: | `:clock1130:` | | | [top](#introduction) | + +### Sky & Weather + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#travel--places) | :new_moon: | `:new_moon:` | :waxing_crescent_moon: | `:waxing_crescent_moon:` | [top](#introduction) | +| [top](#travel--places) | :first_quarter_moon: | `:first_quarter_moon:` | :moon: | `:moon:` `:waxing_gibbous_moon:` | [top](#introduction) | +| [top](#travel--places) | :full_moon: | `:full_moon:` | :waning_gibbous_moon: | `:waning_gibbous_moon:` | [top](#introduction) | +| [top](#travel--places) | :last_quarter_moon: | `:last_quarter_moon:` | :waning_crescent_moon: | `:waning_crescent_moon:` | [top](#introduction) | +| [top](#travel--places) | :crescent_moon: | `:crescent_moon:` | :new_moon_with_face: | `:new_moon_with_face:` | [top](#introduction) | +| [top](#travel--places) | :first_quarter_moon_with_face: | `:first_quarter_moon_with_face:` | :last_quarter_moon_with_face: | `:last_quarter_moon_with_face:` | [top](#introduction) | +| [top](#travel--places) | :thermometer: | `:thermometer:` | :sunny: | `:sunny:` | [top](#introduction) | +| [top](#travel--places) | :full_moon_with_face: | `:full_moon_with_face:` | :sun_with_face: | `:sun_with_face:` | [top](#introduction) | +| [top](#travel--places) | :ringed_planet: | `:ringed_planet:` | :star: | `:star:` | [top](#introduction) | +| [top](#travel--places) | :star2: | `:star2:` | :stars: | `:stars:` | [top](#introduction) | +| [top](#travel--places) | :milky_way: | `:milky_way:` | :cloud: | `:cloud:` | [top](#introduction) | +| [top](#travel--places) | :partly_sunny: | `:partly_sunny:` | :cloud_with_lightning_and_rain: | `:cloud_with_lightning_and_rain:` | [top](#introduction) | +| [top](#travel--places) | :sun_behind_small_cloud: | `:sun_behind_small_cloud:` | :sun_behind_large_cloud: | `:sun_behind_large_cloud:` | [top](#introduction) | +| [top](#travel--places) | :sun_behind_rain_cloud: | `:sun_behind_rain_cloud:` | :cloud_with_rain: | `:cloud_with_rain:` | [top](#introduction) | +| [top](#travel--places) | :cloud_with_snow: | `:cloud_with_snow:` | :cloud_with_lightning: | `:cloud_with_lightning:` | [top](#introduction) | +| [top](#travel--places) | :tornado: | `:tornado:` | :fog: | `:fog:` | [top](#introduction) | +| [top](#travel--places) | :wind_face: | `:wind_face:` | :cyclone: | `:cyclone:` | [top](#introduction) | +| [top](#travel--places) | :rainbow: | `:rainbow:` | :closed_umbrella: | `:closed_umbrella:` | [top](#introduction) | +| [top](#travel--places) | :open_umbrella: | `:open_umbrella:` | :umbrella: | `:umbrella:` | [top](#introduction) | +| [top](#travel--places) | :parasol_on_ground: | `:parasol_on_ground:` | :zap: | `:zap:` | [top](#introduction) | +| [top](#travel--places) | :snowflake: | `:snowflake:` | :snowman_with_snow: | `:snowman_with_snow:` | [top](#introduction) | +| [top](#travel--places) | :snowman: | `:snowman:` | :comet: | `:comet:` | [top](#introduction) | +| [top](#travel--places) | :fire: | `:fire:` | :droplet: | `:droplet:` | [top](#introduction) | +| [top](#travel--places) | :ocean: | `:ocean:` | | | [top](#introduction) | + +## Activities + +- [Event](#event) +- [Award Medal](#award-medal) +- [Sport](#sport) +- [Game](#game) +- [Arts & Crafts](#arts--crafts) + +### Event + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#activities) | :jack_o_lantern: | `:jack_o_lantern:` | :christmas_tree: | `:christmas_tree:` | [top](#introduction) | +| [top](#activities) | :fireworks: | `:fireworks:` | :sparkler: | `:sparkler:` | [top](#introduction) | +| [top](#activities) | :firecracker: | `:firecracker:` | :sparkles: | `:sparkles:` | [top](#introduction) | +| [top](#activities) | :balloon: | `:balloon:` | :tada: | `:tada:` | [top](#introduction) | +| [top](#activities) | :confetti_ball: | `:confetti_ball:` | :tanabata_tree: | `:tanabata_tree:` | [top](#introduction) | +| [top](#activities) | :bamboo: | `:bamboo:` | :dolls: | `:dolls:` | [top](#introduction) | +| [top](#activities) | :flags: | `:flags:` | :wind_chime: | `:wind_chime:` | [top](#introduction) | +| [top](#activities) | :rice_scene: | `:rice_scene:` | :red_envelope: | `:red_envelope:` | [top](#introduction) | +| [top](#activities) | :ribbon: | `:ribbon:` | :gift: | `:gift:` | [top](#introduction) | +| [top](#activities) | :reminder_ribbon: | `:reminder_ribbon:` | :tickets: | `:tickets:` | [top](#introduction) | +| [top](#activities) | :ticket: | `:ticket:` | | | [top](#introduction) | + +### Award Medal + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#activities) | :medal_military: | `:medal_military:` | :trophy: | `:trophy:` | [top](#introduction) | +| [top](#activities) | :medal_sports: | `:medal_sports:` | :1st_place_medal: | `:1st_place_medal:` | [top](#introduction) | +| [top](#activities) | :2nd_place_medal: | `:2nd_place_medal:` | :3rd_place_medal: | `:3rd_place_medal:` | [top](#introduction) | + +### Sport + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#activities) | :soccer: | `:soccer:` | :baseball: | `:baseball:` | [top](#introduction) | +| [top](#activities) | :softball: | `:softball:` | :basketball: | `:basketball:` | [top](#introduction) | +| [top](#activities) | :volleyball: | `:volleyball:` | :football: | `:football:` | [top](#introduction) | +| [top](#activities) | :rugby_football: | `:rugby_football:` | :tennis: | `:tennis:` | [top](#introduction) | +| [top](#activities) | :flying_disc: | `:flying_disc:` | :bowling: | `:bowling:` | [top](#introduction) | +| [top](#activities) | :cricket_game: | `:cricket_game:` | :field_hockey: | `:field_hockey:` | [top](#introduction) | +| [top](#activities) | :ice_hockey: | `:ice_hockey:` | :lacrosse: | `:lacrosse:` | [top](#introduction) | +| [top](#activities) | :ping_pong: | `:ping_pong:` | :badminton: | `:badminton:` | [top](#introduction) | +| [top](#activities) | :boxing_glove: | `:boxing_glove:` | :martial_arts_uniform: | `:martial_arts_uniform:` | [top](#introduction) | +| [top](#activities) | :goal_net: | `:goal_net:` | :golf: | `:golf:` | [top](#introduction) | +| [top](#activities) | :ice_skate: | `:ice_skate:` | :fishing_pole_and_fish: | `:fishing_pole_and_fish:` | [top](#introduction) | +| [top](#activities) | :diving_mask: | `:diving_mask:` | :running_shirt_with_sash: | `:running_shirt_with_sash:` | [top](#introduction) | +| [top](#activities) | :ski: | `:ski:` | :sled: | `:sled:` | [top](#introduction) | +| [top](#activities) | :curling_stone: | `:curling_stone:` | | | [top](#introduction) | + +### Game + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#activities) | :dart: | `:dart:` | :yo_yo: | `:yo_yo:` | [top](#introduction) | +| [top](#activities) | :kite: | `:kite:` | :gun: | `:gun:` | [top](#introduction) | +| [top](#activities) | :8ball: | `:8ball:` | :crystal_ball: | `:crystal_ball:` | [top](#introduction) | +| [top](#activities) | :magic_wand: | `:magic_wand:` | :video_game: | `:video_game:` | [top](#introduction) | +| [top](#activities) | :joystick: | `:joystick:` | :slot_machine: | `:slot_machine:` | [top](#introduction) | +| [top](#activities) | :game_die: | `:game_die:` | :jigsaw: | `:jigsaw:` | [top](#introduction) | +| [top](#activities) | :teddy_bear: | `:teddy_bear:` | :pinata: | `:pinata:` | [top](#introduction) | +| [top](#activities) | :nesting_dolls: | `:nesting_dolls:` | :spades: | `:spades:` | [top](#introduction) | +| [top](#activities) | :hearts: | `:hearts:` | :diamonds: | `:diamonds:` | [top](#introduction) | +| [top](#activities) | :clubs: | `:clubs:` | :chess_pawn: | `:chess_pawn:` | [top](#introduction) | +| [top](#activities) | :black_joker: | `:black_joker:` | :mahjong: | `:mahjong:` | [top](#introduction) | +| [top](#activities) | :flower_playing_cards: | `:flower_playing_cards:` | | | [top](#introduction) | + +### Arts & Crafts + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#activities) | :performing_arts: | `:performing_arts:` | :framed_picture: | `:framed_picture:` | [top](#introduction) | +| [top](#activities) | :art: | `:art:` | :thread: | `:thread:` | [top](#introduction) | +| [top](#activities) | :sewing_needle: | `:sewing_needle:` | :yarn: | `:yarn:` | [top](#introduction) | +| [top](#activities) | :knot: | `:knot:` | | | [top](#introduction) | + +## Objects + +- [Clothing](#clothing) +- [Sound](#sound) +- [Music](#music) +- [Musical Instrument](#musical-instrument) +- [Phone](#phone) +- [Computer](#computer) +- [Light & Video](#light--video) +- [Book Paper](#book-paper) +- [Money](#money) +- [Mail](#mail) +- [Writing](#writing) +- [Office](#office) +- [Lock](#lock) +- [Tool](#tool) +- [Science](#science) +- [Medical](#medical) +- [Household](#household) +- [Other Object](#other-object) + +### Clothing + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#objects) | :eyeglasses: | `:eyeglasses:` | :dark_sunglasses: | `:dark_sunglasses:` | [top](#introduction) | +| [top](#objects) | :goggles: | `:goggles:` | :lab_coat: | `:lab_coat:` | [top](#introduction) | +| [top](#objects) | :safety_vest: | `:safety_vest:` | :necktie: | `:necktie:` | [top](#introduction) | +| [top](#objects) | :shirt: | `:shirt:` `:tshirt:` | :jeans: | `:jeans:` | [top](#introduction) | +| [top](#objects) | :scarf: | `:scarf:` | :gloves: | `:gloves:` | [top](#introduction) | +| [top](#objects) | :coat: | `:coat:` | :socks: | `:socks:` | [top](#introduction) | +| [top](#objects) | :dress: | `:dress:` | :kimono: | `:kimono:` | [top](#introduction) | +| [top](#objects) | :sari: | `:sari:` | :one_piece_swimsuit: | `:one_piece_swimsuit:` | [top](#introduction) | +| [top](#objects) | :swim_brief: | `:swim_brief:` | :shorts: | `:shorts:` | [top](#introduction) | +| [top](#objects) | :bikini: | `:bikini:` | :womans_clothes: | `:womans_clothes:` | [top](#introduction) | +| [top](#objects) | :purse: | `:purse:` | :handbag: | `:handbag:` | [top](#introduction) | +| [top](#objects) | :pouch: | `:pouch:` | :shopping: | `:shopping:` | [top](#introduction) | +| [top](#objects) | :school_satchel: | `:school_satchel:` | :thong_sandal: | `:thong_sandal:` | [top](#introduction) | +| [top](#objects) | :mans_shoe: | `:mans_shoe:` `:shoe:` | :athletic_shoe: | `:athletic_shoe:` | [top](#introduction) | +| [top](#objects) | :hiking_boot: | `:hiking_boot:` | :flat_shoe: | `:flat_shoe:` | [top](#introduction) | +| [top](#objects) | :high_heel: | `:high_heel:` | :sandal: | `:sandal:` | [top](#introduction) | +| [top](#objects) | :ballet_shoes: | `:ballet_shoes:` | :boot: | `:boot:` | [top](#introduction) | +| [top](#objects) | :crown: | `:crown:` | :womans_hat: | `:womans_hat:` | [top](#introduction) | +| [top](#objects) | :tophat: | `:tophat:` | :mortar_board: | `:mortar_board:` | [top](#introduction) | +| [top](#objects) | :billed_cap: | `:billed_cap:` | :military_helmet: | `:military_helmet:` | [top](#introduction) | +| [top](#objects) | :rescue_worker_helmet: | `:rescue_worker_helmet:` | :prayer_beads: | `:prayer_beads:` | [top](#introduction) | +| [top](#objects) | :lipstick: | `:lipstick:` | :ring: | `:ring:` | [top](#introduction) | +| [top](#objects) | :gem: | `:gem:` | | | [top](#introduction) | + +### Sound + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#objects) | :mute: | `:mute:` | :speaker: | `:speaker:` | [top](#introduction) | +| [top](#objects) | :sound: | `:sound:` | :loud_sound: | `:loud_sound:` | [top](#introduction) | +| [top](#objects) | :loudspeaker: | `:loudspeaker:` | :mega: | `:mega:` | [top](#introduction) | +| [top](#objects) | :postal_horn: | `:postal_horn:` | :bell: | `:bell:` | [top](#introduction) | +| [top](#objects) | :no_bell: | `:no_bell:` | | | [top](#introduction) | + +### Music + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#objects) | :musical_score: | `:musical_score:` | :musical_note: | `:musical_note:` | [top](#introduction) | +| [top](#objects) | :notes: | `:notes:` | :studio_microphone: | `:studio_microphone:` | [top](#introduction) | +| [top](#objects) | :level_slider: | `:level_slider:` | :control_knobs: | `:control_knobs:` | [top](#introduction) | +| [top](#objects) | :microphone: | `:microphone:` | :headphones: | `:headphones:` | [top](#introduction) | +| [top](#objects) | :radio: | `:radio:` | | | [top](#introduction) | + +### Musical Instrument + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#objects) | :saxophone: | `:saxophone:` | :accordion: | `:accordion:` | [top](#introduction) | +| [top](#objects) | :guitar: | `:guitar:` | :musical_keyboard: | `:musical_keyboard:` | [top](#introduction) | +| [top](#objects) | :trumpet: | `:trumpet:` | :violin: | `:violin:` | [top](#introduction) | +| [top](#objects) | :banjo: | `:banjo:` | :drum: | `:drum:` | [top](#introduction) | +| [top](#objects) | :long_drum: | `:long_drum:` | | | [top](#introduction) | + +### Phone + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#objects) | :iphone: | `:iphone:` | :calling: | `:calling:` | [top](#introduction) | +| [top](#objects) | :phone: | `:phone:` `:telephone:` | :telephone_receiver: | `:telephone_receiver:` | [top](#introduction) | +| [top](#objects) | :pager: | `:pager:` | :fax: | `:fax:` | [top](#introduction) | + +### Computer + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#objects) | :battery: | `:battery:` | :electric_plug: | `:electric_plug:` | [top](#introduction) | +| [top](#objects) | :computer: | `:computer:` | :desktop_computer: | `:desktop_computer:` | [top](#introduction) | +| [top](#objects) | :printer: | `:printer:` | :keyboard: | `:keyboard:` | [top](#introduction) | +| [top](#objects) | :computer_mouse: | `:computer_mouse:` | :trackball: | `:trackball:` | [top](#introduction) | +| [top](#objects) | :minidisc: | `:minidisc:` | :floppy_disk: | `:floppy_disk:` | [top](#introduction) | +| [top](#objects) | :cd: | `:cd:` | :dvd: | `:dvd:` | [top](#introduction) | +| [top](#objects) | :abacus: | `:abacus:` | | | [top](#introduction) | + +### Light & Video + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#objects) | :movie_camera: | `:movie_camera:` | :film_strip: | `:film_strip:` | [top](#introduction) | +| [top](#objects) | :film_projector: | `:film_projector:` | :clapper: | `:clapper:` | [top](#introduction) | +| [top](#objects) | :tv: | `:tv:` | :camera: | `:camera:` | [top](#introduction) | +| [top](#objects) | :camera_flash: | `:camera_flash:` | :video_camera: | `:video_camera:` | [top](#introduction) | +| [top](#objects) | :vhs: | `:vhs:` | :mag: | `:mag:` | [top](#introduction) | +| [top](#objects) | :mag_right: | `:mag_right:` | :candle: | `:candle:` | [top](#introduction) | +| [top](#objects) | :bulb: | `:bulb:` | :flashlight: | `:flashlight:` | [top](#introduction) | +| [top](#objects) | :izakaya_lantern: | `:izakaya_lantern:` `:lantern:` | :diya_lamp: | `:diya_lamp:` | [top](#introduction) | + +### Book Paper + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#objects) | :notebook_with_decorative_cover: | `:notebook_with_decorative_cover:` | :closed_book: | `:closed_book:` | [top](#introduction) | +| [top](#objects) | :book: | `:book:` `:open_book:` | :green_book: | `:green_book:` | [top](#introduction) | +| [top](#objects) | :blue_book: | `:blue_book:` | :orange_book: | `:orange_book:` | [top](#introduction) | +| [top](#objects) | :books: | `:books:` | :notebook: | `:notebook:` | [top](#introduction) | +| [top](#objects) | :ledger: | `:ledger:` | :page_with_curl: | `:page_with_curl:` | [top](#introduction) | +| [top](#objects) | :scroll: | `:scroll:` | :page_facing_up: | `:page_facing_up:` | [top](#introduction) | +| [top](#objects) | :newspaper: | `:newspaper:` | :newspaper_roll: | `:newspaper_roll:` | [top](#introduction) | +| [top](#objects) | :bookmark_tabs: | `:bookmark_tabs:` | :bookmark: | `:bookmark:` | [top](#introduction) | +| [top](#objects) | :label: | `:label:` | | | [top](#introduction) | + +### Money + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#objects) | :moneybag: | `:moneybag:` | :coin: | `:coin:` | [top](#introduction) | +| [top](#objects) | :yen: | `:yen:` | :dollar: | `:dollar:` | [top](#introduction) | +| [top](#objects) | :euro: | `:euro:` | :pound: | `:pound:` | [top](#introduction) | +| [top](#objects) | :money_with_wings: | `:money_with_wings:` | :credit_card: | `:credit_card:` | [top](#introduction) | +| [top](#objects) | :receipt: | `:receipt:` | :chart: | `:chart:` | [top](#introduction) | + +### Mail + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#objects) | :envelope: | `:envelope:` | :e-mail: | `:e-mail:` `:email:` | [top](#introduction) | +| [top](#objects) | :incoming_envelope: | `:incoming_envelope:` | :envelope_with_arrow: | `:envelope_with_arrow:` | [top](#introduction) | +| [top](#objects) | :outbox_tray: | `:outbox_tray:` | :inbox_tray: | `:inbox_tray:` | [top](#introduction) | +| [top](#objects) | :package: | `:package:` | :mailbox: | `:mailbox:` | [top](#introduction) | +| [top](#objects) | :mailbox_closed: | `:mailbox_closed:` | :mailbox_with_mail: | `:mailbox_with_mail:` | [top](#introduction) | +| [top](#objects) | :mailbox_with_no_mail: | `:mailbox_with_no_mail:` | :postbox: | `:postbox:` | [top](#introduction) | +| [top](#objects) | :ballot_box: | `:ballot_box:` | | | [top](#introduction) | + +### Writing + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#objects) | :pencil2: | `:pencil2:` | :black_nib: | `:black_nib:` | [top](#introduction) | +| [top](#objects) | :fountain_pen: | `:fountain_pen:` | :pen: | `:pen:` | [top](#introduction) | +| [top](#objects) | :paintbrush: | `:paintbrush:` | :crayon: | `:crayon:` | [top](#introduction) | +| [top](#objects) | :memo: | `:memo:` `:pencil:` | | | [top](#introduction) | + +### Office + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#objects) | :briefcase: | `:briefcase:` | :file_folder: | `:file_folder:` | [top](#introduction) | +| [top](#objects) | :open_file_folder: | `:open_file_folder:` | :card_index_dividers: | `:card_index_dividers:` | [top](#introduction) | +| [top](#objects) | :date: | `:date:` | :calendar: | `:calendar:` | [top](#introduction) | +| [top](#objects) | :spiral_notepad: | `:spiral_notepad:` | :spiral_calendar: | `:spiral_calendar:` | [top](#introduction) | +| [top](#objects) | :card_index: | `:card_index:` | :chart_with_upwards_trend: | `:chart_with_upwards_trend:` | [top](#introduction) | +| [top](#objects) | :chart_with_downwards_trend: | `:chart_with_downwards_trend:` | :bar_chart: | `:bar_chart:` | [top](#introduction) | +| [top](#objects) | :clipboard: | `:clipboard:` | :pushpin: | `:pushpin:` | [top](#introduction) | +| [top](#objects) | :round_pushpin: | `:round_pushpin:` | :paperclip: | `:paperclip:` | [top](#introduction) | +| [top](#objects) | :paperclips: | `:paperclips:` | :straight_ruler: | `:straight_ruler:` | [top](#introduction) | +| [top](#objects) | :triangular_ruler: | `:triangular_ruler:` | :scissors: | `:scissors:` | [top](#introduction) | +| [top](#objects) | :card_file_box: | `:card_file_box:` | :file_cabinet: | `:file_cabinet:` | [top](#introduction) | +| [top](#objects) | :wastebasket: | `:wastebasket:` | | | [top](#introduction) | + +### Lock + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#objects) | :lock: | `:lock:` | :unlock: | `:unlock:` | [top](#introduction) | +| [top](#objects) | :lock_with_ink_pen: | `:lock_with_ink_pen:` | :closed_lock_with_key: | `:closed_lock_with_key:` | [top](#introduction) | +| [top](#objects) | :key: | `:key:` | :old_key: | `:old_key:` | [top](#introduction) | + +### Tool + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#objects) | :hammer: | `:hammer:` | :axe: | `:axe:` | [top](#introduction) | +| [top](#objects) | :pick: | `:pick:` | :hammer_and_pick: | `:hammer_and_pick:` | [top](#introduction) | +| [top](#objects) | :hammer_and_wrench: | `:hammer_and_wrench:` | :dagger: | `:dagger:` | [top](#introduction) | +| [top](#objects) | :crossed_swords: | `:crossed_swords:` | :bomb: | `:bomb:` | [top](#introduction) | +| [top](#objects) | :boomerang: | `:boomerang:` | :bow_and_arrow: | `:bow_and_arrow:` | [top](#introduction) | +| [top](#objects) | :shield: | `:shield:` | :carpentry_saw: | `:carpentry_saw:` | [top](#introduction) | +| [top](#objects) | :wrench: | `:wrench:` | :screwdriver: | `:screwdriver:` | [top](#introduction) | +| [top](#objects) | :nut_and_bolt: | `:nut_and_bolt:` | :gear: | `:gear:` | [top](#introduction) | +| [top](#objects) | :clamp: | `:clamp:` | :balance_scale: | `:balance_scale:` | [top](#introduction) | +| [top](#objects) | :probing_cane: | `:probing_cane:` | :link: | `:link:` | [top](#introduction) | +| [top](#objects) | :chains: | `:chains:` | :hook: | `:hook:` | [top](#introduction) | +| [top](#objects) | :toolbox: | `:toolbox:` | :magnet: | `:magnet:` | [top](#introduction) | +| [top](#objects) | :ladder: | `:ladder:` | | | [top](#introduction) | + +### Science + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#objects) | :alembic: | `:alembic:` | :test_tube: | `:test_tube:` | [top](#introduction) | +| [top](#objects) | :petri_dish: | `:petri_dish:` | :dna: | `:dna:` | [top](#introduction) | +| [top](#objects) | :microscope: | `:microscope:` | :telescope: | `:telescope:` | [top](#introduction) | +| [top](#objects) | :satellite: | `:satellite:` | | | [top](#introduction) | + +### Medical + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#objects) | :syringe: | `:syringe:` | :drop_of_blood: | `:drop_of_blood:` | [top](#introduction) | +| [top](#objects) | :pill: | `:pill:` | :adhesive_bandage: | `:adhesive_bandage:` | [top](#introduction) | +| [top](#objects) | :stethoscope: | `:stethoscope:` | | | [top](#introduction) | + +### Household + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#objects) | :door: | `:door:` | :elevator: | `:elevator:` | [top](#introduction) | +| [top](#objects) | :mirror: | `:mirror:` | :window: | `:window:` | [top](#introduction) | +| [top](#objects) | :bed: | `:bed:` | :couch_and_lamp: | `:couch_and_lamp:` | [top](#introduction) | +| [top](#objects) | :chair: | `:chair:` | :toilet: | `:toilet:` | [top](#introduction) | +| [top](#objects) | :plunger: | `:plunger:` | :shower: | `:shower:` | [top](#introduction) | +| [top](#objects) | :bathtub: | `:bathtub:` | :mouse_trap: | `:mouse_trap:` | [top](#introduction) | +| [top](#objects) | :razor: | `:razor:` | :lotion_bottle: | `:lotion_bottle:` | [top](#introduction) | +| [top](#objects) | :safety_pin: | `:safety_pin:` | :broom: | `:broom:` | [top](#introduction) | +| [top](#objects) | :basket: | `:basket:` | :roll_of_paper: | `:roll_of_paper:` | [top](#introduction) | +| [top](#objects) | :bucket: | `:bucket:` | :soap: | `:soap:` | [top](#introduction) | +| [top](#objects) | :toothbrush: | `:toothbrush:` | :sponge: | `:sponge:` | [top](#introduction) | +| [top](#objects) | :fire_extinguisher: | `:fire_extinguisher:` | :shopping_cart: | `:shopping_cart:` | [top](#introduction) | + +### Other Object + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#objects) | :smoking: | `:smoking:` | :coffin: | `:coffin:` | [top](#introduction) | +| [top](#objects) | :headstone: | `:headstone:` | :funeral_urn: | `:funeral_urn:` | [top](#introduction) | +| [top](#objects) | :nazar_amulet: | `:nazar_amulet:` | :moyai: | `:moyai:` | [top](#introduction) | +| [top](#objects) | :placard: | `:placard:` | | | [top](#introduction) | + +## Symbols + +- [Transport Sign](#transport-sign) +- [Warning](#warning) +- [Arrow](#arrow) +- [Religion](#religion) +- [Zodiac](#zodiac) +- [Av Symbol](#av-symbol) +- [Gender](#gender) +- [Math](#math) +- [Punctuation](#punctuation) +- [Currency](#currency) +- [Other Symbol](#other-symbol) +- [Keycap](#keycap) +- [Alphanum](#alphanum) +- [Geometric](#geometric) + +### Transport Sign + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#symbols) | :atm: | `:atm:` | :put_litter_in_its_place: | `:put_litter_in_its_place:` | [top](#introduction) | +| [top](#symbols) | :potable_water: | `:potable_water:` | :wheelchair: | `:wheelchair:` | [top](#introduction) | +| [top](#symbols) | :mens: | `:mens:` | :womens: | `:womens:` | [top](#introduction) | +| [top](#symbols) | :restroom: | `:restroom:` | :baby_symbol: | `:baby_symbol:` | [top](#introduction) | +| [top](#symbols) | :wc: | `:wc:` | :passport_control: | `:passport_control:` | [top](#introduction) | +| [top](#symbols) | :customs: | `:customs:` | :baggage_claim: | `:baggage_claim:` | [top](#introduction) | +| [top](#symbols) | :left_luggage: | `:left_luggage:` | | | [top](#introduction) | + +### Warning + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#symbols) | :warning: | `:warning:` | :children_crossing: | `:children_crossing:` | [top](#introduction) | +| [top](#symbols) | :no_entry: | `:no_entry:` | :no_entry_sign: | `:no_entry_sign:` | [top](#introduction) | +| [top](#symbols) | :no_bicycles: | `:no_bicycles:` | :no_smoking: | `:no_smoking:` | [top](#introduction) | +| [top](#symbols) | :do_not_litter: | `:do_not_litter:` | :non-potable_water: | `:non-potable_water:` | [top](#introduction) | +| [top](#symbols) | :no_pedestrians: | `:no_pedestrians:` | :no_mobile_phones: | `:no_mobile_phones:` | [top](#introduction) | +| [top](#symbols) | :underage: | `:underage:` | :radioactive: | `:radioactive:` | [top](#introduction) | +| [top](#symbols) | :biohazard: | `:biohazard:` | | | [top](#introduction) | + +### Arrow + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#symbols) | :arrow_up: | `:arrow_up:` | :arrow_upper_right: | `:arrow_upper_right:` | [top](#introduction) | +| [top](#symbols) | :arrow_right: | `:arrow_right:` | :arrow_lower_right: | `:arrow_lower_right:` | [top](#introduction) | +| [top](#symbols) | :arrow_down: | `:arrow_down:` | :arrow_lower_left: | `:arrow_lower_left:` | [top](#introduction) | +| [top](#symbols) | :arrow_left: | `:arrow_left:` | :arrow_upper_left: | `:arrow_upper_left:` | [top](#introduction) | +| [top](#symbols) | :arrow_up_down: | `:arrow_up_down:` | :left_right_arrow: | `:left_right_arrow:` | [top](#introduction) | +| [top](#symbols) | :leftwards_arrow_with_hook: | `:leftwards_arrow_with_hook:` | :arrow_right_hook: | `:arrow_right_hook:` | [top](#introduction) | +| [top](#symbols) | :arrow_heading_up: | `:arrow_heading_up:` | :arrow_heading_down: | `:arrow_heading_down:` | [top](#introduction) | +| [top](#symbols) | :arrows_clockwise: | `:arrows_clockwise:` | :arrows_counterclockwise: | `:arrows_counterclockwise:` | [top](#introduction) | +| [top](#symbols) | :back: | `:back:` | :end: | `:end:` | [top](#introduction) | +| [top](#symbols) | :on: | `:on:` | :soon: | `:soon:` | [top](#introduction) | +| [top](#symbols) | :top: | `:top:` | | | [top](#introduction) | + +### Religion + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#symbols) | :place_of_worship: | `:place_of_worship:` | :atom_symbol: | `:atom_symbol:` | [top](#introduction) | +| [top](#symbols) | :om: | `:om:` | :star_of_david: | `:star_of_david:` | [top](#introduction) | +| [top](#symbols) | :wheel_of_dharma: | `:wheel_of_dharma:` | :yin_yang: | `:yin_yang:` | [top](#introduction) | +| [top](#symbols) | :latin_cross: | `:latin_cross:` | :orthodox_cross: | `:orthodox_cross:` | [top](#introduction) | +| [top](#symbols) | :star_and_crescent: | `:star_and_crescent:` | :peace_symbol: | `:peace_symbol:` | [top](#introduction) | +| [top](#symbols) | :menorah: | `:menorah:` | :six_pointed_star: | `:six_pointed_star:` | [top](#introduction) | + +### Zodiac + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#symbols) | :aries: | `:aries:` | :taurus: | `:taurus:` | [top](#introduction) | +| [top](#symbols) | :gemini: | `:gemini:` | :cancer: | `:cancer:` | [top](#introduction) | +| [top](#symbols) | :leo: | `:leo:` | :virgo: | `:virgo:` | [top](#introduction) | +| [top](#symbols) | :libra: | `:libra:` | :scorpius: | `:scorpius:` | [top](#introduction) | +| [top](#symbols) | :sagittarius: | `:sagittarius:` | :capricorn: | `:capricorn:` | [top](#introduction) | +| [top](#symbols) | :aquarius: | `:aquarius:` | :pisces: | `:pisces:` | [top](#introduction) | +| [top](#symbols) | :ophiuchus: | `:ophiuchus:` | | | [top](#introduction) | + +### Av Symbol + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#symbols) | :twisted_rightwards_arrows: | `:twisted_rightwards_arrows:` | :repeat: | `:repeat:` | [top](#introduction) | +| [top](#symbols) | :repeat_one: | `:repeat_one:` | :arrow_forward: | `:arrow_forward:` | [top](#introduction) | +| [top](#symbols) | :fast_forward: | `:fast_forward:` | :next_track_button: | `:next_track_button:` | [top](#introduction) | +| [top](#symbols) | :play_or_pause_button: | `:play_or_pause_button:` | :arrow_backward: | `:arrow_backward:` | [top](#introduction) | +| [top](#symbols) | :rewind: | `:rewind:` | :previous_track_button: | `:previous_track_button:` | [top](#introduction) | +| [top](#symbols) | :arrow_up_small: | `:arrow_up_small:` | :arrow_double_up: | `:arrow_double_up:` | [top](#introduction) | +| [top](#symbols) | :arrow_down_small: | `:arrow_down_small:` | :arrow_double_down: | `:arrow_double_down:` | [top](#introduction) | +| [top](#symbols) | :pause_button: | `:pause_button:` | :stop_button: | `:stop_button:` | [top](#introduction) | +| [top](#symbols) | :record_button: | `:record_button:` | :eject_button: | `:eject_button:` | [top](#introduction) | +| [top](#symbols) | :cinema: | `:cinema:` | :low_brightness: | `:low_brightness:` | [top](#introduction) | +| [top](#symbols) | :high_brightness: | `:high_brightness:` | :signal_strength: | `:signal_strength:` | [top](#introduction) | +| [top](#symbols) | :vibration_mode: | `:vibration_mode:` | :mobile_phone_off: | `:mobile_phone_off:` | [top](#introduction) | + +### Gender + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#symbols) | :female_sign: | `:female_sign:` | :male_sign: | `:male_sign:` | [top](#introduction) | +| [top](#symbols) | :transgender_symbol: | `:transgender_symbol:` | | | [top](#introduction) | + +### Math + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#symbols) | :heavy_multiplication_x: | `:heavy_multiplication_x:` | :heavy_plus_sign: | `:heavy_plus_sign:` | [top](#introduction) | +| [top](#symbols) | :heavy_minus_sign: | `:heavy_minus_sign:` | :heavy_division_sign: | `:heavy_division_sign:` | [top](#introduction) | +| [top](#symbols) | :infinity: | `:infinity:` | | | [top](#introduction) | + +### Punctuation + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#symbols) | :bangbang: | `:bangbang:` | :interrobang: | `:interrobang:` | [top](#introduction) | +| [top](#symbols) | :question: | `:question:` | :grey_question: | `:grey_question:` | [top](#introduction) | +| [top](#symbols) | :grey_exclamation: | `:grey_exclamation:` | :exclamation: | `:exclamation:` `:heavy_exclamation_mark:` | [top](#introduction) | +| [top](#symbols) | :wavy_dash: | `:wavy_dash:` | | | [top](#introduction) | + +### Currency + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#symbols) | :currency_exchange: | `:currency_exchange:` | :heavy_dollar_sign: | `:heavy_dollar_sign:` | [top](#introduction) | + +### Other Symbol + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#symbols) | :medical_symbol: | `:medical_symbol:` | :recycle: | `:recycle:` | [top](#introduction) | +| [top](#symbols) | :fleur_de_lis: | `:fleur_de_lis:` | :trident: | `:trident:` | [top](#introduction) | +| [top](#symbols) | :name_badge: | `:name_badge:` | :beginner: | `:beginner:` | [top](#introduction) | +| [top](#symbols) | :o: | `:o:` | :white_check_mark: | `:white_check_mark:` | [top](#introduction) | +| [top](#symbols) | :ballot_box_with_check: | `:ballot_box_with_check:` | :heavy_check_mark: | `:heavy_check_mark:` | [top](#introduction) | +| [top](#symbols) | :x: | `:x:` | :negative_squared_cross_mark: | `:negative_squared_cross_mark:` | [top](#introduction) | +| [top](#symbols) | :curly_loop: | `:curly_loop:` | :loop: | `:loop:` | [top](#introduction) | +| [top](#symbols) | :part_alternation_mark: | `:part_alternation_mark:` | :eight_spoked_asterisk: | `:eight_spoked_asterisk:` | [top](#introduction) | +| [top](#symbols) | :eight_pointed_black_star: | `:eight_pointed_black_star:` | :sparkle: | `:sparkle:` | [top](#introduction) | +| [top](#symbols) | :copyright: | `:copyright:` | :registered: | `:registered:` | [top](#introduction) | +| [top](#symbols) | :tm: | `:tm:` | | | [top](#introduction) | + +### Keycap + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#symbols) | :hash: | `:hash:` | :asterisk: | `:asterisk:` | [top](#introduction) | +| [top](#symbols) | :zero: | `:zero:` | :one: | `:one:` | [top](#introduction) | +| [top](#symbols) | :two: | `:two:` | :three: | `:three:` | [top](#introduction) | +| [top](#symbols) | :four: | `:four:` | :five: | `:five:` | [top](#introduction) | +| [top](#symbols) | :six: | `:six:` | :seven: | `:seven:` | [top](#introduction) | +| [top](#symbols) | :eight: | `:eight:` | :nine: | `:nine:` | [top](#introduction) | +| [top](#symbols) | :keycap_ten: | `:keycap_ten:` | | | [top](#introduction) | + +### Alphanum + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#symbols) | :capital_abcd: | `:capital_abcd:` | :abcd: | `:abcd:` | [top](#introduction) | +| [top](#symbols) | :1234: | `:1234:` | :symbols: | `:symbols:` | [top](#introduction) | +| [top](#symbols) | :abc: | `:abc:` | :a: | `:a:` | [top](#introduction) | +| [top](#symbols) | :ab: | `:ab:` | :b: | `:b:` | [top](#introduction) | +| [top](#symbols) | :cl: | `:cl:` | :cool: | `:cool:` | [top](#introduction) | +| [top](#symbols) | :free: | `:free:` | :information_source: | `:information_source:` | [top](#introduction) | +| [top](#symbols) | :id: | `:id:` | :m: | `:m:` | [top](#introduction) | +| [top](#symbols) | :new: | `:new:` | :ng: | `:ng:` | [top](#introduction) | +| [top](#symbols) | :o2: | `:o2:` | :ok: | `:ok:` | [top](#introduction) | +| [top](#symbols) | :parking: | `:parking:` | :sos: | `:sos:` | [top](#introduction) | +| [top](#symbols) | :up: | `:up:` | :vs: | `:vs:` | [top](#introduction) | +| [top](#symbols) | :koko: | `:koko:` | :sa: | `:sa:` | [top](#introduction) | +| [top](#symbols) | :u6708: | `:u6708:` | :u6709: | `:u6709:` | [top](#introduction) | +| [top](#symbols) | :u6307: | `:u6307:` | :ideograph_advantage: | `:ideograph_advantage:` | [top](#introduction) | +| [top](#symbols) | :u5272: | `:u5272:` | :u7121: | `:u7121:` | [top](#introduction) | +| [top](#symbols) | :u7981: | `:u7981:` | :accept: | `:accept:` | [top](#introduction) | +| [top](#symbols) | :u7533: | `:u7533:` | :u5408: | `:u5408:` | [top](#introduction) | +| [top](#symbols) | :u7a7a: | `:u7a7a:` | :congratulations: | `:congratulations:` | [top](#introduction) | +| [top](#symbols) | :secret: | `:secret:` | :u55b6: | `:u55b6:` | [top](#introduction) | +| [top](#symbols) | :u6e80: | `:u6e80:` | | | [top](#introduction) | + +### Geometric + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#symbols) | :red_circle: | `:red_circle:` | :orange_circle: | `:orange_circle:` | [top](#introduction) | +| [top](#symbols) | :yellow_circle: | `:yellow_circle:` | :green_circle: | `:green_circle:` | [top](#introduction) | +| [top](#symbols) | :large_blue_circle: | `:large_blue_circle:` | :purple_circle: | `:purple_circle:` | [top](#introduction) | +| [top](#symbols) | :brown_circle: | `:brown_circle:` | :black_circle: | `:black_circle:` | [top](#introduction) | +| [top](#symbols) | :white_circle: | `:white_circle:` | :red_square: | `:red_square:` | [top](#introduction) | +| [top](#symbols) | :orange_square: | `:orange_square:` | :yellow_square: | `:yellow_square:` | [top](#introduction) | +| [top](#symbols) | :green_square: | `:green_square:` | :blue_square: | `:blue_square:` | [top](#introduction) | +| [top](#symbols) | :purple_square: | `:purple_square:` | :brown_square: | `:brown_square:` | [top](#introduction) | +| [top](#symbols) | :black_large_square: | `:black_large_square:` | :white_large_square: | `:white_large_square:` | [top](#introduction) | +| [top](#symbols) | :black_medium_square: | `:black_medium_square:` | :white_medium_square: | `:white_medium_square:` | [top](#introduction) | +| [top](#symbols) | :black_medium_small_square: | `:black_medium_small_square:` | :white_medium_small_square: | `:white_medium_small_square:` | [top](#introduction) | +| [top](#symbols) | :black_small_square: | `:black_small_square:` | :white_small_square: | `:white_small_square:` | [top](#introduction) | +| [top](#symbols) | :large_orange_diamond: | `:large_orange_diamond:` | :large_blue_diamond: | `:large_blue_diamond:` | [top](#introduction) | +| [top](#symbols) | :small_orange_diamond: | `:small_orange_diamond:` | :small_blue_diamond: | `:small_blue_diamond:` | [top](#introduction) | +| [top](#symbols) | :small_red_triangle: | `:small_red_triangle:` | :small_red_triangle_down: | `:small_red_triangle_down:` | [top](#introduction) | +| [top](#symbols) | :diamond_shape_with_a_dot_inside: | `:diamond_shape_with_a_dot_inside:` | :radio_button: | `:radio_button:` | [top](#introduction) | +| [top](#symbols) | :white_square_button: | `:white_square_button:` | :black_square_button: | `:black_square_button:` | [top](#introduction) | + +## Flags + +- [Flag](#flag) +- [Country Flag](#country-flag) +- [Subdivision Flag](#subdivision-flag) + +### Flag + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#flags) | :checkered_flag: | `:checkered_flag:` | :triangular_flag_on_post: | `:triangular_flag_on_post:` | [top](#introduction) | +| [top](#flags) | :crossed_flags: | `:crossed_flags:` | :black_flag: | `:black_flag:` | [top](#introduction) | +| [top](#flags) | :white_flag: | `:white_flag:` | :rainbow_flag: | `:rainbow_flag:` | [top](#introduction) | +| [top](#flags) | :transgender_flag: | `:transgender_flag:` | :pirate_flag: | `:pirate_flag:` | [top](#introduction) | + +### Country Flag + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#flags) | :ascension_island: | `:ascension_island:` | :andorra: | `:andorra:` | [top](#introduction) | +| [top](#flags) | :united_arab_emirates: | `:united_arab_emirates:` | :afghanistan: | `:afghanistan:` | [top](#introduction) | +| [top](#flags) | :antigua_barbuda: | `:antigua_barbuda:` | :anguilla: | `:anguilla:` | [top](#introduction) | +| [top](#flags) | :albania: | `:albania:` | :armenia: | `:armenia:` | [top](#introduction) | +| [top](#flags) | :angola: | `:angola:` | :antarctica: | `:antarctica:` | [top](#introduction) | +| [top](#flags) | :argentina: | `:argentina:` | :american_samoa: | `:american_samoa:` | [top](#introduction) | +| [top](#flags) | :austria: | `:austria:` | :australia: | `:australia:` | [top](#introduction) | +| [top](#flags) | :aruba: | `:aruba:` | :aland_islands: | `:aland_islands:` | [top](#introduction) | +| [top](#flags) | :azerbaijan: | `:azerbaijan:` | :bosnia_herzegovina: | `:bosnia_herzegovina:` | [top](#introduction) | +| [top](#flags) | :barbados: | `:barbados:` | :bangladesh: | `:bangladesh:` | [top](#introduction) | +| [top](#flags) | :belgium: | `:belgium:` | :burkina_faso: | `:burkina_faso:` | [top](#introduction) | +| [top](#flags) | :bulgaria: | `:bulgaria:` | :bahrain: | `:bahrain:` | [top](#introduction) | +| [top](#flags) | :burundi: | `:burundi:` | :benin: | `:benin:` | [top](#introduction) | +| [top](#flags) | :st_barthelemy: | `:st_barthelemy:` | :bermuda: | `:bermuda:` | [top](#introduction) | +| [top](#flags) | :brunei: | `:brunei:` | :bolivia: | `:bolivia:` | [top](#introduction) | +| [top](#flags) | :caribbean_netherlands: | `:caribbean_netherlands:` | :brazil: | `:brazil:` | [top](#introduction) | +| [top](#flags) | :bahamas: | `:bahamas:` | :bhutan: | `:bhutan:` | [top](#introduction) | +| [top](#flags) | :bouvet_island: | `:bouvet_island:` | :botswana: | `:botswana:` | [top](#introduction) | +| [top](#flags) | :belarus: | `:belarus:` | :belize: | `:belize:` | [top](#introduction) | +| [top](#flags) | :canada: | `:canada:` | :cocos_islands: | `:cocos_islands:` | [top](#introduction) | +| [top](#flags) | :congo_kinshasa: | `:congo_kinshasa:` | :central_african_republic: | `:central_african_republic:` | [top](#introduction) | +| [top](#flags) | :congo_brazzaville: | `:congo_brazzaville:` | :switzerland: | `:switzerland:` | [top](#introduction) | +| [top](#flags) | :cote_divoire: | `:cote_divoire:` | :cook_islands: | `:cook_islands:` | [top](#introduction) | +| [top](#flags) | :chile: | `:chile:` | :cameroon: | `:cameroon:` | [top](#introduction) | +| [top](#flags) | :cn: | `:cn:` | :colombia: | `:colombia:` | [top](#introduction) | +| [top](#flags) | :clipperton_island: | `:clipperton_island:` | :costa_rica: | `:costa_rica:` | [top](#introduction) | +| [top](#flags) | :cuba: | `:cuba:` | :cape_verde: | `:cape_verde:` | [top](#introduction) | +| [top](#flags) | :curacao: | `:curacao:` | :christmas_island: | `:christmas_island:` | [top](#introduction) | +| [top](#flags) | :cyprus: | `:cyprus:` | :czech_republic: | `:czech_republic:` | [top](#introduction) | +| [top](#flags) | :de: | `:de:` | :diego_garcia: | `:diego_garcia:` | [top](#introduction) | +| [top](#flags) | :djibouti: | `:djibouti:` | :denmark: | `:denmark:` | [top](#introduction) | +| [top](#flags) | :dominica: | `:dominica:` | :dominican_republic: | `:dominican_republic:` | [top](#introduction) | +| [top](#flags) | :algeria: | `:algeria:` | :ceuta_melilla: | `:ceuta_melilla:` | [top](#introduction) | +| [top](#flags) | :ecuador: | `:ecuador:` | :estonia: | `:estonia:` | [top](#introduction) | +| [top](#flags) | :egypt: | `:egypt:` | :western_sahara: | `:western_sahara:` | [top](#introduction) | +| [top](#flags) | :eritrea: | `:eritrea:` | :es: | `:es:` | [top](#introduction) | +| [top](#flags) | :ethiopia: | `:ethiopia:` | :eu: | `:eu:` `:european_union:` | [top](#introduction) | +| [top](#flags) | :finland: | `:finland:` | :fiji: | `:fiji:` | [top](#introduction) | +| [top](#flags) | :falkland_islands: | `:falkland_islands:` | :micronesia: | `:micronesia:` | [top](#introduction) | +| [top](#flags) | :faroe_islands: | `:faroe_islands:` | :fr: | `:fr:` | [top](#introduction) | +| [top](#flags) | :gabon: | `:gabon:` | :gb: | `:gb:` `:uk:` | [top](#introduction) | +| [top](#flags) | :grenada: | `:grenada:` | :georgia: | `:georgia:` | [top](#introduction) | +| [top](#flags) | :french_guiana: | `:french_guiana:` | :guernsey: | `:guernsey:` | [top](#introduction) | +| [top](#flags) | :ghana: | `:ghana:` | :gibraltar: | `:gibraltar:` | [top](#introduction) | +| [top](#flags) | :greenland: | `:greenland:` | :gambia: | `:gambia:` | [top](#introduction) | +| [top](#flags) | :guinea: | `:guinea:` | :guadeloupe: | `:guadeloupe:` | [top](#introduction) | +| [top](#flags) | :equatorial_guinea: | `:equatorial_guinea:` | :greece: | `:greece:` | [top](#introduction) | +| [top](#flags) | :south_georgia_south_sandwich_islands: | `:south_georgia_south_sandwich_islands:` | :guatemala: | `:guatemala:` | [top](#introduction) | +| [top](#flags) | :guam: | `:guam:` | :guinea_bissau: | `:guinea_bissau:` | [top](#introduction) | +| [top](#flags) | :guyana: | `:guyana:` | :hong_kong: | `:hong_kong:` | [top](#introduction) | +| [top](#flags) | :heard_mcdonald_islands: | `:heard_mcdonald_islands:` | :honduras: | `:honduras:` | [top](#introduction) | +| [top](#flags) | :croatia: | `:croatia:` | :haiti: | `:haiti:` | [top](#introduction) | +| [top](#flags) | :hungary: | `:hungary:` | :canary_islands: | `:canary_islands:` | [top](#introduction) | +| [top](#flags) | :indonesia: | `:indonesia:` | :ireland: | `:ireland:` | [top](#introduction) | +| [top](#flags) | :israel: | `:israel:` | :isle_of_man: | `:isle_of_man:` | [top](#introduction) | +| [top](#flags) | :india: | `:india:` | :british_indian_ocean_territory: | `:british_indian_ocean_territory:` | [top](#introduction) | +| [top](#flags) | :iraq: | `:iraq:` | :iran: | `:iran:` | [top](#introduction) | +| [top](#flags) | :iceland: | `:iceland:` | :it: | `:it:` | [top](#introduction) | +| [top](#flags) | :jersey: | `:jersey:` | :jamaica: | `:jamaica:` | [top](#introduction) | +| [top](#flags) | :jordan: | `:jordan:` | :jp: | `:jp:` | [top](#introduction) | +| [top](#flags) | :kenya: | `:kenya:` | :kyrgyzstan: | `:kyrgyzstan:` | [top](#introduction) | +| [top](#flags) | :cambodia: | `:cambodia:` | :kiribati: | `:kiribati:` | [top](#introduction) | +| [top](#flags) | :comoros: | `:comoros:` | :st_kitts_nevis: | `:st_kitts_nevis:` | [top](#introduction) | +| [top](#flags) | :north_korea: | `:north_korea:` | :kr: | `:kr:` | [top](#introduction) | +| [top](#flags) | :kuwait: | `:kuwait:` | :cayman_islands: | `:cayman_islands:` | [top](#introduction) | +| [top](#flags) | :kazakhstan: | `:kazakhstan:` | :laos: | `:laos:` | [top](#introduction) | +| [top](#flags) | :lebanon: | `:lebanon:` | :st_lucia: | `:st_lucia:` | [top](#introduction) | +| [top](#flags) | :liechtenstein: | `:liechtenstein:` | :sri_lanka: | `:sri_lanka:` | [top](#introduction) | +| [top](#flags) | :liberia: | `:liberia:` | :lesotho: | `:lesotho:` | [top](#introduction) | +| [top](#flags) | :lithuania: | `:lithuania:` | :luxembourg: | `:luxembourg:` | [top](#introduction) | +| [top](#flags) | :latvia: | `:latvia:` | :libya: | `:libya:` | [top](#introduction) | +| [top](#flags) | :morocco: | `:morocco:` | :monaco: | `:monaco:` | [top](#introduction) | +| [top](#flags) | :moldova: | `:moldova:` | :montenegro: | `:montenegro:` | [top](#introduction) | +| [top](#flags) | :st_martin: | `:st_martin:` | :madagascar: | `:madagascar:` | [top](#introduction) | +| [top](#flags) | :marshall_islands: | `:marshall_islands:` | :macedonia: | `:macedonia:` | [top](#introduction) | +| [top](#flags) | :mali: | `:mali:` | :myanmar: | `:myanmar:` | [top](#introduction) | +| [top](#flags) | :mongolia: | `:mongolia:` | :macau: | `:macau:` | [top](#introduction) | +| [top](#flags) | :northern_mariana_islands: | `:northern_mariana_islands:` | :martinique: | `:martinique:` | [top](#introduction) | +| [top](#flags) | :mauritania: | `:mauritania:` | :montserrat: | `:montserrat:` | [top](#introduction) | +| [top](#flags) | :malta: | `:malta:` | :mauritius: | `:mauritius:` | [top](#introduction) | +| [top](#flags) | :maldives: | `:maldives:` | :malawi: | `:malawi:` | [top](#introduction) | +| [top](#flags) | :mexico: | `:mexico:` | :malaysia: | `:malaysia:` | [top](#introduction) | +| [top](#flags) | :mozambique: | `:mozambique:` | :namibia: | `:namibia:` | [top](#introduction) | +| [top](#flags) | :new_caledonia: | `:new_caledonia:` | :niger: | `:niger:` | [top](#introduction) | +| [top](#flags) | :norfolk_island: | `:norfolk_island:` | :nigeria: | `:nigeria:` | [top](#introduction) | +| [top](#flags) | :nicaragua: | `:nicaragua:` | :netherlands: | `:netherlands:` | [top](#introduction) | +| [top](#flags) | :norway: | `:norway:` | :nepal: | `:nepal:` | [top](#introduction) | +| [top](#flags) | :nauru: | `:nauru:` | :niue: | `:niue:` | [top](#introduction) | +| [top](#flags) | :new_zealand: | `:new_zealand:` | :oman: | `:oman:` | [top](#introduction) | +| [top](#flags) | :panama: | `:panama:` | :peru: | `:peru:` | [top](#introduction) | +| [top](#flags) | :french_polynesia: | `:french_polynesia:` | :papua_new_guinea: | `:papua_new_guinea:` | [top](#introduction) | +| [top](#flags) | :philippines: | `:philippines:` | :pakistan: | `:pakistan:` | [top](#introduction) | +| [top](#flags) | :poland: | `:poland:` | :st_pierre_miquelon: | `:st_pierre_miquelon:` | [top](#introduction) | +| [top](#flags) | :pitcairn_islands: | `:pitcairn_islands:` | :puerto_rico: | `:puerto_rico:` | [top](#introduction) | +| [top](#flags) | :palestinian_territories: | `:palestinian_territories:` | :portugal: | `:portugal:` | [top](#introduction) | +| [top](#flags) | :palau: | `:palau:` | :paraguay: | `:paraguay:` | [top](#introduction) | +| [top](#flags) | :qatar: | `:qatar:` | :reunion: | `:reunion:` | [top](#introduction) | +| [top](#flags) | :romania: | `:romania:` | :serbia: | `:serbia:` | [top](#introduction) | +| [top](#flags) | :ru: | `:ru:` | :rwanda: | `:rwanda:` | [top](#introduction) | +| [top](#flags) | :saudi_arabia: | `:saudi_arabia:` | :solomon_islands: | `:solomon_islands:` | [top](#introduction) | +| [top](#flags) | :seychelles: | `:seychelles:` | :sudan: | `:sudan:` | [top](#introduction) | +| [top](#flags) | :sweden: | `:sweden:` | :singapore: | `:singapore:` | [top](#introduction) | +| [top](#flags) | :st_helena: | `:st_helena:` | :slovenia: | `:slovenia:` | [top](#introduction) | +| [top](#flags) | :svalbard_jan_mayen: | `:svalbard_jan_mayen:` | :slovakia: | `:slovakia:` | [top](#introduction) | +| [top](#flags) | :sierra_leone: | `:sierra_leone:` | :san_marino: | `:san_marino:` | [top](#introduction) | +| [top](#flags) | :senegal: | `:senegal:` | :somalia: | `:somalia:` | [top](#introduction) | +| [top](#flags) | :suriname: | `:suriname:` | :south_sudan: | `:south_sudan:` | [top](#introduction) | +| [top](#flags) | :sao_tome_principe: | `:sao_tome_principe:` | :el_salvador: | `:el_salvador:` | [top](#introduction) | +| [top](#flags) | :sint_maarten: | `:sint_maarten:` | :syria: | `:syria:` | [top](#introduction) | +| [top](#flags) | :swaziland: | `:swaziland:` | :tristan_da_cunha: | `:tristan_da_cunha:` | [top](#introduction) | +| [top](#flags) | :turks_caicos_islands: | `:turks_caicos_islands:` | :chad: | `:chad:` | [top](#introduction) | +| [top](#flags) | :french_southern_territories: | `:french_southern_territories:` | :togo: | `:togo:` | [top](#introduction) | +| [top](#flags) | :thailand: | `:thailand:` | :tajikistan: | `:tajikistan:` | [top](#introduction) | +| [top](#flags) | :tokelau: | `:tokelau:` | :timor_leste: | `:timor_leste:` | [top](#introduction) | +| [top](#flags) | :turkmenistan: | `:turkmenistan:` | :tunisia: | `:tunisia:` | [top](#introduction) | +| [top](#flags) | :tonga: | `:tonga:` | :tr: | `:tr:` | [top](#introduction) | +| [top](#flags) | :trinidad_tobago: | `:trinidad_tobago:` | :tuvalu: | `:tuvalu:` | [top](#introduction) | +| [top](#flags) | :taiwan: | `:taiwan:` | :tanzania: | `:tanzania:` | [top](#introduction) | +| [top](#flags) | :ukraine: | `:ukraine:` | :uganda: | `:uganda:` | [top](#introduction) | +| [top](#flags) | :us_outlying_islands: | `:us_outlying_islands:` | :united_nations: | `:united_nations:` | [top](#introduction) | +| [top](#flags) | :us: | `:us:` | :uruguay: | `:uruguay:` | [top](#introduction) | +| [top](#flags) | :uzbekistan: | `:uzbekistan:` | :vatican_city: | `:vatican_city:` | [top](#introduction) | +| [top](#flags) | :st_vincent_grenadines: | `:st_vincent_grenadines:` | :venezuela: | `:venezuela:` | [top](#introduction) | +| [top](#flags) | :british_virgin_islands: | `:british_virgin_islands:` | :us_virgin_islands: | `:us_virgin_islands:` | [top](#introduction) | +| [top](#flags) | :vietnam: | `:vietnam:` | :vanuatu: | `:vanuatu:` | [top](#introduction) | +| [top](#flags) | :wallis_futuna: | `:wallis_futuna:` | :samoa: | `:samoa:` | [top](#introduction) | +| [top](#flags) | :kosovo: | `:kosovo:` | :yemen: | `:yemen:` | [top](#introduction) | +| [top](#flags) | :mayotte: | `:mayotte:` | :south_africa: | `:south_africa:` | [top](#introduction) | +| [top](#flags) | :zambia: | `:zambia:` | :zimbabwe: | `:zimbabwe:` | [top](#introduction) | + +### Subdivision Flag + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#flags) | :england: | `:england:` | :scotland: | `:scotland:` | [top](#introduction) | +| [top](#flags) | :wales: | `:wales:` | | | [top](#introduction) | + +## GitHub Custom Emoji + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#github-custom-emoji) | :accessibility: | `:accessibility:` | :atom: | `:atom:` | [top](#introduction) | +| [top](#github-custom-emoji) | :basecamp: | `:basecamp:` | :basecampy: | `:basecampy:` | [top](#introduction) | +| [top](#github-custom-emoji) | :bowtie: | `:bowtie:` | :dependabot: | `:dependabot:` | [top](#introduction) | +| [top](#github-custom-emoji) | :electron: | `:electron:` | :feelsgood: | `:feelsgood:` | [top](#introduction) | +| [top](#github-custom-emoji) | :finnadie: | `:finnadie:` | :fishsticks: | `:fishsticks:` | [top](#introduction) | +| [top](#github-custom-emoji) | :goberserk: | `:goberserk:` | :godmode: | `:godmode:` | [top](#introduction) | +| [top](#github-custom-emoji) | :hurtrealbad: | `:hurtrealbad:` | :neckbeard: | `:neckbeard:` | [top](#introduction) | +| [top](#github-custom-emoji) | :octocat: | `:octocat:` | :rage1: | `:rage1:` | [top](#introduction) | +| [top](#github-custom-emoji) | :rage2: | `:rage2:` | :rage3: | `:rage3:` | [top](#introduction) | +| [top](#github-custom-emoji) | :rage4: | `:rage4:` | :shipit: | `:shipit:` | [top](#introduction) | +| [top](#github-custom-emoji) | :suspect: | `:suspect:` | :trollface: | `:trollface:` | [top](#introduction) | diff --git a/docs/content/en/quick-reference/functions.md b/docs/content/en/quick-reference/functions.md new file mode 100644 index 000000000..42eafedd3 --- /dev/null +++ b/docs/content/en/quick-reference/functions.md @@ -0,0 +1,14 @@ +--- +title: Functions +description: A quick reference guide to Hugo's functions, grouped by namespace. Aliases, if any, appear in parentheses to the right of the function name. +categories: [quick reference] +keywords: [] +menu: + docs: + parent: quick-reference + weight: 30 +weight: 30 +toc: true +--- + +{{% quick-reference section="functions" %}} diff --git a/docs/content/en/quick-reference/methods.md b/docs/content/en/quick-reference/methods.md new file mode 100644 index 000000000..abd1db709 --- /dev/null +++ b/docs/content/en/quick-reference/methods.md @@ -0,0 +1,14 @@ +--- +title: Methods +description: A quick reference guide to Hugo's methods, grouped by object. +categories: [quick reference] +keywords: [] +menu: + docs: + parent: quick-reference + weight: 40 +weight: 40 +toc: true +--- + +{{% quick-reference section="methods" %}} diff --git a/docs/content/en/quick-reference/page-collections.md b/docs/content/en/quick-reference/page-collections.md new file mode 100644 index 000000000..795eb494d --- /dev/null +++ b/docs/content/en/quick-reference/page-collections.md @@ -0,0 +1,46 @@ +--- +title: Page collections +description: A quick reference guide to Hugo's page collections. +categories: [quick reference] +keywords: [] +menu: + docs: + parent: quick-reference + weight: 50 +weight: 50 +toc: true +--- + +## Page + +Use these `Page` methods when rendering lists on [section] pages, [taxonomy] pages, [term] pages, and the home page. + +[section]: /getting-started/glossary/#section +[taxonomy]: /getting-started/glossary/#taxonomy +[term]: /getting-started/glossary/#term + +{{< list-pages-in-section path=/methods/page filter=methods_page_page_collections filterType=include omitElementIDs=true titlePrefix=PAGE. >}} + +## Site + +Use these `Site` methods when rendering lists on any page. + +{{< list-pages-in-section path=/methods/site filter=methods_site_page_collections filterType=include omitElementIDs=true titlePrefix=SITE. >}} + +## Filter + +Use the [`where`] function to filter page collections. + +[`where`]: /functions/collections/where + +## Sort + +Use these methods to sort page collections. + +{{< list-pages-in-section path=/methods/pages filter=methods_pages_sort filterType=include titlePrefix=. omitElementIDs=true titlePrefix=PAGES. >}} + +## Group + +Use these methods to group page collections. + +{{< list-pages-in-section path=/methods/pages filter=methods_pages_group filterType=include titlePrefix=. omitElementIDs=true titlePrefix=PAGES. >}} diff --git a/docs/content/en/showcase/1password-support/bio.md b/docs/content/en/showcase/1password-support/bio.md new file mode 100644 index 000000000..3e15adc9f --- /dev/null +++ b/docs/content/en/showcase/1password-support/bio.md @@ -0,0 +1,4 @@ + +**1Password** is a password manager that keeps you safe online. It protects your secure information behind the one password only you know. + +The [1Password Support](https://support.1password.com/) website was built from scratch with **Hugo** and enhanced with **React** and **Elasticsearch** to give us the best of both worlds: The simplicity and performance of a static site, with the richness of a hosted web app. diff --git a/docs/content/en/showcase/1password-support/featured.png b/docs/content/en/showcase/1password-support/featured.png Binary files differnew file mode 100644 index 000000000..8e46495e6 --- /dev/null +++ b/docs/content/en/showcase/1password-support/featured.png diff --git a/docs/content/en/showcase/1password-support/index.md b/docs/content/en/showcase/1password-support/index.md new file mode 100644 index 000000000..ed44053c8 --- /dev/null +++ b/docs/content/en/showcase/1password-support/index.md @@ -0,0 +1,39 @@ +--- + +title: 1Password Support +date: 2018-02-22 +description: "Showcase: \"Compiles 400 pages in five languages in the blink of an eye.\"" +siteURL: https://support.1password.com/ +byline: "[Mitch Cohen](https://github.com/mitchchn), Documentation Team Lead" +aliases: [/showcase/1password/] + +--- + +At 1Password, we used to go through a different documentation platform every month: blog engines, ebooks, wikis, site generators written in Ruby and JavaScript. Each was inadequate in its own special way. Then we found **Hugo**. We made one last switch, and we're glad we did. + +### Not all static site generators are created equal + +Finding a tool that will make your customers, writers, designers, _and_ DevOps team happy is no easy task, but we managed it with Hugo: + +**Hugo is static**. We're a security company, so we swear by static sites and use them wherever possible. We feel much safer pointing customers at HTML files than at a complicated server which needs to be hardened. + +**Hugo is Go**. We love the Go programming language at 1Password, and we were delighted to learn that Hugo used the same Go template syntax that our designers and front-end developers had already mastered. + +**Hugo is FAST**. Our previous static site generator took nearly a minute to compile our (then much smaller) site. Developers might be used to this, but it wasn't cutting it for writers who wanted to see live previews of their work. Hugo did the same job in milliseconds, and to this day compiles 400 pages in five languages in the blink of an eye. + +**Hugo is flexible**. Thanks to Hugo's content and layout system, we were able to preserve our existing file and folder structure and port our entire production site in a few days. We could then create new content types that weren't possible before, like these snazzy [showcases](https://support.1password.com/explore/extension/). + +**Hugo is great for writers**. Our documentation team was already comfortable with Markdown and Git and could start creating content for Hugo with zero downtime. Once we added shortcodes, our writers were able to dress up articles with features like [platform boxes](https://support.1password.com/get-the-apps/) with just a bit of new syntax. + +**Hugo has an amazing developer community**. Hugo updates are frequent and filled to the brim with features and fixes. As we developed the multilingual version of our site, we submitted PRs for features we needed and were helped through the process by [@bep](https://github.com/bep) and others. + +**Hugo is simple to deploy**. Hugo has just the right amount of configuration options to fit into our build system without being too complicated. + +### Tech specs + +* [1Password Support](https://support.1password.com) uses Hugo with a custom theme. It shares styles and some template code with [1Password.com](https://1password.com), which we also moved to Hugo in 2016. +* Code and articles live in a private GitHub repository, which is deployed to a static content server using Git hooks. +* Writers build and preview the site on their computers and contribute content using pull requests. +* We use Hugo's [multilingual support](/content-management/multilingual/) to build the site in English, Spanish, French, Italian, German, and Russian. With the help of Hugo, 1Password Support became our very first site in multiple languages. +* Our [contact form](https://support.1password.com/contact) is a single-page React app. We were able to integrate it with Hugo seamlessly thanks to its support for static files. +* The one part of the support site which is not static is our search engine, which we developed with Elasticsearch and host on AWS. diff --git a/docs/content/en/showcase/alora-labs/bio.md b/docs/content/en/showcase/alora-labs/bio.md new file mode 100644 index 000000000..f14a90b75 --- /dev/null +++ b/docs/content/en/showcase/alora-labs/bio.md @@ -0,0 +1,3 @@ +**Alora Labs** is a product development consultancy headquartered in Toronto, Canada. + +We help companies build software and IoT products and were recently recognized as one of the [**top IoT development firms**](https://aloralabs.com/insights/alora-labs-receives-clutch-2021-top-iot-agency-award) in Toronto. diff --git a/docs/content/en/showcase/alora-labs/featured.png b/docs/content/en/showcase/alora-labs/featured.png Binary files differnew file mode 100644 index 000000000..b8e1f302b --- /dev/null +++ b/docs/content/en/showcase/alora-labs/featured.png diff --git a/docs/content/en/showcase/alora-labs/index.md b/docs/content/en/showcase/alora-labs/index.md new file mode 100644 index 000000000..559169319 --- /dev/null +++ b/docs/content/en/showcase/alora-labs/index.md @@ -0,0 +1,18 @@ +--- +title: Alora Labs +date: 2021-05-27 +description: "Showcase: \"Making performant websites accessible for everyone.\"" +siteURL: https://aloralabs.com/ +siteSource: https://github.com/aloralabs/homepage +aliases: [/showcase/aloralabs/] +--- + +At Alora Labs we always have an eye open for new tools and technology that we can utilize to the benefit of our customers or internal projects like our website. + +The previous iteration of our site was built with Jekyll, which served us well at first. However as time went on, we became frustrated with the number of dependencies we had to rely on, that would often break at the most inconvenient times. + +Hugo was a breath of fresh air in this regard, a single binary that works equally well on Windows as it did on macOS or Linux. We no longer need additional tools for image optimization, Sass compilation or JavaScript bundling. Everything just works, and with a substantial performance boost too. + +Hugo has become a favorite tool in the tool belt and the foundation for many client projects. We couldn't be happier with the switch and we are optimistic about recommending Hugo for many years to come. + +Thank you to the vibrant community and talented development team for all the hard work in making Hugo a success. As excellent as Hugo is now, we cannot wait to see what the release notes have in store for us next. diff --git a/docs/content/en/showcase/ampio-help/bio.md b/docs/content/en/showcase/ampio-help/bio.md new file mode 100644 index 000000000..c7dd9894a --- /dev/null +++ b/docs/content/en/showcase/ampio-help/bio.md @@ -0,0 +1,11 @@ + +__We are Ampio.__ We design and manufacture a building automation system that provides control, comfort, safety and reliability. Visit [our page](http://ampio.com/) to learn more about our solution! + +__Ampio Knowledge Base__ is a service built and maintained with Hugo. It is a self-service support platform for our customers and certified installers. It also contains a complete portfolio of our modules---building blocks of the Ampio building automation system. + +The site is built by: + +* [@mgetka](https://github.com/mgetka), developer +* [@SteynAnna](https://github.com/SteynAnna), maintainer + +and other members of the Ampio team responsible for content creation. diff --git a/docs/content/en/showcase/ampio-help/featured.png b/docs/content/en/showcase/ampio-help/featured.png Binary files differnew file mode 100644 index 000000000..07974e7f1 --- /dev/null +++ b/docs/content/en/showcase/ampio-help/featured.png diff --git a/docs/content/en/showcase/ampio-help/index.md b/docs/content/en/showcase/ampio-help/index.md new file mode 100644 index 000000000..2daafbbe1 --- /dev/null +++ b/docs/content/en/showcase/ampio-help/index.md @@ -0,0 +1,77 @@ +--- +title: Ampio Knowledge Base +date: 2022-10-30 + +description: "Knowledge base for the Ampio building automation system." +siteURL: https://help.ampio.com/ +--- + +As a company that specializes in highly customizable smart solutions for various industries, Ampio has accumulated a vast amount of knowledge throughout the years. We were on the lookout for a user-friendly platform to impart this knowledge to our clients and installers. Delivering a service that caters to both audiences, scattered around the globe with vastly divergent needs and expectations, was a challenge. + +On the one hand, we needed something that would let us educate a client with no technical knowledge about our system in a visually appealing way. + +On the other hand, our installers required technical drawings, offline manuals, and a deep dive into highly specialized subjects. + +Over and above that, we could not overlook the fact that our internal team of editors and maintainers of the Knowledge Base included non-programmers who had to be able to create content and navigate the architecture of the site just as well as those adept at coding. + +We started our journey with the following requirements: + + - Ease of contribution + - Efficient search capabilities + - The possibility of deployment to simple shared hosting + - Proper support for multilingualism + +## Dark ages of WordPress + +With the above-mentioned in mind, we built our first revision of the service in WordPress with a commercial knowledge base plugin. The initial requirements seemed not to be exorbitant, and yet we were surprised to see that only a few of the available solutions covered them. Especially, the case of multilingualism appeared to be particularly neglected across the available products. + +The WordPress-based products made big promises: pay some bucks, bootstrap the service in minutes, and forget about all the development troubles. And although those promises could possibly be deliverable on WordPress' end, it was definitely not true for anything more than the most generic deployments. In our case, we were dealing with more and more trade-offs. Plus, the solution was just slow on the simple shared hosting environment that we dedicated to the job. + +## Turning point + +The turning point was the introduction of a new key requirement---each document was to be downloadable in the PDF format. Such functionality was not available in the plugins we owned, nor did it look like any of the other existing WordPress plugins could fulfill our needs to a satisfactory degree. Nobody in our team was brave enough to add such a functionality to the current stack, so we decided to start from scratch. + +On top of that new development, we had to remember another one of our key requirements, namely, that mostly non-programmers were to be responsible for the service maintenance and content creation. Initially, we were leaning towards headless CMS-based solutions, but finally we made a bold move and decided to create a Git-managed Jamstack service and see what happens. + +## Hugo to the rescue + +Hugo was our first choice of SSG. The multilingualism support was the primary feature that convinced us. Later on, going through the documentation, we continued to discover new exciting features that we didn't even know we needed when we started. + +The rich functionalities of WordPress WYSIWYG editors soon turned out to be a curse. It became burdensome to maintain formatting consistency across documents prepared by multiple contributors. When we considered Markdown, we knew that it would give us a lot less flexibility. In our case, it proved to be a blessing in disguise---the constraints imposed by the notation ensured that each document was prepared in the same way. And in the cases where Markdown was not enough, Hugo shortcodes gave us all that we needed to get the results we anticipated. + +In terms of PDF generation, we utilized [custom output formats](/templates/output-formats/) to produce intermediary document representations, which are consumed by our custom tool transforming them to TeX documents, which are finally used to produce PDF files. + +Custom output formats were also used to create search indexes. The search functionality is built on the brilliant [TNTSearch](https://github.com/teamtnt/tntsearch) library. The search queries and results are handled by PHP snippets embedded into static documents handled by Hugo. + +We even implemented a simple REST API generated by Hugo! We have yet to find something that cannot be achieved with this stack, while in WordPress-based solutions we were struggling with things as simple as defining custom document ordering in one of the categories list views. + +When talking about Hugo, we cannot forget about the speed. At the beginning we were not considering it a killer feature, but as our document base grew bigger, we appreciated it more and more. Dry-runs are not so common---most of the time we are working on one of the documents with cache already built during one of the previous Hugo runs. In such a scenario, Hugo rebuilds the site in about a second and we consider it a very good result. + +```text + | EN | PL +-------------------+-----+------ + Pages | 483 | 486 + Paginator pages | 56 | 55 + Non-page files | 745 | 749 + Static files | 917 | 917 + Processed images | 487 | 490 + Aliases | 80 | 79 + Sitemaps | 2 | 1 + Cleaned | 0 | 0 + +Total in 1096 ms +``` + +## Adaptation among the contributors + +Very quickly it became apparent that our initial concerns about the adaptation of the workflow among contributors were grossly exaggerated. Markdown is fairly straightforward and did not cause any trouble for the contributors. + +We recommended that our colleagues use Visual Studio Code as a tool for content creation. The project’s repository tracks project-scoped configuration of the editor, which includes a set of _tasks_ allowing to run a live server from the GUI level. This is very useful for those who are easily frightened when faced with the mighty terminal. + +The basic skills of the Git workflow were also easily acquired. At the end of the day, builds and deployments are fully managed by CI/CD processes, so the administration of the service drills down to reviewing and accepting merge requests in the Git frontend. As a side effect, we receive a full and clear history of contributions, which is well appreciated by our quality assurance auditors. + +We could even say that our experiment spread the love for Git among non-programmers in our organization! + +## Summary + +Hugo is the best! Definitely give it a try if you are ever faced with a challenge similar to ours. And do not give it a second thought if your service contributors are not too technically inclined---it might still turn out great! diff --git a/docs/content/en/showcase/bypasscensorship/bio.md b/docs/content/en/showcase/bypasscensorship/bio.md new file mode 100644 index 000000000..0a847df1e --- /dev/null +++ b/docs/content/en/showcase/bypasscensorship/bio.md @@ -0,0 +1,6 @@ +Bypass Censorship find and promote tools that provide Internet access to everyone. + +The site is built by: + +* [Leyla Avsar](https://www.leylaavsar.com/) (designer) +* [Fredrik Jonsson](https://xdeb.net/) (dev) diff --git a/docs/content/en/showcase/bypasscensorship/featured.png b/docs/content/en/showcase/bypasscensorship/featured.png Binary files differnew file mode 100644 index 000000000..d6f429112 --- /dev/null +++ b/docs/content/en/showcase/bypasscensorship/featured.png diff --git a/docs/content/en/showcase/bypasscensorship/index.md b/docs/content/en/showcase/bypasscensorship/index.md new file mode 100644 index 000000000..8cbda9aa6 --- /dev/null +++ b/docs/content/en/showcase/bypasscensorship/index.md @@ -0,0 +1,24 @@ +--- +title: Bypass Censorship +date: 2019-06-16 +description: "Showcase: Bypass Censorship find and promote tools that provide Internet access to everyone." +siteURL: https://www.bypasscensorship.org/ +byline: "[Fredrik Jonsson](https://xdeb.net/), Web developer & Linux sysadmin" + +--- + +The British Broadcasting Corporation (BBC) (UK), Deutsche Welle (DW) (Germany), France Médias Monde (FMM) (France), the U.S. Agency for Global Media (USAGM) (US) and the Open Technology Fund (OTF) (US) co-sponsor the Bypass Censorship website. + +Websites of international news agencies are often blocked in many countries. In order to connect people to these sites, Bypass Censorship feature and recommend tools in the following languages: English, French, Spanish, Arabic, Farsi, Chinese, and Russian. + +One of the tools is the Bypass Censorship Extension for Firefox and Chrome. The extension help direct people to mirrors of partners sites if they are being censored. + +The first version of the site was built in Drupal 8 but it was relaunched as a static site built with Hugo in 2019. + +Security, page load time and easy of hosting is the main reasons for switching to a static site. As the lead developer I had good experience with Hugo and was interested in exploring the multilingual features. + +It's a simply site, basically one page in seven languages. I had no problems getting Hugo to output what I wanted. Found the multilingual support straight forward and easy to work with. + +Thanks to the design by [Leyla Avsar](https://www.leylaavsar.com/) the site also looks good. I used the [Hugo Zen theme](https://github.com/frjo/hugo-theme-zen) with a few custom templates and the needed CSS. + +The editors can maintain content via [Forestry.io CMS](https://forestry.io/) or directly via Git. Forestry does unfortunately not have multilingual support. All the language versions are in one pile making it harder to find the right file to edit, but it works. diff --git a/docs/content/en/showcase/digitalgov/bio.md b/docs/content/en/showcase/digitalgov/bio.md new file mode 100644 index 000000000..db3ffafaf --- /dev/null +++ b/docs/content/en/showcase/digitalgov/bio.md @@ -0,0 +1,2 @@ + +**Digital.gov** helps people in the U.S. government deliver better, more accessible digital services through publishing essential guidance, resources, tools, and online events that make it easier for people to design, build, and deliver essential services for the public. diff --git a/docs/content/en/showcase/digitalgov/featured.png b/docs/content/en/showcase/digitalgov/featured.png Binary files differnew file mode 100644 index 000000000..7d065dce9 --- /dev/null +++ b/docs/content/en/showcase/digitalgov/featured.png diff --git a/docs/content/en/showcase/digitalgov/index.md b/docs/content/en/showcase/digitalgov/index.md new file mode 100644 index 000000000..3db2c608f --- /dev/null +++ b/docs/content/en/showcase/digitalgov/index.md @@ -0,0 +1,64 @@ +--- +title: Digital.gov +date: 2020-05-01 +description: "Showcase: \"Guidance on building better digital services in government.\"" +siteURL: https://digital.gov/ +siteSource: https://github.com/gsa/digitalgov.gov +--- + +For over a decade, Digital.gov has provided guidance, training, and community support to the people who are responsible for delivering digital services in the U.S. government. Essentially, it is a place where people can find examples of problems being solved in government, and get links to the tools and resources they need. + +Through collaboration in our communities of practice, Digital.gov is a window into the people who work in technology in government and the challenges they face making digital services stronger and more effective. [Read more about our site »](https://digital.gov/2019/12/19/a-new-digitalgov/) + +Digital.gov is built using the [U.S. Web Design System](https://designsystem.digital.gov/) (USWDS) and have followed the [design principles](https://designsystem.digital.gov/maturity-model/) in building out our new site: + +- **Start with real user needs** — We used human-centered design methods to inform our product decisions (like qualitative user research), and gathered feedback from real users. We also continually test our assumptions with small experiments. +- **Earn trust** —We recognize that trust has to be earned every time. We are including all [required links and content](https://digital.gov/resources/required-web-content-and-links/) on our site, clearly identifying as a government site, building with modern best practices, and using HTTPS. +- **Embrace accessibility** — [Accessibility](https://digital.gov/resources/intro-accessibility/) affects everybody, and we built it into every decision. We’re continually working to conform to Section 508 requirements, use user experience best practices, and support a wide range of devices. +- **Promote continuity** — We started from shared solutions like USWDS and [Federalist](https://federalist.18f.gov/). We designed our site to clearly identify as a government site by including USWDS’s .gov banner, common colors and patterns, and built with modern best practices. +- **Listen** — We actively collect user feedback and web metrics. We use the [Digital Analytics Program](https://digital.gov/services/dap/) (DAP) and analyze the data to discover actionable insights. We make small, incremental changes to continuously improve our website by listening to readers and learning from what we hear. + +_More on the [USWDS maturity model »](https://designsystem.digital.gov/maturity-model/)_ + +## Open tools + +We didn’t start from scratch. We built and designed the Digital.gov using many of the open-source tools and services that we develop for government here in the [Technology Transformation Services](https://www.gsa.gov/tts/) (TTS). + +Using services that make it possible to design, build, and iterate quickly are essential to modern web design and development, which is why [Federalist](https://federalist.18f.gov/) and the [U.S. Web Design System](https://designsystem.digital.gov/) are such a great combination. + +**Why Hugo?** Well, with around `~3,000` files _(and growing)_ and `~9,000` built pages, we needed a site generator that could handle that volume with lightning fast speed. + +Hugo was the clear option. The [Federalist](https://federalist.18f.gov/) team quickly added it to their available site generators, and we were off. + +At the moment, it takes around `32 seconds` to build close to `~10,000` pages! + +Take a look: + +```text + + | EN +-------------------+------- + Pages | 7973 + Paginator pages | 600 + Non-page files | 108 + Static files | 851 + Processed images | 0 + Aliases | 1381 + Sitemaps | 1 + Cleaned | 0 + +Built in 32.427 seconds +``` + +In addition to Hugo, we are proudly using a number of other tools and services, all built by government are free to use: + +- [Federalist](https://federalist.18f.gov/) +- [Search.gov](https://www.search.gov/) — A free, hosted search platform for federal websites. +- [Cloud.gov](https://www.cloud.gov/) — helps teams build, run, and authorize cloud-ready or legacy government systems quickly and cheaply. +- [Federal CrowdSource Mobile Testing Program](https://digital.gov/services/service_mobile-testing-program/) — Free mobile compatibility testing by feds, for feds. +- [Digital Analytics Program](https://digital.gov/services/dap/) (DAP) — A free analytics tool for measuring digital services in the federal government +- [Section508.gov](https://www.section508.gov/) and [PlainLanguage.gov](https://www.plainlanguage.gov/) resources +- [API.data.gov](https://api.data.gov/) — a free API management service for federal agencies +- [U.S. Digital Registry](https://digital.gov/services/u-s-digital-registry/) — A resource for confirming the official status of government social media accounts, mobile apps, and mobile websites. + +**Questions or feedback?** [Submit an issue](https://github.com/GSA/digitalgov.gov/issues) or send us an email to [digitalgov@gsa.gov](mailto:digitalgov@gsa.gov) :heart: diff --git a/docs/content/en/showcase/fireship/bio.md b/docs/content/en/showcase/fireship/bio.md new file mode 100644 index 000000000..faf739bfa --- /dev/null +++ b/docs/content/en/showcase/fireship/bio.md @@ -0,0 +1,6 @@ + +**Fireship.io** is an ecosystem of detailed and practical resources for developers who want to build and ship high-quality apps. + +The site is built by: + +* [Jeff Delaney](https://fireship.io/contributors/jeff-delaney/) diff --git a/docs/content/en/showcase/fireship/featured.png b/docs/content/en/showcase/fireship/featured.png Binary files differnew file mode 100644 index 000000000..33d1a47c5 --- /dev/null +++ b/docs/content/en/showcase/fireship/featured.png diff --git a/docs/content/en/showcase/fireship/index.md b/docs/content/en/showcase/fireship/index.md new file mode 100644 index 000000000..a229e4f6a --- /dev/null +++ b/docs/content/en/showcase/fireship/index.md @@ -0,0 +1,17 @@ +--- +title: fireship.io +date: 2019-02-02 +description: "Showcase: \"Hugo helps us create complex technical content that integrates engaging web components\"" +siteURL: https://fireship.io +siteSource: https://github.com/fireship-io/fireship.io +byline: "[Jeff Delaney](https://github.com/codediodeio), Fireship.io Creator" +--- + +After careful consideration of JavaScript/JSX-based static site generators, it became clear that Hugo was the only tool capable of handling our project's complex demands. Not only do we have multiple content formats and taxonomies, but we often need to customize the experience at a more granular level. The problems Hugo has solved for us include: + +- **Render speed.** We know from past experience that JavaScript-based static site generators become very slow when you have thousands of pages and images. +- **Feature-rich.** Our site has a long list of specialized needs and Hugo somehow manages to cover every single use case. +- **Composability.** Hugo's partial and shortcode systems empower us to write DRY and maintainable templates. +- **Simplicity.** Hugo is easy to learn (even without Go experience) and doesn't burden us with brittle dependencies. + +The site is able to achieve Lighthouse performance scores of 95+, despite the fact that it is a fully interactive PWA that ships Angular and Firebase in the JS bundle. This is made possible by (1) prerendering content with Hugo and (2) lazily embedding native web components directly in the HTML and Markdown. We provide a [detailed explanation](https://youtu.be/gun8OiGtlNc) of the architecture on YouTube and can't imagine development without Hugo. diff --git a/docs/content/en/showcase/forestry/bio.md b/docs/content/en/showcase/forestry/bio.md new file mode 100644 index 000000000..0b8f28743 --- /dev/null +++ b/docs/content/en/showcase/forestry/bio.md @@ -0,0 +1,4 @@ + +Forestry.io is a Git-backed CMS (content management system) for websites and web products built using static site generators such as Hugo. + +Forestry bridges the gap between developers and their teams, by making development fun and easy, while providing powerful content management for their teams. diff --git a/docs/content/en/showcase/forestry/featured.png b/docs/content/en/showcase/forestry/featured.png Binary files differnew file mode 100644 index 000000000..1ee315e78 --- /dev/null +++ b/docs/content/en/showcase/forestry/featured.png diff --git a/docs/content/en/showcase/forestry/index.md b/docs/content/en/showcase/forestry/index.md new file mode 100644 index 000000000..32a932a7a --- /dev/null +++ b/docs/content/en/showcase/forestry/index.md @@ -0,0 +1,48 @@ +--- +title: Forestry.io +date: 2018-03-16 +description: "Showcase: \"Seeing Hugo in action is a whole different world of awesome.\"" +siteURL: https://forestry.io/ +siteSource: https://github.com/forestryio/forestry.io +--- + +It was clear from the get-go that we had to go with a static site generator. Static sites are secure, performant, and give you 100% flexibility. At [Forestry.io](https://forestry.io/) we provide Content Management Solutions for websites built with static site generators, so we might be a little biased. The only question: Which static site generator was the right choice for us? + +### Why Hugo? + +In our early research we looked at Ionic’s [site](https://github.com/ionic-team/ionic) to get some inspiration. They used Jekyll to build their website. While Jekyll is a great generator, the build times for larger sites can be painfully slow. With more than 150 pages plus many custom configurations and add-ons, our website doesn’t fall into the low-volume category anymore. Our developers want a smooth experience when working on the website and our content editors need the ability to preview content quickly. In short, we need our builds to be lightning fast. + +We knew Hugo was fast but we did [some additional benchmarking](https://forestry.io/blog/hugo-vs-jekyll-benchmark/) before making our decision. Seeing Hugo in action is a whole different world of awesome. Hugo takes less than one second to build our 150-page site! Take a look: + +```text + | EN ++------------------+-----+ + Pages | 141 + Paginator pages | 4 + Non-page files | 0 + Static files | 537 + Processed images | 0 + Aliases | 60 + Sitemaps | 1 + Cleaned | 0 + +Total in 739 ms +``` + +In fact, we liked Hugo so much that our wizard Chris made his workflow public and we started the open-source project [Create-Static-Site](https://github.com/forestryio/create-static-site). It's [a simple way to spin up sites](https://forestry.io/blog/up-and-running-with-hugo/) and set up a modern web development workflow with one line of code. Essentially it adds build configurations as a dependency for JS, CSS and Image Processing. + +Lastly, we want to take the opportunity to give some love to other amazing tools we used building our website. + +### What tools did we use? + +* Our Norwegian designer Nichlas is in love with [**Sketch**](https://www.sketchapp.com/). From what we hear it’s a designer’s dream come true. +* Some say our main graphic is [mesmerizing](https://twitter.com/hmncllctv/status/968907474664284160). Nichlas created it using [**3DS Max**](https://www.autodesk.com/products/3ds-max/overview). +* [**Hugo**](https://gohugo.io/) -- of course. +* Chris can’t think of modern web development without [**Gulp**](https://gulpjs.com/) & [**Webpack**](https://webpack.js.org/). We used them to add additional build steps such as Browsersync, CSS, JS and SVG optimization. +* Speaking about adding steps to our build, our lives would be much harder without [**CircleCI**](https://circleci.com/) for continuous deployment and automated testing purposes. +* We can’t stop raving about [**Algolia**](https://www.algolia.com/). Chris loves it and even wrote a tutorial on [how to implement Algolia](https://forestry.io/blog/search-with-algolia-in-hugo/) into static sites using Hugo’s [Custom Outputs](/templates/output-formats/). +* [**Cloudinary**](https://cloudinary.com/) is probably one of the easiest ways to get responsive images into your website. +* We might be a little biased on this one - We think [**Forestry.io**](https://forestry.io/) is a great way to add a content management system with a clean UI on top of your site without interrupting your experience as a developer. +* For hosting purposes we use the almighty [**AWS**](https://aws.amazon.com/). +* [**Formspree.io**](https://formspree.io/) is managing our support and enterprise requests. +* We also use browser cookies and JS to customize our user’s experience and give it a more dynamic feel. diff --git a/docs/content/en/showcase/godot-tutorials/bio.md b/docs/content/en/showcase/godot-tutorials/bio.md new file mode 100644 index 000000000..fd849f844 --- /dev/null +++ b/docs/content/en/showcase/godot-tutorials/bio.md @@ -0,0 +1,7 @@ +[Godot Tutorials](https://godottutorials.com) aims to teach beginners how to get up and running with basic game programming and game development skills. + +The website is built with the **Hugo Framework** alongside aws+cloudfront+lambda. + +The site is built by: + +- [Godot Tutorials](https://godottutorials.com) diff --git a/docs/content/en/showcase/godot-tutorials/featured.png b/docs/content/en/showcase/godot-tutorials/featured.png Binary files differnew file mode 100644 index 000000000..fef13b996 --- /dev/null +++ b/docs/content/en/showcase/godot-tutorials/featured.png diff --git a/docs/content/en/showcase/godot-tutorials/index.md b/docs/content/en/showcase/godot-tutorials/index.md new file mode 100644 index 000000000..3b71fd8bc --- /dev/null +++ b/docs/content/en/showcase/godot-tutorials/index.md @@ -0,0 +1,24 @@ +--- + +title: Godot Tutorials +date: 2021-01-07 + +description: "Teaching game development skills with love." + +# The URL to the site on the internet. +siteURL: https://godottutorials.com + +# Add credit to the article author. Leave blank or remove if not needed/wanted. +byline: "[Godot Tutorials](https://godottutorials.com), Web Developer & Game Programmer" + +--- + +[Godot Tutorials](https://godottutorials.com) started as a way to teach beginners game programming and game development. +As I created videos, I ran into a problem; if I made a mistake with a YouTube video, it was difficult to correct errors. + +I discovered that blogging episodes and having articles that teach on top of my videos is a fantastic solution to my problem. + +As I researched blogging platforms, I came across two solutions; however, I chose [Hugo](https://gohugo.io) because it's built with Markdown in mind and simplified my workflow. + +In a sense, with [Hugo](https://gohugo.io) programmed the right way, I can focus **more time on planning, creating, and editing** +my videos and **less time maintaining and fixing** my website. diff --git a/docs/content/en/showcase/hapticmedia/bio.md b/docs/content/en/showcase/hapticmedia/bio.md new file mode 100644 index 000000000..4423edb70 --- /dev/null +++ b/docs/content/en/showcase/hapticmedia/bio.md @@ -0,0 +1 @@ +**Hapticmedia** provides interactive 3D configurators for eCommerce. diff --git a/docs/content/en/showcase/hapticmedia/featured.png b/docs/content/en/showcase/hapticmedia/featured.png Binary files differnew file mode 100644 index 000000000..a47ea9c2c --- /dev/null +++ b/docs/content/en/showcase/hapticmedia/featured.png diff --git a/docs/content/en/showcase/hapticmedia/index.md b/docs/content/en/showcase/hapticmedia/index.md new file mode 100644 index 000000000..7ca2b6cef --- /dev/null +++ b/docs/content/en/showcase/hapticmedia/index.md @@ -0,0 +1,31 @@ +--- +title: Hapticmedia Blog +date: 2019-10-01 +description: "Showcase: \"A simple, but powerful, multilingual blog.\"" +siteURL: https://hapticmedia.fr/blog/en/ +byline: "[Cyril Bonnet](https://github.com/monsieurnebo), Web Developer" +--- + +Our goal was to create a simple, effective and multilingual blog on [3D technology](https://hapticmedia.fr/blog/en/3d-technology/) that could be managed by a non-technical profile. + +## Why Hugo? + +Hugo addresses all these needs, coupled with [Forestry.io](https://forestry.io/) for its administration via a "turnkey" interface. We have attached particular importance to SEO, and therefore to the creation of an advanced taxonomy system. Thus, each author and tag has a dedicated page, listing the related posts. + +## What we liked + +- The **multilingual** content support, especially simple to setup. +- The **multiple environments** support (develop, staging, test, production, ...). +- Although a hard start with the Go language, the power of the **Hugo's templating**. +- The **partial layouts**, including the `internals` (e.g. social meta tags). +- The **build time**, unbeatable ⚡️⚡️⚡️. + +## Tools & workflow + +- We used the same design as **[our website](https://hapticmedia.fr/en/)**, recreated as a Hugo HTML template. +- **[Hugo](https://gohugo.io)** for the static website generator. +- **[CircleCI](https://circleci.com)** for continuous integration & deployment. +- **[AWS](https://aws.amazon.com/)** for web hosting. +- **[Forestry.io](https://forestry.io)** for the content management. + +**All of these tools allow our editor to manage the blog's content without having to worry about its technical aspect, which is managed by the developers.** diff --git a/docs/content/en/showcase/hartwell-insurance/bio.md b/docs/content/en/showcase/hartwell-insurance/bio.md new file mode 100644 index 000000000..7fab74292 --- /dev/null +++ b/docs/content/en/showcase/hartwell-insurance/bio.md @@ -0,0 +1,6 @@ + +Hartwell Insurance is an insurance company set up solely to service the Broker community. + +By combining **Hugo**, **Service Worker** and **Netlify**, we were able to achieve incredible global site performance. + +The site was built by [Tomango](https://www.tomango.co.uk) diff --git a/docs/content/en/showcase/hartwell-insurance/featured.png b/docs/content/en/showcase/hartwell-insurance/featured.png Binary files differnew file mode 100644 index 000000000..ced251f98 --- /dev/null +++ b/docs/content/en/showcase/hartwell-insurance/featured.png diff --git a/docs/content/en/showcase/hartwell-insurance/hartwell-columns.png b/docs/content/en/showcase/hartwell-insurance/hartwell-columns.png Binary files differnew file mode 100644 index 000000000..c9d36b67d --- /dev/null +++ b/docs/content/en/showcase/hartwell-insurance/hartwell-columns.png diff --git a/docs/content/en/showcase/hartwell-insurance/hartwell-lighthouse.png b/docs/content/en/showcase/hartwell-insurance/hartwell-lighthouse.png Binary files differnew file mode 100644 index 000000000..a882f01fd --- /dev/null +++ b/docs/content/en/showcase/hartwell-insurance/hartwell-lighthouse.png diff --git a/docs/content/en/showcase/hartwell-insurance/hartwell-webpagetest.png b/docs/content/en/showcase/hartwell-insurance/hartwell-webpagetest.png Binary files differnew file mode 100644 index 000000000..f60994ea1 --- /dev/null +++ b/docs/content/en/showcase/hartwell-insurance/hartwell-webpagetest.png diff --git a/docs/content/en/showcase/hartwell-insurance/index.md b/docs/content/en/showcase/hartwell-insurance/index.md new file mode 100644 index 000000000..ef0587e41 --- /dev/null +++ b/docs/content/en/showcase/hartwell-insurance/index.md @@ -0,0 +1,69 @@ +--- + +title: Hartwell Insurance + +date: 2018-02-09 + +description: "Showcase: \"Hugo + Netlify + PWA makes for a rapid website.\"" + +siteURL: https://www.hartwell-insurance.com/ + +byline: "[Trys Mudford](http://www.trysmudford.com), Lead Developer, Tomango" + +--- + +We’ve just launched a shiny new website for [Hartwell Insurance](https://www.hartwell-insurance.com/) – I’m really proud of it. It was tackled in a different way to most previous Tomango site builds, using some fancy new tools and some vintage web standards. + +It’s a multi-page, single-page (!) website written in Hugo, a static site generator built with performance as a first-class feature. _I’ve outlined a load of benefits to Hugo & static sites [here](https://why-static.netlify.com/), in case you’re interested._ + +> **In essence, a static site generator pre-renders the whole site into HTML files and serves them like it’s 1995.** + +There’s no Apache or Node backend that does compilation at runtime, it’s all done at the build step. This means the server; Netlify in this case, only has to do one thing – serve files. Unsurprisingly, serving simple files is VERY quick. + +The starter point was the [Victor Hugo](https://github.com/netlify/victor-hugo) repository that Netlify have created. It let me dive in with Hugo, PostCSS, Browsersync and ES6 without setting up any tooling myself – always a win! + +I then took all the content from the design file and moved it into Markdown, putting shortcodes in where necessary. This site did need a number of custom shortcodes for the presentational elements like the expanding circles and full width backgrounds. But mostly it was just clean, semantic HTML with some CSS and JS enhancement thrown in. + +For example, this two column layout shown below. I used CSS Columns with a `break-after: always;` on the `<h1>`. No multi-wrapper or difficult-to-clear shortcodes, just clean HTML. + + + +For the ripple effects on the section headings, I used JS to prepend a `<canvas>` element then animated it with `RequestAnimationFrame`. It adds a nice bit of movement on the page. + +On the Hartwell Profitmaker section, I toyed with the idea of using Vue.js for the calculator, but after giving it some thought, I decided to code in Vanilla. The result, all of the site JS comes in at 3.2KB! + +The plan was to host with Netlify and therefore get access to Netlify Forms. It meant spending 0 minutes on getting a backend set up – I could focus fully on the frontend. + +Cache invalidation isn’t normally something I spend all that much time thinking about when building a site. But as this site was going to be a Progressive Web App, invalidating files would be important to ensure the site didn’t appear broken when we made changes. As I was using Victor-Hugo, I wasn’t really sure how to best tackle this and sadly spent far too many hours wrangling with Webpack and Gulp files to try and get hashed file names working nicely. + +Then; while I was waiting for a haircut, I read a [Netlify blog post](https://www.netlify.com/blog/2017/02/23/better-living-through-caching/) on how they do cache invalidation with HTTP2 and it promptly blew my mind. + +When you request an asset, they send an ETag in the headers which is a hash of the file. There’s also a header to tell the browser not to trust it’s own cache (which sounds a little bit bonkers). + +So when you request the page, it opens a persistent HTTP2 connection up (so no new connections for file requests). When it gets to requesting that asset, the browser sends the ETag back to Netlify and they either return nothing if the ETag matches, or the new file with the new ETag. No `app.klfjlkdsfjdslkfjdslkfdsj.js` or `app.js?v=20180112`. Just a clean `app.js` with instant cache invalidation. Amazing. + +Finally, the [Service Worker](https://www.hartwell-insurance.com/sw.js) could be added. This turned out to be straightforward as the Netlify cache invalidation system solved most of the pain points. I went for a network-first, cache-fallback setup for both assets and HTML. This does mean flaky speeds are reliant on the page connection time, but given we’re on HTTP2, I’m hoping the persistent connection and tiny ETag size will keep it quick. For online connections, every request is up to date and instantly live after any update. Offline connections fall back to every assets’ last cached state. It seems to work really nicely, and there’s no need for an update prompt if assets have changed. + +--- + +## The results + +The WebPageTest results are looking good. The speed index is 456, 10x smaller than the average Alexa top 300,000 score. + + + +[TestMySite.io](https://testmysite.io/5a7e1bb2df99531a23c9ad2f/hartwell-insurance.com) is return ~2ms time to first byte from the CDN edge nodes. Lighthouse audits are also very promising. There’s still some improvement to be gained lazy-loading the images and inlining the CSS. I’m less excited about the [second suggestion](http://www.trysmudford.com/css-in-2017/), but I’ll certainly look at some lazy-loading, especially as I’m already using `IntersectionObserver` for some animations. + + + +The most encouraging result is how quick the site is around the world. Most Tomango clients (and their customers) are pretty local and almost exclusively UK-based. We have a dedicated server in Surrey that serves our market pretty well. It did take me by surprise just how much slower a connection from the USA, Australia and Japan to our server was. They’re waiting ~500ms just for the first byte, let alone downloading each asset. + +[Hartwell Insurance](https://www.hartwell-insurance.com/) are a US company so by putting them on our server, we’d be instantly hampering their local response times by literally seconds. This was one of the main reasons for going with Netlify. They provide global CDN hosting that’s quick from anywhere in the world. + +--- + +This project was such a blast to develop, it’s a real pleasure to put new technologies to good use in production, and to see real performance and usability benefits from them. Even using classic web methods of serving folders with files is fun when you’ve been using dynamic systems for a while – there’s something really pure about it. + +--- + +_This was originally posted on [my website](http://www.trysmudford.com/perfomance-wins-with-hugo-and-netlify/)_ diff --git a/docs/content/en/showcase/keycdn/bio.md b/docs/content/en/showcase/keycdn/bio.md new file mode 100644 index 000000000..90f623dca --- /dev/null +++ b/docs/content/en/showcase/keycdn/bio.md @@ -0,0 +1 @@ +[KeyCDN](https://www.keycdn.com) is a high performance content delivery network (CDN) offering many powerful features, including image processing that can transform and optimize images in real time. Our network offers global coverage to speed up content delivery and is capable of delivering entire static websites, like those built with Hugo, at the edge. diff --git a/docs/content/en/showcase/keycdn/featured.png b/docs/content/en/showcase/keycdn/featured.png Binary files differnew file mode 100644 index 000000000..46018a8f9 --- /dev/null +++ b/docs/content/en/showcase/keycdn/featured.png diff --git a/docs/content/en/showcase/keycdn/index.md b/docs/content/en/showcase/keycdn/index.md new file mode 100644 index 000000000..d092aa07d --- /dev/null +++ b/docs/content/en/showcase/keycdn/index.md @@ -0,0 +1,30 @@ +--- + +title: KeyCDN +date: 2020-04-10 +description: "Showcase: \"Hugo has become an integral part of our stack.\"" +siteURL: https://www.keycdn.com + +--- + +At KeyCDN one of our primary focuses is on performance. With speed being ingrained in our DNA we knew from the start that we must use a fast static website generator that could meet our requirements. When evaluating the right solution, Hugo met our requirements and we looked no further as it was the fastest and most flexible. + +## Why we chose Hugo + +Before our migration to Hugo our website was powered by a PHP-based website that had about 50 pages and a WordPress website that had over 500 posts between our blog and knowledge base. This became harder to maintain as time continued. We felt like we were losing the speed and flexibility that we require. To overcome this we knew we needed to convert our website to be static. This would allow our website to be faster and more secure as it could be delivered by all of our edge locations. + +It wasn’t an easy task at the beginning, however, after evaluating Hugo and benchmarking it we knew we had found the ideal solution. Hugo was by far the fastest setup and offered an intuitive way to build our entire website exactly as needed. The Go-based templates, shortcodes, and configuration options made it easy to build a complex website. + +In the fall of 2018 we started the migration and within a couple short months we had built a custom static website with Hugo and migrated all content from our old systems. The simplicity and vast amount of functionality that Hugo offers made this process fast and left our entire team, including all of our writers and developers, happy with the migration. Since migrating to Hugo we haven’t looked back. Hugo has become an integral part of our stack. We’re grateful to all those who have contributed to make Hugo what it is today. + +## Technical overview + +Below is an overview of what we used with Hugo to build our website: + +* [KeyCDN](https://www.keycdn.com) uses a custom theme and is our primary hub for all style sheets and JavaScript. Our other websites, like [KeyCDN Tools](https://tools.keycdn.com), only import the required style sheets and JavaScript. +* We use [Gulp](https://gulpjs.com) in our build process for many tasks, such as combining, versioning, and compressing our style sheets as well as our JavaScript. +* Our search is powered by a custom solution that we’ve built. It allows our pages, blog, and knowledge base to be searched. It uses [Axios](https://github.com/axios/axios) to send a `POST` request containing the search query. An index file in JSON generated by Hugo is searched and the results are then returned. +* Our commenting system is also powered by a custom solution that we’ve built. It uses Axios to send a `GET` request containing the slug to pull the comment thread and a `POST` request containing the name, email address, and comment when submitting a comment. +* Our contact form is a simple HTML form, which uses Axios as well. +* Our writers use shortcodes to enhance the capability of markdown. +* Our entire website is delivered through KeyCDN using a Pull Zone, which means all of our edge locations are delivering our website. diff --git a/docs/content/en/showcase/letsencrypt/bio.md b/docs/content/en/showcase/letsencrypt/bio.md new file mode 100644 index 000000000..92551dc47 --- /dev/null +++ b/docs/content/en/showcase/letsencrypt/bio.md @@ -0,0 +1,3 @@ + + +Let's Encrypt is a free, automated, and open certificate authority (CA), run for the public's benefit. It is a service provided by the [Internet Security Research Group (ISRG)](https://www.abetterinternet.org/). diff --git a/docs/content/en/showcase/letsencrypt/featured.png b/docs/content/en/showcase/letsencrypt/featured.png Binary files differnew file mode 100644 index 000000000..9535d91bd --- /dev/null +++ b/docs/content/en/showcase/letsencrypt/featured.png diff --git a/docs/content/en/showcase/letsencrypt/index.md b/docs/content/en/showcase/letsencrypt/index.md new file mode 100644 index 000000000..6ad4b7840 --- /dev/null +++ b/docs/content/en/showcase/letsencrypt/index.md @@ -0,0 +1,20 @@ +--- +title: Let’s Encrypt +date: 2018-03-13 +description: "Showcase: Lessons learned from taking letsencrypt.org to Hugo." +siteURL: https://letsencrypt.org/ +siteSource: https://github.com/letsencrypt/website +byline: "[bep](https://github.com/bep), Hugo Lead" +--- + +The **Let’s Encrypt website** has a common set of elements: A landing page and some other static info-pages, a document section, a blog, and a documentation section. Having it moved to Hugo was mostly motivated by a _simpler administration and Hugo's [multilingual support](/content-management/multilingual/)_. They already serve HTTPS to more than 60 million domains, and having the documentation available in more languages will increase that reach.[^1] + +{{< tweet user="letsencrypt" id="971755920639307777" >}} + +I helped them port the site from Jekyll to Hugo. There are usually very few surprises doing this. I know Hugo very well, but working on sites with a history usually comes up with something new. + +That site is bookmarked in many browsers, so preserving the URLs was a must. Hugo's URL handling is very flexible, but there was one challenge. The website has a mix of standard and what we in Hugo call _ugly URLs_ (`https://letsencrypt.org/2017/12/07/looking-forward-to-2018.html`). In Hugo this is handled automatically, and you can turn it on globally or per language. But before Hugo `0.33` you could not configure it for parts of your site. You could set it manually for the relevant pages in front matter -- which is how it was done in Jekyll -- but that would be hard to manage, especially when you start to introduce translations. So, in Hugo 0.33 I added support for _ugly URLs_ per section and also `url` set in front matter for list pages (`https://letsencrypt.org/blog/`). + +The lessons learned from this also lead to [disableLanguages](/content-management/multilingual/#disable-a-language) in Hugo `0.34` (a way to turn off languages during translation). And I also registered [this issue](https://github.com/gohugoio/hugo/issues/4463). Once fixed it will make it easier to handle partially translated sites. + +[^1]: The work on getting the content translated is in progress. diff --git a/docs/content/en/showcase/linode/bio.md b/docs/content/en/showcase/linode/bio.md new file mode 100644 index 000000000..42fa92229 --- /dev/null +++ b/docs/content/en/showcase/linode/bio.md @@ -0,0 +1,4 @@ + +**Linode** is a cloud hosting provider that offers high performance SSD Linux servers for your infrastructure needs. + +**Hugo** offers the documentation team incredible performance as we scale and continue providing quality Linux tutorials. diff --git a/docs/content/en/showcase/linode/featured.png b/docs/content/en/showcase/linode/featured.png Binary files differnew file mode 100644 index 000000000..8e517eacb --- /dev/null +++ b/docs/content/en/showcase/linode/featured.png diff --git a/docs/content/en/showcase/linode/index.md b/docs/content/en/showcase/linode/index.md new file mode 100644 index 000000000..5a341be8a --- /dev/null +++ b/docs/content/en/showcase/linode/index.md @@ -0,0 +1,15 @@ +--- +title: Linode Docs +date: 2018-02-12 +description: "Showcase: \"Hugo allows us to build thousands of pages in seconds.\"" +siteURL: https://linode.com/docs/ +siteSource: https://github.com/linode/docs +--- + +The documentation team at Linode has been writing guides since 2009, with the goal of helping new and experienced Linux users find the best tools and get the most out of their systems. + +As our library grew into thousands of guides, we needed a fast static site generator with intuitive templating and the flexibility to extend Markdown without constantly writing HTML and CSS. + +Hugo solved a lot of our growing pains with features like shortcodes, customizable URLs, LiveReload, and more. We have already brought our site build time down from minutes to just a few seconds, and we are excited to see what future developments in Hugo will bring. + +Thank you to all the [Hugo contributors](https://github.com/gohugoio/hugo/graphs/contributors) and especially [@bep](https://github.com/bep) for helping us with the adoption of Hugo. diff --git a/docs/content/en/showcase/overmindstudios/bio.md b/docs/content/en/showcase/overmindstudios/bio.md new file mode 100644 index 000000000..1bd870984 --- /dev/null +++ b/docs/content/en/showcase/overmindstudios/bio.md @@ -0,0 +1,7 @@ + +**Overmind Studios** is a visual effects studio headquartered in Southern Germany. + +The site is built by: + +* [Tobias Kummer](https://www.overmind-studios.de/about/) + diff --git a/docs/content/en/showcase/overmindstudios/featured.png b/docs/content/en/showcase/overmindstudios/featured.png Binary files differnew file mode 100644 index 000000000..c3eaaaf4c --- /dev/null +++ b/docs/content/en/showcase/overmindstudios/featured.png diff --git a/docs/content/en/showcase/overmindstudios/index.md b/docs/content/en/showcase/overmindstudios/index.md new file mode 100644 index 000000000..3208b2b72 --- /dev/null +++ b/docs/content/en/showcase/overmindstudios/index.md @@ -0,0 +1,13 @@ +--- +title: Overmind Studios +description: "A fresh start to make things easier in the future." +siteURL: https://www.overmind-studios.de/ +byline: "[tobkum](https://github.com/tobkum), Co-Founder Overmind Studios" +--- +After many years of running our site on WordPress, we decided to switch to Hugo. + +WordPress is a great CMS for many people, but it has some downsides, especially for those who need a fast, secure, and customizable site. Plugins can become outdated, customization can be difficult, and bloat can slow down page loading times. + +Hugo is a static site generator that addresses many of these problems. It is fast to build and iterate, does not require PHP, is highly customizable, and is easy to learn and use. It is also secure, as it does not have a backend or MySQL database that can be hacked. + +We are very happy with our switch to Hugo. It is easy to update our site with new projects, and our Lighthouse score and loading times are both excellent. We now have more time to be creative instead of troubleshooting WordPress quirks and updates. diff --git a/docs/content/en/showcase/pharmaseal/bio.md b/docs/content/en/showcase/pharmaseal/bio.md new file mode 100644 index 000000000..7477f1c32 --- /dev/null +++ b/docs/content/en/showcase/pharmaseal/bio.md @@ -0,0 +1,7 @@ +PHARMASEAL began in 2016 with the purpose of disrupting the Clinical Trials Management market through continuous validation and integration + +We've been using **Hugo + Webpack + Netlify** to provide a scalable, modular design for the website, complete with Forestry building blocks to quickly be able to generate engagement pages. + +The site is built by: + +- [Roboto Studio](https://roboto.studio) diff --git a/docs/content/en/showcase/pharmaseal/featured-pharmaseal.png b/docs/content/en/showcase/pharmaseal/featured-pharmaseal.png Binary files differnew file mode 100644 index 000000000..4a64325b7 --- /dev/null +++ b/docs/content/en/showcase/pharmaseal/featured-pharmaseal.png diff --git a/docs/content/en/showcase/pharmaseal/index.md b/docs/content/en/showcase/pharmaseal/index.md new file mode 100644 index 000000000..d324833c9 --- /dev/null +++ b/docs/content/en/showcase/pharmaseal/index.md @@ -0,0 +1,35 @@ +--- + +title: PHARMASEAL +date: 2019-04-29 + +description: "Pharmaseal website developed using Hugo, Forestry, hosted and deployed by Netlify." + +# The URL to the site on the internet. +siteURL: https://pharmaseal.co/ + +# Link to the site's Hugo source code if public and you can/want to share. +# Remove or leave blank if not needed/wanted. + +# Add credit to the article author. Leave blank or remove if not needed/wanted. +byline: "[Roboto Studio](https://roboto.studio), Jonathan Alford" + +--- + +We wanted to shake the status quo with PHARMASEAL, opting for a fast and scalable website built with Hugo instead of slower monolithic systems the competitors were using. + +We had two goals: + +**Make it fast** + +We wanted to optimize the site as much as possible, so we opted for using Cloudinary, enabling us to take advantage of on-the-fly image manipulation, and thanks to the sheer speed of static sites, we achieved a perfect optimization score with Google audits. + +Because we're hosting the site through Netlify and our target audience is in America, we are taking advantage of Netlify edge (Their alternative to a CDN). We're talking blazing fast. + +**Make it easy** + +We're big fans of simplicity, and that's what we delivered with the Forestry building blocks. Every element on the site is built with building blocks in mind, allowing PHARMASEAL to generate multiple pages in the blink of an eye. + +PHARMASEAL have found Forestry CMS combined with HUGO to be so effective at producing fast, purpose driven pages, that we have worked with them to add even more blocks in a scalable, modular fashion. + +**TLDR:** We're blown away with HUGO, the sheer speed, scalability and deployment possibilities with Netlify is the 💣 diff --git a/docs/content/en/showcase/quiply-employee-communications-app/bio.md b/docs/content/en/showcase/quiply-employee-communications-app/bio.md new file mode 100644 index 000000000..f79677a1a --- /dev/null +++ b/docs/content/en/showcase/quiply-employee-communications-app/bio.md @@ -0,0 +1,4 @@ +**Quiply** is an employee communications app enabling mobile collaboration across an entire organization. +Our customers get their own branded app enabling them to communicate fast and effectively with all employees, also non-desk and shift workers. + +As the Quiply app's build process is based on **Gulp**, we have started to build our company and product website using **Gulp + Hugo** which is super-fast and gives us exactly the flexibility we need. diff --git a/docs/content/en/showcase/quiply-employee-communications-app/featured.png b/docs/content/en/showcase/quiply-employee-communications-app/featured.png Binary files differnew file mode 100644 index 000000000..a4e9f046e --- /dev/null +++ b/docs/content/en/showcase/quiply-employee-communications-app/featured.png diff --git a/docs/content/en/showcase/quiply-employee-communications-app/index.md b/docs/content/en/showcase/quiply-employee-communications-app/index.md new file mode 100644 index 000000000..a8c31cc33 --- /dev/null +++ b/docs/content/en/showcase/quiply-employee-communications-app/index.md @@ -0,0 +1,29 @@ +--- + +# A suitable title for this article. +title: Quiply Employee Communications App + +# Set this to the current date. +date: 2018-02-13 + +description: "\"It became immediately clear that we'd use Hugo going forward as it compiles super-fast, is intuitive to use and offers all the features we need.\"" + +# The URL to the site on the internet. +siteURL: https://www.quiply.com + +# Link to the site's Hugo source code if public and you can/want to share. +# Remove or leave blank if not needed/wanted. +# siteSource: https://github.com/gohugoio/hugoDocs + +# Add credit to the article author. Leave blank or remove if not needed/wanted. +byline: "[Sebastian Schirmer](mailto:sebastian.schirmer@quiply.com), Quiply Co-Founder" + +--- + +With the launch of our Employee Communications app Quiply we created a very simple and static one-page website to showcase our product. + +As our customer base and demand for marketing and communication started to grow, we needed a solution to easily grow and extend the contents of our web presence. As we do not have the need to serve dynamic content, we decided to use a static site generator. Amongst a couple of others, we tried Hugo and it became immediately clear that we'd use Hugo going forward as it compiles super-fast, is intuitive to use and offers all the features we need. + +Our website which we launched a couple of weeks ago is still growing and new content is being added constantly. By using Hugo, this can be easily done by content authors writing markdown files without always having to touch HTML or CSS code. It is available in German only for the time being, an English version is in the works. + +Huge thanks to everyone involved in making Hugo a success. diff --git a/docs/content/en/showcase/template/bio.md b/docs/content/en/showcase/template/bio.md new file mode 100644 index 000000000..de9287898 --- /dev/null +++ b/docs/content/en/showcase/template/bio.md @@ -0,0 +1,7 @@ + +Add some **general info** about the site here. + +The site is built by: + +* [Person 1](https://example.org) +* [Person 1](https://example.org) diff --git a/docs/content/en/showcase/template/featured-template.png b/docs/content/en/showcase/template/featured-template.png Binary files differnew file mode 100644 index 000000000..4f390132e --- /dev/null +++ b/docs/content/en/showcase/template/featured-template.png diff --git a/docs/content/en/showcase/template/index.md b/docs/content/en/showcase/template/index.md new file mode 100644 index 000000000..4dc662332 --- /dev/null +++ b/docs/content/en/showcase/template/index.md @@ -0,0 +1,18 @@ +--- +title: Hugo Showcase Template +date: 2018-02-07 +description: "A short description of this page." +siteURL: https://gohugo.io/ +siteSource: https://github.com/gohugoio/hugoDocs +byline: "[bep](https://github.com/bep), Hugo Lead" +--- +Have a **notable Hugo site[^1]**? We would love to feature it in this **Showcase Section** + +Please: + +1. Fork https://github.com/gohugoio/hugoDocs. +2. Run `hugo new content showcase/your-site`. This will use the archetype bundle in the [docs repo](https://github.com/gohugoio/hugoDocs/tree/master/archetypes). +3. Follow the instructions in the newly created page bundle. +4. Create a new pull request in https://github.com/gohugoio/hugoDocs/pulls. + +[^1]: We want this to show Hugo in its best light, so this is not for the average Hugo blog. In most cases the answer to "Is my site [notable](https://www.dictionary.com/browse/notable)?" will be obvious, but if in doubt, create an [issue](https://github.com/gohugoio/hugoDocs/issues) with a link and some words, and we can discuss it. But if you have a site with an interesting Hugo story or a company site where the company itself is notable, you are most welcome. diff --git a/docs/content/en/showcase/tomango/bio.md b/docs/content/en/showcase/tomango/bio.md new file mode 100644 index 000000000..052bd93cd --- /dev/null +++ b/docs/content/en/showcase/tomango/bio.md @@ -0,0 +1,6 @@ + +We help ambitious businesses grow by getting more of the customers they want. + +Our new site runs quickly, anywhere in the world, regardless of internet connectivity. + +The site was built by [Tomango](https://www.tomango.co.uk) diff --git a/docs/content/en/showcase/tomango/featured.png b/docs/content/en/showcase/tomango/featured.png Binary files differnew file mode 100644 index 000000000..d4b037e0f --- /dev/null +++ b/docs/content/en/showcase/tomango/featured.png diff --git a/docs/content/en/showcase/tomango/index.md b/docs/content/en/showcase/tomango/index.md new file mode 100644 index 000000000..6dc1a5c1f --- /dev/null +++ b/docs/content/en/showcase/tomango/index.md @@ -0,0 +1,29 @@ +--- + +title: Tomango + +date: 2018-05-04 + +description: "Showcase: \"Tomango site relaunch: Building our JAMstack site\"" + +siteURL: https://www.tomango.co.uk + +siteSource: https://github.com/trys/tomango-2018 + +byline: "[Trys Mudford](https://www.trysmudford.com), Lead Developer, Tomango" + +--- + +Hugo is our static site generator (SSG) of choice. It's **really quick**. After using it on a number of [client projects](/showcase/hartwell-insurance/), it became clear that our new site _had_ to be built with Hugo. + +The big benefit of an SSG is how it moves all the heavy lifting to the build time. + +For example in WordPress, all the category pages are created at runtime, generating a lot of database queries. In Hugo, the paginated category pages are created at build time - so all the computational complexity is done once, and doesn't impact the user at all. + +Similarly, instead of running a live, or even a heavily cached Instagram feed that checked for new photos on page load, we used IFTTT to flip the feature to work performantly. I've [written about it](https://www.trysmudford.com/blog/making-the-static-dynamic-instagram-importer/) in detail on my blog but in essence: IFTTT sends a webhook to a Netlify Cloud Function every time a photo is uploaded. The function scrapes the photo and commits it to our GitHub repo which triggers a Hugo build on Netlify, deploying the site immediately! + +Shortcodes allow copy editors to continue using WordPress-esque features, Markdown keeps our developers happy, and our users don't have any of the database overheads. It's win-win! + +--- + +This is an extract from our [technical launch post](https://www.tomango.co.uk/thinks/tomango-progressive-web-app/). diff --git a/docs/content/en/templates/404.md b/docs/content/en/templates/404.md new file mode 100644 index 000000000..7fd27a358 --- /dev/null +++ b/docs/content/en/templates/404.md @@ -0,0 +1,55 @@ +--- +title: Custom 404 page +linkTitle: 404 page +description: If you know how to create a single page template, you have unlimited options for creating a custom 404. +categories: [templates] +keywords: ['404',page not found] +menu: + docs: + parent: templates + weight: 220 +weight: 220 +--- + +When using Hugo with [GitHub Pages](https://pages.github.com/), you can provide your own template for a [custom 404 error page](https://docs.github.com/en/pages/getting-started-with-github-pages/creating-a-custom-404-page-for-your-github-pages-site) by creating a 404.html template file in the root of your `layouts` folder. When Hugo generates your site, the `404.html` file will be placed in the root. + +404 pages will have all the regular [page variables][pagevars] available to use in the templates. + +In addition to the standard page variables, the 404 page has access to all site content accessible from `.Pages`. + +```txt +▾ layouts/ + 404.html +``` + +## 404.html + +This is a basic example of a 404.html template: + +{{< code file=layouts/404.html >}} +{{ define "main" }} + <main id="main"> + <div> + <h1 id="title"><a href="{{ "" | relURL }}">Go Home</a></h1> + </div> + </main> +{{ end }} +{{< /code >}} + +## Automatic loading + +Your 404.html file can be set to load automatically when a visitor enters a mistaken URL path, dependent upon the web serving environment you are using. For example: + +* [GitHub Pages](/hosting-and-deployment/hosting-on-github/), [GitLab Pages](/hosting-and-deployment/hosting-on-gitlab/) and [Cloudflare Pages](/hosting-and-deployment/hosting-on-cloudflare-pages/). The 404 page is automatic. +* Apache. You can specify `ErrorDocument 404 /404.html` in an `.htaccess` file in the root of your site. +* Nginx. You might specify `error_page 404 /404.html;` in your `nginx.conf` file. [Details here](https://nginx.org/en/docs/http/ngx_http_core_module.html#error_page). +* Amazon AWS S3. When setting a bucket up for static web serving, you can specify the error file from within the S3 GUI. +* Amazon CloudFront. You can specify the page in the Error Pages section in the CloudFront Console. [Details here](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/custom-error-pages.html) +* Caddy Server. Use the `handle_errors` directive to specify error pages for one or more status codes. [Details here](https://caddyserver.com/docs/caddyfile/directives/handle_errors) +* Netlify. Add `/* /404.html 404` to `content/_redirects`. [Details Here](https://www.netlify.com/docs/redirects/#custom-404) +* Azure Static Web App. set `responseOverrides.404.rewrite` and `responseOverrides.404.statusCode` in configfile `staticwebapp.config.json`. [Details here](https://docs.microsoft.com/en-us/azure/static-web-apps/configuration#response-overrides) +* Azure Storage as Static Web Site Hosting. You can specify the `Error document path` in the Static website configuration page of the Azure portal. [Details here](https://docs.microsoft.com/en-us/azure/storage/blobs/storage-blob-static-website). +* DigitalOcean App Platform. You can specify `error_document` in your app specification file or use control panel to set up error document. [Details here](https://docs.digitalocean.com/products/app-platform/how-to/manage-static-sites/#configure-a-static-site). +* [Firebase Hosting](https://firebase.google.com/docs/hosting/full-config#404): `/404.html` automatically gets used as the 404 page. + +[pagevars]: /variables/page/ diff --git a/docs/content/en/templates/_index.md b/docs/content/en/templates/_index.md new file mode 100644 index 000000000..b2197d162 --- /dev/null +++ b/docs/content/en/templates/_index.md @@ -0,0 +1,16 @@ +--- +title: Templates +linkTitle: Overview +description: Go templating, template types and lookup order, shortcodes, and data. +categories: [] +keywords: [] +menu: + docs: + identifier: templates-overview + parent: templates + weight: 10 +weight: 10 +aliases: [/templates/overview/,/templates/content] +--- + +A template is an HTML file with [template actions](/getting-started/glossary/#template-action), located within the layouts directory of a project, theme, or module. Visit the topics below, in the order presented, to understand template selection and creation. diff --git a/docs/content/en/templates/base.md b/docs/content/en/templates/base.md new file mode 100644 index 000000000..63bf2f9b2 --- /dev/null +++ b/docs/content/en/templates/base.md @@ -0,0 +1,97 @@ +--- +title: Base templates and blocks +description: The base and block constructs allow you to define the outer shell of your master templates (i.e., the chrome of the page). +categories: [templates,fundamentals] +keywords: [blocks,base] +menu: + docs: + parent: templates + weight: 40 +weight: 40 +toc: true +aliases: [/templates/blocks/,/templates/base-templates-and-blocks/] +--- + +The `block` keyword allows you to define the outer shell of your pages' one or more master template(s) and then fill in or override portions as necessary. + +{{< youtube QVOMCYitLEc >}} + +## Base template lookup order + +The base template lookup order closely follows that of the template it applies to (e.g. `_default/list.html`). + +See [Template Lookup Order](/templates/lookup-order/) for details and examples. + +## Define the base template + +The following defines a simple base template at `_default/baseof.html`. As a default template, it is the shell from which all your pages will be rendered unless you specify another `*baseof.html` closer to the beginning of the lookup order. + +{{< code file=layouts/_default/baseof.html >}} +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>{{ block "title" . }} + <!-- Blocks may include default content. --> + {{ .Site.Title }} + {{ end }}</title> + </head> + <body> + <!-- Code that all your templates share, like a header --> + {{ block "main" . }} + <!-- The part of the page that begins to differ between templates --> + {{ end }} + {{ block "footer" . }} + <!-- More shared code, perhaps a footer but that can be overridden if need be in --> + {{ end }} + </body> +</html> +{{< /code >}} + +## Override the base template + +From the above base template, you can define a [default list template][hugolists]. The default list template will inherit all of the code defined above and can then implement its own `"main"` block from: + +{{< code file=layouts/_default/list.html >}} +{{ define "main" }} + <h1>Posts</h1> + {{ range .Pages }} + <article> + <h2>{{ .Title }}</h2> + {{ .Content }} + </article> + {{ end }} +{{ end }} +{{< /code >}} + +This replaces the contents of our (basically empty) "main" block with something useful for the list template. In this case, we didn't define a `"title"` block, so the contents from our base template remain unchanged in lists. + +{{% note %}} +Code that you put outside the block definitions *can* break your layout. This even includes HTML comments. For example: + +```go-html-template +<!-- Seemingly harmless HTML comment..that will break your layout at build --> +{{ define "main" }} +...your code here +{{ end }} +``` +[See this thread from the Hugo discussion forums.](https://discourse.gohugo.io/t/baseof-html-block-templates-and-list-types-results-in-empty-pages/5612/6) +{{% /note %}} + +The following shows how you can override both the `"main"` and `"title"` block areas from the base template with code unique to your [default single page template][singletemplate]: + +{{< code file=layouts/_default/single.html >}} +{{ define "title" }} + <!-- This will override the default value set in baseof.html; i.e., "{{ .Site.Title }}" in the original example--> + {{ .Title }} – {{ .Site.Title }} +{{ end }} +{{ define "main" }} + <h1>{{ .Title }}</h1> + {{ .Content }} +{{ end }} +{{< /code >}} + +[hugolists]: /templates/lists +[lookup]: /templates/lookup-order/ +[rendering the section]: /templates/section-templates/ +[singletemplate]: /templates/single-page-templates/ diff --git a/docs/content/en/templates/data-templates.md b/docs/content/en/templates/data-templates.md new file mode 100644 index 000000000..b862f727e --- /dev/null +++ b/docs/content/en/templates/data-templates.md @@ -0,0 +1,177 @@ +--- +title: Data templates +description: In addition to Hugo's built-in variables, you can specify your own custom data in templates or shortcodes that pull from both local and dynamic sources. +categories: [templates] +keywords: [data,dynamic,csv,json,toml,yaml,xml] +menu: + docs: + parent: templates + weight: 150 +weight: 150 +toc: true +aliases: [/extras/datafiles/,/extras/datadrivencontent/,/doc/datafiles/] +--- + +Hugo supports loading data from YAML, JSON, XML, and TOML files located in the `data` directory at the root of your Hugo project. + +{{< youtube FyPgSuwIMWQ >}} + +## The data directory + +The `data` directory should store additional data for Hugo to use when generating your site. + +Data files are not for generating standalone pages. They should supplement content files by: + +- Extending the content when the front matter fields grow out of control, or +- Showing a larger dataset in a template (see the example below). + +In both cases, it's a good idea to outsource the data in their (own) files. + +These files must be YAML, JSON, XML, or TOML files (using the `.yml`, `.yaml`, `.json`, `.xml`, or `.toml` extension). The data will be accessible as a `map` in the `.Site.Data` variable. + +To access the data using the `site.Data.filename` notation, the file name must begin with an underscore or a Unicode letter, followed by zero or more underscores, Unicode letters, or Unicode digits. For example: + +- `123.json` - Invalid +- `x123.json` - Valid +- `_123.json` - Valid + +To access the data using the [`index`](/functions/collections/indexfunction) function, the file name is irrelevant. For example: + +Data file|Template code +:--|:-- +`123.json`|`{{ index .Site.Data "123" }}` +`x123.json`|`{{ index .Site.Data "x123" }}` +`_123.json`|`{{ index .Site.Data "_123" }}` +`x-123.json`|`{{ index .Site.Data "x-123" }}` + +## Data files in themes + +Data Files can also be used in themes. + +However, note that the theme data files are merged with the project directory taking precedence. That is, Given two files with the same name and relative path, the data in the file in the root project `data` directory will override the data from the file in the `themes/<THEME>/data` directory *for keys that are duplicated*). + +Therefore, theme authors should be careful not to include data files that could be easily overwritten by a user who decides to [customize a theme][customize]. For theme-specific data items that shouldn't be overridden, it can be wise to prefix the folder structure with a namespace; e.g. `mytheme/data/<THEME>/somekey/...`. To check if any such duplicate exists, run hugo with the `-v` flag. + +The keys in the map created with data templates from data files will be a dot-chained set of `path`, `filename`, and `key` in the file (if applicable). + +This is best explained with an example: + +## Examples + +### Jaco Pastorius' Solo Discography + +[Jaco Pastorius](https://en.wikipedia.org/wiki/Jaco_Pastorius_discography) was a great bass player, but his solo discography is short enough to use as an example. [John Patitucci](https://en.wikipedia.org/wiki/John_Patitucci) is another bass giant. + +The example below is a bit contrived, but it illustrates the flexibility of data Files. This example uses TOML as its file format with the two following data files: + +* `data/jazz/bass/jacopastorius.toml` +* `data/jazz/bass/johnpatitucci.toml` + +`jacopastorius.toml` contains the content below. `johnpatitucci.toml` contains a similar list: + +{{< code-toggle file=data/jazz/bass/jacopastorius >}} +discography = [ +"1974 - Modern American Music … Period! The Criteria Sessions", +"1974 - Jaco", +"1976 - Jaco Pastorius", +"1981 - Word of Mouth", +"1981 - The Birthday Concert (released in 1995)", +"1982 - Twins I & II (released in 1999)", +"1983 - Invitation", +"1986 - Broadway Blues (released in 1998)", +"1986 - Honestly Solo Live (released in 1990)", +"1986 - Live In Italy (released in 1991)", +"1986 - Heavy'n Jazz (released in 1992)", +"1991 - Live In New York City, Volumes 1-7.", +"1999 - Rare Collection (compilation)", +"2003 - Punk Jazz: The Jaco Pastorius Anthology (compilation)", +"2007 - The Essential Jaco Pastorius (compilation)" +] +{{< /code-toggle >}} + +The list of bass players can be accessed via `.Site.Data.jazz.bass`, a single bass player by adding the file name without the suffix, e.g. `.Site.Data.jazz.bass.jacopastorius`. + +You can now render the list of recordings for all the bass players in a template: + +```go-html-template +{{ range $.Site.Data.jazz.bass }} + {{ partial "artist.html" . }} +{{ end }} +``` + +And then in the `partials/artist.html`: + +```go-html-template +<ul> +{{ range .discography }} + <li>{{ . }}</li> +{{ end }} +</ul> +``` + +Discover a new favorite bass player? Just add another `.toml` file in the same directory. + +### Accessing named values in a data file + +Assume you have the following data structure in your `user0123` data file located directly in `data/`: + +{{< code-toggle file=data/user0123 >}} +Name: User0123 +"Short Description": "He is a **jolly good** fellow." +Achievements: + - "Can create a Key, Value list from Data File" + - "Learns Hugo" + - "Reads documentation" +{{</ code-toggle >}} + +You can use the following code to render the `Short Description` in your layout: + +```go-html-template +<div>Short Description of {{ .Site.Data.User0123.Name }}: <p>{{ index .Site.Data.User0123 "Short Description" | markdownify }}</p></div> +``` + +Note the use of the [`markdownify`] function. This will send the description through the Markdown rendering engine. + +## Remote data + +Retrieve remote data using these template functions: + +- [`resources.GetRemote`](/functions/resources/getremote) (recommended) +- [`data.GetCSV`](/functions/data/getcsv) +- [`data.GetJSON`](/functions/data/getjson) + +## LiveReload with data files + +There is no chance to trigger a [LiveReload] when the content of a URL changes. However, when a *local* file changes (i.e., `data/*` and `themes/<THEME>/data/*`), a LiveReload will be triggered. Symlinks are not supported. Note too that because downloading data takes a while, Hugo stops processing your Markdown files until the data download has been completed. + +{{% note %}} +If you change any local file and the LiveReload is triggered, Hugo will read the data-driven (URL) content from the cache. If you have disabled the cache (i.e., by running the server with `hugo server --ignoreCache`), Hugo will re-download the content every time LiveReload triggers. This can create *huge* traffic. You may reach API limits quickly. +{{% /note %}} + +## Examples of data-driven content + +- Photo gallery JSON powered: [https://github.com/pcdummy/hugo-lightslider-example](https://github.com/pcdummy/hugo-lightslider-example) +- GitHub Starred Repositories [in a post](https://github.com/SchumacherFM/blog-cs/blob/master/content%2Fposts%2Fgithub-starred.md) using data-driven content in a [custom short code](https://github.com/SchumacherFM/blog-cs/blob/master/layouts%2Fshortcodes%2FghStarred.html). + +## Specs for data formats + +* [TOML Spec][toml] +* [YAML Spec][yaml] +* [JSON Spec][json] +* [CSV Spec][csv] +* [XML Spec][xml] + +[config]: /getting-started/configuration/ +[csv]: https://tools.ietf.org/html/rfc4180 +[customize]: /hugo-modules/theme-components/ +[json]: https://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf +[LiveReload]: /getting-started/usage/#livereload +[lookup]: /templates/lookup-order/ +[`markdownify`]: /functions/transform/markdownify +[OAuth]: https://en.wikipedia.org/wiki/OAuth +[partials]: /templates/partials/ +[toml]: https://toml.io/en/latest +[variadic]: https://en.wikipedia.org/wiki/Variadic_function +[vars]: /variables/ +[yaml]: https://yaml.org/spec/ +[xml]: https://www.w3.org/XML/ diff --git a/docs/content/en/templates/files.md b/docs/content/en/templates/files.md new file mode 100644 index 000000000..1847af9bc --- /dev/null +++ b/docs/content/en/templates/files.md @@ -0,0 +1,56 @@ +--- +title: Local file templates +description: Hugo's `readDir` and `readFile` functions make it easy to traverse your project's directory structure and write file contents to your templates. +categories: [templates] +keywords: [files,directories] +menu: + docs: + parent: templates + weight: 180 +weight: 180 +toc: true +aliases: [/extras/localfiles/,/templates/local-files/] +--- + +## Traverse local files + +With Hugo's [`readDir`] and [`readFile`] template functions, you can traverse your website's files on your server. + +## Use `readDir` + +The [`readDir`] function returns an array of [`os.FileInfo`] structures. It takes the file's `path` as a single string argument. This path can be to any directory of your website (i.e., as found on your server's file system). + +Whether the path is absolute or relative does not matter because---at least for `readDir`---the root of your website (typically `./public/`) in effect becomes both: + +1. The file system root +2. The current working directory + +## Use `readFile` + +The [`readfile`] function reads a file from disk and converts it into a string to be manipulated by other Hugo functions or added as-is. `readFile` takes the file, including path, as an argument passed to the function. + +To use the `readFile` function in your templates, make sure the path is relative to your *Hugo project's root directory*: + +```go-html-template +{{ readFile "/content/templates/local-file-templates" }} +``` + +### `readFile` Example: Add a Project File to Content + +As `readFile` is a function, it is only available to you in your templates and not your content. However, we can create a simple [shortcode template][sct] that calls `readFile`, passes the first argument through the function, and then allows an optional second argument to send the file through the Markdown processor. The pattern for adding this shortcode to your content will be as follows: + +```go-html-template +{{</* readfile file="/path/to/local/file.txt" markdown="true" */>}} +``` + +{{% note %}} +If you are going to create [custom shortcodes](/templates/shortcode-templates/) with `readFile` for a theme, note that usage of the shortcode will refer to the project root and *not* your `themes` directory. +{{% /note %}} + +[called directly in the Hugo docs]: https://github.com/gohugoio/hugoDocs/blob/master/content/en/templates/files.md +[`os.FileInfo`]: https://pkg.go.dev/io/fs#FileInfo +[`readDir`]: /functions/os/readdir +[`readFile`]: /functions/os/readfile +[sc]: /content-management/shortcodes/ +[sct]: /templates/shortcode-templates/ +[readfilesource]: https://github.com/gohugoio/hugoDocs/blob/master/layouts/shortcodes/readfile.html diff --git a/docs/content/en/templates/homepage.md b/docs/content/en/templates/homepage.md new file mode 100644 index 000000000..59b7472fb --- /dev/null +++ b/docs/content/en/templates/homepage.md @@ -0,0 +1,65 @@ +--- +title: Homepage template +description: The homepage of a website is often formatted differently than the other pages. For this reason, Hugo makes it easy for you to define your new site's homepage as a unique template. +categories: [templates] +keywords: [homepage] +menu: + docs: + parent: templates + weight: 70 +weight: 70 +toc: true +aliases: [/layout/homepage/,/templates/homepage-template/] +--- + +Homepage is a `Page` and therefore has all the [page variables][pagevars] and [site variables][sitevars] available for use. + +{{% note %}} +The homepage template is the *only* required template for building a site and therefore useful when bootstrapping a new site and template. It is also the only required template if you are developing a single-page website. +{{% /note %}} + +{{< youtube ut1xtRZ1QOA >}} + +## Homepage template lookup order + +See [Template Lookup](/templates/lookup-order/). + +## Add content and front matter to the homepage + +The homepage, similar to other [list pages in Hugo][lists], accepts content and front matter from an `_index.md` file. This file should live at the root of your `content` folder (i.e., `content/_index.md`). You can then add body copy and metadata to your homepage the way you would any other content file. + +See the homepage template below or [Content Organization][contentorg] for more information on the role of `_index.md` in adding content and front matter to list pages. + +## Example homepage template + +The following is an example of a homepage template that uses [partial][partials], [base] templates, and a content file at `content/_index.md` to populate the `{{ .Title }}` and `{{ .Content }}` [page variables][pagevars]. + +{{< code file=layouts/index.html >}} +{{ define "main" }} + <main aria-role="main"> + <header class="homepage-header"> + <h1>{{ .Title }}</h1> + {{ with .Params.subtitle }} + <span class="subtitle">{{ . }}</span> + {{ end }} + </header> + <div class="homepage-content"> + <!-- Note that the content for index.html, as a sort of list page, will pull from content/_index.md --> + {{ .Content }} + </div> + <div> + {{ range first 10 .Site.RegularPages }} + {{ .Render "summary" }} + {{ end }} + </div> + </main> +{{ end }} +{{< /code >}} + +[base]: /templates/base/ +[contentorg]: /content-management/organization/ +[lists]: /templates/lists/ +[lookup]: /templates/lookup-order/ +[pagevars]: /variables/page/ +[partials]: /templates/partials/ +[sitevars]: /variables/site/ diff --git a/docs/content/en/templates/internal.md b/docs/content/en/templates/internal.md new file mode 100644 index 000000000..9438bfa6f --- /dev/null +++ b/docs/content/en/templates/internal.md @@ -0,0 +1,221 @@ +--- +title: Internal templates +description: Hugo ships with a group of boilerplate templates that cover the most common use cases for static websites. +categories: [templates] +keywords: [internal, analytics,] +menu: + docs: + parent: templates + weight: 190 +weight: 190 +toc: true +--- + +{{% note %}} +While the following internal templates are called similar to partials, they do *not* observe the partial template lookup order. +{{% /note %}} + +## Google Analytics + +Hugo ships with an internal template supporting [Google Analytics 4]. + +[Google Analytics 4]: https://support.google.com/analytics/answer/10089681 + +### Configure Google Analytics + +Provide your tracking ID in your configuration file: + +**Google Analytics 4 (gtag.js)** +{{< code-toggle file=hugo >}} +[services.googleAnalytics] +ID = "G-MEASUREMENT_ID" +{{</ code-toggle >}} + +### Use the Google Analytics template + +Include the Google Analytics internal template in your templates where you want the code to appear: + +```go-html-template +{{ template "_internal/google_analytics.html" . }} +``` + +To create your own template, access the configured ID with `{{ site.Config.Services.GoogleAnalytics.ID }}`. + +## Disqus + +Hugo also ships with an internal template for [Disqus comments][disqus], a popular commenting system for both static and dynamic websites. To effectively use Disqus, secure a Disqus "shortname" by [signing up for the free service][disqussignup]. + +### Configure Disqus + +To use Hugo's Disqus template, first set up a single configuration value: + +{{< code-toggle file="hugo" >}} +[services.disqus] +shortname = 'your-disqus-shortname' +{{</ code-toggle >}} + +Hugo's Disqus template accesses this value with: + +```go-html-template +{{ .Site.Config.Services.Disqus.Shortname }} +``` + +You can also set the following in the front matter for a given piece of content: + +* `disqus_identifier` +* `disqus_title` +* `disqus_url` + +### Use the Disqus template + +To add Disqus, include the following line in the templates where you want your comments to appear: + +```go-html-template +{{ template "_internal/disqus.html" . }} +``` + +### Conditional loading of Disqus comments + +Users have noticed that enabling Disqus comments when running the Hugo web server on `localhost` (i.e. via `hugo server`) causes the creation of unwanted discussions on the associated Disqus account. + +You can create the following `layouts/partials/disqus.html`: + +{{< code file=layouts/partials/disqus.html >}} +<div id="disqus_thread"></div> +<script type="text/javascript"> + +(function() { + // Don't ever inject Disqus on localhost--it creates unwanted + // discussions from 'localhost:1313' on your Disqus account... + if (window.location.hostname == "localhost") + return; + + var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true; + var disqus_shortname = '{{ .Site.Config.Services.Disqus.Shortname }}'; + dsq.src = '//' + disqus_shortname + '.disqus.com/embed.js'; + (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq); +})(); +</script> +<noscript>Please enable JavaScript to view the <a href="https://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript> +<a href="https://disqus.com/" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a> +{{< /code >}} + +The `if` statement skips the initialization of the Disqus comment injection when you are running on `localhost`. + +You can then render your custom Disqus partial template as follows: + +```go-html-template +{{ partial "disqus.html" . }} +``` + +## Open Graph + +An internal template for the [Open Graph protocol](https://ogp.me/), metadata that enables a page to become a rich object in a social graph. +This format is used for Facebook and some other sites. + +### Configure Open Graph + +Hugo's Open Graph template is configured using a mix of configuration variables and [front-matter](/content-management/front-matter/) on individual pages. + +{{< code-toggle file=hugo >}} +[params] + title = "My cool site" + images = ["site-feature-image.jpg"] + description = "Text about my cool site" +[taxonomies] + series = "series" +{{</ code-toggle >}} + +{{< code-toggle file=content/blog/my-post.md >}} +title = "Post title" +description = "Text about this post" +date = "2006-01-02" +images = ["post-cover.png"] +audio = [] +videos = [] +series = [] +tags = [] +{{</ code-toggle >}} + +Hugo uses the page title and description for the title and description metadata. +The first 6 URLs from the `images` array are used for image metadata. +If [page bundles](/content-management/page-bundles/) are used and the `images` array is empty or undefined, images with file names matching `*feature*` or `*cover*,*thumbnail*` are used for image metadata. + +Various optional metadata can also be set: + +- Date, published date, and last modified data are used to set the published time metadata if specified. +- `audio` and `videos` are URL arrays like `images` for the audio and video metadata tags, respectively. +- The first 6 `tags` on the page are used for the tags metadata. +- The `series` taxonomy is used to specify related "see also" pages by placing them in the same series. + +If using YouTube this will produce a og:video tag like `<meta property="og:video" content="url">`. Use the `https://youtu.be/<id>` format with YouTube videos (example: `https://youtu.be/qtIqKaDlqXo`). + +### Use the Open Graph template + +To add Open Graph metadata, include the following line between the `<head>` tags in your templates: + +```go-html-template +{{ template "_internal/opengraph.html" . }} +``` + +## Twitter Cards + +An internal template for [Twitter Cards](https://developer.twitter.com/en/docs/twitter-for-websites/cards/overview/abouts-cards), +metadata used to attach rich media to Tweets linking to your site. + +### Configure Twitter Cards + +Hugo's Twitter Card template is configured using a mix of configuration variables and [front-matter](/content-management/front-matter/) on individual pages. + +{{< code-toggle file=hugo >}} +[params] + images = ["site-feature-image.jpg"] + description = "Text about my cool site" +{{</ code-toggle >}} + +{{< code-toggle file=content/blog/my-post.md >}} +title = "Post title" +description = "Text about this post" +images = ["post-cover.png"] +{{</ code-toggle >}} + +If `images` aren't specified in the page front-matter, then hugo searches for [image page resources](/content-management/image-processing/) with `feature`, `cover`, or `thumbnail` in their name. +If no image resources with those names are found, the images defined in the [site config](/getting-started/configuration/) are used instead. +If no images are found at all, then an image-less Twitter `summary` card is used instead of `summary_large_image`. + +Hugo uses the page title and description for the card's title and description fields. The page summary is used if no description is given. + +Set the value of `twitter:site` in your site configuration: + +{{< code-toggle file="hugo" copy=false >}} +[params.social] +twitter = "GoHugoIO" +{{</ code-toggle >}} + +NOTE: The `@` will be added for you + +```html +<meta name="twitter:site" content="@GoHugoIO"/> +``` + +### Use the Twitter Cards template + +To add Twitter card metadata, include the following line immediately after the `<head>` element in your templates: + +```go-html-template +{{ template "_internal/twitter_cards.html" . }} +``` + +## The internal templates + +The code for these templates is located [here](https://github.com/gohugoio/hugo/tree/master/tpl/tplimpl/embedded/templates). + +* `_internal/disqus.html` +* `_internal/google_analytics.html` +* `_internal/opengraph.html` +* `_internal/pagination.html` +* `_internal/schema.html` +* `_internal/twitter_cards.html` + +[disqus]: https://disqus.com +[disqussignup]: https://disqus.com/profile/signup/ diff --git a/docs/content/en/templates/introduction.md b/docs/content/en/templates/introduction.md new file mode 100644 index 000000000..7fb0ddecf --- /dev/null +++ b/docs/content/en/templates/introduction.md @@ -0,0 +1,672 @@ +--- +title: Templating +linkTitle: Templating +description: Hugo uses Go's `html/template` and `text/template` libraries as the basis for the templating. +categories: [templates,fundamentals] +keywords: [go] +menu: + docs: + parent: templates + weight: 20 +weight: 20 +toc: true +aliases: [/layouts/introduction/,/layout/introduction/, /templates/go-templates/] +--- + +{{% note %}} +The following is only a primer on Go Templates. For an in-depth look into Go Templates, check the official [Go docs](https://golang.org/pkg/text/template/). +{{% /note %}} + +Go Templates provide an extremely simple template language that adheres to the belief that only the most basic of logic belongs in the template or view layer. + +## Basic syntax + +Go Templates are HTML files with the addition of [variables][variables] and [functions][functions]. Go Template variables and functions are accessible within `{{ }}`. + +### Access a predefined variable + +A _predefined variable_ could be a variable already existing in the +current scope (like the `.Title` example in the [Variables](#variables) section below) or a custom variable (like the +`$address` example in that same section). + +```go-html-template +{{ .Title }} +{{ $address }} +``` + +Parameters for functions are separated using spaces. The general syntax is: + +```go-html-template +{{ FUNCTION ARG1 ARG2 .. }} +``` + +The following example calls the `add` function with inputs of `1` and `2`: + +```go-html-template +{{ add 1 2 }} +``` + +#### Methods and fields are accessed via dot notation + +Accessing the Page Parameter `bar` defined in a piece of content's [front matter]. + +```go-html-template +{{ .Params.bar }} +``` + +#### Parentheses can be used to group items together + +```go-html-template +{{ if or (isset .Params "alt") (isset .Params "caption") }} Caption {{ end }} +``` + +#### A single statement can be split over multiple lines + +```go-html-template +{{ if or + (isset .Params "alt") + (isset .Params "caption") +}} +``` + +#### Raw string literals can include newlines + +```go-html-template +{{ $msg := `Line one. +Line two.` }} +``` + +## Variables + +Each Go Template gets a data object. In Hugo, each template is passed +a `Page`. In the below example, `.Title` is one of the elements +accessible in that [`Page` variable][pagevars]. + +With the `Page` being the default scope of a template, the `Title` +element in current scope (`.` -- "the **dot**") is accessible simply +by the dot-prefix (`.Title`): + +```go-html-template +<title>{{ .Title }}</title> +``` + +Values can also be stored in custom variables and referenced later: + +{{% note %}} +The custom variables need to be prefixed with `$`. +{{% /note %}} + +```go-html-template +{{ $address := "123 Main St." }} +{{ $address }} +``` + +Variables can be re-defined using the `=` operator. The example below +prints "Var is Hugo Home" on the home page, and "Var is Hugo Page" on +all other pages: + +```go-html-template +{{ $var := "Hugo Page" }} +{{ if .IsHome }} + {{ $var = "Hugo Home" }} +{{ end }} +Var is {{ $var }} +``` + +Variable names must conform to Go's naming rules for [identifiers][identifier]. + +## Functions + +Go Templates only ship with a few basic functions but also provide a mechanism for applications to extend the original set. + +[Hugo template functions][functions] provide additional functionality specific to building websites. Functions are called by using their name followed by the required parameters separated by spaces. Template functions cannot be added without recompiling Hugo. + +### Example 1: adding numbers + +```go-html-template +{{ add 1 2 }} +<!-- prints 3 --> +``` + +### Example 2: comparing numbers + +```go-html-template +{{ lt 1 2 }} +<!-- prints true (i.e., since 1 is less than 2) --> +``` + +Note that both examples make use of Go Template's [math][math] functions. + +{{% note %}} +There are more boolean operators than those listed in the Hugo docs in the [Go Template documentation](https://golang.org/pkg/text/template/#hdr-Functions). +{{% /note %}} + +## Includes + +When including another template, you will need to pass it the data that it would +need to access. + +{{% note %}} +To pass along the current context, please remember to include a trailing **dot**. +{{% /note %}} + +The templates location will always be starting at the `layouts/` directory +within Hugo. + +### Partial + +The [`partial`][partials] function is used to include _partial_ templates using +the syntax `{{ partial "<PATH>/<PARTIAL>.<EXTENSION>" . }}`. + +Example of including a `layouts/partials/header.html` partial: + +```go-html-template +{{ partial "header.html" . }} +``` + +### Template + +The `template` function was used to include _partial_ templates +in much older Hugo versions. Now it's useful only for calling +[_internal_ templates][internal templates]. The syntax is `{{ template +"_internal/<TEMPLATE>.<EXTENSION>" . }}`. + +{{% note %}} +The available **internal** templates can be found +[here](https://github.com/gohugoio/hugo/tree/master/tpl/tplimpl/embedded/templates). +{{% /note %}} + +Example of including the internal `opengraph.html` template: + +```go-html-template +{{ template "_internal/opengraph.html" . }} +``` + +## Logic + +Go Templates provide the most basic iteration and conditional logic. + +### Iteration + +The Go Templates make heavy use of `range` to iterate over a _map_, +_array_, or _slice_. The following are different examples of how to +use `range`. + +#### Example 1: using context (`.`) + +```go-html-template +{{ range $array }} + {{ . }} <!-- The . represents an element in $array --> +{{ end }} +``` + +#### Example 2: declaring a variable name for an array element's value + +```go-html-template +{{ range $elem_val := $array }} + {{ $elem_val }} +{{ end }} +``` + +#### Example 3: declaring variable names for an array element's index _and_ value + +For an array or slice, the first declared variable will map to each +element's index. + +```go-html-template +{{ range $elem_index, $elem_val := $array }} + {{ $elem_index }} -- {{ $elem_val }} +{{ end }} +``` + +#### Example 4: declaring variable names for a map element's key _and_ value + +For a map, the first declared variable will map to each map element's +key. + +```go-html-template +{{ range $elem_key, $elem_val := $map }} + {{ $elem_key }} -- {{ $elem_val }} +{{ end }} +``` + +#### Example 5: conditional on empty _map_, _array_, or _slice_ + +If the _map_, _array_, or _slice_ passed into the range is zero-length then the else statement is evaluated. + +```go-html-template +{{ range $array }} + {{ . }} +{{ else }} + <!-- This is only evaluated if $array is empty --> +{{ end }} +``` + +### Conditionals + +`if`, `else`, `with`, `or`, `and` and `not` provide the framework for handling conditional logic in Go Templates. Like `range`, `if` and `with` statements are closed with an `{{ end }}`. + +Go Templates treat the following values as **false**: + +- `false` (boolean) +- 0 (integer) +- any zero-length array, slice, map, or string + +#### Example 1: `with` + +It is common to write "if something exists, do this" kind of +statements using `with`. + +{{% note %}} +`with` rebinds the context `.` within its scope (just like in `range`). +{{% /note %}} + +It skips the block if the variable is absent, or if it evaluates to +"false" as explained above. + +```go-html-template +{{ with .Params.title }} + <h4>{{ . }}</h4> +{{ end }} +``` + +#### Example 2: `with` .. `else` + +Below snippet uses the "description" front-matter parameter's value if +set, else uses the default `.Summary` [Page variable][pagevars]: + +```go-html-template +{{ with .Param "description" }} + {{ . }} +{{ else }} + {{ .Summary }} +{{ end }} +``` + +See the [`.Param` function][param]. + +#### Example 3: `if` + +An alternative (and a more verbose) way of writing `with` is using +`if`. Here, the `.` does not get rebound. + +Below example is "Example 1" rewritten using `if`: + +```go-html-template +{{ if isset .Params "title" }} + <h4>{{ index .Params "title" }}</h4> +{{ end }} +``` + +#### Example 4: `if` .. `else` + +Below example is "Example 2" rewritten using `if` .. `else`, and using +[`isset`] + `.Params` variable (different from the +[`.Param` **function**][param]) instead: + +```go-html-template +{{ if (isset .Params "description") }} + {{ index .Params "description" }} +{{ else }} + {{ .Summary }} +{{ end }} +``` + +#### Example 5: `if` .. `else if` .. `else` + +Unlike `with`, `if` can contain `else if` clauses too. + +```go-html-template +{{ if (isset .Params "description") }} + {{ index .Params "description" }} +{{ else if (isset .Params "summary") }} + {{ index .Params "summary" }} +{{ else }} + {{ .Summary }} +{{ end }} +``` + +#### Example 6: `and` & `or` + +```go-html-template +{{ if (and (or (isset .Params "title") (isset .Params "caption")) (isset .Params "attr")) }} +``` + +## Pipes + +One of the most powerful components of Go Templates is the ability to stack actions one after another. This is done by using pipes. Borrowed from Unix pipes, the concept is simple: each pipeline's output becomes the input of the following pipe. + +Because of the very simple syntax of Go Templates, the pipe is essential to being able to chain together function calls. One limitation of the pipes is that they can only work with a single value and that value becomes the last parameter of the next pipeline. + +A few simple examples should help convey how to use the pipe. + +### Example 1: `shuffle` + +The following two examples are functionally the same: + +```go-html-template +{{ shuffle (seq 1 5) }} +``` + +```go-html-template +{{ (seq 1 5) | shuffle }} +``` + +### Example 2: `index` + +The following accesses the page parameter called "disqus_url" and escapes the HTML. This example also uses the [`index`] function, which is built into Go Templates: + +```go-html-template +{{ index .Params "disqus_url" | html }} +``` + +### Example 3: `or` with `isset` + +```go-html-template +{{ if or (or (isset .Params "title") (isset .Params "caption")) (isset .Params "attr") }} +Stuff Here +{{ end }} +``` + +Could be rewritten as + +```go-html-template +{{ if isset .Params "caption" | or isset .Params "title" | or isset .Params "attr" }} +Stuff Here +{{ end }} +``` + +## Context (aka "the dot") {#the-dot} + +The most easily overlooked concept to understand about Go Templates is +that `{{ . }}` always refers to the **current context**. + +- In the top level of your template, this will be the data set made + available to it. +- Inside an iteration, however, it will have the value of the + current item in the loop; i.e., `{{ . }}` will no longer refer to + the data available to the entire page. + +If you need to access page-level data (e.g., page parameters set in front +matter) from within the loop, you will likely want to do one of the +following: + +### 1. Define a variable independent of context + +The following shows how to define a variable independent of the context. + +{{< code file=tags-range-with-page-variable.html >}} +{{ $title := .Site.Title }} +<ul> +{{ range .Params.tags }} + <li> + <a href="/tags/{{ . | urlize }}">{{ . }}</a> + - {{ $title }} + </li> +{{ end }} +</ul> +{{< /code >}} + +{{% note %}} +Notice how once we have entered the loop (i.e. `range`), the value of `{{ . }}` has changed. We have defined a variable outside the loop (`{{ $title }}`) that we've assigned a value so that we have access to the value from within the loop as well. +{{% /note %}} + +### 2. Use `$.` to access the global context + +`$` has special significance in your templates. `$` is set to the starting value of `.` ("the dot") by default. This is a [documented feature of Go text/template][dotdoc]. This means you have access to the global context from anywhere. Here is an equivalent example of the preceding code block but now using `$` to grab `.Site.Title` from the global context: + +{{< code file=range-through-tags-w-global.html >}} +<ul> +{{ range .Params.tags }} + <li> + <a href="/tags/{{ . | urlize }}">{{ . }}</a> + - {{ $.Site.Title }} + </li> +{{ end }} +</ul> +{{< /code >}} + +{{% note %}} +The built-in magic of `$` would cease to work if someone were to mischievously redefine the special character; e.g. `{{ $ := .Site }}`. *Don't do it.* You may, of course, recover from this mischief by using `{{ $ := . }}` in a global context to reset `$` to its default value. +{{% /note %}} + +## Whitespace + +Go 1.6 includes the ability to trim the whitespace from either side of a Go tag by including a hyphen (`-`) and space immediately beside the corresponding `{{` or `}}` delimiter. + +For instance, the following Go Template will include the newlines and horizontal tab in its HTML output: + +```go-html-template +<div> + {{ .Title }} +</div> +``` + +Which will output: + +```html +<div> + Hello, World! +</div> +``` + +Leveraging the `-` in the following example will remove the extra white space surrounding the `.Title` variable and remove the newline: + +```go-html-template +<div> + {{- .Title -}} +</div> +``` + +Which then outputs: + +```html +<div>Hello, World!</div> +``` + +Go considers the following characters _whitespace_: + +* space +* horizontal tab +* carriage return +* newline + +## Comments + +In order to keep your templates organized and share information throughout your team, you may want to add comments to your templates. There are two ways to do that with Hugo. + +### Go templates comments + +Go Templates support `{{/*` and `*/}}` to open and close a comment block. Nothing within that block will be rendered. + +For example: + +```go-html-template +Bonsoir, {{/* {{ add 0 + 2 }} */}}Eliott. +``` + +Will render `Bonsoir, Eliott.`, and not care about the syntax error (`add 0 + 2`) in the comment block. + +### HTML comments + +You can add html comments by piping a string HTML code comment to `safeHTML`. + +For example: + +```go-html-template +{{ "<!-- This is an HTML comment -->" | safeHTML }} +``` + +If you need variables to construct such HTML comments, just pipe `printf` to `safeHTML`. + +For example: + +```go-html-template +{{ printf "<!-- Our website is named: %s -->" .Site.Title | safeHTML }} +``` + +#### HTML comments containing Go templates + +HTML comments are by default stripped, but their content is still evaluated. That means that although the HTML comment will never render any content to the final HTML pages, code contained within the comment may fail the build process. + +{{% note %}} +Do **not** try to comment out Go Template code using HTML comments. +{{% /note %}} + +```go-html-template +<!-- {{ $author := "Emma Goldman" }} was a great woman. --> +{{ $author }} +``` + +The templating engine will strip the content within the HTML comment, but will first evaluate any Go Template code if present within. So the above example will render `Emma Goldman`, as the `$author` variable got evaluated in the HTML comment. But the build would have failed if that code in the HTML comment had an error. + +## Hugo parameters + +Hugo provides the option of passing values to your template layer through your [site configuration][config] (i.e. for site-wide values) or through the metadata of each specific piece of content (i.e. the [front matter]). You can define any values of any type and use them however you want in your templates, as long as the values are supported by the [front matter format](/content-management/front-matter#front-matter-formats). + +## Use content (`Page`) parameters + +You can provide variables to be used by templates in individual content's [front matter]. + +An example of this is used in the Hugo docs. Most of the pages benefit from having the table of contents provided, but sometimes the table of contents doesn't make a lot of sense. We've defined a `notoc` variable in our front matter that will prevent a table of contents from rendering when specifically set to `true`. + +Here is the example front matter: + +{{< code-toggle file=content/example.md fm=true >}} +title: Example +notoc: true +{{< /code-toggle >}} + +Here is an example of corresponding code that could be used inside a `toc.html` [partial template][partials]: + +{{< code file=layouts/partials/toc.html >}} +{{ if not .Params.notoc }} +<aside> + <header> + <a href="#{{ .Title | urlize }}"> + <h3>{{ .Title }}</h3> + </a> + </header> + {{ .TableOfContents }} +</aside> +<a href="#" id="toc-toggle"></a> +{{ end }} +{{< /code >}} + +We want the *default* behavior to be for pages to include a TOC unless otherwise specified. This template checks to make sure that the `notoc:` field in this page's front matter is not `true`. + +## Use site configuration parameters + +You can arbitrarily define as many site-level parameters as you want in your [site's configuration file][config]. These parameters are globally available in your templates. + +For instance, you might declare the following: + +{{< code-toggle file=hugo >}} +params: + copyrighthtml: "Copyright © 2017 John Doe. All Rights Reserved." + twitteruser: "spf13" + sidebarrecentlimit: 5 +{{< /code >}} + +Within a footer layout, you might then declare a `<footer>` that is only rendered if the `copyrighthtml` parameter is provided. If it *is* provided, you will then need to declare the string is safe to use via the [`safeHTML`] function so that the HTML entity is not escaped again. This would let you easily update just your top-level configuration file each January 1st, instead of hunting through your templates. + +```go-html-template +{{ if .Site.Params.copyrighthtml }} + <footer> + <div class="text-center">{{ .Site.Params.CopyrightHTML | safeHTML }}</div> + </footer> +{{ end }} +``` + +An alternative way of writing the "`if`" and then referencing the same value is to use [`with`] instead. `with` rebinds the context (`.`) within its scope and skips the block if the variable is absent: + +{{< code file=layouts/partials/twitter.html >}} +{{ with .Site.Params.twitteruser }} + <div> + <a href="https://twitter.com/{{ . }}" rel="author"> + <img src="/images/twitter.png" width="48" height="48" title="Twitter: {{ . }}" alt="Twitter"></a> + </div> +{{ end }} +{{< /code >}} + +Finally, you can pull "magic constants" out of your layouts as well. The following uses the [`first`] function, as well as the [`.RelPermalink`][relpermalink] page variable and the [`.Site.Pages`][sitevars] site variable. + +```go-html-template +<nav> + <h1>Recent Posts</h1> + <ul> + {{- range first .Site.Params.SidebarRecentLimit .Site.Pages -}} + <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li> + {{- end -}} + </ul> +</nav> +``` + +## Example: show future events + +Given the following content structure and [front matter]: + +```text +content/ +└── events/ + ├── event-1.md + ├── event-2.md + └── event-3.md +``` + +{{< code-toggle file=content/events/event-1.md >}} +title = 'Event 1' +date = 2021-12-06T10:37:16-08:00 +draft = false +start_date = 2021-12-05T09:00:00-08:00 +end_date = 2021-12-05T11:00:00-08:00 +{{< /code-toggle >}} + +This [partial template][partials] renders future events: + +{{< code file=layouts/partials/future-events.html >}} +<h2>Future Events</h2> +<ul> + {{ range where site.RegularPages "Type" "events" }} + {{ if gt (.Params.start_date | time.AsTime) now }} + {{ $startDate := .Params.start_date | time.Format ":date_medium" }} + <li> + <a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a> - {{ $startDate }} + </li> + {{ end }} + {{ end }} +</ul> +{{< /code >}} + +If you restrict front matter to the TOML format, and omit quotation marks surrounding date fields, you can perform date comparisons without casting. + +{{< code file=layouts/partials/future-events.html >}} +<h2>Future Events</h2> +<ul> + {{ range where (where site.RegularPages "Type" "events") "Params.start_date" "gt" now }} + {{ $startDate := .Params.start_date | time.Format ":date_medium" }} + <li> + <a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a> - {{ $startDate }} + </li> + {{ end }} +</ul> +{{< /code >}} + +[`first`]: /functions/collections/first +[`index`]: /functions/collections/indexfunction +[`isset`]: /functions/collections/isset +[config]: /getting-started/configuration +[dotdoc]: https://golang.org/pkg/text/template/#hdr-Variables +[front matter]: /content-management/front-matter +[functions]: /functions +[identifier]: /getting-started/glossary/#identifier +[internal templates]: /templates/internal +[math]: /functions/math +[pagevars]: /variables/page +[param]: /methods/page/param +[partials]: /templates/partials +[relpermalink]: /variables/page +[`safehtml`]: /functions/safe/html +[sitevars]: /variables/site +[variables]: /variables +[`with`]: /functions/go-template/with diff --git a/docs/content/en/templates/lists/index.md b/docs/content/en/templates/lists/index.md new file mode 100644 index 000000000..c26174974 --- /dev/null +++ b/docs/content/en/templates/lists/index.md @@ -0,0 +1,252 @@ +--- +title: Lists of content in Hugo +linkTitle: List templates +description: Lists have a specific meaning and usage in Hugo when it comes to rendering your site homepage, section page, taxonomy list, or taxonomy terms list. +categories: [templates] +keywords: [lists,sections,rss,taxonomies,terms] +menu: + docs: + parent: templates + weight: 60 +weight: 60 +toc: true +aliases: [/templates/list/,/layout/indexes/] +--- + +## What is a list page template? + +{{< youtube 8b2YTSMdMps >}} + +A list page template is a template used to render multiple pieces of content in a single HTML page. The exception to this rule is the homepage, which is still a list but has its own [dedicated template][homepage]. + +Hugo uses the term *list* in its truest sense; i.e. a sequential arrangement of material, especially in alphabetical or numerical order. Hugo uses list templates on any output HTML page where content is traditionally listed: + +* [Home page](/templates/homepage) +* [Section pages](/templates/section-templates) +* [Taxonomy pages](/templates/taxonomy-templates) +* [Taxonomy term pages](/templates/taxonomy-templates) +* [RSS feeds](/templates/rss) +* [Sitemaps](/templates/sitemap-template) + +For template lookup order, see [Template Lookup](/templates/lookup-order/). + +The idea of a list page comes from the [hierarchical mental model of the web][mentalmodel] and is best demonstrated visually: + +[](site-hierarchy.svg) + +## List defaults + +### Default templates + +Since section lists and taxonomy lists (N.B., *not* [taxonomy terms lists][taxterms]) are both *lists* with regards to their templates, both have the same terminating default of `_default/list.html` or `themes/<THEME>/layouts/_default/list.html` in their lookup order. In addition, both [section lists][sectiontemps] and [taxonomy lists][taxlists] have their own default list templates in `_default`. + +See [Template Lookup Order](/templates/lookup-order/) for the complete reference. + +## Add content and front matter to list pages + +Since v0.18, [everything in Hugo is a `Page`][bepsays]. This means list pages and the homepage can have associated content files (i.e. `_index.md`) that contain page metadata (i.e., front matter) and content. + +This new model allows you to include list-specific front matter via `.Params` and also means that list templates (e.g., `layouts/_default/list.html`) have access to all [page variables][pagevars]. + +{{% note %}} +It is important to note that all `_index.md` content files will render according to a *list* template and not according to a [single page template](/templates/single-page-templates/). +{{% /note %}} + +### Example project directory + +The following is an example of a typical Hugo project directory's content: + +```txt +. +... +├── content +| ├── posts +| | ├── _index.md +| | ├── post-01.md +| | └── post-02.md +| └── quote +| | ├── quote-01.md +| | └── quote-02.md +... +``` + +Using the above example, let's assume you have the following in `content/posts/_index.md`: + +{{< code file=content/posts/_index.md >}} +--- +title: My Go Journey +date: 2017-03-23 +publishdate: 2017-03-24 +--- + +I decided to start learning Go in March 2017. + +Follow my journey through this new blog. +{{< /code >}} + +You can now access this `_index.md`'s' content in your list template: + +{{< code file=layouts/_default/list.html >}} +{{ define "main" }} + <main> + <article> + <header> + <h1>{{ .Title }}</h1> + </header> + <!-- "{{ .Content }}" pulls from the markdown content of the corresponding _index.md --> + {{ .Content }} + </article> + <ul> + <!-- Ranges through content/posts/*.md --> + {{ range .Pages }} + <li> + <a href="{{ .RelPermalink }}">{{ .Date.Format "2006-01-02" }} | {{ .LinkTitle }}</a> + </li> + {{ end }} + </ul> + </main> +{{ end }} +{{< /code >}} + +This above will output the following HTML: + +{{< code file=example.com/posts/index.html >}} +<!--top of your baseof code--> +<main> + <article> + <header> + <h1>My Go Journey</h1> + </header> + <p>I decided to start learning Go in March 2017.</p> + <p>Follow my journey through this new blog.</p> + </article> + <ul> + <li><a href="/posts/post-01/">Post 1</a></li> + <li><a href="/posts/post-02/">Post 2</a></li> + </ul> +</main> +<!--bottom of your baseof--> +{{< /code >}} + +### List pages without `_index.md` + +You do *not* have to create an `_index.md` file for every list page (i.e. section, taxonomy, taxonomy terms, etc) or the homepage. If Hugo does not find an `_index.md` within the respective content section when rendering a list template, the page will be created but with no `{{ .Content }}` and only the default values for `.Title` etc. + +Using this same `layouts/_default/list.html` template and applying it to the `quotes` section above will render the following output. Note that `quotes` does not have an `_index.md` file to pull from: + +{{< code file=example.com/quote/index.html >}} +<!--baseof--> +<main> + <article> + <header> + <!-- Hugo assumes that .Title is the name of the section since there is no _index.md content file from which to pull a "title:" field --> + <h1>Quotes</h1> + </header> + </article> + <ul> + <li><a href="https://example.org/quote/quotes-01/">Quote 1</a></li> + <li><a href="https://example.org/quote/quotes-02/">Quote 2</a></li> + </ul> +</main> +<!--baseof--> +{{< /code >}} + +{{% note %}} +The default behavior of Hugo is to pluralize list titles; hence the inflection of the `quote` section to "Quotes" when called with the `.Title` [page variable](/variables/page/). You can change this via the `pluralizeListTitles` directive in your [site configuration](/getting-started/configuration/). +{{% /note %}} + +## Example list templates + +### Section template + +This list template has been modified slightly from a template originally used in [spf13.com](https://spf13.com/). It makes use of [partial templates][partials] for the chrome of the rendered page rather than using a [base template][base]. The examples that follow also use the [content view templates][views] `li.html` or `summary.html`. + +{{< code file=layouts/section/posts.html >}} +{{ partial "header.html" . }} +{{ partial "subheader.html" . }} +<main> + <div> + <h1>{{ .Title }}</h1> + <ul> + <!-- Renders the li.html content view for each content/posts/*.md --> + {{ range .Pages }} + {{ .Render "li" }} + {{ end }} + </ul> + </div> +</main> +{{ partial "footer.html" . }} +{{< /code >}} + +### Taxonomy template + +{{< code file=layouts/_default/taxonomy.html >}} +{{ define "main" }} +<main> + <div> + <h1>{{ .Title }}</h1> + <!-- ranges through each of the content files associated with a particular taxonomy term and renders the summary.html content view --> + {{ range .Pages }} + {{ .Render "summary" }} + {{ end }} + </div> +</main> +{{ end }} +{{< /code >}} + +## Sort content + +By default, Hugo sorts page collections by: + +1. Page [weight] +2. Page [date] (descending) +3. Page [linkTitle], falling back to page [title] +4. Page file path if the page is backed by a file + +[date]: /methods/page/date +[weight]: /methods/page/weight +[linkTitle]: /methods/page/linktitle +[title]: /methods/page/title + +Change the sort order using any of the methods below. + +{{< list-pages-in-section path=/methods/pages filter=methods_pages_sort filterType=include titlePrefix=. omitElementIDs=true >}} + +## Group content + +Group your content by field, parameter, or date using any of the methods below. + +{{< list-pages-in-section path=/methods/pages filter=methods_pages_group filterType=include titlePrefix=. omitElementIDs=true >}} + +## Filtering and limiting lists + +Sometimes you only want to list a subset of the available content. A +common is to only display posts from [main sections] +on the blog's homepage. + +See the documentation on [`where`] and +[`first`] for further details. + +[base]: /templates/base/ +[bepsays]: https://bepsays.com/en/2016/12/19/hugo-018/ +[directorystructure]: /getting-started/directory-structure/ +[`Format` function]: /methods/time/format/ +[front matter]: /content-management/front-matter/ +[getpage]: /methods/page/getpage/ +[homepage]: /templates/homepage/ +[mentalmodel]: https://webstyleguide.com/wsg3/3-information-architecture/3-site-structure.html +[pagevars]: /variables/page/ +[partials]: /templates/partials/ +[RSS 2.0]: https://cyber.harvard.edu/rss/rss.html +[rss]: /templates/rss/ +[sections]: /content-management/sections/ +[sectiontemps]: /templates/section-templates/ +[sitevars]: /variables/site/ +[taxlists]: /templates/taxonomy-templates/#taxonomy-list-templates +[taxterms]: /templates/taxonomy-templates/#taxonomy-terms-templates +[taxvars]: /variables/taxonomy/ +[views]: /templates/views/ +[`where`]: /functions/collections/where +[`first`]: /functions/collections/first/ +[main sections]: /methods/site/mainsections +[`time.Format`]: /functions/time/format diff --git a/docs/content/en/templates/lists/site-hierarchy.svg b/docs/content/en/templates/lists/site-hierarchy.svg new file mode 100644 index 000000000..3c744871b --- /dev/null +++ b/docs/content/en/templates/lists/site-hierarchy.svg @@ -0,0 +1 @@ +<svg height="446" viewBox="0 0 1730 446" width="1730" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd" transform="translate(.538462 .461538)"><g transform="translate(2.996935 .388277)"><path d="m64.0494614 5.00059856 58.8489506 34.18916364v67.3333318l-58.8489506 33.404195-58.75248965-33.404195v-67.3333318z" fill="#ff4088"/><path d="m126.283637 35.8185172 1.230228 2.1375217v69.8133611l-1.253295 2.152899-60.9934622 34.621142h-2.4387878l-60.89490434-34.623239-1.25189712-2.1522v-69.8112641l1.22883034-2.1368227 60.89280732-35.43476985h2.4891154zm-116.37121203 6.0253228v61.994421l54.13913343 30.780872 54.2320996-30.782969v-61.990227l-54.2320996-31.5064271z" fill="#c9177e"/></g><path d="m60.4490685 78.3838073h-16.0432056v-32.93617h-27.9340521v32.93617h-16.04320555v-77.90259702h16.04320555v32.56189542h27.9340521v-32.56189542h16.0432056z" fill="#fff" fill-rule="nonzero" transform="translate(35.169824 33.865851)"/><g transform="translate(329.992265 24.431705)"><path d="m.21765.21067h263.332986v115.673517h-263.332986z" fill="#0083c0"/><path d="m263.550636 115.884187h-263.33298624v-115.6735171h263.33298624zm-260.79463916-113.13482905v110.59614105h258.25629216v-110.59614105z" fill="#000"/></g><g fill="#f2f2f2" fill-rule="nonzero" transform="translate(352.419436 42.870159)"><path d="m22.7288949.05688029h3.6312065v31.52968501h-3.6312065v-14.4804699h-18.90904412v14.4804699h-3.58685032v-31.52968501h3.58685032v13.99359541h18.90904412z"/><path d="m37.3865286 30.4794869c-1.5939528-.9445259-2.826533-2.2879966-3.6974799-4.0296294-.8709468-1.7418937-1.3064203-3.7788866-1.3064203-6.1112394 0-2.332092.4354735-4.3693457 1.3064203-6.1109785.8709469-1.7418937 2.1035271-3.0851036 3.6974799-4.0298904 1.5942137-.94478689 3.4394312-1.41704986 5.5356526-1.41704986 2.0959605 0 3.941178.47226297 5.5353917 1.41704986 1.5942137.9447868 2.826533 2.2879967 3.6974799 4.0298904.8709468 1.7416328 1.3064203 3.7788865 1.3064203 6.1109785 0 2.3323528-.4354735 4.3693457-1.3064203 6.1112394-.8709469 1.7416328-2.1032662 3.0851035-3.6974799 4.0296294-1.5942137.9447869-3.4394312 1.4170499-5.5353917 1.4170499-2.0962214 0-3.9414389-.472263-5.5356526-1.4170499zm10.6280042-3.741836c1.1809184-1.461406 1.7713776-3.594417 1.7713776-6.3990328 0-2.7159035-.6050707-4.8194306-1.8154728-6.3103205-1.2104022-1.4908898-2.8933283-2.2363347-5.0482564-2.2363347-2.1846728 0-3.8822104.7454449-5.0926125 2.2363347-1.2104022 1.4908899-1.8157337 3.594417-1.8157337 6.3103205 0 2.8046158.5977649 4.9376268 1.7935556 6.3990328 1.1955298 1.461406 2.9006339 2.1919786 5.1147906 2.1919786s3.9116942-.7305726 5.0923516-2.1919786z"/><path d="m91.1464927 17.5929699v13.9935954h-3.5868503v-13.8164316c0-2.0959605-.3616334-3.6163341-1.0849002-4.561121-.7232669-.9447869-1.8968795-1.4170498-3.520577-1.4170498-1.8893128 0-3.3655912.6348153-4.4283133 1.9041851-1.0627222 1.2693698-1.5942137 2.9966521-1.5942137 5.181064v12.7093533h-3.5868503v-13.8164316c0-2.0664767-.3692001-3.5795446-1.1070784-4.5389429-.7381392-.9593983-1.9190575-1.4392279-3.542755-1.4392279-1.8893128 0-3.3728969.6348153-4.4504915 1.9041851-1.0775945 1.2693698-1.6163917 2.9966521-1.6163917 5.181064v12.7093533h-3.5868504v-16.0305883c0-2.3026081-.1181962-4.3839571-.3543276-6.24378613h3.4099473l.3540668 3.89682183c.619943-1.4170498 1.5425518-2.5092558 2.7678263-3.27687883 1.2252746-.76762302 2.6496301-1.15143453 4.2733276-1.15143453 1.7713775 0 3.2179112.35432769 4.3398619 1.06272215 1.1216898.70865541 1.9482805 1.80086131 2.479772 3.27713971.6789106-1.3285983 1.6753594-2.3840148 2.9890854-3.16624924 1.313726-.78249538 2.7973101-1.17361262 4.4504915-1.17361262 4.930321 0 7.3952206 2.93742346 7.3952206 8.81227056z"/><path d="m116.609555 20.3386181h-16.340559c.029483 2.8340996.686477 4.9744163 1.970458 6.4212109 1.284242 1.4465336 3.151638 2.1698005 5.601926 2.1698005 2.597968 0 4.989289-.8709469 7.173962-2.6128406l1.19553 2.6128406c-.974271.915303-2.221463 1.6385698-3.741837 2.1698004-1.520373.5314916-3.077797.7971069-4.672011.7971069-3.483526 0-6.214302-1.0259326-8.1923275-3.0775369-1.9780252-2.0518652-2.9669073-4.8637868-2.9669073-8.4360256 0-2.2731244.4427791-4.2882 1.3283374-6.0447052.8858192-1.7565051 2.1257054-3.121893 3.7199194-4.0961637 1.594213-.97427072 3.409686-1.46140606 5.44694-1.46140606 2.952035 0 5.269515.96696496 6.952441 2.90063396 1.682665 1.933669 2.524128 4.5979105 2.524128 7.9929856zm-13.971417-7.0852492c-1.166046 1.1216898-1.911491 2.701292-2.236335 4.7382848h12.974969c-.177164-2.0959604-.789801-3.6901741-1.837651-4.782641-1.048111-1.092206-2.50195-1.6385699-4.36204-1.6385699-1.859829 0-3.372897.5609754-4.538943 1.6829261z"/><path d="m138.352699 10.2421054c1.505502.9742707 2.671548 2.3396586 3.498399 4.0961637.826591 1.7565052 1.239886 3.7861923 1.239886 6.0890613 0 2.3026082-.413295 4.3174229-1.239886 6.0444443-.826851 1.7272822-1.985592 3.0631863-3.476221 4.0077122-1.49089.9447869-3.225478 1.4170499-5.203503 1.4170499-1.741632 0-3.262006-.3838115-4.561121-1.1511736-1.298853-.767623-2.287996-1.8600899-2.966907-3.2771398v13.683624h-3.587111v-25.5958704c0-2.3026081-.117936-4.3839571-.354067-6.24378613h3.409686l.354328 4.29550573c.619943-1.5352461 1.60152-2.7234701 2.944729-3.5649332 1.343471-.841463 2.930118-1.26206406 4.760463-1.26206406 1.948542 0 3.675563.48713534 5.181325 1.46140606zm-.774929 16.4733674c1.19553-1.4760175 1.793295-3.5722389 1.793295-6.2881424 0-2.7161643-.60507-4.8343029-1.815473-6.3546766-1.210402-1.5203736-2.893328-2.2806909-5.048256-2.2806909-2.214418 0-3.911694.7381392-5.092613 2.2141566-1.180918 1.4760175-1.771377 3.5868504-1.771377 6.3324986s.590459 4.8637867 1.771377 6.3546766c1.180919 1.4908898 2.878195 2.2363348 5.092613 2.2363348 2.184412 0 3.874644-.7381392 5.070434-2.2141567z"/><path d="m168.243032 9.31219087v22.27437443h-3.540668v-4.0296295c-.649688 1.387566-1.633352 2.4575939-2.945773 3.2103445-1.313987.7530116-2.841666 1.1292565-4.58356 1.1292565-1.978025 0-3.712352-.472263-5.203242-1.4170499-1.49089-.9445259-2.642325-2.28043-3.454043-4.0077122-.811979-1.7270214-1.217969-3.7418361-1.217969-6.0444443 0-2.302869.413296-4.3325561 1.239886-6.0890613.826852-1.7565051 1.985592-3.121893 3.476221-4.0961637 1.49089-.97427072 3.210606-1.46140606 5.159147-1.46140606 1.741894 0 3.262267.38381151 4.560077 1.15143453 1.299376.76762303 2.288258 1.84521753 2.969256 3.23252263v-3.85246563zm-5.312307 17.38110383c1.179353-1.4908899 1.771639-3.6090284 1.771639-6.3546766s-.592286-4.8564811-1.771639-6.3324986c-1.181962-1.4760174-2.864627-2.2141566-5.0493-2.2141566-2.184412 0-3.889516.7603173-5.114529 2.2806909-1.225275 1.5203737-1.837912 3.6385123-1.837912 6.3546766 0 2.7159035.605331 4.8121249 1.815734 6.2881424 1.210402 1.4760175 2.922551 2.2141567 5.136707 2.2141567 2.184673 0 3.867338-.745445 5.0493-2.2363348z"/><path d="m195.034171 9.31219087v22.09721053c0 3.3066236-.847986 5.8085737-2.543958 7.5061112-1.698581 1.6975375-4.200792 2.5463063-7.506633 2.5463063-3.394553 0-6.319453-.7676231-8.76948-2.3028691l.620987-2.9225511c1.416789.7971068 2.752693 1.3726936 4.007712 1.7270213s2.63528.5314915 4.140781.5314915c2.155189 0 3.778104-.568281 4.871353-1.7051041 1.090641-1.1365622 1.63857-2.826533 1.63857-5.0704345v-5.2695154c-.680998 1.4170498-1.675098 2.5165615-2.990129 3.2990569-1.315031.7822345-2.870106 1.1733517-4.670446 1.1733517-1.949063 0-3.684173-.4573906-5.205329-1.3726936-1.518548-.9150422-2.692682-2.2141567-3.519795-3.8968219-.827112-1.682926-1.239364-3.616595-1.239364-5.8012679 0-2.1846728.412252-4.1183418 1.239364-5.801007.827113-1.682926 2.001247-2.9817797 3.519795-3.8970827 1.521156-.91504214 3.256266-1.37269366 5.205329-1.37269366 1.769029 0 3.313668.38381151 4.62609 1.15143453 1.31503.76762303 2.309131 1.84521753 2.990129 3.23252263v-3.85246563zm-5.424501 16.45118933c1.226318-1.4319222 1.839477-3.4023808 1.839477-5.9118975 0-2.5092558-.613159-4.4799752-1.839477-5.9116365-1.223709-1.4319222-2.914463-2.1478833-5.069652-2.1478833-2.18389 0-3.903345.7159611-5.158364 2.1478833-1.255019 1.4316613-1.881224 3.4023807-1.881224 5.9116365 0 2.5095167.626205 4.4799753 1.881224 5.9118975s2.974474 2.1476224 5.158364 2.1476224c2.155189 0 3.845943-.7157002 5.069652-2.1476224z"/><path d="m220.585946 20.3386181h-16.338733c.028701 2.8340996.686216 4.9744163 1.969936 6.4212109 1.283721 1.4465336 3.151899 2.1698005 5.601926 2.1698005 2.598751 0 4.988767-.8709469 7.172657-2.6128406l1.195008 2.6128406c-.973227.915303-2.220419 1.6385698-3.741575 2.1698004-1.518547.5314916-3.076232.7971069-4.670446.7971069-3.483266 0-6.215085-1.0259326-8.192849-3.0775369-1.977765-2.0518652-2.966647-4.8637868-2.966647-8.4360256 0-2.2731244.443562-4.2882 1.328077-6.0447052.887124-1.7565051 2.126488-3.121893 3.720701-4.0961637 1.594214-.97427072 3.410209-1.46140606 5.445375-1.46140606 2.953601 0 5.270559.96696496 6.953485 2.90063396s2.523085 4.5979105 2.523085 7.9929856zm-13.969591-7.0852492c-1.166307 1.1216898-1.912535 2.701292-2.236074 4.7382848h12.972881c-.177424-2.0959604-.787974-3.6901741-1.836868-4.782641-1.048893-1.092206-2.502211-1.6385699-4.362562-1.6385699-1.86035 0-3.37107.5609754-4.537377 1.6829261z"/></g><g fill="#f2f2f2" fill-rule="nonzero" transform="translate(347.017193 95.746626)"><path d="m.13103057 17.5444886 1.30960428-16.95274668h3.09535177l-1.16678937 14.42893518h7.92875255l-.1903731 2.5238115z"/><path d="m13.2028032 17.5444886.9524268-12.02408921h2.9762458l-.9524267 12.02408921zm1.1904984-17.47658839h3.3095741l-.2142224 2.92868762h-3.3095741z"/><path d="m18.7267099 16.2111754 1.0238341-2.0715176c1.3493063.936574 2.7858728 1.404861 4.3096994 1.404861 1.5396794 0 2.3095892-.4444378 2.3095892-1.3334535 0-.412592-.202438-.7261395-.6071738-.9405021-.4047358-.2142224-1.0516115-.4563624-1.940487-.7261395-.8413173-.2380716-1.5398197-.4762835-2.0953669-.7143551-.5555471-.2380716-1.0277622-.5833245-1.4166453-1.0357588-.388883-.452294-.5833245-1.04361503-.5833245-1.77382287 0-1.14279984.4602905-2.06352109 1.3808714-2.76188318.9207213-.69850237 2.1429251-1.04768342 3.6667517-1.04768342.8890158 0 1.7461858.13495869 2.5715101.40473576.8254645.26991737 1.5159704.64294766 2.0715176 1.11909088l-.999985 2.0238191c-1.1904983-.90472823-2.4206986-1.35716248-3.6906009-1.35716248-.7460606 0-1.3174605.11910595-1.71434.35717755-.3968796.23807161-.5952492.58725266-.5952492 1.04768343 0 .42858501.202438.74998869.6071738.96421105.4047358.21436265 1.0594677.45636238 1.9643363.72627978.8730227.2539243 1.5793813.4960643 2.1190758.7261394.5396944.2302154 1.0040533.5754683 1.3929363 1.0357588.388883.4604308.5833246 1.0556799.5833246 1.7857475 0 1.1587929-.4602905 2.0635211-1.3810118 2.714325-.9207212.6508038-2.1587778.9762759-3.7143099.9762759-1.9525519 0-3.7064536-.5079889-5.262126-1.5238266z"/><path d="m35.3699775 13.1396729c-.1111094 1.4127172.4841397 2.1190758 1.7857475 2.1190758.3651741 0 .7777661-.0555547 1.2381968-.1666642l-.1905134 2.3334385c-.5238417.1903731-1.1746456.2856298-1.9524116.2856298-1.2540496 0-2.2143325-.3294002-2.8809891-.9880603-.6667969-.6588004-1.0001253-1.6151552-1.0001253-2.8690645 0-.2382119.0079966-.4207288.0238493-.547691l.428585-5.54775586h-2.3095892l.1905134-2.23818175h2.28574l.2380716-2.92854732 3.0476532-1.00012522-.309479 3.92867254h3.2143174l-.1903731 2.23818175h-3.1906085z"/><path d="m39.5605709 16.2111754 1.0238342-2.0715176c1.349166.936574 2.7857324 1.404861 4.309559 1.404861 1.5398197 0 2.3095893-.4444378 2.3095893-1.3334535 0-.412592-.2022978-.7261395-.6071738-.9405021-.4047358-.2142224-1.0516116-.4563624-1.9404871-.7261395-.8413172-.2380716-1.5396793-.4762835-2.0952265-.7143551s-1.0279026-.5833245-1.4167856-1.0357588c-.388883-.452294-.5833246-1.04361503-.5833246-1.77382287 0-1.14279984.4602905-2.06352109 1.3810118-2.76188318.9207212-.69850237 2.142925-1.04768342 3.6667517-1.04768342.8888754 0 1.7460455.13495869 2.57151.40473576.8253243.26991737 1.5158301.64294766 2.0715176 1.11909088l-1.0001252 2.0238191c-1.1904983-.90472823-2.4206986-1.35716248-3.6904606-1.35716248-.7460606 0-1.3176008.11910595-1.7143401.35717755-.3968795.23807161-.5952492.58725266-.5952492 1.04768343 0 .42858501.2022978.74998869.6071738.96421105.4047358.21436265 1.0594678.45636238 1.964196.72627978.8731631.2539243 1.5795217.4960643 2.1192161.7261394.5396945.2302154 1.003913.5754683 1.3927961 1.0357588.388883.4604308.5833245 1.0556799.5833245 1.7857475 0 1.1587929-.4602905 2.0635211-1.3808714 2.714325-.9207213.6508038-2.1587778.9762759-3.7144502.9762759-1.9524117 0-3.7064537-.5079889-5.2619858-1.5238266z"/><path d="m58.3943218 15.592077.7380641-1.4999774c.8413173.7142148 1.6984873 1.2222038 2.57151 1.5238266.8730228.3016229 1.8890008.4524343 3.0476533.4524343 1.365159 0 2.4167706-.2659893 3.1548346-.7976872.7382044-.5318382 1.1071663-1.2818269 1.1071663-2.2501064 0-.5713999-.1784485-1.0357588-.5356261-1.392796-.3571775-.3571776-.8254645-.6390196-1.4048609-.8452454-.5793965-.2063662-1.3532344-.4207288-2.3215139-.6429477-1.3016077-.2857701-2.3730001-.59524916-3.2143174-.92857747s-1.5238266-.81353993-2.0476684-1.44049456c-.5238417-.62695464-.7857625-1.44849108-.7857625-2.46432874 0-.96827945.2540646-1.82152136.7619133-2.55958543.507989-.73820436 1.2262722-1.31353239 2.1548497-1.72626467.9285774-.41273227 2.0120347-.61909841 3.2500913-.61909841 1.1746456 0 2.2698872.18265718 3.2857249.54769096 1.0159779.36503378 1.8731479.896872 2.57151 1.59523409l-.7619133 1.50011768c-.7936188-.68264964-1.5991622-1.18264211-2.4166302-1.50011768-.8174681-.31747557-1.710412-.47614322-2.6786914-.47614322-1.3174605 0-2.3492912.28170171-3.0953518.8452454s-1.1190909 1.33738164-1.1190909 2.32151383c0 .85717002.3254721 1.49997739.976276 1.9285624s1.6507888.8016153 3.0000951 1.11909087c1.4602754.34918105 2.6071436.67058473 3.4404644.96435135.833461.29362633 1.527895.73806407 2.0834422 1.3333132.5555472.5952492.8333208 1.3849399.8333208 2.3690721 0 .9524267-.2539244 1.7896756-.7619133 2.5120272-.507989.7222113-1.2341285 1.2816866-2.1785587 1.6785662-.9445705.3968795-2.0517367.5952491-3.3214987.5952491-2.6509141 0-4.7619934-.7143551-6.3335185-2.142925z"/><path d="m83.9663269 11.4967403h-8.7859225c.0158527 1.5238266.3691021 2.674623 1.059608 3.4525293.6905059.7777661 1.6944189 1.1666491 3.0118794 1.1666491 1.3968645 0 2.6826195-.468287 3.8572651-1.404861l.6429477 1.404861c-.5238417.4921362-1.1945668.8810193-2.0120348 1.1666491-.817468.2857701-1.6547169.428585-2.5118869.428585-1.873148 0-3.3414199-.5516191-4.4049561-1.6547169-1.0635361-1.1032382-1.5952341-2.6151402-1.5952341-4.5358464 0-1.2222038.2380716-2.30566106.7143551-3.25009127.4761433-.94443021 1.1427999-1.67856617 1.9999699-2.20240788s1.833446-.78576257 2.9286876-.78576257c1.5872376 0 2.8334309.5199136 3.7381591 1.55960051.9047283 1.03968691 1.3571625 2.47218496 1.3571625 4.29763441zm-7.5120921-3.80956661c-.6269547.60310539-1.0277623 1.45241918-1.202423 2.54766081h6.9763258c-.0951164-1.1269471-.4245166-1.98411712-.9880603-2.57151006-.5635437-.58725265-1.3452378-.88101927-2.345363-.88101927-.999985 0-1.8135249.30162284-2.4404795.90486852z"/><path d="m88.8830598 16.9492395c-.8650263-.5078487-1.5316829-1.2261319-1.9999699-2.1548497-.468287-.9285775-.7024305-2.0118945-.7024305-3.249951 0-1.2381968.2380716-2.32951036.7143551-3.27394057.4761433-.94443021 1.1547245-1.67856617 2.0357438-2.20240788.8808789-.52384171 1.9087815-.78576257 3.0834271-.78576257.8094715 0 1.591306.1388868 2.3452228.41666039.7540571.27777359 1.3770836.66272851 1.8690796 1.15486475l-.6428074 1.42856993c-.6032457-.4762835-1.1865702-.82546455-1.7501139-1.04768342s-1.1388717-.33332831-1.7262647-.33332831c-1.2222038 0-2.1824867.40880417-2.8809891 1.2262722-.6983621.81746804-1.0475431 1.95633978-1.0475431 3.41675548 0 1.4444227.3452529 2.5674416 1.0356185 3.3690569.6905059.8016153 1.6548572 1.202423 2.8929137 1.202423.587393 0 1.162721-.1111094 1.7262647-.3333283s1.1468682-.5713999 1.7501139-1.0476834l.6428074 1.4285699c-.507989.4762835-1.1468683.8532419-1.9166378 1.1310155-.7699098.2777736-1.567597.4166604-2.3929213.4166604-1.1587928 0-2.1707024-.2539244-3.0358689-.7619133z"/><path d="m101.276251 7.09192453v6.54774077c0 .8888755.182517 1.511902.547691 1.8690796.365034.3571776.880879.5357663 1.547536.5357663.444437 0 .873023-.0714074 1.285755-.2143626v1.6429326c-.491996.1588079-1.047543.2380716-1.666642.2380716-1.14294 0-2.035743-.3214037-2.678691-.9642111-.6428075-.6429476-.9642112-1.591306-.9642112-2.8453555v-6.80966167h-2.3334385v-1.52382664h2.3334385v-3.07150253l1.9285622-.69050586v3.76200839h3.42868v1.52382664z"/><path d="m107.038229 17.5444886v-11.97639071h1.928703v11.97639071zm-.190373-17.04800338h2.357148v2.19062355h-2.357148z"/><path d="m114.681352 16.9492395c-.85717-.5078487-1.519898-1.2302003-1.988185-2.166634-.468287-.936574-.702431-2.0318157-.702431-3.2858652 0-1.2539093.234144-2.3492912.702431-3.2857249.468287-.93657398 1.131015-1.65878532 1.988185-2.1667743.85717-.50798897 1.849159-.76191332 2.976246-.76191332 1.126947 0 2.119076.25392435 2.976246.76191332.85717.50798898 1.519898 1.23020032 1.988185 2.1667743.468147.9364337.702291 2.0318156.702291 3.2857249 0 1.2540495-.234144 2.3492912-.702291 3.2858652-.468287.9364337-1.131015 1.6587853-1.988185 2.166634-.85717.5079889-1.849299.7619133-2.976246.7619133-1.127087 0-2.119076-.2539244-2.976246-.7619133zm5.71442-2.0118945c.634951-.7857626.952287-1.9326308.952287-3.4406047 0-1.4602754-.325332-2.59129092-.976136-3.39290622-.650804-.80161531-1.555532-1.20242296-2.714325-1.20242296-1.174646 0-2.08737.40080765-2.738174 1.20242296-.650804.8016153-.976276 1.93263082-.976276 3.39290622 0 1.5079739.321544 2.6548421.964351 3.4406047.642808.7857626 1.559601 1.1785737 2.750099 1.1785737s2.103223-.3928111 2.738174-1.1785737z"/><path d="m136.610315 10.0204719v7.5240167h-1.928563v-7.42876c0-1.11109441-.222219-1.92463434-.666656-2.44047953-.444438-.5158452-1.142941-.77383795-2.095367-.77383795-1.111095 0-1.99997.34132482-2.666627 1.02383418-.666656.68250935-1.000125 1.6032306-1.000125 2.7620235v6.8572198h-1.928562v-8.61925838c0-1.23805653-.063411-2.35714741-.190514-3.35713233h1.833446l.190514 2.14292505c.365033-.77790635.912724-1.37708362 1.642792-1.79767212.730208-.42072879 1.563529-.63102304 2.500102-.63102304 2.873133 0 4.30956 1.57938136 4.30956 4.73814412z"/><path d="m139.515153 16.1634769.642948-1.4285699c.650803.5079889 1.309464.8730227 1.97626 1.0952416.666517.2222189 1.412858.3333283 2.237761.3333283.904869 0 1.590885-.1547395 2.059453-.4642186s.702851-.7579852.702851-1.3452379c0-.4762835-.158527-.85717-.475582-1.1429401-.318457-.2857701-.841738-.507989-1.572647-.6666566l-2.022977-.4762835c-1.000406-.2222189-1.774104-.6189581-2.321795-1.1904983-.547691-.5713999-.821396-1.2539093-.821396-2.04766838 0-1.04754313.420588-1.90078504 1.261906-2.55958543.841317-.65866011 1.952832-.98806031 3.333283-.98806031.841738 0 1.635778.13495869 2.380716.40473577.746341.26991736 1.373436.65880039 1.881285 1.16678937l-.642527 1.40472069c-1.127929-.93657399-2.333018-1.40472069-3.619474-1.40472069-.85717 0-1.519338.16259575-1.987905.48806784-.468427.32533179-.702571.78169416-.702571 1.3690871 0 .49199596.146883.88101927.44051 1.16664909.294328.28577005.765701.50798895 1.416645.66665665l2.02438.4999924c1.111095.2540647 1.935998.6468758 2.476113 1.178714.540116.531698.809472 1.2261319.809472 2.083302 0 1.0318306-.420869 1.8571549-1.262607 2.4762533-.840336.6190984-1.983697.9285775-3.42868.9285775-2.015402 0-3.610776-.5158452-4.785422-1.5476759z"/><path d="m171.469076 17.5444886-1.857435-4.3572575h-8.857891l-1.881285 4.3572575h-2.022977l7.452188-16.95274668h1.71434l7.452189 16.95274668zm-10.025101-5.9763409h7.476038l-3.737318-8.71437478z"/><path d="m178.348883 15.0920845v1.7381893c0 .6666566-.110829 1.2777585-.332487 1.8333057-.22306.5555472-.596231 1.0952416-1.119511 1.6190833l-.904869-.6905058c.618678-.7142148.967999-1.3968645 1.047964-2.0476684h-1.143361v-2.4524041z"/><path d="m200.064324 10.2943173c.540116.7063586.809472 1.5834498.809472 2.6309929 0 1.4762685-.492417 2.6151402-1.475848 3.4167555-.984833.8016153-2.373701 1.2024229-4.166603 1.2024229h-7.048155v-16.95274668h6.809662c1.729772 0 3.07515.38495492 4.036134 1.15486475.959582.76976954 1.439373 1.86108306 1.439373 3.27380026 0 .90486851-.232881 1.68656268-.701449 2.34536307-.468567.65866011-1.12372 1.14686824-1.964055 1.46420352.967998.26991737 1.721354.75798521 2.261469 1.46434378zm-9.95215-2.1785586h4.570638c1.269622 0 2.230606-.25406463 2.88155-.76191332.650944-.50798897.976416-1.25404956.976416-2.23818175 0-1.93655891-1.286456-2.90483837-3.857966-2.90483837h-4.570638zm7.892698 7.0596579c.627095-.4999925.939941-1.2658339.939941-2.2976646 0-2.0793738-1.293471-3.11906071-3.880413-3.11906071h-4.952226v6.16671401h4.952226c1.332752 0 2.313377-.2499962 2.940472-.7499887z"/><path d="m206.064515 15.0920845v1.7381893c0 .6666566-.110829 1.2777585-.33389 1.8333057-.221658.5555472-.594828 1.0952416-1.118109 1.6190833l-.904868-.6905058c.618677-.7142148.967999-1.3968645 1.046561-2.0476684h-1.141958v-2.4524041z"/><path d="m218.957137 16.6873186c-1.182642-.6983621-2.090316-1.7024154-2.725828-3.0118794-.635513-1.3096043-.952567-2.853352-.952567-4.63110303 0-1.77789127.317054-3.31364253.952567-4.60725378.635512-1.29361125 1.543186-2.28966807 2.725828-2.98817045 1.182642-.69836209 2.575719-1.04768342 4.17923-1.04768342 1.174225 0 2.250247.17858878 3.226663.53576634.975013.35717755 1.82096.89294389 2.535035 1.60715871l-.737924 1.50011768c-.809471-.69850238-1.60772-1.19849484-2.393342-1.50011768s-1.654016-.45229397-2.606583-.45229397c-1.857435 0-3.29821.60310539-4.322325 1.80945645-1.022712 1.20635107-1.534769 2.92069111-1.534769 5.14302012 0 2.23818173.507848 3.96430613 1.523546 5.17865373 1.015697 1.2143476 2.460681 1.8215213 4.333548 1.8215213.952567 0 1.820961-.1508114 2.606583-.4524342.785622-.3016229 1.583871-.8016153 2.393342-1.4999774l.737924 1.4999774c-.714075.7143551-1.560022 1.2499811-2.535035 1.6071587-.976416.3571776-2.052438.5357663-3.226663.5357663-1.603511 0-2.996588-.349181-4.17923-1.0476834z"/></g><g transform="translate(.267895 224.553185)"><path d="m.21765.193821h263.332986v106.422426h-263.332986z" fill="#c9177e"/><path d="m263.550636 106.616248h-263.33298624v-106.42242661h263.33298624zm-260.79463916-103.88400537v101.34558437h258.25629216v-101.34558437z" fill="#000"/></g><g transform="translate(.968438 362.150954)"><path d="m.058374.14766h70.625927v81.076506h-70.625927z" fill="#00a88a"/><path d="m70.6843004 81.224166h-70.62592672v-81.07650576h70.62592672zm-68.08746821-78.53804774v75.99958964h65.54828551v-75.99958964z" fill="#000"/></g><g transform="translate(97.321977 362.150954)"><path d="m.058374.14766h70.625927v81.076506h-70.625927z" fill="#00a88a"/><path d="m70.6843004 81.224166h-70.62592672v-81.07650576h70.62592672zm-68.08746821-78.53804774v75.99958964h65.54828551v-75.99958964z" fill="#000"/></g><g transform="translate(193.675515 362.150954)"><path d="m.058374.14766h70.625927v81.076506h-70.625927z" fill="#00a88a"/><path d="m70.6843004 81.224166h-70.62592672v-81.07650576h70.62592672zm-68.08746821-78.53804774v75.99958964h65.54828551v-75.99958964z" fill="#000"/></g><g transform="translate(329.309669 362.924954)"><path d="m.058374.14766h70.625927v81.076506h-70.625927z" fill="#00a88a"/><path d="m70.6843004 81.224166h-70.62592672v-81.07650576h70.62592672zm-68.08746821-78.53804774v75.99958964h65.54828551v-75.99958964z" fill="#000"/></g><g transform="translate(425.663669 362.924954)"><path d="m.058374.14766h70.625927v81.076506h-70.625927z" fill="#00a88a"/><path d="m70.6843004 81.224166h-70.62592672v-81.07650576h70.62592672zm-68.08746821-78.53804774v75.99958964h65.54828551v-75.99958964z" fill="#000"/></g><g transform="translate(523.997669 362.924954)"><path d="m.058374.14766h70.625927v81.076506h-70.625927z" fill="#00a88a"/><path d="m70.6843004 81.224166h-70.62592672v-81.07650576h70.62592672zm-68.08746821-78.53804774v75.99958964h65.54828551v-75.99958964z" fill="#000"/></g><g transform="translate(660.171823 361.893877)"><path d="m.058374.14766h70.625927v81.076506h-70.625927z" fill="#00a88a"/><path d="m70.6843004 81.224166h-70.62592672v-81.07650576h70.62592672zm-68.08746821-78.53804774v75.99958964h65.54828551v-75.99958964z" fill="#000"/></g><g transform="translate(756.527208 361.893877)"><path d="m.058374.14766h70.625927v81.076506h-70.625927z" fill="#00a88a"/><path d="m70.6843004 81.224166h-70.62592672v-81.07650576h70.62592672zm-68.08746821-78.53804774v75.99958964h65.54828551v-75.99958964z" fill="#000"/></g><g transform="translate(852.877977 361.893877)"><path d="m.058374.14766h70.625927v81.076506h-70.625927z" fill="#00a88a"/><path d="m70.6843004 81.224166h-70.62592672v-81.07650576h70.62592672zm-68.08746821-78.53804774v75.99958964h65.54828551v-75.99958964z" fill="#000"/></g><g fill="#f2f2f2" fill-rule="nonzero" transform="translate(26.69736 242.51167)"><path d="m.00427353 31.0947909 1.49915514-3.0461739c1.70855821 1.4504369 3.44902547 2.4820676 5.22225648 3.0946072 1.7729461.6125397 3.83592255.9188095 6.18921435.9188095 2.772098 0 4.9077245-.5401745 6.4068797-1.6199537 1.4988702-1.080064 2.2484478-2.6031509 2.2484478-4.5695456 0-1.1604065-.3626805-2.1034326-1.0880414-2.8285086-.7253608-.7253609-1.6763642-1.2977293-2.8527252-1.7165355-1.1766459-.419091-2.7481662-.8544215-4.7145609-1.3057065-2.6433221-.5803457-4.8194048-1.2088399-6.52767811-1.8857674-1.70855822-.6769275-3.0948921-1.6521476-4.15843184-2.9253753-1.06382464-1.2732277-1.59573696-2.9416147-1.59573696-5.0045912 0-1.96639471.51567289-3.69916961 1.54730359-5.19803984 1.0316307-1.49915513 2.49004483-2.66753887 4.37609709-3.505721 1.88576735-.83818214 4.08578183-1.25727321 6.60004333-1.25727321 2.3854857 0 4.6097168.37094261 6.6729782 1.11225801 2.0629765.74131541 3.8037287 1.82137947 5.2222565 3.23962239l-1.5473036 3.04645873c-1.6119764-1.38633388-3.2478846-2.40172515-4.9080094-3.04645873-1.6601249-.64473357-3.4735271-.96695791-5.4399217-.96695791-2.6755162 0-4.7706866.57208353-6.28579626 1.71653548-1.51510965 1.14445195-2.27266448 2.71597223-2.27266448 4.71456088 0 1.7407521.6606881 3.0461738 1.98234919 3.9165499 1.32166109.870376 3.35272854 1.6279309 6.09263255 2.2726645 2.9658314.7091214 5.2949065 1.3618322 6.9872253 1.9584174 1.6923188.5963002 3.1025845 1.4988702 4.230797 2.70771 1.1284974 1.2088399 1.6926037 2.8125541 1.6926037 4.8111427 0 1.9342007-.5159578 3.6344968-1.5473036 5.101458-1.0316307 1.4666763-2.5065691 2.602866-4.4245304 3.4088542s-4.1664091 1.2088399-6.7453434 1.2088399c-5.38322623 0-9.67071874-1.4507218-12.86219267-4.3518804z"/><path d="m51.9362381 22.7779272h-17.8425672c.0324789 3.0946072.7495776 5.4316596 2.151866 7.011442 1.4022884 1.5794975 3.4413331 2.3692463 6.1168493 2.3692463 2.8367707 0 5.4478989-.9510034 7.8330998-2.8530102l1.3057065 2.8530102c-1.0638246.9994368-2.4256569 1.7891855-4.0857817 2.3692463-1.6604098.5803457-3.3607058.8703761-5.101458.8703761-3.8037287 0-6.7855146-1.1202353-8.9453578-3.3604209-2.1598433-2.2404705-3.2399073-5.310861-3.2399073-9.2114564 0-2.4820676.4837638-4.6823669 1.4507217-6.6003282s2.3210979-3.4088543 4.06185-4.4726789c1.7404673-1.0638247 3.7231014-1.595737 5.9473325-1.595737 3.2236679 0 5.7541688 1.0558474 7.5915028 3.1672572 1.8376189 2.1114099 2.7561434 5.0205458 2.7561434 8.7276926zm-15.2553707-7.736518c-1.2735126 1.2247944-2.0874781 2.949592-2.4418964 5.1738231h14.1676144c-.1934486-2.288619-.8623989-4.0293711-2.0068508-5.2222565-1.1441671-1.1926004-2.7319268-1.7891855-4.7627093-1.7891855-2.0307826 0-3.6829302.6125397-4.9561579 1.8376189z"/><path d="m61.9214888 33.8509343c-1.7569916-1.0313458-3.1108466-2.4900448-4.06185-4.3760971-.9510034-1.8857673-1.4265051-4.0857818-1.4265051-6.6000433 0-2.5145464.4837639-4.7308002 1.4507218-6.6487615s2.3453145-3.4088543 4.1342152-4.4726789c1.7891855-1.0638247 3.8763787-1.595737 6.2618644-1.595737 1.6441703 0 3.2316451.2820531 4.7627093.8461594 1.5313491.5641063 2.7965995 1.3458778 3.7960363 2.3453145l-1.3057066 2.9011587c-1.2247943-.9672429-2.4097024-1.6763643-3.5538694-2.1276493-1.144452-.451285-2.3131206-.6769276-3.505721-.6769276-2.4820676 0-4.4325078.8302049-5.8507507 2.4903298-1.4185278 1.6601248-2.1276493 3.9729605-2.1276493 6.9387919 0 2.9333526.7011442 5.2139943 2.1034326 6.8419253 1.4022884 1.6279309 3.3604209 2.4418963 5.8749674 2.4418963 1.1926004 0 2.361269-.2256425 3.505721-.6769275 1.144167-.451285 2.3290751-1.1604065 3.5538694-2.1276493l1.3057066 2.9011586c-1.0316307.9672429-2.3290751 1.7327749-3.8926181 2.2968812-1.5635431.5641063-3.1832118.8461594-4.8595761.8461594-2.3532918 0-4.408291-.5156729-6.1649977-1.5473036z"/><path d="m87.0894602 13.8325694v13.2972382c0 1.80514.3709426 3.0703905 1.112258 3.7957514s1.7891855 1.0880413 3.1430406 1.0880413c.90257 0 1.7729461-.1450152 2.6111282-.4353305v3.3364892c-.9994368.3225092-2.1276493.4834789-3.3849225.4834789-2.3208129 0-4.1342151-.6527108-5.4396368-1.9581325-1.3057066-1.3057066-1.9584174-3.2316451-1.9584174-5.7783855v-13.8291505h-4.7387775v-3.0946072h4.7387775v-6.23764778l3.9165499-1.4022884v7.63993618h6.9630086v3.0946072z"/><path d="m98.7912464 35.0597742v-24.321812h3.9165496v24.321812zm-.3868972-34.62130978h4.7869258v4.44874713h-4.7869258z"/><path d="m114.312716 33.8509343c-1.740752-1.0313458-3.08663-2.498307-4.037634-4.4000289-.950718-1.9020067-1.42622-4.1262378-1.42622-6.6729782 0-2.5464555.475502-4.7709715 1.42622-6.6726933.951004-1.9020068 2.296882-3.3686831 4.037634-4.4003138s3.75558-1.5473036 6.044199-1.5473036c2.288904 0 4.303447.5156729 6.044199 1.5473036s3.08663 2.498307 4.037633 4.4003138c.951004 1.9017218 1.426505 4.1262378 1.426505 6.6726933 0 2.5467404-.475501 4.7709715-1.426505 6.6729782-.951003 1.9017219-2.296881 3.3686831-4.037633 4.4000289-1.740752 1.0316307-3.755295 1.5473036-6.044199 1.5473036-2.288619 0-4.303447-.5156729-6.044199-1.5473036zm11.604919-4.0857818c1.289467-1.5957369 1.934201-3.924812 1.934201-6.9872253 0-2.9655465-.660973-5.2624277-1.982634-6.8903586s-3.158995-2.4418964-5.512287-2.4418964c-2.385486 0-4.239059.8139655-5.56072 2.4418964s-1.98235 3.9248121-1.98235 6.8903586c0 3.0624133.652711 5.3914884 1.958133 6.9872253 1.305707 1.595737 3.167257 2.393463 5.584937 2.393463s4.271253-.797726 5.56072-2.393463z"/><path d="m158.846626 19.7799018v15.2798724h-3.916835v-15.0864238c0-2.2564251-.451285-3.9085727-1.353855-4.9561579s-2.320813-1.5715203-4.255013-1.5715203c-2.256425 0-4.06185.693167-5.415705 2.079216-1.353856 1.3860489-2.030783 3.2558618-2.030783 5.6091536v13.9257324h-3.91655v-17.5041035c0-2.5142615-.129061-4.786926-.386897-6.8177085h3.723101l.386897 4.3518804c.741316-1.5797825 1.853574-2.7965996 3.33649-3.6507362 1.482915-.8544216 3.175234-1.2814899 5.076956-1.2814899 5.834796 0 8.752194 3.2074284 8.752194 9.6222853z"/><path d="m205.653771 35.0597742-3.772105-8.848776h-17.988722l-3.817689 8.848776h-4.111138l15.134003-34.42786122h3.481504l15.134002 34.42786122zm-20.359108-12.1368318h15.185285l-7.592643-17.69726709z"/></g><g fill="#f2f2f2" fill-rule="nonzero" transform="translate(22.788376 290.137172)"><path d="m.04658391 21.7701602 1.62834138-20.70276002h4.56506199l-1.36656882 17.01005832h9.24650314l-.2907867 3.6927017z"/><path d="m16.3006611 21.7701602 1.1629859-14.74195382h4.3906544l-1.1629859 14.74195382zm1.5119622-21.66232409h4.7104554l-.319801 4.12904304h-4.7104553z"/><path d="m23.395439 20.2000084 1.4247584-3.0530998c.8141707.5622308 1.6863698.9935752 2.6169196 1.2940334.9303887.3004581 1.8609386.4506872 2.7913273.4506872.8141707 0 1.415087-.1163792 1.8027489-.3489764.387662-.2325971.5815736-.5427267.5815736-.9303886 0-.407166-.2277615-.7269669-.6832845-.9595641-.4555229-.2325972-1.1969969-.5040411-2.224422-.8141707-1.0661106-.2907868-1.9384709-.5815735-2.6169196-.8723603-.6784487-.2907867-1.2648579-.72197-1.7590665-1.2938721-.4943697-.5719021-.741474-1.3133761-.741474-2.224422 0-.9498927.2664471-1.78340617.7995024-2.50054048.5330554-.7172955 1.2891976-1.27936503 2.2681045-1.68653097.9789069-.40700475 2.0983714-.61058772 3.3583937-.61058772 1.1047962 0 2.1855752.16473618 3.2420144.49436973 1.0564393.32947236 1.9433067.7753239 2.6606022 1.33755462l-1.3957442 2.93672062c-.7172955-.5233839-1.4732766-.9208785-2.2679433-1.1921612-.7948279-.27144401-1.5701518-.40716599-2.3262941-.40716599-.7946667 0-1.395583.11637918-1.802749.34897639-.4070047.2325971-.6105877.5523981-.6105877.959564 0 .4265088.2422686.7656525.7269669 1.0177537.4845371.25194 1.2211754.5135513 2.2097537.7849953 1.0662719.3101296 1.9336353.6105877 2.6024126.9013745.6687773.2907867 1.2503508.7221312 1.7447205 1.2938721.4942086.5719021.7413128 1.3133761.7413128 2.224422 0 1.4539338-.5765766 2.5927412-1.7300522 3.4165832-1.1533145.8238421-2.7089592 1.2356826-4.6667729 1.2356826-2.5200445 0-4.768645-.6009163-6.7458015-1.802749z"/><path d="m44.7087867 16.0421124c-.0581896.8141707.1065466 1.415087.4942086 1.8027489.3878231.387662.9208784.5815736 1.5993272.5815736.4458515 0 .94006-.0776936 1.482948-.2327584l-.2907868 3.4020761c-.6591059.271444-1.5119622.4070048-2.5587301.4070048-1.6671881 0-2.9417175-.4458516-3.8237491-1.3375546-.8818705-.8915419-1.3228864-2.1515642-1.3228864-3.7799055 0-.3296336.0096714-.5815736.0290142-.7559811l.4651944-5.8154129h-2.7913273l.2616114-3.28569692h2.7914884l.2616114-3.46010454 4.5070336-1.42475841-.3779906 4.88486295h3.7508913l-.2617725 3.28569692h-3.7508913z"/><path d="m49.3900667 20.2000084 1.4247584-3.0530998c.8141707.5622308 1.686531.9935752 2.6169197 1.2940334.9305498.3004581 1.8609385.4506872 2.7914884.4506872.8141707 0 1.415087-.1163792 1.802749-.3489764.3876619-.2325971.5815735-.5427267.5815735-.9303886 0-.407166-.2277615-.7269669-.6832844-.9595641-.4556842-.2325972-1.196997-.5040411-2.224422-.8141707-1.0661107-.2907868-1.938471-.5815735-2.6169197-.8723603-.6784487-.2907867-1.2648579-.72197-1.7592276-1.2938721-.4942086-.5719021-.741474-1.3133761-.741474-2.224422 0-.9498927.2666082-1.78340617.7996635-2.50054048.5330554-.7172955 1.2890365-1.27936503 2.2679433-1.68653097.9789069-.40700475 2.0983715-.61058772 3.3583937-.61058772 1.1049574 0 2.1857364.16473618 3.2421757.49436973 1.0564392.32947236 1.9433066.7753239 2.6604409 1.33755462l-1.395583 2.93672062c-.7172955-.5233839-1.4732766-.9208785-2.2681045-1.1921612-.7946667-.27144401-1.5701518-.40716599-2.3261329-.40716599-.7948279 0-1.3957442.11637918-1.802749.34897639-.4070047.2325971-.6105877.5523981-.6105877.959564 0 .4265088.2422686.7656525.7269669 1.0177537.4845372.25194 1.2211755.5135513 2.2097537.7849953 1.0661107.3101296 1.9336353.6105877 2.6024126.9013745.6687773.2907867 1.2503508.7221312 1.7445594 1.2938721.4943697.5719021.741474 1.3133761.741474 2.224422 0 1.4539338-.5767379 2.5927412-1.7300523 3.4165832-1.1533145.8238421-2.7089592 1.2356826-4.6667729 1.2356826-2.5200445 0-4.768645-.6009163-6.7459627-1.802749z"/><path d="m73.2145935 2.29179942h7.7695192c2.0061707 0 3.5700361.48340881 4.6917573 1.44990405 1.12156.96665643 1.68234 2.29808583 1.68234 3.9942882 0 1.69604118-.5652933 3.03198393-1.6960412 4.00782813-1.1307478.9756831-2.6900999 1.4636052-4.6780561 1.4636052h-5.526238v8.5627352h-2.2432812zm7.5778643 9.05533178c1.4408774 0 2.5260084-.3101295 3.2555544-.9302274.7295459-.62009798 1.0943189-1.51373534 1.0943189-2.68091213 0-1.16733798-.364773-2.05646202-1.0943189-2.66737212-.729546-.61107129-1.814677-.91652634-3.2555544-.91652634h-5.3345831v7.19503799z"/><path d="m102.432215 8.0095311v13.7606291h-2.188638v-2.4894183c-.4012015.8572084-1.0075983 1.5182486-1.8193511 1.9832817-.8115916.4651944-1.7553591.6976303-2.8314635.6976303-1.2218202 0-2.2934114-.2917539-3.214451-.8754229-.9210397-.5835078-1.63221-1.4088006-2.1338332-2.4758784-.5016233-1.0669166-.7522738-2.3116257-.7522738-3.7341275 0-1.4226629.255325-2.6765599.7659749-3.761691s1.2264947-1.92863838 2.1475344-2.53052184c.9210396-.60188346 1.9834429-.90282519 3.1870487-.90282519 1.0761044 0 2.0153585.23711049 2.8179235.71133147.8024039.47422098 1.4134752 1.13993568 1.8328911 1.99698296v-2.3799704zm-3.2829565 10.7376719c.729546-.9210397 1.0943185-2.2295801 1.0943185-3.9257825s-.3647725-3.0002295-1.0943185-3.9120813c-.7295459-.91185183-1.7690602-1.36785834-3.1187041-1.36785834s-2.4028593.46970764-3.1598076 1.40896184c-.756787.9392541-1.1352611 2.2477945-1.1352611 3.9257824 0 1.6778267.3737996 2.9728272 1.12156 3.884679s1.8056504 1.3678583 3.1735087 1.3678583c1.3496439 0 2.3891582-.4605198 3.1187041-1.3815594z"/><path d="m118.983366 8.0095311v13.6511811c0 2.0427609-.524351 3.5884118-1.573054 4.6371139-1.048702 1.0487022-2.594514 1.5730532-4.637113 1.5730532-2.097405 0-3.903055-.4742209-5.41679-1.4226629l.382987-1.8054892c.875423.4924355 1.700716.8480206 2.475878 1.0669166.775163.218896 1.627697.328344 2.557925.328344 1.331429 0 2.334514-.3510718 3.009256-1.0533766.674902-.7021436 1.012273-1.7461713 1.012273-3.1324053v-3.2553932c-.419417.8754229-1.035001 1.5546775-1.846593 2.0380863-.811591.4832477-1.773735.7248715-2.886268.7248715-1.203606 0-2.275197-.2825661-3.214451-.8480206-.939254-.5652933-1.664287-1.3678584-2.174937-2.4073727-.51065-1.0396755-.765974-2.2342546-.765974-3.5838984 0-1.3496439.255324-2.544223.765974-3.5837373.51065-1.0396755 1.235683-1.84207932 2.174937-2.40753384.939254-.56529333 2.010845-.84802059 3.214451-.84802059 1.094319 0 2.047274.23711049 2.858866.71133147s1.427176 1.13993568 1.846593 1.99698296v-2.3799704zm-3.351302 10.1631907c.756787-.8846107 1.135262-2.1019176 1.135262-3.652243 0-1.5501643-.378475-2.7676323-1.135262-3.6520819-.756948-.88461068-1.800976-1.32691604-3.132405-1.32691604-1.349644 0-2.412047.44230536-3.18721 1.32691604-.775001.8844496-1.162663 2.1019176-1.162663 3.6520819 0 1.5503254.387662 2.7676323 1.162663 3.652243.775163.8846107 1.837566 1.3267549 3.18721 1.3267549 1.331429 0 2.375457-.4421442 3.132405-1.3267549z"/><path d="m134.76838 14.8214205h-10.094846c.018375 1.7508458.424091 3.0730874 1.217468 3.9668859.793377.8936374 1.947014 1.340456 3.460749 1.340456 1.604969 0 3.082275-.5380522 4.431758-1.6141566l.738734 1.6141566c-.601884.5654546-1.372372 1.0122732-2.311626 1.3404561-.939415.328344-1.901397.4924354-2.886268.4924354-2.152048 0-3.839062-.633799-5.061044-1.901236-1.221981-1.2675982-1.833052-3.0047428-1.833052-5.2115951 0-1.4042873.2737-2.6491576.820779-3.7342887s1.313215-1.92863838 2.298086-2.53052184c.98471-.60188346 2.106431-.90282519 3.364841-.90282519 1.823865 0 3.255555.59737014 4.295069 1.79194923 1.039675 1.1945791 1.559352 2.8404902 1.559352 4.9378945zm-8.63108-4.3771144c-.720519.6929558-1.181039 1.6688-1.381559 2.9272104h8.015656c-.109448-1.2948393-.487922-2.2797102-1.135422-2.9546127-.647339-.67474139-1.545651-1.01227325-2.694614-1.01227325-1.148962 0-2.083703.3465585-2.804061 1.03967555z"/><path d="m137.285362 20.1834059.738572-1.6413978c.747761.583669 1.504709 1.0030854 2.270684 1.2584103.765975.255325 1.623506.3829875 2.571303.3829875 1.039675 0 1.827894-.1777926 2.366269-.5333778.538375-.3555851.807562-.8709095.807562-1.5456509 0-.54724-.182145-.9848709-.546434-1.3132149-.365901-.328344-.96714-.583669-1.80694-.7659749l-2.32436-.54724c-1.149446-.255325-2.03857-.7111703-2.667856-1.3678584-.629124-.6565268-.943767-1.4407162-.943767-2.3527292 0-1.2036057.483248-2.18396332 1.449904-2.94091156.966656-.75678705 2.243926-1.13526117 3.830036-1.13526117.96714 0 1.877863.15506478 2.735394.46503315.857531.31012956 1.57805.75694824 2.161558 1.34061723l-.73825 1.61399545c-1.295968-1.0761044-2.682202-1.61399545-4.158702-1.61399545-.984871 0-1.745688.18681921-2.284063.56078005-.538213.3737996-.807239.8981506-.807239 1.5730532 0 .5652933.168605 1.0122732.505975 1.340456.336726.328344.879936.583669 1.627858.7659749l2.325972.5744812c1.276625.291915 2.224422.743247 2.845003 1.3543183.61897.6109101.930067 1.4088006.930067 2.3936715 0 1.1855525-.48357 2.1338333-1.45071 2.8451647-.965529.7113315-2.279227 1.0669166-3.939484 1.0669166-2.315817 0-4.148708-.5926956-5.498352-1.778248z"/><path d="m166.776845 19.8826253h4.294102v1.8875349h-10.860982v-1.8875349h4.295713v-14.8003046l-3.994288 2.54422296v-2.16123552l4.979159-3.17350872h1.286296z"/><path d="m177.692632 18.9523978v1.9971441c0 .7659749-.128952 1.4681185-.383632 2.1064309s-.683446 1.2584104-1.286296 1.8602938l-1.039676-.7933771c.71246-.8206183 1.113823-1.6049689 1.20409-2.3527293h-1.313699v-2.8177624z"/><path d="m194.243621 19.8826253v1.8875349h-12.529298v-1.6960412l6.811889-7.5506231c.910724-1.0214611 1.576438-1.9425007 1.997144-2.76311902.419094-.82077948.628641-1.64139777.628641-2.46217725 0-1.07610444-.311096-1.90139724-.930066-2.4758784-.620582-.57448116-1.505515-.86172174-2.654799-.86172174-1.860133 0-3.700923.74776041-5.525594 2.24328123l-.847859-1.72344348c.765652-.72954594 1.732792-1.31321493 2.899808-1.75084578 1.167016-.43779204 2.343703-.65668806 3.530061-.65668806 1.785985 0 3.199622.46051983 4.239297 1.38155949 1.039676.92103966 1.560319 2.16574884 1.560319 3.73428873 0 1.11253338-.251456 2.18396331-.752757 3.21445098-.501301 1.0304877-1.336265 2.1841245-2.503281 3.4607493l-5.552995 6.0186734z"/><path d="m200.425258 18.9523978v1.9971441c0 .7659749-.12734 1.4681185-.38202 2.1064309-.256292.6383124-.683446 1.2584104-1.286297 1.8602938l-1.039675-.7933771c.710848-.8206183 1.112211-1.6049689 1.204089-2.3527293h-1.313698v-2.8177624z"/><path d="m215.691563 13.4535622c.601239.802565.902664 1.814677.902664 3.0366584 0 1.6962023-.575448 3.0321451-1.723121 4.0078281-1.149285.9758443-2.709604 1.4636052-4.679346 1.4636052-1.257282 0-2.466207-.2097082-3.623551-.6291245-1.158956-.4195776-2.138991-1.0122732-2.941718-1.7782481l.875262-1.7236047c1.805328 1.495682 3.684803 2.2434424 5.635202 2.2434424 1.386234 0 2.440417-.3101295 3.160936-.9302275.72052-.6200979 1.079973-1.5319497 1.079973-2.7357166 0-2.3891582-1.495843-3.5837373-4.485917-3.5837373h-2.243765v-1.8876961h1.805328c1.441038 0 2.54519-.3191562 3.310842-.9574686.765653-.63847359 1.149285-1.55032542 1.149285-2.73571668 0-1.05788997-.315932-1.86948162-.944573-2.43493614-.628641-.56529333-1.51841-.84802059-2.667695-.84802059-1.860132 0-3.702534.74776041-5.525593 2.24328123l-.847859-1.72344348c.783383-.74776041 1.745687-1.33594272 2.885301-1.76454693 1.141225-.42860421 2.330807-.64298691 3.570358-.64298691 1.752135 0 3.151265.44681868 4.200612 1.34061723 1.047735.89363736 1.571602 2.09740428 1.571602 3.61113957 0 1.11253338-.272411 2.08821645-.820457 2.9272104-.546434.838994-1.304027 1.4408774-2.269555 1.8054892 1.147673.328344 2.022934.8937985 2.625785 1.6962024z"/></g><g transform="translate(329.992265 224.553185)"><path d="m.21765.193821h263.332986v106.422426h-263.332986z" fill="#c9177e"/><path d="m263.550636 106.616248h-263.33298624v-106.42242661h263.33298624zm-260.79463916-103.88400537v101.34558437h258.25629216v-101.34558437z" fill="#000"/></g><g fill="#f2f2f2" fill-rule="nonzero" transform="translate(359.320353 242.51167)"><path d="m.14615481 31.0947909 1.49887023-3.0461739c1.70855821 1.4504369 3.44931037 2.4820676 5.22225648 3.0946072 1.7729461.6125397 3.83620748.9188095 6.18921438.9188095 2.7723829 0 4.9080094-.5401745 6.4068796-1.6199537 1.4991552-1.080064 2.2484478-2.6031509 2.2484478-4.5695456 0-1.1604065-.3623955-2.1034326-1.0877564-2.8285086-.7253609-.7253609-1.6763643-1.2977293-2.8530102-1.7165355-1.1766458-.419091-2.7481661-.8544215-4.7145608-1.3057065-2.6433222-.5803457-4.81911993-1.2088399-6.52767814-1.8857674-1.70855822-.6769275-3.0946072-1.6521476-4.15843184-2.9253753s-1.59573696-2.9416147-1.59573696-5.0045912c0-1.96639471.5159578-3.69916961 1.54730359-5.19803984 1.0316307-1.49915513 2.49032973-2.66753887 4.37609709-3.505721 1.88576735-.83818214 4.08606666-1.25727321 6.60032816-1.25727321 2.3854858 0 4.6097169.37094261 6.6726934 1.11225801 2.0632614.74131541 3.8040135 1.82137947 5.2222565 3.23962239l-1.5473036 3.04645873c-1.6116915-1.38633388-3.2475997-2.40172515-4.9077245-3.04645873-1.6601249-.64473357-3.4735271-.96695791-5.4399218-.96695791-2.6755161 0-4.77097143.57208353-6.28608109 1.71653548-1.51510965 1.14445195-2.27266448 2.71597223-2.27266448 4.71456088 0 1.7407521.660973 3.0461738 1.98263409 3.9165499 1.32166109.870376 3.35244368 1.6279309 6.09263258 2.2726645 2.9655465.7091214 5.2946216 1.3618322 6.9869404 1.9584174 1.6926037.5963002 3.1028694 1.4988702 4.2310819 2.70771 1.1282125 1.2088399 1.6923188 2.8125541 1.6923188 4.8111427 0 1.9342007-.5156729 3.6344968-1.5473036 5.101458-1.0316307 1.4666763-2.5062843 2.602866-4.4242456 3.4088542-1.9182462.8059882-4.166694 1.2088399-6.7453434 1.2088399-5.38351106 0-9.67071867-1.4507218-12.86219259-4.3518804z"/><path d="m52.0781194 22.7779272h-17.8425672c.032194 3.0946072.7495776 5.4316596 2.151866 7.011442 1.4022884 1.5794975 3.4410482 2.3692463 6.1165643 2.3692463 2.8367708 0 5.447899-.9510034 7.8333847-2.8530102l1.3057066 2.8530102c-1.0638246.9994368-2.4259418 1.7891855-4.0860667 2.3692463-1.6601248.5803457-3.3604209.8703761-5.101173.8703761-3.8040136 0-6.7857995-1.1202353-8.9456428-3.3604209-2.1598432-2.2404705-3.2396224-5.310861-3.2396224-9.2114564 0-2.4820676.483479-4.6823669 1.4507218-6.6003282.9669579-1.9179613 2.320813-3.4088543 4.0615651-4.4726789 1.7407522-1.0638247 3.7233863-1.595737 5.9476174-1.595737 3.2233829 0 5.7541688 1.0558474 7.5915028 3.1672572 1.837334 2.1114099 2.7561434 5.0205458 2.7561434 8.7276926zm-15.2556556-7.736518c-1.2732277 1.2247944-2.0871932 2.949592-2.4418964 5.1738231h14.1676143c-.1931636-2.288619-.8621139-4.0293711-2.0065658-5.2222565-1.144452-1.1926004-2.7319268-1.7891855-4.7627094-1.7891855-2.0310674 0-3.683215.6125397-4.9564427 1.8376189z"/><path d="m62.0630852 33.8509343c-1.7567067-1.0313458-3.1105617-2.4900448-4.0615651-4.3760971-.9510034-1.8857673-1.4265051-4.0857818-1.4265051-6.6000433 0-2.5145464.483479-4.7308002 1.4507218-6.6487615.9669579-1.9179613 2.3450296-3.4088543 4.1342151-4.4726789 1.7889007-1.0638247 3.8763787-1.595737 6.2618645-1.595737 1.6438854 0 3.2316451.2820531 4.7627093.8461594 1.531349.5641063 2.7965995 1.3458778 3.7957514 2.3453145l-1.3054217 2.9011587c-1.2250793-.9672429-2.4097024-1.6763643-3.5541544-2.1276493-1.144167-.451285-2.3128357-.6769276-3.505721-.6769276-2.4820675 0-4.4322228.8302049-5.8507506 2.4903298-1.4182429 1.6601248-2.1273644 3.9729605-2.1273644 6.9387919 0 2.9333526.7011442 5.2139943 2.1031477 6.8419253 1.4022884 1.6279309 3.3607058 2.4418963 5.8749673 2.4418963 1.1928853 0 2.361554-.2256425 3.505721-.6769275 1.144452-.451285 2.3290751-1.1604065 3.5541544-2.1276493l1.3054217 2.9011586c-1.0316307.9672429-2.3290751 1.7327749-3.8923333 2.2968812-1.563543.5641063-3.1834966.8461594-4.859576.8461594-2.3532918 0-4.408291-.5156729-6.1652826-1.5473036z"/><path d="m87.2313415 13.8325694v13.2972382c0 1.80514.3706577 3.0703905 1.112258 3.7957514.7413154.7253609 1.7889006 1.0880413 3.1427556 1.0880413.9025701 0 1.7729461-.1450152 2.6111283-.4353305v3.3364892c-.9991519.3225092-2.1273644.4834789-3.3846376.4834789-2.3210979 0-4.1342152-.6527108-5.4399217-1.9581325-1.3054217-1.3057066-1.9581325-3.2316451-1.9581325-5.7783855v-13.8291505h-4.7387776v-3.0946072h4.7387776v-6.23764778l3.9165499-1.4022884v7.63993618h6.9630086v3.0946072z"/><path d="m98.9328427 35.0597742v-24.321812h3.9168353v24.321812zm-.3866122-34.62130978h4.7869255v4.44874713h-4.7869255z"/><path d="m114.454597 33.8509343c-1.740752-1.0313458-3.08663-2.498307-4.037633-4.4000289-.951004-1.9020067-1.426505-4.1262378-1.426505-6.6729782 0-2.5464555.475501-4.7709715 1.426505-6.6726933.951003-1.9020068 2.296881-3.3686831 4.037633-4.4003138s3.755295-1.5473036 6.044199-1.5473036c2.288619 0 4.303447.5156729 6.044199 1.5473036 1.740753 1.0316307 3.08663 2.498307 4.037634 4.4003138.950718 1.9017218 1.42622 4.1262378 1.42622 6.6726933 0 2.5467404-.475502 4.7709715-1.42622 6.6729782-.951004 1.9017219-2.296881 3.3686831-4.037634 4.4000289-1.740752 1.0316307-3.75558 1.5473036-6.044199 1.5473036-2.288904 0-4.303447-.5156729-6.044199-1.5473036zm11.604919-4.0857818c1.289468-1.5957369 1.933916-3.924812 1.933916-6.9872253 0-2.9655465-.660688-5.2624277-1.982349-6.8903586s-3.158995-2.4418964-5.512287-2.4418964c-2.385486 0-4.239059.8139655-5.56072 2.4418964s-1.982634 3.9248121-1.982634 6.8903586c0 3.0624133.652996 5.3914884 1.958417 6.9872253 1.305707 1.595737 3.167257 2.393463 5.584937 2.393463s4.271253-.797726 5.56072-2.393463z"/><path d="m158.988222 19.7799018v15.2798724h-3.916549v-15.0864238c0-2.2564251-.451285-3.9085727-1.353856-4.9561579-.90257-1.0475852-2.321097-1.5715203-4.255298-1.5715203-2.256425 0-4.061565.693167-5.41542 2.079216-1.353855 1.3860489-2.031068 3.2558618-2.031068 5.6091536v13.9257324h-3.91655v-17.5041035c0-2.5142615-.128775-4.786926-.386897-6.8177085h3.723387l.386897 4.3518804c.741315-1.5797825 1.853573-2.7965996 3.336204-3.6507362 1.482916-.8544216 3.175234-1.2814899 5.077241-1.2814899 5.834796 0 8.751909 3.2074284 8.751909 9.6222853z"/><path d="m203.619569 20.3360308c1.096874 1.4344824 1.643886 3.2156906 1.643886 5.343055 0 2.9980254-1.000007 5.3108611-3.00002 6.938792-1.997164 1.6279309-4.817695 2.4418964-8.461594 2.4418964h-14.310635v-34.42786122h13.82915c3.512844 0 6.245056.78177151 8.196635 2.34531453 1.948731 1.56325812 2.923097 3.77951197 2.923097 6.64847666 0 1.83761893-.475787 3.42509373-1.424511 4.76299423-.951573 1.3376156-2.282066 2.3290751-3.991479 2.9735238 1.968673.5481517 3.498598 1.5393263 4.595471 2.9738086zm-20.213807-4.4242455h9.284961c2.578364 0 4.529944-.5159578 5.85189-1.5473036 1.321946-1.0316307 1.982919-2.5467404 1.982919-4.54532897 0-3.93278933-2.612553-5.899184-7.834809-5.899184h-9.284961zm16.031444 14.3368462c1.273512-1.0153913 1.908844-2.5706722 1.908844-4.6661275 0-4.2228197-2.626798-6.3342296-7.880393-6.3342296h-10.059895v12.523444h10.059895c2.70657 0 4.698036-.5076956 5.971549-1.5230869z"/></g><g fill="#f2f2f2" fill-rule="nonzero" transform="translate(356.809897 292.199308)"><path d="m.10689318 19.8854177 1.48742717-18.91226722h4.17039899l-1.24844346 15.53895012h8.44675212l-.2655896 3.3733171z"/><path d="m14.955185 19.8854177 1.0625151-13.46697537h4.01092l-1.0625151 13.46697537zm1.3811601-19.78885388h4.3031155l-.2921955 3.77193628h-4.3031156z"/><path d="m21.436386 18.4510458 1.3014988-2.7889259c.7437136.5134941 1.540639.9074182 2.3906198 1.1819286.8499807.2745105 1.6999614.4117657 2.5499422.4117657.7437136 0 1.2927345-.1062672 1.6469061-.3188015.3541717-.2125343.5311793-.495809.5311793-.8499807 0-.3718568-.2079956-.6640524-.6241435-.8765867-.4161478-.2123778-1.0935031-.4602823-2.0320659-.7437136-.973933-.2655896-1.7708584-.5311792-2.3906197-.7967689-.6197613-.2657461-1.1554793-.6596702-1.6069973-1.1820852-.451518-.5224149-.6773553-1.1997702-.6773553-2.0320659 0-.86766582.2435224-1.62906451.7305671-2.28435256.4868883-.65513154 1.1775465-1.16862571 2.0718183-1.5404825s1.916878-.5579417 3.0679751-.5579417c1.0093032 0 1.9965392.15055818 2.9615514.45167454.9651687.30095986 1.7752405.70834338 2.4305286 1.22183754l-1.2750494 2.68281528c-.6551315-.47812392-1.3457898-.84121642-2.0718183-1.08912095s-1.4343718-.37185679-2.1250301-.37185679c-.7260285 0-1.2748928.10626716-1.6467496.31880147-.3718568.21237781-.5577852.50457336-.5577852.87643017 0 .3896984.2212986.6995791.6640523.9297985.4425972.2302194 1.1155704.4692031 2.0186065.7171076.9740895.2832748 1.7664762.5577852 2.3773168.8233749.610997.2657461 1.1421763.6596702 1.5938508 1.1820851.451518.522415.6773553 1.1997703.6773553 2.032066 0 1.3281047-.5269536 2.3683959-1.5805479 3.1210303-1.0535942.7526344-2.4746631 1.1288734-4.2632067 1.1288734-2.3020377 0-4.3561708-.5490209-6.1623995-1.6469062z"/><path d="m40.9064384 14.6526601c-.0530553.7437136.0973463 1.2927345.451518 1.6469062s.8412165.5311793 1.4609778.5311793c.407227 0 .8589015-.0707405 1.3547106-.2123778l-.2657461 3.1077274c-.6020763.2479045-1.3811601.3718568-2.337408.3718568-1.5229539 0-2.6871974-.407227-3.4928871-1.2218376-.8056897-.8146105-1.2085346-1.9655511-1.2085346-3.4531348 0-.3009598.0087643-.5311792.0264494-.6906582l.4250686-5.31241881h-2.5499422l.2389837-3.00146026h2.5499422l.2391403-3.16093925 4.1170306-1.30149878-.3452509 4.46243803h3.4265289l-.2389837 3.00146026h-3.4265289z"/><path d="m45.182948 18.4510458 1.3014988-2.7889259c.7438701.5134941 1.540639.9074182 2.3906198 1.1819286.8499807.2745105 1.6999614.4117657 2.5499422.4117657.7438701 0 1.2927345-.1062672 1.6469062-.3188015.3541716-.2125343.5313357-.495809.5313357-.8499807 0-.3718568-.2081521-.6640524-.6242999-.8765867-.4161479-.2123778-1.0935032-.4602823-2.032066-.7437136-.973933-.2655896-1.7707019-.5311792-2.3904632-.7967689-.6199178-.2657461-1.1554793-.6596702-1.6069973-1.1820852-.4516745-.5224149-.6773553-1.1997702-.6773553-2.0320659 0-.86766582.2433659-1.62906451.7304106-2.28435256.4868883-.65513154 1.1775465-1.16862571 2.0718183-1.5404825s1.916878-.5579417 3.0679751-.5579417c1.0093032 0 1.9965392.15055818 2.9617079.45167454.9650122.30095986 1.7752405.70834338 2.4303721 1.22183754l-1.2748929 2.68281528c-.655288-.47812392-1.3459463-.84121642-2.0719748-1.08912095-.7260284-.24790453-1.4343718-.37185679-2.1248736-.37185679-.7260284 0-1.2750493.10626716-1.6469061.31880147-.3718568.21237781-.5577852.50457336-.5577852.87643017 0 .3896984.2212986.6995791.6640523.9297985.4427538.2302194 1.1155704.4692031 2.018763.7171076.973933.2832748 1.7663198.5577852 2.3773168.8233749.6108405.2657461 1.1421763.6596702 1.5936943 1.1820851.451518.522415.6773553 1.1997703.6773553 2.032066 0 1.3281047-.5267971 2.3683959-1.5805479 3.1210303-1.0535942.7526344-2.4746631 1.1288734-4.2632066 1.1288734-2.3020378 0-4.3561709-.5490209-6.1623996-1.6469062z"/><path d="m67.4951382.97315048h7.543716c1.9478661 0 3.4664378.46935965 4.5554023 1.40776594 1.0891209.93856279 1.6336032 2.23129726 1.6336032 3.87820343 0 1.64674965-.5490209 2.94386628-1.6469062 3.89134985-1.0978853.9473271-2.6119184 1.4210689-4.5420993 1.4210689h-5.3654741v8.3138791h-2.1782419zm7.3577876 8.7921595c1.3990017 0 2.4525959-.30111636 3.1609393-.90319258.7083434-.60207621 1.062515-1.46974206 1.062515-2.60299755 0-1.133412-.3541716-1.9966957-1.062515-2.58985111-.7083434-.59331191-1.7619376-.88988961-3.1609393-.88988961h-5.1795457v6.98593085z"/><path d="m95.8636172 6.52470948v13.36070822h-2.1250301v-2.4170692c-.3895419.8322956-.9783152 1.4741242-1.7663198 1.9256423-.7880046.4516745-1.7043436.6773553-2.7491736.6773553-1.1864673 0-2.2267586-.2832748-3.1210303-.8499808-.8942718-.5665495-1.5849301-1.367857-2.0718183-2.4039227-.4870448-1.0359091-.7305671-2.2444437-.7305671-3.6256037 0-1.3813166.2479045-2.5987719.7437135-3.65236619.4959656-1.05359425 1.191006-1.87258693 2.0852778-2.45697803.8941152-.58439111 1.9256422-.87658666 3.0944244-.87658666 1.04483 0 1.9567869.23021942 2.7358707.69065826.7792403.46043884 1.3723957 1.10680608 1.7796227 1.93894521v-2.31080201zm-3.1873886 10.42560622c.7083433-.8942718 1.0623585-2.1647825 1.0623585-3.8116887 0-1.6469061-.3540152-2.9130347-1.0623585-3.79838565-.7083434-.88535096-1.7178031-1.32810469-3.0280662-1.32810469-1.3104196 0-2.3331823.45605669-3.0679751 1.36801357-.7349493.91195687-1.1024239 2.18246757-1.1024239 3.81168867 0 1.6290645.3630925 2.8864288 1.089121 3.7717797.7260284.885351 1.7530168 1.3281047 3.081278 1.3281047 1.3102631 0 2.3197228-.4471359 3.0280662-1.3414076z"/><path d="m111.933747 6.52470948v13.25444102c0 1.9833927-.509112 3.4841229-1.527336 4.5023469s-2.518955 1.5273361-4.502191 1.5273361c-2.036448 0-3.789621-.4604389-5.259363-1.3813166l.371857-1.7530168c.84998.478124 1.651288.8233749 2.403922 1.0359092.752478.2125343 1.580392.3188014 2.483584.3188014 1.292578 0 2.266511-.3408687 2.921799-1.0227627.655132-.6817374.982854-1.6954228.982854-3.0413691v-3.1607827c-.407384.8499807-1.005078 1.5094944-1.793082 1.978854-.788005.4692032-1.722029.7038048-2.802229.7038048-1.168782 0-2.209074-.274354-3.12103-.8233749-.911957-.5488644-1.615919-1.3281047-2.1117276-2.3374079-.4958091-1.0094597-.7437136-2.1693211-.7437136-3.4797407s.2479045-2.470281.7437136-3.47958423c.4958086-1.00945973 1.1997706-1.78854354 2.1117276-2.33756443.911956-.54886438 1.952248-.82337482 3.12103-.82337482 1.062515 0 1.987775.23021942 2.775779.69065826.788005.46043884 1.385543 1.10680608 1.792926 1.93894521v-2.31080201zm-3.253904 9.86782102c.734949-.8589016 1.102424-2.0408302 1.102424-3.546099 0-1.5051123-.367475-2.6871975-1.102424-3.54594251-.734793-.85890155-1.748634-1.28835233-3.041369-1.28835233-1.31042 0-2.34179.42945078-3.094424 1.28835233-.752635.85874501-1.128874 2.04083021-1.128874 3.54594251 0 1.5052688.376239 2.6871974 1.128874 3.546099.752634.8589015 1.784004 1.2881958 3.094424 1.2881958 1.292735 0 2.306576-.4292943 3.041369-1.2881958z"/><path d="m127.260162 13.138627h-9.801462c.017685 1.6999615.411765 2.9837752 1.182085 3.8515976.770319.8676658 1.890272 1.3014987 3.360014 1.3014987 1.558324 0 2.992696-.5224149 4.303116-1.5672449l.717264 1.5672449c-.584391.5490209-1.332644.9828538-2.244601 1.3014988-.911956.3188015-1.845981.478124-2.802228.478124-2.08966 0-3.727646-.6153792-4.914113-1.8459811-1.186467-1.2307583-1.779623-2.9174168-1.779623-5.060132 0-1.363475.26559-2.572166.796926-3.62576029.531179-1.05359425 1.274893-1.87258693 2.23114-2.45697803.956248-.58439111 2.045369-.87658666 3.267207-.87658666 1.770702 0 3.160939.58000895 4.170242 1.73987036 1.009304 1.1598614 1.514033 2.75793792 1.514033 4.79438592zm-8.380393-4.24990368c-.699423.67281665-1.146559 1.62030028-1.341408 2.84213778h7.7827c-.106111-1.2572078-.473586-2.21345565-1.102268-2.8687437-.628682-.65513154-1.50073-.98285381-2.616457-.98285381-1.11557 0-2.023145.33648658-2.722567 1.00945973z"/><path d="m129.703837 18.3447787.717265-1.5936944c.726028.566706 1.460821.973933 2.204691 1.2218376.743714.2479045 1.576009.3718568 2.496261.3718568 1.00946 0 1.776336-.1726255 2.297499-.5178764.522728-.3452508.784092-.8455986.784092-1.5007301 0-.5313358-.176851-.9562479-.530553-1.2750494-.355268-.3188014-.939033-.566706-1.752861-.7437135l-2.258529-.5313358c-1.115727-.2479046-1.97901-.6905018-2.589851-1.3281047-.610997-.6374465-.916339-1.3988452-.916339-2.2843526 0-1.16862572.469203-2.12049147 1.407766-2.85544076.938563-.73479278 2.178085-1.10226742 3.718411-1.10226742.939033 0 1.824853.15055818 2.655897.45151803.832608.30111636 1.532187.73494929 2.098737 1.30165528l-.716795 1.56708842c-1.256738-1.04482995-2.602684-1.56708842-4.037839-1.56708842-.955934 0-1.695266.18138975-2.217681.54448224-.522415.36293598-.783622.872048-.783622 1.52733603 0 .5488644.163861.9828538.491427 1.3014988.327565.3188015.854362.566706 1.580391.7437136l2.258216.5577852c1.239523.2834312 2.159774.7216463 2.76232 1.3149582.602546.5931554.903036 1.3678571.903036 2.324105 0 1.1510971-.469516 2.0718183-1.408548 2.7624765-.937467.6906583-2.212986 1.0359092-3.824992 1.0359092-2.248356 0-4.027979-.5754703-5.338399-1.7265674z"/><path d="m163.62325 13.9621584v1.8062286h-2.868744v4.1170307h-2.17699v-4.1170307h-8.712655v-1.6469061l9.110179-13.14833042h1.779466v12.98900792zm-11.500016 0h6.454282v-9.29688939z"/><path d="m168.936607 17.149547v1.9391018c0 .7437135-.123639 1.425451-.372483 2.0452123-.247278.6197613-.663582 1.2218376-1.247347 1.8062287l-1.011025-.7703195c.691754-.796769 1.081452-1.5583242 1.169095-2.2843526h-1.273954v-2.7358707z"/><path d="m182.52284 8.76915321c.893645.50472986 1.580704 1.20853458 2.058046 2.11172719.478906.903036.718359 1.947866.718359 3.1343333s-.261364 2.2400616-.784092 3.1609393c-.522728.9207211-1.266128 1.6336032-2.231766 2.1381765-.964074.5047299-2.094043.7570166-3.386777.7570166-1.150315 0-2.283414-.2079957-3.399297-.6241435s-2.054916-.987236-2.815532-1.7132645l.823218-1.673512c1.752861 1.4522134 3.551108 2.1782419 5.391611 2.1782419 1.328731 0 2.369492-.3763954 3.122282-1.1290298.751226-.7524779 1.128404-1.7752406 1.128404-3.0678186 0-1.2573642-.372483-2.2710496-1.115883-3.0413691-.743401-.7703195-1.735645-1.15547928-2.975168-1.15547928-1.806072 0-3.249051.73479278-4.328938 2.20469138h-1.514973v-11.07651212h11.341946v1.80622865h-9.163391v6.74679062c1.045456-1.00930322 2.382012-1.51403309 4.011233-1.51403309 1.186311 0 2.227072.25228668 3.120718.75701655z"/><path d="m191.010127 17.149547v1.9391018c0 .7437135-.125205 1.425451-.372483 2.0452123-.247279.6197613-.663583 1.2218376-1.248913 1.8062287l-1.00946-.7703195c.691754-.796769 1.081452-1.5583242 1.169095-2.2843526h-1.275518v-2.7358707z"/><path d="m204.543147 8.76915321c.893646.50472986 1.58853 1.21307323 2.084652 2.12503009.496122.9119569.743401 1.9522482.743401 3.1210304s-.259799 2.2134557-.782527 3.1343333c-.522728.9208777-1.244218 1.6423675-2.166035 2.1647825-.920251.522415-1.964142.7836225-3.133238.7836225-2.284978 0-4.047229-.7969254-5.286751-2.3906198-1.239523-1.5936943-1.859284-3.8603618-1.859284-6.7998459 0-2.12503014.287969-3.94894389.863909-5.47189779.57594-1.52279739 1.406984-2.6828153 2.496261-3.47958421 1.089278-.79692542 2.396098-1.19538813 3.918895-1.19538813 1.097103 0 2.164469.20377001 3.200535.61099702s1.943797.98285382 2.721629 1.7265674l-.823219 1.67335558c-.88582-.74371359-1.735644-1.29273448-2.549472-1.64690617-.813828-.35401518-1.646437-.53117927-2.496261-.53117927-1.629221 0-2.89535.72602848-3.798386 2.17808544-.903036 1.45205695-1.355336 3.48850502-1.355336 6.10934423v.3984627c.406914-1.0094598 1.072061-1.80622867 1.992313-2.39061978s1.975098-.87658666 3.161409-.87658666c1.150314 0 2.172295.25228668 3.067505.75701655zm-.438215 8.34048499c.743401-.770163 1.115884-1.7929257 1.115884-3.0678186 0-1.2573642-.377178-2.2710496-1.129969-3.0413691s-1.73095-1.15547928-2.934476-1.15547928c-1.239523 0-2.248983.38954188-3.028379 1.16878218-.779397.7790838-1.169096 1.7883871-1.169096 3.0280662 0 1.2572078.389699 2.2754318 1.169096 3.0546721.779396.7790838 1.796681 1.1686257 3.054985 1.1686257 1.203526 0 2.178555-.3851597 2.921955-1.1554792z"/></g><g transform="translate(660.011742 224.553185)"><path d="m.21765.193821h263.332986v106.422426h-263.332986z" fill="#c9177e"/><path d="m263.550636 106.616248h-263.33298624v-106.42242661h263.33298624zm-260.79463916-103.88400537v101.34558437h258.25629216v-101.34558437z" fill="#000"/></g><g fill="#f2f2f2" fill-rule="nonzero" transform="translate(688.758199 242.51167)"><path d="m.07350476 31.0947909 1.49915513-3.0461739c1.70855822 1.4504369 3.44902547 2.4820676 5.22225648 3.0946072 1.7729461.6125397 3.83592263.9188095 6.18921443.9188095 2.7720979 0 4.9077245-.5401745 6.4068796-1.6199537 1.4988702-1.080064 2.2484478-2.6031509 2.2484478-4.5695456 0-1.1604065-.3626804-2.1034326-1.0880413-2.8285086-.7253609-.7253609-1.6763643-1.2977293-2.8527253-1.7165355-1.1766459-.419091-2.7481662-.8544215-4.7145608-1.3057065-2.6433222-.5803457-4.81940488-1.2088399-6.52767819-1.8857674-1.70855822-.6769275-3.0948921-1.6521476-4.15843184-2.9253753-1.06382464-1.2732277-1.59573696-2.9416147-1.59573696-5.0045912 0-1.96639471.5156729-3.69916961 1.5473036-5.19803984 1.0316307-1.49915513 2.49004482-2.66753887 4.37609708-3.505721 1.88576736-.83818214 4.08578181-1.25727321 6.60004331-1.25727321 2.3854857 0 4.6097168.37094261 6.6729782 1.11225801 2.0629765.74131541 3.8037287 1.82137947 5.2222565 3.23962239l-1.5473036 3.04645873c-1.6119764-1.38633388-3.2478845-2.40172515-4.9080094-3.04645873-1.6601248-.64473357-3.473527-.96695791-5.4399217-.96695791-2.6755161 0-4.77068658.57208353-6.28579623 1.71653548-1.51510966 1.14445195-2.27266449 2.71597223-2.27266449 4.71456088 0 1.7407521.6606881 3.0461738 1.98234919 3.9165499 1.32166109.870376 3.35272853 1.6279309 6.09263253 2.2726645 2.9658315.7091214 5.2949066 1.3618322 6.9872254 1.9584174 1.6923187.5963002 3.1025844 1.4988702 4.2307969 2.70771 1.1284975 1.2088399 1.6926037 2.8125541 1.6926037 4.8111427 0 1.9342007-.5159578 3.6344968-1.5473036 5.101458-1.0316307 1.4666763-2.5065691 2.602866-4.4245304 3.4088542s-4.1664091 1.2088399-6.7453434 1.2088399c-5.3832262 0-9.67071872-1.4507218-12.86219264-4.3518804z"/><path d="m52.0054694 22.7779272h-17.8425672c.0324788 3.0946072.7495775 5.4316596 2.1518659 7.011442 1.4022884 1.5794975 3.4413332 2.3692463 6.1168493 2.3692463 2.8367707 0 5.447899-.9510034 7.8330998-2.8530102l1.3057066 2.8530102c-1.0638247.9994368-2.425657 1.7891855-4.0857818 2.3692463-1.6604098.5803457-3.3607058.8703761-5.101458.8703761-3.8037286 0-6.7855146-1.1202353-8.9453578-3.3604209-2.1598432-2.2404705-3.2399073-5.310861-3.2399073-9.2114564 0-2.4820676.4837639-4.6823669 1.4507218-6.6003282s2.3210978-3.4088543 4.06185-4.4726789c1.7407521-1.0638247 3.7231013-1.595737 5.9473324-1.595737 3.2236679 0 5.7541688 1.0558474 7.5915028 3.1672572 1.8376189 2.1114099 2.7561435 5.0205458 2.7561435 8.7276926zm-15.2553708-7.736518c-1.2735126 1.2247944-2.0874781 2.949592-2.4418963 5.1738231h14.1676143c-.1934486-2.288619-.8623988-4.0293711-2.0068508-5.2222565-1.144167-1.1926004-2.7319268-1.7891855-4.7627093-1.7891855-2.0307826 0-3.6829301.6125397-4.9561579 1.8376189z"/><path d="m61.99072 33.8509343c-1.7569915-1.0313458-3.1108466-2.4900448-4.06185-4.3760971-.9510034-1.8857673-1.426505-4.0857818-1.426505-6.6000433 0-2.5145464.4837638-4.7308002 1.4507217-6.6487615s2.3453146-3.4088543 4.1342152-4.4726789c1.7891855-1.0638247 3.8763787-1.595737 6.2618644-1.595737 1.6441703 0 3.2316451.2820531 4.7629942.8461594 1.5310642.5641063 2.7963147 1.3458778 3.7957514 2.3453145l-1.3057066 2.9011587c-1.2247943-.9672429-2.4097024-1.6763643-3.5538694-2.1276493-1.144452-.451285-2.3131206-.6769276-3.505721-.6769276-2.4820676 0-4.4325077.8302049-5.8507507 2.4903298-1.4185278 1.6601248-2.1276492 3.9729605-2.1276492 6.9387919 0 2.9333526.7011442 5.2139943 2.1034326 6.8419253 1.4022884 1.6279309 3.3604209 2.4418963 5.8749673 2.4418963 1.1926004 0 2.361269-.2256425 3.505721-.6769275 1.144167-.451285 2.3290751-1.1604065 3.5538694-2.1276493l1.3057066 2.9011586c-1.0316307.9672429-2.3290751 1.7327749-3.8926181 2.2968812s-3.1832118.8461594-4.859576.8461594c-2.3532918 0-4.4082911-.5156729-6.1649978-1.5473036z"/><path d="m87.1586914 13.8325694v13.2972382c0 1.80514.3709426 3.0703905 1.112258 3.7957514s1.7891856 1.0880413 3.1430406 1.0880413c.90257 0 1.7729461-.1450152 2.6111282-.4353305v3.3364892c-.9994367.3225092-2.1276493.4834789-3.3849225.4834789-2.3208129 0-4.1342151-.6527108-5.4396368-1.9581325-1.3057066-1.3057066-1.9584174-3.2316451-1.9584174-5.7783855v-13.8291505h-4.7387775v-3.0946072h4.7387775v-6.23764778l3.9165499-1.4022884v7.63993618h6.9630087v3.0946072z"/><path d="m98.8604776 35.0597742v-24.321812h3.9165494v24.321812zm-.3868971-34.62130978h4.7869255v4.44874713h-4.7869255z"/><path d="m114.381947 33.8509343c-1.740752-1.0313458-3.08663-2.498307-4.037633-4.4000289-.950719-1.9020067-1.426221-4.1262378-1.426221-6.6729782 0-2.5464555.475502-4.7709715 1.426221-6.6726933.951003-1.9020068 2.296881-3.3686831 4.037633-4.4003138s3.75558-1.5473036 6.044199-1.5473036c2.288904 0 4.303447.5156729 6.044199 1.5473036s3.08663 2.498307 4.037634 4.4003138c.951003 1.9017218 1.426505 4.1262378 1.426505 6.6726933 0 2.5467404-.475502 4.7709715-1.426505 6.6729782-.951004 1.9017219-2.296882 3.3686831-4.037634 4.4000289-1.740752 1.0316307-3.755295 1.5473036-6.044199 1.5473036-2.288619 0-4.303447-.5156729-6.044199-1.5473036zm11.604919-4.0857818c1.289468-1.5957369 1.934201-3.924812 1.934201-6.9872253 0-2.9655465-.660973-5.2624277-1.982634-6.8903586s-3.158995-2.4418964-5.512287-2.4418964c-2.385486 0-4.239059.8139655-5.56072 2.4418964s-1.982349 3.9248121-1.982349 6.8903586c0 3.0624133.652711 5.3914884 1.958132 6.9872253 1.305707 1.595737 3.167257 2.393463 5.584937 2.393463s4.271253-.797726 5.56072-2.393463z"/><path d="m158.915857 19.7799018v15.2798724h-3.916835v-15.0864238c0-2.2564251-.451285-3.9085727-1.353855-4.9561579s-2.320812-1.5715203-4.255013-1.5715203c-2.256425 0-4.06185.693167-5.415705 2.079216-1.353855 1.3860489-2.030783 3.2558618-2.030783 5.6091536v13.9257324h-3.91655v-17.5041035c0-2.5142615-.12906-4.786926-.386897-6.8177085h3.723101l.386898 4.3518804c.741315-1.5797825 1.853573-2.7965996 3.336489-3.6507362 1.482915-.8544216 3.175234-1.2814899 5.076956-1.2814899 5.834796 0 8.752194 3.2074284 8.752194 9.6222853z"/><path d="m185.630847 33.319022c-2.401725-1.4182429-4.247891-3.4572876-5.535648-6.1165644-1.290607-2.6595616-1.934486-5.7946249-1.934486-9.404905 0-3.6105649.643879-6.7293888 1.934486-9.35647159 1.287757-2.62708276 3.133923-4.64988805 5.535648-6.06841587 2.401726-1.41824292 5.230804-2.12764929 8.487236-2.12764929 2.384631 0 4.56983.36268044 6.552749 1.08804133 1.98007.72536088 3.69803 1.81340221 5.148182 3.26383907l-1.498585 3.04645873c-1.643886-1.41852782-3.264979-2.4339191-4.860431-3.04645873s-3.358996-.91852454-5.293482-.91852454c-3.772105 0-6.69805 1.22479436-8.777835 3.67466798-2.079786 2.44987362-3.11683 5.93137791-3.11683 10.44451291 0 4.545329 1.031346 8.0507651 3.094037 10.5168782 2.062692 2.466113 4.997184 3.6991695 8.800628 3.6991695 1.934486 0 3.69803-.3062698 5.293482-.9188094 1.595452-.6125397 3.216545-1.6279309 4.860431-3.0461739l1.498585 3.0461739c-1.450152 1.4507217-3.168112 2.5384782-5.148182 3.263839-1.982919.7253609-4.168118 1.0880414-6.552749 1.0880414-3.256432 0-6.08551-.7091215-8.487236-2.1276493z"/></g><g fill="#f2f2f2" fill-rule="nonzero" transform="translate(683.970025 292.181215)"><path d="m.10947429 20.3655834 1.52334352-19.36893462h4.27110005l-1.27858915 15.91416332h8.65071269l-.2720028 3.4547713z"/><path d="m15.3163023 20.3655834 1.0881712-13.79215735h4.1077702l-1.0881712 13.79215735zm1.4145104-20.26668789h4.4070212l-.2992511 3.86301581h-4.4070212z"/><path d="m21.9540024 18.8965763 1.3329256-2.8562691c.7616718.5258933 1.5778402.9293293 2.4483451 1.2104683.870505.2811389 1.7410099.4217084 2.6115148.4217084.7616717 0 1.3239496-.1088332 1.6866734-.3264995.3627237-.2176663.5440054-.5077811.5440054-.8705049 0-.3808359-.213018-.680087-.6392144-.8977533-.4261964-.217506-1.1199075-.4713966-2.0811335-.7616717-.9974502-.2720027-1.8136186-.5440055-2.4483451-.8160082-.6347265-.272163-1.1833802-.675599-1.6458009-1.2106285-.4624206-.5350296-.6937111-1.2287407-.6937111-2.0811335 0-.88861705.2494026-1.66840095.7482079-2.33951199.4986449-.67095076 1.2059803-1.19684408 2.1218457-1.57767996s1.963164-.5714141 3.1420563-.5714141c1.0336745 0 2.0447488.15419365 3.0330628.46258095.9884743.30822702 1.8181067.72544747 2.4892177 1.25134079l-1.3058375 2.74759621c-.6709507-.489669-1.3782861-.86152895-2.1218457-1.11541954-.7435596-.25389058-1.4690071-.38083588-2.1763424-.38083588-.7435596 0-1.3056772.10883315-1.6865131.32649945-.3808359.21750602-.5712538.51675707-.5712538.89759297 0 .3991083.2266422.7164716.6800869.95225.4532845.2357784 1.1425077.4805328 2.067349.7344234.9976105.2901149 1.8091307.5712538 2.434721.8432566.6257505.272163 1.169756.675599 1.6323369 1.2106285.4624207.5350295.6937112 1.2287407.6937112 2.0811334 0 1.360174-.5396778 2.4255848-1.6187128 3.1963928s-2.5344179 1.1561318-4.3661487 1.1561318c-2.3576242 0-4.4613577-.5622779-6.3112007-1.6866734z"/><path d="m41.8941909 15.0064724c-.0543365.7616718.0996969 1.3239497.4624206 1.6866734.3627238.3627238.861529.5440055 1.4962555.5440055.4170601 0 .8796411-.0724486 1.3874223-.217506l-.272163 3.1827685c-.6166144.2538906-1.4145104.3808359-2.3938485.3808359-1.5597281 0-2.7520842-.4170602-3.5772286-1.2513408s-1.2377166-2.0130125-1.2377166-3.5365164c0-.308227.0089759-.5440054.0270881-.7073353l.4353326-5.44069574h-2.6115148l.2447544-3.07393541h2.6115147l.2449147-3.23726527 4.216443-1.33292558-.3535875 4.57019085h3.509268l-.2447544 3.07393541h-3.509268z"/><path d="m46.2739638 18.8965763 1.3329255-2.8562691c.7618321.5258933 1.5778403.9293293 2.4483452 1.2104683.8705049.2811389 1.7410098.4217084 2.6115147.4217084.7618321 0 1.3239497-.1088332 1.6866734-.3264995.3627238-.2176663.5441658-.5077811.5441658-.8705049 0-.3808359-.2131784-.680087-.6393748-.8977533-.4261963-.217506-1.1199075-.4713966-2.0811334-.7616717-.9974502-.2720027-1.8134584-.5440055-2.4481849-.8160082-.6348867-.272163-1.1833801-.675599-1.6458008-1.2106285-.462581-.5350296-.6937112-1.2287407-.6937112-2.0811335 0-.88861705.2492424-1.66840095.7480476-2.33951199.498645-.67095076 1.2059803-1.19684408 2.1218457-1.57767996s1.9631641-.5714141 3.1420563-.5714141c1.0336745 0 2.0447489.15419365 3.0332232.46258095.988314.30822702 1.8181066.72544747 2.4890574 1.25134079l-1.3056773 2.74759621c-.671111-.489669-1.3784463-.86152895-2.1220059-1.11541954-.7435597-.25389058-1.4690071-.38083588-2.1761822-.38083588-.7435596 0-1.3058375.10883315-1.6866734.32649945-.3808358.21750602-.5712538.51675707-.5712538.89759297 0 .3991083.2266422.7164716.680087.95225.4534447.2357784 1.1425076.4805328 2.0675093.7344234.9974502.2901149 1.8089704.5712538 2.4347209.8432566.6255903.272163 1.169756.675599 1.6321767 1.2106285s.6937111 1.2287407.6937111 2.0811334c0 1.360174-.5395175 2.4255848-1.6187127 3.1963928-1.079035.770808-2.5344179 1.1561318-4.3661488 1.1561318-2.3576241 0-4.4613577-.5622779-6.3112006-1.6866734z"/><path d="m69.124918.99664878h7.7258714c1.9949004 0 3.5501405.4806931 4.6653998 1.44175873 1.1154195.96122592 1.6730492 2.28517557 1.6730492 3.97184896 0 1.6865131-.5622779 3.01495072-1.6866734 3.98531283-1.1243955.9702019-2.6749874 1.4553829-4.6517756 1.4553829h-5.4950322v8.5146312h-2.2308392zm7.5354534 9.00446052c1.4327828 0 2.5118178-.30838734 3.2372653-.92500167.7254475-.61661432 1.0881712-1.50523137 1.0881712-2.66585116 0-1.16078007-.3627237-2.04490916-1.0881712-2.65238727-.7254475-.60763839-1.8044825-.91137745-3.2372653-.91137745h-5.3046142v7.15461755z"/><path d="m98.1784001 6.6822592v13.6833242h-2.1763424v-2.4754332c-.3989481.8523927-1.0019382 1.5097193-1.8089705 1.97214-.8070322.4625809-1.7454977.6937111-2.8155568.6937111-1.2151165 0-2.2805273-.2901148-3.1963927-.8705049-.9158655-.5802297-1.6232008-1.4008862-2.1218457-2.4619693-.4988053-1.0609229-.7482079-2.2986395-.7482079-3.7131498 0-1.4146707.2538906-2.6615235.7616717-3.74055852.5079415-1.07903499 1.2197648-1.91780358 2.1356302-2.51630576.9157051-.59850218 1.97214-.89775327 3.1691444-.89775327 1.0700591 0 2.0040366.23577845 2.8019327.70733533.7980563.47155689 1.4055344 1.13353171 1.8225946 1.9857642v-2.36660008zm-3.2643534 10.6773494c.7254475-.9158654 1.088011-2.2170547 1.088011-3.9037281 0-1.6866733-.3625635-2.9833746-1.088011-3.89010384-.7254474-.90672919-1.7592822-1.36017394-3.1011837-1.36017394-1.3420618 0-2.3895208.46706892-3.1420563 1.40104648-.7526958.9339776-1.1290438 2.2351668-1.1290438 3.9037281 0 1.6684009.37186 2.9561263 1.1154196 3.8628555s1.7953463 1.3601739 3.1556805 1.3601739c1.3419015 0 2.3757363-.4579327 3.1011837-1.3737981z"/><path d="m114.636569 6.6822592v13.574491c0 2.031285-.521405 3.5682527-1.564216 4.6110634s-2.579779 1.5642161-4.610903 1.5642161c-2.085622 0-3.881128-.4715569-5.38636-1.4146707l.380836-1.7953462c.870505.489669 1.691162.8432565 2.46197 1.0609228.770647.2176663 1.618552.3264995 2.543554.3264995 1.323789 0 2.321239-.3490996 2.99235-1.047459.670951-.6981991 1.006587-1.7363615 1.006587-3.1148079v-3.237105c-.417221.8705049-1.029347 1.5459436-1.836379 2.0266367-.807033.4805329-1.76361.7207993-2.869894.7207993-1.197004 0-2.262415-.2809787-3.196392-.8432566-.933978-.5621176-1.654937-1.3601739-2.162719-2.3938484-.507781-1.0338348-.761671-2.2217029-.761671-3.5637647s.25389-2.52993.761671-3.56360448c.507782-1.03383477 1.228741-1.83173082 2.162719-2.39400871.933977-.56211761 1.999388-.84325656 3.196392-.84325656 1.088172 0 2.035773.23577845 2.842806.70733533.807032.47155689 1.418998 1.13353171 1.836218 1.9857642v-2.36660008zm-3.332474 10.1060956c.752695-.8796411 1.129043-2.0901094 1.129043-3.6317253 0-1.5414557-.376348-2.7520842-1.129043-3.63156509-.752536-.87964112-1.790859-1.31946169-3.114808-1.31946169-1.342062 0-2.398337.43982057-3.169145 1.31946169-.770808.87948089-1.156131 2.09010939-1.156131 3.63156509 0 1.5416159.385323 2.7520842 1.156131 3.6317253s1.827083 1.3193014 3.169145 1.3193014c1.323949 0 2.362272-.4396603 3.114808-1.3193014z"/><path d="m130.333066 13.4558805h-10.038135c.018112 1.7410099.421708 3.0558233 1.210628 3.9446006.788921.8886171 1.935916 1.3329256 3.441148 1.3329256 1.595952 0 3.064959-.5350295 4.407021-1.6050886l.734584 1.6050886c-.598503.5622779-1.364823 1.0065864-2.2988 1.3329256-.933978.3264995-1.890555.489669-2.869893.489669-2.140119 0-3.817656-.6302385-5.032772-1.8905552-1.215117-1.260477-1.822595-2.9878626-1.822595-5.1823172 0-1.3963982.272003-2.6342751.816169-3.71331012.544005-1.07903499 1.305677-1.91780358 2.285015-2.51630576s2.094757-.89775327 3.346098-.89775327c1.813459 0 3.237266.59401422 4.27094 1.78188236 1.033675 1.18786815 1.550592 2.82453279 1.550592 4.91015419zm-8.582752-4.35252451c-.716311.6890629-1.174244 1.65942501-1.373798 2.91076581h7.970625c-.108672-1.2875651-.48502-2.26690312-1.128883-2.93801417-.643863-.67095075-1.536968-1.00658641-2.679636-1.00658641-1.142507 0-2.071997.34461159-2.788308 1.03383477z"/><path d="m132.835747 18.7877432.734584-1.6321767c.74356.58039 1.496095.9974502 2.257927 1.2513408.761672.2538906 1.614065.3808359 2.556538.3808359 1.033834 0 1.819228-.1767938 2.352975-.5303813.535351-.3535875.803026-.866017.803026-1.5369677 0-.5441658-.181122-.9793381-.543365-1.3058375-.363845-.3264995-.961706-.5803901-1.795186-.7616718l-2.313065-.5441657c-1.142668-.2538906-2.026797-.7071751-2.652387-1.360174-.625751-.6528386-.938466-1.4326225-.938466-2.339512 0-1.19684406.480533-2.17169415 1.441759-2.92438998.961226-.75253555 2.230679-1.12888347 3.808199-1.12888347.961706 0 1.868917.15419366 2.720027.46242067.852713.30838731 1.569185.75269584 2.149415 1.33308587l-.734103 1.60492831c-1.287084-1.07005906-2.665531-1.60492831-4.135339-1.60492831-.979018 0-1.736202.18576969-2.271231.55762964-.53503.37169967-.802544.89310502-.802544 1.56421607 0 .5621176.167817 1.0065864.503293 1.3329256.335475.3264994.874993.58039 1.618552.7616717l2.312745.5712539c1.269453.2902751 2.211925.7390716 2.829021 1.34671.617095.6074781.924841 1.4008862.924841 2.3802243 0 1.1788922-.480854 2.1218457-1.44256 2.829181-.960104.7073353-2.266423 1.0609228-3.917353 1.0609228-2.302646 0-4.125241-.5893659-5.467303-1.7682581z"/><path d="m153.917963.99664878h12.785891v1.65942503l-9.084923 17.70950959h-2.39465l9.032029-17.49184329h-10.338347z"/><path d="m173.015856 17.5636507v1.9859245c0 .7616718-.126624 1.4598709-.381477 2.0945973-.253249.6347265-.679606 1.2513408-1.277467 1.849843l-1.035437-.7889201c.708457-.8160082 1.107565-1.5959524 1.197324-2.339512h-1.304715v-2.8019327z"/><path d="m188.807081 12.1909156c.698841.8434168 1.048261 1.8543309 1.048261 3.0332231 0 1.6502888-.626712 2.9516384-1.878534 3.9037281-1.250219.9520897-2.938014 1.4281345-5.058578 1.4281345-2.122166 0-3.809961-.4760448-5.06018-1.4281345-1.251822-.9520897-1.876931-2.2534393-1.876931-3.9037281 0-1.1788922.357434-2.1944545 1.073906-3.0468473.716471-.8523928 1.700618-1.4417587 2.95244-1.7682582-1.16046-.3444513-2.050039-.91121715-2.667134-1.70013727-.615492-.78892012-.924841-1.71840971-.924841-2.78830849 0-1.03383478.272483-1.93607601.815848-2.70688399.544967-.77064769 1.311127-1.36914987 2.300082-1.79534625.987352-.42619638 2.117357-.63937472 3.38681-.63937472s2.397856.21317834 3.386811.63937472c.987352.42619638 1.753512 1.02469856 2.298479 1.79534625.543365.77080798.815848 1.67304921.815848 2.70688399 0 1.06989878-.312555 1.99938837-.939267 2.78830849-.625109.78892012-1.500262 1.35568597-2.623856 1.70013727 1.269452.3446116 2.251996.9386258 2.950836 1.7818824zm-9.004781-3.59085282c.770969.64386269 1.809612 1.03832275 3.11593 1.18338018 1.304716-.14505743 2.343359-.53951749 3.114327-1.18338018.770969-.64386268 1.155651-1.48263127 1.155651-2.51630576 0-1.07005906-.376668-1.91331562-1.128402-2.52992994-.753337-.61661432-1.799995-.92500163-3.141576-.92500163-1.343183 0-2.389841.30838731-3.143178.92500163-.751734.61661432-1.128403 1.45987088-1.128403 2.52992994 0 1.03367449.384683 1.87244308 1.155651 2.51630576zm6.624557 9.18125422c.815848-.6166143 1.224574-1.5143676 1.224574-2.6932598 0-1.0698988-.431166-1.9267795-1.291893-2.5706422-.862331-.6438627-2.009967-1.0383227-3.441308-1.1833802-1.432943.1450575-2.580579.5395175-3.441307 1.1833802-.86233.6438627-1.293496 1.5007434-1.293496 2.5706422 0 1.1788922.408726 2.0766455 1.224574 2.6932598s1.985924.9248414 3.510229.9248414c1.522703 0 2.692779-.3082271 3.508627-.9248414z"/><path d="m195.622377 17.5636507v1.9859245c0 .7616718-.128228 1.4598709-.381477 2.0945973-.25325.6347265-.679606 1.2513408-1.27907 1.849843l-1.033835-.7889201c.708457-.8160082 1.107566-1.5959524 1.197325-2.339512h-1.306318v-2.8019327z"/><path d="m210.339696 3.22732763c1.26785 1.63217667 1.902577 3.95357653 1.902577 6.96419957 0 3.2824655-.657167 5.8351558-1.971499 7.6577504-1.314333 1.8225946-3.151193 2.7339721-5.508977 2.7339721-1.105963 0-2.189486-.2085301-3.250569-.6257505-1.061083-.4170602-1.998747-1.0064262-2.816198-1.7680979l.871947-1.7139218c.924842.7799442 1.803201 1.3465498 2.638283 1.7002976.833479.3535875 1.676575.5303813 2.529288.5303813 1.668562 0 2.960454-.7435596 3.877282-2.2306789.915224-1.4871192 1.373637-3.5727406 1.373637-6.2568642v-.35358755c-.416739 1.01556235-1.097948 1.81810665-2.040421 2.40747265-.944075.5895262-2.02279.8841291-3.237746.8841291-1.178091 0-2.221543-.2583786-3.128753-.775296-.905607-.5167571-1.614064-1.2422046-2.120563-2.1761821-.508102-.93413786-.762954-1.99954868-.762954-3.19655303 0-1.19684408.267675-2.26690314.803025-3.21001692.53535-.94295348 1.274262-1.68202514 2.216734-2.21705467.944076-.53502953 2.013173-.8025443 3.210498-.8025443 2.340153 0 4.143353.81616848 5.414409 2.44834515zm-2.176663 6.85536647c.796614-.79805638 1.195722-1.83173087 1.195722-3.10118381 0-1.28772536-.399108-2.33053607-1.195722-3.12843212-.798217-.79805633-1.841668-1.19700436-3.128753-1.19700436-1.232587 0-2.231159.39446006-2.992511 1.18338018-.761351.78892012-1.142828 1.83621879-1.142828 3.1420563 0 1.28756508.381477 2.32588782 1.142828 3.11480791.761352.7889202 1.767938 1.1833802 3.01976 1.1833802 1.269453 0 2.303287-.3991083 3.101504-1.1970043z"/></g><path d="m17.8381448 46.9715784h11.4351924v5.0258027h-28.91585333v-5.0258027h11.43519243v-39.40433576l-10.63396507 6.77374006v-5.75407418l13.25608567-8.44915063h3.4233479z" fill="#f2f2f2" fill-rule="nonzero" transform="translate(21.524072 376.769072)"/><path d="m35.1591611 47.829883v5.0258027h-33.35886717v-4.5159698l18.13640567-20.1027815c2.4277146-2.719109 4.2001136-5.1712853 5.3167679-7.3565289 1.1170835-2.1848144 1.6754107-4.3700579 1.6754107-6.5553015 0-2.8645916-.8256891-5.06185144-2.476638-6.59135026-1.6509489-1.52992798-4.0057077-2.29467739-7.0651345-2.29467739-4.9528467 0-9.85677016 1.99083755-14.71262852 5.97294185l-2.25819944-4.58892566c2.03976092-1.94234334 4.61295815-3.4958747 7.72087917-4.66145237 3.10749189-1.16557766 6.23944539-1.74793734 9.39586059-1.74793734 4.7584408 0 8.5216774 1.22608814 11.2897098 3.67826442 2.7676032 2.45217629 4.1516194 5.76609041 4.1516194 9.94174235 0 2.9620092-.667761 5.8150138-2.003283 8.5585845-1.3350928 2.7431415-3.5568143 5.8145846-6.6643061 9.2134709l-14.7855845 16.024118z" fill="#f2f2f2" fill-rule="nonzero" transform="translate(113.15712 375.910768)"/><path d="m32.1649655 30.7131432c1.6024547 2.1367493 2.403682 4.8318258 2.403682 8.0848003 0 4.5159698-1.5294988 8.0727841-4.5884964 10.6708722-3.0594268 2.5976589-7.2110463 3.8967029-12.4548583 3.8967029-3.3508212 0-6.5677469-.5587563-9.65077711-1.6754106-3.08345933-1.1166543-5.69356366-2.6950765-7.82988385-4.7344083l2.33072618-4.5884964c4.806935 3.9816751 9.80827598 5.9725126 15.00402298 5.9725126 3.6902807 0 6.494791-.825689 8.4126727-2.4766379 1.9178817-1.650949 2.8770371-4.0786636 2.8770371-7.283573 0-6.3608955-3.9816751-9.5413433-11.9450254-9.5413433h-5.9729418v-5.0258026h4.8073642c3.8361924 0 6.77374-.8497216 8.8130718-2.5491647 2.0393317-1.6994432 3.0594268-4.1275869 3.0594268-7.283573 0-2.8165266-.8377053-4.97730847-2.513116-6.48234561-1.6749814-1.50546629-4.0421855-2.25819944-7.1016123-2.25819944-4.9528468 0-9.85677025 1.99083755-14.71262861 5.97294185l-2.25819944-4.58892566c2.08825513-1.99083756 4.6494361-3.55681433 7.68440122-4.69793031 3.03496513-1.14111599 6.20339663-1.7114594 9.50529443-1.7114594 4.6614524 0 8.388211 1.18961019 11.180276 3.56883059 2.7920649 2.37922039 4.1880973 5.58412982 4.1880973 9.61429918 0 2.9620092-.7287006 5.5596681-2.1852435 7.7934059-1.456543 2.2337377-3.4718422 3.8361925-6.0454686 4.8073641 3.0589977.8737541 5.390153 2.3792204 6.9921786 4.5155406z" fill="#f2f2f2" fill-rule="nonzero" transform="translate(210.490122 375.910768)"/><path d="m37.9113149 35.7548245v4.9528468h-7.8663618v11.2897098h-5.9725127v-11.2897098h-23.89005067v-4.5159697l24.98267247-36.05394371h4.8798909v35.61706661zm-31.53797398 0h17.69909948v-25.4925054z" fill="#f2f2f2" fill-rule="nonzero" transform="translate(344.333123 377.543534)"/><path d="m27.0614862 21.5151218c2.4521763 1.3840162 4.3340092 3.3143433 5.6450695 5.7905521 1.3110603 2.4766379 1.9663758 5.3412296 1.9663758 8.5946332 0 3.2534037-.7162552 6.142457-2.1487656 8.6675892-1.4320812 2.5251322-3.4718421 4.4794918-6.1179953 5.863508-2.6465822 1.383587-5.7420578 2.0758097-9.2868559 2.0758097-3.1559861 0-6.2634779-.5707726-9.32290473-1.7118886-3.05899765-1.1411159-5.63262403-2.7070927-7.72045001-4.6979303l2.25777029-4.5884964c4.80736415 3.9816751 9.73574925 5.9725126 14.78558445 5.9725126 3.6422156 0 6.494791-1.0316821 8.5585845-3.0954756 2.0633643-2.0637934 3.0954756-4.8678746 3.0954756-8.4126727 0-3.4473804-1.0196659-6.2274291-3.0589977-8.3397168-2.0397609-2.1122876-4.7588699-3.1684314-8.1577562-3.1684314-4.9528468 0-8.91048936 2.0152992-11.87249858 6.0454685h-4.15161943v-30.37282541h31.10109691v4.95284678h-25.12858424v18.50075603c2.86502084-2.7680324 6.53126894-4.1520486 10.99831534-4.1520486 3.2534036 0 6.105979.6922227 8.5581553 2.0758097z" fill="#f2f2f2" fill-rule="nonzero" transform="translate(442.786269 377.543534)"/><path d="m28.6326128 22.3734264c2.4521763 1.3840162 4.3580417 3.3263595 5.7175962 5.82703s2.0393318 5.3536751 2.0393318 8.5581554c0 3.2049094-.7162552 6.0699302-2.1487656 8.5946332-1.4320813 2.5251322-3.4109026 4.5039535-5.9360347 5.9364639-2.5247031 1.4320813-5.3897239 2.1483365-8.5946333 2.1483365-6.2639071 0-11.09530378-2.1848144-14.49419005-6.5553015-3.39931543-4.370058-5.09875857-10.5854709-5.09875857-18.6458095 0-5.82703.78921109-10.828371 2.36720413-15.004023 1.57799303-4.1760811 3.86022501-7.35652885 6.84669592-9.5417724 2.98604177-2.18524355 6.56731777-3.27743617 10.74339887-3.27743617 3.0105034 0 5.9360347.55832715 8.7765938 1.67498145 2.8405592 1.11708346 5.3292134 2.69507649 7.4655336 4.73440826l-2.2577703 4.58892566c-2.4277146-2.03976095-4.7584408-3.5447981-6.9921786-4.51596977-2.2337377-.97117167-4.5159697-1.45697208-6.8466959-1.45697208-4.4670463 0-7.9388885 1.99083755-10.41552648 5.97294185-2.47620881 3.9816751-3.71474237 9.5653758-3.71474237 16.7519603v1.0926218c1.11708345-2.7676033 2.93797669-4.9528468 5.46267975-6.5553015 2.5251321-1.6024547 5.4141855-2.4036821 8.6675891-2.4036821 3.1564153 0 5.9604964.6922227 8.4126727 2.0758097zm-1.2016264 22.8708139c2.0393317-2.1122876 3.0589976-4.9163688 3.0589976-8.4126726 0-3.4473805-1.0321113-6.2274292-3.0954756-8.3397168-2.0637934-2.1122877-4.7464245-3.1684315-8.0483224-3.1684315-3.3993154 0-6.1669186 1.0681601-8.303668 3.2049094-2.13632016 2.1363202-3.20448025 4.9043526-3.20448025 8.3032389 0 3.4473804 1.06816009 6.2394454 3.20448025 8.3761947 2.1367494 2.1363202 4.9288143 3.2049094 8.3761948 3.2049094 3.3018978 0 5.9725126-1.0561438 8.0122736-3.1684315z" fill="#f2f2f2" fill-rule="nonzero" transform="translate(539.405045 376.685229)"/><path d="m.06008132.13775789h34.23305048v4.44301384l-24.32735691 47.41660937h-6.40938972l24.18144513-46.83382053h-27.67774898z" fill="#f2f2f2" fill-rule="nonzero" transform="translate(678.757195 376.512457)"/><path d="m34.6622027 30.9684888c1.8693875 2.2577703 2.8040812 4.9648631 2.8040812 8.1208491 0 4.4189814-1.6749814 7.9028398-5.0253735 10.4520045-3.3508212 2.5495939-7.8663618 3.8241762-13.5474801 3.8241762-5.6815474 0-10.19708794-1.2745823-13.54748-3.8241762-3.35082122-2.5491647-5.02580268-6.0330231-5.02580268-10.4520045 0-3.155986.95872626-5.875095 2.87703707-8.157327 1.91788167-2.282232 4.55201853-3.8606542 7.90241061-4.7344083-3.10749187-.9226774-5.48671227-2.44016-7.1376612-4.5524477-1.65094892-2.1122876-2.47663796-4.6005127-2.47663796-7.4655335 0-2.7676032.72870062-5.18373073 2.18524355-7.24709502 1.45654293-2.06379345 3.50832011-3.66624817 6.15447324-4.80736415 2.64658227-1.14111599 5.66910197-1.7114594 9.06841737-1.7114594 3.3988863 0 6.421406.57034341 9.0679883 1.7114594 2.6461531 1.14111598 4.6979303 2.7435707 6.1544733 4.80736415 1.456972 2.06336429 2.1852435 4.47949182 2.1852435 7.24709502 0 2.8650208-.8377053 5.3532459-2.5131159 7.4655335-1.6749815 2.1122877-4.0177239 3.6297703-7.0286565 4.5524477 3.3993154.9226775 6.0334523 2.5126868 7.9028397 4.7708862zm-24.1084891-9.6147283c2.0633642 1.7239048 4.8434129 2.7800487 8.3397167 3.1684315 3.4958747-.3883828 6.2759234-1.4445267 8.3397168-3.1684315 2.0633643-1.7234756 3.0954756-3.9692297 3.0954756-6.7372621 0-2.8645916-1.0076496-5.12279105-3.0229488-6.77373998-2.0148701-1.65094892-4.8193804-2.47620881-8.4122436-2.47620881-3.5932922 0-6.3978026.82525989-8.4126726 2.47620881-2.01529928 1.65094893-3.0229489 3.90914838-3.0229489 6.77373998 0 2.7680324 1.0321113 5.0137865 3.0959048 6.7372621zm17.7355774 24.5822734c2.1848144-1.650949 3.2774361-4.054631 3.2774361-7.2106171 0-2.8650208-1.1531322-5.1592691-3.4598259-6.8831739-2.3062645-1.7239048-5.3777075-2.7800486-9.2134709-3.1684315-3.8361924.3883829-6.9076355 1.4445267-9.2139 3.1684315-2.30669365 1.7239048-3.4598259 4.0181531-3.4598259 6.8831739 0 3.1559861 1.09262177 5.5596681 3.27786532 7.2106171 2.18481438 1.6509489 5.31676798 2.4766379 9.39586058 2.4766379 4.0786636 0 7.2106171-.825689 9.3958607-2.4766379z" fill="#f2f2f2" fill-rule="nonzero" transform="translate(773.608278 376.236614)"/><path d="m31.3560134 6.96900432c3.3988862 4.37005798 5.0987585 10.58547078 5.0987585 18.64580948 0 8.7890393-1.7603827 15.6232898-5.2807191 20.5031806-3.5203364 4.8803201-8.4367052 7.320051-14.7495357 7.320051-2.9620092 0-5.8630788-.5583272-8.70363793-1.6749815-2.84055913-1.1170835-5.35367504-2.6950765-7.53848944-4.7344083l2.33072618-4.5884964c2.47620882 2.0878259 4.83139668 3.6053085 7.06513445 4.5520185 2.23330864.94671 4.49150804 1.4204941 6.77374004 1.4204941 4.4670464 0 7.9268723-1.9908375 10.3790485-5.9725126 2.4521763-3.9821043 3.6782645-9.565805 3.6782645-16.7523895v-.9471392c-1.1170835 2.7195382-2.9379767 4.8678747-5.4626798 6.4462969-2.5251321 1.577993-5.4141855 2.3672041-8.6675891 2.3672041-3.1564152 0-5.9484801-.6922227-8.37619475-2.0758097-2.42771461-1.3840162-4.32156374-3.3263596-5.68111825-5.8270301s-2.03933177-5.353675-2.03933177-8.5581553c0-3.2049094.7162552-6.0699302 2.14833645-8.59463325 1.43251041-2.52513218 3.4113317-4.50395347 5.93646388-5.93646387 2.52470304-1.43208125 5.38972384-2.14833645 8.59463324-2.14833645 6.2639071 0 11.0953038 2.18481439 14.4941901 6.55530149zm-5.8270301 18.35441508c2.1367494-2.1363202 3.2049095-4.9043526 3.2049095-8.3032389 0-3.4473805-1.0681601-6.2394454-3.2049095-8.37619472-2.1363202-2.13632019-4.9283851-3.20490943-8.3757656-3.20490943-3.3018978 0-5.9729418 1.05614383-8.01227355 3.16843149-2.03933176 2.11228766-3.05899765 4.91636886-3.05899765 8.41267266 0 3.4473805 1.01966589 6.2274292 3.05899765 8.3397168 2.03933175 2.1122877 4.73440825 3.1684315 8.08480035 3.1684315 3.3993154 0 6.1669186-1.0681601 8.3032388-3.2049094z" fill="#f2f2f2" fill-rule="nonzero" transform="translate(867.854354 375.654152)"/><path d="m330.093135.33214542v84.43190468-42.5518783h-329.66215607v42.5518783" stroke="#000" stroke-width="2.538347" transform="translate(131.785126 139.982935)"/><path d="m.10801477.42233775h329.31542823v42.21595235" stroke="#000" stroke-width="2.538347" transform="translate(461.770246 182.108695)"/><path d="m36.186655 346.60579v15.692843" stroke="#000" stroke-width="2.540394"/><path d="m132.152376 331.426017v30.871702" stroke="#000" stroke-width="2.538347"/><path d="m228.893645 346.60579v15.692843" stroke="#000" stroke-width="2.540394"/><g transform="translate(1221.45577 24.489117)"><path d="m.197608.154988h239.084215v85.099871h-239.084215z" fill="#0083c0"/><path d="m239.281823 85.2548586h-239.08421531v-85.09987082h239.08421531zm-236.54571658-82.56147761v80.02308441h234.00574658v-80.02308441z" fill="#000"/></g><g transform="translate(956.909366 124.770501)"><path d="m.184449.095195h223.163411v52.269131h-223.163411z" fill="#c9177e"/><path d="m223.347859 52.3643259h-223.16341016v-52.26913097h223.16341016zm-220.62506465-49.73066919v47.19220749h218.08488865v-47.19220749z" fill="#000"/></g><g transform="translate(1231.923745 124.770501)"><path d="m.183618.095195h222.158079v52.269131h-222.158079z" fill="#c9177e"/><path d="m222.341696 52.3643259h-222.15807809v-52.26913097h222.15807809zm-219.61932129-49.73066919v47.19220749h217.08147629v-47.19220749z" fill="#000"/></g><path d="m91.4241325.12672749v8.67595862h-91.3476086v8.67108449" stroke="#000" stroke-width="2.539424" transform="translate(1252.516016 177.005152)"/><g transform="translate(1504.487683 124.770501)"><path d="m.182671.095195h221.012609v52.269131h-221.012609z" fill="#c9177e"/><path d="m221.19528 52.3643259h-221.01260884v-52.26913097h221.01260884zm-218.47425033-49.73066919v47.19220749h215.93589233v-47.19220749z" fill="#000"/></g><g transform="translate(1018.734446 194.392443)"><path d="m.035471.089728h42.916712v49.26713h-42.916712z" fill="#00a88a"/><path d="m42.9521838 49.3568579h-42.91671231v-49.26713035h42.91671231zm-40.37825665-46.72872807v44.19032577h37.83980095v-44.19032577z" fill="#000"/></g><path d="m19.5454361 18.6632185c.9737513 1.298422 1.4606269 2.9361183 1.4606269 4.9128281 0 2.7441845-.9294187 4.9055264-2.7882562 6.4842865-1.8590982 1.5784993-4.3818807 2.3678794-7.5683475 2.3678794-2.03616765 0-3.99097204-.3395352-5.86441318-1.0180839-1.87370191-.6785486-3.45976385-1.6376963-4.75792503-2.8769212l1.41629437-2.7882563c2.92099306 2.4195138 5.96011931 3.6292707 9.11737874 3.6292707 2.2424444 0 3.9466395-.5017401 5.1120638-1.5049595 1.1654244-1.0032194 1.7482669-2.4784499 1.7482669-4.4259525 0-3.8652762-2.4195137-5.7979144-7.2585412-5.7979144h-3.62953146v-3.0539906h2.92125384c2.33110942 0 4.11614632-.5163438 5.35537122-1.5490313 1.239225-1.0326875 1.8590983-2.5081788 1.8590983-4.4259525 0-1.71149696-.5090419-3.02452258-1.5271257-3.93907688-1.0178231-.91481507-2.4562837-1.37222261-4.315382-1.37222261-3.00965814 0-5.9895874 1.20975688-8.94030934 3.62953142l-1.37222261-2.78851699c1.26895386-1.20975688 2.82528692-2.16134189 4.66952073-2.85475502 1.84423381-.69341314 3.7695701-1.03998932 5.77600882-1.03998932 2.8325888 0 5.0971994.72288124 6.7938319 2.16864372 1.6966326 1.44576248 2.5449488 3.39326503 2.5449488 5.8422469 0 1.79990128-.4428039 3.37840058-1.32789 4.73575878-.8850862 1.3573582-2.1097076 2.3311094-3.6736032 2.9212538 1.8588374.5309474 3.2753926 1.4457625 4.2488831 2.7439237z" fill="#f2f2f2" fill-rule="nonzero" transform="translate(1028.654902 202.599599)"/><g transform="translate(1078.488158 194.392443)"><path d="m.035471.089728h42.916712v49.26713h-42.916712z" fill="#00a88a"/><path d="m42.9521838 49.3568579h-42.91671231v-49.26713035h42.91671231zm-40.37825665-46.72872807v44.19032577h37.83980095v-44.19032577z" fill="#000"/></g><path d="m22.936251 22.0604515v3.0096581h-4.7800913v6.8603307h-3.6292707v-6.8603307h-14.51708251v-2.7441844l15.18102761-21.9086215h2.9653256v21.6431478zm-19.16443702 0h10.75507502v-15.49083387z" fill="#f2f2f2" fill-rule="nonzero" transform="translate(1089.451732 203.121158)"/><g transform="translate(1138.52553 194.392443)"><path d="m.035471.089728h42.916712v49.26713h-42.916712z" fill="#00a88a"/><path d="m42.9521838 49.3568579h-42.91671231v-49.26713035h42.91671231zm-40.37825665-46.72872807v44.19032577h37.83980095v-44.19032577z" fill="#000"/></g><path d="m16.4136394 13.9290806c1.4900951.8410145 2.6336139 2.0140014 3.4302958 3.5187001.7966819 1.5049595 1.1948924 3.2456637 1.1948924 5.2226344s-.4352412 3.7325394-1.3057238 5.2669669c-.8702217 1.5344276-2.1097075 2.7220182-3.7176749 3.5630326-1.6082282.8407537-3.489232 1.2613913-5.643272 1.2613913-1.9177737 0-3.80607928-.346837-5.66517753-1.0402501-1.85883747-.6934131-3.42273314-1.6449981-4.69142622-2.854755l1.37196183-2.7882562c2.92125384 2.4195137 5.91604755 3.6292706 8.98464192 3.6292706 2.213237 0 3.9466395-.6269143 5.2007289-1.8810037 1.2538286-1.2540895 1.8810037-2.9580238 1.8810037-5.1120639 0-2.094843-.6196125-3.7841737-1.8588374-5.0677312-1.2394858-1.2835576-2.8917858-1.9253363-4.9571607-1.9253363-3.00965819 0-5.41456828 1.2246213-7.21446955 3.6736031h-2.52278251v-18.45642016h18.89896326v3.00965815h-15.26969262v11.24221151c1.74096506-1.6820289 3.96880576-2.5230433 6.68326132-2.5230433 1.9769707 0 3.7103731.4206376 5.2004681 1.2613912z" fill="#f2f2f2" fill-rule="nonzero" transform="translate(1148.445985 201.599599)"/><g transform="translate(957.360703 194.392443)"><path d="m.035471.089728h42.916712v49.26713h-42.916712z" fill="#00a88a"/><path d="m42.9521838 49.3568579h-42.91671231v-49.26713035h42.91671231zm-40.37816863-46.72872807v44.19032577h37.83971293v-44.19032577z" fill="#000"/></g><path d="m10.8395677 28.5428562h6.948735v3.0539907h-17.57107324v-3.0539907h6.94873503v-23.94452832l-6.46185939 4.11614628v-3.49653379l8.05522316-5.1342301h2.08023944z" fill="#f2f2f2" fill-rule="nonzero" transform="translate(970.410431 203.121158)"/><g transform="translate(1231.099754 194.213333)"><path d="m.035471.089728h42.916712v49.26713h-42.916712z" fill="#00a88a"/><path d="m42.9521838 49.3568579h-42.91671231v-49.26713035h42.91671231zm-40.37816863-46.72872807v44.19032577h37.83971293v-44.19032577z" fill="#000"/></g><path d="m21.3648958 29.0644155v3.0539907h-20.27092509v-2.7441844l11.02080949-12.215702c1.4752306-1.6523 2.5522507-3.142395 3.2307994-4.4702851.6788094-1.3276293 1.0180838-2.6555193 1.0180838-3.98340939 0-1.74070428-.5017401-3.07589618-1.5049595-4.00531492-1.0032194-.92967951-2.4341174-1.39438888-4.2932157-1.39438888-3.0096581 0-5.98958737 1.20975688-8.94030931 3.62953142l-1.37222261-2.78851699c1.23948576-1.18028878 2.80312065-2.12431118 4.691687-2.83258875 1.88830558-.70827758 3.79147559-1.06215559 5.70951002-1.06215559 2.891525 0 5.1783019.74504751 6.8603307 2.23514253 1.6817681 1.49009502 2.5227826 3.50383562 2.5227826 6.04122179 0 1.79990128-.4057732 3.53356448-1.2173195 5.20072888-.8112856 1.6669037-2.1613419 3.5333038-4.0496475 5.5986787l-8.98464189 9.737252z" fill="#f2f2f2" fill-rule="nonzero" transform="translate(1241.784164 202.570441)"/><g transform="translate(1292.473373 194.213333)"><path d="m.035471.089728h42.916712v49.26713h-42.916712z" fill="#00a88a"/><path d="m42.9521838 49.3568579h-42.91671231v-49.26713035h42.91671231zm-40.37825665-46.72872807v44.19032577h37.83980095v-44.19032577z" fill="#000"/></g><path d="m23.0372759 21.726858v3.0096582h-4.7800914v6.8603307h-3.6292706v-6.8603307h-14.51708254v-2.7441845l15.18102754-21.90862143h2.9653256v21.64314773zm-19.16443705 0h10.75507505v-15.4908338z" fill="#f2f2f2" fill-rule="nonzero" transform="translate(1301.574474 203.100332)"/><g fill="#fff" fill-rule="nonzero" transform="translate(974.127869 141.527307)"><path d="m5.47365255 15.5387394v-13.14066544h-5.07689804v-1.43299542h11.85291919v1.43299542h-5.07689802v13.14066544z"/><path d="m21.1342453 10.3380383h-7.553933c.0136476 1.3111421.3173061 2.3005913.9109757 2.9683477.5936695.6677563 1.4568786 1.0040716 2.5896274 1.0040716 1.2009866 0 2.3064402-.4045531 3.3163608-1.2087853l.5527268 1.2087853c-.45037.4240497-1.02698.7554908-1.7298302 1.0040716-.7028501.2437067-1.4227597.3655601-2.1597288.3655601-1.6104139 0-2.8728146-.472791-3.7872021-1.418373-.9143876-.9504562-1.3715814-2.25185-1.3715814-3.9041814 0-1.04793885.2047137-1.97889846.6141409-2.79287884.4094273-.80910626.9826255-1.44274368 1.7195945-1.89116402.7369691-.45329446 1.576295-.67750463 2.5179777-.67750463 1.3647575 0 2.4360922.44842033 3.214004 1.34038686.7779118.89684067 1.1668677 2.12512245 1.1668677 3.69459363zm-6.4587151-3.27541805c-.5390792.52153234-.8836805 1.24777832-1.0338038 2.19336032h5.9981094c-.0818855-.96995267-.3650727-1.70594692-.8495616-2.21285686s-1.156632-.75549078-2.0164293-.75549078c-.8597972 0-1.5592354.25832911-2.0983147.77498732z"/><path d="m29.3842046 5.11784076-.0409427 1.51585569c-.3138943-.10723095-.675555-.16572056-1.0849823-.16572056-.996273 0-1.736654.31194458-2.2211429.93095961-.4844889.62388916-.7267334 1.37937994-.7267334 2.26647234v5.87333156h-1.6581804v-7.40868379c0-1.06743536-.0545903-2.02763977-.1637709-2.8903615h1.576295l.1637709 1.90578642c.2593039-.69700117.675555-1.22828178 1.2487531-1.59871597.5731982-.36556006 1.2282818-.55077715 1.9652509-.55077715.3411894 0 .6550836.03899307.9416827.12185335z"/><path d="m45.9045945 9.07076348v6.46797592h-1.6581804v-6.38511564c0-.96995268-.1671828-1.67182798-.5015484-2.11050005-.3343655-.43867206-.8768567-.65313396-1.6274733-.65313396-.8734448 0-1.5558236.29244804-2.0471363.87734413-.4913127.58977022-.7369691 1.38425407-.7369691 2.39807396v5.87333156h-1.6581804v-6.38511564c0-.95533028-.1705947-1.65720558-.5117841-2.10075178s-.8870924-.66288223-1.637709-.66288223c-.8734448 0-1.5592355.29244804-2.057372.87734413-.4981365.58977022-.7472047 1.38425407-.7472047 2.39807396v5.87333156h-1.6581805v-7.40868379c0-1.06743536-.0545903-2.02763977-.1637709-2.8903615h1.576295l.1637709 1.8034296c.2865991-.65313396.7130858-1.1600439 1.2794602-1.51585569s1.2248699-.53128061 1.9754865-.53128061c.8188545 0 1.4875857.16572056 2.0061936.49228754s.90074.83347692 1.1463963 1.51585569c.3138943-.61414089.7744999-1.1015543 1.381817-1.46711435.6073171-.36068592 1.2931078-.54102888 2.057372-.54102888 2.2791451 0 3.4187176 1.3598834 3.4187176 4.07477607z"/><path d="m60.3369055 14.1252405h3.214004v1.4134989h-8.1271311v-1.4134989h3.214004v-11.07403258l-2.988819 1.90578642v-1.61821251l3.725788-2.37370329h.9621541z"/><path d="m66.396429 5.46877841h2.1085503v2.12512245h-2.1085503zm0 7.95946089h2.1085503v1.4963592c0 .5751478-.095533 1.0966801-.286599 1.5743453-.1910661.4776651-.5117841.945582-.9621541 1.3940023l-.7779118-.5946443c.5322554-.6141409.8325021-1.199037.90074-1.7595624h-.9826254z"/><path d="m76.2226832 15.5387394 1.1463963-14.57366086h3.214004l-.962154 11.97574736h6.5098934l-.2047136 2.5979135z"/><path d="m87.6661752 15.5387394.8188545-10.37703143h3.0911758l-.8188545 10.37703143zm1.0645108-15.25116549h3.3163608l-.225185 2.9049839h-3.3163608z"/><path d="m92.6611877 14.4323109 1.0030968-2.1494931c.5731982.3948049 1.1873391.7018753 1.8424227.9114631.6550836.2144619 1.3101672.3168187 1.9652508.3168187.5731982 0 .996273-.0828603 1.2692246-.2437067.2729515-.1657206.4094272-.3850566.4094272-.6580081 0-.2826998-.160359-.5117841-.481077-.6726305-.320718-.1657206-.8427378-.3558118-1.5660593-.5751478-.7506166-.2047136-1.3647575-.4094273-1.8424227-.6141409-.4776651-.2047136-.8905043-.5069099-1.2385174-.91146307-.3480132-.399679-.5220198-.92121134-.5220198-1.56459704 0-.66775636.1876542-1.25752658.5629625-1.75956239.3753083-.50690994.9075638-.9017148 1.5967663-1.18928871.6892026-.28757391 1.4773501-.4289238 2.3644424-.4289238.7779118 0 1.5387642.11697922 2.2825572.34606352.743793.23395844 1.368169.54590302 1.87313.94558201l-.982626 2.06663284c-.50496-.37043419-1.037216-.64825983-1.5967662-.83835106-.5595506-.19496536-1.1054536-.28757391-1.637709-.28757391-.5595506 0-.9826255.08286028-1.2692245.2437067-.2865991.16572056-.4298987.38993073-.4298987.67750464 0 .29732218.1705947.53615474.5117841.7164977.3411894.17546883.8597973.36068592 1.5558236.55077715.7506166.21933604 1.3613456.4289238 1.8321867.63363743.470842.20471359.880269.51178409 1.228282.91146309.348013.4045531.52202.9260855.52202 1.5694711 0 1.0235682-.406016 1.8229262-1.218046 2.4029481-.812031.580022-1.9072489.87247-3.285654.87247-1.7741848 0-3.3573036-.4240496-4.7493563-1.272149z"/><path d="m107.666697 11.5078305c-.040943.5702737.075062.9943234.348013 1.2672749.272952.2729515.64826.4094272 1.125925.4094272.313894 0 .661907-.0536155 1.044039-.1657205l-.204713 2.3980739c-.464018.1900913-1.064511.2875739-1.80148.2875739-1.173692 0-2.07102-.3168187-2.691984-.945582-.620965-.6238891-.931447-1.5109815-.931447-2.6612772 0-.2290843.006823-.4094272.020471-.5312806l.327542-4.09427259h-1.965251l.184242-2.31033954h1.965251l.184242-2.43706703 3.173062-1.00407162-.266128 3.44113865h2.640806l-.184243 2.31033954h-2.640805z"/><path d="m110.962586 14.4323109 1.003097-2.1494931c.573198.3948049 1.187339.7018753 1.842423.9114631.655083.2144619 1.310167.3168187 1.965251.3168187.573198 0 .996273-.0828603 1.269224-.2437067.272952-.1657206.409427-.3850566.409427-.6580081 0-.2826998-.160359-.5117841-.481077-.6726305-.320718-.1657206-.842737-.3558118-1.566059-.5751478-.750617-.2047136-1.364757-.4094273-1.842423-.6141409-.477665-.2047136-.890504-.5069099-1.238517-.91146307-.348013-.399679-.52202-.92121134-.52202-1.56459704 0-.66775636.187654-1.25752658.562963-1.75956239.375308-.50690994.907563-.9017148 1.596766-1.18928871s1.47735-.4289238 2.364442-.4289238c.777912 0 1.538765.11697922 2.282557.34606352.743793.23395844 1.36817.54590302 1.87313.94558201l-.982625 2.06663284c-.504961-.37043419-1.037216-.64825983-1.596767-.83835106-.55955-.19496536-1.105453-.28757391-1.637709-.28757391-.55955 0-.982625.08286028-1.269224.2437067-.286599.16572056-.429899.38993073-.429899.67750464 0 .29732218.170595.53615474.511784.7164977.34119.17546883.859798.36068592 1.555824.55077715.750616.21933604 1.361345.4289238 1.832187.63363743.470841.20471359.880268.51178409 1.228282.91146309.348013.4045531.522019.9260855.522019 1.5694711 0 1.0235682-.406015 1.8229262-1.218046 2.4029481-.81203.580022-1.907248.87247-3.285653.87247-1.774185 0-3.357304-.4240496-4.749357-1.272149z"/><path d="m133.890513 14.1252405h3.214004v1.4134989h-8.127131v-1.4134989h3.214004v-11.07403258l-2.988819 1.90578642v-1.61821251l3.725788-2.37370329h.962154z"/><path d="m142.058587 13.4282393v1.4963592c0 .5751478-.095533 1.0966801-.286599 1.5743453-.191066.4776651-.511784.945582-.962154 1.3940023l-.777912-.5946443c.532255-.6141409.832502-1.199037.90074-1.7595624h-.982626v-2.1105001z"/><path d="m153.481607 9.31447018c.45037.59951849.675555 1.35988342.675555 2.27134652 0 1.2721489-.429898 2.2713464-1.289696 3.0024665-.859797.726246-2.026665 1.0918061-3.500603 1.0918061-.941682 0-1.845834-.1559723-2.712455-.4679169-.866621-.3168187-1.600178-.7603649-2.200672-1.3306386l.655084-1.2916455c1.35111 1.1210508 2.75681 1.6815762 4.217101 1.6815762 1.037215 0 1.825363-.2339584 2.364442-.6970012.539079-.4630427.808619-1.1454215.808619-2.0471363 0-1.78880715-1.119101-2.68077369-3.357304-2.68077369h-1.678651v-1.41349887h1.35111c1.078158 0 1.903836-.23883257 2.477034-.71649771.573199-.47766514.859798-1.1600439.859798-2.0471363 0-.79448385-.235421-1.39887648-.706262-1.82292614-.470842-.42404966-1.136161-.63363743-1.995958-.63363743-1.392053 0-2.770458.56052542-4.135216 1.67670212l-.634612-1.28677139c.586846-.56052542 1.306756-.99919749 2.159729-1.32089033.852973-.32169285 1.743478-.48253927 2.671513-.48253927 1.310167 0 2.357619.33631525 3.142354 1.00407161.784736.66775637 1.177103 1.56947117 1.177103 2.70027027 0 .83347692-.204713 1.56459703-.61414 2.19336032-.409428.62388916-.975802 1.07718363-1.699124 1.35013514.859798.2437067 1.514881.66775636 1.965251 1.26727485z"/><path d="m159.070289 13.4282393v1.4963592c0 .5751478-.095533 1.0966801-.286599 1.5743453-.191066.4776651-.511784.945582-.962154 1.3940023l-.777912-.5946443c.532256-.6141409.832503-1.199037.90074-1.7595624h-.982625v-2.1105001z"/><path d="m171.98772 10.9716758v1.3940023h-2.210908v3.1730613h-1.678651v-3.1730613h-6.714608v-1.2672749l7.021678-10.13332466h1.371581v10.00659726zm-8.864101 0h4.974542v-7.1649771z"/><path d="m176.081992 13.4282393v1.4963592c0 .5751478-.095533 1.0966801-.286599 1.5743453-.191066.4776651-.511784.945582-.962154 1.3940023l-.777912-.5946443c.532256-.6141409.832502-1.199037.90074-1.7595624h-.982625v-2.1105001z"/><path d="m186.553094 6.9700117c.689203.38993073 1.218046.93095961 1.586531 1.62796078.368484.69700117.552727 1.50123332.552727 2.41757052 0 .911463-.201302 1.7254434-.603905 2.437067-.402604.7067494-.975802 1.2575266-1.719595 1.6474573s-1.613826.580022-2.610099.580022c-.887092 0-1.760537-.1559723-2.620334-.4776652-.859797-.3216928-1.583119-.7603649-2.169965-1.3208903l.634613-1.2916455c1.35111 1.1210508 2.736338 1.6815762 4.155686 1.6815762 1.023568 0 1.825363-.292448 2.405385-.87247.580022-.5800219.870033-1.3696316.870033-2.363955 0-.9699527-.286599-1.74981412-.859797-2.34445848-.573198-.59464435-1.337462-.89196653-2.292793-.89196653-1.392052 0-2.50433.57027369-3.336832 1.70107279h-1.166867v-8.53460874h8.741272v1.38912821h-7.062621v5.20070104c.805207-.77986145 1.835599-1.16491804 3.091176-1.16491804.914388 0 1.716183.19496536 2.405385.58002195z"/></g><g fill="#fff" fill-rule="nonzero" transform="translate(1248.643217 141.651852)"><path d="m5.47365255 15.5387394v-13.14066544h-5.07689804v-1.43299542h11.85291919v1.43299542h-5.07689802v13.14066544z"/><path d="m21.1342453 10.3380383h-7.553933c.0136476 1.3111421.3173061 2.3005913.9109757 2.9683477.5936695.6677563 1.4568786 1.0040716 2.5896274 1.0040716 1.2009866 0 2.3064402-.4045531 3.3163608-1.2087853l.5527268 1.2087853c-.45037.4240497-1.02698.7554908-1.7298302 1.0040716-.7028501.2437067-1.4227597.3655601-2.1597288.3655601-1.6104139 0-2.8728146-.472791-3.7872021-1.418373-.9143876-.9504562-1.3715814-2.25185-1.3715814-3.9041814 0-1.04793885.2047137-1.97889846.6141409-2.79287884.4094273-.80910626.9826255-1.44274368 1.7195945-1.89116402.7369691-.45329446 1.576295-.67750463 2.5179777-.67750463 1.3647575 0 2.4360922.44842033 3.214004 1.34038686.7779118.89684067 1.1668677 2.12512245 1.1668677 3.69459363zm-6.4587151-3.27541805c-.5390792.52153234-.8836805 1.24777832-1.0338038 2.19336032h5.9981094c-.0818855-.96995267-.3650727-1.70594692-.8495616-2.21285686s-1.156632-.75549078-2.0164293-.75549078c-.8597972 0-1.5592354.25832911-2.0983147.77498732z"/><path d="m29.3842046 5.11784076-.0409427 1.51585569c-.3138943-.10723095-.675555-.16572056-1.0849823-.16572056-.996273 0-1.736654.31194458-2.2211429.93095961-.4844889.62388916-.7267334 1.37937994-.7267334 2.26647234v5.87333156h-1.6581804v-7.40868379c0-1.06743536-.0545903-2.02763977-.1637709-2.8903615h1.576295l.1637709 1.90578642c.2593039-.69700117.675555-1.22828178 1.2487531-1.59871597.5731982-.36556006 1.2282818-.55077715 1.9652509-.55077715.3411894 0 .6550836.03899307.9416827.12185335z"/><path d="m45.9045945 9.07076348v6.46797592h-1.6581804v-6.38511564c0-.96995268-.1671828-1.67182798-.5015484-2.11050005-.3343655-.43867206-.8768567-.65313396-1.6274733-.65313396-.8734448 0-1.5558236.29244804-2.0471363.87734413-.4913127.58977022-.7369691 1.38425407-.7369691 2.39807396v5.87333156h-1.6581804v-6.38511564c0-.95533028-.1705947-1.65720558-.5117841-2.10075178s-.8870924-.66288223-1.637709-.66288223c-.8734448 0-1.5592355.29244804-2.057372.87734413-.4981365.58977022-.7472047 1.38425407-.7472047 2.39807396v5.87333156h-1.6581805v-7.40868379c0-1.06743536-.0545903-2.02763977-.1637709-2.8903615h1.576295l.1637709 1.8034296c.2865991-.65313396.7130858-1.1600439 1.2794602-1.51585569s1.2248699-.53128061 1.9754865-.53128061c.8188545 0 1.4875857.16572056 2.0061936.49228754s.90074.83347692 1.1463963 1.51585569c.3138943-.61414089.7744999-1.1015543 1.381817-1.46711435.6073171-.36068592 1.2931078-.54102888 2.057372-.54102888 2.2791451 0 3.4187176 1.3598834 3.4187176 4.07477607z"/><path d="m63.8784513 14.1252405v1.4134989h-9.3758843v-1.2672749l5.0973694-5.65399549c.6823788-.76036491 1.1805153-1.45249195 1.4944095-2.06663284.3138943-.61414089.4708414-1.22828178.4708414-1.84242267 0-.80423212-.2320088-1.42324715-.6960264-1.85217094-.4640175-.4289238-1.1259249-.6433857-1.9857222-.6433857-1.3920527 0-2.7704578.56052542-4.1352153 1.67670212l-.6346123-1.28677139c.5731982-.54590302 1.2965197-.98457508 2.1699645-1.31114206.8734448-.32656699 1.7537134-.49228754 2.6408058-.49228754 1.3374624 0 2.3951495.34606351 3.1730613 1.03331642.7779118.6872529 1.1668677 1.62308664 1.1668677 2.79287881 0 .83347692-.1876542 1.63770904-.5629625 2.40782222-.3753083.77011319-.9996849 1.63283491-1.8731297 2.58816519l-4.1556867 4.50369987z"/><path d="m66.396429 5.46877841h2.1085503v2.12512245h-2.1085503zm0 7.95946089h2.1085503v1.4963592c0 .5751478-.095533 1.0966801-.286599 1.5743453-.1910661.4776651-.5117841.945582-.9621541 1.3940023l-.7779118-.5946443c.5322554-.6141409.8325021-1.199037.90074-1.7595624h-.9826254z"/><path d="m76.2226832 15.5387394 1.1463963-14.57366086h3.214004l-.962154 11.97574736h6.5098934l-.2047136 2.5979135z"/><path d="m87.6661752 15.5387394.8188545-10.37703143h3.0911758l-.8188545 10.37703143zm1.0645108-15.25116549h3.3163608l-.225185 2.9049839h-3.3163608z"/><path d="m92.6611877 14.4323109 1.0030968-2.1494931c.5731982.3948049 1.1873391.7018753 1.8424227.9114631.6550836.2144619 1.3101672.3168187 1.9652508.3168187.5731982 0 .996273-.0828603 1.2692246-.2437067.2729515-.1657206.4094272-.3850566.4094272-.6580081 0-.2826998-.160359-.5117841-.481077-.6726305-.320718-.1657206-.8427378-.3558118-1.5660593-.5751478-.7506166-.2047136-1.3647575-.4094273-1.8424227-.6141409-.4776651-.2047136-.8905043-.5069099-1.2385174-.91146307-.3480132-.399679-.5220198-.92121134-.5220198-1.56459704 0-.66775636.1876542-1.25752658.5629625-1.75956239.3753083-.50690994.9075638-.9017148 1.5967663-1.18928871.6892026-.28757391 1.4773501-.4289238 2.3644424-.4289238.7779118 0 1.5387642.11697922 2.2825572.34606352.743793.23395844 1.368169.54590302 1.87313.94558201l-.982626 2.06663284c-.50496-.37043419-1.037216-.64825983-1.5967662-.83835106-.5595506-.19496536-1.1054536-.28757391-1.637709-.28757391-.5595506 0-.9826255.08286028-1.2692245.2437067-.2865991.16572056-.4298987.38993073-.4298987.67750464 0 .29732218.1705947.53615474.5117841.7164977.3411894.17546883.8597973.36068592 1.5558236.55077715.7506166.21933604 1.3613456.4289238 1.8321867.63363743.470842.20471359.880269.51178409 1.228282.91146309.348013.4045531.52202.9260855.52202 1.5694711 0 1.0235682-.406016 1.8229262-1.218046 2.4029481-.812031.580022-1.9072489.87247-3.285654.87247-1.7741848 0-3.3573036-.4240496-4.7493563-1.272149z"/><path d="m107.666697 11.5078305c-.040943.5702737.075062.9943234.348013 1.2672749.272952.2729515.64826.4094272 1.125925.4094272.313894 0 .661907-.0536155 1.044039-.1657205l-.204713 2.3980739c-.464018.1900913-1.064511.2875739-1.80148.2875739-1.173692 0-2.07102-.3168187-2.691984-.945582-.620965-.6238891-.931447-1.5109815-.931447-2.6612772 0-.2290843.006823-.4094272.020471-.5312806l.327542-4.09427259h-1.965251l.184242-2.31033954h1.965251l.184242-2.43706703 3.173062-1.00407162-.266128 3.44113865h2.640806l-.184243 2.31033954h-2.640805z"/><path d="m110.962586 14.4323109 1.003097-2.1494931c.573198.3948049 1.187339.7018753 1.842423.9114631.655083.2144619 1.310167.3168187 1.965251.3168187.573198 0 .996273-.0828603 1.269224-.2437067.272952-.1657206.409427-.3850566.409427-.6580081 0-.2826998-.160359-.5117841-.481077-.6726305-.320718-.1657206-.842737-.3558118-1.566059-.5751478-.750617-.2047136-1.364757-.4094273-1.842423-.6141409-.477665-.2047136-.890504-.5069099-1.238517-.91146307-.348013-.399679-.52202-.92121134-.52202-1.56459704 0-.66775636.187654-1.25752658.562963-1.75956239.375308-.50690994.907563-.9017148 1.596766-1.18928871s1.47735-.4289238 2.364442-.4289238c.777912 0 1.538765.11697922 2.282557.34606352.743793.23395844 1.36817.54590302 1.87313.94558201l-.982625 2.06663284c-.504961-.37043419-1.037216-.64825983-1.596767-.83835106-.55955-.19496536-1.105453-.28757391-1.637709-.28757391-.55955 0-.982625.08286028-1.269224.2437067-.286599.16572056-.429899.38993073-.429899.67750464 0 .29732218.170595.53615474.511784.7164977.34119.17546883.859798.36068592 1.555824.55077715.750616.21933604 1.361345.4289238 1.832187.63363743.470841.20471359.880268.51178409 1.228282.91146309.348013.4045531.522019.9260855.522019 1.5694711 0 1.0235682-.406015 1.8229262-1.218046 2.4029481-.81203.580022-1.907248.87247-3.285653.87247-1.774185 0-3.357304-.4240496-4.749357-1.272149z"/><path d="m137.432059 14.1252405v1.4134989h-9.375885v-1.2672749l5.09737-5.65399549c.682379-.76036491 1.180515-1.45249195 1.494409-2.06663284.313895-.61414089.470842-1.22828178.470842-1.84242267 0-.80423212-.232009-1.42324715-.696027-1.85217094-.464017-.4289238-1.125925-.6433857-1.985722-.6433857-1.392053 0-2.770458.56052542-4.135215 1.67670212l-.634612-1.28677139c.573198-.54590302 1.296519-.98457508 2.169964-1.31114206.873445-.32656699 1.753713-.49228754 2.640806-.49228754 1.337462 0 2.395149.34606351 3.173061 1.03331642.777912.6872529 1.166868 1.62308664 1.166868 2.79287881 0 .83347692-.187654 1.63770904-.562963 2.40782222-.375308.77011319-.999685 1.63283491-1.873129 2.58816519l-4.155687 4.50369987z"/><path d="m142.058587 13.4282393v1.4963592c0 .5751478-.095533 1.0966801-.286599 1.5743453-.191066.4776651-.511784.945582-.962154 1.3940023l-.777912-.5946443c.532255-.6141409.832502-1.199037.90074-1.7595624h-.982626v-2.1105001z"/><path d="m154.976017 10.9716758v1.3940023h-2.210907v3.1730613h-1.678652v-3.1730613h-6.714607v-1.2672749l7.021677-10.13332466h1.371582v10.00659726zm-8.8641 0h4.974541v-7.1649771z"/><path d="m159.070289 13.4282393v1.4963592c0 .5751478-.095533 1.0966801-.286599 1.5743453-.191066.4776651-.511784.945582-.962154 1.3940023l-.777912-.5946443c.532256-.6141409.832503-1.199037.90074-1.7595624h-.982625v-2.1105001z"/><path d="m169.541392 6.9700117c.689202.38993073 1.218046.93095961 1.58653 1.62796078.368485.69700117.552727 1.50123332.552727 2.41757052 0 .911463-.201302 1.7254434-.603905 2.437067-.402604.7067494-.975802 1.2575266-1.719595 1.6474573-.743792.3899307-1.613825.580022-2.610098.580022-.887093 0-1.760538-.1559723-2.620335-.4776652-.859797-.3216928-1.583119-.7603649-2.169964-1.3208903l.634612-1.2916455c1.35111 1.1210508 2.736339 1.6815762 4.155687 1.6815762 1.023568 0 1.825363-.292448 2.405385-.87247.580022-.5800219.870033-1.3696316.870033-2.363955 0-.9699527-.286599-1.74981412-.859798-2.34445848-.573198-.59464435-1.337462-.89196653-2.292792-.89196653-1.392053 0-2.50433.57027369-3.336832 1.70107279h-1.166868v-8.53460874h8.741272v1.38912821h-7.06262v5.20070104c.805207-.77986145 1.835599-1.16491804 3.091175-1.16491804.914388 0 1.716183.19496536 2.405386.58002195z"/><path d="m176.081992 13.4282393v1.4963592c0 .5751478-.095533 1.0966801-.286599 1.5743453-.191066.4776651-.511784.945582-.962154 1.3940023l-.777912-.5946443c.532256-.6141409.832502-1.199037.90074-1.7595624h-.982625v-2.1105001z"/><path d="m187.965618 9.38758219c.525432.63363741.788148 1.39400231.788148 2.28109471 0 1.2429042-.470842 2.2226052-1.412524 2.9391029-.941683.7164977-2.210907 1.0723095-3.807674 1.0723095-1.596766 0-2.865991-.3558118-3.807673-1.0723095-.941683-.7164977-1.412524-1.6961987-1.412524-2.9391029 0-.8870924.269539-1.6523314.808619-2.29084297.539079-.6433857 1.27946-1.0869319 2.221142-1.3306386-.873444-.25832911-1.542176-.6872529-2.006193-1.28189726-.464018-.59464435-.696026-1.29164552-.696026-2.09587764 0-.77986145.204713-1.45736609.61414-2.03738804.409428-.58002195.986038-1.02844229 1.729831-1.35013513.743792-.32169285 1.593354-.48253927 2.548684-.48253927.955331 0 1.804892.16084642 2.548685.48253927.743793.32169284 1.320403.77011318 1.72983 1.35013513s.614141 1.25752659.614141 2.03738804c0 .80423212-.235421 1.50123329-.706262 2.09587764-.470841.59464436-1.129337 1.02356815-1.975487 1.28189726.955331.2583291 1.695712.70674944 2.221143 1.34038686zm-6.776021-2.7051444c.580022.48741341 1.361346.78473559 2.343971.89196653.982626-.10723094 1.763949-.40455312 2.343971-.89196653.580022-.48253927.870033-1.11130256.870033-1.89116401 0-.80423212-.283187-1.43786955-.849561-1.90578642-.566375-.46304273-1.354522-.69212703-2.364443-.69212703-1.00992 0-1.798068.2290843-2.364442.69212703-.566375.46791687-.849562 1.1015543-.849562 1.90578642 0 .77986145.290011 1.40862474.870033 1.89116401zm4.984777 6.91152211c.614141-.4630428.921211-1.1405474.921211-2.0276398 0-.8042321-.324129-1.4476178-.972389-1.9350312-.64826-.48253927-1.511469-.77986145-2.589628-.8870924-1.078158.10723095-1.941367.40455313-2.589627.8870924-.64826.4874134-.97239 1.1307991-.97239 1.9350312 0 .8870924.307071 1.564597.921211 2.0276398.614141.4630427 1.49441.6970012 2.640806.6970012 1.146397 0 2.026665-.2339585 2.640806-.6970012z"/></g><g fill="#fff" fill-rule="nonzero" transform="translate(1520.629778 141.651852)"><path d="m5.47365255 15.5387394v-13.14066544h-5.07689804v-1.43299542h11.85291919v1.43299542h-5.07689802v13.14066544z"/><path d="m21.1342453 10.3380383h-7.553933c.0136476 1.3111421.3173061 2.3005913.9109757 2.9683477.5936695.6677563 1.4568786 1.0040716 2.5896274 1.0040716 1.2009866 0 2.3064402-.4045531 3.3163608-1.2087853l.5527268 1.2087853c-.45037.4240497-1.02698.7554908-1.7298302 1.0040716-.7028501.2437067-1.4227597.3655601-2.1597288.3655601-1.6104139 0-2.8728146-.472791-3.7872021-1.418373-.9143876-.9504562-1.3715814-2.25185-1.3715814-3.9041814 0-1.04793885.2047137-1.97889846.6141409-2.79287884.4094273-.80910626.9826255-1.44274368 1.7195945-1.89116402.7369691-.45329446 1.576295-.67750463 2.5179777-.67750463 1.3647575 0 2.4360922.44842033 3.214004 1.34038686.7779118.89684067 1.1668677 2.12512245 1.1668677 3.69459363zm-6.4587151-3.27541805c-.5390792.52153234-.8836805 1.24777832-1.0338038 2.19336032h5.9981094c-.0818855-.96995267-.3650727-1.70594692-.8495616-2.21285686s-1.156632-.75549078-2.0164293-.75549078c-.8597972 0-1.5592354.25832911-2.0983147.77498732z"/><path d="m29.3842046 5.11784076-.0409427 1.51585569c-.3138943-.10723095-.675555-.16572056-1.0849823-.16572056-.996273 0-1.736654.31194458-2.2211429.93095961-.4844889.62388916-.7267334 1.37937994-.7267334 2.26647234v5.87333156h-1.6581804v-7.40868379c0-1.06743536-.0545903-2.02763977-.1637709-2.8903615h1.576295l.1637709 1.90578642c.2593039-.69700117.675555-1.22828178 1.2487531-1.59871597.5731982-.36556006 1.2282818-.55077715 1.9652509-.55077715.3411894 0 .6550836.03899307.9416827.12185335z"/><path d="m45.9045945 9.07076348v6.46797592h-1.6581804v-6.38511564c0-.96995268-.1671828-1.67182798-.5015484-2.11050005-.3343655-.43867206-.8768567-.65313396-1.6274733-.65313396-.8734448 0-1.5558236.29244804-2.0471363.87734413-.4913127.58977022-.7369691 1.38425407-.7369691 2.39807396v5.87333156h-1.6581804v-6.38511564c0-.95533028-.1705947-1.65720558-.5117841-2.10075178s-.8870924-.66288223-1.637709-.66288223c-.8734448 0-1.5592355.29244804-2.057372.87734413-.4981365.58977022-.7472047 1.38425407-.7472047 2.39807396v5.87333156h-1.6581805v-7.40868379c0-1.06743536-.0545903-2.02763977-.1637709-2.8903615h1.576295l.1637709 1.8034296c.2865991-.65313396.7130858-1.1600439 1.2794602-1.51585569s1.2248699-.53128061 1.9754865-.53128061c.8188545 0 1.4875857.16572056 2.0061936.49228754s.90074.83347692 1.1463963 1.51585569c.3138943-.61414089.7744999-1.1015543 1.381817-1.46711435.6073171-.36068592 1.2931078-.54102888 2.057372-.54102888 2.2791451 0 3.4187176 1.3598834 3.4187176 4.07477607z"/><path d="m62.9162972 9.31447018c.45037.59951849.675555 1.35988342.675555 2.27134652 0 1.2721489-.4298986 2.2713464-1.2896959 3.0024665-.8597972.726246-2.0266649 1.0918061-3.500603 1.0918061-.9416827 0-1.8458346-.1559723-2.7124556-.4679169-.8666211-.3168187-1.6001782-.7603649-2.2006716-1.3306386l.6550837-1.2916455c1.3511099 1.1210508 2.7568102 1.6815762 4.2171007 1.6815762 1.0372158 0 1.8253632-.2339584 2.3644425-.6970012.5390792-.4630427.8086188-1.1454215.8086188-2.0471363 0-1.78880715-1.1191012-2.68077369-3.3573035-2.68077369h-1.6786518v-1.41349887h1.35111c1.0781584 0 1.9038367-.23883257 2.4770349-.71649771s.8597972-1.1600439.8597972-2.0471363c0-.79448385-.2354206-1.39887648-.706262-1.82292614-.4708413-.42404966-1.1361606-.63363743-1.9959579-.63363743-1.3920527 0-2.7704578.56052542-4.1352153 1.67670212l-.6346123-1.28677139c.5868458-.56052542 1.3067554-.99919749 2.1597288-1.32089033.8529735-.32169285 1.7434778-.48253927 2.6715129-.48253927 1.3101672 0 2.3576186.33631525 3.1423542 1.00407161.7847356.66775637 1.1771034 1.56947117 1.1771034 2.70027027 0 .83347692-.2047136 1.56459703-.6141409 2.19336032-.4094272.62388916-.9758016 1.07718363-1.6991231 1.35013514.8597972.2437067 1.5148808.66775636 1.9652508 1.26727485z"/><path d="m66.396429 5.46877841h2.1085503v2.12512245h-2.1085503zm0 7.95946089h2.1085503v1.4963592c0 .5751478-.095533 1.0966801-.286599 1.5743453-.1910661.4776651-.5117841.945582-.9621541 1.3940023l-.7779118-.5946443c.5322554-.6141409.8325021-1.199037.90074-1.7595624h-.9826254z"/><path d="m76.2226832 15.5387394 1.1463963-14.57366086h3.214004l-.962154 11.97574736h6.5098934l-.2047136 2.5979135z"/><path d="m87.6661752 15.5387394.8188545-10.37703143h3.0911758l-.8188545 10.37703143zm1.0645108-15.25116549h3.3163608l-.225185 2.9049839h-3.3163608z"/><path d="m92.6611877 14.4323109 1.0030968-2.1494931c.5731982.3948049 1.1873391.7018753 1.8424227.9114631.6550836.2144619 1.3101672.3168187 1.9652508.3168187.5731982 0 .996273-.0828603 1.2692246-.2437067.2729515-.1657206.4094272-.3850566.4094272-.6580081 0-.2826998-.160359-.5117841-.481077-.6726305-.320718-.1657206-.8427378-.3558118-1.5660593-.5751478-.7506166-.2047136-1.3647575-.4094273-1.8424227-.6141409-.4776651-.2047136-.8905043-.5069099-1.2385174-.91146307-.3480132-.399679-.5220198-.92121134-.5220198-1.56459704 0-.66775636.1876542-1.25752658.5629625-1.75956239.3753083-.50690994.9075638-.9017148 1.5967663-1.18928871.6892026-.28757391 1.4773501-.4289238 2.3644424-.4289238.7779118 0 1.5387642.11697922 2.2825572.34606352.743793.23395844 1.368169.54590302 1.87313.94558201l-.982626 2.06663284c-.50496-.37043419-1.037216-.64825983-1.5967662-.83835106-.5595506-.19496536-1.1054536-.28757391-1.637709-.28757391-.5595506 0-.9826255.08286028-1.2692245.2437067-.2865991.16572056-.4298987.38993073-.4298987.67750464 0 .29732218.1705947.53615474.5117841.7164977.3411894.17546883.8597973.36068592 1.5558236.55077715.7506166.21933604 1.3613456.4289238 1.8321867.63363743.470842.20471359.880269.51178409 1.228282.91146309.348013.4045531.52202.9260855.52202 1.5694711 0 1.0235682-.406016 1.8229262-1.218046 2.4029481-.812031.580022-1.9072489.87247-3.285654.87247-1.7741848 0-3.3573036-.4240496-4.7493563-1.272149z"/><path d="m107.666697 11.5078305c-.040943.5702737.075062.9943234.348013 1.2672749.272952.2729515.64826.4094272 1.125925.4094272.313894 0 .661907-.0536155 1.044039-.1657205l-.204713 2.3980739c-.464018.1900913-1.064511.2875739-1.80148.2875739-1.173692 0-2.07102-.3168187-2.691984-.945582-.620965-.6238891-.931447-1.5109815-.931447-2.6612772 0-.2290843.006823-.4094272.020471-.5312806l.327542-4.09427259h-1.965251l.184242-2.31033954h1.965251l.184242-2.43706703 3.173062-1.00407162-.266128 3.44113865h2.640806l-.184243 2.31033954h-2.640805z"/><path d="m110.962586 14.4323109 1.003097-2.1494931c.573198.3948049 1.187339.7018753 1.842423.9114631.655083.2144619 1.310167.3168187 1.965251.3168187.573198 0 .996273-.0828603 1.269224-.2437067.272952-.1657206.409427-.3850566.409427-.6580081 0-.2826998-.160359-.5117841-.481077-.6726305-.320718-.1657206-.842737-.3558118-1.566059-.5751478-.750617-.2047136-1.364757-.4094273-1.842423-.6141409-.477665-.2047136-.890504-.5069099-1.238517-.91146307-.348013-.399679-.52202-.92121134-.52202-1.56459704 0-.66775636.187654-1.25752658.562963-1.75956239.375308-.50690994.907563-.9017148 1.596766-1.18928871s1.47735-.4289238 2.364442-.4289238c.777912 0 1.538765.11697922 2.282557.34606352.743793.23395844 1.36817.54590302 1.87313.94558201l-.982625 2.06663284c-.504961-.37043419-1.037216-.64825983-1.596767-.83835106-.55955-.19496536-1.105453-.28757391-1.637709-.28757391-.55955 0-.982625.08286028-1.269224.2437067-.286599.16572056-.429899.38993073-.429899.67750464 0 .29732218.170595.53615474.511784.7164977.34119.17546883.859798.36068592 1.555824.55077715.750616.21933604 1.361345.4289238 1.832187.63363743.470841.20471359.880268.51178409 1.228282.91146309.348013.4045531.522019.9260855.522019 1.5694711 0 1.0235682-.406015 1.8229262-1.218046 2.4029481-.81203.580022-1.907248.87247-3.285653.87247-1.774185 0-3.357304-.4240496-4.749357-1.272149z"/><path d="m137.964314 10.9716758v1.3940023h-2.210907v3.1730613h-1.678652v-3.1730613h-6.714607v-1.2672749l7.021678-10.13332466h1.371581v10.00659726zm-8.8641 0h4.974541v-7.1649771z"/><path d="m142.058587 13.4282393v1.4963592c0 .5751478-.095533 1.0966801-.286599 1.5743453-.191066.4776651-.511784.945582-.962154 1.3940023l-.777912-.5946443c.532255-.6141409.832502-1.199037.90074-1.7595624h-.982626v-2.1105001z"/><path d="m152.488746 6.9700117c.689203.38993073 1.22487.93583374 1.607002 1.63770904.382132.70674944.573198 1.50610746.573198 2.40782226s-.201301 1.7059469-.603905 2.4126963c-.402603.7116236-.958742 1.2672749-1.668416 1.671828-.709674.399679-1.514881.6043926-2.415621.6043926-1.760537 0-3.118471-.6141409-4.073801-1.8424226-.95533-1.2282818-1.432995-2.978096-1.432995-5.24456829 0-1.63770904.221773-3.04145965.665319-4.21612596.443546-1.1746663 1.084982-2.06663284 1.924308-2.68077373s1.845835-.92121133 3.019526-.92121133c.84615 0 1.668416.15597229 2.466799.472791.798383.31194458 1.497822.75549078 2.098315 1.3306386l-.634612 1.28677139c-.682379-.57027369-1.337463-.99432335-1.965251-1.26727486-.627789-.2729515-1.269225-.40942726-1.924308-.40942726-1.255577 0-2.231379.56052542-2.927405 1.67670212-.696026 1.12105083-1.04404 2.690522-1.04404 4.7084135v.30707044c.313895-.77498731.825679-1.3891282 1.535353-1.84242267.709674-.44842033 1.521704-.6726305 2.436092-.6726305.887092 0 1.67524.19496536 2.364442.58002195zm-.337777 6.4289828c.573198-.5946443.859797-1.3793799.859797-2.363955 0-.9699527-.290011-1.74981412-.870033-2.34445848-.580022-.59464435-1.33405-.89196653-2.262086-.89196653-.95533 0-1.733242.30219631-2.333735.9017148s-.90074 1.37937991-.90074 2.33471021c0 .9699527.300247 1.7546883.90074 2.3542068.600493.5995184 1.385229.9017148 2.354207.9017148.928035 0 1.678652-.2973222 2.25185-.8919666z"/><path d="m159.070289 13.4282393v1.4963592c0 .5751478-.095533 1.0966801-.286599 1.5743453-.191066.4776651-.511784.945582-.962154 1.3940023l-.777912-.5946443c.532256-.6141409.832503-1.199037.90074-1.7595624h-.982625v-2.1105001z"/><path d="m161.711095.96507854h9.621541v1.24777832l-6.837435 13.32588254h-1.80148l6.796492-13.16503611h-7.779118z"/><path d="m176.081992 13.4282393v1.4963592c0 .5751478-.095533 1.0966801-.286599 1.5743453-.191066.4776651-.511784.945582-.962154 1.3940023l-.777912-.5946443c.532256-.6141409.832502-1.199037.90074-1.7595624h-.982625v-2.1105001z"/><path d="m187.157 2.64178066c.95533 1.22828178 1.432995 2.97322177 1.432995 5.23969411 0 2.47118593-.494725 4.39159483-1.484174 5.76610063-.989449 1.3696316-2.371266 2.0568845-4.145451 2.0568845-.832502 0-1.647945-.1608464-2.446328-.472791s-1.504645-.7554908-2.118786-1.3306386l.655084-1.2916455c.696026.5897702 1.357934 1.0138199 1.985722 1.2818973.627788.2680773 1.262401.399679 1.903837.399679 1.255577 0 2.227966-.5605255 2.917169-1.6815763.689203-1.1161767 1.033804-2.68564786 1.033804-4.70841349v-.26320324c-.313894.76523904-.825679 1.36963167-1.535352 1.80830373-.709674.44842034-1.521705.6677564-2.436093.6677564-.887092 0-1.671828-.19496539-2.354206-.58489612-.682379-.38505659-1.214635-.93583374-1.596767-1.63770904-.382132-.70187531-.573198-1.50123329-.573198-2.40294809s.201302-1.70594692.603905-2.41757049c.402604-.70674944.958743-1.26727486 1.668416-1.66695385.709674-.40455313 1.514881-.60439262 2.415621-.60439262 1.760538 0 3.118471.61414089 4.073802 1.84242267zm-1.63771 5.15683383c.600494-.59951849.90074-1.3745058.90074-2.32983608 0-.96995268-.300246-1.75468826-.90074-2.35420675-.600493-.60439262-1.385228-.9017148-2.354206-.9017148-.928035 0-1.678652.29732218-2.25185.89196653-.573198.58977023-.859797 1.37937994-.859797 2.36395502 0 .96507855.286599 1.74981413.859797 2.34445848.573198.58977022 1.330638.8870924 2.272321.8870924.95533 0 1.733242-.29732218 2.333735-.9017148z"/></g><g transform="translate(1352.227084 194.213333)"><path d="m.035471.089728h42.916712v49.26713h-42.916712z" fill="#00a88a"/><path d="m42.9521838 49.3568579h-42.91671231v-49.26713035h42.91671231zm-40.37825665-46.72872807v44.19032577h37.83980095v-44.19032577z" fill="#000"/></g><path d="m16.4442443 13.0739279c1.490095.8410144 2.6336139 2.0140013 3.4302957 3.5187.7966819 1.5049595 1.1948925 3.2456638 1.1948925 5.2226344 0 1.9769707-.4352413 3.7325394-1.3057238 5.266967-.8702218 1.5344275-2.1097075 2.7220182-3.717675 3.5630326-1.6082282.8407536-3.4892319 1.2613912-5.643272 1.2613912-1.91777365 0-3.80607922-.3468369-5.66517747-1.0402501-1.85883748-.6934131-3.42273314-1.6449981-4.69142623-2.854755l1.37196183-2.7882562c2.92125384 2.4195138 5.91604755 3.6292706 8.98464187 3.6292706 2.2132371 0 3.9466395-.6269143 5.2007289-1.8810037 1.2538287-1.2540894 1.8810038-2.9580238 1.8810038-5.1120638 0-2.0948431-.6196125-3.7841738-1.8588375-5.0677313-1.2394857-1.2835575-2.8917857-1.9253363-4.9571607-1.9253363-3.00965814 0-5.41456823 1.2246213-7.2144695 3.6736032h-2.52278251v-18.45642023h18.89896331v3.00965815h-15.26969267v11.24221148c1.74096506-1.6820289 3.96880577-2.5230433 6.68326137-2.5230433 1.9769706 0 3.7103731.4206376 5.2004681 1.2613913z" fill="#f2f2f2" fill-rule="nonzero" transform="translate(1362.630417 203.100332)"/><g transform="translate(1412.266122 194.392443)"><path d="m.035471.089728h42.916712v49.26713h-42.916712z" fill="#00a88a"/><path d="m42.9521838 49.3568579h-42.91671231v-49.26713035h42.91671231zm-40.37825665-46.72872807v44.19032577h37.83980095v-44.19032577z" fill="#000"/></g><path d="m21.062913 18.8183824c1.1359562 1.3719618 1.7039343 3.01696 1.7039343 4.9347336 0 2.6852483-1.017823 4.8022576-3.0537299 6.3512889-2.0361676 1.549292-4.7800913 2.3238076-8.2322925 2.3238076-3.45246205 0-6.19638571-.7745156-8.23229258-2.3238076-2.03616764-1.5490313-3.05399069-3.6660406-3.05399069-6.3512889 0-1.9177736.58258178-3.5700736 1.7482669-4.9568999 1.16542433-1.3868263 2.76608993-2.3459739 4.8019968-2.8769213-1.88830558-.5606763-3.33406805-1.4827932-4.33728744-2.7663507-1.00321938-1.2835575-1.50495946-2.795558-1.50495946-4.5365231 0-1.68176807.44280388-3.1499576 1.32789007-4.40378625.88508619-1.25408942 2.13187378-2.2278407 3.73984121-2.92125383 1.60822822-.69341314 3.44489942-1.03998932 5.51053519-1.03998932 2.0653749 0 3.9020461.34657618 5.5102744 1.03998932 1.6079674.69341313 2.854755 1.66716441 3.7398412 2.92125383.8853469 1.25382865 1.32789 2.72201818 1.32789 4.40378625 0 1.7409651-.5090419 3.2529656-1.5271257 4.5365231-1.017823 1.2835575-2.4414192 2.2056744-4.2710494 2.7663507 2.0656358.5606763 3.6663014 1.526865 4.8022576 2.8990876zm-14.64981941-5.8425077c1.25382864 1.0475519 2.94315933 1.6893307 5.06773131 1.9253363 2.1243111-.2360056 3.8136418-.8777844 5.0677313-1.9253363 1.2538286-1.0472911 1.8810037-2.4119511 1.8810037-4.09397999 0-1.74070429-.6123107-3.1129269-1.836932-4.11614628-1.2243605-1.00321938-2.9285556-1.50469868-5.111803-1.50469868-2.18350818 0-3.88770331.5014793-5.11206385 1.50469868-1.22462132 1.00321938-1.83693198 2.37544199-1.83693198 4.11614628 0 1.68202889.6271751 3.04668889 1.88126452 4.09397999zm10.77724131 14.9377202c1.3276293-1.0032194 1.9915743-2.4638463 1.9915743-4.38162 0-1.7409651-.7007149-3.1350932-2.1024056-4.1826451-1.40143-1.0475519-3.2678301-1.6893307-5.5986787-1.9253363-2.33110948.2360056-4.19750956.8777844-5.59893949 1.9253363-1.40169072 1.0475519-2.10240568 2.44168-2.10240568 4.1826451 0 1.9177737.66394503 3.3784006 1.9918351 4.38162 1.32762929 1.0032193 3.2307993 1.5049594 5.70951007 1.5049594 2.4784499 0 4.38162-.5017401 5.70951-1.5049594z" fill="#f2f2f2" fill-rule="nonzero" transform="translate(1421.105194 202.753717)"/><g transform="translate(1503.787344 194.392443)"><path d="m.035471.089728h42.916712v49.26713h-42.916712z" fill="#00a88a"/><path d="m42.9521838 49.3568579h-42.91671231v-49.26713035h42.91671231zm-40.37816863-46.72872807v44.19032577h37.83971293v-44.19032577z" fill="#000"/></g><path d="m23.0372759 21.726858v3.0096582h-4.7800914v6.8603307h-3.6292706v-6.8603307h-14.51708254v-2.7441845l15.18102754-21.90862143h2.9653256v21.64314773zm-19.16443705 0h10.75507505v-15.4908338z" fill="#f2f2f2" fill-rule="nonzero" transform="translate(1512.887196 203.275277)"/><g transform="translate(1565.163879 194.392443)"><path d="m.035471.089728h42.916712v49.26713h-42.916712z" fill="#00a88a"/><path d="m42.9521838 49.3568579h-42.91671231v-49.26713035h42.91671231zm-40.37816863-46.72872807v44.19032577h37.83971293v-44.19032577z" fill="#000"/></g><path d="m17.3989587 13.5954872c1.490095.8410144 2.6482175 2.0213032 3.4743675 3.5408663.82615 1.5195632 1.239225 3.2532264 1.239225 5.2004682 0 1.9475025-.4352413 3.6884676-1.3057238 5.2226344-.8702218 1.5344275-2.0726768 2.7368826-3.6071044 3.6073651-1.5341668.8702218-3.2751319 1.305463-5.2226344 1.305463-3.80634005 0-6.74219755-1.3276293-8.80757252-3.9834094-2.06563575-2.6555193-3.09832323-6.4323913-3.09832323-11.330355 0-3.5408663.47957381-6.5799926 1.43846065-9.11737874.95888684-2.53764695 2.34571311-4.47028507 4.16047882-5.79817514 1.81450493-1.32789007 3.99071125-1.99157432 6.52835818-1.99157432 1.8293694 0 3.6071044.33927435 5.333205 1.01782304 1.7261006.67880948 3.2383619 1.63769632 4.5365231 2.8769213l-1.3719618 2.78851699c-1.4752306-1.23948576-2.891525-2.15404006-4.2488832-2.74418445-1.3573581-.59014439-2.7441844-.88534697-4.1604788-.88534697-2.71445553 0-4.82416305 1.20975688-6.32912251 3.62953142-1.50469868 2.41951375-2.2573088 5.81251797-2.2573088 10.17953437v.663945c.67880947-1.6817681 1.7852976-3.0096582 3.31946439-3.9834094 1.53442756-.9737513 3.28999632-1.460627 5.26696692-1.460627 1.9180345 0 3.6219688.4206377 5.1120639 1.2613913zm-.7301831 13.8977308c1.239225-1.2835575 1.8588375-2.9874918 1.8588375-5.1120638 0-2.0948431-.6271751-3.7841737-1.8810038-5.0677313-1.2540894-1.2835575-2.8842231-1.9253363-4.8906619-1.9253363-2.06563572 0-3.7474038.6490806-5.04582577 1.9475026-1.29816118 1.2981612-1.94724178 2.98019-1.94724178 5.045565 0 2.0948431.6490806 3.7914756 1.94724178 5.0898976 1.29842197 1.2981612 2.99505449 1.9475025 5.08989757 1.9475025 2.0064388 0 3.6292706-.6417787 4.8687564-1.9253363z" fill="#f2f2f2" fill-rule="nonzero" transform="translate(1574.52451 202.753717)"/><g transform="translate(1624.915924 194.392443)"><path d="m.035471.089728h42.916712v49.26713h-42.916712z" fill="#00a88a"/><path d="m42.9521838 49.3568579h-42.91671231v-49.26713035h42.91671231zm-40.37816863-46.72872807v44.19032577h37.83971293v-44.19032577z" fill="#000"/></g><path d="m.03650915.08371027h20.80213335v2.6998519l-14.78281705 28.81328473h-3.89474434l14.69415189-28.45914594h-16.81872385z" fill="#f2f2f2" fill-rule="nonzero" transform="translate(1635.972745 203.629332)"/><g transform="translate(1684.951213 194.392443)"><path d="m.035471.089728h42.916712v49.26713h-42.916712z" fill="#00a88a"/><path d="m42.9521838 49.3568579h-42.91671231v-49.26713035h42.91671231zm-40.37825665-46.72872807v44.19032577h37.83980095v-44.19032577z" fill="#000"/></g><path d="m19.0538664 4.23480103c2.065375 2.65551935 3.0983233 6.43239127 3.0983233 11.33035497 0 5.3407676-1.0697182 9.4936838-3.2088939 12.4590094-2.1391756 2.9655864-5.1266674 4.4481188-8.96273635 4.4481188-1.79990127 0-3.56277183-.3392743-5.28887245-1.017823-1.72610062-.6788095-3.25322635-1.6376963-4.58085564-2.8769213l1.41629437-2.7882562c1.50469869 1.2686931 2.9358575 2.19081 4.29321568 2.7660899 1.35709739.57528 2.72932.8631807 4.11614627.8631807 2.71445552 0 4.81686122-1.2097569 6.30695622-3.6292706 1.4900951-2.4197745 2.2351426-5.8127788 2.2351426-10.1797951v-.5755408c-.6788095 1.6525608-1.7852976 2.9580238-3.3194644 3.9171714-1.5344276.9588869-3.2899963 1.4384607-5.26696696 1.4384607-1.91803446 0-3.61466698-.4206376-5.08989756-1.2613913-1.47523058-.8410144-2.62605125-2.0213032-3.45220124-3.5408663s-1.23922498-3.2532264-1.23922498-5.2004681c0-1.94750259.43524126-3.68846765 1.30546302-5.22263444.87048253-1.53442756 2.07293758-2.73688261 3.60736514-3.60736514 1.53416679-.87022175 3.27513185-1.30546302 5.22263438-1.30546302 3.8063401 0 6.7421976 1.32762929 8.8075725 3.98340943zm-3.5408663 11.15328557c1.298422-1.2981611 1.9475026-2.98019 1.9475026-5.045565 0-2.09484305-.6490806-3.79147556-1.9475026-5.08989753-1.2981612-1.29816119-2.9947937-1.94750256-5.0896368-1.94750256-2.00643874 0-3.62953139.64177876-4.86875638 1.92533629-1.23922498 1.28355752-1.85883747 2.98749187-1.85883747 5.1120638 0 2.0948431.61961249 3.7841738 1.85883747 5.0677313 1.23922499 1.2835575 2.8769213 1.9253363 4.91282818 1.9253363 2.0656357 0 3.7474038-.6490806 5.045565-1.9475026z" fill="#f2f2f2" fill-rule="nonzero" transform="translate(1694.05523 202.753717)"/><path d="m274.413747 0v15.1195638-7.54515948h-274.07401986v7.54515948" stroke="#000" stroke-width="2.539424" transform="translate(1068.761162 109.742102)"/><path d="m0 .24858084h272.688304v7.55978192" stroke="#000" stroke-width="2.539424" transform="translate(1343.17491 117.053303)"/><path d="m90.8465476.12672749v8.60284661h-90.40348881v8.7441965" stroke="#000" stroke-width="2.539424" transform="translate(978.589682 177.005152)"/><path d="m1040.343498 185.807838v8.671084" stroke="#000" stroke-width="2.539424"/><path d="m.18765416.0292448h90.06863584v8.67108449" stroke="#000" stroke-width="2.539424" transform="translate(1069.248576 185.778593)"/><path d="m1100.026783 185.807838v8.671084" stroke="#000" stroke-width="2.539424"/><path d="m1314.628568 185.807838v8.671084" stroke="#000" stroke-width="2.539424"/><path d="m.27782564.0292448h88.64587606v8.67108449" stroke="#000" stroke-width="2.539424" transform="translate(1343.662323 185.778593)"/><path d="m1373.584633 185.807838v8.671084" stroke="#000" stroke-width="2.539424"/><path d="m90.3956902.12672749v8.67595862h-90.07887149v8.67108449" stroke="#000" stroke-width="2.539424" transform="translate(1525.467524 177.005152)"/><path d="m1586.145618 185.807838v8.671084" stroke="#000" stroke-width="2.539424"/><path d="m.22421017.0292448h90.27871103v8.67108449" stroke="#000" stroke-width="2.539424" transform="translate(1615.639004 185.778593)"/><path d="m1645.921998 185.807838v8.671084" stroke="#000" stroke-width="2.539424"/><g fill="#f2f2f2" fill-rule="nonzero" transform="translate(1263.581889 37.572233)"><path d="m7.95815261 22.540308v-20.02691984h-7.73636299v-2.18343345h18.06186388v2.18343345h-7.736363v20.02691984z"/><path d="m32.5082157 6.84954575v15.69076225h-2.495645v-2.8385659c-.4572278.9772392-1.1488702 1.7313239-2.0742447 2.2615717s-2.001566.7953717-3.2285744.7953717c-1.3935212 0-2.6154113-.3326845-3.6653293-.9980533-1.0502591-.6657101-1.8613267-1.6067805-2.4332026-2.8232112-.571876-1.2164307-.857814-2.6358843-.857814-4.2580194s.2910562-3.0518251.8731686-4.2894112c.5824537-1.2372448 1.3986395-2.1991293 2.4488986-2.88531225s2.2615716-1.02944503 3.6342787-1.02944503c1.2270084 0 2.2977405.27024212 3.2128785.81106756.9151381.54082545 1.6118987 1.29968715 2.0899406 2.27726753v-2.71402246zm-3.7431262 12.24381045c.8315404-1.0502592 1.2474812-2.5423915 1.2474812-4.4763969 0-1.9340055-.4159408-3.4210195-1.2474812-4.460701-.8318817-1.04002268-2.0172619-1.55969281-3.5564818-1.55969281-1.5388787 0-2.7396136.53536601-3.602887 1.60643921-.8629322 1.0710733-1.294569 2.5632056-1.294569 4.4763969s.4265185 3.3896277 1.2788731 4.4296504c.8526958 1.0396815 2.0588901 1.5596929 3.6185829 1.5596929 1.5392199 0 2.7246001-.5251296 3.5564818-1.5753887z"/><path d="m44.8301643 14.4610241 6.4571488 8.0792839h-3.0258928l-4.9598983-6.176329-4.8974559 6.176329h-3.0883351l6.5195911-8.0792839-6.1452784-7.61147835h3.0572845l4.5541938 5.77096575 4.5545351-5.77096575h3.0879939z"/><path d="m56.3720959 21.7606322c-1.1229379-.6657101-1.9913295-1.6118987-2.6048337-2.8389071s-.9202563-2.6618166-.9202563-4.3047658.3067521-3.0777574.9202563-4.3047658c.6135042-1.22700843 1.4818958-2.17319705 2.6048337-2.83890711 1.1229379-.66536885 2.422625-.99805327 3.8994026-.99805327 1.4764365 0 2.7761236.33268442 3.8990615.99805327 1.1232791.66571006 1.9913295 1.61189868 2.6048337 2.83890711.6135042 1.2270084.9202563 2.6618166.9202563 4.3047658s-.3067521 3.0777574-.9202563 4.3047658-1.4815546 2.173197-2.6048337 2.8389071c-1.1229379.6653688-2.422625.9980533-3.8990615.9980533-1.4767776 0-2.7764647-.3326845-3.8994026-.9980533zm7.4865938-2.6358843c.8318816-1.029445 1.2478225-2.532155 1.2478225-4.5077886 0-1.9131914-.4261773-3.3950872-1.2788731-4.4453463-.8526957-1.04991795-2.0380759-1.57504751-3.5561406-1.57504751-1.5388787 0-2.7348365.52512956-3.5875323 1.57504751-.8526957 1.0502591-1.278873 2.5321549-1.278873 4.4453463 0 1.9756336.421059 3.4783436 1.2631771 4.5077886.8424594 1.0291038 2.0435354 1.543997 3.6032282 1.543997 1.5596929 0 2.7553095-.5148932 3.5871912-1.543997z"/><path d="m85.1023814 12.6829538v9.8573542h-2.5270367v-9.7324695c0-1.4559636-.2910562-2.5215774-.8731687-3.19752386-.5824536-.67594651-1.4975917-1.01374915-2.7454142-1.01374915-1.4556223 0-2.6201884.44699138-3.4936983 1.34131535-.8735098.89432396-1.3102648 2.10051826-1.3102648 3.61858286v8.9838443h-2.5266955v-11.2925036c0-1.62179388-.0832564-3.08799385-.249428-4.39825865h2.4018109l.2497692 2.80751531c.4783832-1.01886737 1.1956167-1.80400261 2.152383-2.3550645.956425-.55106189 2.0483124-.82676344 3.2753208-.82676344 3.7642815 0 5.6464223 2.0691265 5.6464223 6.20772068z"/><path d="m92.4640906 21.7606322c-1.1229379-.6657101-1.9913295-1.6118987-2.6048337-2.8389071s-.9202563-2.6618166-.9202563-4.3047658.3067521-3.0777574.9202563-4.3047658c.6135042-1.22700843 1.4818958-2.17319705 2.6048337-2.83890711 1.1229379-.66536885 2.4229662-.99805327 3.8994026-.99805327 1.4764365 0 2.7761236.33268442 3.8994028.99805327 1.122938.66571006 1.990988 1.61189868 2.604492 2.83890711.613505 1.2270084.920257 2.6618166.920257 4.3047658s-.306752 3.0777574-.920257 4.3047658c-.613504 1.2270084-1.481554 2.173197-2.604492 2.8389071-1.1232792.6653688-2.4229663.9980533-3.8994028.9980533-1.4764364 0-2.7764647-.3326845-3.8994026-.9980533zm7.4865938-2.6358843c.8318816-1.029445 1.2478226-2.532155 1.2478226-4.5077886 0-1.9131914-.426177-3.3950872-1.2788732-4.4453463-.8526958-1.04991795-2.0380759-1.57504751-3.5561406-1.57504751-1.5388787 0-2.7348365.52512956-3.5875323 1.57504751-.8526958 1.0502591-1.278873 2.5321549-1.278873 4.4453463 0 1.9756336.421059 3.4783436 1.2635183 4.5077886.8421182 1.0291038 2.0431942 1.543997 3.602887 1.543997 1.5596929 0 2.7553095-.5148932 3.5871912-1.543997z"/><path d="m130.334156 12.6829538v9.8573542h-2.526696v-9.7324695c0-1.4767777-.254546-2.5478509-.764321-3.21321974-.509434-.66536885-1.336197-.99805327-2.479949-.99805327-1.330738 0-2.370761.44699138-3.119386 1.34131535-.748625.89432396-1.122938 2.11075466-1.122938 3.64963346v8.9527937h-2.526695v-9.7324695c0-1.4559636-.260006-2.5215774-.780017-3.19752386-.520012-.67594651-1.351552-1.01374915-2.495645-1.01374915-1.330738 0-2.375879.44699138-3.135082 1.34131535-.758861.89432396-1.138292 2.11075466-1.138292 3.64963346v8.9527937h-2.527037v-11.2925036c0-1.62179388-.082915-3.08799385-.249428-4.39825865h2.402152l.249428 2.74507301c.436755-.99805327 1.086428-1.76749263 1.949701-2.30831808.862933-.54082544 1.866445-.81106756 3.010197-.81106756 1.247823 0 2.26669.24942801 3.056944.74862526.790253.49919724 1.372707 1.26863659 1.747019 2.30831807.478383-.93561096 1.180262-1.679118 2.105637-2.23017989.925374-.55106189 1.970515-.82676344 3.135081-.82676344 3.472884 0 5.209327 2.0691265 5.209327 6.20772068z"/><path d="m148.926608 6.84954575-7.330999 17.12591165c-.76944 1.7883067-1.736784 3.0985715-2.90135 3.9304532s-2.599374 1.4037577-4.304766 1.715628l-.530247-1.9653972c1.476436-.3326844 2.594256-.7745576 3.353459-1.3256195.758861-.5510619 1.388061-1.3986394 1.887259-2.5423914l.62374-1.4037577-6.644475-15.53482705h2.65158l5.30316 12.94568925 5.364238-12.94568925z"/></g><g fill="#f2f2f2" fill-rule="nonzero" transform="translate(1242.021555 73.436333)"><path d="m.1061178 18.7869453 1.3955685-17.74521654h3.91271003l-1.17104917 14.58010814h7.92539604l-.2490868 3.1651084z"/><path d="m14.0379178 18.7869453.9970296-12.63586623h3.763258l-.9970297 12.63586623zm1.2959338-18.56754419h4.0375946l-.2739955 3.53907983h-4.0375946z"/><path d="m20.1190478 17.4411941 1.2212078-2.6167762c.6981254.4817953 1.445727.8513309 2.243146 1.1089481.7977602.2576171 1.5951792.3862551 2.3925981.3862551.6977843 0 1.2130186-.0996347 1.5453618-.2989042.3323432-.1996106.4985148-.4654169.4985148-.7977601 0-.3487216-.1951748-.6230583-.5858658-.8223277-.3903497-.1996106-1.0260328-.4319779-1.906367-.6977842-.9141144-.2494281-1.661716-.4985149-2.243146-.7479429-.5817713-.2490868-1.0843807-.6189636-1.5078282-1.108948-.4237888-.4903257-.6356832-1.1256676-.6356832-1.9067083 0-.8141385.2286139-1.52864228.6855005-2.14317012.4568867-.61486905 1.1048535-1.09666434 1.9439007-1.44572707.8390472-.34872152 1.7985432-.5234235 2.878488-.5234235.9472123 0 1.8736104.14126293 2.7791945.42378878.9052428.28252585 1.6654694.66468641 2.2803385 1.1464817l-1.1962991 2.51714153c-.6148691-.44869746-1.262836-.78922982-1.9439007-1.02193831-.6814059-.23236727-1.3460923-.34872152-1.9940592-.34872152-.6810648 0-1.1962991.09963472-1.5450206.29890416-.3490627.19961066-.5234235.47360613-.5234235.82266887 0 .36544108.2074586.65615608.6230582.87214498.4152584.215989 1.046847.4405083 1.8940833.6728756.9137732.2661475 1.6572803.5234235 2.2305211.7728515.5732409.2490868 1.0717557.6189636 1.4955445 1.1089481.4237887.4903256.6353419 1.1256676.6353419 1.9067082 0 1.2461165-.494079 2.222332-1.4829195 2.9283054-.9884992.7063146-2.3219667 1.0594719-4.000061 1.0594719-2.1598896 0-4.087412-.5152343-5.7822259-1.5453618z"/><path d="m38.3876878 13.8772056c-.0498173.6977843.0914456 1.2130186.4237888 1.5453618.3323432.332002.7892298.4981736 1.3706598.4981736.3821606 0 .8059494-.0661957 1.2710251-.1992694l-.2490868 2.9160216c-.5650517.2327085-1.2959338.3490627-2.1933287.3490627-1.4286663 0-2.5212361-.3821605-3.2773681-1.1464817-.7557907-.7643211-1.1338567-1.8442659-1.1338567-3.2401757 0-.2825258.0081891-.4985148.0249087-.6479668l.3988801-4.98446573h-2.3925982l.2241782-2.8163869h2.3925981l.2241781-2.96583898 3.8632339-1.22120774-.3241541 4.18704672h3.215267l-.2245193 2.8163869h-3.2149258z"/><path d="m42.4003738 17.4411941 1.2212077-2.6167762c.6977843.4817953 1.4457271.8513309 2.2431461 1.1089481.7974189.2576171 1.5951791.3862551 2.3925981.3862551.6977842 0 1.2130186-.0996347 1.5453618-.2989042.332002-.1996106.4981736-.4654169.4981736-.7977601 0-.3487216-.1951749-.6230583-.5855246-.8223277-.3903497-.1996106-1.0260329-.4319779-1.9067083-.6977842-.9137732-.2494281-1.6613748-.4985149-2.243146-.7479429-.58143-.2490868-1.0840394-.6189636-1.5078282-1.108948-.4234475-.4903257-.6353419-1.1256676-.6353419-1.9067083 0-.8141385.2282727-1.52864228.6851593-2.14317012.4572278-.61486905 1.1051947-1.09666434 1.9442419-1.44572707.8390472-.34872152 1.7985432-.5234235 2.878488-.5234235.9472122 0 1.8732692.14126293 2.7788532.42378878.9055841.28252585 1.6658107.66468641 2.2806797 1.1464817l-1.196299 2.51714153c-.6148691-.44869746-1.262836-.78922982-1.9442419-1.02193831-.6810648-.23236727-1.3457512-.34872152-1.9937181-.34872152-.6814059 0-1.196299.09963472-1.5453618.29890416-.3487215.19961066-.5234235.47360613-.5234235.82266887 0 .36544108.2077999.65615608.6233995.87214498.4152584.215989 1.0465057.4405083 1.8940833.6728756.9137732.2661475 1.6572802.5234235 2.2305211.7728515.5732408.2490868 1.0717556.6189636 1.4955444 1.1089481.4234476.4903256.635342 1.1256676.635342 1.9067082 0 1.2461165-.4944203 2.222332-1.4829195 2.9283054-.9884993.7063146-2.3219667 1.0594719-4.000061 1.0594719-2.1598897 0-4.087412-.5152343-5.7822259-1.5453618z"/><path d="m67.62263 18.7869453v-16.0005853h-6.1811059v-1.74463124h14.430656v1.74463124h-6.181106v16.0005853z"/><path d="m86.688689 12.4567284h-9.1967623c.0167195 1.594838.3865964 2.7996674 1.1092893 3.6138059s1.7736345 1.2212077 3.1528247 1.2212077c1.4621054 0 2.8078565-.4903256 4.0372534-1.4706357l.6732168 1.4706357c-.5483322.5148932-1.2505522.9219624-2.1059777 1.2212078-.8557667.2989041-1.7323475.4486974-2.6294012.4486974-1.9606202 0-3.4977928-.5776766-4.6108355-1.7323475-1.1133839-1.1546708-1.6699052-2.737225-1.6699052-4.7476626 0-1.2795555.2490868-2.4134122.7476016-3.40225268.4985148-.98849926 1.1962991-1.75691497 2.093694-2.30524714.8970537-.54833217 1.918992-.82232765 3.0654737-.82232765 1.6613748 0 2.965839.54389638 3.9130512 1.63237157.9468711 1.08813397 1.4204772 2.587773 1.4204772 4.4985758zm-7.8632949-3.98777725c-.656156.63124737-1.0758502 1.52011191-1.2584001 2.66659365h7.3023377c-.0996347-1.17957958-.4446028-2.07697448-1.034222-2.69150233-.5899604-.61486905-1.4081934-.92230358-2.4550404-.92230358s-1.8981779.31562368-2.5546752.94721226z"/><path d="m96.7326876 6.10126171-.0498173 1.84426595c-.3821606-.13307377-.8226689-.19926944-1.3208425-.19926944-1.2130186 0-2.114508.37772478-2.7041272 1.13385676-.5899604.75613198-.88477 1.67399982-.88477 2.75394462v7.1528857h-2.0189679v-9.02206036c0-1.29593379-.0665369-2.46732417-.1992694-3.51417115h1.918992l.1992694 2.31787208c.3159649-.84723633.8226689-1.49554443 1.5204531-1.94390067.6977843-.44869745 1.4955445-.67287557 2.3925981-.67287557.4152584 0 .797419.04981736 1.1464817.14945208z"/><path d="m116.845594 10.9113666v7.8755787h-2.018627v-7.7759439c0-1.17957958-.203705-2.03534628-.610775-2.56695893-.407069-.53161264-1.067661-.79776018-1.981434-.79776018-1.063225 0-1.894083.35725189-2.492233 1.07175566-.598149.71450378-.897395 1.68662475-.897395 2.91602165v7.1528857h-2.018626v-7.7759439c0-1.16320127-.2078-2.01453218-.623059-2.55467519-.415258-.53980181-1.079944-.81004392-1.993718-.81004392-1.063566 0-1.898519.35725189-2.504857 1.07175566-.606339.71450378-.909679 1.68662475-.909679 2.91602165v7.1528857h-2.018968v-9.02206036c0-1.29593379-.0661956-2.46732417-.1992694-3.51417115h1.9189924l.19961 2.19332868c.348722-.79776018.868051-1.41228802 1.557646-1.84426595s1.491108-.64796689 2.404882-.64796689c.997029 0 1.811168.19926944 2.442415.59814953.631589.39853888 1.096664 1.01340793 1.39591 1.84426595.38216-.74794282.942776-1.34165656 1.682189-1.78216486.739412-.44016708 1.574365-.66025062 2.504858-.66025062 2.774758 0 4.162138 1.65318567 4.162138 4.95955697z"/><path d="m119.911067 17.3415594.672876-1.4955444c.681406.5316126 1.371001.9137732 2.068785 1.1464817s1.478825.3490627 2.342781.3490627c.946871 0 1.665469-.162077 2.155795-.4862311.489984-.3238128.735318-.7933244.735318-1.4078522 0-.4985148-.166172-.8973949-.498515-1.1962991-.332343-.2992453-.880675-.5319538-1.644996-.6981254l-2.118603-.4981736c-1.046506-.2327085-1.85655-.6483081-2.429791-1.2464577-.573241-.5981495-.859861-1.3123121-.859861-2.14317008 0-1.09666435.440167-1.98962346 1.320843-2.67921855.880675-.6895951 2.043876-1.03422204 3.489262-1.03422204.880675 0 1.711533.14092171 2.492233.42344756.781041.28252584 1.437197.68959509 1.96915 1.22120774l-.673216 1.47063576c-1.17958-.9803101-2.442416-1.47063576-3.788167-1.47063576-.897054 0-1.591085.17026618-2.081069.51113976-.489984.34053236-.735318.81823307-.735318 1.43310213 0 .51489308.153888.92196238.461323 1.22120778.307093.2989041.801513.5316126 1.482919.6977842l2.118261.5234235c1.163202.2658063 2.027158.6769702 2.592209 1.2334915.564711.5568625.847237 1.28365.847237 2.1807037 0 1.0802861-.440168 1.9442419-1.320843 2.5922088s-2.076974.9721209-3.588897.9721209c-2.110414 0-3.779978-.540143-5.009716-1.6200878z"/><path d="m146.77832 17.0672227h3.91271v1.7197226h-9.894546v-1.7197226h3.913051v-13.48310252l-3.638715 2.31753087v-1.96880935l4.53611-2.89111294h1.17139z"/><path d="m156.722343 16.2199864v1.8193573c0 .6977842-.116013 1.3375619-.348722 1.918992-.232708.5817712-.623058 1.1464817-1.17139 1.6948138l-.947212-.7226929c.647967-.7476016 1.013749-1.4621054 1.096664-2.1435113h-1.196299v-2.5669589z"/><path d="m171.801648 17.0672227v1.7197226h-11.415341v-1.5450206l6.204991-6.8788902c.832564-.93049277 1.436515-1.76953995 1.818675-2.51714156.382161-.74794282.573241-1.49554443.573241-2.24314604 0-.9803101-.279796-1.73200629-.846213-2.25542978-.563004-.5234235-1.371683-.78513524-2.4158-.78513524-1.696179 0-3.374274.68106472-5.03599 2.04353539l-.77251-1.56992926c.697784-.66468642 1.57846-1.19629906 2.641685-1.59517916 1.063567-.39888009 2.136346-.59814953 3.214585-.59814953 1.627594 0 2.917386.41935298 3.862551 1.25874137.948577.83904718 1.422866 1.97290393 1.422866 3.40191149 0 1.01340793-.228614 1.98962345-.685842 2.92830535-.457228.93868189-1.218137 1.98962347-2.279315 3.15282467l-5.061239 5.4829805z"/><path d="m177.435104 16.2199864v1.8193573c0 .6977842-.119425 1.3375619-.351451 1.918992-.232026.5817712-.621011 1.1464817-1.170367 1.6948138l-.948577-.7226929c.648308-.7476016 1.01682-1.4621054 1.098712-2.1435113h-1.197664v-2.5669589z"/><path d="m191.339607 11.2102708c.549356.7312233.822328 1.6535269.822328 2.7665695 0 1.5453618-.522059 2.762475-1.569588 3.6513395-1.04753.8888646-2.466983 1.3334674-4.261773 1.3334674-1.146482 0-2.245193-.1910802-3.302959-.5732408-1.054354-.3821606-1.948337-.9223036-2.678536-1.6200878l.798442-1.5702705c1.644656 1.3624706 3.354142 2.0438766 5.131871 2.0438766 1.265907 0 2.22472-.2825259 2.879853-.8475776.658544-.5647104.98611-1.3955685.98611-2.4922328 0-2.1766092-1.364859-3.2650844-4.087753-3.2650844h-2.043876v-1.71938129h1.644655c1.313677 0 2.316848-.29105622 3.016339-.87248623.696078-.58143001 1.047529-1.41228803 1.047529-2.49223284 0-.96359058-.290033-1.70300303-.859861-2.21823737-.573241-.51489312-1.385332-.77251029-2.432862-.77251029-1.692425 0-3.371202.68106472-5.032918 2.04353539l-.771145-1.56992926c.713139-.68140594 1.590061-1.21711317 2.627354-1.6078041 1.037293-.39034973 2.122356-.58552459 3.251777-.58552459 1.596885 0 2.873028.40706925 3.82843 1.22120775.955401.81413849 1.433102 1.91080284 1.433102 3.28999303 0 1.01340793-.252499 1.90227247-.750673 2.6665936-.498174.76432114-1.187427 1.31265331-2.067762 1.64499652 1.04753.29890416 1.845972.81413848 2.391916 1.54502058z"/></g><g transform="translate(1238.737766 301.42884)"><path d="m.162355.124952h196.432387v68.608179h-196.432387z" fill="#0083c0"/><path d="m196.594742 68.7331309h-196.43238687v-68.60817855h196.43238687zm-193.8939261-66.06958614v63.53099374h191.3558681v-63.53099374z" fill="#000"/></g><g fill="#f2f2f2" fill-rule="nonzero" transform="translate(1249.006069 345.842567)"><path d="m.56874621 14.4291604 1.02879531-13.08192845h2.88430112l-.8634532 10.74723665h5.84208763l-.18371345 2.3346918z"/><path d="m10.8383279 14.4291604.7348538-9.31580278h2.7740731l-.7348538 9.31580278zm.95531-13.68665188h2.9761578l-.2020848 2.6102619h-2.9761578z"/><path d="m15.320936 13.4340458.9001959-1.9289912c.5143977.3597722 1.065538.6276877 1.6534211.8190558.587883.1913682 1.175766.2832249 1.7636491.2832249.5143976 0 .8940721-.0688925 1.1390233-.2143323.2449513-.1530946.3674269-.3444627.3674269-.589414 0-.2602607-.1439088-.4592836-.4317266-.6047234-.2878177-.1530946-.756287-.3214986-1.4054078-.5205215-.673616-.1837134-1.2247564-.3674269-1.6534211-.5511403-.4286647-.18371346-.7991535-.4516289-1.1114663-.81140107-.3123129-.36742689-.4684693-.83436524-.4684693-1.40846976 0-.59706871.168404-1.12524487.505212-1.57687376.3368079-.45928362.8144629-.81140106 1.4329648-1.07166178.618502-.25260599 1.3257988-.38273635 2.1218904-.38273635.6981111 0 1.3809127.10716618 2.0484049.31384381s1.2278182.48990253 1.6809781.84201997l-.8818246 1.86009865c-.4531598-.33680798-.9308148-.58175925-1.4329649-.75781797-.5021501-.16840399-.9920526-.25260599-1.4697076-.25260599-.5021501 0-.8818245.06889254-1.1390233.21433236-.2571989.15309454-.3857983.35211744-.3857983.61237816 0 .26791544.1530946.4822478.4592836.64299706.3061891.15309454.7715965.32149853 1.3962222.48990253.673616.1990229 1.2216945.39039107 1.6442354.57410452s.7899678.45162889 1.1022807.81905582c.3123128.3597721.4684693.8267105.4684693 1.400815 0 .9185672-.364365 1.6381116-1.093095 2.158633-.7287301.5205214-1.711597.7807822-2.9486009.7807822-1.5921832 0-3.0129005-.3750817-4.262152-1.1405544z"/><path d="m28.7871317 10.8084745c-.0367426.5128667.0673616.895603.3123129 1.1405543s.5817593.3674269 1.010424.3674269c.2816939 0 .5940068-.0459284.9369385-.1454398l-.1837134 2.1509783c-.4164171.168404-.9553099.252606-1.6166783.252606-1.0532905 0-1.8585677-.2832249-2.4158319-.84202-.5572641-.5664498-.8358962-1.3625414-.8358962-2.3882748 0-.2066776.0061238-.3674269.0183714-.4822478l.2939415-3.67426897h-1.7636491l.1653421-2.07443101h1.7636491l.1653421-2.18159719 2.8475584-.90325778-.2388274 3.08485497h2.3699034l-.1653421 2.07443101h-2.3699034z"/><path d="m31.7449182 13.4340458.9001959-1.9289912c.5143977.3597722 1.065538.6276877 1.6534211.8190558.587883.1913682 1.175766.2832249 1.7636491.2832249.5143976 0 .8940721-.0688925 1.1390233-.2143323.2449513-.1530946.3674269-.3444627.3674269-.589414 0-.2602607-.1439088-.4592836-.4317266-.6047234-.2878177-.1530946-.756287-.3214986-1.4054078-.5205215-.673616-.1837134-1.2247564-.3674269-1.6534211-.5511403-.4286647-.18371346-.7991535-.4516289-1.1114663-.81140107-.3123129-.36742689-.4684693-.83436524-.4684693-1.40846976 0-.59706871.168404-1.12524487.505212-1.57687376.3368079-.45928362.8144629-.81140106 1.4329649-1.07166178.6185019-.25260599 1.3257987-.38273635 2.1218903-.38273635.6981111 0 1.3809127.10716618 2.0484049.31384381s1.2278182.48990253 1.6809781.84201997l-.8818246 1.86009865c-.4531598-.33680798-.9308148-.58175925-1.4329649-.75781797-.5021501-.16840399-.9920526-.25260599-1.4697076-.25260599-.5021501 0-.8818245.06889254-1.1390233.21433236-.2571989.15309454-.3857983.35211744-.3857983.61237816 0 .26791544.1530946.4822478.4592836.64299706.3061891.15309454.7715965.32149853 1.3962222.48990253.673616.1990229 1.2216945.39039107 1.6442354.57410452s.7899678.45162889 1.1022807.81905582c.3123128.3597721.4684693.8267105.4684693 1.400815 0 .9185672-.364365 1.6381116-1.093095 2.158633-.7287301.5205214-1.711597.7807822-2.9486009.7807822-1.5921832 0-3.0129005-.3750817-4.262152-1.1405544z"/><path d="m52.3208244 13.1584757h2.8843011v1.2706847h-7.2934239v-1.2706847h2.8843011v-9.93583564l-2.6822163 1.70700411v-1.4467434l3.3435848-2.13566882h.8634532z"/><path d="m59.6509909 12.5384428v1.3395772c0 .5128667-.0857329.9874598-.2571988 1.4161245s-.4592836.84202-.8634532 1.2477205l-.6981111-.5358309c.4776549-.5511403.7471013-1.0716618.8083392-1.5768737h-.8818246v-1.8907176z"/><path d="m70.7656545 13.1584757v1.2706847h-8.4140759v-1.1405544l4.5744648-5.06742923c.6123782-.68892542 1.0594142-1.30895831 1.3411082-1.86009865.2816939-.55114034.4225409-1.10228069.4225409-1.65342103 0-.71954434-.2082085-1.27068468-.6246257-1.66107575-.4164171-.38273635-1.010424-.57410453-1.7820204-.57410453-1.2492515 0-2.4862554.49755726-3.7110117 1.50032649l-.5695117-1.15586377c.5143977-.48990253 1.1635185-.8802936 1.9473626-1.17117323.783844-.29853435 1.5738118-.44397416 2.3699035-.44397416 1.2002611 0 2.1494473.30618907 2.8475584.92622196.6981111.62003288 1.0471666 1.45439813 1.0471666 2.51075045 0 .74250851-.168404 1.46205285-.5052119 2.15863301-.336808.68892542-.897134 1.46205285-1.6809781 2.31938227l-3.729383 4.04169587z"/><path d="m74.9175784 12.5384428v1.3395772c0 .5128667-.0857329.9874598-.2571988 1.4161245s-.4592837.84202-.8634532 1.2477205l-.6981111-.5358309c.4776549-.5511403.7471013-1.0716618.8083391-1.5768737h-.8818245v-1.8907176z"/><path d="m85.1687888 8.84120966c.4041695.54348561.6062543 1.22475634.6062543 2.04381214 0 1.1405543-.3857982 2.0361573-1.1573947 2.6868091-.7715965.6583065-1.8187631.9874598-3.1414999.9874598-.8450819 0-1.6564829-.1454398-2.4342032-.42101-.7777203-.2832249-1.4360268-.6812707-1.9749196-1.1941374l.5878831-1.1635185c1.2125087 1.010424 2.4740077 1.5079812 3.784497 1.5079812.9308148 0 1.6381116-.2066776 2.1218903-.6200329.4837787-.4210099.7256681-1.0333881.7256681-1.8371344 0-1.60749269-1.0043002-2.41123903-3.0129005-2.41123903h-1.5064503v-1.26302995h1.2125088c.9675574 0 1.708535-.21433235 2.2229327-.64299706.5143976-.42866471.7715965-1.04104287.7715965-1.83713448 0-.71188961-.2112705-1.25537522-.6338114-1.63811157-.422541-.38273635-1.0196097-.5664498-1.7912062-.5664498-1.2492514 0-2.4862553.49755726-3.7110116 1.50032649l-.5695117-1.15586377c.5266452-.49755726 1.1727042-.89560306 1.9381769-1.18648268.7654727-.2832249 1.5646262-.42866471 2.3974605-.42866471 1.175766 0 2.1157665.29853435 2.8200014.90325778.7042349.5970687 1.0563523 1.40846976 1.0563523 2.41889372 0 .75016325-.1837134 1.40846977-.5511403 1.96726484-.3674269.56644979-.8757008.97215032-1.5248216 1.21710159.7715964.21433235 1.3594795.5970687 1.7636491 1.13289959z"/><path d="m90.1841659 12.5384428v1.3395772c0 .5128667-.085733.9874598-.2571988 1.4161245-.1714659.4286647-.4592837.84202-.8634533 1.2477205l-.6981111-.5358309c.477655-.5511403.7471014-1.0716618.8083392-1.5768737h-.8818245v-1.8907176z"/><path d="m101.776484 10.3338814v1.2477205h-1.9841048v2.8475585h-1.5064503v-2.8475585h-6.0258011v-1.1405543l6.3013713-9.09381565h1.2308801v8.98664945zm-7.9547919 0h4.4642368v-6.42997064z"/><path d="m105.450753 12.5384428v1.3395772c0 .5128667-.085733.9874598-.257198 1.4161245-.171466.4286647-.459284.84202-.863454 1.2477205l-.698111-.5358309c.477655-.5511403.747102-1.0716618.808339-1.5768737h-.881824v-1.8907176z"/><path d="m114.847696 6.74381447c.618502.34446271 1.093095.83436524 1.423779 1.45439812.330685.62768761.496027 1.34723195.496027 2.17394251 0 .8190557-.180652 1.5462548-.541955 2.1815971-.361303.6353424-.875701 1.1328996-1.543193 1.4773623-.667492.3521175-1.448274.5281762-2.342346.5281762-.796092 0-1.579936-.1454398-2.351532-.4363194-.771597-.2832249-1.420718-.6812707-1.947363-1.178828l.569512-1.1635185c1.212508 1.010424 2.455636 1.5079812 3.729383 1.5079812.918567 0 1.638111-.2602607 2.158633-.7807821.520521-.5205215.780782-1.2247563.780782-2.1203594 0-.87263887-.257199-1.56921902-.771597-2.10504991-.514397-.52817616-1.200261-.79609161-2.05759-.79609161-1.249252 0-2.247428.50521198-2.994529 1.52329067h-1.047167v-7.6623817h7.844564v1.2477205h-6.338114v4.66938345c.722606-.69658015 1.647297-1.04869759 2.774073-1.04869759.820587 0 1.540131.17605872 2.158633.52817616z"/><path d="m120.717341 12.5384428v1.3395772c0 .5128667-.085733.9874598-.257199 1.4161245s-.459284.84202-.863453 1.2477205l-.698111-.5358309c.477655-.5511403.747101-1.0716618.808339-1.5768737h-.881825v-1.8907176z"/><path d="m130.077541 6.74381447c.618502.34446271 1.099219.83436524 1.442151 1.46970758.342931.62768761.514397 1.34723194.514397 2.15863305 0 .8037463-.180651 1.5309453-.541954 2.1662877-.361304.6353423-.860392 1.1328996-1.497265 1.4926717-.636873.3674269-1.35948.5434857-2.167819.5434857-1.579935 0-2.798568-.5511404-3.655897-1.6534211-.85733-1.1022806-1.285994-2.6714997-1.285994-4.70000233 0-1.46970758.199022-2.73273753.597068-3.78908985.398046-1.0486976.973681-1.85244393 1.726907-2.40358427.753225-.55114034 1.656483-.82671051 2.709773-.82671051.759349 0 1.497265.13778508 2.213747.42100998s1.34417.6812707 1.883063 1.19413741l-.569512 1.15586377c-.612378-.51286671-1.200261-.88794833-1.763649-1.13289959s-1.139023-.3674269-1.726906-.3674269c-1.126776 0-2.002477.49755726-2.627103 1.50032649-.624625 1.01042396-.936938 2.41889373-.936938 4.22540929v.27557017c.281694-.69658015.740977-1.24772049 1.377851-1.65342102.636873-.39804581 1.365603-.60472343 2.18619-.60472343.796091 0 1.503388.17605872 2.12189.52817616zm-.303127 5.76400943c.514397-.5281762.771596-1.2400658.771596-2.1203594 0-.87263887-.26026-1.56921902-.780782-2.10504991-.520521-.52817616-1.197199-.79609161-2.030033-.79609161-.85733 0-1.555441.26791545-2.094334.80374634-.538893.54348561-.808339 1.24006577-.808339 2.09739518 0 .8726389.269446 1.5768738.808339 2.1127047.538893.5358308 1.243128.811401 2.112705.811401.832834 0 1.50645-.2679154 2.020848-.8037463z"/><path d="m135.983928 12.5384428v1.3395772c0 .5128667-.085733.9874598-.257199 1.4161245-.171465.4286647-.459283.84202-.863453 1.2477205l-.698111-.5358309c.477655-.5511403.747102-1.0716618.808339-1.5768737h-.881824v-1.8907176z"/><path d="m138.353832 1.34723195h8.634532v1.12524486l-6.136029 11.95668359h-1.616679l6.099287-11.81124377h-6.981111z"/><path d="m151.250516 12.5384428v1.3395772c0 .5128667-.085733.9874598-.257199 1.4161245s-.459284.84202-.863453 1.2477205l-.698111-.5358309c.477655-.5511403.747101-1.0716618.808339-1.5768737h-.881825v-1.8907176z"/><path d="m161.915081 8.9101022c.471532.5664498.707297 1.2477205.707297 2.0438121 0 1.1175901-.422541 1.9978837-1.267623 2.6408808-.845081.6429971-1.984105.9644956-3.41707.9644956s-2.571988-.3214985-3.41707-.9644956-1.267623-1.5232907-1.267623-2.6408808c0-.7960916.24189-1.4773623.725669-2.05146683.483778-.58175925 1.148209-.97980505 1.99329-1.1941374-.783844-.23729654-1.383974-.62003289-1.800391-1.14820905-.416418-.53583089-.624626-1.1635185-.624626-1.88306284 0-.70423488.183713-1.30895831.55114-1.82947974.367427-.52052144.884887-.92622197 1.552379-1.21710159.667492-.2832249 1.429903-.42866471 2.287232-.42866471.85733 0 1.619741.14543981 2.287233.42866471.667492.29087962 1.184951.69658015 1.552378 1.21710159.367427.52052143.551141 1.12524486.551141 1.82947974 0 .71954434-.211271 1.34723195-.633812 1.88306284-.422541.52817616-1.013486.91091251-1.772834 1.14820905.857329.2296418 1.521759.62768761 1.99329 1.20179213zm-6.080915-2.42654845c.520522.43631944 1.221695.70423488 2.103519.7960916.881825-.09185672 1.582998-.35977216 2.103519-.7960916.520522-.43631944.780782-1.00276923.780782-1.69934939 0-.71954434-.254137-1.29364886-.76241-1.70700412-.508274-.42100998-1.215571-.62768761-2.121891-.62768761-.906319 0-1.613616.20667763-2.12189.62768761-.508274.41335526-.762411.98745978-.762411 1.70700412 0 .69658016.260261 1.26302995.780782 1.69934939zm4.473423 6.20032885c.55114-.4133553.82671-1.0257334.82671-1.821825 0-.7195444-.290879-1.30130361-.872639-1.72996832-.581759-.43631943-1.356417-.70423488-2.323975-.80374633-.967557.09951145-1.742216.3674269-2.323975.80374633-.581759.42866471-.872639 1.01042392-.872639 1.72996832 0 .7960916.27557 1.4084697.826711 1.821825.55114.4133553 1.341108.6276876 2.369903.6276876 1.028796 0 1.818763-.2143323 2.369904-.6276876z"/><path d="m166.517103 12.5384428v1.3395772c0 .5128667-.085733.9874598-.257199 1.4161245-.171465.4286647-.459283.84202-.863453 1.2477205l-.698111-.5358309c.477655-.5511403.747102-1.0716618.808339-1.5768737h-.881824v-1.8907176z"/><path d="m176.456001 2.85521316c.857329 1.10228069 1.285994 2.67149972 1.285994 4.70000237 0 2.21987082-.443974 3.94218437-1.331923 5.17459547-.887948 1.232411-2.128014 1.8447892-3.720197 1.8447892-.747101 0-1.478893-.1377851-2.195376-.42101-.716482-.2832249-1.350293-.6812707-1.901434-1.1941374l.587883-1.1558638c.624626.5281762 1.218633.9109125 1.782021 1.148209.563388.2372966 1.132899.3597722 1.708535.3597722 1.126776 0 1.999414-.505212 2.617916-1.5079812s.927753-2.411239.927753-4.22540929v-.23729654c-.281694.6812707-.740977 1.22475632-1.377851 1.62280212-.636873.3980458-1.365603.5970687-2.18619.5970687-.796091 0-1.500326-.17605872-2.112704-.52052143-.612378-.35211744-1.090033-.84201997-1.432965-1.46970758-.342932-.63534234-.514398-1.35488667-.514398-2.15863301 0-.81140106.180652-1.53094539.541955-2.17394246.361303-.63534234.860391-1.13289959 1.497265-1.49267176.636873-.35977217 1.359479-.54348561 2.167818-.54348561 1.579936 0 2.798568.55114034 3.655898 1.65342102zm-1.469708 4.63110982c.538893-.54348561.808339-1.24006577.808339-2.09739519 0-.86498415-.269446-1.56921903-.808339-2.11270464-.538893-.53583089-1.243127-.80374634-2.112704-.80374634-.832835 0-1.506451.26026072-2.020848.79609161-.514398.53583089-.771597 1.24006577-.771597 2.12035937 0 .87263888.257199 1.56921903.771597 2.10504992.514397.53583089 1.194137.79609161 2.039219.79609161.857329 0 1.55544-.26791545 2.094333-.80374634z"/></g><g fill="#f2f2f2" fill-rule="nonzero" transform="translate(1307.966463 315.478416)"><path d="m15.7309762 20.418335h-2.3788531l-2.4066219-6.4812177c-.2915715-.8025158-.6979203-1.3403033-1.21719525-1.6133623-.51927495-.2739846-1.2532946-.4100513-2.20205898-.4100513h-4.86785547v8.5046313h-2.21501771v-19.47142187h7.74006606c2.09653785 0 3.70527205.46466314 4.82620245 1.39491504 1.121856.92932627 1.6818584 2.26962951 1.6818584 4.01998408 0 1.2764352-.332299 2.34738191-.9978225 3.21284015-.6655235.8663839-1.6272466 1.4819237-2.8851693 1.8466194.5655561.0907112 1.0487317.332299 1.4495268.7247635.4007951.3915388.7386478.9524668 1.0117068 1.6818584zm-7.73914047-10.3651351c2.98976477 0 4.48464727-1.22089777 4.48464727-3.66454456 0-1.20331091-.3646958-2.10116598-1.0940874-2.6935652-.7284659-.59239922-1.85957813-.88859883-3.39055987-.88859883h-5.33344423v7.24670859z"/><path d="m18.2745903 18.1755486.8478714-1.7225859c.9663512.8201027 1.9502893 1.4041713 2.9536655 1.7503546 1.0024506.3461833 2.1696621.5192749 3.5007091.5192749 1.5680067 0 2.7759458-.3054558 3.6228915-.9154419.8478714-.6109117 1.2718071-1.4726674 1.2718071-2.5843416 0-.6571929-.2045629-1.1903522-.6146142-1.6004035-.410977-.4100513-.9487644-.7340197-1.6142879-.9709794-.6655235-.2369596-1.5541223-.4831756-2.6657965-.7377221-1.495808-.3285964-2.725962-.684036-3.6923132-1.0672442-.9663513-.3822826-1.7503546-.93395442-2.3520101-1.65408972-.6016554-.72013531-.9024831-1.66427156-.9024831-2.83055753 0-1.11259978.2915714-2.09190974.8747144-2.93978113.5840686-.84787138 1.4087994-1.50876676 2.475118-1.98268614 1.0672442-.474845 2.3112826-.71180469 3.7330407-.71180469 1.3495595 0 2.6074822.2101166 3.7746938.62942417 1.166286.41930758 2.1511497 1.03021927 2.9536655 1.83180947l-.8756401 1.72351148c-.9117394-.78400334-1.8364376-1.35881571-2.7759457-1.72351148-.9385825-.36377015-1.9641737-.54611803-3.0767735-.54611803-1.5133948 0-2.6981933.3230427-3.5553209.97005372-.856202.64793665-1.2847658 1.53653548-1.2847658 2.66672212 0 .9848637.373952 1.72258585 1.1209304 2.21501771.747904.49243185 1.8966031.92099566 3.4460973 1.28569143 1.6772303.40079512 2.994393.77011902 3.9514879 1.10797162.957095.3369271 1.7549827.8469458 2.3927375 1.5309818.6386804.684036.9580206 1.5911473.9580206 2.7213339 0 1.0940873-.2924971 2.0558104-.8756401 2.8851693-.5831429.8293589-1.41713 1.4726675-2.501961 1.9280744-1.0848311.4554069-2.3566382.6840359-3.8154213.6840359-3.0443766 0-5.4695109-.8210283-7.2744773-2.4621592z"/><path d="m35.3125473 18.1755486.8478714-1.7225859c.9663512.8201027 1.9502893 1.4041713 2.9536654 1.7503546 1.0024506.3461833 2.1696622.5192749 3.5007092.5192749 1.5680067 0 2.7750201-.3054558 3.6228915-.9154419.8478714-.6109117 1.271807-1.4726674 1.271807-2.5843416 0-.6571929-.2045628-1.1903522-.6155398-1.6004035-.4100513-.4100513-.9478387-.7340197-1.6133622-.9709794-.6655235-.2369596-1.5541223-.4831756-2.6657965-.7377221-1.495808-.3285964-2.725962-.684036-3.6923133-1.0672442-.9663512-.3822826-1.7503545-.93395442-2.35201-1.65408972-.6016555-.72013531-.9024832-1.66427156-.9024832-2.83055753 0-1.11259978.2915715-2.09190974.8747145-2.93978113.5840686-.84787138 1.4087994-1.50876676 2.475118-1.98268614 1.0672442-.474845 2.3112826-.71180469 3.7330407-.71180469 1.3495595 0 2.6074822.2101166 3.7746938.62942417 1.1662859.41930758 2.1511496 1.03021927 2.9536655 1.83180947l-.8756401 1.72351148c-.9117395-.78400334-1.8364376-1.35881571-2.7759458-1.72351148-.9385825-.36377015-1.9641736-.54611803-3.0767734-.54611803-1.5133949 0-2.6981933.3230427-3.555321.97005372-.856202.64793665-1.2847658 1.53653548-1.2847658 2.66672212 0 .9848637.373952 1.72258585 1.1209304 2.21501771.747904.49243185 1.8966032.92099566 3.4460974 1.28569143 1.6772303.40079512 2.9943929.77011902 3.9514879 1.10797162.957095.3369271 1.7549827.8469458 2.3927375 1.5309818.6386804.684036.9580206 1.5911473.9580206 2.7213339 0 1.0940873-.2924971 2.0558104-.8756401 2.8851693s-1.41713 1.4726675-2.5019611 1.9280744-2.3566381.6840359-3.8154212.6840359c-3.0443766 0-5.469511-.8210283-7.2744773-2.4621592z"/></g><g transform="translate(1132.952069 387.954528)"><path d="m.039304.099422h47.553665v54.590201h-47.553665z" fill="#00a88a"/><path d="m47.5929694 54.6896229h-47.55366538v-54.59020073h47.55366538zm-45.01519163-52.05176699v49.51333329h42.47652283v-49.51333329z" fill="#000"/></g><path d="m23.6732656 32.2046798v3.383959h-22.46109685v-3.0406798l12.21155275-13.5355472c1.6346218-1.8308227 2.8280084-3.4819151 3.5798709-4.953277.7521514-1.4710729 1.1280827-2.9424349 1.1280827-4.4137968 0-1.92877865-.5559506-3.40823133-1.6675628-4.43806909-1.1116122-1.03012673-2.6971116-1.54504561-4.7570761-1.54504561-3.33483658 0-6.63673225 1.34046504-9.90626489 4.02168407l-1.52048438-3.08980225c1.37340598-1.30781306 3.10598377-2.35383234 5.19860024-3.13863575 2.09232752-.78480342 4.2011255-1.17691617 6.32639393-1.17691617 3.2039397 0 5.7377914.82554616 7.6015551 2.47663847 1.8634746 1.65109231 2.7953564 3.88240747 2.7953564 6.69394548 0 1.99437155-.4496149 3.91534845-1.3488447 5.76264155-.8989409 1.8470042-2.394864 3.9150595-4.4871916 6.2035878l-9.95538731 10.7893133z" fill="#f2f2f2" fill-rule="nonzero" transform="translate(1144.791113 397.615433)"/><g transform="translate(1191.307406 387.954528)"><path d="m.039304.099422h47.553665v54.590201h-47.553665z" fill="#00a88a"/><path d="m47.5929694 54.6896229h-47.55366538v-54.59020073h47.55366538zm-45.0150941-52.05176699v49.51333329h42.4764253v-49.51333329z" fill="#000"/></g><path d="m21.6572224 20.6796856c1.0789602 1.4387099 1.6184403 3.2533511 1.6184403 5.4436346 0 3.0406798-1.0298378 5.4355438-3.0895133 7.184881-2.0599645 1.7490483-4.855321 2.6237169-8.3860695 2.6237169-2.25616532 0-4.42217651-.3762202-6.49803356-1.1280827-2.076146-.7518625-3.83357397-1.8146412-5.27199496-3.1877582l1.56931788-3.0895133c3.2365917 2.6809301 6.60408028 4.0213951 10.10246574 4.0213951 2.4847292 0 4.3730541-.5559506 5.6643967-1.6675628s1.9371583-2.746234 1.9371583-4.9041544c0-4.2829-2.68093-6.4243499-8.0427902-6.4243499h-4.02168406v-3.3839591h3.23688066c2.5829741 0 4.5608752-.5721321 5.9339922-1.7163963 1.3731171-1.1442642 2.0599645-2.779175 2.0599645-4.90415445 0-1.89641562-.5640413-3.35130707-1.692124-4.36467437-1.1277937-1.01365625-2.7216728-1.52048438-4.7816373-1.52048438-3.33483658 0-6.63673225 1.34046504-9.90626489 4.02168407l-1.52048437-3.08980225c1.40605796-1.34046504 3.13054499-2.39486403 5.17403901-3.16319698 2.04349402-.76833294 4.17685323-1.15235494 6.40007765-1.15235494 3.1386357 0 5.6479262.80098493 7.5278713 2.40295479 1.8799452 1.60196986 2.8199177 3.75989029 2.8199177 6.47347235 0 1.99437156-.4906466 3.74341986-1.4713619 5.24743376s-2.3376508 2.5829741-4.0705175 3.2368806c2.0596755.5883136 3.6292823 1.6019699 4.7079536 3.0403909z" fill="#f2f2f2" fill-rule="nonzero" transform="translate(1203.470522 396.880376)"/><g transform="translate(1249.976943 388.127483)"><path d="m.039304.099422h47.553665v54.590201h-47.553665z" fill="#00a88a"/><path d="m47.5929694 54.6896229h-47.55366538v-54.59020073h47.55366538zm-45.01519163-52.05176699v49.51333329h42.47652283v-49.51333329z" fill="#000"/></g><path d="m25.5263379 24.074336v3.3348366h-5.2965562v7.601555h-4.0213951v-7.601555h-16.08558047v-3.0406798l16.82126147-24.27573805h3.2857141v23.98158125zm-21.23505825 0h11.91710695v-17.16454069z" fill="#f2f2f2" fill-rule="nonzero" transform="translate(1260.680298 397.799392)"/><g transform="translate(1072.3219 388.127483)"><path d="m.039304.099422h47.553665v54.590201h-47.553665z" fill="#00a88a"/><path d="m47.5929694 54.6896229h-47.55366538v-54.59020073h47.55366538zm-45.0150941-52.05176699v49.51333329h42.4764253v-49.51333329z" fill="#000"/></g><path d="m12.0107286 31.6267686h7.6995109v3.383959h-19.46953948v-3.383959h7.69951097v-26.53161447l-7.16003086 4.56087523v-3.87431672l8.92554959-5.68895789h2.30499888z" fill="#f2f2f2" fill-rule="nonzero" transform="translate(1086.781678 397.799392)"/><g transform="translate(1310.293872 388.430153)"><path d="m.039304.099422h47.553665v54.590201h-47.553665z" fill="#00a88a"/><path d="m47.5929694 54.6896229h-47.55366538v-54.59020073h47.55366538zm-45.01519163-52.05176699v49.51333329h42.47652283v-49.51333329z" fill="#000"/></g><path d="m18.2209624 14.4865002c1.6510923.9318818 2.9181626 2.2316041 3.8009219 3.8988779.8827594 1.6675628 1.3239946 3.5963414 1.3239946 5.7869138 0 2.1905725-.4822669 4.1358216-1.4468007 5.8360363-.9642448 1.7002148-2.3376508 3.0161186-4.119351 3.9480004-1.7819892.9315929-3.866226 1.3976783-6.2529993 1.3976783-2.12497947 0-4.21730699-.384311-6.27727148-1.1526439-2.05967553-.768333-3.79254227-1.822732-5.19831128-3.163197l1.52019542-3.0895133c3.23688066 2.6809301 6.55524679 4.0213951 9.95538734 4.0213951 2.4523662 0 4.3730541-.6946492 5.7626416-2.0842367 1.3892985-1.3895875 2.0842368-3.2776234 2.0842368-5.6643967 0-2.3211804-.6865586-4.1930347-2.0596756-5.6152742-1.373406-1.4222395-3.2042286-2.1333592-5.492757-2.1333592-3.33483662 0-5.99958518 1.3569355-7.99395675 4.0705175h-2.79535649v-20.45054375h20.94090144v3.3348366h-16.91950633v12.45687605c1.9290676-1.8637637 4.39761531-2.7956455 7.40535413-2.7956455 2.1905725 0 4.1112603.4660854 5.7623527 1.3976783z" fill="#f2f2f2" fill-rule="nonzero" transform="translate(1322.999783 398.270213)"/><g transform="translate(1374.317793 388.430153)"><path d="m.039304.099422h47.553665v54.590201h-47.553665z" fill="#00a88a"/><path d="m47.5929694 54.6896229h-47.55366538v-54.59020073h47.55366538zm-45.01519163-52.05176699v49.51333329h42.47652283v-49.51333329z" fill="#000"/></g><path d="m19.2788288 15.0644114c1.6510923.9318818 2.9343442 2.2396948 3.8497555 3.9234391.9154114 1.6837443 1.373117 3.6047212 1.373117 5.7623526 0 2.1579205-.4822669 4.0869881-1.4468007 5.7869139-.9642448 1.7002148-2.2966191 3.032589-3.9968339 3.9971228-1.6999258.9642449-3.6289934 1.4465118-5.7869138 1.4465118-4.21759597 0-7.47065814-1.471073-9.75918651-4.4137968-2.28881733-2.9424349-3.43308151-7.1273789-3.43308151-12.554543 0-3.9234392.53138935-7.2909278 1.5938791-10.10246581 1.06248975-2.81182696 2.59915564-4.95327693 4.60999768-6.42463886 2.01055308-1.47136192 4.42188754-2.20675393 7.23371454-2.20675393 2.0270235 0 3.9968339.37593124 5.909431 1.12779372 1.9125972.75215143 3.5882507 1.81464118 5.0266717 3.1877582l-1.5201954 3.08980225c-1.6346219-1.37340597-3.2039398-2.38677327-4.7079537-3.0406798s-3.0406798-.98100427-4.6099976-.98100427c-3.0077389 0-5.34538973 1.34046504-7.01295251 4.02168407-1.66727383 2.68093003-2.5011997 6.44053143-2.5011997 11.27938193v.735681c.75215144-1.8634747 1.97819006-3.3348366 3.67811586-4.4137969 1.70021477-1.0789602 3.64546385-1.6184403 5.83603635-1.6184403 2.1252684 0 4.0133043.4660854 5.6643966 1.3976783zm-.8090757 15.3993109c1.3731171-1.4222395 2.0596756-3.3102754 2.0596756-5.6643967 0-2.3211804-.6949383-4.1930347-2.0842368-5.6152742-1.3895875-1.4222395-3.195849-2.1333592-5.4190734-2.1333592-2.2888173 0-4.15229196.7192105-5.5910019 2.1579204-1.43842099 1.438421-2.15763148 3.3021846-2.15763148 5.590713 0 2.3211803.71921049 4.2011255 2.15763148 5.6398354 1.43870994 1.438421 3.3186551 2.1579205 5.6398354 2.1579205 2.2232244 0 4.0213952-.7111198 5.3948011-2.1333592z" fill="#f2f2f2" fill-rule="nonzero" transform="translate(1384.69083 397.697106)"/><g transform="translate(1436.988825 388.430153)"><path d="m.039304.099422h47.553665v54.590201h-47.553665z" fill="#00a88a"/><path d="m47.5929694 54.6896229h-47.55366538v-54.59020073h47.55366538zm-45.01528916-52.05176699v49.51333329h42.47662036v-49.51333329z" fill="#000"/></g><path d="m.04045378.09275475h23.04969942v2.99155735l-16.38002621 31.9264155h-4.31555192l16.28178133-31.5340138h-18.63590262z" fill="#f2f2f2" fill-rule="nonzero" transform="translate(1447.938813 398.275017)"/><g transform="translate(1499.78573 388.430153)"><path d="m.039304.099422h47.553665v54.590201h-47.553665z" fill="#00a88a"/><path d="m47.5929694 54.6896229h-47.55366538v-54.59020073h47.55366538zm-45.01519163-52.05176699v49.51333329h42.47652283v-49.51333329z" fill="#000"/></g><path d="m23.338655 20.8516142c1.2586906 1.5201954 1.8880359 3.3429273 1.8880359 5.4679068 0 2.9753759-1.1277937 5.3211174-3.3836701 7.0375137-2.2561653 1.7166852-5.2965562 2.5748834-9.1217504 2.5748834-3.82548323 0-6.86587408-.8581982-9.12175046-2.5748834-2.25616535-1.7163963-3.38395906-4.0621378-3.38395906-7.0375137 0-2.1249795.64552681-3.9558022 1.93715836-5.4924681 1.29134258-1.5366659 3.06495207-2.5994446 5.32082845-3.1877582-2.09232751-.6212545-3.69429737-1.6430015-4.80590957-3.065241s-1.66756278-3.0976041-1.66756278-5.02667165c0-1.86347468.49064661-3.49029472 1.47136193-4.87959325.98071531-1.38958749 2.36221204-2.46854771 4.14391229-3.23688066 1.78198919-.76833294 3.81710354-1.15235494 6.10592084-1.15235494 2.2885284 0 4.3236427.384022 6.1056319 1.15235494 1.7817002.76833295 3.1631969 1.84729317 4.1439122 3.23688066.9810043 1.38929853 1.471362 3.01611857 1.471362 4.87959325 0 1.92906755-.5640414 3.60443215-1.692124 5.02667165-1.1277937 1.4222395-2.7052024 2.4439865-4.7325149 3.065241 2.2888173.6212546 4.0624268 1.6918351 5.3211174 3.2123195zm-16.23265883-6.4737613c1.38929853 1.1607346 3.26115293 1.8718543 5.61527423 2.1333592 2.3538323-.2615049 4.2256867-.9726246 5.6152742-2.1333592 1.3892985-1.1604457 2.0842368-2.6725504 2.0842368-4.53631405 0-1.92877864-.6784678-3.44926302-2.0354033-4.56087522-1.3566466-1.1116122-3.2449714-1.66727383-5.6641077-1.66727383-2.4194253 0-4.30775013.55566163-5.66439668 1.66727383-1.35693551 1.1116122-2.03540327 2.63209658-2.03540327 4.56087522 0 1.86376365.69493823 3.37586835 2.08452572 4.53631405zm11.94166813 16.5516658c1.471073-1.1116122 2.206754-2.7300525 2.206754-4.855032 0-1.9290676-.7764237-3.4738243-2.3295601-4.6345589-1.5528474-1.1607347-3.6209026-1.8718544-6.2035878-2.1333592-2.5829741.2615048-4.65102939.9726245-6.20387679 2.1333592-1.55313637 1.1607346-2.32956007 2.7054913-2.32956007 4.6345589 0 2.1249795.73568096 3.7434198 2.20704289 4.855032 1.47107297 1.1116122 3.57987096 1.6675628 6.32639397 1.6675628 2.746234 0 4.855032-.5559506 6.3263939-1.6675628z" fill="#f2f2f2" fill-rule="nonzero" transform="translate(1509.579895 397.697106)"/><g transform="translate(1565.056846 388.430153)"><path d="m.039304.099422h47.553665v54.590201h-47.553665z" fill="#00a88a"/><path d="m47.5929694 54.6896229h-47.55366538v-54.59020073h47.55366538zm-45.01519163-52.05176699v49.51333329h42.47652283v-49.51333329z" fill="#000"/></g><path d="m21.1125411 4.69235002c2.2885283 2.9424349 3.4330815 7.12737888 3.4330815 12.55454298 0 5.9178108-1.1852959 10.5194287-3.5555987 13.8051429-2.3703028 3.2860031-5.6805782 4.9287157-9.9311151 4.9287157-1.99437156 0-3.94771143-.3759313-5.86030856-1.1277937-1.91259713-.7521515-3.60472114-1.8146412-5.07579411-3.1877582l1.56931788-3.0895133c1.66727382 1.405769 3.25306216 2.427516 4.75707607 3.064952 1.50372496.6374361 3.02420934.9564431 4.56087522.9564431 3.0077389 0 5.3372989-1.3404651 6.9883912-4.0213951 1.6510924-2.6812191 2.4766385-6.4408204 2.4766385-11.2796709v-.637725c-.7521514 1.8311116-1.97819 3.2776234-3.6781158 4.3404021-1.7002148 1.0624897-3.6454639 1.5938791-5.8360363 1.5938791-2.1252685 0-4.00521365-.4660854-5.63983549-1.3976783-1.63462184-.9318818-2.90978291-2.2396949-3.82519426-3.9234391-.91541134-1.6837443-1.37311702-3.6047212-1.37311702-5.7623527 0-2.1579204.4822669-4.086988 1.44651175-5.78691381.9645338-1.70021476 2.29690808-3.03258905 3.99712284-3.99712285 1.69992581-.96424484 3.62899341-1.44651174 5.78691388-1.44651174 4.2175959 0 7.4706581 1.47107297 9.7591865 4.41379682zm-3.9234392 12.35834218c1.4387099-1.438421 2.1579204-3.3021847 2.1579204-5.590713 0-2.32118037-.7192105-4.20112552-2.1579204-5.63983546-1.438421-1.43842099-3.3183661-2.15792044-5.6395465-2.15792044-2.22322439 0-4.02168405.71111974-5.39480107 2.13335921-1.37311703 1.42223948-2.05967554 3.31027538-2.05967554 5.66439669 0 2.3211803.68655851 4.1930347 2.05967554 5.6152742 1.37311702 1.4222395 3.1877582 2.1333592 5.44363457 2.1333592 2.2888173 0 4.152292-.7192105 5.590713-2.1579204z" fill="#f2f2f2" fill-rule="nonzero" transform="translate(1575.139966 397.697106)"/><g stroke="#000"><path d="m1096.073546 379.827207v8.703347" stroke-width="2.540471"/><path d="m1334.698583 379.827107h-238.625356" stroke-width="2.536666"/><path d="m1157.047962 379.827207v8.703347" stroke-width="2.540471"/><path d="m1214.724654 379.827207v8.703347" stroke-width="2.540471"/><path d="m1273.792589 379.827207v8.703347" stroke-width="2.540471"/><path d="m.25679382.11881745v8.70067791h253.66824618v8.70607874" stroke-width="2.537062" transform="translate(1333.854479 371.007868)"/><path d="m1522.192353 379.827363v8.706079" stroke-width="2.538373"/><path d="m1460.272258 379.827363v8.706079" stroke-width="2.538373"/><path d="m1398.172318 379.827363v8.706079" stroke-width="2.538373"/><path d="m461.035492 332.200017v30.871702" stroke-width="2.538347"/><path d="m555.359389 347.854087v15.218407" stroke-width="2.537588"/><path d="m695.541211 347.854373v14.187222" stroke-width="2.538524"/><path d="m790.885848 362.040642v-30.871702" stroke-width="2.538347"/><path d="m887.942518 362.041595v-14.187222" stroke-width="2.538524"/><path d="m.019213 15.299472.406607-15.172668" stroke-width="2.539569" transform="matrix(-1 0 0 1 367.859321 347.727644)"/></g><g transform="translate(728.528993 23.597628)"><path d="m.027562.06972h33.346975v38.281514h-33.346975z" fill="#00a88a"/><path d="m33.3745364 38.3512337h-33.34697449v-38.28151366h33.34697449zm-30.80847438-35.74309116v33.20466866h28.26976908v-33.20466866z" fill="#000"/></g><g fill="#000" transform="translate(771.880716 31.029736)"><path d="m12.5751769 7.68008917v1.60645421h-12.54602874v-1.60645421zm0 5.15096053v1.6066044h-12.54602874v-1.6066044z"/><path d="m26.1286201 17.4720676c-1.3345049-.7649138-2.3587471-1.8486543-3.0727268-3.2512217-.7141299-1.4025673-1.0711197-3.0473348-1.0711197-4.93430252 0-1.86998963.3569898-3.50634324 1.0711197-4.90876034.7139797-1.40256734 1.7382219-2.48210096 3.0727268-3.23860086 1.3345049-.75649991 2.8942319-1.13467473 4.6793313-1.13467473 1.2239222 0 2.3757252.19126601 3.4552588.57364779 1.0795337.38253202 1.9762152.91380981 2.6901948 1.59383335l-1.0709695 2.39706047c-.8159982-.6630455-1.6277894-1.14338913-2.4352235-1.44088065-.8075843-.29749152-1.6703097-.44623728-2.5883264-.44623728-1.7509931 0-3.1068332.56959109-4.06722 1.70862301-.960537 1.13888168-1.4408806 2.77102834-1.4408806 4.89598924 0 2.14193892.4761367 3.78670642 1.4281095 4.93430252.9519729 1.1474458 2.31202 1.7212439 4.0799911 1.7212439.9180167 0 1.7807421-.1487458 2.5883264-.4462373.8074341-.2974915 1.6192253-.7778352 2.4352235-1.4407304l1.0709695 2.3969102c-.7139796.6800236-1.6106611 1.2113013-2.6901948 1.5938334-1.0795336.382532-2.2313366.573798-3.4552588.573798-1.7850994 0-3.3448264-.382532-4.6793313-1.1475961z"/><path d="m41.938792 17.7781233c-.9944932-.5440489-1.7595572-1.3217338-2.295042-2.333205-.5354847-1.0116214-.8032271-2.1973805-.8032271-3.5574276 0-1.3598968.2677424-2.54565597.8032271-3.55727739.5354848-1.01147117 1.3005488-1.78915607 2.295042-2.33320496.9944931-.54404888 2.1462961-.8159982 3.4552588-.8159982 1.2919846 0 2.4310166.27194932 3.4169455.8159982.9860792.54404889 1.7467861 1.32173379 2.2822708 2.33320496.535635 1.01162142.8033774 2.19738059.8033774 3.55727739 0 1.3600471-.2677424 2.5458062-.8033774 3.5574276-.5354847 1.0114712-1.2961916 1.7891561-2.2822708 2.333205-.9859289.5440489-2.1249609.8159982-3.4169455.8159982-1.3089627 0-2.4607657-.2719493-3.4552588-.8159982zm5.9160245-2.7412792c.5694408-.7055657.8543115-1.7552.8543115-3.1493534 0-1.3768749-.2890776-2.42665936-.8670826-3.14920316s-1.3940032-1.08374057-2.4479946-1.08374057c-1.0709695 0-1.8955318.36119677-2.4735368 1.08374057s-.8670826 1.77232826-.8670826 3.14920316c0 1.3941534.2848706 2.4437877.8543115 3.1493534.5695911.7055658 1.3897962 1.0581984 2.4607657 1.0581984 1.0880978 0 1.9167168-.3526326 2.4863079-1.0581984z"/><path d="m66.6356966 10.4850736v7.9050108h-3.1875165v-7.7520581c0-1.0200353-.1954729-1.7637641-.5864189-2.23118638-.3910962-.46757253-.9946433-.7013588-1.8106415-.7013588-.968951 0-1.7509931.31026262-2.3459761.93078786-.594983.62052525-.8924746 1.44073042-.8924746 2.46076572v7.2930497h-3.1621245v-9.23110178c0-1.35989684-.0679122-2.57540513-.2038868-3.64652485h2.9834793l.2295793 2.116547c.4418801-.78204211 1.0412203-1.38543905 1.7977202-1.81049133s1.6108115-.63750329 2.5627843-.63750329c3.0769338 0 4.6154758 1.76797107 4.6154758 5.30406345z"/><path d="m74.0818492 7.90951823v5.76307187c0 1.5129998.7054155 2.2694997 2.1163968 2.2694997.3910962 0 .8161484-.0680625 1.2751568-.2040371v2.5246212c-.5610269.2038869-1.2410505.3059054-2.0400706.3059054-1.4620657 0-2.5841195-.407924-3.3660114-1.2239222-.7820421-.8159982-1.172988-1.9891365-1.172988-3.5191143v-5.91602457h-2.4735368v-2.39706046h2.4735368v-3.13643206l3.1875164-1.07111972v4.20755178h3.4169456v2.39706046z"/><path d="m90.9629905 12.11707h-8.8741119c.0680624 1.3770252.4122812 2.3927033 1.0328064 3.0473349.6205252.6544813 1.542749.981722 2.7666711.981722 1.4111315 0 2.7200942-.4590084 3.9270384-1.3770251l.9180167 2.1930233c-.6119611.4929645-1.364254.8882676-2.2567286 1.1857591-.8924745.2974915-1.7977202.4462373-2.715737.4462373-2.1081331 0-3.7655214-.594983-4.9726158-1.7849491-1.2069441-1.1901163-1.8104913-2.8221128-1.8104913-4.8961395 0-1.3089627.2635354-2.47353681.790456-3.49357213.5270708-1.01988507 1.2665927-1.81469827 2.2185655-2.38413911.9519729-.56959109 2.0315065-.85431151 3.2386009-.85431151 1.7679711 0 3.1661812.57379804 4.1947807 1.72124387 1.0284492 1.14759607 1.5427489 2.72430113 1.5427489 4.73026538zm-7.7392869-3.88872499c-.535635.50137838-.8798538 1.22812913-1.0328065 2.18025229h5.9925009c-.1020185-.96910121-.3951528-1.70005891-.8797034-2.1930234-.4845506-.49311473-1.151803-.73952185-2.0017574-.73952185-.8501045 0-1.5427489.25076432-2.0782336.75229296z"/><path d="m105.651108 10.4850736v7.9050108h-3.187516v-7.7520581c0-1.0200353-.195473-1.7637641-.586569-2.23118638-.390946-.46757253-.994493-.7013588-1.810491-.7013588-.9689514 0-1.7509935.31026262-2.3459765.93078786-.594983.62052525-.8924746 1.44073042-.8924746 2.46076572v7.2930497h-3.1621245v-9.23110178c0-1.35989684-.0679122-2.57540513-.2040371-3.64652485h2.9836296l.2294291 2.116547c.4420303-.78204211 1.0412203-1.38543905 1.7977202-1.81049133.7566501-.42505228 1.6108118-.63750329 2.5627838-.63750329 3.077084 0 4.615626 1.76797107 4.615626 5.30406345z"/><path d="m113.097111 7.90951823v5.76307187c0 1.5129998.705566 2.2694997 2.116547 2.2694997.391096 0 .815998-.0680625 1.275006-.2040371v2.5246212c-.561026.2038869-1.24105.3059054-2.03992.3059054-1.462066 0-2.584119-.407924-3.366162-1.2239222-.781891-.8159982-1.172988-1.9891365-1.172988-3.5191143v-5.91602457h-2.473536v-2.39706046h2.473536v-3.13643206l3.187517-1.07111972v4.20755178h3.417096v2.39706046z"/><path d="m125.923803.23393651h7.879619c1.95488 0 3.476444.47177949 4.564542 1.41533845 1.087947.94340871 1.631996 2.2311864 1.631996 3.86318281s-.548256 2.9241313-1.644767 3.87610416c-1.096512.95197287-2.613869 1.42795927-4.551771 1.42795927h-4.590084v7.5735632h-3.289535zm7.497087 8.03257155c1.139032 0 2.001758-.23378627 2.588176-.70120855.58657-.46757253.879854-1.14323888.879854-2.02729954 0-.90103871-.289078-1.5852692-.867083-2.05269149-.578004-.46757253-1.444937-.70135879-2.600947-.70135879h-4.207552v5.48255837z"/><path d="m154.509583 5.51245777v12.87762663h-3.136582v-2.0654626c-.390946.7139797-.951973 1.2707996-1.683081 1.6703097-.730958.3995101-1.563934.59919-2.498929.59919-1.122054 0-2.116547-.2719493-2.983479-.8159982-.867083-.5440489-1.538542-1.3175268-2.014528-2.3205841-.476137-1.002907-.71413-2.1674811-.71413-3.4934219 0-1.326091.24235-2.50328596.72675-3.53188543.484551-1.02844922 1.160368-1.82746937 2.0273-2.39691021.867083-.56959109 1.853012-.85431151 2.958087-.85431151.934995 0 1.767971.19967991 2.498929.59918999.731108.39951008 1.292135.95633006 1.683081 1.67030971v-1.93805208zm-4.003514 9.48607303c.578005-.7309577.866932-1.7594069.866932-3.0854979 0-1.3600471-.288927-2.40547436-.866932-3.13643206-.578005-.73110795-1.402568-1.09651167-2.473537-1.09651167-1.053992 0-1.874347.37817482-2.460766 1.13467473-.586569.7564999-.879854 1.8062844-.879854 3.1493534 0 1.3259408.293285 2.3459761.879854 3.0599557.586419.7139797 1.415188 1.0709695 2.486158 1.0709695 1.053991 0 1.87014-.3654037 2.448145-1.0965117z"/><path d="m170.421623 5.51245777v12.46970263c0 2.0059643-.552462 3.5275283-1.657388 4.5645416-1.105076 1.0370134-2.728658 1.5555201-4.870597 1.5555201-1.988987 0-3.73998-.4164881-5.25313-1.2496147l.510093-2.4224524c1.563934.8159982 3.119454 1.2239222 4.66656 1.2239222 2.295042 0 3.442488-1.1388817 3.442488-3.4169455v-2.5500132c-.390946.6970016-.960537 1.2622355-1.708473 1.6957017-.748086.4336164-1.589626.6502744-2.524621.6502744-1.121904 0-2.120754-.2677424-2.99625-.8032271-.875497-.5354848-1.55552-1.2919847-2.039921-2.2694997-.48455-.9775151-.72675-2.095362-.72675-3.3532403 0-1.2580286.2422-2.37587548.72675-3.35339054.484401-.97751507 1.164424-1.73401497 2.039921-2.26949971.875496-.53548473 1.874346-.8032271 2.99625-.8032271.952123 0 1.797871.19967991 2.537392.59918999.739522.39951008 1.304756.95633006 1.695702 1.67030971v-1.93805208zm-4.06722 8.97613053c.603548-.6970016.905246-1.6575386.905246-2.8814608 0-1.2240724-.297491-2.18460946-.892474-2.88161106s-1.42811-1.04542727-2.499079-1.04542727c-1.053992 0-1.882761.34842567-2.486308 1.04542727-.603397.6970016-.905246 1.65753866-.905246 2.88161106 0 1.2239222.301849 2.1844592.905246 2.8814608.603547.6970016 1.432316 1.0455775 2.486308 1.0455775 1.053991 0 1.88276-.3485759 2.486307-1.0455775z"/><path d="m185.135284 12.11707h-8.874112c.068062 1.3770252.412281 2.3927033 1.032806 3.0473349.620525.6544813 1.542749.981722 2.766821.981722 1.410982 0 2.719944-.4590084 3.927039-1.3770251l.918016 2.1930233c-.612111.4929645-1.364254.8882676-2.256878 1.1857591-.892475.2974915-1.797721.4462373-2.715737.4462373-2.107983 0-3.765522-.594983-4.972466-1.7849491-1.207094-1.1901163-1.810491-2.8221128-1.810491-4.8961395 0-1.3089627.263385-2.47353681.790456-3.49357213.52692-1.01988507 1.266442-1.81469827 2.218565-2.38413911.951973-.56959109 2.031507-.85431151 3.238451-.85431151 1.767971 0 3.166331.57379804 4.194781 1.72124387 1.028599 1.14759607 1.542749 2.72430113 1.542749 4.73026538zm-7.739287-3.88872499c-.535485.50137838-.879704 1.22812913-1.032807 2.18025229h5.992651c-.102018-.96910121-.395303-1.70005891-.879853-2.1930234-.484401-.49311473-1.151653-.73952185-2.001758-.73952185-.849954 0-1.542749.25076432-2.078233.75229296z"/></g><path d="m367.838539 347.854154h94.040308" stroke="#000" stroke-width="2.538462"/><path d="m461.878846 347.854154h93.484616" stroke="#000" stroke-width="2.538462"/><path d="m.33230769 1.70030769 96.35538461-1.24846154 96.0461537 1.24846154" stroke="#000" stroke-width="2.538462" transform="translate(695.209615 346.153846)"/><path d="m.05446154.45184615h95.96584616l96.7416923 1.24846154" stroke="#000" stroke-width="2.538462" transform="translate(36.132692 346.153846)"/></g></svg>
\ No newline at end of file diff --git a/docs/content/en/templates/lookup-order.md b/docs/content/en/templates/lookup-order.md new file mode 100644 index 000000000..406a17c38 --- /dev/null +++ b/docs/content/en/templates/lookup-order.md @@ -0,0 +1,136 @@ +--- +title: Template lookup order +description: Hugo uses the rules below to select a template for a given page, starting from the most specific. +categories: [templates,fundamentals] +keywords: [templates] +menu: + docs: + parent: templates + weight: 30 +weight: 30 +toc: true +--- + +## Lookup rules + +Hugo takes the parameters listed below into consideration when choosing a template for a given page. The templates are ordered by specificity. This should feel natural, but look at the table below for concrete examples of the different parameter variations. + +Kind +: The page `Kind` (the home page is one). See the example tables below per kind. This also determines if it is a **single page** (i.e. a regular content page. We then look for a template in `_default/single.html` for HTML) or a **list page** (section listings, home page, taxonomy lists, taxonomy terms. We then look for a template in `_default/list.html` for HTML). + +Layout +: Can be set in front matter. + +Output Format +: See [Custom Output Formats](/templates/output-formats). An output format has both a `name` (e.g. `rss`, `amp`, `html`) and a `suffix` (e.g. `xml`, `html`). We prefer matches with both (e.g. `index.amp.html`), but look for less specific templates. + +Note that if the output format's Media Type has more than one suffix defined, only the first is considered. + +Language +: We will consider a language tag in the template name. If the site language is `fr`, `index.fr.amp.html` will win over `index.amp.html`, but `index.amp.html` will be chosen before `index.fr.html`. + +Type +: Is value of `type` if set in front matter, else it is the name of the root section (e.g. "blog"). It will always have a value, so if not set, the value is "page". + +Section +: Is relevant for `section`, `taxonomy` and `term` types. + +{{% note %}} +Templates can live in either the project's or the themes' layout folders, and the most specific templates will be chosen. Hugo will interleave the lookups listed below, finding the most specific one either in the project or themes. +{{% /note %}} + +## Target a template + +You cannot change the lookup order to target a content page, but you can change a content page to target a template. Specify `type`, `layout`, or both in front matter. + +Consider this content structure: + +```text +content/ +├── about.md +└── contact.md +``` + +Files in the root of the content directory have a [content type] of `page`. To render these pages with a unique template, create a matching subdirectory: + +[content type]: /getting-started/glossary/#content-type + +```text +layouts/ +└── page/ + └── single.html +``` + +But the contact page probably has a form and requires a different template. In the front matter specify `layout`: + +{{< code-toggle file=content/contact.md >}} +title = 'Contact' +layout = 'contact' +{{< /code-toggle >}} + +Then create the template for the contact page: + +```text +layouts/ +└── page/ + └── contact.html <-- renders contact.md + └── single.html <-- renders about.md +``` + +As a content type, the word `page` is vague. Perhaps `miscellaneous` would be better. Add `type` to the front matter of each page: + +{{< code-toggle file=content/about.md >}} +title = 'About' +type = 'miscellaneous' +{{< /code-toggle >}} + +{{< code-toggle file=content/contact.md >}} +title = 'Contact' +type = 'miscellaneous' +layout = 'contact' +{{< /code-toggle >}} + +Now place the layouts in the corresponding directory: + +```text +layouts/ +└── miscellaneous/ + └── contact.html <-- renders contact.md + └── single.html <-- renders about.md +``` + +## Home page + +{{< datatable-filtered "output" "layouts" "Kind == home" "Example" "OutputFormat" "Suffix" "Template Lookup Order" >}} + +## Single pages + +{{< datatable-filtered "output" "layouts" "Kind == page" "Example" "OutputFormat" "Suffix" "Template Lookup Order" >}} + +## Section pages + +A section page is a list of pages within a given section. + +{{< datatable-filtered "output" "layouts" "Kind == section" "Example" "OutputFormat" "Suffix" "Template Lookup Order" >}} + +## Taxonomy pages + +A taxonomy page is a list of terms within a given taxonomy. The examples below assume the following site configuration: + +{{< code-toggle file=hugo >}} +[taxonomies] +category = 'categories' +{{< /code-toggle >}} + +{{< datatable-filtered "output" "layouts" "Kind == taxonomy" "Example" "OutputFormat" "Suffix" "Template Lookup Order" >}} + +## Term pages + +A term page is a list of pages associated with a given term. The examples below assume the following site configuration: + +{{< code-toggle file=hugo >}} +[taxonomies] +category = 'categories' +{{< /code-toggle >}} + +{{< datatable-filtered "output" "layouts" "Kind == term" "Example" "OutputFormat" "Suffix" "Template Lookup Order" >}} diff --git a/docs/content/en/templates/menu-templates.md b/docs/content/en/templates/menu-templates.md new file mode 100644 index 000000000..8dab65abf --- /dev/null +++ b/docs/content/en/templates/menu-templates.md @@ -0,0 +1,132 @@ +--- +title: Menu templates +description: Use menu variables and methods in your templates to render a menu. +categories: [templates] +keywords: [lists,sections,menus] +menu: + docs: + parent: templates + weight: 140 +weight: 140 +toc: true +aliases: [/templates/menus/] +--- + +## Overview + +After [defining menu entries], use [menu variables and methods] to render a menu. + +Three factors determine how to render a menu: + +1. The method used to define the menu entries: [automatic], [in front matter], or [in site configuration] +1. The menu structure: flat or nested +1. The method used to [localize the menu entries]: site configuration or translation tables + +The example below handles every combination. + +## Example + +This partial template recursively "walks" a menu structure, rendering a localized, accessible nested list. + +{{< code file=layouts/partials/menu.html copy=true >}} +{{- $page := .page }} +{{- $menuID := .menuID }} + +{{- with index site.Menus $menuID }} + <nav> + <ul> + {{- partial "inline/menu/walk.html" (dict "page" $page "menuEntries" .) }} + </ul> + </nav> +{{- end }} + +{{- define "partials/inline/menu/walk.html" }} + {{- $page := .page }} + {{- range .menuEntries }} + {{- $attrs := dict "href" .URL }} + {{- if $page.IsMenuCurrent .Menu . }} + {{- $attrs = merge $attrs (dict "class" "active" "aria-current" "page") }} + {{- else if $page.HasMenuCurrent .Menu .}} + {{- $attrs = merge $attrs (dict "class" "ancestor" "aria-current" "true") }} + {{- end }} + {{- $name := .Name }} + {{- with .Identifier }} + {{- with T . }} + {{- $name = . }} + {{- end }} + {{- end }} + <li> + <a + {{- range $k, $v := $attrs }} + {{- with $v }} + {{- printf " %s=%q" $k $v | safeHTMLAttr }} + {{- end }} + {{- end -}} + >{{ $name }}</a> + {{- with .Children }} + <ul> + {{- partial "inline/menu/walk.html" (dict "page" $page "menuEntries" .) }} + </ul> + {{- end }} + </li> + {{- end }} +{{- end }} +{{< /code >}} + +Call the partial above, passing a menu ID and the current page in context. + +{{< code file=layouts/_default/single.html >}} +{{ partial "menu.html" (dict "menuID" "main" "page" .) }} +{{ partial "menu.html" (dict "menuID" "footer" "page" .) }} +{{< /code >}} + +## Page references + +Regardless of how you [define menu entries], an entry associated with a page has access to page variables and methods. + +This simplistic example renders a page parameter named `version` next to each entry's `name`. Code defensively using `with` or `if` to handle entries where (a) the entry points to an external resource, or (b) the `version` parameter is not defined. + +{{< code file=layouts/_default/single.html >}} +{{- range site.Menus.main }} + <a href="{{ .URL }}"> + {{ .Name }} + {{- with .Page }} + {{- with .Params.version -}} + ({{ . }}) + {{- end }} + {{- end }} + </a> +{{- end }} +{{< /code >}} + +## Menu entry parameters + +When you define menu entries [in site configuration] or [in front matter], you can include a `params` key as shown in these examples: + +- [Menu entry defined in site configuration] +- [Menu entry defined in front matter] + +This simplistic example renders a `class` attribute for each anchor element. Code defensively using `with` or `if` to handle entries where `params.class` is not defined. + +{{< code file=layouts/partials/menu.html >}} +{{- range site.Menus.main }} + <a {{ with .Params.class -}} class="{{ . }}" {{ end -}} href="{{ .URL }}"> + {{ .Name }} + </a> +{{- end }} +{{< /code >}} + +## Localize + +Hugo provides two methods to localize your menu entries. See [multilingual]. + +[automatic]: /content-management/menus/#define-automatically +[define menu entries]: /content-management/menus/ +[defining menu entries]: /content-management/menus/ +[in front matter]: /content-management/menus/#define-in-front-matter +[in site configuration]: /content-management/menus/#define-in-site-configuration +[localize the menu entries]: /content-management/multilingual/#menus +[menu entry defined in front matter]: /content-management/menus/#example-front-matter +[menu entry defined in site configuration]: /content-management/menus/#example-site-configuration +[menu variables and methods]: /variables/menu-entry/ +[multilingual]: /content-management/multilingual/#menus diff --git a/docs/content/en/templates/output-formats.md b/docs/content/en/templates/output-formats.md new file mode 100644 index 000000000..23a420882 --- /dev/null +++ b/docs/content/en/templates/output-formats.md @@ -0,0 +1,231 @@ +--- +title: Custom output formats +description: Hugo can output content in multiple formats, including calendar events, e-book formats, Google AMP, and JSON search indexes, or any custom text format. +categories: [templates,fundamentals] +keywords: ["amp", "outputs", "rss"] +menu: + docs: + parent: templates + weight: 210 +weight: 210 +toc: true +aliases: [/templates/outputs/,/extras/output-formats/,/content-management/custom-outputs/] +--- + +This page describes how to properly configure your site with the media types and output formats, as well as where to create your templates for your custom outputs. + +## Media types + +A [media type] (formerly known as a MIME type) is a two-part identifier for file formats and format contents transmitted on the internet. + +This is the full set of built-in media types in Hugo: + +{{< datatable "config" "mediaTypes" "_key" "suffixes" >}} + +**Note:** + +- It is possible to add custom media types or change the defaults; e.g., if you want to change the suffix for `text/html` to `asp`. +- `Suffixes` are the values that will be used for URLs and file names for that media type in Hugo. +- The `Type` is the identifier that must be used when defining new/custom `Output Formats` (see below). +- The full set of media types will be registered in Hugo's built-in development server to make sure they are recognized by the browser. + +To add or modify a media type, define it in a `mediaTypes` section in your [site configuration], either for all sites or for a given language. + +{{< code-toggle file=hugo >}} +[mediaTypes] + [mediaTypes."text/enriched"] + suffixes = ["enr"] + [mediaTypes."text/html"] + suffixes = ["asp"] +{{</ code-toggle >}} + +The above example adds one new media type, `text/enriched`, and changes the suffix for the built-in `text/html` media type. + +**Note:** these media types are configured for **your output formats**. If you want to redefine one of Hugo's default output formats (e.g. `HTML`), you also need to redefine the media type. So, if you want to change the suffix of the `HTML` output format from `html` (default) to `htm`: + +{{< code-toggle file=hugo >}} +[mediaTypes] + [mediaTypes."text/html"] + suffixes = ["htm"] + +[outputFormats] + [outputFormats.html] + mediaType = "text/html" +{{</ code-toggle >}} + +{{% note %}} +For the above to work, you also need to add an `outputs` definition in your site configuration. +{{% /note %}} + +## Output format definitions + +Given a media type and some additional configuration, you get an **Output Format**. + +This is the full set of Hugo's built-in output formats: + +{{< datatable "config" "outputFormats" "name" "mediaType" "path" "baseName" "rel" "protocol" "isPlainText" "isHTML" "noUgly" "permalinkable" >}} + +- A page can be output in as many output formats as you want, and you can have an infinite amount of output formats defined **as long as they resolve to a unique path on the file system**. In the above table, the best example of this is `amp` vs. `html`. `amp` has the value `amp` for `path` so it doesn't overwrite the `html` version; e.g. we can now have both `/index.html` and `/amp/index.html`. +- The `mediaType` must match a defined media type. +- You can define new output formats or redefine built-in output formats; e.g., if you want to put `amp` pages in a different path. + +To add or modify an output format, define it in an `outputFormats` section in your site's [configuration file](/getting-started/configuration/), either for all sites or for a given language. + +{{< code-toggle file=hugo >}} +[outputFormats.MyEnrichedFormat] +mediaType = "text/enriched" +baseName = "myindex" +isPlainText = true +protocol = "bep://" +{{</ code-toggle >}} + +The above example is fictional, but if used for the homepage on a site with `baseURL` `https://example.org`, it will produce a plain text homepage with the URL `bep://example.org/myindex.enr`. + +### Configure output formats + +The following is the full list of configuration options for output formats and their default values: + +name +: the output format identifier. This is used to define what output format(s) you want for your pages. + +mediaType +: this must match the `Type` of a defined media type. + +path +: sub path to save the output files. + +baseName +: the base file name for the list file names (homepage, etc.). **Default:** `index`. + +rel +: can be used to create `rel` values in `link` tags. **Default:** `alternate`. + +protocol +: will replace the "http://" or "https://" in your `baseURL` for this output format. + +isPlainText +: use Go's plain text templates parser for the templates. **Default:** `false`. + +isHTML +: used in situations only relevant for `HTML`-type formats; e.g., page aliases. **Default:** `false`. + +noUgly +: used to turn off ugly URLs If `uglyURLs` is set to `true` in your site. **Default:** `false`. + +notAlternative +: enable if it doesn't make sense to include this format in an `AlternativeOutputFormats` format listing on `Page` (e.g., with `CSS`). Note that we use the term _alternative_ and not _alternate_ here, as it does not necessarily replace the other format. **Default:** `false`. + +permalinkable +: make `.Permalink` and `.RelPermalink` return the rendering Output Format rather than main ([see below](#link-to-output-formats)). This is enabled by default for `HTML` and `AMP`. **Default:** `false`. + +weight +: Setting this to a non-zero value will be used as the first sort criteria. + +## Output formats for pages + +A `Page` in Hugo can be rendered to multiple _output formats_ on the file +system. + +### Default output formats + +Every `Page` has a [`Kind`][page_kinds] attribute, and the default Output +Formats are set based on that. + +{{< code-toggle config=outputs />}} + +### Customizing output formats + +This can be changed by defining an `outputs` list of output formats in either +the `Page` front matter or in the site configuration (either for all sites or +per language). + +Example from site configuration file: + +{{< code-toggle file=hugo >}} +[outputs] + home = ["html", "amp", "rss"] + page = ["html"] +{{</ code-toggle >}} + +Note that in the above examples, the _output formats_ for `section`, +`taxonomy` and `term` will stay at their default value `['html','rss']`. + +* The `outputs` definition is per page [`Kind`][page_kinds]. +* The names (e.g. `html`, `amp`) must match the `name` of a defined output format, and can be overridden per page in front matter. + +The following is an example of front matter in a content file that defines output formats for the rendered `Page`: + +{{< code-toggle file=content/example.md fm=true >}} +title: Example +outputs: +- html +- amp +- json +{{< /code-toggle >}} + +## List output formats + +Each `Page` has both an `.OutputFormats` (all formats, including the current) and an `.AlternativeOutputFormats` variable, the latter of which is useful for creating a `link rel` list in your site's `<head>`: + +```go-html-template +{{ range .AlternativeOutputFormats -}} + <link rel="{{ .Rel }}" type="{{ .MediaType.Type }}" href="{{ .Permalink | safeURL }}"> +{{ end }} +``` + +## Link to output formats + +`.Permalink` and `.RelPermalink` on `Page` will return the first output format defined for that page (usually `HTML` if nothing else is defined). This is regardless of the template file they are being called from. + +__from `single.json.json`:__ +```go-html-template +{{ .RelPermalink }} → /that-page/ +{{ with .OutputFormats.Get "json" }} + {{ .RelPermalink }} → /that-page/index.json +{{ end }} +``` + +In order for them to return the output format of the current template file instead, the given output format should have its `permalinkable` setting set to true. + +**Same template file as above with json output format's `permalinkable` set to true:** + +```go-html-template +{{ .RelPermalink }} → /that-page/index.json +{{ with .OutputFormats.Get "html" }} + {{ .RelPermalink }} → /that-page/ +{{ end }} +``` + +From content files, you can use the [`ref` or `relref` shortcodes](/content-management/shortcodes/#ref-and-relref): + +```go-html-template +[Neat]({{</* ref "blog/neat.md" "amp" */>}}) +[Who]({{</* relref "about.md#who" "amp" */>}}) +``` + +## Templates for your output formats + +Each output format requires a corresponding template conforming to the [template lookup order](/templates/lookup-order/). Hugo considers both output format and suffix when selecting a template. + +For example, to generate a JSON file for the home page, the template with highest specificity is `layouts/index.json.json`. + +Hugo will now also detect the media type and output format of partials, if possible, and use that information to decide if the partial should be parsed as a plain text template or not. + +Hugo will look for the name given, so you can name it whatever you want. But if you want it treated as plain text, you should use the file suffix and, if needed, the name of the Output Format. The pattern is as follows: + +```go-html-template +[partial name].[OutputFormat].[suffix] +``` + +The partial below is a plain text template . The output format is `csv`, and since this is the only output format with the suffix `csv`, we don't need to include the output format `name`): + +```go-html-template +{{ partial "mytextpartial.csv" . }} +``` + +[base]: /templates/base/ +[site configuration]: /getting-started/configuration/ +[lookup order]: /templates/lookup-order/ +[media type]: https://en.wikipedia.org/wiki/Media_type +[partials]: /templates/partials/ +[page_kinds]: /templates/section-templates/#page-kinds diff --git a/docs/content/en/templates/pagination.md b/docs/content/en/templates/pagination.md new file mode 100644 index 000000000..0854a6844 --- /dev/null +++ b/docs/content/en/templates/pagination.md @@ -0,0 +1,154 @@ +--- +title: Pagination +description: Hugo supports pagination for your homepage, section pages, and taxonomies. +categories: [templates] +keywords: [lists,sections,pagination] +menu: + docs: + parent: templates + weight: 100 +weight: 100 +toc: true +aliases: [/extras/pagination,/doc/pagination/] +--- + +The real power of Hugo pagination shines when combined with the [`where`] function and its SQL-like operators: [`first`], [`last`], and [`after`]. You can even [order the content][lists] the way you've become used to with Hugo. + +## Configure pagination + +Pagination can be configured in your [site configuration][configuration]: + +paginate +: default = `10`. This setting can be overridden within the template. + +paginatePath +: default = `page`. Allows you to set a different path for your pagination pages. + +Setting `paginate` to a positive value will split the list pages for the homepage, sections and taxonomies into chunks of that size. But note that the generation of the pagination pages for sections, taxonomies and homepage is *lazy* --- the pages will not be created if not referenced by a `.Paginator` (see below). + +`paginatePath` is used to adapt the `URL` to the pages in the paginator (the default setting will produce URLs on the form `/page/1/`. + +## List paginator pages + +{{% note %}} +`.Paginator` is provided to help you build a pager menu. This feature is currently only supported on homepage and list pages (i.e., taxonomies and section lists). +{{% /note %}} + +There are two ways to configure and use a `.Paginator`: + +1. The simplest way is just to call `.Paginator.Pages` from a template. It will contain the pages for *that page*. +2. Select another set of pages with the available template functions and ordering options, and pass the slice to `.Paginate`, e.g. + * `{{ range (.Paginate ( first 50 .Pages.ByTitle )).Pages }}` or + * `{{ range (.Paginate .RegularPagesRecursive).Pages }}`. + +For a given **Page**, it's one of the options above. The `.Paginator` is static and cannot change once created. + +If you call `.Paginator` or `.Paginate` multiple times on the same page, you should ensure all the calls are identical. Once *either* `.Paginator` or `.Paginate` is called while generating a page, its result is cached, and any subsequent similar call will reuse the cached result. This means that any such calls which do not match the first one will not behave as written. + +(Remember that function arguments are eagerly evaluated, so a call like `$paginator := cond x .Paginator (.Paginate .RegularPagesRecursive)` is an example of what you should *not* do. Use `if`/`else` instead to ensure exactly one evaluation.) + +The global page size setting (`Paginate`) can be overridden by providing a positive integer as the last argument. The examples below will give five items per page: + +* `{{ range (.Paginator 5).Pages }}` +* `{{ $paginator := .Paginate (where .Pages "Type" "posts") 5 }}` + +It is also possible to use the `GroupBy` functions in combination with pagination: + +```go-html-template +{{ range (.Paginate (.Pages.GroupByDate "2006")).PageGroups }} +``` + +## Build the navigation + +The `.Paginator` contains enough information to build a paginator interface. + +The easiest way to add this to your pages is to include the built-in template (with `Bootstrap`-compatible styles): + +```go-html-template +{{ template "_internal/pagination.html" . }} +``` + +{{% note %}} +If you use any filters or ordering functions to create your `.Paginator` *and* you want the navigation buttons to be shown before the page listing, you must create the `.Paginator` before it's used. +{{% /note %}} + +The following example shows how to create `.Paginator` before its used: + +```go-html-template +{{ $paginator := .Paginate (where .Pages "Type" "posts") }} +{{ template "_internal/pagination.html" . }} +{{ range $paginator.Pages }} + {{ .Title }} +{{ end }} +``` + +Without the `where` filter, the above example is even simpler: + +```go-html-template +{{ template "_internal/pagination.html" . }} +{{ range .Paginator.Pages }} + {{ .Title }} +{{ end }} +``` + +If you want to build custom navigation, you can do so using the `.Paginator` object, which includes the following properties: + +PageNumber +: The current page's number in the pager sequence + +URL +: The relative URL to the current pager + +Pages +: The pages in the current pager + +NumberOfElements +: The number of elements on this page + +HasPrev +: Whether there are page(s) before the current + +Prev +: The pager for the previous page + +HasNext +: Whether there are page(s) after the current + +Next +: The pager for the next page + +First +: The pager for the first page + +Last +: The pager for the last page + +Pagers +: A list of pagers that can be used to build a pagination menu + +PageSize +: Size of each pager + +TotalPages +: The number of pages in the paginator + +TotalNumberOfElements +: The number of elements on all pages in this paginator + +## Additional information + +The pages are built on the following form (`BLANK` means no value): + +```txt +[SECTION/TAXONOMY/BLANK]/index.html +[SECTION/TAXONOMY/BLANK]/page/1/index.html => redirect to [SECTION/TAXONOMY/BLANK]/index.html +[SECTION/TAXONOMY/BLANK]/page/2/index.html +.... +``` + +[`first`]: /functions/collections/first/ +[`last`]: /functions/collections/last/ +[`after`]: /functions/collections/after/ +[configuration]: /getting-started/configuration/ +[lists]: /templates/lists/ +[`where`]: /functions/collections/where diff --git a/docs/content/en/templates/partials.md b/docs/content/en/templates/partials.md new file mode 100644 index 000000000..35ba2ee9e --- /dev/null +++ b/docs/content/en/templates/partials.md @@ -0,0 +1,182 @@ +--- +title: Partial templates +description: Partials are smaller, context-aware components in your list and page templates that can be used economically to keep your templating DRY. +categories: [templates] +keywords: [lists,sections,partials] +menu: + docs: + parent: templates + weight: 120 +weight: 120 +toc: true +aliases: [/templates/partial/,/layout/chrome/,/extras/analytics/] +--- + +{{< youtube pjS4pOLyB7c >}} + +## Partial template lookup order + +Partial templates---like [single page templates][singletemps] and [list page templates][listtemps]---have a specific [lookup order]. However, partials are simpler in that Hugo will only check in two places: + +1. `layouts/partials/*<PARTIALNAME>.html` +2. `themes/<THEME>/layouts/partials/*<PARTIALNAME>.html` + +This allows a theme's end user to copy a partial's contents into a file of the same name for [further customization][customize]. + +## Use partials in your templates + +All partials for your Hugo project are located in a single `layouts/partials` directory. For better organization, you can create multiple subdirectories within `partials` as well: + +```txt +layouts/ +└── partials/ + ├── footer/ + │ ├── scripts.html + │ └── site-footer.html + ├── head/ + │ ├── favicons.html + │ ├── metadata.html + │ ├── prerender.html + │ └── twitter.html + └── header/ + ├── site-header.html + └── site-nav.html +``` + +All partials are called within your templates using the following pattern: + +```go-html-template +{{ partial "<PATH>/<PARTIAL>.html" . }} +``` + +{{% note %}} +One of the most common mistakes with new Hugo users is failing to pass a context to the partial call. In the pattern above, note how "the dot" (`.`) is required as the second argument to give the partial context. You can read more about "the dot" in the [Hugo templating introduction](/templates/introduction/). +{{% /note %}} + +{{% note %}} +`<PARTIAL>` including `baseof` is reserved. ([#5373](https://github.com/gohugoio/hugo/issues/5373)) +{{% /note %}} + +As shown in the above example directory structure, you can nest your directories within `partials` for better source organization. You only need to call the nested partial's path relative to the `partials` directory: + +```go-html-template +{{ partial "header/site-header.html" . }} +{{ partial "footer/scripts.html" . }} +``` + +### Variable scoping + +The second argument in a partial call is the variable being passed down. The above examples are passing the `.`, which tells the template receiving the partial to apply the current [context][context]. + +This means the partial will *only* be able to access those variables. The partial is isolated and *has no access to the outer scope*. From within the partial, `$.Var` is equivalent to `.Var`. + +## Returning a value from a partial + +In addition to outputting markup, partials can be used to return a value of any type. In order to return a value, a partial must include a lone `return` statement *at the end of the partial*. + +### Example GetFeatured + +```go-html-template +{{/* layouts/partials/GetFeatured.html */}} +{{ return first . (where site.RegularPages "Params.featured" true) }} +``` + +```go-html-template +{{/* layouts/index.html */}} +{{ range partial "GetFeatured.html" 5 }} + [...] +{{ end }} +``` + +### Example GetImage + +```go-html-template +{{/* layouts/partials/GetImage.html */}} +{{ $image := false }} +{{ with .Params.gallery }} + {{ $image = index . 0 }} +{{ end }} +{{ with .Params.image }} + {{ $image = . }} +{{ end }} +{{ return $image }} +``` + +```go-html-template +{{/* layouts/_default/single.html */}} +{{ with partial "GetImage.html" . }} + [...] +{{ end }} +``` + +{{% note %}} +Only one `return` statement is allowed per partial file. +{{% /note %}} + +## Inline partials + +You can also define partials inline in the template. But remember that template namespace is global, so you need to make sure that the names are unique to avoid conflicts. + +```go-html-template +Value: {{ partial "my-inline-partial.html" . }} + +{{ define "partials/my-inline-partial.html" }} +{{ $value := 32 }} +{{ return $value }} +{{ end }} +``` + +## Cached partials + +The `partialCached` template function provides significant performance gains for complex templates that don't need to be re-rendered on every invocation. See [details][partialcached]. + +## Examples + +### `header.html` + +The following `header.html` partial template is used for [spf13.com](https://spf13.com/): + +{{< code file=layouts/partials/header.html >}} +<!DOCTYPE html> +<html class="no-js" lang="en-US" prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb#"> +<head> + <meta charset="utf-8"> + + {{ partial "meta.html" . }} + + <base href="{{ .Site.BaseURL }}"> + <title> {{ .Title }} : spf13.com </title> + <link rel="canonical" href="{{ .Permalink }}"> + {{ if .RSSLink }}<link href="{{ .RSSLink }}" rel="alternate" type="application/rss+xml" title="{{ .Title }}" />{{ end }} + + {{ partial "head_includes.html" . }} +</head> +{{< /code >}} + +{{% note %}} +The `header.html` example partial was built before the introduction of block templates to Hugo. Read more on [base templates and blocks](/templates/base/) for defining the outer chrome or shell of your master templates (i.e., your site's head, header, and footer). You can even combine blocks and partials for added flexibility. +{{% /note %}} + +### `footer.html` + +The following `footer.html` partial template is used for [spf13.com](https://spf13.com/): + +{{< code file=layouts/partials/footer.html >}} +<footer> + <div> + <p> + © 2013-14 Steve Francia. + <a href="https://creativecommons.org/licenses/by/3.0/" title="Creative Commons Attribution">Some rights reserved</a>; + please attribute properly and link back. + </p> + </div> +</footer> +{{< /code >}} + +[context]: /templates/introduction/ +[customize]: /hugo-modules/theme-components/ +[listtemps]: /templates/lists/ +[lookup order]: /templates/lookup-order/ +[partialcached]: /functions/partials/includecached +[singletemps]: /templates/single-page-templates/ +[themes]: /themes/ diff --git a/docs/content/en/templates/render-hooks.md b/docs/content/en/templates/render-hooks.md new file mode 100644 index 000000000..8e174bdee --- /dev/null +++ b/docs/content/en/templates/render-hooks.md @@ -0,0 +1,183 @@ +--- +title: Markdown render hooks +linkTitle: Render hooks +description: Render Hooks allow custom templates to override markdown rendering functionality. +categories: [templates] +keywords: [markdown] +toc: true +menu: + docs: + parent: templates + weight: 200 +weight: 200 +--- + +Note that this is only supported with the [Goldmark](/getting-started/configuration-markup#goldmark) renderer. + +You can override certain parts of the default Markdown rendering to HTML by creating templates with base names `render-{kind}` in `layouts/_default/_markup`. + +You can also create type/section specific hooks in `layouts/[type/section]/_markup`, e.g.: `layouts/blog/_markup`. + +The hook kinds currently supported are: + +* `image` +* `link` +* `heading` +* `codeblock`{{< new-in 0.93.0 >}} + +You can define [Output-Format-](/templates/output-formats) and [language-](/content-management/multilingual/)specific templates if needed. Your `layouts` folder may look like this: + +```text +layouts/ +└── _default/ + └── _markup/ + ├── render-codeblock-bash.html + ├── render-codeblock.html + ├── render-heading.html + ├── render-image.html + ├── render-image.rss.xml + └── render-link.html +``` + +Some use cases for the above: + +* Resolve link references using `.GetPage`. This would make links portable as you could translate `./my-post.md` (and similar constructs that would work on GitHub) into `/blog/2019/01/01/my-post/` etc. +* Add `target=_blank` to external links. +* Resolve and [process](/content-management/image-processing/) images. +* Add [header links](https://remysharp.com/2014/08/08/automatic-permalinks-for-blog-posts). + +## Render hooks for headings, links and images + +### Context passed to `render-link` and `render-image` + +The `render-link` and `render-image` templates will receive this context: + +Page +: The [Page](/variables/page/) being rendered. + +Destination +: The URL. + +Title +: The title attribute. + +Text +: The rendered (HTML) link text. + +PlainText +: The plain variant of the above. + +### Context passed to `render-heading` + +The `render-heading` template will receive this context: + +Page +: The [Page](/variables/page/) being rendered. + +Level +: The header level (1--6) + +Anchor +: An auto-generated html id unique to the header within the page + +Text +: The rendered (HTML) text. + +PlainText +: The plain variant of the above. + +Attributes (map) +: A map of attributes (e.g. `id`, `class`). Note that this will currently always be empty for links. + +The `render-image` templates will also receive: + +IsBlock {{< new-in 0.108.0 >}} +: Returns true if this is a standalone image and the configuration option [markup.goldmark.parser.wrapStandAloneImageWithinParagraph](/getting-started/configuration-markup/#goldmark) is disabled. + +Ordinal {{< new-in 0.108.0 >}} +: Zero-based ordinal for all the images in the current document. + +### Link with title markdown example + +```md +[Text](https://www.gohugo.io "Title") +``` + +Here is a code example for how the render-link.html template could look: + +{{< code file=layouts/_default/_markup/render-link.html >}} +<a href="{{ .Destination | safeURL }}"{{ with .Title }} title="{{ . }}"{{ end }}{{ if strings.HasPrefix .Destination "http" }} target="_blank" rel="noopener"{{ end }}>{{ .Text | safeHTML }}</a> +{{< /code >}} + +### Image markdown example + +```md + +``` + +Here is a code example for how the render-image.html template could look: + +{{< code file=layouts/_default/_markup/render-image.html >}} +<p class="md__image"> + <img src="{{ .Destination | safeURL }}" alt="{{ .Text }}" {{ with .Title }} title="{{ . }}"{{ end }} /> +</p> +{{< /code >}} + +### Heading link example + +Given this template file + +{{< code file=layouts/_default/_markup/render-heading.html >}} +<h{{ .Level }} id="{{ .Anchor | safeURL }}">{{ .Text | safeHTML }} <a href="#{{ .Anchor | safeURL }}">¶</a></h{{ .Level }}> +{{< /code >}} + +And this markdown + +```md +### Section A +``` + +The rendered html will be + +```html +<h3 id="section-a">Section A <a href="#section-a">¶</a></h3> +``` + +## Render hooks for code blocks + +{{< new-in 0.93.0 >}} + +You can add a hook template for either all code blocks or for a specific type/language (`bash` in the example below): + +```goat { class="black f7" } +layouts +└── _default + └── _markup + └── render-codeblock.html + └── render-codeblock-bash.html +``` + +The default behavior for these code blocks is to do [Code Highlighting](/content-management/syntax-highlighting/#highlighting-in-code-fences), but since you can pass attributes to these code blocks, they can be used for almost anything. One example would be the built-in [GoAT Diagrams](/content-management/diagrams/#goat-diagrams-ascii) or this [Mermaid Diagram Code Block Hook](/content-management/diagrams/#mermaid-diagrams) example. + +The context (the ".") you receive in a code block template contains: + +Type (string) +: The type of code block. This will be the programming language, e.g. `bash`, when doing code highlighting. + +Attributes (map) +: Attributes passed in from Markdown (e.g. `{ attrName1=attrValue1 attrName2="attr Value 2" }`). + +Options (map) +: Chroma highlighting processing options. This will only be filled if `Type` is a known [Chroma Lexer](/content-management/syntax-highlighting/#list-of-chroma-highlighting-languages). + +Inner (string) +: The text between the code fences. + +Ordinal (integer) +: Zero-based ordinal for all code blocks in the current document. + +Page +: The owning `Page`. + +Position +: Useful in error logging as it prints the file name and position (linenumber, column), e.g. `{{ errorf "error in code block: %s" .Position }}`. diff --git a/docs/content/en/templates/robots.md b/docs/content/en/templates/robots.md new file mode 100644 index 000000000..0efd85ba2 --- /dev/null +++ b/docs/content/en/templates/robots.md @@ -0,0 +1,59 @@ +--- +title: Robots.txt file +linkTitle: Robots.txt +description: Hugo can generate a customized robots.txt in the same way as any other template. +categories: [templates] +keywords: [robots,search engines] +menu: + docs: + parent: templates + weight: 230 +weight: 230 +aliases: [/extras/robots-txt/] +--- + +To generate a robots.txt file from a template, change the [site configuration]: + +{{< code-toggle file=hugo >}} +enableRobotsTXT = true +{{< /code-toggle >}} + +By default, Hugo generates robots.txt using an [internal template][internal]. + +```text +User-agent: * +``` + +Search engines that honor the Robots Exclusion Protocol will interpret this as permission to crawl everything on the site. + +## robots.txt template lookup order + +You may overwrite the internal template with a custom template. Hugo selects the template using this lookup order: + +1. `/layouts/robots.txt` +2. `/themes/<THEME>/layouts/robots.txt` + +## robots.txt template example + +{{< code file=layouts/robots.txt >}} +User-agent: * +{{ range .Pages }} +Disallow: {{ .RelPermalink }} +{{ end }} +{{< /code >}} + +This template creates a robots.txt file with a `Disallow` directive for each page on the site. Search engines that honor the Robots Exclusion Protocol will not crawl any page on the site. + +{{% note %}} +To create a robots.txt file without using a template: + +1. Set `enableRobotsTXT` to `false` in the site configuration. +2. Create a robots.txt file in the `static` directory. + +Remember that Hugo copies everything in the [static directory][static] to the root of `publishDir` (typically `public`) when you build your site. + +[static]: /getting-started/directory-structure/ +{{% /note %}} + +[site configuration]: /getting-started/configuration/ +[internal]: https://github.com/gohugoio/hugo/blob/master/tpl/tplimpl/embedded/templates/_default/robots.txt diff --git a/docs/content/en/templates/rss.md b/docs/content/en/templates/rss.md new file mode 100644 index 000000000..9a2ce9b3c --- /dev/null +++ b/docs/content/en/templates/rss.md @@ -0,0 +1,91 @@ +--- +title: RSS templates +description: Use the built-in RSS template, or create your own. +categories: [templates] +keywords: [rss,xml,templates] +menu: + docs: + parent: templates + weight: 160 +weight: 160 +toc: true +--- + +## Configuration + +By default, when you build your site, Hugo generates RSS feeds for home, section, taxonomy, and term pages. Control feed generation in your site configuration. For example, to generate feeds for home and section pages, but not for taxonomy and term pages: + +{{< code-toggle file=hugo >}} +[outputs] +home = ['html', 'rss'] +section = ['html', 'rss'] +taxonomy = ['html'] +term = ['html'] +{{< /code-toggle >}} + +To disable feed generation for all [page kinds]: + +{{< code-toggle file=hugo >}} +disableKinds = ['rss'] +{{< /code-toggle >}} + +By default, the number of items in each feed is unlimited. Change this as needed in your site configuration: + +{{< code-toggle file=hugo >}} +[services.rss] +limit = 42 +{{< /code-toggle >}} + +Set `limit` to `-1` to generate an unlimited number of items per feed. + +The built-in RSS template will render the following values, if present, from your site configuration: + +{{< code-toggle file=hugo >}} +copyright = '© 2023 ABC Widgets, Inc.' +[params.author] +name = 'John Doe' +email = 'jdoe@example.org' +{{< /code-toggle >}} + +## Include feed reference + +To include a feed reference in the `head` element of your rendered pages, place this within the `head` element of your templates: + +```go-html-template +{{ with .OutputFormats.Get "rss" -}} + {{ printf `<link rel=%q type=%q href=%q title=%q>` .Rel .MediaType.Type .Permalink site.Title | safeHTML }} +{{ end }} +``` + +Hugo will render this to: + +```html +<link rel="alternate" type="application/rss+xml" href="https://example.org/index.xml" title="ABC Widgets"> +``` + +## Custom templates + +Override Hugo's [built-in RSS template] by creating one or more of your own, following the naming conventions as shown in the [template lookup order table]. + +For example, to use different templates for home, section, taxonomy, and term pages: + +```text +layouts/ +└── _default/ + ├── home.rss.xml + ├── section.rss.xml + ├── taxonomy.rss.xml + └── term.rss.xml +``` + +RSS templates receive the `.Page` and `.Site` objects in context. + +[built-in RSS template]: https://github.com/gohugoio/hugo/blob/master/tpl/tplimpl/embedded/templates/_default/rss.xml +[page kinds]: /getting-started/glossary/#page-kind +[template lookup order table]: #template-lookup-order + +## Template lookup order + +The table below shows the RSS template lookup order for the different page kinds. The first listing shows the lookup order when running with a theme (`demoTheme`). + +{{< datatable-filtered "output" "layouts" "OutputFormat == rss" "Example" "OutputFormat" "Suffix" "Template Lookup Order" >}} diff --git a/docs/content/en/templates/section-templates.md b/docs/content/en/templates/section-templates.md new file mode 100644 index 000000000..42eb12bec --- /dev/null +++ b/docs/content/en/templates/section-templates.md @@ -0,0 +1,110 @@ +--- +title: Section page templates +linkTitle: Section templates +description: Templates used for section pages are **lists** and therefore have all the variables and methods available to list pages. +categories: [templates] +keywords: [lists,sections,templates] +menu: + docs: + parent: templates + weight: 80 +weight: 80 +toc: true +aliases: [/templates/sections/] +--- + +## Add content and front matter to section templates + +To effectively leverage section page templates, you should first understand Hugo's [content organization](/content-management/organization/) and, specifically, the purpose of `_index.md` for adding content and front matter to section and other list pages. + +## Section template lookup order + +See [Template Lookup](/templates/lookup-order/). + +## Page kinds + +Every `Page` in Hugo has a `.Kind` attribute. + +{{% include "content-management/_common/page-kinds.md" %}} + +## `.Site.GetPage` with sections + +`Kind` can easily be combined with the [`where`] function in your templates to create kind-specific lists of content. This method is ideal for creating lists, but there are times where you may want to fetch just the index page of a single section via the section's path. + +The [`.GetPage` function][getpage] looks up an index page of a given `Kind` and `path`. + +You can call `.Site.GetPage` with two arguments: `kind` (one of the valid values +of `Kind` from above) and `kind value`. + +Examples: + +- `{{ .Site.GetPage "section" "posts" }}` +- `{{ .Site.GetPage "page" "search" }}` + +## Example: creating a default section template + +{{< code file=layouts/_default/section.html >}} +{{ define "main" }} + <main> + {{ .Content }} + <ul class="contents"> + {{ range .Paginator.Pages }} + <li>{{ .Title }} + <div> + {{ partial "summary.html" . }} + </div> + </li> + {{ end }} + </ul> + {{ partial "pagination.html" . }} + </main> +{{ end }} +{{< /code >}} + +### Example: using `.Site.GetPage` + +The `.Site.GetPage` example that follows assumes the following project directory structure: + +```txt +. +└── content + ├── blog + │ ├── _index.md # "title: My Hugo Blog" in the front matter + │ ├── post-1.md + │ ├── post-2.md + │ └── post-3.md + └── events #Note there is no _index.md file in "events" + ├── event-1.md + └── event-2.md +``` + +`.Site.GetPage` will return `nil` if no `_index.md` page is found. Therefore, if `content/blog/_index.md` does not exist, the template will output the section name: + +```go-html-template +<h1>{{ with .Site.GetPage "section" "blog" }}{{ .Title }}{{ end }}</h1> +``` + +Since `blog` has a section index page with front matter at `content/blog/_index.md`, the above code will return the following result: + +```html +<h1>My Hugo Blog</h1> +``` + +If we try the same code with the `events` section, however, Hugo will default to the section title because there is no `content/events/_index.md` from which to pull content and front matter: + +```go-html-template +<h1>{{ with .Site.GetPage "section" "events" }}{{ .Title }}{{ end }}</h1> +``` + +Which then returns the following: + +```html +<h1>Events</h1> +``` + +[contentorg]: /content-management/organization/ +[getpage]: /methods/page/getpage +[lists]: /templates/lists/ +[lookup]: /templates/lookup-order/ +[`where`]: /functions/collections/where +[sections]: /content-management/sections/ diff --git a/docs/content/en/templates/shortcode-templates.md b/docs/content/en/templates/shortcode-templates.md new file mode 100644 index 000000000..6e3d968cf --- /dev/null +++ b/docs/content/en/templates/shortcode-templates.md @@ -0,0 +1,413 @@ +--- +title: Create your own shortcodes +linkTitle: Shortcode templates +description: You can extend Hugo's built-in shortcodes by creating your own using the same templating syntax as that for single and list pages. +categories: [templates] +keywords: [shortcodes,templates] +menu: + docs: + parent: templates + weight: 130 +weight: 130 +aliases: [/functions/get] +toc: true +--- + +Shortcodes are a means to consolidate templating into small, reusable snippets that you can embed directly inside your content. + +{{% note %}} +Hugo also ships with built-in shortcodes for common use cases. (See [Content Management: Shortcodes](/content-management/shortcodes/).) +{{% /note %}} + +## Create custom shortcodes + +Hugo's built-in shortcodes cover many common, but not all, use cases. Luckily, Hugo provides the ability to easily create custom shortcodes to meet your website's needs. + +{{< youtube Eu4zSaKOY4A >}} + +### File location + +To create a shortcode, place an HTML template in the `layouts/shortcodes` directory of your [source organization]. Consider the file name carefully since the shortcode name will mirror that of the file but without the `.html` extension. For example, `layouts/shortcodes/myshortcode.html` will be called with either `{{</* myshortcode /*/>}}` or `{{%/* myshortcode /*/%}}`. + +You can organize your shortcodes in subdirectories, e.g. in `layouts/shortcodes/boxes`. These shortcodes would then be accessible with their relative path, e.g: + +```go-html-template +{{</* boxes/square */>}} +``` + +Note the forward slash. + +### Shortcode template lookup order + +Shortcode templates have a simple [lookup order]: + +1. `/layouts/shortcodes/<SHORTCODE>.html` +2. `/themes/<THEME>/layouts/shortcodes/<SHORTCODE>.html` + +### Positional vs. named parameters + +You can create shortcodes using the following types of parameters: + +* Positional parameters +* Named parameters +* Positional *or* named parameters (i.e, "flexible") + +In shortcodes with positional parameters, the order of the parameters is important. If a shortcode has a single required value (e.g., the `youtube` shortcode below), positional parameters work very well and require less typing from content authors. + +For more complex layouts with multiple or optional parameters, named parameters work best. While less terse, named parameters require less memorization from a content author and can be added in a shortcode declaration in any order. + +Allowing both types of parameters (i.e., a "flexible" shortcode) is useful for complex layouts where you want to set default values that can be easily overridden by users. + +### Access parameters + +All shortcode parameters can be accessed via the `.Get` method. Whether you pass a key (i.e., string) or a number to the `.Get` method depends on whether you are accessing a named or positional parameter, respectively. + +To access a parameter by name, use the `.Get` method followed by the named parameter as a quoted string: + +```go-html-template +{{ .Get "class" }} +``` + +To access a parameter by position, use the `.Get` followed by a numeric position, keeping in mind that positional parameters are zero-indexed: + +```go-html-template +{{ .Get 0 }} +``` + +For the second position, you would just use: + +```go-html-template +{{ .Get 1 }} +``` + +`with` is great when the output depends on a parameter being set: + +```go-html-template +{{ with .Get "class" }} class="{{ . }}"{{ end }} +``` + +`.Get` can also be used to check if a parameter has been provided. This is +most helpful when the condition depends on either of the values, or both: + +```go-html-template +{{ if or (.Get "title") (.Get "alt") }} alt="{{ with .Get "alt" }}{{ . }}{{ else }}{{ .Get "title" }}{{ end }}"{{ end }} +``` + +#### `.Inner` + +If a closing shortcode is used, the `.Inner` variable will be populated with the content between the opening and closing shortcodes. To check if `.Inner` contains anything other than white space: + +```go-html-template +{{ if strings.ContainsNonSpace .Inner }} + Inner is not empty +{{ end }} +``` + +A shortcode with content declared via the `.Inner` variable can also be declared without the content and without the closing tag by using the self-closing syntax: + +```go-html-template +{{</* innershortcode /*/>}} +``` + +{{% note %}} +Any shortcode that refers to `.Inner` must be closed or self-closed. + +{{% /note %}} + +#### `.Params` + +The `.Params` variable in shortcodes contains the list parameters passed to shortcode for more complicated use cases. You can also access higher-scoped parameters with the following logic: + +$.Params +: these are the parameters passed directly into the shortcode declaration (e.g., a YouTube video ID) + +$.Page.Params +: refers to the page's parameters; the "page" in this case refers to the content file in which the shortcode is declared (e.g., a `shortcode_color` field in a content's front matter could be accessed via `$.Page.Params.shortcode_color`). + +$.Page.Site.Params +: refers to global variables as defined in your [site's configuration file][config]. + +#### `.IsNamedParams` + +The `.IsNamedParams` variable checks whether the shortcode declaration uses named parameters and returns a boolean value. + +For example, you could create an `image` shortcode that can take either a `src` named parameter or the first positional parameter, depending on the preference of the content's author. Let's assume the `image` shortcode is called as follows: + +```go-html-template +{{</* image src="images/my-image.jpg" */>}} +``` + +You could then include the following as part of your shortcode templating: + +```go-html-template +{{ if .IsNamedParams }} +<img src="{{ .Get "src" }}" alt=""> +{{ else }} +<img src="{{ .Get 0 }}" alt=""> +{{ end }} +``` + +See the [example Vimeo shortcode][vimeoexample] below for `.IsNamedParams` in action. + +{{% note %}} +While you can create shortcode templates that accept both positional and named parameters, you *cannot* declare shortcodes in content with a mix of parameter types. Therefore, a shortcode declared like `{{</* image src="images/my-image.jpg" "This is my alt text" */>}}` will return an error. +{{% /note %}} + +You can also use the variable `.Page` to access all the normal [page variables][pagevars]. + +Shortcodes can also be nested. In a nested shortcode, you can access the parent shortcode context with the [`.Parent`] shortcode method. This can be very useful for inheritance of common shortcode parameters from the root. + +### Checking for existence + +You can check if a specific shortcode is used on a page by calling `.HasShortcode` in that page template, providing the name of the shortcode. This is sometimes useful when you want to include specific scripts or styles in the header that are only used by that shortcode. + +## Custom shortcode examples + +The following are examples of the different types of shortcodes you can create via shortcode template files in `/layouts/shortcodes`. + +### Single-word example: `year` + +Let's assume you would like to keep mentions of your copyright year current in your content files without having to continually review your Markdown. Your goal is to be able to call the shortcode as follows: + +```go-html-template +{{</* year */>}} +``` + +{{< code file=layouts/shortcodes/year.html >}} +{{ now.Format "2006" }} +{{< /code >}} + +### Single positional example: `youtube` + +Embedded videos are a common addition to Markdown content that can quickly become unsightly. The following is the code used by [Hugo's built-in YouTube shortcode][youtubeshortcode]: + +```go-html-template +{{</* youtube 09jf3ow9jfw */>}} +``` + +Would load the template at `/layouts/shortcodes/youtube.html`: + +{{< code file=layouts/shortcodes/youtube.html >}} +<div class="embed video-player"> +<iframe class="youtube-player" type="text/html" width="640" height="385" src="https://www.youtube.com/embed/{{ index .Params 0 }}" allowfullscreen frameborder="0"> +</iframe> +</div> +{{< /code >}} + +{{< code file=youtube-embed.html >}} +<div class="embed video-player"> + <iframe class="youtube-player" type="text/html" + width="640" height="385" + src="https://www.youtube.com/embed/09jf3ow9jfw" + allowfullscreen frameborder="0"> + </iframe> +</div> +{{< /code >}} + +### Single named example: `image` + +Let's say you want to create your own `img` shortcode rather than use Hugo's built-in [`figure` shortcode][figure]. Your goal is to be able to call the shortcode as follows in your content files: + +{{< code file=content-image.md >}} +{{</* img src="/media/spf13.jpg" title="Steve Francia" */>}} +{{< /code >}} + +You have created the shortcode at `/layouts/shortcodes/img.html`, which loads the following shortcode template: + +{{< code file=layouts/shortcodes/img.html >}} +<!-- image --> +<figure {{ with .Get "class" }}class="{{ . }}"{{ end }}> + {{ with .Get "link" }}<a href="{{ . }}">{{ end }} + <img src="{{ .Get "src" }}" {{ if or (.Get "alt") (.Get "caption") }}alt="{{ with .Get "alt" }}{{ . }}{{ else }}{{ .Get "caption" }}{{ end }}"{{ end }} /> + {{ if .Get "link" }}</a>{{ end }} + {{ if or (or (.Get "title") (.Get "caption")) (.Get "attr") }} + <figcaption>{{ if isset .Params "title" }} + <h4>{{ .Get "title" }}</h4>{{ end }} + {{ if or (.Get "caption") (.Get "attr") }}<p> + {{ .Get "caption" }} + {{ with .Get "attrlink" }}<a href="{{ . }}"> {{ end }} + {{ .Get "attr" }} + {{ if .Get "attrlink" }}</a> {{ end }} + </p> {{ end }} + </figcaption> + {{ end }} +</figure> +<!-- image --> +{{< /code >}} + +Would be rendered as: + +{{< code file=img-output.html >}} +<figure> + <img src="/media/spf13.jpg" /> + <figcaption> + <h4>Steve Francia</h4> + </figcaption> +</figure> +{{< /code >}} + +### Single flexible example: `vimeo` + +```go-html-template +{{</* vimeo 49718712 */>}} +{{</* vimeo id="49718712" class="flex-video" */>}} +``` + +Would load the template found at `/layouts/shortcodes/vimeo.html`: + +{{< code file=layouts/shortcodes/vimeo.html >}} +{{ if .IsNamedParams }} + <div class="{{ if .Get "class" }}{{ .Get "class" }}{{ else }}vimeo-container{{ end }}"> + <iframe src="https://player.vimeo.com/video/{{ .Get "id" }}" allowfullscreen></iframe> + </div> +{{ else }} + <div class="{{ if len .Params | eq 2 }}{{ .Get 1 }}{{ else }}vimeo-container{{ end }}"> + <iframe src="https://player.vimeo.com/video/{{ .Get 0 }}" allowfullscreen></iframe> + </div> +{{ end }} +{{< /code >}} + +Would be rendered as: + +{{< code file=vimeo-iframes.html >}} +<div class="vimeo-container"> + <iframe src="https://player.vimeo.com/video/49718712" allowfullscreen></iframe> +</div> +<div class="flex-video"> + <iframe src="https://player.vimeo.com/video/49718712" allowfullscreen></iframe> +</div> +{{< /code >}} + +### Paired example: `highlight` + +The following is taken from `highlight`, which is a [built-in shortcode] that ships with Hugo. + +{{< code file=highlight-example.md >}} +{{</* highlight html */>}} + <html> + <body> This HTML </body> + </html> +{{</* /highlight */>}} +{{< /code >}} + +The template for the `highlight` shortcode uses the following code, which is already included in Hugo: + +```go-html-template +{{ .Get 0 | highlight .Inner }} +``` + +The rendered output of the HTML example code block will be as follows: + +{{< code file=syntax-highlighted.html >}} +<div class="highlight" style="background: #272822"><pre style="line-height: 125%"><span style="color: #f92672"><html></span> + <span style="color: #f92672"><body></span> This HTML <span style="color: #f92672"></body></span> +<span style="color: #f92672"></html></span> +</pre></div> +{{< /code >}} + +### Nested shortcode: image gallery + +Hugo's [`.Parent`] shortcode method provides access to the parent shortcode context when the shortcode in question is called within the context of a *parent* shortcode. This provides an inheritance model for common shortcode parameters. + +The following example is contrived but demonstrates the concept. Assume you have a `gallery` shortcode that expects one named `class` parameter: + +{{< code file=layouts/shortcodes/gallery.html >}} +<div class="{{ .Get "class" }}"> + {{ .Inner }} +</div> +{{< /code >}} + +You also have an `img` shortcode with a single named `src` parameter that you want to call inside of `gallery` and other shortcodes, so that the parent defines the context of each `img`: + +{{< code file=layouts/shortcodes/img.html >}} +{{- $src := .Get "src" -}} +{{- with .Parent -}} + <img src="{{ $src }}" class="{{ .Get "class" }}-image"> +{{- else -}} + <img src="{{ $src }}"> +{{- end -}} +{{< /code >}} + +You can then call your shortcode in your content as follows: + +```go-html-template +{{</* gallery class="content-gallery" */>}} + {{</* img src="/images/one.jpg" */>}} + {{</* img src="/images/two.jpg" */>}} +{{</* /gallery */>}} +{{</* img src="/images/three.jpg" */>}} +``` + +This will output the following HTML. Note how the first two `img` shortcodes inherit the `class` value of `content-gallery` set with the call to the parent `gallery`, whereas the third `img` only uses `src`: + +```html +<div class="content-gallery"> + <img src="/images/one.jpg" class="content-gallery-image"> + <img src="/images/two.jpg" class="content-gallery-image"> +</div> +<img src="/images/three.jpg"> +``` + +## Error handling in shortcodes + +Use the [errorf](/functions/fmt/errorf) template function and [`.Position`] shortcode method to get useful error messages in shortcodes: + +```sh +{{ with .Get "name" }} +{{ else }} +{{ errorf "missing value for parameter 'name': %s" .Position }} +{{ end }} +``` + +When the above fails, you will see an `ERROR` log similar to the below: + +```sh +ERROR 2018/11/07 10:05:55 missing value for parameter name: "/Users/bep/dev/go/gohugoio/hugo/docs/content/en/variables/shortcodes.md:32:1" +``` + +## Inline shortcodes + +You can also implement your shortcodes inline -- e.g. where you use them in the content file. This can be useful for scripting that you only need in one place. + +This feature is disabled by default, but can be enabled in your site configuration: + +{{< code-toggle file=hugo >}} +[security] +enableInlineShortcodes = true +{{< /code-toggle >}} + +It is disabled by default for security reasons. The security model used by Hugo's template handling assumes that template authors are trusted, but that the content files are not, so the templates are injection-safe from malformed input data. But in most situations you have full control over the content, too, and then `enableInlineShortcodes = true` would be considered safe. But it's something to be aware of: It allows ad-hoc [Go Text templates](https://golang.org/pkg/text/template/) to be executed from the content files. + +And once enabled, you can do this in your content files: + + ```go-html-template + {{</* time.inline */>}}{{ now }}{{</* /time.inline */>}} + ``` + +The above will print the current date and time. + + Note that an inline shortcode's inner content is parsed and executed as a Go text template with the same context as a regular shortcode template. + +This means that the current page can be accessed via `.Page.Title` etc. This also means that there are no concept of "nested inline shortcodes". + +The same inline shortcode can be reused later in the same content file, with different parameters if needed, using the self-closing syntax: + + ```go-html-template +{{</* time.inline /*/>}} +``` + +[basic content files]: /content-management/formats/ +[built-in shortcode]: /content-management/shortcodes/ +[config]: /getting-started/configuration/ +[Content Management: Shortcodes]: /content-management/shortcodes/#using-hugo-s-built-in-shortcodes +[source organization]: /getting-started/directory-structure/ +[docsshortcodes]: https://github.com/gohugoio/hugo/tree/master/docs/layouts/shortcodes +[figure]: /content-management/shortcodes/#figure +[hugosc]: /content-management/shortcodes/#using-hugo-s-built-in-shortcodes +[lookup order]: /templates/lookup-order/ +[pagevars]: /variables/page/ +[`.Parent`]: /methods/shortcode/parent/ +[`.Position`]: /methods/shortcode/position/ +[spfscs]: https://github.com/spf13/spf13.com/tree/master/layouts/shortcodes +[vimeoexample]: #single-flexible-example-vimeo +[youtubeshortcode]: /content-management/shortcodes/#youtube diff --git a/docs/content/en/templates/single-page-templates.md b/docs/content/en/templates/single-page-templates.md new file mode 100644 index 000000000..cd8a2715c --- /dev/null +++ b/docs/content/en/templates/single-page-templates.md @@ -0,0 +1,85 @@ +--- +title: Single page templates +description: The primary view of content in Hugo is the single view. Hugo will render every Markdown file provided with a corresponding single template. +categories: [templates] +keywords: [page, templates] +menu: + docs: + parent: templates + weight: 50 +weight: 50 +toc: true +aliases: [/layout/content/] +--- + +## Single page template lookup order + +See [Template Lookup](/templates/lookup-order/). + +## Example single page templates + +Content pages are of the type `page` and will therefore have all the [page variables][pagevars] and [site variables] available to use in their templates. + +### `posts/single.html` + +This single page template makes use of Hugo [base templates], the [`.Format` function] for dates, the [`.WordCount` page variable][pagevars], and ranges through the single content's specific [taxonomies][pagetaxonomy]. [`with`] is also used to check whether the taxonomies are set in the front matter. + +{{< code file=layouts/posts/single.html >}} +{{ define "main" }} + <section id="main"> + <h1 id="title">{{ .Title }}</h1> + <div> + <article id="content"> + {{ .Content }} + </article> + </div> + </section> + <aside id="meta"> + <div> + <section> + <h4 id="date"> {{ .Date.Format "Mon Jan 2, 2006" }} </h4> + <h5 id="wordcount"> {{ .WordCount }} Words</h5> + </section> + {{ with .GetTerms "topics" }} + <ul id="topics"> + {{ range . }} + <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li> + {{ end }} + </ul> + {{ end }} + {{ with .GetTerms "tags" }} + <ul id="tags"> + {{ range . }} + <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li> + {{ end }} + </ul> + {{ end }} + </div> + <div> + {{ with .PrevInSection }} + <a class="previous" href="{{ .RelPermalink }}"> {{ .LinkTitle }}</a> + {{ end }} + {{ with .NextInSection }} + <a class="next" href="{{ .RelPermalink }}"> {{ .LinkTitle }}</a> + {{ end }} + </div> + </aside> +{{ end }} +{{< /code >}} + +To easily generate new instances of a content type (e.g., new `.md` files in a section like `project/`) with preconfigured front matter, use [content archetypes][archetypes]. + +[archetypes]: /content-management/archetypes/ +[base templates]: /templates/base/ +[content type]: /content-management/types/ +[directory structure]: /getting-started/directory-structure/ +[dry]: https://en.wikipedia.org/wiki/Don%27t_repeat_yourself +[`.format` function]: /methods/time/format/ +[front matter]: /content-management/front-matter/ +[pagetaxonomy]: /templates/taxonomy-templates/#list-terms-assigned-to-a-page +[pagevars]: /variables/page/ +[partials]: /templates/partials/ +[section]: /content-management/sections/ +[site variables]: /variables/site/ +[spf13]: https://spf13.com/ +[`with`]: /functions/go-template/with/ diff --git a/docs/content/en/templates/sitemap-template.md b/docs/content/en/templates/sitemap-template.md new file mode 100644 index 000000000..07acfdb63 --- /dev/null +++ b/docs/content/en/templates/sitemap-template.md @@ -0,0 +1,79 @@ +--- +title: Sitemap templates +description: Hugo provides built-in sitemap templates. +categories: [templates] +keywords: [sitemap,xml,templates] +menu: + docs: + parent: templates + weight: 170 +weight: 170 +toc: true +aliases: [/layout/sitemap/,/templates/sitemap/] +--- + +## Overview + +Hugo's built-in sitemap templates conform to v0.9 of the [sitemap protocol]. + +With a monolingual project, Hugo generates a sitemap.xml file in the root of the [`publishDir`] using the built-in [sitemap.xml] template. + +With a multilingual project, Hugo generates: + +- A sitemap.xml file in the root of each site (language) using the built-in [sitemap.xml] template +- A sitemap.xml file in the root of the [`publishDir`] using the built-in [sitemapindex.xml] template + +## Configuration + +Set the default values for [change frequency] and [priority], and the name of the generated file, in your site configuration. + +{{< code-toggle config=sitemap />}} + +changefreq +: How frequently a page is likely to change. Valid values are `always`, `hourly`, `daily`, `weekly`, `monthly`, `yearly`, and `never`. Default is `""` (change frequency omitted from rendered sitemap). + +filename +: The name of the generated file. Default is `sitemap.xml`. + +priority +: The priority of a page relative to any other page on the site. Valid values range from 0.0 to 1.0. Default is `-1` (priority omitted from rendered sitemap). + +## Override default values + +Override the default values for a given page in front matter. + +{{< code-toggle file=news.md fm=true >}} +title = 'News' +[sitemap] + changefreq = 'weekly' + priority = 0.8 +{{</ code-toggle >}} + +## Override built-in templates + +To override the built-in sitemap.xml template, create a new file in either of these locations: + +- layouts/sitemap.xml +- layouts/_default/sitemap.xml + +When ranging through the page collection, access the _change frequency_ and _priority_ with `.Sitemap.ChangeFreq` and `.Sitemap.Priority` respectively. + +To override the built-in sitemapindex.xml template, create a new file in either of these locations: + +- layouts/sitemapindex.xml +- layouts/_default/sitemapindex.xml + +## Disable sitemap generation + +You may disable sitemap generation in your site configuration: + +{{< code-toggle file=hugo >}} +disableKinds = ['sitemap'] +{{</ code-toggle >}} + +[`publishDir`]: /getting-started/configuration#publishdir +[change frequency]: <https://www.sitemaps.org/protocol.html#changefreqdef> +[priority]: <https://www.sitemaps.org/protocol.html#priority> +[sitemap protocol]: <https://www.sitemaps.org/protocol.html> +[sitemap.xml]: <https://github.com/gohugoio/hugo/blob/master/tpl/tplimpl/embedded/templates/_default/sitemap.xml> +[sitemapindex.xml]: <https://github.com/gohugoio/hugo/blob/master/tpl/tplimpl/embedded/templates/_default/sitemapindex.xml> diff --git a/docs/content/en/templates/taxonomy-templates.md b/docs/content/en/templates/taxonomy-templates.md new file mode 100644 index 000000000..ff149e940 --- /dev/null +++ b/docs/content/en/templates/taxonomy-templates.md @@ -0,0 +1,318 @@ +--- +title: Taxonomy templates +description: Taxonomy templating includes taxonomy list pages, taxonomy terms pages, and using taxonomies in your single page templates. +categories: [templates] +keywords: [taxonomies,metadata,front matter,terms,templates] +menu: + docs: + parent: templates + weight: 90 +weight: 90 +toc: true +aliases: [/taxonomies/displaying/,/templates/terms/,/indexes/displaying/,/taxonomies/templates/,/indexes/ordering/, /templates/taxonomies/, /templates/taxonomy/] +--- + +Hugo includes support for user-defined groupings of content called **taxonomies**. Taxonomies are classifications that demonstrate logical relationships between content. See [Taxonomies under Content Management](/content-management/taxonomies) if you are unfamiliar with how Hugo leverages this powerful feature. + +Hugo provides multiple ways to use taxonomies throughout your project templates: + +* Order the way content associated with a taxonomy term is displayed in a [taxonomy list template](#taxonomy-list-templates) +* Order the way the terms for a taxonomy are displayed in a [taxonomy terms template](#taxonomy-terms-templates) +* List a single content's taxonomy terms within a [single page template] + +## Taxonomy list templates + +Taxonomy list page templates are lists and therefore have all the variables and methods available to [list pages][lists]. + +### Taxonomy list template lookup order + +See [Template Lookup](/templates/lookup-order/). + +## Taxonomy terms templates + +### Taxonomy terms templates lookup order + +See [Template Lookup](/templates/lookup-order/). + +### Taxonomy methods + +A Taxonomy is a `map[string]WeightedPages`. + +.Get TERM +: Returns the WeightedPages for a given term. For example: ; +`site.Taxonomies.tags.Get "tag-a"`. + +.Count TERM +: The number of pieces of content assigned to the given term. For example: \ +`site.Taxonomies.tags.Count "tag-a"`. + +.Alphabetical +: Returns an OrderedTaxonomy (slice) ordered by term. + +.ByCount +: Returns an OrderedTaxonomy (slice) ordered by number of entries. + +.Reverse +: Returns an OrderedTaxonomy (slice) in reverse order. Must be used with an OrderedTaxonomy. + +### OrderedTaxonomy + +Since Maps are unordered, an OrderedTaxonomy is a special structure that has a defined order. + +```go +[]struct { + Name string + WeightedPages WeightedPages +} +``` + +Each element of the slice has: + +.Term +: The Term used. + +.WeightedPages +: A slice of Weighted Pages. + +.Count +: The number of pieces of content assigned to this term. + +.Page +: Returns a page reference for this term. + +.Pages +: All Pages assigned to this term. All [list methods][renderlists] are available to this. + +## WeightedPages + +WeightedPages is simply a slice of WeightedPage. + +```go +type WeightedPages []WeightedPage +``` + +.Count +: The number of pieces of content assigned to this term. + +.Page +: Returns a page reference for this term. + +.Pages +: Returns a slice of pages, which then can be ordered using any of the [list methods][renderlists]. + +## Displaying custom metadata in taxonomy terms templates + +If you need to display custom metadata for each taxonomy term, you will need to create a page for that term at `/content/<TAXONOMY>/<TERM>/_index.md` and add your metadata in its front matter, [as explained in the taxonomies documentation](/content-management/taxonomies/#add-custom-metadata-to-a-taxonomy-or-term). Based on the Actors taxonomy example shown there, within your taxonomy terms template, you may access your custom fields by iterating through the variable `.Pages` as such: + +```go-html-template +<ul> + {{ range .Pages }} + <li> + <a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a> + {{ .Params.wikipedia }} + </li> + {{ end }} +</ul> +``` + +## Order taxonomies + +Taxonomies can be ordered by either alphabetical key or by the number of content pieces assigned to that key. + +### Order alphabetically example + +```go-html-template +<ul> + {{ range .Data.Terms.Alphabetical }} + <li><a href="{{ .Page.Permalink }}">{{ .Page.Title }}</a> {{ .Count }}</li> + {{ end }} +</ul> +``` + +## Order content within taxonomies + +Hugo uses both `date` and `weight` to order content within taxonomies. + +Each piece of content in Hugo can optionally be assigned a date. It can also be assigned a weight for each taxonomy it is assigned to. + +When iterating over content within taxonomies, the default sort is the same as that used for section and list pages: first by weight, then by date. This means that if the weights for two pieces of content are the same, then the more recent content will be displayed first. + +The default weight for any piece of content is 0. Zero means "does not have a weight", not "has a weight of numerical value zero". + +Weights of zero are thus treated specially: if two pages have unequal weights, and one of them is zero, then the zero-weighted page will always appear after the other one, regardless of the other's weight. Zero weights should thus be used with care: for example, if both positive and negative weights are used to extend a sequence in both directions, a zero-weighted page will appear not in the middle of the list, but at the end. + +### Assign weight + +Content can be assigned weight for each taxonomy that it's assigned to. + +{{< code-toggle file=content/example.md fm=true >}} +tags = [ "a", "b", "c" ] +tags_weight = 22 +categories = ["d"] +title = "Example" +categories_weight = 44 +{{< /code-toggle >}} + +The convention is `taxonomyname_weight`. + +In the above example, this piece of content has a weight of 22 which applies to the sorting when rendering the pages assigned to the "a", "b" and "c" values of the 'tag' taxonomy. + +It has also been assigned the weight of 44 when rendering the 'd' category. + +With this the same piece of content can appear in different positions in different taxonomies. + +Currently taxonomies only support the default ordering of content which is weight -> date. + +There are two different templates that the use of taxonomies will require you to provide. + +Both templates are covered in detail in the templates section. + +A [list template](/templates/lists/) is any template that will be used to render multiple pieces of content in a single html page. This template will be used to generate all the automatically created taxonomy pages. + +A [taxonomy template](/templates/taxonomy-templates/) is a template used to +generate the list of terms for a given template. + +There are four common ways you can display the data in your +taxonomies in addition to the automatic taxonomy pages created by hugo +using the [list templates](/templates/lists/): + +1. For a given piece of content, you can list the terms attached +2. For a given piece of content, you can list other content with the same + term +3. You can list all terms for a taxonomy +4. You can list all taxonomies (with their terms) + +## List terms assigned to a page + +List the terms assigned to a page using the `.Page.GetTerms` method. + +To render an unordered list: + +```go-html-template +{{ $taxonomy := "tags" }} +{{ with .GetTerms $taxonomy }} + <p>{{ (site.GetPage $taxonomy).LinkTitle }}:</p> + <ul> + {{ range . }} + <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li> + {{ end }} + </ul> +{{ end }} +``` + +To render a comma-delimited list: + +```go-html-template +{{ $taxonomy := "tags" }} +{{ with .GetTerms $taxonomy }} + <p> + {{ (site.GetPage $taxonomy).LinkTitle }}: + {{ range $k, $_ := . -}} + {{ if $k }}, {{ end }} + <a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a> + {{- end }} + </p> +{{ end }} +``` + +## List content with the same taxonomy term + +If you are using a taxonomy for something like a series of posts, you can list individual pages associated with the same taxonomy. This is also a quick and dirty method for showing related content: + +### Example: showing content in same series + +```go-html-template +<ul> + {{ range .Site.Taxonomies.series.golang }} + <li><a href="{{ .Page.RelPermalink }}">{{ .Page.Title }}</a></li> + {{ end }} +</ul> +``` + +## List all content in a given taxonomy + +This would be very useful in a sidebar as “featured content”. You could even have different sections of “featured content” by assigning different terms to the content. + +### Example: grouping "featured" content + +```go-html-template +<section id="menu"> + <ul> + {{ range $key, $taxonomy := .Site.Taxonomies.featured }} + <li>{{ $key }}</li> + <ul> + {{ range $taxonomy.Pages }} + <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li> + {{ end }} + </ul> + {{ end }} + </ul> +</section> +``` + +## Render a site's taxonomies + +If you wish to display the list of all keys for your site's taxonomy, you can retrieve them from the [`.Site` variable][sitevars] available on every page. + +This may take the form of a tag cloud, a menu, or simply a list. + +The following example displays all terms in a site's tags taxonomy: + +### Example: list all site tags + +```go-html-template +<ul> + {{ range .Site.Taxonomies.tags }} + <li><a href="{{ .Page.Permalink }}">{{ .Page.Title }}</a> {{ .Count }}</li> + {{ end }} +</ul> +``` + +### Example: list all taxonomies, terms, and assigned content + +This example will list all taxonomies and their terms, as well as all the content assigned to each of the terms. + +{{< code file=layouts/partials/all-taxonomies.html >}} +<ul> + {{ range $taxonomy, $terms := site.Taxonomies }} + <li> + {{ with site.GetPage $taxonomy }} + <a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a> + {{ end }} + <ul> + {{ range $term, $weightedPages := $terms }} + <li> + <a href="{{ .Page.RelPermalink }}">{{ .Page.LinkTitle }}</a> + <ul> + {{ range $weightedPages }} + <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li> + {{ end }} + </ul> + </li> + {{ end }} + </ul> + </li> + {{ end }} +</ul> +{{< /code >}} + +## `.Site.GetPage` for taxonomies + +Because taxonomies are lists, the [`.GetPage` function][getpage] can be used to get all the pages associated with a particular taxonomy term using a terse syntax. The following ranges over the full list of tags on your site and links to each of the individual taxonomy pages for each term without having to use the more fragile URL construction of the ["List All Site Tags" example above](#example-list-all-site-tags): + +{{< code file=links-to-all-tags.html >}} +{{ $taxo := "tags" }} +<ul class="{{ $taxo }}"> + {{ with ($.Site.GetPage (printf "/%s" $taxo)) }} + {{ range .Pages }} + <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li> + {{ end }} + {{ end }} +</ul> +{{< /code >}} + +[getpage]: /methods/page/getpage +[lists]: /templates/lists/ +[renderlists]: /templates/lists/ +[single page template]: /templates/single-page-templates/ +[sitevars]: /variables/site/ diff --git a/docs/content/en/templates/views.md b/docs/content/en/templates/views.md new file mode 100644 index 000000000..e49f1debb --- /dev/null +++ b/docs/content/en/templates/views.md @@ -0,0 +1,113 @@ +--- +title: Content view templates +description: Hugo can render alternative views of your content, useful in list and summary views. +categories: [templates] +keywords: [views] +menu: + docs: + parent: templates + weight: 110 +weight: 110 +toc: true +--- + +These alternative **content views** are especially useful in [list templates][lists]. + +The following are common use cases for content views: + +* You want content of every type to be shown on the homepage but only with limited [summary views][summaries]. +* You only want a bulleted list of your content on a [taxonomy list page][taxonomylists]. Views make this very straightforward by delegating the rendering of each different type of content to the content itself. + +## Create a content view + +To create a new view, create a template in each of your different content type directories with the view name. The following example contains an "li" view and a "summary" view for the `posts` and `project` content types. As you can see, these sit next to the [single content view][single] template, `single.html`. You can even provide a specific view for a given type and continue to use the `_default/single.html` for the primary view. + +```txt + ▾ layouts/ + ▾ posts/ + li.html + single.html + summary.html + ▾ project/ + li.html + single.html + summary.html +``` + +Hugo also has support for a default content template to be used in the event that a specific content view template has not been provided for that type. Content views can also be defined in the `_default` directory and will work the same as list and single templates who eventually trickle down to the `_default` directory as a matter of the lookup order. + +```txt +▾ layouts/ + ▾ _default/ + li.html + single.html + summary.html +``` + +## Which template will be rendered? + +The following is the [lookup order][lookup] for content views: + +1. `/layouts/<TYPE>/<VIEW>.html` +2. `/layouts/_default/<VIEW>.html` +3. `/themes/<THEME>/layouts/<TYPE>/<VIEW>.html` +4. `/themes/<THEME>/layouts/_default/<VIEW>.html` + +## Example: content view inside a list + +The following example demonstrates how to use content views inside your [list templates][lists]. + +### `list.html` + +In this example, `.Render` is passed into the template to call the [render function][render]. `.Render` is a special function that instructs content to render itself with the view template provided as the first argument. In this case, the template is going to render the `summary.html` view that follows: + +{{< code file=layouts/_default/list.html >}} +<main id="main"> + <div> + <h1 id="title">{{ .Title }}</h1> + {{ range .Pages }} + {{ .Render "summary" }} + {{ end }} + </div> +</main> +{{< /code >}} + +### `summary.html` + +Hugo will pass the entire page object to the following `summary.html` view template. (See [Page Variables][pagevars] for a complete list.) + +{{< code file=layouts/_default/summary.html >}} +<article class="post"> + <header> + <h2><a href="{{ .RelPermalink }}">{{ .Title }}</a></h2> + <div class="post-meta">{{ .Date.Format "Mon, Jan 2, 2006" }} - {{ .FuzzyWordCount }} Words </div> + </header> + {{ .Summary }} + <footer> + <a href='{{ .RelPermalink }}'>Read more »</a> + </footer> +</article> +{{< /code >}} + +### `li.html` + +Continuing on the previous example, we can change our render function to use a smaller `li.html` view by changing the argument in the call to the `.Render` function (i.e., `{{ .Render "li" }}`). + +{{< code file=layouts/_default/li.html >}} +<li> + <a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a> + <div class="meta">{{ .Date.Format "Mon, Jan 2, 2006" }}</div> +</li> +{{< /code >}} + +[lists]: /templates/lists/ +[lookup]: /templates/lookup-order/ +[pagevars]: /variables/page/ +[render]: /methods/page/render/ +[single]: /templates/single-page-templates/ +[spf]: https://spf13.com +[spfsourceli]: https://github.com/spf13/spf13.com/blob/master/layouts/_default/li.html +[spfsourcesection]: https://github.com/spf13/spf13.com/blob/master/layouts/_default/section.html +[spfsourcesummary]: https://github.com/spf13/spf13.com/blob/master/layouts/_default/summary.html +[summaries]: /content-management/summaries/ +[taxonomylists]: /templates/taxonomy-templates/ diff --git a/docs/content/en/tools/_index.md b/docs/content/en/tools/_index.md new file mode 100644 index 000000000..006bed053 --- /dev/null +++ b/docs/content/en/tools/_index.md @@ -0,0 +1,20 @@ +--- +title: Developer tools +linkTitle: Overview +description: In addition to Hugo's powerful CLI, there is a large number of community-developed tool chains for Hugo developers. +categories: [] +keywords: [] +menu: + docs: + identifier: developer-tools-overview + parent: developer-tools + weight: 10 +weight: 10 +--- + +One of Hugo's greatest strengths is its passionate---and always evolving---developer community. With the exception of the `highlight` shortcode mentioned in [Syntax Highlighting][syntax], the tools and other projects featured in this section are offerings from both commercial services and open-source projects, many of which are developed by Hugo developers just like you. + +[See the popularity of Hugo compared with other static site generators.][staticgen] + +[staticgen]: https://staticgen.com +[syntax]: /content-management/syntax-highlighting/ diff --git a/docs/content/en/tools/editors.md b/docs/content/en/tools/editors.md new file mode 100644 index 000000000..d94b7af0f --- /dev/null +++ b/docs/content/en/tools/editors.md @@ -0,0 +1,66 @@ +--- +title: Editor plugins +linkTitle: Editor plugins +description: The Hugo community uses a wide range of tools and has developed plugins for some of the most popular text editors to help automate parts of your workflow. +categories: [developer tools] +keywords: [editor,plugin] +menu: + docs: + parent: developer-tools + weight: 20 +weight: 20 +toc: true +--- + +## Visual Studio Code + +[Front Matter](https://marketplace.visualstudio.com/items?itemName=eliostruyf.vscode-front-matter) +: Once you go for a static site, you need to think about how you are going to manage your articles. Front matter is a tool that helps you maintain the metadata/front matter of your articles like: creation date, modified date, slug, tile, SEO check, and more. + +[Hugo Helper](https://marketplace.visualstudio.com/items?itemName=rusnasonov.vscode-hugo) +: Hugo Helper is a plugin for Visual Studio Code that has some useful commands for Hugo. The source code can be found [here](https://github.com/rusnasonov/vscode-hugo). + +[Hugo Language and Syntax Support](https://marketplace.visualstudio.com/items?itemName=budparr.language-hugo-vscode) +: Hugo Language and Syntax Support is a Visual Studio Code plugin for Hugo syntax highlighting and snippets. The source code can be found [here](https://github.com/budparr/language-hugo-vscode). + +[Hugo Themer](https://marketplace.visualstudio.com/items?itemName=eliostruyf.vscode-hugo-themer) +: Hugo Themer is an extension to help you while developing themes. It allows you to easily navigate through your theme files. + +[Hugofy](https://marketplace.visualstudio.com/items?itemName=akmittal.hugofy) +: Hugofy is a plugin for Visual Studio Code to "make life easier" when developing with Hugo. The source code can be found [here](https://github.com/akmittal/hugofy-vscode). + +[Prettier Plugin for Go Templates](https://github.com/NiklasPor/prettier-plugin-go-template) +: Format Hugo templates using this [Prettier](https://prettier.io/) plugin. See [installation instructions](https://discourse.gohugo.io/t/38403). + +[Syntax Highlighting for Hugo Shortcodes](https://marketplace.visualstudio.com/items?itemName=kaellarkin.hugo-shortcode-syntax) +: This extension adds some syntax highlighting for Shortcodes, making visual identification of individual pieces easier. + +## Emacs + +[emacs-easy-hugo](https://github.com/masasam/emacs-easy-hugo) +: Emacs major mode for managing hugo blogs. Note that Hugo also supports [Org-mode][formats]. + +[ox-hugo.el](https://ox-hugo.scripter.co) +: Native Org-mode exporter that exports to Blackfriday Markdown with Hugo front-matter. `ox-hugo` supports two common Org blogging flows --- exporting multiple Org subtrees in a single file to multiple Hugo posts, and exporting a single Org file to a single Hugo post. It also leverages the Org tag and property inheritance features. See [*Why ox-hugo?*](https://ox-hugo.scripter.co/doc/why-ox-hugo/) for more. + +## Sublime Text + +[Hugofy](https://github.com/akmittal/Hugofy) +: Hugofy is a plugin for Sublime Text 3 to make life easier to use Hugo static site generator. + +[Hugo Snippets](https://packagecontrol.io/packages/Hugo%20Snippets) +: Hugo Snippets is a useful plugin for adding automatic snippets to Sublime Text 3. + +## Vim + +[Vim Hugo Helper]: https://github.com/robertbasic/vim-hugo-helper + +[Vim Hugo Helper] +: A small Vim plugin that facilitates authoring pages and blog posts with Hugo. + +[xxx]: xxx + +[vim-hugo](https://github.com/phelipetls/vim-hugo) +: A Vim plugin with syntax highlighting for templates and a few other features. + +[formats]: /content-management/formats/ diff --git a/docs/content/en/tools/front-ends.md b/docs/content/en/tools/front-ends.md new file mode 100644 index 000000000..acce84d8d --- /dev/null +++ b/docs/content/en/tools/front-ends.md @@ -0,0 +1,30 @@ +--- +title: Front-end interfaces +linkTitle: Front-ends +description: Do you prefer a graphical user interface over a text editor? Give these front-ends a try. +categories: [developer tools] +keywords: [frontend, gui] +menu: + docs: + parent: developer-tools + weight: 30 +weight: 30 +toc: true +aliases: [/tools/frontends/] +--- + +## Commercial + +[CloudCannon](https://cloudcannon.com/hugo-cms/) +: The intuitive Git-based CMS for your Hugo website. CloudCannon syncs changes from your Git repository and pushes content changes back, so your development and content teams are always in sync. Edit all of your content on the page with visual editing, build entire pages with reusable custom components and then publish confidently. + +[DatoCMS](https://www.datocms.com) +: DatoCMS is a fully customizable administrative area for your static websites. Use your favorite website generator, let your clients publish new content independently, and the host the site anywhere you like. + +## Open source + +[Decap CMS](https://decapcms.org/) +: Decap CMS is an open-source, serverless solution for managing Git based content in static sites, and it works on any platform that can host static sites. A [Hugo/Decap CMS starter](https://github.com/decaporg/one-click-hugo-cms) is available to get new projects running quickly. + +[Sveltia CMS](https://github.com/sveltia/sveltia-cms/) +: Sveltia CMS is a drop-in replacement for Decap CMS which is built from the ground up with powerful and performant modern UI library Svelte. Sveltia CMS incorporates i18n into every corner of the product, while striving to radically improve UX, performance and productivity. diff --git a/docs/content/en/tools/migrations.md b/docs/content/en/tools/migrations.md new file mode 100644 index 000000000..0e61274c4 --- /dev/null +++ b/docs/content/en/tools/migrations.md @@ -0,0 +1,102 @@ +--- +title: Migrate to Hugo +linkTitle: Migrations +description: A list of community-developed tools for migrating from your existing static site generator or content management system to Hugo. +categories: [developer tools] +keywords: [migrations,jekyll,wordpress,drupal,ghost,contentful] +menu: + docs: + parent: developer-tools + weight: 50 +weight: 50 +toc: true +aliases: [/developer-tools/migrations/, /developer-tools/migrated/] +--- + +This section highlights some projects around Hugo that are independently developed. These tools try to extend the functionality of our static site generator or help you to get started. + +Take a look at this list of migration tools if you currently use other blogging tools like Jekyll or WordPress but intend to switch to Hugo instead. They'll take care to export your content into Hugo-friendly formats. + +## Jekyll + +Alternatively, you can use the [Jekyll import command](/commands/hugo_import_jekyll/). + +[JekyllToHugo](https://github.com/fredrikloch/JekyllToHugo) +: A Small script for converting Jekyll blog posts to a Hugo site. + +[ConvertToHugo](https://github.com/coderzh/ConvertToHugo) +: Convert your blog from Jekyll to Hugo. + +## Octopress + +[octohug](https://github.com/codebrane/octohug) +: Octopress to Hugo migrator. + +## DokuWiki + +[dokuwiki-to-hugo](https://github.com/wgroeneveld/dokuwiki-to-hugo) +: Migrates your DokuWiki source pages from [DokuWiki syntax](https://www.dokuwiki.org/wiki:syntax) to Hugo Markdown syntax. Includes extra's like the TODO plugin. Written with extensibility in mind using python 3. Also generates a TOML header for each page. Designed to copypaste the wiki directory into your /content directory. + +## WordPress + +[wordpress-to-hugo-exporter](https://github.com/SchumacherFM/wordpress-to-hugo-exporter) +: A one-click WordPress plugin that converts all posts, pages, taxonomies, metadata, and settings to Markdown and YAML which can be dropped into Hugo. (Note: If you have trouble using this plugin, you - \s-\scan [export your site for Jekyll](https://wordpress.org/plugins/jekyll-exporter/) and use Hugo's built in Jekyll converter listed above.) + +[blog2md](https://github.com/palaniraja/blog2md) +: Works with [exported xml](https://en.support.wordpress.com/export/) file of your free YOUR-TLD.wordpress.com website. It also saves approved comments to `YOUR-POST-NAME-comments.md` file along with posts. + +[wordhugopress](https://github.com/nantipov/wordhugopress) +: A small utility written in Java, exports the entire WordPress site from the database and resource (e.g. images) files stored locally or remotely. Therefore, migration from the backup files is possible. Supports merging of the multiple WordPress sites into a single Hugo one. + +## Medium + +[medium2md](https://github.com/gautamdhameja/medium-2-md) +: A simple Medium to Hugo exporter able to import stories in one command, including front matter. + +[medium-to-hugo](https://github.com/bgadrian/medium-to-hugo) +: CLI tool written in Go to export medium posts into a Hugo compatible Markdown format. Tags and images are included. All images will be downloaded locally and linked appropriately. + +## Tumblr + +[tumblr-importr](https://github.com/carlmjohnson/tumblr-importr) +: An importer that uses the Tumblr API to create a Hugo static site. + +[tumblr2hugomarkdown](https://github.com/Wysie/tumblr2hugomarkdown) +: Export all your Tumblr content to Hugo Markdown files with preserved original formatting. + +[Tumblr to Hugo](https://github.com/jipiboily/tumblr-to-hugo) +: A migration tool that converts each of your Tumblr posts to a content file with a proper title and path. Furthermore, "Tumblr to Hugo" creates a CSV file with the original URL and the new path on Hugo, to help you setup the redirections. + +## Drupal + +[drupal2hugo](https://github.com/danapsimer/drupal2hugo) +: Convert a Drupal site to Hugo. + +## Joomla + +[hugojoomla](https://github.com/davetcc/hugojoomla) +: This utility written in Java takes a Joomla database and converts all the content into Markdown files. It changes any URLs that are in Joomla's internal format and converts them to a suitable form. + +## Blogger + +[blogimport](https://github.com/natefinch/blogimport) +: A tool to import from Blogger posts to Hugo. + +[blogger-to-hugo](https://pypi.org/project/blogger-to-hugo/) +: Another tool to import Blogger posts to Hugo. It also downloads embedded images so they will be stored locally. + +[blog2md](https://github.com/palaniraja/blog2md) +: Works with [exported xml](https://support.google.com/blogger/answer/41387?hl=en) file of your YOUR-TLD.blogspot.com website. It also saves comments to `YOUR-POST-NAME-comments.md` file along with posts. + +[BloggerToHugo](https://github.com/huanlin/blogger-to-hugo) +: Yet another tool to import Blogger posts to Hugo. For Windows platform only, and .NET Framework 4.5 is required. See README.md before using this tool. + +## Contentful + +[contentful-hugo](https://github.com/ModiiMedia/contentful-hugo) +: A tool to create content-files for Hugo from content on [Contentful](https://www.contentful.com/). + +## BlogML + +[BlogML2Hugo](https://github.com/jijiechen/BlogML2Hugo) +: A tool that helps you convert BlogML xml file to Hugo Markdown files. Users need to take care of links to attachments and images by themselves. This helps the blogs that export BlogML files (e.g. BlogEngine.NET) transform to hugo sites easily. diff --git a/docs/content/en/tools/other.md b/docs/content/en/tools/other.md new file mode 100644 index 000000000..f5243632c --- /dev/null +++ b/docs/content/en/tools/other.md @@ -0,0 +1,23 @@ +--- +title: Other community projects +linkTitle: Other projects +description: Some interesting projects developed by the Hugo community that don't quite fit into our other developer tool categories. +categories: [developer tools] +keywords: [frontend,gui] +menu: + docs: + parent: developer-tools + weight: 60 +weight: 60 +--- + +And for all the other small things around Hugo: + +- [hugo-gallery](https://github.com/icecreammatt/hugo-gallery) lets you create an image gallery for Hugo sites. +- [flickr-hugo-embed](https://github.com/nikhilm/flickr-hugo-embed) prints shortcodes to embed a set of images from an album on Flickr into Hugo. +- [hugo-openapispec-shortcode](https://github.com/tenfourty/hugo-openapispec-shortcode) A shortcode that allows you to include [Open API Spec](https://openapis.org) (formerly known as Swagger Spec) in a page. +- [HugoPhotoSwipe](https://github.com/GjjvdBurg/HugoPhotoSwipe) makes it easy to create image galleries using PhotoSwipe. +- [Hugo SFTP Upload](https://github.com/thomasmey/HugoSftpUpload) Syncs the local build of your Hugo website with your remote web server via SFTP. +- [Emacs Easy Hugo](https://github.com/masasam/emacs-easy-hugo) Emacs package for writing blog posts in markdown or org-mode and building your site with Hugo. +- [JAMStack Themes](https://jamstackthemes.dev/ssg/hugo/). JAMStack themes is a collection of site themes filterable by static site generator and supported CMS to help build CMS-connected sites using Hugo (linking to Hugo-specific themes). +- [plausible-hugo](https://github.com/divinerites/plausible-hugo). Easy Hugo integration for Plausible Analytics, a simple, open-source, lightweight and privacy-friendly web analytics alternative to Google Analytics. diff --git a/docs/content/en/tools/search.md b/docs/content/en/tools/search.md new file mode 100644 index 000000000..c3db0dc98 --- /dev/null +++ b/docs/content/en/tools/search.md @@ -0,0 +1,55 @@ +--- +title: Search tools +linkTitle: Search +description: See some of the open-source and commercial search options for your newly created Hugo website. +categories: [developer tools] +keywords: [search] +menu: + docs: + parent: developer-tools + weight: 40 +weight: 40 +toc: true +--- + +A static website with a dynamic search function? Yes, Hugo provides an alternative to embeddable scripts from Google or other search engines for static websites. Hugo allows you to provide your visitors with a custom search function by indexing your content files directly. + +## Open source + +[Pagefind](https://github.com/cloudcannon/pagefind) +: A fully static search library that aims to perform well on large sites, while using as little of your users' bandwidth as possible. + +[GitHub Gist for Hugo Workflow](https://gist.github.com/sebz/efddfc8fdcb6b480f567) +: This gist contains a simple workflow to create a search index for your static website. It uses a simple Grunt script to index all your content files and [lunr.js](https://lunrjs.com/) to serve the search results. + +[hugo-lunr](https://www.npmjs.com/package/hugo-lunr) +: A simple way to add site search to your static Hugo site using [lunr.js](https://lunrjs.com/). Hugo-lunr will create an index file of any HTML and Markdown documents in your Hugo project. + +[hugo-lunr-zh](https://www.npmjs.com/package/hugo-lunr-zh) +: A bit like Hugo-lunr, but Hugo-lunr-zh can help you separate the Chinese keywords. + +[GitHub Gist for Fuse.js integration](https://gist.github.com/eddiewebb/735feb48f50f0ddd65ae5606a1cb41ae) +: This gist demonstrates how to leverage Hugo's existing build time processing to generate a searchable JSON index used by [Fuse.js](https://fusejs.io/) on the client-side. Although this gist uses Fuse.js for fuzzy matching, any client-side search tool capable of reading JSON indexes will work. Does not require npm, grunt, or other build-time tools except Hugo! + +[hugo-search-index](https://www.npmjs.com/package/hugo-search-index) +: A library containing Gulp tasks and a prebuilt browser script that implements search. Gulp generates a search index from project markdown files. + +[hugofastsearch](https://gist.github.com/cmod/5410eae147e4318164258742dd053993) +: A usability and speed update to "GitHub Gist for Fuse.js integration" — global, keyboard-optimized search. + +[JS & Fuse.js tutorial](https://makewithhugo.com/add-search-to-a-hugo-site/) +: A simple client-side search solution, using FuseJS (does not require jQuery). + +[Hugo Lyra](https://github.com/paolomainardi/hugo-lyra) +: Hugo-Lyra is a JavaScript module to integrate [Lyra](https://github.com/LyraSearch/lyra) into a Hugo website. It contains the server-side part to generate the index and the client-side library (optional) to bootstrap the search engine easily. + +## Commercial + +[Algolia](https://www.algolia.com/) +: Algolia's Search API makes it easy to deliver a great search experience in your apps and websites. Algolia Search provides hosted full-text, numerical, faceted, and geolocalized search. + +[Bonsai](https://www.bonsai.io) +: Bonsai is a fully-managed hosted Elasticsearch service that is fast, reliable, and simple to set up. Easily ingest your docs from Hugo into Elasticsearch following [this guide from the docs](https://bonsai.io/docs/hugo). + +[ExpertRec](https://www.expertrec.com/) +: ExpertRec is a hosted search-as-a-service solution that is fast and scalable. Set-up and integration is extremely easy and takes only a few minutes. The search settings can be modified without coding using a dashboard. diff --git a/docs/content/en/troubleshooting/_index.md b/docs/content/en/troubleshooting/_index.md new file mode 100644 index 000000000..65263ab32 --- /dev/null +++ b/docs/content/en/troubleshooting/_index.md @@ -0,0 +1,16 @@ +--- +title: Troubleshooting +linkTitle: Overview +description: Use these techniques when troubleshooting your site. +categories: [] +keywords: [] +menu: + docs: + identifier: troubleshooting-overview + parent: troubleshooting + weight: 10 +weight: 10 +aliases: [/templates/template-debugging/] +--- + +Use these techniques when troubleshooting your site. diff --git a/docs/content/en/troubleshooting/audit/index.md b/docs/content/en/troubleshooting/audit/index.md new file mode 100644 index 000000000..f00ed8f8d --- /dev/null +++ b/docs/content/en/troubleshooting/audit/index.md @@ -0,0 +1,73 @@ +--- +title: Site audit +linkTitle: Audit +description: Run this audit before deploying your production site. +categories: [troubleshooting] +keywords: [] +menu: + docs: + parent: troubleshooting + weight: 20 +weight: 20 +--- + +There are several conditions that can produce errors in your published site which are not detected during the build. Run this audit before your final build. + +{{< code copy=true >}} +HUGO_MINIFY_TDEWOLFF_HTML_KEEPCOMMENTS=true HUGO_ENABLEMISSINGTRANSLATIONPLACEHOLDERS=true hugo && grep -inorE "<\!-- raw HTML omitted -->|ZgotmplZ|\[i18n\]|\(<nil>\)|(<nil>)|hahahugo" public/ +{{< /code >}} + +_Tested with GNU Bash 5.1 and GNU grep 3.7._ + +## Example output + + + +## Explanation + +### Environment variables + +`HUGO_MINIFY_TDEWOLFF_HTML_KEEPCOMMENTS=true` +: Retain HTML comments even if minification is enabled. This takes precedence over `minify.tdewolff.html.keepComments` in the site configuration. If you minify without keeping HTML comments when performing this audit, you will not be able to detect when raw HTML has been omitted. + +`HUGO_ENABLEMISSINGTRANSLATIONPLACEHOLDERS=true` +: Show a placeholder instead of the default value or an empty string if a translation is missing. This takes precedence over `enableMissingTranslationPlaceholders` in the site configuration. + +### Grep options + +`-i, --ignore-case` +: Ignore case distinctions in patterns and input data, so that characters that differ only in case match each other. + +`-n, --line-number` +: Prefix each line of output with the 1-based line number within its input file. + +`-o, --only-matching` +: Print only the matched (non-empty) parts of a matching line, with each such part on a separate output line. + +`-r, --recursive` +: Read all files under each directory, recursively, following symbolic links only if they are on the command line. + +`-E, --extended-regexp` +: Interpret PATTERNS as extended regular expressions. + +### Patterns + +`<!-- raw HTML omitted -->` +: By default, Hugo strips raw HTML from your markdown prior to rendering, and leaves this HTML comment in its place. + +`ZgotmplZ` +: ZgotmplZ is a special value that indicates that unsafe content reached a CSS or URL context at runtime. See [details]. + +[details]: https://pkg.go.dev/html/template + +`[i18n]` +: This is the placeholder produced instead of the default value or an empty string if a translation is missing. + +`(<nil>)` +: This string will appear in the rendered HTML when passing a nil value to the `printf` function. + +`(<nil>)` +: Same as above when the value returned from the `printf` function has not been passed through `safeHTML`. + +`HAHAHUGO` +: Under certain conditions a rendered shortcode may include all or a portion of the string HAHAHUGOSHORTCODE in either uppercase or lowercase. This is difficult to detect in all circumstances, but a case-insensitive search of the output for `HAHAHUGO` is likely to catch the majority of cases without producing false positives. diff --git a/docs/content/en/troubleshooting/audit/screen-capture.png b/docs/content/en/troubleshooting/audit/screen-capture.png Binary files differnew file mode 100644 index 000000000..221abfff0 --- /dev/null +++ b/docs/content/en/troubleshooting/audit/screen-capture.png diff --git a/docs/content/en/troubleshooting/deprecation.md b/docs/content/en/troubleshooting/deprecation.md new file mode 100644 index 000000000..aa4bb71a2 --- /dev/null +++ b/docs/content/en/troubleshooting/deprecation.md @@ -0,0 +1,50 @@ +--- +title: Deprecation +description: The Hugo project follows a formal and consistent process to deprecate functions, methods, and configuration settings. +categories: [troubleshooting] +keywords: [] +menu: + docs: + parent: troubleshooting + weight: 50 +weight: 50 +--- + +When a project _deprecates_ something, they are telling its users: + +1. Don't use Thing One anymore. +2. Use Thing Two instead. +3. We're going to remove Thing One at some point in the future. + +[reasons for deprecation]: https://en.wikipedia.org/wiki/Deprecation + +Common [reasons for deprecation]: + +- A feature has been replaced by a more powerful alternative. +- A feature contains a design flaw. +- A feature is considered extraneous, and will be removed in the future in order to simplify the system as a whole. +- A future version of the software will make major structural changes, making it impossible or impractical to support older features. +- Standardization or increased consistency in naming. +- A feature that once was available only independently is now combined with its co-feature. + +After the project team deprecates something in code, Hugo will: + +1. Log an INFO message for 6 minor releases[^1] +2. Log a WARN message for another 6 minor releases +3. Log an ERROR message and fail the build thereafter + +To see the INFO messages, you must use the `--logLevel` command line flag: + +```text +hugo --logLevel info +``` + +To limit the output to deprecation notices: + +```text +hugo --logLevel info | grep deprecate +``` + +Run the above command every time you upgrade Hugo. + +[^1]: For example, v0.1.1 => v0.2.0 is a minor release. diff --git a/docs/content/en/troubleshooting/faq.md b/docs/content/en/troubleshooting/faq.md new file mode 100644 index 000000000..0425ca277 --- /dev/null +++ b/docs/content/en/troubleshooting/faq.md @@ -0,0 +1,124 @@ +--- +title: Frequently asked questions +linkTitle: FAQs +description: These questions are frequently asked by new users. +categories: [troubleshooting] +keywords: [faq] +menu: + docs: + parent: troubleshooting + weight: 70 +weight: 70 +# Use level 6 headings for each question. +--- + +Hugo’s [forum] is an active community of users and developers who answer questions, share knowledge, and provide examples. A quick search of over 20,000 topics will often answer your question. Please be sure to read about [requesting help] before asking your first question. + +These are just a few of the questions most frequently asked by new users. + +###### An error message indicates that a feature is not available. Why? + +Hugo is available in two editions: standard and extended. With the extended edition you can (a) encode to the WebP format when processing images, and (b) transpile Sass to CSS using the embedded LibSass transpiler. The extended edition is not required to use the Dart Sass transpiler. + +When you attempt to perform either of the operations above with the standard edition, Hugo throws this error: + +```go-html-template +Error: this feature is not available in your current Hugo version +``` + +To resolve, uninstall the standard edition, then install the extended edition. See the [installation] section for details. + +###### Why do I see "Page Not Found" when visiting the home page? + +In the content/_index.md file: + + - Is `draft` set to `true`? + - Is the `date` in the future? + - Is the `publishDate` in the future? + - Is the `expiryDate` in the past? + +If the answer to any of these questions is yes, either change the field values, or use one of these command line flags: `--buildDrafts`, `--buildFuture`, or `--buildExpired`. + +###### Why is a given section not published? + +In the content/section/_index.md file: + + - Is `draft` set to `true`? + - Is the `date` in the future? + - Is the `publishDate` in the future? + - Is the `expiryDate` in the past? + +If the answer to any of these questions is yes, either change the field values, or use one of these command line flags: `--buildDrafts`, `--buildFuture`, or `--buildExpired`. + +###### Why is a given page not published? + +In the content/section/page.md file, or in the content/section/page/index.md file: + + - Is `draft` set to `true`? + - Is the `date` in the future? + - Is the `publishDate` in the future? + - Is the `expiryDate` in the past? + +If the answer to any of these questions is yes, either change the field values, or use one of these command line flags: `--buildDrafts`, `--buildFuture`, or `--buildExpired`. + +###### Why can't I see any of a page's descendants? + +You may have an index.md file instead of an _index.md file. See [details](/content-management/page-bundles/). + +###### What is the difference between an index.md file and an _index.md file? + +A directory with an index.md file is a [leaf bundle]. A directory with an _index.md file is a [branch bundle]. See [details](/content-management/page-bundles/). + +[branch bundle]: /getting-started/glossary/#branch-bundle +[leaf bundle]: /getting-started/glossary/#leaf-bundle + +###### Why is my partial template not rendered as expected? {#foo} + +You may have neglected to pass the required [context] when calling the partial. For example: + +```go-html-template +{{/* incorrect */}} +{{ partial "_internal/pagination.html" }} + +{{/* correct */}} +{{ partial "_internal/pagination.html" . }} +``` + +###### In a template, what's the difference between `:=` and `=` when assigning values to variables? + +Use `:=` to initialize a variable, and use `=` to assign a value to a variable that has been previously initialized. See [details](https://pkg.go.dev/text/template#hdr-Variables). + +###### When I paginate a list page, why is the page collection not filtered as specified? + +You are probably invoking the [`Paginate`] or [`Paginator`] method more than once on the same page. See [details](/templates/pagination/#list-paginator-pages). + +###### Why are there two ways to call a shortcode? + +Use the `{{%/* shortcode */%}}` notation if the shortcode template, or the content between the opening and closing shortcode tags, contains markdown. Otherwise use the\ +`{{</* shortcode */>}}` notation. See [details](/content-management/shortcodes/). + +###### Can I use environment variables to control configuration? + +Yes. See [details](/getting-started/configuration/#configure-with-environment-variables). + +###### Why am I seeing inconsistent output from one build to the next? + +The most common causes are page collisions (publishing two pages to the same path) and the effects of concurrency. Use the `--printPathWarnings` command line flag to check for page collisions, and create a topic on the [forum] if you suspect concurrency problems. + +###### Which page methods trigger content rendering? + +The following methods on a `Page` object trigger content rendering: `Content`, `FuzzyWordCount`, `Len`, `Plain`, `PlainWords`, `ReadingTime`, `Summary`, `Truncated`, and `WordCount`. + +{{% note %}} +For other questions please visit the [forum]. A quick search of over 20,000 topics will often answer your question. Please be sure to read about [requesting help] before asking your first question. + +[forum]: https://discourse.gohugo.io +[requesting help]: https://discourse.gohugo.io/t/requesting-help/9132 +{{% /note %}} + +[`Paginate`]: /methods/page/paginate +[`Paginator`]: /methods/page/paginator +[context]: /getting-started/glossary/#context +[forum]: https://discourse.gohugo.io +[installation]: /installation +[requesting help]: https://discourse.gohugo.io/t/requesting-help/9132 diff --git a/docs/content/en/troubleshooting/inspection.md b/docs/content/en/troubleshooting/inspection.md new file mode 100644 index 000000000..826229153 --- /dev/null +++ b/docs/content/en/troubleshooting/inspection.md @@ -0,0 +1,72 @@ +--- +title: Data inspection +linkTitle: Inspection +description: Use template functions to inspect values and data structures. +categories: [troubleshooting] +keywords: [] +menu: + docs: + parent: troubleshooting + weight: 40 +weight: 40 +--- + +Use the [`jsonify`] function to inspect a data structure: + +```go-html-template +<pre>{{ jsonify (dict "indent" " ") .Params }}</pre> +``` + +```text +{ + "date": "2023-11-10T15:10:42-08:00", + "draft": false, + "iscjklanguage": false, + "lastmod": "2023-11-10T15:10:42-08:00", + "publishdate": "2023-11-10T15:10:42-08:00", + "tags": [ + "foo", + "bar" + ], + "title": "My first post" +} +``` + +{{% note %}} +Hugo will throw an error if you attempt to use the construct above to display context that includes a page collection. For example, in a home page template, this will fail: + +`{{ jsonify (dict "indent" " ") . }}` +{{% /note %}} + +Use the [`debug.Dump`] function to inspect data types: + +```go-html-template +<pre>{{ debug.Dump .Params }}</pre> +``` + +```text +maps.Params{ + "date": time.Time{}, + "draft": false, + "iscjklanguage": false, + "lastmod": time.Time{}, + "publishdate": time.Time{}, + "tags": []string{ + "foo", + "bar", + }, + "title": "My first post", +} +``` + +Use the [`printf`] function (render) or [`warnf`] function (log to console) to inspect simple data structures. The layout string below displays both value and data type. + +```go-html-template +{{ $value := 42 }} +{{ printf "%[1]v (%[1]T)" $value }} → 42 (int) +``` + +[`jsonify`]: /functions/encoding/jsonify +[`debug.Dump`]: /functions/debug/dump +[`printf`]: /functions/fmt/printf +[`warnf`]: /functions/fmt/warnf diff --git a/docs/content/en/troubleshooting/logging.md b/docs/content/en/troubleshooting/logging.md new file mode 100644 index 000000000..8879c1846 --- /dev/null +++ b/docs/content/en/troubleshooting/logging.md @@ -0,0 +1,56 @@ +--- +title: Logging +description: Enable logging to inspect events while building your site. +categories: [troubleshooting] +keywords: [] +menu: + docs: + parent: troubleshooting + weight: 30 +weight: 30 +toc: true +--- + +## Command line + +Enable console logging with the `--logLevel` command line flag. + +Hugo has four logging levels: + +error +: Display error messages only. + +```sh +hugo --logLevel error +``` + +warn +: Display warning and error messages. + +```sh +hugo --logLevel warn +``` + +info +: Display information, warning, and error messages. + +```sh +hugo --logLevel info +``` + +debug +: Display debug, information, warning, and error messages. + +```sh +hugo --logLevel debug +``` + +{{% note %}} +If you do not specify a logging level with the `--logLevel` flag, warnings and errors are always displayed. +{{% /note %}} + +## Template functions + +You can also use template functions to print warnings or errors to the console. These functions are typically used to report data validation errors, missing files, etc. + +{{< list-pages-in-section path=/functions/fmt filter=functions_fmt_logging filterType=include >}} diff --git a/docs/content/en/troubleshooting/performance.md b/docs/content/en/troubleshooting/performance.md new file mode 100644 index 000000000..174d6cfd9 --- /dev/null +++ b/docs/content/en/troubleshooting/performance.md @@ -0,0 +1,94 @@ +--- +title: Performance +description: Use template metrics and timers to identify opportunities to improve performance. +categories: [troubleshooting] +keywords: [] +menu: + docs: + parent: troubleshooting + weight: 60 +weight: 60 +toc: true +aliases: [/troubleshooting/build-performance/] +--- + +## Template metrics + +Hugo is fast, but inefficient templates impede performance. Enable template metrics to determine which templates take the most time, and to identify caching opportunities: + +```sh +hugo --templateMetrics --templateMetricsHints +``` + +The result will look something like this: + +```text +Template Metrics: + + cumulative average maximum cache percent cached total + duration duration duration potential cached count count template + ---------- -------- -------- --------- ------- ------ ----- -------- + 36.037476822s 135.990478ms 225.765245ms 11 0 0 265 partials/head.html + 35.920040902s 164.018451ms 233.475072ms 0 0 0 219 articles/single.html + 34.163268129s 128.917992ms 224.816751ms 23 0 0 265 partials/head/meta/opengraph.html + 1.041227437s 3.92916ms 186.303376ms 47 0 0 265 partials/head/meta/schema.html + 805.628827ms 27.780304ms 114.678523ms 0 0 0 29 _default/list.html + 624.08354ms 15.221549ms 108.420729ms 8 0 0 41 partials/utilities/render-page-collection.html + 545.968801ms 775.523µs 105.045775ms 0 0 0 704 _default/summary.html + 334.680981ms 1.262947ms 127.412027ms 100 0 0 265 partials/head/js.html + 272.763205ms 2.050851ms 24.371757ms 0 0 0 133 _default/_markup/render-codeblock.html + 230.490038ms 8.865001ms 177.4615ms 0 0 0 26 shortcodes/template.html + 176.921913ms 176.921913ms 176.921913ms 0 0 0 1 examples.tmpl + 163.951469ms 14.904679ms 70.267953ms 0 0 0 11 articles/list.html + 153.07021ms 577.623µs 73.593597ms 100 0 0 265 partials/head/init.html + 150.910984ms 150.910984ms 150.910984ms 0 0 0 1 _default/single.html + 146.785804ms 146.785804ms 146.785804ms 0 0 0 1 _default/contact.html + 115.364617ms 115.364617ms 115.364617ms 0 0 0 1 authors/term.html + 87.392071ms 329.781µs 10.687132ms 100 0 0 265 partials/head/css.html + 86.803122ms 86.803122ms 86.803122ms 0 0 0 1 _default/home.html +``` + +From left to right, the columns represent: + +cumulative duration +: The cumulative time spent executing the template. + +average duration +: The average time spent executing the template. + +maximum duration +: The maximum time spent executing the template. + +cache potential +: Displayed as a percentage, any partial template with a 100% cache potential should be called with the [`partialCached`] function instead of the [`partial`] function. See the [caching](#caching) section below. + +percent cached +: The number of times the rendered templated was cached divided by the number of times the template was executed. + +cached count +: The number of times the rendered templated was cached. + +total count +: The number of times the template was executed. + +template +: The path to the template, relative to the layouts directory. + +[`partial`]: /functions/partials/include +[`partialCached`]: /functions/partials/includecached + +{{% note %}} +Hugo builds pages in parallel where multiple pages are generated simultaneously. Because of this parallelism, the sum of "cumulative duration" values is usually greater than the actual time it takes to build a site. +{{% /note %}} + +## Caching + +Some partial templates such as sidebars or menus are executed many times during a site build. Depending on the content within the partial template and the desired output, the template may benefit from caching to reduce the number of executions. The [`partialCached`] template function provides caching capabilities for partial templates. + +{{% note %}} +Note that you can create cached variants of each partial by passing additional parameters to `partialCached` beyond the initial context. See the `partialCached` documentation for more details. +{{% /note %}} + +## Timers + +Use the `debug.Timer` function to determine execution time for a block of code, useful for finding performance bottle necks in templates. See [details](/functions/debug/timer/). diff --git a/docs/content/en/variables/_common/_index.md b/docs/content/en/variables/_common/_index.md new file mode 100644 index 000000000..47d5812fb --- /dev/null +++ b/docs/content/en/variables/_common/_index.md @@ -0,0 +1,13 @@ +--- +cascade: + _build: + list: never + publishResources: false + render: never +--- + +<!-- +Files within this headless branch bundle are markdown snippets. Each file must contain front matter delimiters, though front matter fields are not required. + +Include the rendered content using the "include" shortcode. +--> diff --git a/docs/content/en/variables/_common/consistent-terminology.md b/docs/content/en/variables/_common/consistent-terminology.md new file mode 100644 index 000000000..8774c817b --- /dev/null +++ b/docs/content/en/variables/_common/consistent-terminology.md @@ -0,0 +1,20 @@ +--- +# Do not remove front matter. +--- + +{{% note %}} +We are making an effort to unify our [terminology], and to use these terms consistently throughout the documentation. + +Historically, we have inconsistently referred to the items on this page as [functions], [parameters], [variables], or [methods]. They are not functions, parameters, or variables; they are methods. + +This page will remain in place as readers become familiar with the unified terminology. See the [methods section] for a list of methods by [object], or the [methods quick reference guide]. + +[functions]: /getting-started/glossary/#function +[methods quick reference guide]: /quick-reference/methods +[methods section]: /methods +[methods]: /getting-started/glossary/#method +[object]: /getting-started/glossary/#object +[parameters]: /getting-started/glossary/#parameter +[terminology]: /getting-started/glossary/ +[variables]: /getting-started/glossary/#variable +{{% /note %}} diff --git a/docs/content/en/variables/_index.md b/docs/content/en/variables/_index.md new file mode 100644 index 000000000..d8dbf9d67 --- /dev/null +++ b/docs/content/en/variables/_index.md @@ -0,0 +1,16 @@ +--- +title: Variables +linkTitle: Overview +description: Use these variables in your templates. +categories: [] +keywords: [] +menu: + docs: + identifier: variables-overview + parent: variables + weight: 10 +weight: 10 +aliases: [/templates/variables/] +--- + +{{% include "variables/_common/consistent-terminology.md" %}} diff --git a/docs/content/en/variables/file.md b/docs/content/en/variables/file.md new file mode 100644 index 000000000..248d84991 --- /dev/null +++ b/docs/content/en/variables/file.md @@ -0,0 +1,18 @@ +--- +title: File variables +description: Retrieve file information about any page that is backed by a file. +categories: [variables] +keywords: [] +menu: + docs: + parent: variables + weight: 20 +weight: 20 +aliases: [/variables/file-variables/,/variables/files/] +--- + +{{% include "variables/_common/consistent-terminology.md" %}} + +To retrieve file information about any page that is backed by a file, see the documentation for the [`File`] method on a `Page` object. + +[`File`]: /methods/page/file diff --git a/docs/content/en/variables/git.md b/docs/content/en/variables/git.md new file mode 100644 index 000000000..3dc473265 --- /dev/null +++ b/docs/content/en/variables/git.md @@ -0,0 +1,18 @@ +--- +title: Git variables +description: Retrieve Git information related to the last commit of any page. +categories: [variables] +keywords: [] +menu: + docs: + parent: variables + weight: 30 +weight: 30 +aliases: [/extras/gitinfo/] +--- + +{{% include "variables/_common/consistent-terminology.md" %}} + +To retrieve Git information related to the last commit of any page, see the documentation for the [`GitInfo`] method on a `Page` object. + +[`GitInfo`]: /methods/page/gitinfo diff --git a/docs/content/en/variables/menu-entry.md b/docs/content/en/variables/menu-entry.md new file mode 100644 index 000000000..5b90dab6f --- /dev/null +++ b/docs/content/en/variables/menu-entry.md @@ -0,0 +1,16 @@ +--- +title: Menu entry variables +description: Use these methods in your menu templates. +categories: [variables] +keywords: [] +menu: + docs: + parent: variables + weight: 40 +weight: 40 +aliases: [/variables/menus/] +--- + +{{% include "variables/_common/consistent-terminology.md" %}} + +{{< list-pages-in-section path=/methods/menu-entry titlePrefix=. >}} diff --git a/docs/content/en/variables/page.md b/docs/content/en/variables/page.md new file mode 100644 index 000000000..732cf5499 --- /dev/null +++ b/docs/content/en/variables/page.md @@ -0,0 +1,63 @@ +--- +title: Page variables +description: Use these methods with a Page object. +categories: [variables] +keywords: [] +menu: + docs: + parent: variables + weight: 50 +weight: 50 +toc: true +--- + +{{% include "variables/_common/consistent-terminology.md" %}} + +## All methods + +Use any of these methods in your templates. + +{{< list-pages-in-section path=/methods/page titlePrefix=. >}} + +## Dates + +Use these methods to access content dates. + +{{< list-pages-in-section path=/methods/page filter=methods_page_dates filterType=include titlePrefix=. omitElementIDs=true >}} + +## Multilingual + +Use these methods with your multilingual projects. + +{{< list-pages-in-section path=/methods/page filter=methods_page_multilingual filterType=include titlePrefix=. omitElementIDs=true >}} + +## Navigation + +Use these methods to create navigation links between pages. + +{{< list-pages-in-section path=/methods/page filter=methods_page_navigation filterType=include titlePrefix=. omitElementIDs=true >}} + +## Page collections + +Range through these collections when rendering lists on [section] pages, [taxonomy] pages, [term] pages, and the home page. + +[section]: /getting-started/glossary/#section +[taxonomy]: /getting-started/glossary/#taxonomy +[term]: /getting-started/glossary/#term +[context]: /getting-started/glossary/#context + +{{< list-pages-in-section path=/methods/page filter=methods_page_page_collections filterType=include titlePrefix=. omitElementIDs=true >}} + +## Parameters + +Use these methods to access page parameters. + +{{< list-pages-in-section path=/methods/page filter=methods_page_parameters filterType=include titlePrefix=. omitElementIDs=true >}} + +## Sections + +Use these methods to access section pages, and their ancestors and descendants. See [details]. + +[details]: /content-management/sections/ + +{{< list-pages-in-section path=/methods/page filter=methods_page_sections filterType=include titlePrefix=. omitElementIDs=true >}} diff --git a/docs/content/en/variables/pages.md b/docs/content/en/variables/pages.md new file mode 100644 index 000000000..24b8fbbf4 --- /dev/null +++ b/docs/content/en/variables/pages.md @@ -0,0 +1,39 @@ +--- +title: Pages variables +description: Use these methods with a collection of Page objects. +categories: [variables] +keywords: [] +menu: + docs: + parent: variables + weight: 60 +weight: 60 +toc: true +aliases: [/variables/site-variables/] +--- + +{{% include "variables/_common/consistent-terminology.md" %}} + +## All methods + +Use any of these methods with page collections in your templates. + +{{< list-pages-in-section path=/methods/pages titlePrefix=. >}} + +## Sort by + +Use these methods to sort page collections. + +{{< list-pages-in-section path=/methods/pages filter=methods_pages_sort filterType=include titlePrefix=. omitElementIDs=true >}} + +## Group by + +Use these methods to group page collections. + +{{< list-pages-in-section path=/methods/pages filter=methods_pages_group filterType=include titlePrefix=. omitElementIDs=true >}} + +## Navigation + +Use these methods to create navigation links between pages. + +{{< list-pages-in-section path=/methods/pages filter=methods_pages_navigation filterType=include titlePrefix=. omitElementIDs=true >}} diff --git a/docs/content/en/variables/shortcode.md b/docs/content/en/variables/shortcode.md new file mode 100644 index 000000000..57279b5de --- /dev/null +++ b/docs/content/en/variables/shortcode.md @@ -0,0 +1,16 @@ +--- +title: Shortcode variables +description: Use these methods in your shortcode templates. +categories: [variables] +keywords: [] +menu: + docs: + parent: variables + weight: 70 +weight: 70 +aliases: [/variables/shortcodes] +--- + +{{% include "variables/_common/consistent-terminology.md" %}} + +{{< list-pages-in-section path=/methods/shortcode titlePrefix=. >}} diff --git a/docs/content/en/variables/site.md b/docs/content/en/variables/site.md new file mode 100644 index 000000000..532357785 --- /dev/null +++ b/docs/content/en/variables/site.md @@ -0,0 +1,55 @@ +--- +title: Site variables +description: Use these methods with Site objects. A multilingual project will have two or more sites, one for each language. +categories: [variables] +keywords: [] +menu: + docs: + parent: variables + weight: 80 +weight: 80 +toc: true +aliases: [/variables/site-variables/] +--- + +{{% include "variables/_common/consistent-terminology.md" %}} + +## All methods + +Use any of these methods in your templates. + +{{< list-pages-in-section path=/methods/site titlePrefix=.Site. >}} + +## Multilingual + +Use these methods with your multilingual projects. + +{{< list-pages-in-section path=/methods/site filter=methods_site_multilingual filterType=include titlePrefix=.Site. omitElementIDs=true >}} + +[`site`]: /functions/global/site +[context]: /getting-started/glossary/#context +[configuration file]: /getting-started/configuration + +## Page collections + +Range through these collections when rendering lists on any page. + +{{< list-pages-in-section path=/methods/site filter=methods_site_page_collections filterType=include titlePrefix=.Site. omitElementIDs=true >}} + +## Global site function + +Within a partial template, if you did not pass a `Page` or `Site` object in [context], you cannot use this syntax: + +```go-html-template +{{ .Site.SomeMethod }} +``` + +Instead, use the global [`site`] function: + +```go-html-template +{{ site.SomeMethod }} +``` + +{{% note %}} +You can use the global site function in all templates to avoid context problems. Its usage is not limited to partial templates. +{{% /note %}} diff --git a/docs/content/en/variables/taxonomy.md b/docs/content/en/variables/taxonomy.md new file mode 100644 index 000000000..ee6d73b2e --- /dev/null +++ b/docs/content/en/variables/taxonomy.md @@ -0,0 +1,21 @@ +--- +title: Taxonomy variables +description: Use these methods with Taxonomy objects. +categories: [variables] +keywords: [] +menu: + docs: + parent: variables + weight: 90 +weight: 90 +--- + +{{% include "variables/_common/consistent-terminology.md" %}} + +{{< list-pages-in-section path=/methods/taxonomy titlePrefix=. >}} + +{{% note %}} +Within a taxonomy or term template use the [`Data`] method to retrieve information specific to the taxonomy or term. + +[`Data`]: /methods/page/data +{{% /note %}} |