packages/server-renderer/src/create-renderer.ts TYPESCRIPT 165 lines View on github.com → Search inside
1import RenderStream from './render-stream'2import { createWriteFunction } from './write'3import { createRenderFunction } from './render'4import { createPromiseCallback } from './util'5import TemplateRenderer from './template-renderer/index'6import type { ClientManifest } from './template-renderer/index'7import type { Component } from 'types/component'8import VNode from 'core/vdom/vnode'9import { Readable } from 'stream'1011export type Renderer = {12  renderToString: (13    component: Component,14    context?: any,15    cb?: any16  ) => Promise<string> | undefined17  renderToStream: (component: Component, context?: Object) => Readable18}1920type RenderCache = {21  get: (key: string, cb?: Function) => string | void22  set: (key: string, val: string) => void23  has?: (key: string, cb?: Function) => boolean | void24}2526export type RenderOptions = {27  modules?: Array<(vnode: VNode) => string | null>28  directives?: Object29  isUnaryTag?: Function30  cache?: RenderCache31  template?:32    | string33    | ((content: string, context: any) => string | Promise<string>)34  inject?: boolean35  basedir?: string36  shouldPreload?: Function37  shouldPrefetch?: Function38  clientManifest?: ClientManifest39  serializer?: Function40  runInNewContext?: boolean | 'once'41}4243export function createRenderer({44  modules = [],45  directives = {},46  isUnaryTag = () => false,47  template,48  inject,49  cache,50  shouldPreload,51  shouldPrefetch,52  clientManifest,53  serializer54}: RenderOptions = {}): Renderer {55  const render = createRenderFunction(modules, directives, isUnaryTag, cache)56  const templateRenderer = new TemplateRenderer({57    template,58    inject,59    // @ts-expect-error60    shouldPreload,61    // @ts-expect-error62    shouldPrefetch,63    clientManifest,64    serializer65  })6667  return {68    renderToString(69      component: Component,70      context?: any,71      cb?: any72    ): Promise<string> {73      if (typeof context === 'function') {74        cb = context75        context = {}76      }77      if (context) {78        templateRenderer.bindRenderFns(context)79      }8081      // no callback, return Promise82      let promise83      if (!cb) {84        ;({ promise, cb } = createPromiseCallback())85      }8687      let result = ''88      const write = createWriteFunction(text => {89        result += text90        return false91      }, cb)92      try {93        // @ts-expect-error TODO improve94        render(component, write, context, err => {95          if (err) {96            return cb(err)97          }98          if (context && context.rendered) {99            context.rendered(context)100          }101          if (template) {102            try {103              const res = templateRenderer.render(result, context)104              if (typeof res !== 'string') {105                // function template returning promise106                res.then(html => cb(null, html)).catch(cb)107              } else {108                cb(null, res)109              }110            } catch (e: any) {111              cb(e)112            }113          } else {114            cb(null, result)115          }116        })117      } catch (e: any) {118        cb(e)119      }120121      return promise122    },123124    renderToStream(component: Component, context?: Object): Readable {125      if (context) {126        templateRenderer.bindRenderFns(context)127      }128      const renderStream = new RenderStream((write, done) => {129        // @ts-expect-error130        render(component, write, context, done)131      })132      if (!template) {133        // @ts-expect-error134        if (context && context.rendered) {135          // @ts-expect-error136          const rendered = context.rendered137          renderStream.once('beforeEnd', () => {138            rendered(context)139          })140        }141        return renderStream142      } else if (typeof template === 'function') {143        throw new Error(144          `function template is only supported in renderToString.`145        )146      } else {147        const templateStream = templateRenderer.createStream(context)148        renderStream.on('error', err => {149          templateStream.emit('error', err)150        })151        renderStream.pipe(templateStream)152        //@ts-expect-error153        if (context && context.rendered) {154          //@ts-expect-error155          const rendered = context.rendered156          renderStream.once('beforeEnd', () => {157            rendered(context)158          })159        }160        return templateStream161      }162    }163  }164}

Findings

✓ No findings reported for this file.

Get this view in your editor

Same data, no extra tab — call code_get_file + code_get_findings over MCP from Claude/Cursor/Copilot.