Last active
August 25, 2016 19:47
-
-
Save dcolucci/fbe4908bb2ffae6e9b6e7c8dd5f78a6d to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import React from 'react'; | |
| import JsonML from 'jsonml.js/lib/utils'; | |
| import isFunction from 'lodash.isfunction'; | |
| import { | |
| reactConverters, | |
| toStyleObject | |
| } from './utils'; | |
| /***************** | |
| * Better way to do this? | |
| * Perhaps there is something closer to `React.isVoidElement(element)`? | |
| *****************/ | |
| const VOID_ELEMENTS = [ 'br', 'hr' ]; | |
| /** | |
| * JsonmlToReact class | |
| */ | |
| export default class JsonmlToReact { | |
| /** | |
| * Constructor | |
| * @param {Object} converters - Aditional converters | |
| */ | |
| constructor(converters) { | |
| this.converters = Object.assign({}, reactConverters, converters); | |
| } | |
| /** | |
| * Visit JsonML nodes recursively and convert to React | |
| * @param {Array} node - JsonML structure | |
| * @param {Number} index - Node index to be used as key | |
| * @param {Object} [data] - Data to be passed to the converters | |
| * @returns {Object} React component | |
| * @private | |
| */ | |
| _visit(node, index, data) { | |
| // Is leaf node | |
| if (!node || typeof node === 'string') { | |
| return node; | |
| } | |
| let attrs = Object.assign({ key: index }, JsonML.getAttributes(node)); | |
| if (attrs.class) { | |
| attrs.className = attrs.class; | |
| attrs.class = undefined; | |
| } | |
| if (attrs.style) { | |
| attrs.style = toStyleObject(attrs.style); | |
| } | |
| const tag = JsonML.getTagName(node); | |
| const children = JsonML.getChildren(node) || []; | |
| const converter = this.converters[tag]; | |
| const result = isFunction(converter) ? converter(attrs, data) : {}; | |
| const type = result.type || tag; | |
| const props = result.props || attrs; | |
| /************************ | |
| * create a really vanilla element without props, etc | |
| * maybe this method logic can be rearranged so this can be done earlier | |
| * for better performance | |
| ************************/ | |
| if (VOID_ELEMENTS.indexOf(type) > -1) { | |
| return React.createElement(type); | |
| } | |
| // reassign key in case `converter` removed it | |
| props.key = props.key || index; | |
| return React.createElement(type, props, children.map((child, index) => this._visit(child, index, data))); | |
| } | |
| /** | |
| * Convert JsonML to React component | |
| * @param {Array} jsonml - JsonML structure | |
| * @param {Object} [data] - Data to be passed to the converters | |
| * @returns {Object} React component | |
| */ | |
| convert(jsonml, data) { | |
| return this._visit(jsonml, 0, data); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment