Skip to content

Stabilize localized heading anchors at build time#342

Open
mlonsk wants to merge 5 commits into
mainfrom
normalize-localized-heading-anchors
Open

Stabilize localized heading anchors at build time#342
mlonsk wants to merge 5 commits into
mainfrom
normalize-localized-heading-anchors

Conversation

@mlonsk

@mlonsk mlonsk commented Jun 22, 2026

Copy link
Copy Markdown
Collaborator

DocFX derives a heading's anchor from its text, but cross-references hardcode the English anchor (xref:uid#bookmark, #anchor, <a href="…#anchor">). When a heading is translated the slug drifts (Object pathsobject-paths becomes Rutas de objetorutas-de-objeto), so every English anchor link breaks in es/zh and DocFX emits InvalidBookmark warnings. English builds stay clean because the anchors match there — so this only ever surfaces on translated pages, and recurs on any new page that links to a sub-heading.

This adds build_scripts/normalize-localized-heading-anchors.py, a pre-build normalizer (same pattern as the existing alert normalizer) that injects a hidden bookmark anchor carrying the English slug before each translated heading:

<a id="model-io" data-loc-xref></a>
## 模型 I/O

The English #anchor now resolves and lands on the right section, while the heading keeps its translated text. It:

  • aligns to the English source positionally and skips files whose heading count differs (rather than risk a misaligned anchor),
  • is idempotent (data-loc-xref marker — strips and regenerates),
  • skips frontmatter, fenced code blocks, and toc.md,
  • handles BOM and CRLF, and never touches en.

Wired into build-docs.py right after the alert normalizer.

DocFX derives heading anchors from heading text, but cross-references hardcode
the English anchor (xref:uid#bookmark, #anchor, <a href="...#anchor">). When a
heading is translated the slug drifts, so every English anchor link breaks in
es/zh and DocFX emits InvalidBookmark warnings (English builds stay clean).

build_scripts/normalize-localized-heading-anchors.py injects a hidden bookmark
anchor carrying the English slug before each translated heading, so the English
anchor resolves and the link lands on the right section while the heading keeps
its translated text. It aligns to the English source positionally, is idempotent
(data-loc-xref marker), skips frontmatter/code fences/toc.md, and skips files
whose heading count differs from the source rather than risk a misaligned anchor.
Wired into build-docs.py right after the alert normalizer.

Reduces InvalidBookmark warnings 72 -> 5 (en 0, es 32->2, zh 40->3); the
residuals are a stale translation (preferences.md) and 3 malformed link hrefs.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

Azure Static Web Apps: Your stage site is ready! Visit it here: https://delightful-mud-081affe03-342.westeurope.azurestaticapps.net

1 similar comment
@github-actions

Copy link
Copy Markdown

Azure Static Web Apps: Your stage site is ready! Visit it here: https://delightful-mud-081affe03-342.westeurope.azurestaticapps.net

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new pre-build normalization step to keep DocFX heading anchors stable across localized (translated) Markdown pages by injecting hidden bookmark anchors using the English slug, preventing InvalidBookmark warnings and broken #anchor links in non-English builds.

Changes:

  • Wire a new normalizer into the localized build pipeline right after the existing alert normalizer.
  • Add normalize-localized-heading-anchors.py to compute English heading slugs and inject <a id="..."> bookmarks before corresponding translated headings.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

File Description
build-docs.py Runs the new localized heading-anchor normalizer after the localized alert normalizer.
build_scripts/normalize-localized-heading-anchors.py Implements the heading alignment, English-slug generation, and bookmark injection logic for localized Markdown files.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread build_scripts/normalize-localized-heading-anchors.py Outdated
Comment thread build_scripts/normalize-localized-heading-anchors.py Outdated
Comment thread build_scripts/normalize-localized-heading-anchors.py
Comment thread build_scripts/normalize-localized-heading-anchors.py Outdated
mlonsk and others added 4 commits June 22, 2026 20:32
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@github-actions

Copy link
Copy Markdown

Azure Static Web Apps: Your stage site is ready! Visit it here: https://delightful-mud-081affe03-342.westeurope.azurestaticapps.net

1 similar comment
@github-actions

Copy link
Copy Markdown

Azure Static Web Apps: Your stage site is ready! Visit it here: https://delightful-mud-081affe03-342.westeurope.azurestaticapps.net

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants