UNPKG

2.63 kBJavaScriptView Raw
1/* @flow */
2
3import RenderStream from './render-stream'
4import { createWriteFunction } from './write'
5import { createRenderFunction } from './render'
6import TemplateRenderer from './template-renderer/index'
7import type { ClientManifest } from './template-renderer/index'
8
9export type Renderer = {
10 renderToString: (component: Component, context: any, cb: any) => void;
11 renderToStream: (component: Component, context?: Object) => stream$Readable;
12};
13
14type RenderCache = {
15 get: (key: string, cb?: Function) => string | void;
16 set: (key: string, val: string) => void;
17 has?: (key: string, cb?: Function) => boolean | void;
18};
19
20export type RenderOptions = {
21 modules?: Array<(vnode: VNode) => ?string>;
22 directives?: Object;
23 isUnaryTag?: Function;
24 cache?: RenderCache;
25 template?: string;
26 inject?: boolean;
27 basedir?: string;
28 shouldPreload?: Function;
29 clientManifest?: ClientManifest;
30 runInNewContext?: boolean | 'once';
31};
32
33export function createRenderer ({
34 modules = [],
35 directives = {},
36 isUnaryTag = (() => false),
37 template,
38 inject,
39 cache,
40 shouldPreload,
41 clientManifest
42}: RenderOptions = {}): Renderer {
43 const render = createRenderFunction(modules, directives, isUnaryTag, cache)
44 const templateRenderer = new TemplateRenderer({
45 template,
46 inject,
47 shouldPreload,
48 clientManifest
49 })
50
51 return {
52 renderToString (
53 component: Component,
54 context: any,
55 done: any
56 ): void {
57 if (typeof context === 'function') {
58 done = context
59 context = {}
60 }
61 if (context) {
62 templateRenderer.bindRenderFns(context)
63 }
64 let result = ''
65 const write = createWriteFunction(text => {
66 result += text
67 return false
68 }, done)
69 try {
70 render(component, write, context, () => {
71 if (template) {
72 result = templateRenderer.renderSync(result, context)
73 }
74 done(null, result)
75 })
76 } catch (e) {
77 done(e)
78 }
79 },
80
81 renderToStream (
82 component: Component,
83 context?: Object
84 ): stream$Readable {
85 if (context) {
86 templateRenderer.bindRenderFns(context)
87 }
88 const renderStream = new RenderStream((write, done) => {
89 render(component, write, context, done)
90 })
91 if (!template) {
92 return renderStream
93 } else {
94 const templateStream = templateRenderer.createStream(context)
95 renderStream.on('error', err => {
96 templateStream.emit('error', err)
97 })
98 renderStream.pipe(templateStream)
99 return templateStream
100 }
101 }
102 }
103}