1 |
|
2 |
|
3 | import RenderStream from './render-stream'
|
4 | import { createWriteFunction } from './write'
|
5 | import { createRenderFunction } from './render'
|
6 | import TemplateRenderer from './template-renderer/index'
|
7 | import type { ClientManifest } from './template-renderer/index'
|
8 |
|
9 | export type Renderer = {
|
10 | renderToString: (component: Component, context: any, cb: any) => void;
|
11 | renderToStream: (component: Component, context?: Object) => stream$Readable;
|
12 | };
|
13 |
|
14 | type 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 |
|
20 | export 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 |
|
33 | export 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 | }
|