Comparing version 1.1.1 to 2.0.0
143
index.js
!function() { | ||
function merge(target, source) { | ||
for (var attr in source) { | ||
target[attr] = source[attr]; | ||
function merge() { | ||
var target = arguments[0]; | ||
var sources = Array.prototype.slice.call(arguments, 1); | ||
var source; | ||
for(var i = 0; i < sources.length; i++) { | ||
source = sources[i]; | ||
if (!source) { | ||
continue; | ||
} | ||
for(var attr in source) { | ||
if (typeof source[attr] !== 'undefined') { | ||
target[attr] = source[attr]; | ||
} | ||
} | ||
} | ||
@@ -42,22 +56,60 @@ | ||
function buildDescriptor(treeBuilder, target, key, attr) { | ||
if (typeof attr.setup === 'function') { | ||
attr.setup(target, key); | ||
/** | ||
* Default `Descriptor` builder | ||
* | ||
* @param {TreeNode} node - parent node | ||
* @param {String} blueprintKey - key to build | ||
* @param {Descriptor} descriptor - descriptor to build | ||
* @param {Function} defaultBuilder - default function to build this type of node | ||
* | ||
* @return undefined | ||
*/ | ||
function buildDescriptor(node, blueprintKey, descriptor /*, descriptorBuilder*/) { | ||
if (typeof descriptor.setup === 'function') { | ||
descriptor.setup(node, blueprintKey); | ||
} | ||
defineProperty(target, key, attr.value, attr.get); | ||
if (descriptor.value) { | ||
defineProperty(node, blueprintKey, descriptor.value); | ||
} else { | ||
defineProperty(node, blueprintKey, undefined, function() { | ||
return descriptor.get.call(this, blueprintKey); | ||
}); | ||
} | ||
} | ||
function buildObject(treeBuilder, target, key, attr) { | ||
var object = {}; | ||
/** | ||
* Default `Object` builder | ||
* | ||
* @param {TreeNode} node - parent node | ||
* @param {String} blueprintKey - key to build | ||
* @param {Object} blueprint - blueprint to build | ||
* @param {Function} defaultBuilder - default function to build this type of node | ||
* | ||
* @return {Array} [node, blueprint] to build | ||
*/ | ||
function buildObject(node, blueprintKey, blueprint /*, defaultBuilder*/) { | ||
var value = {}; | ||
// Create child component | ||
defineProperty(target, key, object); | ||
defineProperty(node, blueprintKey, value); | ||
// Recursion | ||
treeBuilder.processNode(attr, object, target); | ||
// Set meta to object | ||
setMeta(value, blueprintKey); | ||
return [value, blueprint]; | ||
} | ||
function buildDefault(treeBuilder, target, key, attr) { | ||
defineProperty(target, key, attr); | ||
/** | ||
* Default builder | ||
* | ||
* @param {TreeNode} node - parent node | ||
* @param {String} blueprintKey - key to build | ||
* @param {Any} value - value to build | ||
* @param {Function} defaultBuilder - default function to build this type of node | ||
* | ||
* @return undefined | ||
*/ | ||
function buildDefault(node, blueprintKey, value /*, defaultBuilder*/) { | ||
defineProperty(node, blueprintKey, value); | ||
} | ||
@@ -79,3 +131,2 @@ | ||
// Be carefull: typeof(null) === 'object' | ||
if (typeof object === 'object' && object !== null) { | ||
@@ -86,4 +137,22 @@ return object['__parentTreeNode']; | ||
function TreeBuilder(definition, builders) { | ||
this.definition = definition; | ||
function setMeta(target, key) { | ||
Object.defineProperty(target, '__meta', { | ||
value: { | ||
key: key, | ||
type: 'node' | ||
}, | ||
configurable: false, | ||
enumerable: false | ||
}); | ||
} | ||
function meta(object) { | ||
// Be carefull: typeof(null) === 'object' | ||
if (typeof object === 'object' && object !== null) { | ||
return object['__meta']; | ||
} | ||
} | ||
function TreeBuilder(blueprint, builders) { | ||
this.blueprint = blueprint; | ||
this.builders = builders; | ||
@@ -101,3 +170,3 @@ } | ||
this.processNode({ root: this.definition }, root); | ||
this.processNode({ root: this.blueprint }, root); | ||
@@ -110,12 +179,18 @@ node = root['root']; | ||
processNode: function(definition, target, parent) { | ||
var keys = Object.keys(definition), | ||
that = this;; | ||
processNode: function(blueprintNode, target, parent) { | ||
var keys = Object.keys(blueprintNode), | ||
that = this; | ||
keys.forEach(function(key) { | ||
var attr = definition[key], | ||
builder; | ||
var blueprintAttribute = blueprintNode[key], | ||
builder, | ||
defaultBuilder, | ||
result; | ||
builder = that.builderFor(attr); | ||
builder(that, target, key, attr); | ||
builder = that.builderFor(blueprintAttribute); | ||
defaultBuilder = builderFor(blueprintAttribute); | ||
if (result = builder(target, key, blueprintAttribute, defaultBuilder)) { | ||
that.processNode(result[1], result[0], target); | ||
} | ||
}); | ||
@@ -129,2 +204,6 @@ | ||
function builderFor(value) { | ||
return DEFAULT_BUILDERS[typeOf(value)] || DEFAULT_BUILDERS['default']; | ||
} | ||
var DEFAULT_BUILDERS = { | ||
@@ -137,14 +216,10 @@ descriptor: buildDescriptor, | ||
var Ceibo = { | ||
defaults: { | ||
builder: DEFAULT_BUILDERS | ||
}, | ||
defineProperty: defineProperty, | ||
create: function(definition, options) { | ||
create: function(blueprint, options) { | ||
options = options || {}; | ||
var builder = merge(merge({}, this.defaults.builder), options.builder); | ||
var builder = merge({}, DEFAULT_BUILDERS, options.builder); | ||
return new TreeBuilder(definition, builder).build(options.parent); | ||
return new TreeBuilder(blueprint, builder).build(options.parent); | ||
}, | ||
@@ -154,2 +229,6 @@ | ||
return parent(node); | ||
}, | ||
meta: function(node) { | ||
return meta(node); | ||
} | ||
@@ -156,0 +235,0 @@ }; |
{ | ||
"name": "ceibo", | ||
"version": "1.1.1", | ||
"version": "2.0.0", | ||
"description": "Ceibo is a JavaScript micro library to model trees that evaluate arbitrary code when accessing its nodes.", | ||
@@ -9,3 +9,3 @@ "homepage": "https://github.com/san650/ceibo#readme", | ||
"scripts": { | ||
"test": "node ./node_modules/testem/testem ci" | ||
"test": "testem ci" | ||
}, | ||
@@ -12,0 +12,0 @@ "repository": { |
# Ceibo | ||
![Latest version](https://img.shields.io/npm/v/ceibo.svg) | ||
JavaScript micro library to model trees that evaluate arbitrary code when | ||
@@ -97,4 +99,5 @@ accessing its nodes. | ||
```js | ||
function buildString(treeBuilder, target, keyName, value) { | ||
Ceibo.defineProperty(target, keyName, `Cuack ${value}`); | ||
function buildString(node, blueprintKey, value, defaultBuilder) { | ||
return defaultBuilder(node, blueprintKey, `Cuack ${value}`); | ||
} | ||
@@ -119,12 +122,13 @@ | ||
```js | ||
function buildObject(treeBuilder, target, keyName, value) { | ||
var childNode = { | ||
function buildObject(node, blueprintKey, blueprint /*, defaultBuilder */) { | ||
var value = { | ||
generatedProperty: 'generated property' | ||
}; | ||
// define current keyName and assign the new object | ||
Ceibo.defineProperty(target, keyName, childNode); | ||
// define current key and assign the new object | ||
Ceibo.defineProperty(node, blueprintKey, value); | ||
// continue to build the tree recursively | ||
treeBuilder.processNode(value, childNode, target); | ||
return [value, blueprint]; | ||
} | ||
@@ -173,2 +177,57 @@ | ||
Descriptor's `get` function receive the `key` when evaluated | ||
```js | ||
var descriptor = { | ||
isDescriptor: true, | ||
get: function(key) { | ||
return key; | ||
} | ||
}; | ||
var root = Ceibo.create({ | ||
foo: descriptor, | ||
bar: descriptor | ||
}); | ||
console.log(root.foo); // "foo" | ||
console.log(root.bar); // "bar" | ||
``` | ||
Ceibo's nodes store some meta data, you can access said meta data using | ||
`Ceib.meta` function. | ||
```js | ||
var descriptor = { | ||
isDescriptor: true, | ||
get: function(key) { | ||
var keys = [key]; | ||
var node = this; | ||
var meta; | ||
do { | ||
meta = Ceibo.meta(node); | ||
keys.unshift(meta.key); | ||
} while(node = Ceibo.parent(node)); | ||
return keys; | ||
} | ||
}; | ||
var tree = Ceibo.create({ | ||
foo: { | ||
bar: { | ||
baz: { | ||
qux: descriptor | ||
} | ||
} | ||
} | ||
}); | ||
console.log(tree.foo.bar.baz.qux); // ['root', 'foo', 'bar', 'baz', 'qux'] | ||
``` | ||
## Project's health | ||
@@ -175,0 +234,0 @@ |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
240
12386
7
195
1