diff --git a/src/dom/createRenderer.js b/src/dom/createRenderer.js new file mode 100644 index 0000000..c674f46 --- /dev/null +++ b/src/dom/createRenderer.js @@ -0,0 +1,36 @@ +import createElement from './createElement' +import {diffNode} from '../diff' +import patch from './patch' +import uid from 'uid' + +/** + * Create a DOM renderer using a container element. Everything will be rendered + * inside of that container. Returns a function that accepts new state that can + * replace what is currently rendered. + */ + +export default function createDOMRenderer (container, dispatch) { + let oldVnode = null + let node = null + let path = uid() + + let update = (newVnode, context) => { + let changes = diffNode(oldVnode, newVnode, path) + node = changes.reduce(patch(dispatch, context), node) + oldVnode = newVnode + return node + } + + let create = (vnode, context) => { + node = createElement(vnode, path, dispatch, context) + if (container) container.appendChild(node) + oldVnode = vnode + return node + } + + return (vnode, context = {}) => { + return node !== null + ? update(vnode, context) + : create(vnode, context) + } +} diff --git a/src/dom/index.js b/src/dom/index.js index c674f46..09b0bf7 100644 --- a/src/dom/index.js +++ b/src/dom/index.js @@ -1,36 +1,9 @@ +import createRenderer from './createRenderer' import createElement from './createElement' -import {diffNode} from '../diff' import patch from './patch' -import uid from 'uid' -/** - * Create a DOM renderer using a container element. Everything will be rendered - * inside of that container. Returns a function that accepts new state that can - * replace what is currently rendered. - */ - -export default function createDOMRenderer (container, dispatch) { - let oldVnode = null - let node = null - let path = uid() - - let update = (newVnode, context) => { - let changes = diffNode(oldVnode, newVnode, path) - node = changes.reduce(patch(dispatch, context), node) - oldVnode = newVnode - return node - } - - let create = (vnode, context) => { - node = createElement(vnode, path, dispatch, context) - if (container) container.appendChild(node) - oldVnode = vnode - return node - } - - return (vnode, context = {}) => { - return node !== null - ? update(vnode, context) - : create(vnode, context) - } +export default { + createRenderer, + createElement, + patch } diff --git a/src/string/index.js b/src/string/index.js index 3f4ab9e..f6dd550 100644 --- a/src/string/index.js +++ b/src/string/index.js @@ -1,57 +1,5 @@ -import {isText, isValidAttribute, isThunk} from '../shared/utils' +import renderString from './renderString' -/** - * Turn an object of key/value pairs into a HTML attribute string. This - * function is responsible for what attributes are allowed to be rendered and - * should handle any other special cases specific to deku. - */ - -function attributesToString (attributes) { - var str = '' - for (var name in attributes) { - let value = attributes[name] - if (name === 'innerHTML') continue - if (isValidAttribute(value)) str += (' ' + name + '="' + attributes[name] + '"') - } - return str -} - -/** - * Render a virtual element to a string. You can pass in an option state context - * object that will be given to all components. - */ - -export default function renderString (element, context, path = '0') { - if (isText(element)) { - return element.nodeValue - } - - if (isThunk(element)) { - let { props, data, children } = element - let { render } = data - let output = render({ - children, - props, - path, - context - }) - return renderString( - output, - context, - path - ) - } - - let {attributes, type, children} = element - let innerHTML = attributes.innerHTML - let str = '<' + type + attributesToString(attributes) + '>' - - if (innerHTML) { - str += innerHTML - } else { - str += children.map((child, i) => renderString(child, context, path + '.' + (child.key == null ? i : child.key))).join('') - } - - str += '' - return str +export default { + renderString } diff --git a/src/string/renderString.js b/src/string/renderString.js new file mode 100644 index 0000000..3f4ab9e --- /dev/null +++ b/src/string/renderString.js @@ -0,0 +1,57 @@ +import {isText, isValidAttribute, isThunk} from '../shared/utils' + +/** + * Turn an object of key/value pairs into a HTML attribute string. This + * function is responsible for what attributes are allowed to be rendered and + * should handle any other special cases specific to deku. + */ + +function attributesToString (attributes) { + var str = '' + for (var name in attributes) { + let value = attributes[name] + if (name === 'innerHTML') continue + if (isValidAttribute(value)) str += (' ' + name + '="' + attributes[name] + '"') + } + return str +} + +/** + * Render a virtual element to a string. You can pass in an option state context + * object that will be given to all components. + */ + +export default function renderString (element, context, path = '0') { + if (isText(element)) { + return element.nodeValue + } + + if (isThunk(element)) { + let { props, data, children } = element + let { render } = data + let output = render({ + children, + props, + path, + context + }) + return renderString( + output, + context, + path + ) + } + + let {attributes, type, children} = element + let innerHTML = attributes.innerHTML + let str = '<' + type + attributesToString(attributes) + '>' + + if (innerHTML) { + str += innerHTML + } else { + str += children.map((child, i) => renderString(child, context, path + '.' + (child.key == null ? i : child.key))).join('') + } + + str += '' + return str +} diff --git a/test/createDOMRenderer.js b/test/createDOMRenderer.js index 13604b3..509a20b 100644 --- a/test/createDOMRenderer.js +++ b/test/createDOMRenderer.js @@ -1,6 +1,6 @@ /** @jsx h */ import test from 'tape' -import createDOMRenderer from '../src/dom' +import createDOMRenderer from '../src/dom/createRenderer' import h from '../src/element' test('rendering elements', t => { diff --git a/test/renderString.js b/test/renderString.js index 04b680f..273579e 100644 --- a/test/renderString.js +++ b/test/renderString.js @@ -1,6 +1,6 @@ /** @jsx h */ import test from 'tape' -import render from '../src/string' +import render from '../src/string/renderString' import h from '../src/element' test('render to a string', t => { diff --git a/test/thunk.js b/test/thunk.js index ac561fd..af33fa8 100644 --- a/test/thunk.js +++ b/test/thunk.js @@ -1,5 +1,5 @@ /** @jsx h */ -import createDOMRenderer from '../src/dom' +import createDOMRenderer from '../src/dom/createRenderer' import h from '../src/element' import test from 'tape' import trigger from 'trigger-event'