Create Declarative frameworks that output tree structures with properties (e.g. ArtReact)
npm install art-object-tree-factory> simple, elegant and fast declarative tree generation
Fast, easy way to create declarative APIs for data-structures which consist of per-node-properties and per-node-ordered-children.
An object-tree-factory (OTF) is powerful tool for creating declarative programmatic structures or DSLs. OTFs are useful because they accept simplify a complex set of descriptive inputs into a simple set of outputs:
an arbitrary list of plain-objects, a function which accepts an arbitrary
``
IN:
Arguments are compacted and flattened
The resulting list of arguments can be any combination of:
plainObjects for props (merged in the order they appear)
other objects which become the 'children'
OUT:
object-tree-node generated by the nodeFactory
`
Object-tree-factories excel when used in a reduced-syntax language such as CaffeineScript (or CoffeeScript). For example, you can express HTML much more compactly:
`coffeescriptCaffeineScript
import &ArtHtmlFactory
console.log
Html
Head
Meta name: "viewport" content: "user-scalable=no, width=device-width, initial-scale=1.0, viewport-fit=cover"
Meta name: "apple-mobile-web-app-capable" content: "yes"
Meta name: "apple-mobile-web-app-status-bar-style" content: "black"
Meta name: "format-detection" content: "telephone=no"
Body
H1 "Art.ObjectTreeFactory"
P "simple, elegant, fast declarative tree generation library"
`
Outputs: simple, elegant, fast declarative tree generation library
`html`
Art.ObjectTreeFactory
Even in JavaScript, object-tree-factories are an effective way to express HTML programmatically:
`javascript
import {Html, Head, Meta, Body, H1, P} from "art-html-factory"
console.log(
Html(
Head(
Meta({
name: "viewport",
content: "user-scalable=no, width=device-width, initial-scale=1.0, viewport-fit=cover"
}),
Meta({ name: "apple-mobile-web-app-capable", content: "yes" }),
Meta({ name: "apple-mobile-web-app-status-bar-style", content: "black" }),
Meta({ name: "format-detection", content: "telephone=no" })
),
Body(
H1("Art.ObjectTreeFactory"),
P("simple, elegant, fast declarative tree generation library")
)
)
);
`
You can easily create all your React factories:
`coffeescriptCaffeineScript
import &ArtStandardLib, &ArtObjectTreeFactory, &React
createObjectTreeFactories
:Div :Link
(nodeName, props, children) -> createElement nodeName, props, children...
`
Use:
`coffeescript`CaffeineScript
React Function Component in
(props) ->
Div
"Everything you need "
Link "is here" src: "http://wikipedia.org"
Create one object-tree-factory.
`typescript`
createObjectTreeFactory = (...inputs) => objectTreeFactory
> Note: createObjectTreeFactory's inputs can appear in any order:`
* nodeFactory:
typescript`
(props `
* nodeClass:
typescript`
class Foo {
constructor(props
* options:
* inspectedName: string
for introspection:
Factory.getName() == inspectedName
* class: alternative way to pass the nodeClass
* bind:
list of method-names to bind from nodeClass onto the factory
(note: nodeClass must be set)
* mergePropsInto: (intoProps
* preprocessElement: (inputElement, Factory) -> inputElement
called on every input element, whether props, null, undefined or any other value. Note: you can return any value you wish, but don't mutate inputElement.
Example:
`coffeescript
class TreeNode
constructor: (@props, @children) ->
toObjects: ->
TreeNode: {}
@props
children: @children && array child in @children
child.toObjects?() || child
Node = createObjectTreeFactory TreeNode
commonProps = color: "black"
a = Node
commonProps
height: "100"
width: "200"
"Does this work for you?"
Node commonProps, source: "images/piglet.png"
"This works for me!"
Node "Ka-blam!"
b = TreeNode:
props:
color: :black
height: :100
width: :200
children: []
"Does this work for you?"
TreeNode:
props:
color: :black
source: :images/piglet.png
children: undefined
"This works for me!"
TreeNode: props: undefined, children: [] "Ka-blam!"
JSON.stringify(a.toObjects()) === JSON.stringify(b)
`
Create many object-tree-factories:
`javascript`
createObjectTreeFactories = (...inputs) => factoryMap
> note: createObjectTreeFactories is itself an object-tree-factory! That means you can pass in arguments in any order. Props (options) are merged down. Strings are parsed into words and concatenated.
IN:
* options : passed directly to createObjectTreeFactory as optionsnodeTypeNames
* strings are parsed into words and concatenatednodeFactory <(nodeTypeName, props, children) -> node>
* called each time a factory is used to construct the nodenodeFactoryFactory <(nodeTypeName) -> (props, children) -> node>
* called once for each nodeTypeName to generate a factory for that node-type
Required: You must have exactly one nodeFactory or one nodeFactoryFactory.
OUT:
* factories is a map from nodeTypeNames (upperCamelCased) to factories returned from createObjectTreeFactory
Example:
`coffeescriptAn example class
class TagNode
constructor: (@tag, @props, @children) ->
# Output an HTML string
toString: (indent = '')->
"<#{@tag}"
+ if @props
' ' +
array v, k in @props
"#{k}='#{v}'"
.join ' '
else ''
+ ">"
+ if @children
indent2 = indent + ' '
"\n" + indent2 +
array child in @children
child.toString indent2
.join "\n#{indent2}"
+ "\n"
else ''
+ "#{indent}#{@tag}>"
##############################
Create Object Tree Factories
##############################
{Html, Head, Body, Div, P, B} = createObjectTreeFactories
:html :head :body :div :p :b
TagNode
##########################
Create and output a Tree
##########################
console.log Html Head Body
Div
class: "row"
Div
class: "col"
P
"This is truly "
B "fantastic"
"!"
Div
class: "col"
P "What do you think?"
`
The output:
`html``
This is truly
fantastic
!
What do you think?