{"version":3,"file":"FileRenderer.js","names":["options: FileRendererOptions","onRenderUpdate?: () => unknown","workerManager?: WorkerPoolManager | undefined","options: RenderFileOptions","options","contentArray: ElementContent[]"],"sources":["../../src/renderers/FileRenderer.ts"],"sourcesContent":["import type { ElementContent, Element as HASTElement } from 'hast';\nimport { toHtml } from 'hast-util-to-html';\n\nimport { DEFAULT_RENDER_RANGE, DEFAULT_THEMES } from '../constants';\nimport { areLanguagesAttached } from '../highlighter/languages/areLanguagesAttached';\nimport {\n  getHighlighterIfLoaded,\n  getSharedHighlighter,\n} from '../highlighter/shared_highlighter';\nimport { areThemesAttached } from '../highlighter/themes/areThemesAttached';\nimport { hasResolvedThemes } from '../highlighter/themes/hasResolvedThemes';\nimport type {\n  BaseCodeOptions,\n  DiffsHighlighter,\n  FileContents,\n  FileHeaderRenderMode,\n  LineAnnotation,\n  RenderedFileASTCache,\n  RenderFileOptions,\n  RenderFileResult,\n  RenderRange,\n  SupportedLanguages,\n  ThemedFileResult,\n} from '../types';\nimport { areRenderRangesEqual } from '../utils/areRenderRangesEqual';\nimport { areThemesEqual } from '../utils/areThemesEqual';\nimport { createAnnotationElement } from '../utils/createAnnotationElement';\nimport { createContentColumn } from '../utils/createContentColumn';\nimport { createFileHeaderElement } from '../utils/createFileHeaderElement';\nimport { createPreElement } from '../utils/createPreElement';\nimport { getFiletypeFromFileName } from '../utils/getFiletypeFromFileName';\nimport { getHighlighterOptions } from '../utils/getHighlighterOptions';\nimport { getLineAnnotationName } from '../utils/getLineAnnotationName';\nimport { getThemes } from '../utils/getThemes';\nimport {\n  createGutterGap,\n  createGutterItem,\n  createGutterWrapper,\n  createHastElement,\n} from '../utils/hast_utils';\nimport { isFilePlainText } from '../utils/isFilePlainText';\nimport { iterateOverFile } from '../utils/iterateOverFile';\nimport { renderFileWithHighlighter } from '../utils/renderFileWithHighlighter';\nimport { shouldUseTokenTransformer } from '../utils/shouldUseTokenTransformer';\nimport { splitFileContents } from '../utils/splitFileContents';\nimport type { WorkerPoolManager } from '../worker';\n\ntype AnnotationLineMap<LAnnotation> = Record<\n  number,\n  LineAnnotation<LAnnotation>[] | undefined\n>;\n\ninterface GetRenderOptionsReturn {\n  options: RenderFileOptions;\n  forceRender: boolean;\n}\n\nexport interface FileRenderResult {\n  gutterAST: ElementContent[];\n  contentAST: ElementContent[];\n  preAST: HASTElement;\n  headerAST: HASTElement | undefined;\n  css: string;\n  totalLines: number;\n  themeStyles: string;\n  baseThemeType: 'light' | 'dark' | undefined;\n  rowCount: number;\n  bufferBefore: number;\n  bufferAfter: number;\n}\n\ninterface LineCache {\n  cacheKey: string | undefined;\n  lines: string[];\n}\n\nexport interface FileRendererOptions extends BaseCodeOptions {\n  headerRenderMode?: FileHeaderRenderMode;\n}\n\nlet instanceId = -1;\n\nexport class FileRenderer<LAnnotation = undefined> {\n  readonly __id: string = `file-renderer:${++instanceId}`;\n\n  private highlighter: DiffsHighlighter | undefined;\n  private renderCache: RenderedFileASTCache | undefined;\n  private computedLang: SupportedLanguages = 'text';\n  private lineAnnotations: AnnotationLineMap<LAnnotation> = {};\n  private lineCache: LineCache | undefined;\n\n  constructor(\n    public options: FileRendererOptions = { theme: DEFAULT_THEMES },\n    private onRenderUpdate?: () => unknown,\n    private workerManager?: WorkerPoolManager | undefined\n  ) {\n    if (workerManager?.isWorkingPool() !== true) {\n      this.highlighter = areThemesAttached(options.theme ?? DEFAULT_THEMES)\n        ? getHighlighterIfLoaded()\n        : undefined;\n    }\n  }\n\n  public setOptions(options: FileRendererOptions): void {\n    this.options = options;\n  }\n\n  public mergeOptions(options: Partial<FileRendererOptions>): void {\n    this.options = { ...this.options, ...options };\n  }\n\n  public setLineAnnotations(\n    lineAnnotations: LineAnnotation<LAnnotation>[]\n  ): void {\n    this.lineAnnotations = {};\n    for (const annotation of lineAnnotations) {\n      const arr = this.lineAnnotations[annotation.lineNumber] ?? [];\n      this.lineAnnotations[annotation.lineNumber] = arr;\n      arr.push(annotation);\n    }\n  }\n\n  public cleanUp(): void {\n    this.renderCache = undefined;\n    this.highlighter = undefined;\n    this.workerManager = undefined;\n    this.onRenderUpdate = undefined;\n    this.lineCache = undefined;\n  }\n\n  public hydrate(file: FileContents): void {\n    const { options } = this.getRenderOptions(file);\n    let cache = this.workerManager?.getFileResultCache(file);\n    if (cache != null && !areRenderOptionsEqual(options, cache.options)) {\n      cache = undefined;\n    }\n    this.renderCache ??= {\n      file,\n      options,\n      highlighted: !isFilePlainText(file),\n      result: cache?.result,\n      // FIXME(amadeus): Add support for renderRanges\n      renderRange: undefined,\n    };\n    if (this.workerManager?.isWorkingPool() === true) {\n      if (this.renderCache.result == null) {\n        // We should only kick off a preload of the AST if we have a WorkerPool\n        this.workerManager.highlightFileAST(this, file);\n      }\n    }\n    // Lets attempt to get the highlighter/languages ready immediately\n    else if (this.highlighter == null) {\n      this.computedLang = file.lang ?? getFiletypeFromFileName(file.name);\n      void this.initializeHighlighter();\n    }\n  }\n\n  private getRenderOptions(file: FileContents): GetRenderOptionsReturn {\n    const options: RenderFileOptions = (() => {\n      if (this.workerManager?.isWorkingPool() === true) {\n        return this.workerManager.getFileRenderOptions();\n      }\n      const { theme = DEFAULT_THEMES, tokenizeMaxLineLength = 1000 } =\n        this.options;\n      return {\n        theme,\n        useTokenTransformer: shouldUseTokenTransformer(this.options),\n        tokenizeMaxLineLength,\n      };\n    })();\n    const { renderCache } = this;\n    if (renderCache?.result == null) {\n      return { options, forceRender: true };\n    }\n    if (\n      file !== renderCache.file ||\n      !areRenderOptionsEqual(options, renderCache.options)\n    ) {\n      return { options, forceRender: true };\n    }\n    return { options, forceRender: false };\n  }\n\n  public getOrCreateLineCache(file: FileContents): string[] {\n    // Uncached files will get split every time, not the greatest experience\n    // tbh... but something people should try to optimize away\n    if (file.cacheKey == null) {\n      this.lineCache = undefined;\n      return splitFileContents(file.contents);\n    }\n\n    let { lineCache } = this;\n    if (lineCache == null || lineCache.cacheKey !== file.cacheKey) {\n      lineCache = {\n        cacheKey: file.cacheKey,\n        lines: splitFileContents(file.contents),\n      };\n    }\n    this.lineCache = lineCache;\n    return lineCache.lines;\n  }\n\n  public renderFile(\n    file: FileContents | undefined = this.renderCache?.file,\n    renderRange: RenderRange = DEFAULT_RENDER_RANGE\n  ): FileRenderResult | undefined {\n    if (file == null) {\n      return undefined;\n    }\n    const cache = this.workerManager?.getFileResultCache(file);\n    if (cache != null && this.renderCache == null) {\n      this.renderCache = {\n        file,\n        highlighted: true,\n        renderRange: undefined,\n        ...cache,\n      };\n    }\n    const { options, forceRender } = this.getRenderOptions(file);\n    this.renderCache ??= {\n      file,\n      highlighted: false,\n      options,\n      result: undefined,\n      renderRange: undefined,\n    };\n    if (this.workerManager?.isWorkingPool() === true) {\n      // Cache invalidation based on renderRange comparison\n      if (\n        this.renderCache.result == null ||\n        (!this.renderCache.highlighted &&\n          (file !== this.renderCache.file ||\n            !areRenderRangesEqual(this.renderCache.renderRange, renderRange)))\n      ) {\n        this.renderCache.file = file;\n        this.renderCache.result = this.workerManager.getPlainFileAST(\n          file,\n          renderRange.startingLine,\n          renderRange.totalLines,\n          this.getOrCreateLineCache(file)\n        );\n        this.renderCache.renderRange = renderRange;\n      }\n\n      if (\n        // We should only attempt to kick off the worker highlighter if there\n        // are lines to render\n        renderRange.totalLines > 0 &&\n        (!this.renderCache.highlighted || forceRender)\n      ) {\n        this.workerManager.highlightFileAST(this, file);\n      }\n    } else {\n      this.computedLang = file.lang ?? getFiletypeFromFileName(file.name);\n      const hasThemes =\n        this.highlighter != null && areThemesAttached(options.theme);\n      const hasLangs =\n        this.highlighter != null && areLanguagesAttached(this.computedLang);\n\n      // If we have any semblance of a highlighter with the correct theme(s)\n      // attached, we can kick off some form of rendering.  If we don't have\n      // the correct language, then we can render plain text and after kick off\n      // an async job to get the highlighted AST\n      if (\n        this.highlighter != null &&\n        hasThemes &&\n        (forceRender ||\n          (!this.renderCache.highlighted && hasLangs) ||\n          this.renderCache.result == null)\n      ) {\n        const { result, options } = this.renderFileWithHighlighter(\n          file,\n          this.highlighter,\n          !hasLangs\n        );\n        this.renderCache = {\n          file,\n          options,\n          highlighted: hasLangs,\n          result,\n          renderRange: undefined,\n        };\n      }\n\n      // If we get in here it means we'll have to kick off an async highlight\n      // process which will involve initializing the highlighter with new themes\n      // and languages\n      if (!hasThemes || !hasLangs) {\n        void this.asyncHighlight(file).then(({ result, options }) => {\n          // In this case we need to force a re-render, so we can do that by\n          // reaching into renderCache\n          if (this.renderCache != null) {\n            this.renderCache.highlighted = false;\n          }\n          this.onHighlightSuccess(file, result, options);\n        });\n      }\n    }\n\n    return this.renderCache.result != null\n      ? this.processFileResult(\n          this.renderCache.file,\n          renderRange,\n          this.renderCache.result\n        )\n      : undefined;\n  }\n\n  async asyncRender(\n    file: FileContents,\n    renderRange: RenderRange = DEFAULT_RENDER_RANGE\n  ): Promise<FileRenderResult> {\n    const { result } = await this.asyncHighlight(file);\n    return this.processFileResult(file, renderRange, result);\n  }\n\n  private async asyncHighlight(file: FileContents): Promise<RenderFileResult> {\n    this.computedLang = file.lang ?? getFiletypeFromFileName(file.name);\n    const hasThemes =\n      this.highlighter != null &&\n      hasResolvedThemes(getThemes(this.options.theme));\n    const hasLangs =\n      this.highlighter != null && areLanguagesAttached(this.computedLang);\n    // If we don't have the required langs or themes, then we need to\n    // initialize the highlighter to load the appropriate languages and themes\n    if (this.highlighter == null || !hasThemes || !hasLangs) {\n      this.highlighter = await this.initializeHighlighter();\n    }\n    return this.renderFileWithHighlighter(file, this.highlighter);\n  }\n\n  private renderFileWithHighlighter(\n    file: FileContents,\n    highlighter: DiffsHighlighter,\n    forcePlainText = false\n  ): RenderFileResult {\n    const { options } = this.getRenderOptions(file);\n    const result = renderFileWithHighlighter(file, highlighter, options, {\n      forcePlainText,\n    });\n    return { result, options };\n  }\n\n  private processFileResult(\n    file: FileContents,\n    renderRange: RenderRange,\n    { code, themeStyles, baseThemeType }: ThemedFileResult\n  ): FileRenderResult {\n    const { disableFileHeader = false } = this.options;\n    const contentArray: ElementContent[] = [];\n    const gutter = createGutterWrapper();\n    const lines = this.getOrCreateLineCache(file);\n    let rowCount = 0;\n\n    iterateOverFile({\n      lines,\n      startingLine: renderRange.startingLine,\n      totalLines: renderRange.totalLines,\n      callback: ({ lineIndex, lineNumber }) => {\n        // Sparse array - directly indexed by lineIndex\n        const line = code[lineIndex];\n        if (line == null) {\n          const message = 'FileRenderer.processFileResult: Line doesnt exist';\n          console.error(message, {\n            name: file.name,\n            lineIndex,\n            lineNumber,\n            lines,\n          });\n          throw new Error(message);\n        }\n\n        if (line != null) {\n          // Add gutter line number\n          gutter.children.push(\n            createGutterItem('context', lineNumber, `${lineIndex}`)\n          );\n          contentArray.push(line);\n          rowCount++;\n\n          // Check annotations using ACTUAL line number from file\n          const annotations = this.lineAnnotations[lineNumber];\n          if (annotations != null) {\n            gutter.children.push(createGutterGap('context', 'annotation', 1));\n            contentArray.push(\n              createAnnotationElement({\n                type: 'annotation',\n                hunkIndex: 0,\n                lineIndex: lineNumber,\n                annotations: annotations.map((annotation) =>\n                  getLineAnnotationName(annotation)\n                ),\n              })\n            );\n            rowCount++;\n          }\n        }\n      },\n    });\n\n    // Finalize: wrap gutter and content\n    gutter.properties.style = `grid-row: span ${rowCount}`;\n    return {\n      gutterAST: gutter.children ?? [],\n      contentAST: contentArray,\n      preAST: this.createPreElement(lines.length),\n      headerAST: !disableFileHeader ? this.renderHeader(file) : undefined,\n      totalLines: lines.length,\n      rowCount,\n      themeStyles: themeStyles,\n      baseThemeType,\n      bufferBefore: renderRange.bufferBefore,\n      bufferAfter: renderRange.bufferAfter,\n      css: '',\n    };\n  }\n\n  private renderHeader(file: FileContents) {\n    const { headerRenderMode = 'default' } = this.options;\n    return createFileHeaderElement({\n      fileOrDiff: file,\n      mode: headerRenderMode,\n    });\n  }\n\n  public renderFullHTML(result: FileRenderResult): string {\n    return toHtml(this.renderFullAST(result));\n  }\n\n  public renderFullAST(\n    result: FileRenderResult,\n    children: ElementContent[] = []\n  ): HASTElement {\n    children.push(\n      createHastElement({\n        tagName: 'code',\n        children: this.renderCodeAST(result),\n        properties: { 'data-code': '' },\n      })\n    );\n    return { ...result.preAST, children };\n  }\n\n  public renderCodeAST(result: FileRenderResult): ElementContent[] {\n    const gutter = createGutterWrapper();\n    gutter.children = result.gutterAST;\n    gutter.properties.style = `grid-row: span ${result.rowCount}`;\n    const contentColumn = createContentColumn(\n      result.contentAST,\n      result.rowCount\n    );\n    return [gutter, contentColumn];\n  }\n\n  public renderPartialHTML(\n    children: ElementContent[],\n    includeCodeNode: boolean = false\n  ): string {\n    if (!includeCodeNode) {\n      return toHtml(children);\n    }\n    return toHtml(\n      createHastElement({\n        tagName: 'code',\n        children,\n        properties: { 'data-code': '' },\n      })\n    );\n  }\n\n  public async initializeHighlighter(): Promise<DiffsHighlighter> {\n    this.highlighter = await getSharedHighlighter(\n      getHighlighterOptions(this.computedLang, this.options)\n    );\n    return this.highlighter;\n  }\n\n  public onHighlightSuccess(\n    file: FileContents,\n    result: ThemedFileResult,\n    options: RenderFileOptions\n  ): void {\n    if (this.renderCache == null) {\n      return;\n    }\n    const triggerRenderUpdate =\n      this.renderCache.file !== file ||\n      !this.renderCache.highlighted ||\n      !areRenderOptionsEqual(options, this.renderCache.options);\n\n    this.renderCache = {\n      file,\n      options,\n      highlighted: true,\n      result,\n      renderRange: undefined,\n    };\n\n    if (triggerRenderUpdate) {\n      this.onRenderUpdate?.();\n    }\n  }\n\n  public onHighlightError(error: unknown): void {\n    console.error(error);\n  }\n\n  private createPreElement(totalLines: number): HASTElement {\n    const { disableLineNumbers = false, overflow = 'scroll' } = this.options;\n    return createPreElement({\n      type: 'file',\n      diffIndicators: 'none',\n      disableBackground: true,\n      disableLineNumbers,\n      overflow,\n      split: false,\n      totalLines,\n    });\n  }\n}\n\nfunction areRenderOptionsEqual(\n  optionsA: RenderFileOptions,\n  optionsB: RenderFileOptions\n): boolean {\n  return (\n    areThemesEqual(optionsA.theme, optionsB.theme) &&\n    optionsA.useTokenTransformer === optionsB.useTokenTransformer &&\n    optionsA.tokenizeMaxLineLength === optionsB.tokenizeMaxLineLength\n  );\n}\n"],"mappings":"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"}