Skip to content

[Bug/Architecture] Build-time plugin state pollution in changelog generator and client-side figure caption race condition #699

Description

@bhuvan-somisetty

Page URL:

  • Build pipeline: npm run build / changelog/source/
  • Client module: /docs, /zh/docs, /docs/*, /zh/docs/*, and /blog/*

What happened:

While auditing the website build pipeline and client-side runtime modules, we identified two systemic defects affecting site build consistency, internationalization (i18n) accuracy, and figure rendering:

  1. Global state leak in changelog-plugin: Module-level variables in the changelog plugin (publishTimes and authorsMap in src/plugins/changelog/index.js) persist across locale build passes within the same Node process during npm run build. On multi-locale builds, publishTimes.has(...) evaluates to true for every entry during the zh pass, causing the while loop to decrement hour (201918...). This causes release dates, changelog post order, and RSS/Atom feed timestamps for Chinese to drift and desynchronize from English.
  2. Client-side race condition, locale desync, and broken anchor links in imageFigureNumber.js: onRouteDidUpdate uses triple setTimeout timers (100ms, 500ms, 1000ms) and reads document.documentElement.lang. During SPA navigation between /docs/ and /zh/docs/, lang is updated by Docusaurus after route transition. Early timeout calls read stale lang attributes, outputting English captions on Chinese pages or vice versa. Additionally, root doc paths (/docs or /zh/docs) were missed by strict /\/docs\// regex, and wrapping unlinked images detached <img> from parent <a> tags.

What you expected:

  1. changelog-plugin state (publishTimes, authorsMap) is scoped to loadContent() / plugin instance execution so multi-locale builds produce identical, deterministic timestamps and clean author maps across all locales.
  2. imageFigureNumber.js determines locale deterministically from location pathname (e.g. /zh/ prefix), covers root doc routes, preserves anchor wrappers around images, and uses clean idempotency guards to prevent duplicate captions.

Browser and locale:

  • Node.js build environment (Node 20+)
  • All browsers (Chrome, Firefox, Safari) across en and zh locales

Systemic Defects & Technical Details

1. Module-level global state in changelog-plugin

  • Location: src/plugins/changelog/index.js
    const publishTimes = new Set();
    const authorsMap = {};
    During production builds (npm run build), Docusaurus runs loadContent() sequentially for en and zh within the same process. Because publishTimes is not cleared between locale passes, zh detects en timestamps as collisions and shifts Chinese changelog timestamps backward.

2. Client-side DOM race condition and link detachment in imageFigureNumber.js

  • Location: src/client/imageFigureNumber.js
    setTimeout polling reads mutable document.documentElement.lang which lags behind SPA route transitions, missed root routes like /docs, and detached images from anchor wrappers.

Acceptance Criteria

  • changelog-plugin state is scoped per plugin instance / loadContent() call.
  • imageFigureNumber.js derives locale from pathname, covers root doc paths, preserves anchor tags around linked images, and enforces idempotent DOM updates.
  • npm run check:all passes cleanly.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions