From 95c1ed7a67cc08a6c7ebf3f5b78bd791e20db6ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simen=20S=C3=A6grov?= Date: Thu, 21 Sep 2017 16:57:37 +0200 Subject: [PATCH 1/5] Add support for mixed rendering Mixed rendering is a mode that works like shallow rendering, but where you can specify a list of components you want to render even tho they are deeply nested. --- src/index.d.ts | 2 ++ src/index.js | 25 ++++++++++++-- test/mixedRender.js | 84 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 108 insertions(+), 3 deletions(-) create mode 100644 test/mixedRender.js diff --git a/src/index.d.ts b/src/index.d.ts index c69419c6..0bc7e113 100644 --- a/src/index.d.ts +++ b/src/index.d.ts @@ -5,10 +5,12 @@ declare module render { shallow:boolean; xml:boolean; pretty:boolean; + alwaysRenderedComponents: Array[String]; } function render(vnode:VNode, context?:any, options?:Options):string; function shallowRender(vnode:VNode, context?:any):string; + function mixedRender(vnode: VNode, alwaysRenderedComponents: Array[String], context?: any): string; } export = render; diff --git a/src/index.js b/src/index.js index b2de14cd..14800590 100644 --- a/src/index.js +++ b/src/index.js @@ -48,12 +48,27 @@ renderToString.render = renderToString; let shallowRender = (vnode, context) => renderToString(vnode, context, SHALLOW); +/** + * Only render elements, leaving Components inline as `` + * except those specified in fullyRenderedComponents. + * This method is just a convenience alias for `render(vnode, context, { shallow:true, alwaysRenderedComponented: [] })` + * @param {VNode} vnode JSX VNode to render. + * @param {Array} alwaysRenderedComponents List of components that should be rendered with shallow rendering + * @param {Object} [context={}] Optionally pass an initial context object through the render path. + */ +let mixedRender = (vnode, alwaysRenderedComponents = [], context) => { + const opts = Object.assign({ alwaysRenderedComponents }, SHALLOW); + return renderToString(vnode, context, opts); +}; + + /** The default export is an alias of `render()`. */ export default function renderToString(vnode, context, opts, inner, isSvgMode) { let { nodeName, attributes, children } = vnode || EMPTY, isComponent = false; context = context || {}; opts = opts || {}; + opts.alwaysRenderedComponents = opts.alwaysRenderedComponents || []; let pretty = opts.pretty, indentChar = typeof pretty==='string' ? pretty : '\t'; @@ -69,9 +84,12 @@ export default function renderToString(vnode, context, opts, inner, isSvgMode) { // components if (typeof nodeName==='function') { + let componentName = getComponentName(nodeName); isComponent = true; - if (opts.shallow && (inner || opts.renderRootComponent===false)) { - nodeName = getComponentName(nodeName); + if (opts.shallow && + (inner || opts.renderRootComponent===false) && + !opts.alwaysRenderedComponents.includes(componentName)) { + nodeName = componentName; } else { let props = getNodeProps(vnode), @@ -235,5 +253,6 @@ renderToString.shallowRender = shallowRender; export { renderToString as render, renderToString, - shallowRender + shallowRender, + mixedRender }; diff --git a/test/mixedRender.js b/test/mixedRender.js new file mode 100644 index 00000000..e2d543fd --- /dev/null +++ b/test/mixedRender.js @@ -0,0 +1,84 @@ +import { mixedRender } from '../src'; +import { h, Component } from 'preact'; +import chai, { expect } from 'chai'; +import { spy, match } from 'sinon'; +import sinonChai from 'sinon-chai'; +chai.use(sinonChai); + +describe('mixedRender()', () => { + it('should not render nested components when not white listed', () => { + let Test = spy( ({ foo, children }) =>
test child{ children }
); + Test.displayName = 'Test'; + + let rendered = mixedRender( +
+ asdf +
+ ); + + expect(rendered).to.equal(`
asdf
`); + expect(Test).not.to.have.been.called; + }); + + it('should always render root component', () => { + let Test = spy( ({ foo, children }) =>
test child{ children }
); + Test.displayName = 'Test'; + + let rendered = mixedRender( + + asdf + + ); + + expect(rendered).to.equal(`
test childasdf
`); + expect(Test).to.have.been.calledOnce; + }); + + it('should render nested components when they are white listed', () => { + let Test = spy( ({ foo, children }) =>
test child{ children }
); + Test.displayName = 'Test'; + + let rendered = mixedRender( +
+ asdf +
+ , ['Test']); + + expect(rendered).to.equal(`
test childasdf
`); + expect(Test).to.have.been.called; + }); + + it('should not render nested components inside a whitelisted component', () => { + let Test = spy( ({ foo, children }) =>
test child{ children }
); + let Ignored = spy( ({ title, children }) =>

This {title} should not be rendered

); + Test.displayName = 'Test'; + Ignored.displayName = 'Ignored'; + + let rendered = mixedRender( +
+ +
+ , ['Test']); + + expect(rendered).to.equal(`
test child
`); + expect(Test).to.have.been.called; + expect(Ignored).to.not.have.been.called; + }); + + it('should render deeply nested components when all are white listed', () => { + let Test = spy( ({ foo, children }) =>
test child{ children }
); + let Ignored = spy( ({ title, children }) =>

This {title} should be rendered

); + Test.displayName = 'Test'; + Ignored.displayName = 'Ignored'; + + let rendered = mixedRender( +
+ +
+ , ['Test', 'Ignored']); + + expect(rendered).to.equal(`
test child

This FooBarTitle should be rendered

`); + expect(Test).to.have.been.called; + expect(Ignored).to.have.been.called; + }); +}); From 7873f3f27600450601352bf781e6424d2945ffad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simen=20S=C3=A6grov?= Date: Fri, 22 Sep 2017 09:51:53 +0200 Subject: [PATCH 2/5] Set version and yr package name --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index ea2a6310..a2ae9efe 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { - "name": "preact-render-to-string", + "name": "@yr/preact-render-to-string", "amdName": "preactRenderToString", - "version": "3.6.3", + "version": "4.0.0", "description": "Render JSX to an HTML string, with support for Preact components.", "main": "dist/index.js", "jsnext:main": "src/index.js", From ce770383ee5fcc8d3db58c0d42084c38840fd4d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simen=20S=C3=A6grov?= Date: Fri, 22 Sep 2017 10:16:21 +0200 Subject: [PATCH 3/5] Fix package.json with correct urls --- package.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index a2ae9efe..67636f80 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@yr/preact-render-to-string", "amdName": "preactRenderToString", - "version": "4.0.0", + "version": "4.0.1", "description": "Render JSX to an HTML string, with support for Preact components.", "main": "dist/index.js", "jsnext:main": "src/index.js", @@ -20,15 +20,15 @@ "universal", "isomorphic" ], - "author": "Jason Miller ", + "author": "Jason Miller , Simen Sægrov ", "license": "MIT", "typings": "src/index.d.ts", "repository": { "type": "git", - "url": "https://github.com/developit/preact-render-to-string.git" + "url": "https://github.com/yr/preact-render-to-string.git" }, "bugs": { - "url": "https://github.com/developit/preact-render-to-string/issues" + "url": "https://github.com/yr/preact-render-to-string/issues" }, "homepage": "https://github.com/developit/preact-render-to-string", "peerDependencies": { From fe0d405da2c567e3af508d5aaa00b17b100e02c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simen=20S=C3=A6grov?= Date: Fri, 22 Sep 2017 11:39:39 +0200 Subject: [PATCH 4/5] Export mixedRender function --- src/index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/index.js b/src/index.js index 14800590..090dd101 100644 --- a/src/index.js +++ b/src/index.js @@ -248,6 +248,7 @@ function getFallbackComponentName(component) { return name; } renderToString.shallowRender = shallowRender; +renderToString.mixedRender = mixedRender; export { From 4837e7bf4766fa4cadc3253103e0bcf34772114b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simen=20S=C3=A6grov?= Date: Fri, 22 Sep 2017 11:40:09 +0200 Subject: [PATCH 5/5] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 67636f80..14891fb2 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@yr/preact-render-to-string", "amdName": "preactRenderToString", - "version": "4.0.1", + "version": "4.0.2", "description": "Render JSX to an HTML string, with support for Preact components.", "main": "dist/index.js", "jsnext:main": "src/index.js",