-
Notifications
You must be signed in to change notification settings - Fork 20
Types And Derive
A description of valid reoccurring type(s) and their behavior.
For somewhat complex types, there is a flexibility of values you can use as there are shortcuts, for example.
Filename specifications (or simply filenames), expressed in 'umatch'. In short it can be:
-
String
in gruntjs's expand minimatch format (eg'**/*.coffee'
) and its exclusion cousin (eg'!**/DRAFT*.*'
) -
RegExp
s that match filenames (eg/./
) again with a
[..., '!', /regexp/, ...]
exclusion pattern.
- A
function(filename){}
callback, returning true if filename is to be matched. Consistently it can have a negation/exclusion flag before it:
[..., '!', function(f){ return f === 'excludeMe.js' }, ...]
```.
@note use a `true` (i.e matched) as the result preceded by '!' for exclusion, **rather the common trap than of a false result for your *excluded matches* (cause all your non-excluded with match with true, which is probably not what you want!)**.
* @todo: NOT IMPLEMENTED: An `Array<String|RegExp|Function|Array>, recursive, i.e
[ ..., ['AllowMe*.*', '!', function(f){ return f === 'excludeMe.js' }, [.., []], ...], ...]
@see uses ['umatch'](https://github.com/anodynos/umatch)
@example
```coffee
bundle: {
filez: [
'**/recources/*.*'
'!dummy.json'
/.*\.someExtension$/i
'!', /.*\.excludeExtension$/i
(filename)-> filename is 'includedFile.ext'
]
}
Defines one or more dependencies (i.e Modules or other Resources), that each is bound to one or more identifiers (i.e variable or property names).
Its used in many places (like injecting deps in bundle.dependencies.imports
) and is often useful.
The formal type, (i.e. where each depVars value ends up as, no matter how its declared as), is an Object like this:
{
'dep1': ['dep1VarName1', 'dep1VarName2'],
...
'underscore': ['_'],
'Backbone': ['backbone'],
....
'depN': ['depNVarName1', ...]
}
The depsVars
type has shortcuts:
-
Array: eg
['arrayDep1', 'arrayDep2', ..., 'arrayDepn']
, with one or more deps. -
String: eg
'soloDep'
, of just one dep. -
or even deps with one identifier
{ 'lodash': '_', xxx: [] }
Shortcut types are converted to the formal type when deriving, using the dependenciesBindings derive - the above will end up as
-
{arrayDep1:[], arrayDep2:[], ..arrayDepn:[]}
-
{soloDep: []}
-
{ 'lodash': ['_'], xxx: [] }
-
when injecting dependencies, eg exporting declarativelly through
bundle.dependencies.imports
eg 'lodash', bind '_' as the var to access the module in the code. -
when converting through 'combined' template. Local dependencies (like
'underscore'
or'jquery'
) are not part of thecombined.js
file. At run time, when running on the module-less Web side as acombined.js
via a simple<script/>
, the uRequire generated code will only know how to grab the dependency using the binding$
from the global object (i.ewindow
).
If a dependency (key) ends up with no identifier (var name), for example { myDep:[], ...}
, then the identifiers are automagically inferred from:
-
the code it self, i.e when you have
define ['lodash'], (_)->
or_ = require 'lodash'
somewhere in your code, it binds'lodash'
dependency with_
identifier. -
or using any other relevant part of the config like
bundle.dependencies.depsVars
,bundle.dependencies._knownDepsVars
etc.
This type controls if a key applies to all, none or some filenames/module paths. Its either:
-
boolean (true/false), so all or none files/modules get the setting.
-
A filespecs. Important @note: if the config setting (eg
globalWindow
,useStrict
etc) is dealing with modules (usually), a module bundleRelative path is expected without the filename extension, i.e['models/PersonModel', ...]
without'.js'
. If dealing with general file, you have to match filename and extension.
Unless otherwise specified, booleanOrFilespecs
uses derive arraysConcatOrOverwrite
.
A config can can be derived from one or more parent configs. Its a similar notion to classical OO Inheritance, where a subclass overrides the values of a superclass, but better.
Ultimately all configs are derived (inherit) from MasterDefaultsConfig
which holds all default parent values.
Derivation is more flexible than simple OO inheritance (or any _.extend
like function) for two main reasons :
Keys of the config are not flat - derivation goes deeply in paths of keys, i.e {a: {b1:11, b2:12}}
--derive--> {a: {b1:1, b3:3}}
gives {a: {b1:11, b2:12, b3:3}}
, something like or _.deepExtend
.
Behavior goes longer than depth: when inheriting in OO (or an _.extend
like function), all overriding child keys simply overwrite (or hide) those on parent(s).
With derive
of uRequire configs, at each member/key (or keys path, since we have depth), there is a different behavior for how to derive (or blend) with the parent's values of that key.
For example when a key is supposed to hold an Array
value with derive type arrayizeConcat, the resulting Array
is the child's array concat
-ed to parent's. Also, if the value held is NOT already an Array
(as it should), then that value becomes the 1st item of an Array
first, before being concatenated to parent's. In any case, even if there just one config (nort derived by any other), the resulting value is guaranteed to be an Array
.
??????
Both parent and child values are considered to be of Array type (or are turned into an Array first with _B.arrayize).
Then the items on child configs are pushed after the ones they inherit (the parent's array, higher up in hierarchy).The parent is always a shallow clone of the original parent array which remains intact. In v0.6.10 the child can be a function callback.
For example consider key bundle.filez
(that has the arrayizeConcat derive behavior).
-
parent config
bundle: filez: ['**/*', '!DRAFT/*.*']
-
child config
bundle: filez: ['!vendor/*.*]
-
derived config:
bundle: filez: ['**/*', '!DRAFT/*.*', '!vendor/*.*]
.
The type for both child and parent values, are either Array<Anything>
or Anything
but Array (which is _B.arrayize-d first).
The child can also be a callback function(parentArray)
, that receives a shallow clone of parentArray and returns the resulted array.
Example:
-
parent config
bundle:{ filez: ['**/*.js', '!DRAFT/*.*']}
-
child config
bundle: { filez: function(parentArray){ parentArray.unshift('**/*.coffee'); parentArray } }
-
derived config:
bundle: { filez: ['**/*.coffee', '**/*.js', '!DRAFT/*.*'] }
.
This way you can manipulate the inherited array as desired.
To reset the inherited parent array (always in your new child destination array), use [null]
as the 1st item of your child array. For example
-
parent config
bundle:filez: ['**/*', '!DRAFT/*.*']
-
child config
bundle:filez: [[null], 'vendorOnly/*.*]
-
derived config:
bundle: filez: ['vendorOnly/*.*]
.
Just like arrayizeConcat, but only === unique items are pushed to the result array.
If both child and parent values are already an Array, then the items on child (derived) configs are pushed after the ones they inherit (like arrayizeConcat
).
Otherwise, the child value (even if its an array) overwrites the value it inherits.
For example consider key build.globalWindow
(that has the arraysConcatOrOverwrite derive behavior).
-
parent config
build: globalWindow: ['**/*']
-
child config
build: globalWindow: true
-
blended config:
build: globalWindow: true
or similarly
-
parent config
build: globalWindow: true
-
child config
build: globalWindow: ['**/*']
-
blended config:
build: globalWindow: ['**/*']
@note reset parent works like arrayizeConcat's, so you can produce a new Array, even when deriving from an Array.
This derivation refers to depsVars
type.
Each dependency name (the key) of child configs is added to the resulted object, if not already there.
Its identifiers / variable names are then arrayizeUniqueConcat-ed onto the array.
For example with a parent value:
{
myDep1: ['myDep1Var1', 'myDep1Var2']
}
and a child value:
{
myDep1: ['myDep1Var1', 'myMissingDep1Var3']
# identifier is a String, not an Array
myDep2: 'myDep2Var'
}
the resulted derived object will be
{
# only missing 'myMissingDep1Var3' identifier is appended to array
myDep1: ['myDep1Var1', 'myDep1Var2', 'myMissingDep1Var3']
# identifier is arrayized
myDep2: ['myDep2Var']
}