Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
.PHONY: build check dev serve
.PHONY: browser build check dev serve

browser:
HUGO_MODULE_REPLACEMENTS='github.com/pgsty/oink -> $(abspath ../oink)' npm run test:browser

build:
hugo --cleanDestinationDir --minify
Expand Down
17 changes: 9 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,20 @@ For theme development, clone both repositories as siblings:
└── oink.pgsty.com/
```

The four Make targets separate published-theme checks from local-theme work:
The five Make targets separate published-theme checks from local-theme work:

```sh
make build # Build production output with the version pinned in go.mod
make check # Test the sibling theme with the non-browser regression suite
make dev # Start the fastest server with the sibling theme
make serve # Preview the pinned theme in the production environment
make build # Build production output with the version pinned in go.mod
make check # Test the sibling theme with the non-browser regression suite
make browser # Run the browser regression suite with the sibling theme
make dev # Start the fastest server with the sibling theme
make serve # Preview the pinned theme in the production environment
```

`build` and `serve` invoke Hugo directly and resolve the published version of
`github.com/pgsty/oink` pinned in `go.mod`. `dev` and `check` set a one-command
module replacement to `../oink`; they do not create a `go.work` file or modify
`go.mod`. `dev` keeps Hugo's fast-render defaults and renders to memory;
`github.com/pgsty/oink` pinned in `go.mod`. `dev`, `check`, and `browser` set a
one-command module replacement to `../oink`; they do not create a `go.work`
file or modify `go.mod`. `dev` keeps Hugo's fast-render defaults and renders to memory;
`serve` uses the production environment, minifies the output, performs full
renders after changes, and does not inject live reload. Node and npm are needed
for the regression tests, not to build the OINK theme or site.
Expand Down
4 changes: 2 additions & 2 deletions TRANSLATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@
| 合计 | 127 |

覆盖检查逐一核对首页以及 `docs/`、`blog/`、`book/`、`case/`、
`authors/` 与 `series/`。`content/search.md` 是由主题 i18n 驱动的特殊搜索页面,
不要求独立的 `.zh.md` 同伴。以下命令同时检查文件覆盖率、显式锚点、中英文渲染 ID 和站内链接:
`authors/` 与 `series/`。以下命令同时检查文件覆盖率、显式锚点、中英文渲染 ID
和站内链接:

```bash
make build
Expand Down
3 changes: 3 additions & 0 deletions content/blog/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ sidebar_root_link_self: true
footer_style: slim
comments: true
blog_index: cards
# The section root is a feed index, not a destination: backlinks belong on
# the posts it lists, so it opts out of the site-wide default.
backlinks: false
# The Book/Blog reading shells keep the title bar pinned: long-form reading
# should not make the navbar appear and disappear under the pointer.
navbar_autohide: false
Expand Down
3 changes: 3 additions & 0 deletions content/blog/_index.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ sidebar_root_link_self: true
footer_style: slim
comments: true
blog_index: cards
# 栏目根页是一份文章索引而不是落点:反向链接属于它列出的那些文章,所以这一页
# 退出站点级默认。
backlinks: false
# The Book/Blog reading shells keep the title bar pinned: long-form reading
# should not make the navbar appear and disappear under the pointer.
navbar_autohide: false
Expand Down
90 changes: 90 additions & 0 deletions content/blog/release/1.1.0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
---
title: OINK 1.1.0 — Native locales and taxonomy directories
linkTitle: OINK v1.1.0
date: 2026-09-03T18:00:00+08:00
lastmod: 2026-09-03T18:00:00+08:00
draft: true
description: >-
OINK 1.1.0 completes the native interface for every Docsy locale, turns
taxonomy roots into navigable directories, and carries the post-1.0
correctness and bounded-checker fixes without requiring a site migration.
authors: [oink]
categories: [release]
tags: [Oink, Release]
series: [oink-releases]
series_weight: 31
release_url: https://github.com/pgsty/oink/releases/tag/v1.1.0
---

> [!IMPORTANT] Release candidate
> The source changes are merged on `main`, but the `v1.1.0` tag, Go Proxy
> module, documentation-site pin, deployment, and live verification are still
> pending. This note remains a draft until those states are complete.

OINK 1.1.0 is the first minor release after the stable 1.0 contract. It adds a
complete native interface for every locale OINK inherits from Docsy and gives
taxonomy roots a real directory surface. It also includes the correctness fixes
prepared after the 1.0 review. No component, configuration, or content migration
is required.

## At a glance {#at-a-glance}

- All 31 Docsy locale catalogs plus generic `zh` now carry the same 194 OINK
messages without generated English fallback. Page counts use Hugo's CLDR
plural selection, including the Arabic, Polish, Romanian, Russian, Serbian,
and Ukrainian forms that cannot be expressed as a simple singular/plural
pair.
- `/tags/`, `/categories/`, `/authors/`, and `/series/` are now directories of
compact term cards instead of a filter-chip row. Taxonomy and term pages share
a localized head, and their right rail starts with a switcher between the
taxonomies declared by the site. Term pages remain row-list archives.
- Cached sidebars preserve page and cascade settings, remain navigable without
JavaScript, and hydrate their active path without a transient contrast drop.
- Dedicated Print output contains no shell navbar, and one per-page coordinator
keeps plain Print and overlapping Book aggregates from racing on Page Store.
- Invalid `book-toc drafts` and Landing `preview.source` inputs now follow the
existing warn-and-fallback or warn-and-omit contract in ordinary previews.
- Redoc static paths behave the same with or without a leading slash under root
and subpath deployments.
- The obsolete ScrollSpy patch no longer ships. Its 1.x configuration key stays
accepted as a quiet compatibility no-op because the normal outline runtime
already tracks the active heading.
- Output checkers build fresh input by default, every checker-owned Hugo process
has a 120-second ceiling, and redundant warning-fatal canaries were removed
without dropping per-case diagnostic and safe-output checks.

## Compatibility {#compatibility}

OINK 1.1.0 keeps the released 1.0 authoring and configuration surface. Existing
sites need no source migration; taxonomy roots change presentation only. The
only retired runtime was unreachable or duplicated existing behavior;
compatibility partials, all three supported search providers, explicit locale
fallbacks, and the migration tools remain in place. Hugo Extended 0.160.1 stays
the floor; on 0.160.x, a non-default generic `zh` alongside `zh-cn` and `zh-tw`
uses `locale: zh-CN`.

## Verification {#verification}

The candidate passed the complete ordered theme suite, the strict synthetic
fixture, 85 migration tests, 41 browser-runtime tests, Book publication checks,
and the real bilingual documentation site. The browser gate covered
accessibility, responsive navigation, keyboard control, content components,
code blocks, Landing, and section theme colors.

The checker trace fell from 735 Hugo starts with 305 warning-fatal builds to 614
and 184 respectively. All 613 checker-owned starts are now bounded; the one
remaining unwrapped build is the CI-owned top-level fixture command.

## Upgrade after publication {#upgrade}

After the public tag and module proxy are verified:

```bash
hugo mod get github.com/pgsty/oink@v1.1.0
hugo mod tidy
hugo --cleanDestinationDir --gc --minify --environment production \
--printPathWarnings --panicOnWarning
```

Pinning the module, passing a local build, deployment, and live rendering remain
separate completion states.
74 changes: 74 additions & 0 deletions content/blog/release/1.1.0.zh.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
---
title: OINK 1.1.0:原生多语言界面与分类法目录
linkTitle: OINK v1.1.0
date: 2026-09-03T18:00:00+08:00
lastmod: 2026-09-03T18:00:00+08:00
draft: true
description: >-
OINK 1.1.0 补齐全部 Docsy locale 的原生界面,将分类法根页改造成可导航的目录,
并纳入 1.0 之后的正确性修复与有界 checker,现有站点无需迁移。
authors: [oink]
categories: [release]
tags: [Oink, Release]
series: [oink-releases]
series_weight: 31
release_url: https://github.com/pgsty/oink/releases/tag/v1.1.0
---

> [!IMPORTANT] 发布候选
> 源码修改已经合入 `main`,但 `v1.1.0` 标签、Go Proxy 模块、文档站版本固定、
> 部署与线上核验仍未完成。在这些状态闭环前,本说明保持草稿。

OINK 1.1.0 是稳定 1.0 契约之后的第一个次版本:它为 OINK 从 Docsy 继承的全部
locale 补齐原生界面,也让分类法根页拥有真正的目录表面,同时纳入 1.0 评审后准备的
正确性修复。组件、配置与内容均无需迁移。

## 概览 {#at-a-glance}

- Docsy 的 31 份 locale catalog 加上通用 `zh`,现在都拥有相同的 194 条 OINK
消息,不再生成英文回退。页面计数交给 Hugo 按 CLDR 复数类别选择,正确覆盖无法用
简单单复数二分表达的阿拉伯语、波兰语、罗马尼亚语、俄语、塞尔维亚语与乌克兰语。
- `/tags/`、`/categories/`、`/authors/` 与 `/series/` 从筛选芯片行变成紧凑的
术语卡片目录。分类法页与术语页共用本地化页头,右栏先提供站点已声明分类法之间的
切换器;具体术语页继续使用行列表归档。
- 缓存侧栏保留页面与 cascade 设置;没有 JavaScript 时仍可导航,恢复 active 路径时
也不会短暂跌破对比度门槛。
- 专用 Print 输出不再包含外壳 navbar;每页一个 coordinator,避免普通 Print 与
重叠 Book 聚合在 Page Store 上竞态。
- 非法 `book-toc drafts` 与 Landing `preview.source` 输入在普通预览中遵循既有的
「告警并回退」或「告警并省略」契约。
- Redoc 的 static 路径在根路径与子路径部署下,无论开头是否带 `/` 都得到相同结果。
- 不再下发无效 ScrollSpy 补丁。其 1.x 配置键继续作为静默兼容 no-op 接受,因为
普通大纲运行时已经跟踪当前标题。
- 输出 checker 默认构建新鲜输入;checker 启动的每个 Hugo 进程都有 120 秒上限;
重复的 warning-fatal canary 被收缩,但逐例诊断与安全输出检查全部保留。

## 兼容性 {#compatibility}

OINK 1.1.0 保持已经发布的 1.0 创作与配置表面,现有站点不需要迁移源码;分类法根页
只改变呈现。唯一退役的运行时本来不可达或重复既有行为;兼容 partial、三种受支持
搜索后端、显式 locale fallback 与迁移工具均继续保留。Hugo Extended 0.160.1 仍是
下限;在 0.160.x 上同时配置非默认通用 `zh`、`zh-cn` 与 `zh-tw` 时,通用语言需使用
`locale: zh-CN`。

## 验证 {#verification}

候选版本通过完整有序主题套件、严格合成 fixture、85 个迁移测试、41 个浏览器运行时
测试、Book 出版检查,以及真实双语文档站。浏览器门禁覆盖无障碍、响应式导航、键盘
控制、内容组件、代码块、Landing 与分区主题色。

checker trace 从 735 次 Hugo 启动、其中 305 次 warning-fatal,降到 614 与 184。
613 次 checker 自有启动现在全部有界;唯一未包装的是 CI 自己直接执行的顶层 fixture。

## 发布后升级 {#upgrade}

公开标签与模块代理核验通过后执行:

```bash
hugo mod get github.com/pgsty/oink@v1.1.0
hugo mod tidy
hugo --cleanDestinationDir --gc --minify --environment production \
--printPathWarnings --panicOnWarning
```

模块固定、本地构建、部署与线上渲染仍是彼此独立的完成状态。
3 changes: 3 additions & 0 deletions content/docs/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ icon: fa-solid fa-book
sidebar_expanded: true
sidebar_root_for: self
sidebar_root_link_self: true
# The section root is a table of contents, not a destination: backlinks
# belong on the pages it leads to, so it opts out of the site-wide default.
backlinks: false
# Docs pins the title bar: a reference tree is read by jumping between pages,
# so the global menu has to stay where the pointer left it.
navbar_autohide: false
Expand Down
3 changes: 3 additions & 0 deletions content/docs/_index.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ icon: fa-solid fa-book
sidebar_expanded: true
sidebar_root_for: self
sidebar_root_link_self: true
# 栏目根页是一份目录而不是落点:反向链接属于它指向的那些页面,所以这一页
# 退出站点级默认。
backlinks: false
# 文档区固定顶栏:参考树是靠页面间跳转来读的,全局菜单必须停在指针离开时的位置。
navbar_autohide: false
# 分区身份:文档保持品牌蓝,但显式写出而不是隐式继承 —— 这样侧栏根切换器里
Expand Down
8 changes: 4 additions & 4 deletions content/docs/customize/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ precedence first:
3. Site `params`.

**Drop the `ui.` prefix when writing it in front matter.** The site's
`params.ui.scroll_spy` is simply `scroll_spy` on a page. A `ui:` block in front
`params.ui.reading_time` is simply `reading_time` on a page. A `ui:` block in front
matter is read by nobody and reported by nobody, so a setting that seems to have
no effect is worth checking against
[Page parameters](/docs/write/frontmatter/) first.
Expand All @@ -82,7 +82,7 @@ title: Wide reference
page_width: wide
navbar_enabled: false
footer_style: slim
scroll_spy: true
reading_time: false
---
```

Expand Down Expand Up @@ -238,7 +238,7 @@ than from a parameter — see
| `params.ui.sidebar_menu_compact` | boolean | true | Expands only the current branch and its neighbours |
| `params.ui.sidebar_menu_foldable` | boolean | true | Lets the reader expand and collapse sections |
| `params.ui.sidebar_menu_truncate` | integer | 2000 | Maximum entries rendered in one section; the rest are truncated |
| `params.ui.sidebar_cache_limit` | integer | 500 | Above this page count the site reuses shared navigation markup, and the browser restores the active state |
| `params.ui.sidebar_cache_limit` | integer | 500 | At this page count, reuse visible neutral navigation markup for matching language/root/effective settings; the browser adds active state |
| `params.ui.sidebar_width_min` | integer | 220 | Lower bound in pixels for drag-resizing on the desktop |
| `params.ui.sidebar_width_max` | integer | 480 | Upper bound in pixels for drag-resizing |
| `params.ui.sidebar_item_overflow` | enum | ellipsis | `ellipsis` truncates a long title, `wrap` wraps it |
Expand All @@ -263,7 +263,7 @@ the tracking behaviour:
| --- | --- | --- | --- |
| `markup.tableOfContents.startLevel` | integer | 2 | Hugo's own: the highest heading level collected |
| `markup.tableOfContents.endLevel` | integer | 3 | Hugo's own: the lowest heading level collected |
| `params.ui.scroll_spy` | boolean | false | Scroll position tracking; `true` highlights the active entry |
| `params.ui.scroll_spy` | boolean | false | Quiet 1.x compatibility no-op; the normal shell runtime always tracks the active outline heading and this key emits no asset |
{.fields meta="type default"}

Hide the outline on one page with the front matter `notoc: true` — see
Expand Down
8 changes: 4 additions & 4 deletions content/docs/customize/config.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ Hugo 的 `.Param` 查找让大部分参数可以逐页覆盖,优先级从高
3. 站点 `params`。

**写进 front matter 时要去掉 `ui.` 前缀。**
站点上的 `params.ui.scroll_spy` 在页面里就写成 `scroll_spy`。front matter 里出现 `ui:`
站点上的 `params.ui.reading_time` 在页面里就写成 `reading_time`。front matter 里出现 `ui:`
块的话,里面的键没有人读,也没有人报错——某个设置看着没生效时,先对照[页面参数](/zh/docs/write/frontmatter/)核一遍键名。

```yaml {title="content/docs/wide-reference.md"}
Expand All @@ -72,7 +72,7 @@ title: 宽版参考
page_width: wide
navbar_enabled: false
footer_style: slim
scroll_spy: true
reading_time: false
---
```

Expand Down Expand Up @@ -211,7 +211,7 @@ favicon 没有参数:主题按约定名扫描 `static/`(`favicon.ico` `favic
| `params.ui.sidebar_menu_compact` | boolean | true | 只展开当前分支与邻近条目 |
| `params.ui.sidebar_menu_foldable` | boolean | true | 允许读者展开/折叠分区 |
| `params.ui.sidebar_menu_truncate` | integer | 2000 | 一个分区最多渲染的条目数,超出截断 |
| `params.ui.sidebar_cache_limit` | integer | 500 | 站点页数超过它就复用共享导航标记,active 状态改由浏览器还原 |
| `params.ui.sidebar_cache_limit` | integer | 500 | 页数达到此值后,按语言、导航根与有效设置复用可见的中性导航标记;浏览器补 active 状态 |
| `params.ui.sidebar_width_min` | integer | 220 | 桌面端拖拽调宽的下限,像素 |
| `params.ui.sidebar_width_max` | integer | 480 | 拖拽调宽的上限,像素 |
| `params.ui.sidebar_item_overflow` | enum | ellipsis | `ellipsis` 长标题省略,`wrap` 换行 |
Expand All @@ -232,7 +232,7 @@ favicon 没有参数:主题按约定名扫描 `static/`(`favicon.ico` `favic
| --- | --- | --- | --- |
| `markup.tableOfContents.startLevel` | integer | 2 | Hugo 原生:收录的最高标题级别 |
| `markup.tableOfContents.endLevel` | integer | 3 | Hugo 原生:收录的最低标题级别 |
| `params.ui.scroll_spy` | boolean | false | 滚动位置跟踪;设为 `true` 打开活动项高亮 |
| `params.ui.scroll_spy` | boolean | false | 1.x 静默兼容 no-op;普通外壳运行时始终跟踪当前大纲标题,此键不加载资源 |
{.fields meta="type default"}

单页隐藏大纲用 front matter `notoc: true`,见[页面参数](/zh/docs/write/frontmatter/)。
Expand Down
27 changes: 15 additions & 12 deletions content/docs/customize/layout.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,12 @@ params:
- `sidebar_width_min` / `sidebar_width_max` bound drag-resizing on the desktop, in pixels. The reader's adjusted width is kept locally, and double-clicking the divider restores the default.
- `sidebar_item_overflow` defaults to `ellipsis` (long titles truncate); a site with many long titles can use `wrap`.

At `sidebar_cache_limit`, pages with the same effective settings may share a
neutral rendered tree. It remains visible and navigable without JavaScript;
the shell runtime only adds the current path and opens its ancestors. Page or
cascade overrides select the matching cached variant. A Book page with
`sidebar_headings` enabled keeps its page-specific tree instead.

Fold state, width and scroll position are stored locally per language. Below
`md` the sidebar becomes a drawer with a backdrop.

Expand Down Expand Up @@ -270,19 +276,16 @@ markup:
ordered: false
```

The theme governs only the tracking behaviour:

```yaml {title="hugo.yml"}
params:
ui:
scroll_spy: false
```
The normal shell runtime always tracks the active heading. It draws a continuous
rail, highlights the current section, and marks the position without a separate
switch. The reader can collapse the right column entirely, and that state is
kept locally. Below `xl` the right column is hidden and its content moves into
the sidebar drawer.

Scroll tracking is **off** by default. Set to `true`, the outline draws a
continuous rail, highlights the current section and marks the position. The
reader can collapse the right column entirely, and that state is kept locally.
Below `xl` the right column is hidden and its content moves into the sidebar
drawer.
The old `params.ui.scroll_spy` site key and `scroll_spy` page key remain accepted
as quiet compatibility no-ops throughout 1.x. Either boolean value produces the
same outline and loads no extra runtime; removing the keys is reserved for a
future breaking release.

To hide the outline on one page, use the front matter `notoc: true`.

Expand Down
Loading