Skip to content

refactor: highlight flow stability#134

Open
AVGVSTVS96 wants to merge 16 commits intomainfrom
refactor/highlight-flow-stability
Open

refactor: highlight flow stability#134
AVGVSTVS96 wants to merge 16 commits intomainfrom
refactor/highlight-flow-stability

Conversation

@AVGVSTVS96
Copy link
Copy Markdown
Owner

@AVGVSTVS96 AVGVSTVS96 commented Mar 19, 2026

Async robustness improvements

  • Add request ID tracking to prevent stale highlight results from overriding newer ones
  • Preserve last valid highlight when language becomes invalid instead of clearing
  • Fix throttle timing to base next allowed time on execution time rather than scheduling time

Architecture refactoring

  • Extract highlight logic into separate highlight.ts module with getEmbeddedLanguages and resolveHighlight functions
  • Replace ThemeResult with discriminated union ResolvedTheme for better type safety
  • Move DEFAULT_THEMES to theme module and handle invalid multi-theme configs with console warnings
  • Simplify buildShikiOptions to accept resolved theme and use positional parameters
  • Tighten HighlightedCode type from ReactNode to ReactElement | string | null

Biome configuration updates

  • Enable noUnusedImports and noUnusedVariables as errors
  • Add naming convention for object literal properties allowing Fragment or any pattern
  • Update file includes to exclude package/dist and remove wildcards from exclusions
  • Add overrides to enforce noExplicitAny as error in package/src/** and disable in package/tests/**

Plugin improvements

  • Enhance rehypeInlineCodeProperty with proper type checking for parent elements

Test enhancements

  • Add comprehensive async robustness tests for stale request handling
  • Add throttling timing verification tests
  • Improve test reliability with proper timeout handling

AVGVSTVS96 and others added 13 commits March 5, 2026 20:28
- theme.ts: replace ThemeResult with discriminated union ResolvedTheme,
  remove dead themeId field, move DEFAULT_THEMES here, handle invalid
  configs with console.warn instead of sentinel nulls
- options.ts: accept ShikiInputOptions instead of full HighlighterOptions,
  remove OMIT_KEYS/underscore destructuring, use positional params
- highlight.ts: remove dead ResolvedHighlight type, move HighlighterFactory
  to types.ts, type shikiOptions as CodeToHastOptions
- types.ts: add HighlighterFactory, ShikiInputOptions, tighten
  HighlightedCode from ReactNode to ReactElement
- hook.ts: destructure hook-only keys before passing to buildShikiOptions,
  remove type cast on return

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Mar 19, 2026

🦋 Changeset detected

Latest commit: 6adef49

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
react-shiki Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel
Copy link
Copy Markdown

vercel bot commented Mar 19, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
react-shiki Ready Ready Preview, Comment Apr 10, 2026 3:29am
react-shiki-docs Error Error Apr 10, 2026 3:29am

Copy link
Copy Markdown
Owner Author

AVGVSTVS96 commented Mar 19, 2026

@claude
Copy link
Copy Markdown

claude bot commented Mar 19, 2026

Claude finished @AVGVSTVS96's task —— View job


Code Review Complete ✅

This is an excellent refactoring that significantly improves code quality, robustness, and maintainability. The changes demonstrate thoughtful architecture decisions and solid engineering practices.

Review Summary

Strengths

  • Outstanding async robustness: Request ID tracking prevents stale results - a common React issue solved elegantly
  • Clean architecture: Proper separation of concerns with extracted highlight.ts module
  • Type safety improvements: Discriminated union ResolvedTheme and tightened HighlightedCode type
  • Excellent test coverage: Comprehensive async behavior tests including stale request handling
  • Performance optimization: Corrected throttling logic bases timing on execution rather than scheduling
  • Error handling: Proper console warnings for invalid themes, graceful fallbacks

Code Quality Assessment

Architecture & Design ⭐⭐⭐⭐⭐

  • Excellent modular design with single-responsibility functions
  • highlight.ts extraction creates clean boundaries between concerns
  • Proper abstraction layers with factory pattern usage
  • Good separation between core logic and React-specific hooks

Type Safety ⭐⭐⭐⭐⭐

  • ResolvedTheme discriminated union prevents invalid state combinations
  • HighlightedCode type properly constrained from overly broad ReactNode
  • Excellent type checking in isTextmateTheme function (theme.ts:13-17)
  • Good use of TypeScript's type system throughout

Async Handling ⭐⭐⭐⭐⭐

  • Request ID pattern (hook.ts:92,100,112) is the gold standard for preventing stale async results
  • Proper cleanup in useEffect return function prevents memory leaks
  • Language validation preserves last valid highlight instead of clearing - excellent UX decision

Performance ⭐⭐⭐⭐⭐

  • Throttling fix (utils.ts:44) bases timing on actual execution - critical performance improvement
  • useStableValue prevents unnecessary re-renders with deep equality checks
  • Proper memoization strategies throughout

Error Handling & Resilience ⭐⭐⭐⭐⭐

  • Graceful fallbacks for invalid theme configurations (theme.ts:39-47)
  • Console warnings for debugging without breaking functionality
  • Fallback to plaintext for unrecognized languages (language.ts:65)

Specific Technical Improvements

  1. Request Racing Protection (hook.ts:100,112)

    const requestId = ++requestIdRef.current;
    // ...
    if (requestId === requestIdRef.current) {
      setHighlightedCode(result);
    }

    This prevents a classic React async race condition. Excellent implementation.

  2. Throttling Fix (utils.ts:44)

    timeoutControl.current.nextAllowedTime = Date.now() + throttleMs;

    Now correctly bases timing on execution completion rather than scheduling time.

  3. Type Safety Enhancement (theme.ts:9-11)

    export type ResolvedTheme =
      | { isMulti: true; themes: Themes; themesToLoad: Theme[] }
      | { isMulti: false; theme: Theme; themesToLoad: Theme[] };

    Discriminated union eliminates invalid state combinations.

  4. Plugin Type Safety (plugins.ts:17,20)
    Proper parent type checking prevents runtime errors.

Test Coverage Analysis ⭐⭐⭐⭐⭐

Comprehensive test additions demonstrate strong testing discipline:

  • Stale request handling: Tests prove async robustness (hook.test.tsx:251-327)
  • Language preservation: Verifies UX improvement when language becomes invalid (hook.test.tsx:329+)
  • Throttling verification: Tests timing behavior correctly (utils.test.tsx:119-142)

Documentation & Changeset ✅

  • Changeset included: Proper semantic versioning with clear description
  • No API surface changes: Internal refactoring preserves public interface
  • Code comments: Functions well-documented with usage examples
  • No documentation updates needed: Internal changes don't affect public API

Biome Configuration ✅

Excellent linting improvements:

  • noUnusedImports and noUnusedVariables as errors improve code cleanliness
  • Proper noExplicitAny enforcement in source with test exemptions
  • Smart naming convention rules accommodate React patterns

Security & Performance Assessment ✅

  • No security concerns: Proper HTML sanitization handling, no dynamic code execution
  • Performance optimized: Throttling improvements, stable value checking
  • Memory leak prevention: Proper cleanup in effects and timeout management

Minor Suggestions

  1. Consider adding JSDoc to new highlight.ts exports for better IDE experience
  2. The isTextmateTheme function could benefit from more comprehensive validation

Verdict

This is exemplary refactoring work. The code demonstrates:

  • Deep understanding of React async patterns
  • Excellent architectural thinking
  • Comprehensive testing approach
  • Attention to performance and UX details

Strongly recommend approval 🚀


@AVGVSTVS96 AVGVSTVS96 marked this pull request as ready for review March 19, 2026 03:34
@AVGVSTVS96 AVGVSTVS96 changed the title fix: prevent stale highlight updates and correct throttle timing refactor: highlight flow stability Mar 19, 2026
@AVGVSTVS96 AVGVSTVS96 force-pushed the refactor/highlight-flow-stability branch from 7ad3821 to 8c412b5 Compare April 9, 2026 00:04
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.

1 participant