react-shiki 0.11.1 → 0.11.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugins-C0Uf67_P.mjs","names":["componentCss","featuresCss"],"sources":["../src/lib/utils.ts","../src/styles/component.css?inline","../src/styles/features.css?inline","../src/lib/styles.ts","../src/lib/language.ts","../src/lib/theme.ts","../src/lib/engine.ts","../src/lib/transformers.ts","../src/lib/options.ts","../src/lib/hook.ts","../src/lib/component.tsx","../src/lib/plugins.ts"],"sourcesContent":["import { useRef } from 'react';\nimport { dequal } from 'dequal';\n\nimport type { TimeoutState } from './types';\n\n/**\n * Returns a referentially stable version of `value` that only updates when content changes.\n * Uses reference equality as a fast path and deep comparison to prevent unnecessary updates.\n */\nexport const useStableValue = <T>(value: T): T => {\n const ref = useRef(value);\n\n if (value !== ref.current && !dequal(value, ref.current)) {\n ref.current = value;\n }\n\n return ref.current;\n};\n\n/**\n * Optionally throttles rapid sequential highlighting operations\n *\n * @example\n * const timeoutControl = useRef<TimeoutState>({\n * nextAllowedTime: 0,\n * timeoutId: undefined\n * });\n *\n * throttleHighlighting(highlightCode, timeoutControl, 1000);\n */\nexport const throttleHighlighting = (\n performHighlight: () => Promise<void>,\n timeoutControl: { current: TimeoutState },\n throttleMs: number\n) => {\n clearTimeout(timeoutControl.current.timeoutId);\n\n const delay = Math.max(\n 0,\n timeoutControl.current.nextAllowedTime - Date.now()\n );\n\n timeoutControl.current.timeoutId = setTimeout(() => {\n void performHighlight();\n timeoutControl.current.nextAllowedTime = Date.now() + throttleMs;\n }, delay);\n};\n","/* Unlayered :where() defaults: immune to layered resets, overridden by any user rule. */\n:where(.rs-root) {\n position: relative;\n}\n\n:where(.rs-root.rs-default-styles pre) {\n overflow: auto;\n border-radius: 0.5rem;\n padding-inline: 1.5rem;\n padding-block: 1.25rem;\n}\n\n:where(.rs-root .rs-language-label) {\n position: absolute;\n z-index: 1;\n right: 0.75rem;\n top: 0.5rem;\n font-family: monospace;\n font-size: 0.75rem;\n letter-spacing: -0.05em;\n color: rgba(107, 114, 128, 0.85);\n}\n",":where(.rs-has-line-numbers) {\n counter-reset: line-number calc(var(--line-start, 1) - 1);\n}\n\n:where(.rs-has-line-numbers .rs-line-number)::before {\n counter-increment: line-number;\n content: counter(line-number);\n display: inline-flex;\n justify-content: flex-end;\n align-items: flex-start;\n box-sizing: content-box;\n min-width: var(--rs-line-numbers-width, 2ch);\n padding-left: var(--rs-line-numbers-padding-left, 0ch);\n padding-right: var(--rs-line-numbers-padding-right, 2ch);\n color: var(--rs-line-numbers-foreground, rgba(107, 114, 128, 0.5));\n font-size: var(--rs-line-numbers-font-size, inherit);\n font-weight: var(--rs-line-numbers-font-weight, inherit);\n line-height: var(--rs-line-numbers-line-height, inherit);\n font-family: var(--rs-line-numbers-font-family, inherit);\n opacity: var(--rs-line-numbers-opacity, 1);\n user-select: none;\n pointer-events: none;\n}\n\n:where(.rs-has-highlighted-lines) {\n display: block;\n width: fit-content;\n min-width: 100%;\n}\n\n:where(.rs-highlighted-line) {\n --_rs-hl-background: var(\n --rs-highlighted-line-background,\n color-mix(in srgb, currentColor 10%, transparent)\n );\n display: inline-block;\n width: 100%;\n min-height: 1lh;\n background-color: var(--_rs-hl-background);\n}\n\n/* Full bleed: the 100vw outset paints into the pre's padding, clipped by its overflow. */\n:where(.rs-default-styles .rs-highlighted-line) {\n background-color: transparent;\n border-image:\n linear-gradient(var(--_rs-hl-background) 0 0) fill 0 / 0 / 0 100vw;\n}\n\n:where(.rs-has-line-numbers .rs-highlighted-line)::before {\n color: var(\n --rs-highlighted-line-number-foreground,\n color-mix(in srgb, currentColor 65%, transparent)\n );\n}\n","import componentCss from '../styles/component.css?inline';\nimport featuresCss from '../styles/features.css?inline';\nimport * as React from 'react';\n// Side-effect import so tsdown emits dist/style.css for the ./css export;\n// stripped from the built JS, guarded by check:package\nimport '../styles/index.css';\n\nconst injected = new Set<string>();\n\nconst useStyleInsertionEffect =\n React.useInsertionEffect ?? React.useLayoutEffect;\n\nconst inject = (css: string, key: string) => {\n if (injected.has(key) || typeof document === 'undefined') {\n return;\n }\n\n injected.add(key);\n\n try {\n // Not governed by CSP style-src in current browsers, unlike the <style> fallback\n const sheet = new CSSStyleSheet();\n sheet.replaceSync(css);\n document.adoptedStyleSheets = [...document.adoptedStyleSheets, sheet];\n } catch {\n const style = document.createElement('style');\n style.dataset.reactShiki = key;\n style.textContent = css;\n document.head.append(style);\n }\n};\n\n/** Installs component styles before layout without triggering a render. */\nexport const useComponentStyles = () => {\n useStyleInsertionEffect(() => {\n inject(componentCss, 'component');\n }, []);\n};\n\n/** Installs line-number/highlight styles only when those options are used. */\nexport const useFeatureStyles = (enabled: boolean) => {\n useStyleInsertionEffect(() => {\n if (enabled) {\n inject(featuresCss, 'features');\n }\n }, [enabled]);\n};\n","import type { Language, PreloadLanguage } from './types';\nimport { guessEmbeddedLanguages, isSpecialLang } from 'shiki/core';\nimport type {\n DynamicImportLanguageRegistration,\n Highlighter,\n HighlighterCore,\n LanguageInput,\n LanguageRegistration,\n} from 'shiki';\n\nexport const FALLBACK_LANGUAGE = 'plaintext';\n\nconst toArray = <T>(value?: T | T[]): T[] => {\n if (value == null) {\n return [];\n }\n\n return Array.isArray(value) ? value : [value];\n};\n\n/** Deferred `LanguageInput` forms (getter, promise, module, array) that shiki resolves itself */\ntype DynamicLanguage = Exclude<LanguageInput, LanguageRegistration>;\n\nconst isDynamicLanguage = (\n lang: PreloadLanguage\n): lang is DynamicLanguage =>\n typeof lang === 'function' ||\n lang instanceof Promise ||\n Array.isArray(lang) ||\n (typeof lang === 'object' && lang != null && 'default' in lang);\n\nconst isRegistration = (\n lang: PreloadLanguage\n): lang is LanguageRegistration =>\n typeof lang === 'object' && lang != null && !isDynamicLanguage(lang);\n\n/** Dedupe identity: strings and registrations by value, dynamic inputs by reference */\nconst languageKey = (lang: PreloadLanguage): string | object | null => {\n if (lang == null) {\n return null;\n }\n\n if (typeof lang === 'string') {\n return `s:${lang}`;\n }\n\n if (isDynamicLanguage(lang)) {\n return lang;\n }\n\n return `o:${lang.name}::${lang.scopeName}`;\n};\n\nconst dedupeLanguages = (langs: PreloadLanguage[]): PreloadLanguage[] => {\n const seen = new Set<string | object>();\n\n return langs.filter((lang) => {\n const key = languageKey(lang);\n\n if (key == null || seen.has(key)) {\n return false;\n }\n\n seen.add(key);\n\n return true;\n });\n};\n\n/**\n * A registration matches a query by name, scopeName (full or its last\n * segment, e.g. \"source.tsx\" -> \"tsx\"), aliases, or fileTypes.\n */\nconst registrationMatches = (\n candidate: LanguageRegistration,\n matches: (str: string | undefined) => boolean\n): boolean =>\n matches(candidate.name) ||\n matches(candidate.scopeName) ||\n matches(candidate.scopeName?.split('.').pop()) ||\n !!candidate.aliases?.some(matches) ||\n !!candidate.fileTypes?.some(matches);\n\ninterface LanguageResult {\n languageId: string;\n langsToLoad: PreloadLanguage[];\n}\n\n/**\n * Resolves the language prop to a shiki language id plus everything the\n * factory should load (primary, preloaded, and custom grammars, deduped).\n */\nexport const resolveLanguage = (\n lang: Language,\n customLanguages?: LanguageRegistration | LanguageRegistration[],\n langAliases?: Record<string, string>,\n preloadLanguages?: PreloadLanguage | PreloadLanguage[]\n): LanguageResult => {\n const customLangs = toArray(customLanguages);\n const preloadLangs = toArray(preloadLanguages);\n\n const result = (\n languageId: string,\n primary?: Language\n ): LanguageResult => ({\n languageId,\n langsToLoad: dedupeLanguages([\n primary,\n ...preloadLangs,\n ...customLangs,\n ]),\n });\n\n if (lang == null || (typeof lang === 'string' && !lang.trim())) {\n return result(FALLBACK_LANGUAGE);\n }\n\n if (typeof lang === 'object') {\n return result(lang.name, lang);\n }\n\n const normalized = lang.trim();\n const query = normalized.toLowerCase();\n\n const matches = (str: string | undefined): boolean =>\n str?.toLowerCase() === query;\n\n // Custom registrations (from both customLanguages and preloadLanguages)\n const customMatch = [...customLangs, ...preloadLangs]\n .filter(isRegistration)\n .find((candidate) => registrationMatches(candidate, matches));\n\n if (customMatch) {\n return result(customMatch.name || normalized, customMatch);\n }\n\n const alias = Object.entries(langAliases ?? {}).find(([name]) =>\n matches(name)\n )?.[1];\n\n if (alias) {\n return result(alias, alias);\n }\n\n // Any other string passes through to the factory\n return result(normalized, normalized);\n};\n\n/**\n * Used in factories to check if language is supported.\n * Objects are validated as grammar registrations (name + scopeName);\n * dynamic imports pass through for shiki to resolve.\n */\nexport const isLoadableLanguage = <T extends string>(\n lang: PreloadLanguage,\n bundledLanguages: Record<T, DynamicImportLanguageRegistration>\n): lang is NonNullable<PreloadLanguage> => {\n if (lang == null) {\n return false;\n }\n\n if (typeof lang === 'string') {\n return lang in bundledLanguages;\n }\n\n if (isDynamicLanguage(lang)) {\n return true;\n }\n\n return (\n typeof lang.name === 'string' && typeof lang.scopeName === 'string'\n );\n};\n\n/**\n * Used in hook to resolve loaded language for highlighting.\n * Falls back to \"plaintext\" if not supported.\n */\nexport const resolveLoadedLanguage = (\n languageId: string,\n loadedLanguages: string[]\n): string =>\n isSpecialLang(languageId) || loadedLanguages.includes(languageId)\n ? languageId\n : FALLBACK_LANGUAGE;\n\nexport const getEmbeddedLanguages = (\n code: string,\n languageId: string,\n highlighter: Highlighter | HighlighterCore\n): LanguageInput[] => {\n const bundled: Record<string, LanguageInput> =\n highlighter.getBundledLanguages();\n\n return guessEmbeddedLanguages(code, languageId).flatMap(\n // oxlint-disable-next-line typescript/promise-function-async -- returns shiki's LanguageInput, which can itself be a promise\n (language) => bundled[language] ?? []\n );\n};\n","import type { Theme, Themes } from './types';\nimport type { ThemeRegistrationAny } from 'shiki/core';\n\nexport const DEFAULT_THEMES: Themes = {\n light: 'github-light',\n dark: 'github-dark',\n};\n\nexport type ResolvedTheme =\n | {\n isMulti: true;\n themes: Record<string, Theme>;\n themesToLoad: Theme[];\n }\n | { isMulti: false; theme: Theme; themesToLoad: Theme[] };\n\nconst isTextmateTheme = (\n value: Theme | Themes | undefined\n): value is ThemeRegistrationAny => {\n if (typeof value !== 'object' || value === null) {\n return false;\n }\n\n const hasTokens =\n ('tokenColors' in value && Array.isArray(value.tokenColors)) ||\n ('settings' in value && Array.isArray(value.settings));\n\n const hasIdentity =\n ('name' in value && typeof value.name === 'string') ||\n ('type' in value && typeof value.type === 'string');\n\n return hasTokens && hasIdentity;\n};\n\nexport function resolveTheme(themeInput: Theme | Themes): ResolvedTheme {\n if (\n typeof themeInput !== 'object' ||\n themeInput === null ||\n isTextmateTheme(themeInput)\n ) {\n return {\n isMulti: false,\n theme: themeInput,\n themesToLoad: [themeInput],\n };\n }\n\n const validEntries = Object.entries(themeInput).filter(\n ([key, value]) =>\n key.trim() !== '' &&\n ((typeof value === 'string' && value.trim() !== '') ||\n isTextmateTheme(value))\n );\n\n if (validEntries.length === 0) {\n console.warn(\n '[react-shiki] invalid multi-theme config, falling back to defaults'\n );\n\n return {\n isMulti: true,\n themes: DEFAULT_THEMES,\n themesToLoad: Object.values(DEFAULT_THEMES),\n };\n }\n\n if (validEntries.length !== Object.keys(themeInput).length) {\n console.warn(\n '[react-shiki] multi-theme config contained invalid entries; they were dropped'\n );\n }\n\n const themes = Object.fromEntries(validEntries);\n\n return {\n isMulti: true,\n themes,\n themesToLoad: validEntries.map(([, value]) => value),\n };\n}\n","import type { Awaitable, RegexEngine } from 'shiki/core';\nimport type { EngineName } from './types';\n\nconst engines = new Map<EngineName, Promise<RegexEngine>>();\n\n// Dynamic imports keep unused engines out of the loaded graph: naming an\n// engine loads only that engine, and 'javascript' never fetches the wasm.\nconst loaders: Record<EngineName, () => Promise<RegexEngine>> = {\n javascript: async () => {\n const { createJavaScriptRegexEngine } =\n await import('shiki/engine/javascript');\n\n return createJavaScriptRegexEngine();\n },\n oniguruma: async () => {\n const { createOnigurumaEngine } =\n await import('shiki/engine/oniguruma');\n\n return await createOnigurumaEngine(import('shiki/wasm'));\n },\n};\n\n/**\n * Resolves a named engine to a lazily created, cached instance.\n * Engine instances and undefined pass through untouched.\n *\n * The cache makes named engines referentially stable across renders and\n * call sites, unlike inline `createJavaScriptRegexEngine()` calls.\n */\nexport const resolveEngine = (\n engine: EngineName | Awaitable<RegexEngine> | undefined\n): Awaitable<RegexEngine> | undefined => {\n if (typeof engine !== 'string') {\n return engine;\n }\n\n if (!Object.hasOwn(loaders, engine)) {\n throw new Error(\n `[react-shiki] unknown engine '${engine}', expected 'javascript' or 'oniguruma'`\n );\n }\n\n const cached = engines.get(engine);\n\n if (cached) {\n return cached;\n }\n\n const instance = loaders[engine]();\n // Evict rejected loads (e.g. transient wasm fetch failure) so the\n // next highlight retries instead of reusing the cached rejection.\n instance.catch(() => engines.delete(engine));\n engines.set(engine, instance);\n\n return instance;\n};\n","import type { ShikiTransformer } from 'shiki/core';\n\nconst toLineNumberSet = (lineNumbers: readonly number[]) =>\n new Set(lineNumbers.filter(Number.isInteger));\n\n/**\n * Creates a transformer that enables line numbers display\n * @param startLine - The starting line number (defaults to 1)\n */\nexport function lineNumbersTransformer(startLine = 1): ShikiTransformer {\n return {\n name: 'react-shiki:line-numbers',\n code(node) {\n this.addClassToHast(node, 'rs-has-line-numbers');\n\n if (startLine !== 1) {\n const existing = node.properties?.style;\n node.properties = {\n ...node.properties,\n style: [existing, `--line-start: ${startLine}`]\n .filter(Boolean)\n .join('; '),\n };\n }\n },\n line(node) {\n this.addClassToHast(node, 'rs-line-number');\n\n return node;\n },\n };\n}\n\n/**\n * Creates a transformer that marks selected displayed line numbers.\n * @param lineNumbers - Displayed line numbers to highlight\n * @param startLine - The starting line number (defaults to 1)\n */\nexport function highlightedLinesTransformer(\n lineNumbers: readonly number[],\n startLine = 1\n): ShikiTransformer {\n const highlightedLines = toLineNumberSet(lineNumbers);\n\n return {\n name: 'react-shiki:highlight-lines',\n code(node) {\n this.addClassToHast(node, 'rs-has-highlighted-lines');\n },\n line(node, line) {\n const displayedLine = startLine + line - 1;\n\n if (highlightedLines.has(displayedLine)) {\n this.addClassToHast(node, 'rs-highlighted-line');\n }\n\n return node;\n },\n };\n}\n","import type {\n BundledTheme,\n CodeOptionsMultipleThemes,\n CodeOptionsSingleTheme,\n CodeToHastOptions,\n} from 'shiki';\n\nimport type {\n HighlighterOptions,\n HighlighterOptionsFor,\n OutputFormat,\n} from './types';\nimport type { ResolvedTheme } from './theme';\nimport {\n highlightedLinesTransformer,\n lineNumbersTransformer,\n} from './transformers';\n\nconst buildThemeOptions = (\n resolvedTheme: ResolvedTheme,\n defaultColor: HighlighterOptions['defaultColor'],\n cssVariablePrefix: HighlighterOptions['cssVariablePrefix']\n):\n | CodeOptionsMultipleThemes<BundledTheme>\n | CodeOptionsSingleTheme<BundledTheme> => {\n if (resolvedTheme.isMulti) {\n return {\n themes: resolvedTheme.themes,\n defaultColor,\n cssVariablePrefix,\n };\n }\n\n return {\n theme: resolvedTheme.theme,\n };\n};\n\nexport const buildShikiOptions = (\n languageId: string,\n resolvedTheme: ResolvedTheme,\n options: HighlighterOptionsFor<OutputFormat>\n): CodeToHastOptions => {\n const {\n delay,\n // oxlint-disable-next-line typescript/no-deprecated -- omitted from the options passed through to shiki\n customLanguages,\n preloadLanguages,\n outputFormat,\n highlighter,\n langAlias,\n engine,\n defaultColor,\n cssVariablePrefix,\n showLineNumbers,\n startingLineNumber,\n highlightLineNumbers,\n transformers: userTransformers,\n ...shikiPassthrough\n } = options;\n\n const transformers = [...(userTransformers ?? [])];\n\n if (showLineNumbers) {\n transformers.push(lineNumbersTransformer(startingLineNumber));\n }\n\n if (highlightLineNumbers?.length) {\n transformers.push(\n highlightedLinesTransformer(\n highlightLineNumbers,\n startingLineNumber\n )\n );\n }\n\n return {\n lang: languageId,\n ...buildThemeOptions(resolvedTheme, defaultColor, cssVariablePrefix),\n ...shikiPassthrough,\n transformers,\n };\n};\n","import { useEffect, useMemo, useRef, useState } from 'react';\nimport type { ReactElement } from 'react';\nimport { jsx, jsxs, Fragment } from 'react/jsx-runtime';\nimport { toJsxRuntime } from 'hast-util-to-jsx-runtime';\nimport type { CodeToHastOptions } from 'shiki';\n\nimport type {\n HighlightCache,\n HighlighterFactory,\n HighlighterOptions,\n HighlighterOptionsFor,\n HighlightResult,\n HighlightResultMap,\n Language,\n OutputFormat,\n PreloadLanguage,\n Theme,\n Themes,\n TimeoutState,\n} from './types';\n\nimport { throttleHighlighting, useStableValue } from './utils';\nimport { useFeatureStyles } from './styles';\nimport {\n getEmbeddedLanguages,\n resolveLanguage,\n resolveLoadedLanguage,\n} from './language';\nimport { resolveTheme } from './theme';\nimport { resolveEngine } from './engine';\nimport { buildShikiOptions } from './options';\n\nexport async function highlight<F extends OutputFormat = 'react'>(\n code: string,\n resolved: {\n languageId: string;\n langsToLoad: PreloadLanguage[];\n themesToLoad: Theme[];\n shikiOptions: CodeToHastOptions;\n },\n opts: Pick<HighlighterOptions, 'highlighter' | 'engine'> & {\n outputFormat?: F;\n },\n factory: HighlighterFactory\n): Promise<HighlightResultMap[F]> {\n const { languageId, langsToLoad, themesToLoad, shikiOptions } =\n resolved;\n\n const format: OutputFormat = opts.outputFormat ?? 'react';\n\n const highlighter =\n opts.highlighter ??\n (await (async () => {\n const hl = await factory(\n langsToLoad,\n themesToLoad,\n resolveEngine(opts.engine)\n );\n\n await hl.loadLanguage(\n ...getEmbeddedLanguages(code, languageId, hl)\n );\n\n return hl;\n })());\n\n const language = resolveLoadedLanguage(\n languageId,\n highlighter.getLoadedLanguages()\n );\n\n const options = { ...shikiOptions, lang: language };\n\n const outputs = {\n react: (): ReactElement =>\n // oxlint-disable-next-line typescript/no-unsafe-return -- toJsxRuntime returns the global JSX.Element, which React 19's types no longer declare\n toJsxRuntime(highlighter.codeToHast(code, options), {\n jsx,\n jsxs,\n Fragment,\n }),\n html: () => highlighter.codeToHtml(code, options),\n tokens: () => highlighter.codeToTokens(code, options),\n } satisfies { [K in OutputFormat]: () => HighlightResultMap[K] };\n\n // Untyped call sites can pass formats outside OutputFormat; degrade to\n // react rendering like the pre-tokens ternary did instead of throwing.\n // oxlint-disable-next-line typescript/no-unsafe-type-assertion, anti-slop/require-safety-comment-for-type-assertion -- outputs[format] returns HighlightResultMap[format], and TS can't tie format to the generic F\n return (outputs[format] ?? outputs.react)() as HighlightResultMap[F];\n}\n\nconst readCache = <F extends OutputFormat>(\n cache: HighlightCache | undefined,\n key: string | undefined\n): HighlightResult<F> => {\n if (!key) {\n return null;\n }\n\n // oxlint-disable-next-line typescript/no-unsafe-type-assertion, anti-slop/require-safety-comment-for-type-assertion -- the key includes outputFormat, so an entry under it is HighlightResultMap[F]\n const cached = cache?.get(key) as HighlightResultMap[F] | undefined;\n\n return cached === undefined || cached === '' ? null : cached;\n};\n\nexport const useHighlight = <F extends OutputFormat = 'react'>(\n code: string,\n lang: Language,\n themeInput: Theme | Themes,\n optionsInput: HighlighterOptionsFor<F> | undefined,\n highlighterFactory: HighlighterFactory\n): HighlightResult<F> => {\n const { cache, ...rest } = optionsInput ?? {};\n const cacheRef = useRef(cache);\n cacheRef.current = cache;\n\n // This hook owns the line-number/highlight output, so it also owns the\n // corresponding styles. The primitive boolean limits effect reruns.\n useFeatureStyles(\n Boolean(rest.showLineNumbers || rest.highlightLineNumbers?.length)\n );\n\n const stableLang = useStableValue(lang);\n const stableTheme = useStableValue(themeInput);\n const stableOpts = useStableValue(rest);\n\n const resolved = useMemo(() => {\n const { languageId, langsToLoad } = resolveLanguage(\n stableLang,\n // oxlint-disable-next-line typescript/no-deprecated -- the hook still honors its own deprecated prop\n stableOpts.customLanguages,\n stableOpts.langAlias,\n stableOpts.preloadLanguages\n );\n\n const theme = resolveTheme(stableTheme);\n\n const shikiOptions = buildShikiOptions(languageId, theme, stableOpts);\n\n return {\n languageId,\n langsToLoad,\n themesToLoad: theme.themesToLoad,\n shikiOptions,\n };\n }, [stableLang, stableTheme, stableOpts]);\n\n const hasCache = Boolean(cache);\n\n const cacheScope = useMemo(\n () =>\n hasCache\n ? JSON.stringify([\n stableOpts.outputFormat ?? 'react',\n resolved.shikiOptions,\n stableOpts.startingLineNumber,\n stableOpts.highlightLineNumbers,\n ])\n : undefined,\n [hasCache, resolved, stableOpts]\n );\n\n const cacheKey = cacheScope && `${cacheScope}\\n${code}`;\n\n const [highlightedCode, setHighlightedCode] = useState(() =>\n readCache<F>(cache, cacheKey)\n );\n\n const shown = useRef({ key: cacheKey, result: highlightedCode });\n\n useEffect(\n () => () => {\n const { key, result } = shown.current;\n\n if (key && result !== null && result !== '') {\n cacheRef.current?.set(key, result);\n }\n },\n []\n );\n\n const requestIdRef = useRef(0);\n\n const timeoutControl = useRef<TimeoutState>({\n nextAllowedTime: 0,\n timeoutId: undefined,\n });\n\n // Factory is invoked imperatively; its identity is not semantic, so it must\n // not invalidate the effect on every render. See issue #161.\n const highlighterFactoryRef = useRef(highlighterFactory);\n highlighterFactoryRef.current = highlighterFactory;\n\n useEffect(() => {\n const requestId = ++requestIdRef.current;\n const timeouts = timeoutControl.current;\n\n const show = (result: HighlightResult<F>) => {\n shown.current = { key: cacheKey, result };\n setHighlightedCode(result);\n };\n\n const run = async () => {\n try {\n const result = await highlight<F>(\n code,\n resolved,\n stableOpts,\n highlighterFactoryRef.current\n );\n\n if (requestId === requestIdRef.current) {\n show(result);\n }\n } catch (error) {\n console.error('[react-shiki] highlight failed', error);\n }\n };\n\n const cached = readCache<F>(cacheRef.current, cacheKey);\n\n if (!resolved.languageId) {\n return () => {\n clearTimeout(timeouts.timeoutId);\n };\n }\n\n if (cached !== null) {\n if (shown.current.result !== cached) {\n show(cached);\n }\n } else if (stableOpts.delay) {\n throttleHighlighting(run, timeoutControl, stableOpts.delay);\n } else {\n void run();\n }\n\n return () => {\n clearTimeout(timeouts.timeoutId);\n };\n }, [code, cacheKey, resolved, stableOpts]);\n\n return highlightedCode;\n};\n","import { clsx } from 'clsx';\n\nimport type {\n HighlighterOptions,\n Language,\n OutputFormat,\n Theme,\n Themes,\n UseShikiHighlighter,\n} from './types';\nimport { forwardRef } from 'react';\nimport { useComponentStyles } from './styles';\n\nlet warnedTokensOutputFormat = false;\n\n/**\n * The component's props exclude `outputFormat: 'tokens'`, but plain-JS\n * callers can still pass it. Tokens are not renderable React children,\n * so fall back to 'react' instead of crashing the render.\n */\nconst resolveOutputFormat = (\n outputFormat: OutputFormat | undefined\n): HighlighterOptions['outputFormat'] => {\n if (outputFormat !== 'tokens') {\n return outputFormat;\n }\n\n if (!warnedTokensOutputFormat) {\n warnedTokensOutputFormat = true;\n console.warn(\n \"[react-shiki] outputFormat 'tokens' is only supported by the useShikiHighlighter hook, falling back to 'react'\"\n );\n }\n\n return 'react';\n};\n\n/**\n * Props for the ShikiHighlighter component\n */\nexport interface ShikiHighlighterProps extends HighlighterOptions {\n /**\n * The programming language for syntax highlighting\n * Supports custom textmate grammar objects in addition to Shiki's bundled languages\n * @see https://shiki.style/languages\n */\n language: Language;\n\n /**\n * The code to be highlighted\n */\n children: string;\n\n /**\n * The color theme or themes for syntax highlighting\n * Supports single, dual, or multiple themes\n * Supports custom textmate theme objects in addition to Shiki's bundled themes\n *\n * @example\n * theme='github-dark' // single theme\n * theme={{ light: 'github-light', dark: 'github-dark' }} // multi-theme\n *\n * @see https://shiki.style/themes\n */\n theme: Theme | Themes;\n\n /**\n * Controls the application of default styles to the generated code blocks\n *\n * Default styles include padding, overflow handling, border radius, language label styling, and font settings\n * @default true\n */\n addDefaultStyles?: boolean;\n\n /**\n * Add custom inline styles to the generated code block\n */\n style?: React.CSSProperties;\n\n /**\n * Add custom inline styles to the language label\n */\n langStyle?: React.CSSProperties;\n\n /**\n * Add custom CSS class names to the generated code block\n */\n className?: string;\n\n /**\n * Add custom CSS class names to the language label\n */\n langClassName?: string;\n\n /**\n * Whether to show the language label\n * @default true\n */\n showLanguage?: boolean;\n\n /**\n * The HTML element that wraps the generated code block.\n * @default 'div'\n */\n as?: React.ElementType;\n}\n\n/**\n * Base ShikiHighlighter component factory.\n * This creates a component that uses the provided hook implementation.\n */\nexport const createShikiHighlighterComponent = (\n useShikiHighlighterImpl: UseShikiHighlighter\n) =>\n forwardRef<HTMLElement, ShikiHighlighterProps>(\n // oxlint-disable-next-line react/display-name -- naming the render function would change the name React DevTools shows for the published component\n (\n {\n language,\n theme,\n addDefaultStyles = true,\n style,\n langStyle,\n className,\n langClassName,\n showLanguage = true,\n children: code,\n as: Element = 'div',\n outputFormat,\n ...options\n },\n ref\n ) => {\n // Kept inside the component so hook-only bundles can tree-shake it\n // together with the component CSS.\n useComponentStyles();\n\n const displayLanguageId =\n typeof language === 'object'\n ? language.name || null\n : language?.trim() || null;\n\n const highlightedCode = useShikiHighlighterImpl(\n code,\n language,\n theme,\n {\n ...options,\n outputFormat: resolveOutputFormat(outputFormat),\n }\n );\n\n return (\n <Element\n ref={ref}\n data-testid=\"shiki-container\"\n data-slot=\"container\"\n className={clsx(\n 'rs-root',\n 'not-prose',\n addDefaultStyles && 'rs-default-styles',\n className\n )}\n style={style}\n >\n {showLanguage && displayLanguageId ? (\n <span\n data-slot=\"language-label\"\n className={clsx('rs-language-label', langClassName)}\n style={langStyle}\n >\n {displayLanguageId}\n </span>\n ) : null}\n {typeof highlightedCode === 'string' ? (\n <div\n data-slot=\"content\"\n // oxlint-disable-next-line react/no-danger -- outputFormat 'html' renders shiki's escaped HTML by design\n dangerouslySetInnerHTML={{ __html: highlightedCode }}\n />\n ) : (\n highlightedCode\n )}\n </Element>\n );\n }\n );\n","import { visit } from 'unist-util-visit';\nimport type { Root } from 'hast';\nimport type { Element } from './types';\n\n/**\n * Rehype plugin to add an 'inline' property to <code> elements\n * Sets 'inline' property to true if the <code> is not within a <pre> tag\n *\n * Pass this plugin to the `rehypePlugins` prop of react-markdown\n * You can then access `inline` as a prop in components passed to react-markdown\n *\n * @example\n * <ReactMarkdown rehypePlugins={[rehypeInlineCodeProperty]} />\n */\nexport function rehypeInlineCodeProperty() {\n return (tree: Root): undefined => {\n visit(tree, 'element', (node: Element, _index, parent) => {\n if (\n node.tagName === 'code' &&\n parent?.type === 'element' &&\n parent.tagName !== 'pre'\n ) {\n node.properties.inline = true;\n }\n });\n };\n}\n\n/**\n * Function to determine if code is inline based on the presence of line breaks\n *\n * @example\n * const isInline = node && isInlineCode(node: Element)\n */\nexport const isInlineCode = (node: Element): boolean => {\n const textContent = (node.children ?? [])\n .filter((child) => child.type === 'text')\n .map((child) => child.value)\n .join('');\n\n return !textContent.includes('\\n');\n};\n"],"mappings":"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"}