Comparing version 0.13.0 to 0.13.2
@@ -27,8 +27,2 @@ module.exports = function(grunt) { | ||
releaseNoVendor: { | ||
src: ['lib/<%= pkg.name %>.js'], | ||
dest: 'bin/<%= pkg.name %>.release.no-vendor.js', | ||
options: { standalone: '<%= pkg.name %>', ignore: 'underscore' } | ||
}, | ||
test: { | ||
@@ -44,19 +38,20 @@ src: ['test/main.js'], | ||
src: ['bin/<%= pkg.name %>.release.js'], | ||
dest: 'bin/<%= pkg.name %>.min.js' | ||
dest: 'bin/<%= pkg.name %>.min.js', | ||
options: { report: 'gzip' } | ||
}, | ||
releaseNoVendor: { | ||
src: ['bin/<%= pkg.name %>.release.no-vendor.js'], | ||
dest: 'bin/<%= pkg.name %>.no-vendor.min.js' | ||
}, | ||
options: { report: 'gzip' } | ||
}, | ||
watch: { | ||
all: { | ||
files: [ | ||
'lib/**/*.js', | ||
'test/main.js', | ||
'test/unit/**/*.js' | ||
], | ||
tasks: ['default'] | ||
lib: { | ||
files: ['lib/**/*.js'], | ||
tasks: ['build', 'test'] | ||
}, | ||
test: { | ||
files: ['test/unit/**/*.js', 'test/main.js'], | ||
tasks: ['lint', 'browserify:test'] | ||
}, | ||
options: { | ||
livereload: 35729 | ||
} | ||
@@ -80,6 +75,7 @@ }, | ||
grunt.registerTask('lint', ['jshint']); | ||
grunt.registerTask('build', ['lint', 'browserify']); | ||
grunt.registerTask('test', ['lint', 'browserify:test', 'qunit']); | ||
grunt.registerTask('default', ['build', 'uglify']); | ||
grunt.registerTask('build', ['lint', 'browserify:debug']); | ||
grunt.registerTask('test', ['build', 'browserify:test', 'qunit']); | ||
grunt.registerTask('release', ['lint', 'browserify:release', 'uglify:release']); | ||
grunt.registerTask('default', ['build']); | ||
}; |
@@ -168,5 +168,2 @@ // ---------------------------------------------------------------------------- | ||
// track everything | ||
var globalNamespace = {}; | ||
var defineThing = function(name, thing, parents, hash) | ||
@@ -194,5 +191,2 @@ { | ||
// ensure we add it to ns | ||
globalNamespace[name] = thing; | ||
return thing; | ||
@@ -293,11 +287,10 @@ }; | ||
signature : core.getSignature, | ||
global : globalNamespace, | ||
Exception : require('./exception'), | ||
BaseObject : BaseObject, | ||
isClass : core.isClass, | ||
isMixin : core.isMixin, | ||
isInterface : core.isInterface, | ||
getFunctionSignature : util.getFunctionSignature | ||
isInterface : core.isInterface | ||
}; |
@@ -38,3 +38,3 @@ var _ = require('underscore'); | ||
// Extract parameter string | ||
var args = f.toString().match(/function\s\(([^\)]+)/); | ||
var args = f.toString().match(/function\s?\(([^\)]+)/); | ||
if (!args) | ||
@@ -41,0 +41,0 @@ return []; |
{ | ||
"name": "typedef", | ||
"version": "0.13.0", | ||
"version": "0.13.2", | ||
"description": "Familiar classes, mixins, and interfaces in ES5 Javascript. Member decorations for powerful objects that keep your code DRY", | ||
@@ -14,3 +14,3 @@ "main": "lib/typedef.js", | ||
"type": "git", | ||
"url": "git@bitbucket.org:bvalosek/compose.js.git" | ||
"url": "git@github.com:bvalosek/typedef.git" | ||
}, | ||
@@ -17,0 +17,0 @@ "author": "Brandon Valosek", |
143
README.md
# Typedef | ||
[![Build Status](https://travis-ci.org/bvalosek/typedef.png?branch=master)](https://travis-ci.org/bvalosek/typedef) | ||
**Typedef** is a lightweight library (1.7 KB, 4.7 KB with | ||
@@ -28,4 +30,4 @@ [underscore.js](http://www.underscorejs.org) bundled in) that brings some | ||
* **Mixins.** Add member functions to a class without enforcing a | ||
strict single-inheritance relationships. The `before`, `after`, and `wrapped` | ||
* **Mixins.** Add member functions to a class without enforcing a strict | ||
single-inheritance relationships. The `before`, `after`, and `wrapped` | ||
"advice" decorations can be used to modify existing functions. | ||
@@ -48,19 +50,89 @@ | ||
**Typedef** is packaged with the [UMD pattern](https://github.com/umdjs/umd), | ||
so it can be used in the browser via a global with a `<script>` tag, on the | ||
server with Node, as an AMD module with RequireJS, or with CommonJS via | ||
[Browserify](https://github.com/substack/node-browserify). | ||
### Building | ||
Install all of the required modules to build and use `grunt` to build the files into the `bin/` directory: | ||
``` | ||
npm install | ||
grunt release | ||
``` | ||
## Defining Classes | ||
Easy peasy. Defining a class involves passing a hash of all the corresponding | ||
member functions to the typedef function, as well as (optionally) naming the class. | ||
``` | ||
// Base class definition example .... | ||
``` | ||
It works exactly as you might imagine. | ||
``` | ||
// Base class instantiation and use example ... | ||
``` | ||
Notice that the (optional) constructor function is provided via the | ||
`__constructor__` property in the hash. | ||
Classes are constructor functions that leverage the native prototypical | ||
inheritance model. | ||
### Extending Classes | ||
**Typedef** allows for single-inheritance from a base class via chaining the | ||
`.extends()` function in your class definition. Child constructors are | ||
implicitly called, from the base up, when instantiating child classes. | ||
``` | ||
// Child class definition example | ||
``` | ||
Child classes can be thought of as inheriting the members of the base class-- | ||
though really what is going on is simply building up the native prototype | ||
chain. | ||
``` | ||
// Child class use example | ||
``` | ||
### Using Mixins | ||
Mixins provide a way to add or augment existing member functions in a class. | ||
Multiple mixins can be used during a class definition, and the *advice* | ||
decorations allow for modifying existing functions. | ||
Mixins are added *after* the class is setup, meaning any wrapping augmentations | ||
will be applied on top of defined members of the class. | ||
To add a mixin to your class definition, chain the `.uses()` method in your | ||
definition. | ||
``` | ||
// Mixin definition ... | ||
``` | ||
### Implementing Interfaces | ||
## Class Member Decorations | ||
Interfaces give you a way of specifying a required set of member functions be | ||
present in a class implementation. Though this may seem superfluous for a | ||
duck-typed language like Javascript, this allows you run-time inspection of an | ||
object's abilities with a greater degree of clarity. | ||
Member decorations are a key part of **Typedef**. They allow for the attachment | ||
of meta tags onto members during class definition. This meta information can | ||
then be used to inforce certain rules, or change the behavior of the member. | ||
In addition, using interface patterns allows for your code to be more | ||
self-documenting. Any discrepancy between a class and an interface it | ||
implements will cause define-time exception, informing you of the issue. | ||
All decorations are surrounded by 2 underscores, and multiple decorations can | ||
be set on a single member. | ||
Specify that a class implements a specific interface by chaining the | ||
`implements()` method in your class definition. | ||
``` | ||
// Interface definition ... | ||
``` | ||
## Inheritance Decorations | ||
@@ -77,10 +149,38 @@ | ||
The `virtual` decoration follows its classical use, in that indicates a class | ||
member *may* be overridden in child class. By default, all members are | ||
non-virtual, and thus cannot be overridden. This effectively makes any sort of | ||
member hiding in **Typedef** explicit. | ||
Attempting to override a base member that isn't virtual will result in a | ||
define-time error. | ||
### abstract | ||
An `abstract` member is the same as a `virtual` member, with the difference | ||
that a derived class *must* override the abstract member. | ||
A class with at least one abstract member is considered an abstract class. An | ||
exception is thrown when attempting to instantiate an abstract class. | ||
### override | ||
### sealed | ||
The `override` decoration is required when overriding a base member in a child | ||
class. The base member must be `virtual`. | ||
### new | ||
The `new` decoration indicates that the previous implementation of a member is | ||
to be disregarded. This can be used to explicitly hide a base class member that | ||
isn't set to `virtual`, for example. | ||
### sealed | ||
A `sealed` member indicates that it cannot be override at all, even if using | ||
the `new` decoration. This provides a way to very clearly indicate that a | ||
member should not be changed in derived implementations of a class. | ||
Attempting to override a `sealed` member will result in a define-time | ||
exception. | ||
## Accessor Decorations | ||
@@ -90,2 +190,9 @@ | ||
Using the `readonly` decoration will define the property with the `writable` | ||
flag set to `false`. Any attempts to update a `readonly` property will silently | ||
fail (unless you `use strict`). | ||
Note that this only applies for the values of members; if a member set as | ||
`readonly` is initialized with an object, that object can still be mutated. | ||
### static | ||
@@ -101,13 +208,18 @@ | ||
## Semantic Decorations | ||
## Behavior-enforcing Decorations | ||
### fluent | ||
## Constructor Decoration | ||
This decoration allows you to signal in your public API that method is designed | ||
to returned the `this` pointer. This allows for the elegant "fluent API" style | ||
of method chaining. | ||
### constructor | ||
The define-time check uses `function#toString` to check all return statements | ||
to ensure that they are returning `this`. Returning something else (or not | ||
having any `return` statements) will result in a define-time warning. | ||
## Compatibility | ||
**Typedef** will work with the following browsers: | ||
**Typedef** makes liberal use of ES5 features such as `Object.defineProperty` | ||
and `Object.create`, and thus will work with any modern browser: | ||
@@ -122,2 +234,5 @@ * Chrome 7+ | ||
Testing is powered by [QUnit](http://qunitjs.com/) and can be run from the | ||
command line via `grunt-contrib-qunit`. To install all modules and test: | ||
``` | ||
@@ -128,4 +243,2 @@ npm install | ||
## Special Thanks | ||
### Contributers | ||
@@ -132,0 +245,0 @@ |
@@ -8,3 +8,2 @@ // Run all tests | ||
require('./unit/ondefine'); | ||
require('./unit/global'); | ||
require('./unit/fluent'); |
112238
247
3190