diff --git a/src/reconciler.js b/src/reconciler.js index 24782ce..45eff5f 100644 --- a/src/reconciler.js +++ b/src/reconciler.js @@ -1 +1,29 @@ -export function render(element, container) {} +export function render(element, parentDom) { + const { type, props } = element; + + // Create DOM element + const isTextElement = type === "TEXT ELEMENT"; + const dom = isTextElement + ? document.createTextNode("") + : document.createElement(type); + + // Add event listeners + const isListener = name => name.startsWith("on"); + Object.keys(props).filter(isListener).forEach(name => { + const eventType = name.toLowerCase().substring(2); + dom.addEventListener(eventType, props[name]); + }); + + // Set properties + const isAttribute = name => !isListener(name) && name != "children"; + Object.keys(props).filter(isAttribute).forEach(name => { + dom[name] = props[name]; + }); + + // Render children + const childElements = props.children || []; + childElements.forEach(childElement => render(childElement, dom)); + + // Append to parent + parentDom.appendChild(dom); +} diff --git a/test/00.render-dom-elements.test.js b/test/00.render-dom-elements.test.js new file mode 100644 index 0000000..3379320 --- /dev/null +++ b/test/00.render-dom-elements.test.js @@ -0,0 +1,70 @@ +import test from "ava"; +import browserEnv from "browser-env"; +import { render } from "../src/didact"; + +// Create document global var +browserEnv(["document"]); + +test.beforeEach(t => { + const root = document.createElement("div"); + document.body.appendChild(root); + t.context.root = root; +}); + +test.afterEach.always(t => { + const root = t.context.root; + root.innerHTML = ""; + document.body.removeChild(root); +}); + +test("render div", t => { + const root = t.context.root; + const element = { + type: "div", + props: {} + }; + render(element, root); + t.is(root.innerHTML, "
"); +}); + +test("render div with children", t => { + const root = t.context.root; + const element = { + type: "div", + props: { + children: [ + { type: "b", props: {} }, + { type: "a", props: { href: "foo" } } + ] + } + }; + render(element, root); + t.is(root.innerHTML, '
'); +}); + +test("render div with props", t => { + const root = t.context.root; + const element = { + type: "div", + props: { id: "foo" } + }; + render(element, root); + t.is(root.innerHTML, '
'); +}); + +test("render span with text child", t => { + const root = t.context.root; + const element = { + type: "span", + props: { + children: [ + { + type: "TEXT ELEMENT", + props: { nodeValue: "Foo" } + } + ] + } + }; + render(element, root); + t.is(root.innerHTML, "Foo"); +});