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.