Files
Anthony Lio 6d08a747f1 fix(docs): guide reference perf enhancements (#50239)
## What kind of change does this PR introduce?

follow-up to #50235 to reduce reference page payloads and cold rendering
overhead

## What is the current behavior?

reference pages ship a large rsc payload inside the html _ most of it is
duplication rather than content along with shiki that writes ~30
character css variable name for every syntax token making the page heavy
in some cases

## What is the new behavior?

- moves repeated styles into shared css and uses compact, namespaced
token classes
- renders details icons inside the client trigger
- follows shiki’s guidance to [reuse one
highlighter](https://shiki.style/guide/best-performance#cache-the-highlighter-instance)
and [load languages on
demand](https://shiki.style/guide/best-performance#use-shorthands)

`page size`
page | before | after | change
-- | -- | -- | --
javascript | 10.61 mb | 8.28 mb | -21.9%
dart | 4.59 mb | 4.13 mb | -10.1%
python | 4.38 mb | 3.73 mb | -14.9%
swift | 2.87 mb | 2.56 mb | -10.9%
server | 1.59 mb | 1.35 mb | -15.2%
kotlin | 3.42 mb | 3.17 mb | -7.2%

`cold initialization`
language | before | after | reduction
-- | -- | -- | --
bash | 2,180 ms | 23 ms | 98.95%
javascript | 2,245 ms | 38 ms | 98.29%

## Additional context

measured on a local production build which uses the checked in generated
content _ production has larger sdk data, so absolute sizes there will
be higher

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added reusable expand/collapse controls for API reference details,
with updated icons, labels, and styling.
* Improved code block rendering with class-based syntax highlighting,
wrapped-code support, responsive layouts, and lazy language loading.

* **Style**
* Added theme-aware syntax-token colors, line-number styling, and
configurable code-block shadows.
  * Consolidated expandable reference panel and item styling.

* **Tests**
* Added coverage for syntax highlighting, code block rendering, language
support, token stability, and reference details.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-15 23:55:49 +03:00

67 lines
1.9 KiB
TypeScript

// As defined in @shikijs/core/dist/chunk-tokens.d.mts
enum FontStyle {
NotSet = -1,
None = 0,
Italic = 1,
Bold = 2,
Underline = 4,
}
// Fence aliases a screen reader would otherwise read letter by letter
const LANGUAGE_LABELS: Record<string, string> = {
c: 'C',
html: 'HTML',
js: 'JavaScript',
json: 'JSON',
jsx: 'JavaScript',
py: 'Python',
sh: 'Shell',
shell: 'Shell',
sql: 'SQL',
toml: 'TOML',
ts: 'TypeScript',
tsx: 'TypeScript',
yaml: 'YAML',
}
export function getCodeBlockLabel(lang: string | null, lineCount: number): string {
const lines = `${lineCount} ${lineCount === 1 ? 'line' : 'lines'}`
if (!lang) return lines
return `${LANGUAGE_LABELS[lang] ?? lang}, ${lines}`
}
/*
* Shiki gives every token a ~30 char css variable name making page heavier
* this sends a one letter code instead for perf optimization
*
* nb. color missing from this table still renders but full length
*/
const COLOR_CLASSES: Record<string, string> = {
'var(--code-foreground)': 's-f',
'var(--code-token-comment)': 's-c',
'var(--code-token-constant)': 's-n',
'var(--code-token-function)': 's-u',
'var(--code-token-keyword)': 's-k',
'var(--code-token-parameter)': 's-a',
'var(--code-token-property)': 's-r',
'var(--code-token-punctuation)': 's-p',
'var(--code-token-string)': 's-s',
'var(--code-token-string-expression)': 's-e',
'var(--code-token-variable)': 's-v',
}
export const getTokenClassName = (
color: string | undefined,
fontStyle: number | undefined
): string | undefined => {
const classes: Array<string> = []
const colorClass = color === undefined ? undefined : COLOR_CLASSES[color]
if (colorClass) classes.push(colorClass)
if (fontStyle && fontStyle > 0) {
if (fontStyle & FontStyle.Italic) classes.push('s-i')
if (fontStyle & FontStyle.Bold) classes.push('s-b')
if (fontStyle & FontStyle.Underline) classes.push('s-l')
}
return classes.length ? classes.join(' ') : undefined
}