发布日期: 2026-04-28
版本号: v0.161.0

本次发布包含多项更新:首先,两项安全加固措施——默认为Node工具(如PostCSS、Babel和TailwindCSS)启用权限标识(需Node≥22且Tailwind CSS必须以Node.js包形式安装,不再支持独立可执行文件),以及收紧HTTP URL的默认安全策略。其次,引入多项新功能,包括:在css.Build和css.Sass中支持嵌套的Hugo变量导入;permavlinks配置现可采用基于Slice的灵活匹配规则,支持按路径、类型等条件分类设置;文件名中支持更丰富的维度标识符(如角色、版本、输出格式等),替代原有的挂载配置。此外,更新还涵盖错误修复、依赖升级及代码清理等大量变更。

更新内容 (中文)

本版本包含两个安全加固修复:

  • 我们现在默认使用 --permission 标志运行 Node 工具 PostCSS、Babel 和 TailwindCSS,权限定义在 security.node.permissions 中。这意味着您需要安装 Node >= 22,且 css.TailwindCSS 现在要求 Tailwind CSS CLI 必须作为 Node.js 包安装。独立可执行文件不再受支持
  • 我们使 security.http.urls 中的默认值更加严格。

但还有一些值得注意的新功能:

css.Build 和 css.Sass 中的嵌套变量支持

css.Build 中的一个实际示例是在 hugo.toml 中如下配置:

[params.style]
    primary    = \"#000000\"
    background = \"#ffffff\"
    [params.style.dark]
        primary    = \"#ffffff\"
        background = \"#000000\"

在样式表中:

@import \"hugo:vars\";
@import \"hugo:vars/dark\" (prefers-color-scheme: dark);

:root {
  color-scheme: light dark;
}

基于切片的永久链接配置

permalinks 配置现在更加灵活(旧设置仍然有效)。它使用与 cascade 配置中相同的 target 匹配器,这意味着您现在可以这样操作:

permalinks:
  - target:
      kind: page
      path: \"/books/**\"
    pattern: /books/:year/:slug/
  - target:
      kind: section
      path: \"/{books,books/**}\"
    pattern: /libros/:sections[1:]
  - target:
      kind: page
    pattern: /other/:slug/

以上示例并不完美,但至少展示了核心思想。

文件名中更灵活的标识符方案

我们之前的做法例如 content/mypost.en.md,告知 Hugo 内容文件为英语。使用新方案,您也可以将文件命名为 content/mypost._language_en_.md。这本身听起来不太有用,但它允许使用更多前缀:

前缀 描述 相关场景
language_ 语言 内容和布局文件。
role_ 角色 内容和布局文件。
version_ 版本 内容和布局文件。
outputformat_ 输出格式 布局文件。
mediatype_ 媒体类型 布局文件。
kind_ 页面类型 布局文件。
layout_ 布局 布局文件。

所有变更

  • langs/i18n:修复使用语言变体时的翻译查找 72b85d5f @jmooring #7982
  • create:修复 hugo new content 中的非确定性冲突检测 6436deb3 @jmooring #12602 #12786 #14112 #14769
  • commands:修复配置设置的环境隔离 1eea9fba @jmooring #14763
  • 修复文件名维度标识符(role_Xversion_X)以替换挂载配置 8d6145f3 @bep #14756
  • 修复确保永远不会自动回退到其他角色/版本的页面资源 97477242 @bep #14749 #14752
  • css:支持嵌套的 hugo:vars/ 导入 7622dd86 @bep #14705
  • github:更新 GitHub actions 版本 0814059b @bep #14810
  • hugolib:如果页面未渲染则不渲染别名 8920d56e @jmooring #14807
  • langs/i18n:改进默认内容语言回退 633cc772 @jmooring #14243
  • helpers:移除未使用的代码 4c40c6d5 @bep
  • common/constants:移除未使用的常量 d2594db6 @bep
  • common/paths:移除未使用的代码 ab2de51e @bep
  • tests:更新 Ruby 设置 action 至 v1.305.0 75f61832 @jmooring
  • langs:使用 Language.Locale 作为主要本地化键 1b7495bc @jmooring #9109
  • config/security:向白名单添加 "! " 否定,加固默认 http.urls 79f030be @bep #14792
  • 使用 –permission 标志加固 Node 工具执行 a54c398b @bep #7287
  • tpl/collections:在 where 比较中遵循 Eqer 接口 f5fce935 @bep #14777
  • modules:在 go.mod 重写中忽略非 require 块 4169c1f7 @bep #14783
  • 用相同的上游版本替换并发映射 7574e35b @bep
  • 添加基于切片的永久链接配置,支持 PageMatcher 目标 017a7cd6 @bep #14744
  • commands:添加缺失的导入 e3413d92 @bep
  • 回退 "common/hugo:弃用 extended 和 extended_withdeploy 版本" b01cc147 @bep #14771
  • 稍作调整 SECURITY.md 8ee19ff9 @bep
  • resources/page:为 Issue #14325 添加传递测试 0d58e428 @jmooring
  • 添加更灵活的文件名标识符方案,允许设置角色和版本 (#14754) ce2a156a @bep #14750
  • common/hugo:弃用 extended 和 extended_withdeploy 版本 a17bdbc5 @jmooring #14696
  • parser/pageparser:添加解析器模糊测试 8f94d65c @bep
  • 在测试中用 hugo.Sites 替换已弃用的 .Site.Sites/.Page.Sites 90d8bf34 @bep
  • agents:添加关于在测试名称中包含问题 ID 的说明 bbb42b5a @bep
  • build(deps):将 github.com/getkin/kin-openapi 从 0.135.0 升级到 0.137.0 d4ae662d @dependabot[bot]
  • build(deps):将 github.com/mattn/go-isatty 从 0.0.21 升级到 0.0.22 9ede5fb9 @dependabot[bot]
  • build(deps):将 github.com/tdewolff/minify/v2 从 2.24.12 升级到 2.24.13 833a878e @dependabot[bot]
  • build(deps):将 github.com/magefile/mage 从 1.17.1 升级到 1.17.2 4c03129f @dependabot[bot]
  • deps:升级 github.com/bep/imagemeta v0.17.1 => v0.17.2 080970bc @bep
  • build(deps):将 github.com/aws/aws-sdk-go-v2/service/cloudfront 升级 (#14789) 896bc89a @dependabot[bot]
  • build(deps):将 github.com/mattn/go-isatty 从 0.0.20 升级到 0.0.21 (#14788) 100dde53 @dependabot[bot]
  • build(deps):将 github.com/bep/mclib 升级 (#14787) bdebb797 @dependabot[bot]
  • build(deps):将 google.golang.org/api 从 0.267.0 升级到 0.276.0 52123ae2 @dependabot[bot]
  • build(deps):将 github.com/aws/aws-sdk-go-v2 从 1.41.5 升级到 1.41.6 38b8afdc @dependabot[bot]
  • build(deps):将 github.com/getkin/kin-openapi 从 0.134.0 升级到 0.135.0 (#14781) 92766600 @dependabot[bot]
  • build(deps):将 github.com/bep/goportabletext 从 0.1.0 升级到 0.2.0 (#14779) 790f4084 @dependabot[bot]
  • build(deps):将 golang.org/x/image 从 0.38.0 升级到 0.39.0 (#14780) de6955ba @dependabot[bot]
  • deps:升级 github.com/bep/imagemeta v0.17.0 => v0.17.1 (#14775) a77bd527 @bep #14758
  • build(deps):将 golang.org/x/tools 从 0.43.0 升级到 0.44.0 547ab29c @dependabot[bot]
  • build(deps):将 github.com/evanw/esbuild 从 0.27.4 升级到 0.28.0 9a5c7e0d @dependabot[bot]
  • build(deps):将 github.com/aws/aws-sdk-go-v2 从 1.41.1 升级到 1.41.5 6613b08e @dependabot[bot]
  • build(deps):将 github.com/pelletier/go-toml/v2 从 2.2.4 升级到 2.3.0 582c26ef @dependabot[bot]
  • build(deps):将 github.com/tdewolff/minify/v2 从 2.24.11 升级到 2.24.12 a4f2a8a5 @dependabot[bot]

更新内容 (原始)

This release contains two security hardening fixes:

  • We now run the Node tools PostCSS, Babel and TailwindCSS, by default, with the --permission flag with the permissions defined in security.node.permissions. This means that you need Node >= 22 installed and that css.TailwindCSS now requires that the Tailwind CSS CLI must be installed as a Node.js package. The standalone executable is no longer supported
  • We have made the defaults in security.http.urls more restrictive.

But there are some notable new features, as well:

Nested vars support in css.Build and css.Sass

A practical example in css.Build would be to have something like this in hugo.toml:

[params.style]
    primary    = "#000000"
    background = "#ffffff"
    [params.style.dark]
        primary    = "#ffffff"
        background = "#000000"

And in the stylesheet:

@import "hugo:vars";
@import "hugo:vars/dark" (prefers-color-scheme: dark);

:root {
  color-scheme: light dark;
}

The permalinks configuration is now much more flexible (the old setup still works). It uses the same target matchers as in the cascade config, meaning you can now do:

permalinks:
  - target:
      kind: page
      path: "/books/**"
    pattern: /books/:year/:slug/
  - target:
      kind: section
      path: "/{books,books/**}"
    pattern: /libros/:sections[1:]
  - target:
      kind: page
    pattern: /other/:slug/

The above example isn’t great, but it at least shows the gist of it.

A more flexible scheme for identifiers in filenames

What we had before was e.g. content/mypost.en.md which told Hugo that the content files was in English. With the new setup you could also name the file content/mypost._language_en_.md. This alone doesn’t sound very useful, but this allows you to use more prefixes:

Prefix Description Relevant for
language_ Language Content and layout files.
role_ Role Content and layout files.
version_ Version Content and layout files.
outputformat_ Output format Layout files.
mediatype_ Media type Layout files.
kind_ Page kind Layout files.
layout_ Layout Layout files.

All Changes

  • langs/i18n: Fix translation lookup when using language variants 72b85d5f @jmooring #7982
  • create: Fix non-deterministic conflict detection in hugo new content 6436deb3 @jmooring #12602 #12786 #14112 #14769
  • commands: Fix environment isolation for configuration settings 1eea9fba @jmooring #14763
  • Fix filename dimension identifiers (role_X, version_X) to replace mount config 8d6145f3 @bep #14756
  • Fix it so we never auto-fallback to page resources in other roles/versions 97477242 @bep #14749 #14752
  • css: Support nested hugo:vars/ imports 7622dd86 @bep #14705
  • github: Update GitHub actions versions 0814059b @bep #14810
  • hugolib: Do not render aliases if the page is not rendered 8920d56e @jmooring #14807
  • langs/i18n: Improve default content language fallback 633cc772 @jmooring #14243
  • helpers: Remove unused code 4c40c6d5 @bep
  • common/constants: Remove unused consts d2594db6 @bep
  • common/paths: Remove unused code ab2de51e @bep
  • tests: Update Ruby setup action to v1.305.0 75f61832 @jmooring
  • langs: Use Language.Locale as primary localization key 1b7495bc @jmooring #9109
  • config/security: Add “! " negation to Whitelist, harden default http.urls 79f030be @bep #14792
  • Harden Node tool execution with –permission flag a54c398b @bep #7287
  • tpl/collections: Honor the Eqer interface in where comparisons f5fce935 @bep #14777
  • modules: Ignore non-require blocks in go.mod rewrite 4169c1f7 @bep #14783
  • Replace the concurrent map with an identical upstream version 7574e35b @bep
  • Add slice-based permalinks config with PageMatcher target 017a7cd6 @bep #14744
  • commands: Add missing import e3413d92 @bep
  • Revert “common/hugo: Deprecate extended and extended_withdeploy editions” b01cc147 @bep #14771
  • Adjust the SECURITY.md slightly 8ee19ff9 @bep
  • resources/page: Add passing test for Issue #14325 0d58e428 @jmooring
  • Add a more flexible filename identifier scheme that also allows setting roles and versions (#14754) ce2a156a @bep #14750
  • common/hugo: Deprecate extended and extended_withdeploy editions a17bdbc5 @jmooring #14696
  • parser/pageparser: Add a parser fuzz test 8f94d65c @bep
  • Replace deprecated .Site.Sites/.Page.Sites with hugo.Sites intests 90d8bf34 @bep
  • agents: Add a note about having the issue ID in test names bbb42b5a @bep
  • build(deps): bump github.com/getkin/kin-openapi from 0.135.0 to 0.137.0 d4ae662d @dependabot[bot]
  • build(deps): bump github.com/mattn/go-isatty from 0.0.21 to 0.0.22 9ede5fb9 @dependabot[bot]
  • build(deps): bump github.com/tdewolff/minify/v2 from 2.24.12 to 2.24.13 833a878e @dependabot[bot]
  • build(deps): bump github.com/magefile/mage from 1.17.1 to 1.17.2 4c03129f @dependabot[bot]
  • deps: Upgrade github.com/bep/imagemeta v0.17.1 => v0.17.2 080970bc @bep
  • build(deps): bump github.com/aws/aws-sdk-go-v2/service/cloudfront (#14789) 896bc89a @dependabot[bot]
  • build(deps): bump github.com/mattn/go-isatty from 0.0.20 to 0.0.21 (#14788) 100dde53 @dependabot[bot]
  • build(deps): bump github.com/bep/mclib (#14787) bdebb797 @dependabot[bot]
  • build(deps): bump google.golang.org/api from 0.267.0 to 0.276.0 52123ae2 @dependabot[bot]
  • build(deps): bump github.com/aws/aws-sdk-go-v2 from 1.41.5 to 1.41.6 38b8afdc @dependabot[bot]
  • build(deps): bump github.com/getkin/kin-openapi from 0.134.0 to 0.135.0 (#14781) 92766600 @dependabot[bot]
  • build(deps): bump github.com/bep/goportabletext from 0.1.0 to 0.2.0 (#14779) 790f4084 @dependabot[bot]
  • build(deps): bump golang.org/x/image from 0.38.0 to 0.39.0 (#14780) de6955ba @dependabot[bot]
  • deps: Upgrade github.com/bep/imagemeta v0.17.0 => v0.17.1 (#14775) a77bd527 @bep #14758
  • build(deps): bump golang.org/x/tools from 0.43.0 to 0.44.0 547ab29c @dependabot[bot]
  • build(deps): bump github.com/evanw/esbuild from 0.27.4 to 0.28.0 9a5c7e0d @dependabot[bot]
  • build(deps): bump github.com/aws/aws-sdk-go-v2 from 1.41.1 to 1.41.5 6613b08e @dependabot[bot]
  • build(deps): bump github.com/pelletier/go-toml/v2 from 2.2.4 to 2.3.0 582c26ef @dependabot[bot]
  • build(deps): bump github.com/tdewolff/minify/v2 from 2.24.11 to 2.24.12 a4f2a8a5 @dependabot[bot]

下载链接