JSON Schema describes web component
Example
given
{
"node": "div",
"props": {
"style": {
"color": "red"
}
},
"children": [
{
"node": "p",
"children": {
"node": "span",
"children": "Text"
}
}
]
}
out
<div style="color: red">
<p><span>Text</span></p>
</div>
$ npm i @fratercula/puffin
simple
import React from 'react'
import { render } from 'react-dom'
import { C } from '@fratercula/puffin'
const schema = {
"node": "p",
"children": [
{
"node": "span",
"children": "span"
}
]
}
render((
<C {...schema} />
), document.getElementById('root'))
use components
import React from 'react'
import { render } from 'react-dom'
import { C } from '@fratercula/puffin'
import * as antd from 'antd'
const schema = {
"node": "Carousel", // antd Carousel
"props": {
"autoplay": true
},
"children": [
{
"node": "div",
"children": 1
},
{
"node": "div",
"children": 2
}
]
}
render((
<C {...schema} components={antd} />
), document.getElementById('root'))
function callback
import React from 'react'
import { render } from 'react-dom'
import { C } from '@fratercula/puffin'
import * as antd from 'antd'
const schema = {
"node": "Carousel", // antd Carousel
"props": {
"afterChange": ":afterChange", // :key
},
"children": [
{
"node": "div",
"children": 2
}
]
}
render((
<C
{...schema}
components={antd}
onEvent={(key, args) => {
console.log(key, args)
}}
/>
), document.getElementById('root'))
{
/*
first letter lowercase, it is HTML tag
first letter uppercase, it is React component
example: node: 'Tabs'
*/
node: 'div',
/*
tag props or component props
example: style: {}, src: 'img/path'
*/
props: {},
/*
component recursive children
array, object, string, boolean, number
example: children: [{
node: 'p',
children: {
node: 'span',
children: 'span',
},
}]
*/
children: [],
}
Puffin provides helper function p
for parsing schema props
import { p } from '@fratercula/puffin'
const props = {
style: {
color: 'red',
},
tab: {
node: 'Icon',
props: {
type: 'link',
},
},
}
const parsed = p(props)
/*
{
style: {
color: 'red',
},
tab: (<Icon type="link" />)
}
*/
basic
// given
{
style: {
color: 'red',
},
href: 'link/to',
}
// out
<... style="color: red" href="link/to" />
React component
// given
{
tab: {
node: 'Icon',
props: {
type: 'link',
},
},
}
// out
<... tab={(<Icon type="link" />)} />
function
// given
{
tab: {
arguments: ['text', 'record'],
node: 'div',
children: '${text}, ${record.name}',
},
}
// out
<... tab={(text, record) => {
return (<div>{`${text}, ${record.name}`}</div>)
}} />
callback function
import { C } from '@fratercula/puffin'
<C onEvent={(key, args) => console.log(key, args)} />
// given
{
afterChange: ':afterChange', // :key
}
// out
<... afterChange={args => onEvent('afterChange', args)} />
import React, { Component } from 'react'
import { Timeline } from 'antd'
import { C, p } from '@fratercula/puffin'
class Custom extends Component {
static puffinParse = false // disable puffin parse data
render() {
const { props, children } = this.props
const {
pending,
mode,
other,
...rest
} = props
const parsed = p(other)
return (
<Timeline
{...rest}
pending={pending}
mode={mode}
other={parsed}
>
{
children.map((item, i) => {
const { props: childProps = {} } = item
const { dot, color, ...childRest } = childProps
const node = { ...item, prop: childRest, node: 'div' }
return (
<Timeline.Item
key={i}
color={color}
dot={dot ? (<C {...dot} />) : undefined}
>
<C {...node} />
</Timeline.Item>
)
})
}
</Timeline>
)
}
}
function Another({ node, props, children }) {
// ...
}
Another.puffinParse = false // not parse, use origin data
export default { Custom, Another }
# install `falco` global
$ npm i @fratercula/falco -g
# start
$ npm start
# build
$ npm run build
# lint
$ npm run lint
MIT
Puffin