npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

art-object-tree-factory

v2.2.11

Published

Create Declarative frameworks that output tree structures with properties (e.g. ArtReact)

Downloads

629

Readme

Art.ObjectTreeFactory

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.

The Object Tree Factory

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

<function>: objectTreeFactory = ->
  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

Example ArtHtmlFactory

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:

# CaffeineScript
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:

<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">
  </head>
  <body>
    <h1>Art.ObjectTreeFactory</h1>
    <p>simple, elegant, fast declarative tree generation library</p>
  </body>
</html>

Even in JavaScript, object-tree-factories are an effective way to express HTML programmatically:

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")
    )
  )
);

Example: React

You can easily create all your React factories:

# CaffeineScript
import &ArtStandardLib, &ArtObjectTreeFactory, &React

createObjectTreeFactories
  :Div :Link
  (nodeName, props, children) -> createElement nodeName, props, children...

Use:

# CaffeineScript
# React Function Component in
(props) ->
  Div
    "Everything you need "
    Link "is here" src: "http://wikipedia.org"

API

createObjectTreeFactory

Create one object-tree-factory.

createObjectTreeFactory = (...inputs) => objectTreeFactory

Note: createObjectTreeFactory's inputs can appear in any order:

  • nodeFactory:

    (props <Object>, children <Array>) => anything
  • nodeClass:

    class Foo {
      constructor(props <Object>, children <Array>) {}
    }
  • options: <Object>

    • inspectedName: string for introspection: Factory.getName() == inspectedName

    • class: alternative way to pass the nodeClass

    • bind: <String or Array<String>> list of method-names to bind from nodeClass onto the factory (note: nodeClass must be set)

    • mergePropsInto: (intoProps <Object>, fromProps <Object>) -> custom function to merge fromProps into intoProps. This function is only called if there are two or more props-objects. If so, it will be called for every props object passed into the factory. However, since it won't be called if there is exactly one props object, it should not be relied upon to preprocess props. Note: it's safe to mutate intoProps, but NOT safe to mutate fromProps.

    • 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:

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)

createObjectTreeFactories

Create many object-tree-factories:

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 <Object>: passed directly to createObjectTreeFactory as options
  • nodeTypeNames <Strings> strings are parsed into words and concatenated
  • nodeFactory <(nodeTypeName, props, children) -> node> called each time a factory is used to construct the node
  • nodeFactoryFactory <(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 <Object> is a map from nodeTypeNames (upperCamelCased) to factories returned from createObjectTreeFactory

Example:

# An 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>
  <head>
    <body>
      <div class='row'>
        <div class='col'>
          <p>
            This is truly
            <b>
              fantastic
            </b>
            !
          </p>
        </div>
        <div class='col'>
          <p>
            What do you think?
          </p>
        </div>
      </div>
    </body>
  </head>
</html>