{"version":3,"sources":["../src/shiki/index.ts"],"names":[],"mappings":";;;AAmDA,eAAsB,sBAAA,CACpB,OAAA,GAAmC,EAAC,EACZ;AACxB,EAAA,MAAM,KAAA,GAAQ,QAAQ,KAAA,IAAS,aAAA;AAC/B,EAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,KAAA,IAAS,CAAC,YAAA,EAAc,YAAA,EAAc,KAAA,EAAO,QAAA,EAAU,MAAA,EAAQ,IAAA,EAAM,MAAA,EAAQ,MAAM,CAAA;AAEzG,EAAA,MAAM,KAAA,GAAS,MAAM,OAAO,OAAO,CAAA;AAKnC,EAAA,MAAM,OAAA,GAAU,KAAA,CAAM,iBAAA,IAAqB,KAAA,CAAM,cAAA;AACjD,EAAA,IAAI,CAAC,OAAA,EAAS,MAAM,IAAI,MAAM,oEAAoE,CAAA;AAClG,EAAA,MAAM,WAAA,GAAc,MAAM,OAAA,CAAQ;AAAA,IAChC,MAAA,EAAQ,CAAC,KAAK,CAAA;AAAA,IACd;AAAA,GACD,CAAA;AAED,EAAA,MAAM,KAAA,uBAAY,GAAA,EAAwD;AAE1E,EAAA,OAAO,CAAC,MAAc,QAAA,KAAqB;AACzC,IAAA,MAAM,GAAA,GAAM,CAAA,EAAG,QAAQ,CAAA,EAAA,EAAI,IAAI,CAAA,CAAA;AAC/B,IAAA,MAAM,MAAA,GAAS,KAAA,CAAM,GAAA,CAAI,GAAG,CAAA;AAC5B,IAAA,IAAI,QAAQ,OAAO,MAAA;AAEnB,IAAA,MAAM,OAAO,QAAA,IAAY,MAAA;AACzB,IAAA,IAAI,CAAC,WAAA,CAAY,kBAAA,EAAmB,CAAE,QAAA,CAAS,IAAI,CAAA,EAAG;AAEpD,MAAA,KAAK,YAAY,YAAA,CAAa,IAAI,CAAA,CAAE,KAAA,CAAM,MAAM,MAAS,CAAA;AACzD,MAAA,OAAO,CAAC,EAAE,IAAA,EAAM,IAAA,EAAM,SAAA,EAAW,IAAI,CAAA;AAAA,IACvC;AAEA,IAAA,IAAI,MAAA;AACJ,IAAA,IAAI;AACF,MAAA,MAAA,GAAS,YAAY,YAAA,CAAa,IAAA,EAAM,EAAE,IAAA,EAAM,OAAO,CAAA;AAAA,IACzD,CAAA,CAAA,MAAQ;AACN,MAAA,OAAO,CAAC,EAAE,IAAA,EAAM,IAAA,EAAM,SAAA,EAAW,IAAI,CAAA;AAAA,IACvC;AACA,IAAA,MAAM,SAAqD,EAAC;AAC5D,IAAA,MAAA,CAAO,MAAA,CAAO,OAAA,CAAQ,CAAC,IAAA,EAAM,EAAA,KAAO;AAClC,MAAA,KAAA,MAAW,KAAK,IAAA,EAAM;AAKpB,QAAA,MAAM,GAAA,GAAM,EAAE,KAAA,GAAQ,CAAA,UAAA,EAAa,aAAa,CAAA,CAAE,KAAK,CAAC,CAAA,CAAA,GAAK,EAAA;AAC7D,QAAA,MAAA,CAAO,KAAK,EAAE,IAAA,EAAM,EAAE,OAAA,EAAS,SAAA,EAAW,KAAK,CAAA;AAAA,MACjD;AACA,MAAA,IAAI,EAAA,GAAK,MAAA,CAAO,MAAA,CAAO,MAAA,GAAS,CAAA,EAAG,MAAA,CAAO,IAAA,CAAK,EAAE,IAAA,EAAM,IAAA,EAAM,SAAA,EAAW,EAAA,EAAI,CAAA;AAAA,IAC9E,CAAC,CAAA;AACD,IAAA,KAAA,CAAM,GAAA,CAAI,KAAK,MAAM,CAAA;AACrB,IAAA,OAAO,MAAA;AAAA,EACT,CAAA;AACF;AAEA,SAAS,aAAa,KAAA,EAAuB;AAC3C,EAAA,OAAO,QAAA,GAAW,KAAA,CAAM,OAAA,CAAQ,eAAA,EAAiB,EAAE,CAAA;AACrD","file":"shiki.cjs","sourcesContent":["/**\n * stream-md/shiki — Shiki-backed syntax highlighter (lazy).\n *\n * Shiki uses TextMate grammars + VS Code themes for production-grade syntax\n * highlighting. Required as an *optional* peer dependency (zero cost if\n * not imported).\n *\n * @example\n * ```tsx\n * import { StreamMD } from 'stream-md';\n * import { createShikiHighlighter } from 'stream-md/shiki';\n *\n * const highlighter = await createShikiHighlighter({\n *   theme: 'github-dark',\n *   langs: ['ts', 'tsx', 'python', 'rust'],\n * });\n *\n * <StreamMD text={text} highlighter={highlighter} />\n * ```\n */\n\nimport type { HighlighterFn } from \"../parser/types\";\n\nexport interface ShikiHighlighterOptions {\n  /** Theme name or theme object. */\n  theme?: string;\n  /** Languages to load up-front. Others are lazy-loaded on first use. */\n  langs?: string[];\n}\n\ninterface ShikiTokenLike {\n  content: string;\n  color?: string;\n}\n\ninterface ShikiHighlighterLike {\n  codeToTokens: (\n    code: string,\n    options: { lang: string; theme: string },\n  ) => { tokens: ShikiTokenLike[][] };\n  loadLanguage: (lang: string) => Promise<void>;\n  getLoadedLanguages: () => string[];\n}\n\n/**\n * Create a Shiki-backed highlighter. Returns an async function compatible\n * with `<StreamMD highlighter={...} />`.\n *\n * Note: highlighter is async at create time, but synchronous when called\n * from the component (uses cached results).\n */\nexport async function createShikiHighlighter(\n  options: ShikiHighlighterOptions = {},\n): Promise<HighlighterFn> {\n  const theme = options.theme ?? \"github-dark\";\n  const langs = options.langs ?? [\"javascript\", \"typescript\", \"tsx\", \"python\", \"rust\", \"go\", \"bash\", \"json\"];\n\n  const shiki = (await import(\"shiki\")) as unknown as {\n    createHighlighter?: (opts: { themes: string[]; langs: string[] }) => Promise<ShikiHighlighterLike>;\n    getHighlighter?: (opts: { themes: string[]; langs: string[] }) => Promise<ShikiHighlighterLike>;\n  };\n  // shiki@1+ uses createHighlighter; older uses getHighlighter.\n  const factory = shiki.createHighlighter ?? shiki.getHighlighter;\n  if (!factory) throw new Error(\"[stream-md/shiki] No createHighlighter/getHighlighter export found\");\n  const highlighter = await factory({\n    themes: [theme],\n    langs,\n  });\n\n  const cache = new Map<string, Array<{ text: string; className: string }>>();\n\n  return (code: string, language: string) => {\n    const key = `${language}\u0000${code}`;\n    const cached = cache.get(key);\n    if (cached) return cached;\n\n    const lang = language || \"text\";\n    if (!highlighter.getLoadedLanguages().includes(lang)) {\n      // Async-load and return plain for now; subsequent calls will hit the cache.\n      void highlighter.loadLanguage(lang).catch(() => undefined);\n      return [{ text: code, className: \"\" }];\n    }\n\n    let result;\n    try {\n      result = highlighter.codeToTokens(code, { lang, theme });\n    } catch {\n      return [{ text: code, className: \"\" }];\n    }\n    const tokens: Array<{ text: string; className: string }> = [];\n    result.tokens.forEach((line, li) => {\n      for (const t of line) {\n        // Use inline style via a className that consumers can target by color.\n        // To keep CSP-safe (no inline styles), we encode the color in a custom\n        // CSS variable through a className. Consumers needing exact colors\n        // should use Shiki's HTML output directly via a `pre` override.\n        const cls = t.color ? `smd-shiki ${colorToClass(t.color)}` : \"\";\n        tokens.push({ text: t.content, className: cls });\n      }\n      if (li < result.tokens.length - 1) tokens.push({ text: \"\\n\", className: \"\" });\n    });\n    cache.set(key, tokens);\n    return tokens;\n  };\n}\n\nfunction colorToClass(color: string): string {\n  return \"smd-c-\" + color.replace(/[^a-zA-Z0-9]/g, \"\");\n}\n"]}