A bunch of random progress

This commit is contained in:
Timothy Warren 2014-10-20 16:56:45 -04:00
parent b2d214d288
commit 6542c8f674
3733 changed files with 2576023 additions and 21 deletions

28
Gruntfile.js Normal file
View File

@ -0,0 +1,28 @@
module.exports = function(grunt) {
'use strict';
var exec = require('child_process').exec;
// Project configuration
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
jsdoc: {
dist: {
src: ['lib/**/*.js', 'README.md'],
options: {
destination: 'docs'
}
}
},
nodeunit: {
all: ['tests/**/*_test.js']
}
});
grunt.loadNpmTasks('grunt-jsdoc');
grunt.loadNpmTasks('grunt-contrib-nodeunit');
grunt.registerTask('default', ['nodeunit','jsdoc']);
grunt.registerTask('tests', 'nodeunit');
};

17
README.md Executable file
View File

@ -0,0 +1,17 @@
#Node-query
A node query builder for various SQL databases, based on CodeIgniter's query builder.
### Probable use
var query = require('node-query');
var res = query
.select('foo')
.from('bar')
.where('x', 3)
.orWhere('y', 2)
.orderBy('x')
.limit(2, 3)
.get();

11
config.json Normal file
View File

@ -0,0 +1,11 @@
{
"source": {
"include": ["lib", "lib/drivers"],
"includePattern": ".+\\.js(doc)?$"
},
"opts" : {
"template": "templates/default",
"destination": "./docs/",
"lenient": true
}
}

178
docs/driver.js.html Normal file
View File

@ -0,0 +1,178 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSDoc: Source: driver.js</title>
<script src="scripts/prettify/prettify.js"> </script>
<script src="scripts/prettify/lang-css.js"> </script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
</head>
<body>
<div id="main">
<h1 class="page-title">Source: driver.js</h1>
<section>
<article>
<pre class="prettyprint source"><code>/** @module driver */
"use strict";
var helpers = require('./helpers');
/**
* Base Database Driver
*
* @type {{identifierChar: string, quoteIdentifiers: quoteIdentifiers}}
*/
module.exports = {
identifierChar: '"',
tablePrefix: null,
/**
* Low level function for naive quoting of strings
* @param {String} str
* @return {String}
* @private
*/
_quote: function(str) {
return (helpers.isString(str) && ! (str.startsWith(this.identifierChar) || str.endsWith(this.identifierChar)))
? this.identifierChar + str + this.identifierChar
: str;
},
/**
* Sets the table prefix on the passed string
*
* @param {String} str
* @return {String}
* @private
*/
_prefix: function(str) {
if (str.startsWith(this.prefix))
{
return str;
}
return this.prefix + str;
},
/**
* Set the limit clause
* @param {String} sql
* @param {Number} limit
* @param {Number|null} offset
* @return {String}
*/
limit: function(sql, limit, offset) {
sql += " LIMIT " + limit;
if (helpers.isNumber(offset))
{
sql += " OFFSET " + offset;
}
return sql;
},
/**
* Prefixes a table if it is not already prefixed
*
* @param {String} table
* @return {String}
*/
prefixTable: function(table) {
if (this.tablePrefix)
{
// Split identifier by period, will split into:
// database.schema.table OR
// schema.table OR
// database.table OR
// table
var idents = table.split('.', table);
var segments = idents.length;
// Add the database prefix
idents[segments - 1] = this._prefix(idents[segments - 1]);
table = idents.join('.');
}
return table;
},
/**
* Quote database table name, and set prefix
*
* @param {String} table
* @return {String}
*/
quoteTable: function(table) {
table = this.prefixTable(table);
// Quote after prefix
return this.quoteIdentifiers(table);
},
/**
* Use the driver's escape character to quote identifiers
*
* @param {String|Array}
* @return {String|Array}
*/
quoteIdentifiers: function(str) {
var hiers, raw;
// Recurse for arrays of identifiiers
if (Array.isArray(str))
{
return str.map(this.quoteIdentifiers);
}
// Handle commas
str = helpers.splitTrim(',', str);
// Split identifiers by period
hiers = str.split('.').map(String.trim).map(this._quote);
raw = hiers.join('.');
// TODO: fix functions
return raw;
}
};</code></pre>
</article>
</section>
</div>
<nav>
<h2><a href="index.html">Index</a></h2><h3>Modules</h3><ul><li><a href="module-driver.html">driver</a></li><li><a href="module-helpers.html">helpers</a></li><li><a href="module-query-builder.html">query-builder</a></li></ul><h3><a href="global.html">Global</a></h3>
</nav>
<br clear="both">
<footer>
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.2.2</a> on Mon Oct 20 2014 16:34:02 GMT-0400 (EDT)
</footer>
<script> prettyPrint(); </script>
<script src="scripts/linenumber.js"> </script>
</body>
</html>

183
docs/global.html Normal file
View File

@ -0,0 +1,183 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSDoc: Global</title>
<script src="scripts/prettify/prettify.js"> </script>
<script src="scripts/prettify/lang-css.js"> </script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
</head>
<body>
<div id="main">
<h1 class="page-title">Global</h1>
<section>
<header>
<h2>
</h2>
</header>
<article>
<div class="container-overview">
<dl class="details">
</dl>
</div>
<h3 class="subsection-title">Members</h3>
<dl>
<dt>
<h4 class="name" id="module:driver"><span class="type-signature"></span>module:driver<span class="type-signature"> :Object</span></h4>
</dt>
<dd>
<div class="description">
Base Database Driver
</div>
<h5>Type:</h5>
<ul>
<li>
<span class="param-type">Object</span>
</li>
</ul>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="driver.js.html">driver.js</a>, <a href="driver.js.html#line12">line 12</a>
</li></ul></dd>
</dl>
</dd>
</dl>
</article>
</section>
</div>
<nav>
<h2><a href="index.html">Index</a></h2><h3>Modules</h3><ul><li><a href="module-driver.html">driver</a></li><li><a href="module-helpers.html">helpers</a></li><li><a href="module-query-builder.html">query-builder</a></li></ul><h3><a href="global.html">Global</a></h3>
</nav>
<br clear="both">
<footer>
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.2.2</a> on Mon Oct 20 2014 16:34:02 GMT-0400 (EDT)
</footer>
<script> prettyPrint(); </script>
<script src="scripts/linenumber.js"> </script>
</body>
</html>

109
docs/helpers.js.html Normal file
View File

@ -0,0 +1,109 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSDoc: Source: helpers.js</title>
<script src="scripts/prettify/prettify.js"> </script>
<script src="scripts/prettify/lang-css.js"> </script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
</head>
<body>
<div id="main">
<h1 class="page-title">Source: helpers.js</h1>
<section>
<article>
<pre class="prettyprint source"><code>/** @module helpers */
"use strict";
if (!String.prototype.startsWith) {
Object.defineProperty(String.prototype, 'startsWith', {
enumerable: false,
configurable: false,
writable: false,
value: function (searchString, position) {
position = position || 0;
return this.lastIndexOf(searchString, position) === position;
}
});
}
if (!String.prototype.endsWith) {
Object.defineProperty(String.prototype, 'endsWith', {
value: function (searchString, position) {
var subjectString = this.toString();
if (position === undefined || position > subjectString.length) {
position = subjectString.length;
}
position -= searchString.length;
var lastIndex = subjectString.indexOf(searchString, position);
return lastIndex !== -1 && lastIndex === position;
}
});
}
module.exports = {
/**
* Split a string by a character, trim the string
* and rejoin the string
*
* @param {String} char
* @param {String} string
* @return {String}
*/
splitTrim: function(char, string) {
return string.split(char).map(String.trim).join(char);
},
/**
* Determine whether an object is a string
* @param {mixed} obj
* @return {bool}
*/
isString: function(obj) {
return (typeof obj === 'string' || obj instanceof String);
},
/**
* Determine whether an object is numeric
* @param {mixed} obj
* @return {bool}
*/
isNumber: function(obj) {
return ! isNaN(parseFloat(obj)) && isFinite(obj);
}
};
</code></pre>
</article>
</section>
</div>
<nav>
<h2><a href="index.html">Index</a></h2><h3>Modules</h3><ul><li><a href="module-driver.html">driver</a></li><li><a href="module-helpers.html">helpers</a></li><li><a href="module-query-builder.html">query-builder</a></li></ul><h3><a href="global.html">Global</a></h3>
</nav>
<br clear="both">
<footer>
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.2.2</a> on Mon Oct 20 2014 16:34:02 GMT-0400 (EDT)
</footer>
<script> prettyPrint(); </script>
<script src="scripts/linenumber.js"> </script>
</body>
</html>

79
docs/index.html Normal file
View File

@ -0,0 +1,79 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSDoc: Index</title>
<script src="scripts/prettify/prettify.js"> </script>
<script src="scripts/prettify/lang-css.js"> </script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
</head>
<body>
<div id="main">
<h1 class="page-title">Index</h1>
<h3> </h3>
<section>
<article><h1>Node-query</h1>
<p>A node query builder for various SQL databases, based on CodeIgniter's query builder.</p>
<h3>Probable use</h3>
<pre><code>var query = require('node-query');
var res = query
.select('foo')
.from('bar')
.where('x', 3)
.orWhere('y', 2)
.orderBy('x')
.limit(2, 3)
.get();</code></pre></article>
</section>
</div>
<nav>
<h2><a href="index.html">Index</a></h2><h3>Modules</h3><ul><li><a href="module-driver.html">driver</a></li><li><a href="module-helpers.html">helpers</a></li><li><a href="module-query-builder.html">query-builder</a></li></ul><h3><a href="global.html">Global</a></h3>
</nav>
<br clear="both">
<footer>
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.2.2</a> on Mon Oct 20 2014 16:34:02 GMT-0400 (EDT)
</footer>
<script> prettyPrint(); </script>
<script src="scripts/linenumber.js"> </script>
</body>
</html>

989
docs/module-driver.html Normal file
View File

@ -0,0 +1,989 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSDoc: Module: driver</title>
<script src="scripts/prettify/prettify.js"> </script>
<script src="scripts/prettify/lang-css.js"> </script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
</head>
<body>
<div id="main">
<h1 class="page-title">Module: driver</h1>
<section>
<header>
<h2>
driver
</h2>
</header>
<article>
<div class="container-overview">
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="driver.js.html">driver.js</a>, <a href="driver.js.html#line1">line 1</a>
</li></ul></dd>
</dl>
</div>
<h3 class="subsection-title">Methods</h3>
<dl>
<dt>
<h4 class="name" id="_prefix"><span class="type-signature">&lt;private, static> </span>_prefix<span class="signature">(str)</span><span class="type-signature"> &rarr; {String}</span></h4>
</dt>
<dd>
<div class="description">
Sets the table prefix on the passed string
</div>
<h5>Parameters:</h5>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>str</code></td>
<td class="type">
<span class="param-type">String</span>
</td>
<td class="description last"></td>
</tr>
</tbody>
</table>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="driver.js.html">driver.js</a>, <a href="driver.js.html#line36">line 36</a>
</li></ul></dd>
</dl>
<h5>Returns:</h5>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">String</span>
</dd>
</dl>
</dd>
<dt>
<h4 class="name" id="_quote"><span class="type-signature">&lt;private, static> </span>_quote<span class="signature">(str)</span><span class="type-signature"> &rarr; {String}</span></h4>
</dt>
<dd>
<div class="description">
Low level function for naive quoting of strings
</div>
<h5>Parameters:</h5>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>str</code></td>
<td class="type">
<span class="param-type">String</span>
</td>
<td class="description last"></td>
</tr>
</tbody>
</table>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="driver.js.html">driver.js</a>, <a href="driver.js.html#line23">line 23</a>
</li></ul></dd>
</dl>
<h5>Returns:</h5>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">String</span>
</dd>
</dl>
</dd>
<dt>
<h4 class="name" id="limit"><span class="type-signature">&lt;static> </span>limit<span class="signature">(sql, limit, offset)</span><span class="type-signature"> &rarr; {String}</span></h4>
</dt>
<dd>
<div class="description">
Set the limit clause
</div>
<h5>Parameters:</h5>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>sql</code></td>
<td class="type">
<span class="param-type">String</span>
</td>
<td class="description last"></td>
</tr>
<tr>
<td class="name"><code>limit</code></td>
<td class="type">
<span class="param-type">Number</span>
</td>
<td class="description last"></td>
</tr>
<tr>
<td class="name"><code>offset</code></td>
<td class="type">
<span class="param-type">Number</span>
|
<span class="param-type">null</span>
</td>
<td class="description last"></td>
</tr>
</tbody>
</table>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="driver.js.html">driver.js</a>, <a href="driver.js.html#line53">line 53</a>
</li></ul></dd>
</dl>
<h5>Returns:</h5>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">String</span>
</dd>
</dl>
</dd>
<dt>
<h4 class="name" id="prefixTable"><span class="type-signature">&lt;static> </span>prefixTable<span class="signature">(table)</span><span class="type-signature"> &rarr; {String}</span></h4>
</dt>
<dd>
<div class="description">
Prefixes a table if it is not already prefixed
</div>
<h5>Parameters:</h5>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>table</code></td>
<td class="type">
<span class="param-type">String</span>
</td>
<td class="description last"></td>
</tr>
</tbody>
</table>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="driver.js.html">driver.js</a>, <a href="driver.js.html#line70">line 70</a>
</li></ul></dd>
</dl>
<h5>Returns:</h5>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">String</span>
</dd>
</dl>
</dd>
<dt>
<h4 class="name" id="quoteIdentifiers"><span class="type-signature">&lt;static> </span>quoteIdentifiers<span class="signature">(str)</span><span class="type-signature"> &rarr; {String|Array}</span></h4>
</dt>
<dd>
<div class="description">
Use the driver's escape character to quote identifiers
</div>
<h5>Parameters:</h5>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>str</code></td>
<td class="type">
<span class="param-type">String</span>
|
<span class="param-type">Array</span>
</td>
<td class="description last"></td>
</tr>
</tbody>
</table>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="driver.js.html">driver.js</a>, <a href="driver.js.html#line109">line 109</a>
</li></ul></dd>
</dl>
<h5>Returns:</h5>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">String</span>
|
<span class="param-type">Array</span>
</dd>
</dl>
</dd>
<dt>
<h4 class="name" id="quoteTable"><span class="type-signature">&lt;static> </span>quoteTable<span class="signature">(table)</span><span class="type-signature"> &rarr; {String}</span></h4>
</dt>
<dd>
<div class="description">
Quote database table name, and set prefix
</div>
<h5>Parameters:</h5>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>table</code></td>
<td class="type">
<span class="param-type">String</span>
</td>
<td class="description last"></td>
</tr>
</tbody>
</table>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="driver.js.html">driver.js</a>, <a href="driver.js.html#line96">line 96</a>
</li></ul></dd>
</dl>
<h5>Returns:</h5>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">String</span>
</dd>
</dl>
</dd>
</dl>
</article>
</section>
</div>
<nav>
<h2><a href="index.html">Index</a></h2><h3>Modules</h3><ul><li><a href="module-driver.html">driver</a></li><li><a href="module-helpers.html">helpers</a></li><li><a href="module-query-builder.html">query-builder</a></li></ul><h3><a href="global.html">Global</a></h3>
</nav>
<br clear="both">
<footer>
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.2.2</a> on Mon Oct 20 2014 16:34:02 GMT-0400 (EDT)
</footer>
<script> prettyPrint(); </script>
<script src="scripts/linenumber.js"> </script>
</body>
</html>

553
docs/module-helpers.html Normal file
View File

@ -0,0 +1,553 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSDoc: Module: helpers</title>
<script src="scripts/prettify/prettify.js"> </script>
<script src="scripts/prettify/lang-css.js"> </script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
</head>
<body>
<div id="main">
<h1 class="page-title">Module: helpers</h1>
<section>
<header>
<h2>
helpers
</h2>
</header>
<article>
<div class="container-overview">
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="helpers.js.html">helpers.js</a>, <a href="helpers.js.html#line1">line 1</a>
</li></ul></dd>
</dl>
</div>
<h3 class="subsection-title">Methods</h3>
<dl>
<dt>
<h4 class="name" id="isNumber"><span class="type-signature">&lt;static> </span>isNumber<span class="signature">(obj)</span><span class="type-signature"> &rarr; {bool}</span></h4>
</dt>
<dd>
<div class="description">
Determine whether an object is numeric
</div>
<h5>Parameters:</h5>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>obj</code></td>
<td class="type">
<span class="param-type">mixed</span>
</td>
<td class="description last"></td>
</tr>
</tbody>
</table>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="helpers.js.html">helpers.js</a>, <a href="helpers.js.html#line56">line 56</a>
</li></ul></dd>
</dl>
<h5>Returns:</h5>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">bool</span>
</dd>
</dl>
</dd>
<dt>
<h4 class="name" id="isString"><span class="type-signature">&lt;static> </span>isString<span class="signature">(obj)</span><span class="type-signature"> &rarr; {bool}</span></h4>
</dt>
<dd>
<div class="description">
Determine whether an object is a string
</div>
<h5>Parameters:</h5>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>obj</code></td>
<td class="type">
<span class="param-type">mixed</span>
</td>
<td class="description last"></td>
</tr>
</tbody>
</table>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="helpers.js.html">helpers.js</a>, <a href="helpers.js.html#line48">line 48</a>
</li></ul></dd>
</dl>
<h5>Returns:</h5>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">bool</span>
</dd>
</dl>
</dd>
<dt>
<h4 class="name" id="splitTrim"><span class="type-signature">&lt;static> </span>splitTrim<span class="signature">(char, string)</span><span class="type-signature"> &rarr; {String}</span></h4>
</dt>
<dd>
<div class="description">
Split a string by a character, trim the string
and rejoin the string
</div>
<h5>Parameters:</h5>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>char</code></td>
<td class="type">
<span class="param-type">String</span>
</td>
<td class="description last"></td>
</tr>
<tr>
<td class="name"><code>string</code></td>
<td class="type">
<span class="param-type">String</span>
</td>
<td class="description last"></td>
</tr>
</tbody>
</table>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="helpers.js.html">helpers.js</a>, <a href="helpers.js.html#line40">line 40</a>
</li></ul></dd>
</dl>
<h5>Returns:</h5>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">String</span>
</dd>
</dl>
</dd>
</dl>
</article>
</section>
</div>
<nav>
<h2><a href="index.html">Index</a></h2><h3>Modules</h3><ul><li><a href="module-driver.html">driver</a></li><li><a href="module-helpers.html">helpers</a></li><li><a href="module-query-builder.html">query-builder</a></li></ul><h3><a href="global.html">Global</a></h3>
</nav>
<br clear="both">
<footer>
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.2.2</a> on Mon Oct 20 2014 16:34:02 GMT-0400 (EDT)
</footer>
<script> prettyPrint(); </script>
<script src="scripts/linenumber.js"> </script>
</body>
</html>

View File

@ -0,0 +1,772 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSDoc: Module: query-builder</title>
<script src="scripts/prettify/prettify.js"> </script>
<script src="scripts/prettify/lang-css.js"> </script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
</head>
<body>
<div id="main">
<h1 class="page-title">Module: query-builder</h1>
<section>
<header>
<h2>
query-builder
</h2>
</header>
<article>
<div class="container-overview">
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="query-builder.js.html">query-builder.js</a>, <a href="query-builder.js.html#line1">line 1</a>
</li></ul></dd>
</dl>
</div>
<h3 class="subsection-title">Members</h3>
<dl>
<dt>
<h4 class="name" id="_p"><span class="type-signature">&lt;private, inner> </span>_p<span class="type-signature"></span></h4>
</dt>
<dd>
<div class="description">
"Private" methods
</div>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="query-builder.js.html">query-builder.js</a>, <a href="query-builder.js.html#line24">line 24</a>
</li></ul></dd>
</dl>
</dd>
<dt>
<h4 class="name" id="state"><span class="type-signature">&lt;private, inner> </span>state<span class="type-signature"> :Object</span></h4>
</dt>
<dd>
<div class="description">
Variables controlling the sql building
</div>
<h5>Type:</h5>
<ul>
<li>
<span class="param-type">Object</span>
</li>
</ul>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="query-builder.js.html">query-builder.js</a>, <a href="query-builder.js.html#line15">line 15</a>
</li></ul></dd>
</dl>
</dd>
</dl>
<h3 class="subsection-title">Methods</h3>
<dl>
<dt>
<h4 class="name" id="from"><span class="type-signature">&lt;static> </span>from<span class="signature">(tableName)</span><span class="type-signature"> &rarr; {exports}</span></h4>
</dt>
<dd>
<div class="description">
Specify the database table to select from
</div>
<h5>Parameters:</h5>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>tableName</code></td>
<td class="type">
<span class="param-type">String</span>
</td>
<td class="description last"></td>
</tr>
</tbody>
</table>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="query-builder.js.html">query-builder.js</a>, <a href="query-builder.js.html#line101">line 101</a>
</li></ul></dd>
</dl>
<h5>Returns:</h5>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">exports</span>
</dd>
</dl>
</dd>
<dt>
<h4 class="name" id="getCompiledSelect"><span class="type-signature">&lt;static> </span>getCompiledSelect<span class="signature">()</span><span class="type-signature"> &rarr; {String}</span></h4>
</dt>
<dd>
<div class="description">
Return generated select query SQL
</div>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="query-builder.js.html">query-builder.js</a>, <a href="query-builder.js.html#line238">line 238</a>
</li></ul></dd>
</dl>
<h5>Returns:</h5>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">String</span>
</dd>
</dl>
</dd>
<dt>
<h4 class="name" id="getState"><span class="type-signature">&lt;static> </span>getState<span class="signature">()</span><span class="type-signature"> &rarr; {Object}</span></h4>
</dt>
<dd>
<div class="description">
Returns the current class state for testing or other purposes
</div>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="query-builder.js.html">query-builder.js</a>, <a href="query-builder.js.html#line304">line 304</a>
</li></ul></dd>
</dl>
<h5>Returns:</h5>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">Object</span>
</dd>
</dl>
</dd>
<dt>
<h4 class="name" id="resetQuery"><span class="type-signature">&lt;static> </span>resetQuery<span class="signature">()</span><span class="type-signature"></span></h4>
</dt>
<dd>
<div class="description">
Reset the object state for a new query
</div>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="query-builder.js.html">query-builder.js</a>, <a href="query-builder.js.html#line275">line 275</a>
</li></ul></dd>
</dl>
<h5>Returns:</h5>
<div class="param-desc">
void
</div>
</dd>
<dt>
<h4 class="name" id="select"><span class="type-signature">&lt;static> </span>select<span class="signature">(fields)</span><span class="type-signature"> &rarr; {exports}</span></h4>
</dt>
<dd>
<div class="description">
Specify rows to select in the query
</div>
<h5>Parameters:</h5>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>fields</code></td>
<td class="type">
<span class="param-type">String</span>
|
<span class="param-type">Array</span>
</td>
<td class="description last"></td>
</tr>
</tbody>
</table>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="query-builder.js.html">query-builder.js</a>, <a href="query-builder.js.html#line67">line 67</a>
</li></ul></dd>
</dl>
<h5>Returns:</h5>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">exports</span>
</dd>
</dl>
</dd>
</dl>
</article>
</section>
</div>
<nav>
<h2><a href="index.html">Index</a></h2><h3>Modules</h3><ul><li><a href="module-driver.html">driver</a></li><li><a href="module-helpers.html">helpers</a></li><li><a href="module-query-builder.html">query-builder</a></li></ul><h3><a href="global.html">Global</a></h3>
</nav>
<br clear="both">
<footer>
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.2.2</a> on Mon Oct 20 2014 16:34:02 GMT-0400 (EDT)
</footer>
<script> prettyPrint(); </script>
<script src="scripts/linenumber.js"> </script>
</body>
</html>

76
docs/mysql.js.html Normal file
View File

@ -0,0 +1,76 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSDoc: Source: drivers/mysql.js</title>
<script src="scripts/prettify/prettify.js"> </script>
<script src="scripts/prettify/lang-css.js"> </script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
</head>
<body>
<div id="main">
<h1 class="page-title">Source: drivers/mysql.js</h1>
<section>
<article>
<pre class="prettyprint source"><code>"use strict";
/**
* Driver for MySQL databases
*
* @returns {driver}
*/
module.exports = function() {
var driver = require('../driver'),
helpers = require('../helpers');
driver.identifierChar = '`';
/**
* Override default limit method because mysql likes to be different
*/
driver.limit = function(sql, limit, offset) {
if ( ! helpers.isNumber(offset))
{
return sql += " LIMIT " + limit;
}
return sql += " LIMIT " + offset + "," + limit;
};
return driver;
};</code></pre>
</article>
</section>
</div>
<nav>
<h2><a href="index.html">Index</a></h2><h3>Modules</h3><ul><li><a href="module-driver.html">driver</a></li><li><a href="module-helpers.html">helpers</a></li><li><a href="module-query-builder.html">query-builder</a></li></ul><h3><a href="global.html">Global</a></h3>
</nav>
<br clear="both">
<footer>
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.2.2</a> on Mon Oct 20 2014 16:34:02 GMT-0400 (EDT)
</footer>
<script> prettyPrint(); </script>
<script src="scripts/linenumber.js"> </script>
</body>
</html>

61
docs/pg.js.html Normal file
View File

@ -0,0 +1,61 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSDoc: Source: drivers/pg.js</title>
<script src="scripts/prettify/prettify.js"> </script>
<script src="scripts/prettify/lang-css.js"> </script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
</head>
<body>
<div id="main">
<h1 class="page-title">Source: drivers/pg.js</h1>
<section>
<article>
<pre class="prettyprint source"><code>"use strict";
/**
* Driver for PostgreSQL databases
*
* @returns {driver}
*/
module.exports = function() {
var driver = require('../driver');
return driver;
};</code></pre>
</article>
</section>
</div>
<nav>
<h2><a href="index.html">Index</a></h2><h3>Modules</h3><ul><li><a href="module-driver.html">driver</a></li><li><a href="module-helpers.html">helpers</a></li><li><a href="module-query-builder.html">query-builder</a></li></ul><h3><a href="global.html">Global</a></h3>
</nav>
<br clear="both">
<footer>
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.2.2</a> on Mon Oct 20 2014 16:34:02 GMT-0400 (EDT)
</footer>
<script> prettyPrint(); </script>
<script src="scripts/linenumber.js"> </script>
</body>
</html>

358
docs/query-builder.js.html Normal file
View File

@ -0,0 +1,358 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSDoc: Source: query-builder.js</title>
<script src="scripts/prettify/prettify.js"> </script>
<script src="scripts/prettify/lang-css.js"> </script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
</head>
<body>
<div id="main">
<h1 class="page-title">Source: query-builder.js</h1>
<section>
<article>
<pre class="prettyprint source"><code>/** @module query-builder */
var async = require('async');
module.exports = function(driver) {
"use strict";
/**
* Variables controlling the sql building
*
* @private
* @type {{}}
*/
var state = {};
// ------------------------------------------------------------------------
/**
* "Private" methods
*
* @private
*/
var _p = {
/**
* Complete the sql building based on the type provided
*
* @param {String} type
* @param {String} table
* @return {String}
*/
compile: function (type, table) {
switch(type) {
case "insert":
break;
case "update":
break;
case "delete":
break;
default:
break;
}
},
compileType: function (type, table) {
}
};
// ------------------------------------------------------------------------
// Set up state object
this.resetQuery();
// ------------------------------------------------------------------------
// ! Query Builder Methods
// ------------------------------------------------------------------------
/**
* Specify rows to select in the query
*
* @param {String|Array} fields
* @returns {exports}
*/
this.select = function(fields) {
// Split/trim fields by comma
fields = (Array.isArray(fields)) ? fields : fields.split(",").map(String.trim);
// Split on 'As'
fields.forEach(function (field, index) {
if (field.match(/as/i))
{
fields[index] = field.split(/ as /i).map(String.trim);
}
});
var safeArray = driver.quoteIdentifiers(fields);
// Join the strings back together
safeArray.forEach(function (field, index) {
if (Array.isArray(field))
{
safeArray[index] = safeArray[index].join(' AS ');
}
});
state.selectString += safeArray.join(', ');
return this;
};
/**
* Specify the database table to select from
*
* @param {String} tableName
* @returns {exports}
*/
this.from = function(tableName) {
// Split identifiers on spaces
var identArray = String.trim(tableName).split(' ').map(String.trim);
// Quote/prefix identifiers
identArray[0] = driver.quoteTable(identArray[0]);
identArray = driver.quoteIdentifiers(identArray);
// Put it back together
state.fromString = identArray.join(' ');
return this;
};
this.like = function(field, val, pos) {
};
this.orLike = function(field, val, pos) {
};
this.orNotLike = function(field, val, pos) {
};
this.having = function(key, val) {
};
this.orHaving = function(key, val) {
};
this.where = function(key, val) {
};
this.orWhere = function(key, val) {
};
this.whereIn = function(key, val) {
};
this.orWhereIn = function(key, val) {
};
this.whereNotIn = function(key, val) {
};
this.orWhereNotIn = function(key, val) {
};
this.set = function(key, val) {
return this;
};
this.join = function(table1, cond, table2, type) {
type = type || "inner";
return this;
};
this.groupBy = function(field) {
};
this.orderBy = function(field) {
};
this.limit = function(limit, offset) {
state.limit = limit;
state.offset = offset;
return this;
};
this.groupStart = function() {
};
this.orGroupStart = function() {
};
this.orNotGroupStart = function() {
};
this.groupEnd = function() {
};
// ------------------------------------------------------------------------
// ! Result Methods
// ------------------------------------------------------------------------
this.get = function(table, limit, offset) {
// Reset state
this.resetQuery();
};
this.getWhere = function(table, where, limit, offset) {
// Reset state
this.resetQuery();
};
this.insert = function(table, data) {
// Reset state
this.resetQuery();
};
this.update = function(table, data) {
// Reset state
this.resetQuery();
};
this['delete'] = function (table, where) {
// Reset state
this.resetQuery();
};
// ------------------------------------------------------------------------
// ! Methods returning SQL
// ------------------------------------------------------------------------
/**
* Return generated select query SQL
*
* @return {String}
*/
this.getCompiledSelect = function() {
// Return sql
// Reset state
this.resetQuery();
};
this.getCompiledInsert = function() {
// Return sql
// Reset state
this.resetQuery();
};
this.getCompiledUpdate = function() {
// Return sql
// Reset state
this.resetQuery();
};
this.getCompiledDelete = function() {
// Return sql
// Reset state
this.resetQuery();
};
// ----------------------------------------------------------------------------
// ! Miscellaneous Methods
// ----------------------------------------------------------------------------
/**
* Reset the object state for a new query
*
* @return void
*/
this.resetQuery = function() {
state = {
// Arrays/Maps
queryMap: {},
values: [],
whereValues: [],
setArrayKeys: [],
orderArray: [],
groupArray: [],
havingMap: [],
// Partials
selectString: '',
fromString: '',
setString: '',
orderString: '',
groupString: '',
// Other various values
limit: null,
offset: null
};
};
/**
* Returns the current class state for testing or other purposes
*
* @return {Object}
*/
this.getState = function() {
return state;
};
return this;
};</code></pre>
</article>
</section>
</div>
<nav>
<h2><a href="index.html">Index</a></h2><h3>Modules</h3><ul><li><a href="module-driver.html">driver</a></li><li><a href="module-helpers.html">helpers</a></li><li><a href="module-query-builder.html">query-builder</a></li></ul><h3><a href="global.html">Global</a></h3>
</nav>
<br clear="both">
<footer>
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.2.2</a> on Mon Oct 20 2014 16:34:02 GMT-0400 (EDT)
</footer>
<script> prettyPrint(); </script>
<script src="scripts/linenumber.js"> </script>
</body>
</html>

View File

@ -0,0 +1,17 @@
(function() {
var counter = 0;
var numbered;
var source = document.getElementsByClassName('prettyprint source');
if (source && source[0]) {
source = source[0].getElementsByTagName('code')[0];
numbered = source.innerHTML.split('\n');
numbered = numbered.map(function(item) {
counter++;
return '<span id="line' + counter + '" class="line"></span>' + item;
});
source.innerHTML = numbered.join('\n');
}
})();

View File

@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@ -0,0 +1,2 @@
PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\f\r ]+/,null," \t\r\n "]],[["str",/^"(?:[^\n\f\r"\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*"/,null],["str",/^'(?:[^\n\f\r'\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*'/,null],["lang-css-str",/^url\(([^"')]*)\)/i],["kwd",/^(?:url|rgb|!important|@import|@page|@media|@charset|inherit)(?=[^\w-]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*)\s*:/i],["com",/^\/\*[^*]*\*+(?:[^*/][^*]*\*+)*\//],["com",
/^(?:<\!--|--\>)/],["lit",/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],["lit",/^#[\da-f]{3,6}/i],["pln",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i],["pun",/^[^\s\w"']+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[["kwd",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[["str",/^[^"')]+/]]),["css-str"]);

View File

@ -0,0 +1,28 @@
var q=null;window.PR_SHOULD_USE_CONTINUATION=!0;
(function(){function L(a){function m(a){var f=a.charCodeAt(0);if(f!==92)return f;var b=a.charAt(1);return(f=r[b])?f:"0"<=b&&b<="7"?parseInt(a.substring(1),8):b==="u"||b==="x"?parseInt(a.substring(2),16):a.charCodeAt(1)}function e(a){if(a<32)return(a<16?"\\x0":"\\x")+a.toString(16);a=String.fromCharCode(a);if(a==="\\"||a==="-"||a==="["||a==="]")a="\\"+a;return a}function h(a){for(var f=a.substring(1,a.length-1).match(/\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\[0-3][0-7]{0,2}|\\[0-7]{1,2}|\\[\S\s]|[^\\]/g),a=
[],b=[],o=f[0]==="^",c=o?1:0,i=f.length;c<i;++c){var j=f[c];if(/\\[bdsw]/i.test(j))a.push(j);else{var j=m(j),d;c+2<i&&"-"===f[c+1]?(d=m(f[c+2]),c+=2):d=j;b.push([j,d]);d<65||j>122||(d<65||j>90||b.push([Math.max(65,j)|32,Math.min(d,90)|32]),d<97||j>122||b.push([Math.max(97,j)&-33,Math.min(d,122)&-33]))}}b.sort(function(a,f){return a[0]-f[0]||f[1]-a[1]});f=[];j=[NaN,NaN];for(c=0;c<b.length;++c)i=b[c],i[0]<=j[1]+1?j[1]=Math.max(j[1],i[1]):f.push(j=i);b=["["];o&&b.push("^");b.push.apply(b,a);for(c=0;c<
f.length;++c)i=f[c],b.push(e(i[0])),i[1]>i[0]&&(i[1]+1>i[0]&&b.push("-"),b.push(e(i[1])));b.push("]");return b.join("")}function y(a){for(var f=a.source.match(/\[(?:[^\\\]]|\\[\S\s])*]|\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\\d+|\\[^\dux]|\(\?[!:=]|[()^]|[^()[\\^]+/g),b=f.length,d=[],c=0,i=0;c<b;++c){var j=f[c];j==="("?++i:"\\"===j.charAt(0)&&(j=+j.substring(1))&&j<=i&&(d[j]=-1)}for(c=1;c<d.length;++c)-1===d[c]&&(d[c]=++t);for(i=c=0;c<b;++c)j=f[c],j==="("?(++i,d[i]===void 0&&(f[c]="(?:")):"\\"===j.charAt(0)&&
(j=+j.substring(1))&&j<=i&&(f[c]="\\"+d[i]);for(i=c=0;c<b;++c)"^"===f[c]&&"^"!==f[c+1]&&(f[c]="");if(a.ignoreCase&&s)for(c=0;c<b;++c)j=f[c],a=j.charAt(0),j.length>=2&&a==="["?f[c]=h(j):a!=="\\"&&(f[c]=j.replace(/[A-Za-z]/g,function(a){a=a.charCodeAt(0);return"["+String.fromCharCode(a&-33,a|32)+"]"}));return f.join("")}for(var t=0,s=!1,l=!1,p=0,d=a.length;p<d;++p){var g=a[p];if(g.ignoreCase)l=!0;else if(/[a-z]/i.test(g.source.replace(/\\u[\da-f]{4}|\\x[\da-f]{2}|\\[^UXux]/gi,""))){s=!0;l=!1;break}}for(var r=
{b:8,t:9,n:10,v:11,f:12,r:13},n=[],p=0,d=a.length;p<d;++p){g=a[p];if(g.global||g.multiline)throw Error(""+g);n.push("(?:"+y(g)+")")}return RegExp(n.join("|"),l?"gi":"g")}function M(a){function m(a){switch(a.nodeType){case 1:if(e.test(a.className))break;for(var g=a.firstChild;g;g=g.nextSibling)m(g);g=a.nodeName;if("BR"===g||"LI"===g)h[s]="\n",t[s<<1]=y++,t[s++<<1|1]=a;break;case 3:case 4:g=a.nodeValue,g.length&&(g=p?g.replace(/\r\n?/g,"\n"):g.replace(/[\t\n\r ]+/g," "),h[s]=g,t[s<<1]=y,y+=g.length,
t[s++<<1|1]=a)}}var e=/(?:^|\s)nocode(?:\s|$)/,h=[],y=0,t=[],s=0,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=document.defaultView.getComputedStyle(a,q).getPropertyValue("white-space"));var p=l&&"pre"===l.substring(0,3);m(a);return{a:h.join("").replace(/\n$/,""),c:t}}function B(a,m,e,h){m&&(a={a:m,d:a},e(a),h.push.apply(h,a.e))}function x(a,m){function e(a){for(var l=a.d,p=[l,"pln"],d=0,g=a.a.match(y)||[],r={},n=0,z=g.length;n<z;++n){var f=g[n],b=r[f],o=void 0,c;if(typeof b===
"string")c=!1;else{var i=h[f.charAt(0)];if(i)o=f.match(i[1]),b=i[0];else{for(c=0;c<t;++c)if(i=m[c],o=f.match(i[1])){b=i[0];break}o||(b="pln")}if((c=b.length>=5&&"lang-"===b.substring(0,5))&&!(o&&typeof o[1]==="string"))c=!1,b="src";c||(r[f]=b)}i=d;d+=f.length;if(c){c=o[1];var j=f.indexOf(c),k=j+c.length;o[2]&&(k=f.length-o[2].length,j=k-c.length);b=b.substring(5);B(l+i,f.substring(0,j),e,p);B(l+i+j,c,C(b,c),p);B(l+i+k,f.substring(k),e,p)}else p.push(l+i,b)}a.e=p}var h={},y;(function(){for(var e=a.concat(m),
l=[],p={},d=0,g=e.length;d<g;++d){var r=e[d],n=r[3];if(n)for(var k=n.length;--k>=0;)h[n.charAt(k)]=r;r=r[1];n=""+r;p.hasOwnProperty(n)||(l.push(r),p[n]=q)}l.push(/[\S\s]/);y=L(l)})();var t=m.length;return e}function u(a){var m=[],e=[];a.tripleQuotedStrings?m.push(["str",/^(?:'''(?:[^'\\]|\\[\S\s]|''?(?=[^']))*(?:'''|$)|"""(?:[^"\\]|\\[\S\s]|""?(?=[^"]))*(?:"""|$)|'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$))/,q,"'\""]):a.multiLineStrings?m.push(["str",/^(?:'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$)|`(?:[^\\`]|\\[\S\s])*(?:`|$))/,
q,"'\"`"]):m.push(["str",/^(?:'(?:[^\n\r'\\]|\\.)*(?:'|$)|"(?:[^\n\r"\\]|\\.)*(?:"|$))/,q,"\"'"]);a.verbatimStrings&&e.push(["str",/^@"(?:[^"]|"")*(?:"|$)/,q]);var h=a.hashComments;h&&(a.cStyleComments?(h>1?m.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,q,"#"]):m.push(["com",/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\n\r]*)/,q,"#"]),e.push(["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,q])):m.push(["com",/^#[^\n\r]*/,
q,"#"]));a.cStyleComments&&(e.push(["com",/^\/\/[^\n\r]*/,q]),e.push(["com",/^\/\*[\S\s]*?(?:\*\/|$)/,q]));a.regexLiterals&&e.push(["lang-regex",/^(?:^^\.?|[!+-]|!=|!==|#|%|%=|&|&&|&&=|&=|\(|\*|\*=|\+=|,|-=|->|\/|\/=|:|::|;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|[?@[^]|\^=|\^\^|\^\^=|{|\||\|=|\|\||\|\|=|~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\s*(\/(?=[^*/])(?:[^/[\\]|\\[\S\s]|\[(?:[^\\\]]|\\[\S\s])*(?:]|$))+\/)/]);(h=a.types)&&e.push(["typ",h]);a=(""+a.keywords).replace(/^ | $/g,
"");a.length&&e.push(["kwd",RegExp("^(?:"+a.replace(/[\s,]+/g,"|")+")\\b"),q]);m.push(["pln",/^\s+/,q," \r\n\t\xa0"]);e.push(["lit",/^@[$_a-z][\w$@]*/i,q],["typ",/^(?:[@_]?[A-Z]+[a-z][\w$@]*|\w+_t\b)/,q],["pln",/^[$_a-z][\w$@]*/i,q],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i,q,"0123456789"],["pln",/^\\[\S\s]?/,q],["pun",/^.[^\s\w"-$'./@\\`]*/,q]);return x(m,e)}function D(a,m){function e(a){switch(a.nodeType){case 1:if(k.test(a.className))break;if("BR"===a.nodeName)h(a),
a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)e(a);break;case 3:case 4:if(p){var b=a.nodeValue,d=b.match(t);if(d){var c=b.substring(0,d.index);a.nodeValue=c;(b=b.substring(d.index+d[0].length))&&a.parentNode.insertBefore(s.createTextNode(b),a.nextSibling);h(a);c||a.parentNode.removeChild(a)}}}}function h(a){function b(a,d){var e=d?a.cloneNode(!1):a,f=a.parentNode;if(f){var f=b(f,1),g=a.nextSibling;f.appendChild(e);for(var h=g;h;h=g)g=h.nextSibling,f.appendChild(h)}return e}
for(;!a.nextSibling;)if(a=a.parentNode,!a)return;for(var a=b(a.nextSibling,0),e;(e=a.parentNode)&&e.nodeType===1;)a=e;d.push(a)}var k=/(?:^|\s)nocode(?:\s|$)/,t=/\r\n?|\n/,s=a.ownerDocument,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=s.defaultView.getComputedStyle(a,q).getPropertyValue("white-space"));var p=l&&"pre"===l.substring(0,3);for(l=s.createElement("LI");a.firstChild;)l.appendChild(a.firstChild);for(var d=[l],g=0;g<d.length;++g)e(d[g]);m===(m|0)&&d[0].setAttribute("value",
m);var r=s.createElement("OL");r.className="linenums";for(var n=Math.max(0,m-1|0)||0,g=0,z=d.length;g<z;++g)l=d[g],l.className="L"+(g+n)%10,l.firstChild||l.appendChild(s.createTextNode("\xa0")),r.appendChild(l);a.appendChild(r)}function k(a,m){for(var e=m.length;--e>=0;){var h=m[e];A.hasOwnProperty(h)?window.console&&console.warn("cannot override language handler %s",h):A[h]=a}}function C(a,m){if(!a||!A.hasOwnProperty(a))a=/^\s*</.test(m)?"default-markup":"default-code";return A[a]}function E(a){var m=
a.g;try{var e=M(a.h),h=e.a;a.a=h;a.c=e.c;a.d=0;C(m,h)(a);var k=/\bMSIE\b/.test(navigator.userAgent),m=/\n/g,t=a.a,s=t.length,e=0,l=a.c,p=l.length,h=0,d=a.e,g=d.length,a=0;d[g]=s;var r,n;for(n=r=0;n<g;)d[n]!==d[n+2]?(d[r++]=d[n++],d[r++]=d[n++]):n+=2;g=r;for(n=r=0;n<g;){for(var z=d[n],f=d[n+1],b=n+2;b+2<=g&&d[b+1]===f;)b+=2;d[r++]=z;d[r++]=f;n=b}for(d.length=r;h<p;){var o=l[h+2]||s,c=d[a+2]||s,b=Math.min(o,c),i=l[h+1],j;if(i.nodeType!==1&&(j=t.substring(e,b))){k&&(j=j.replace(m,"\r"));i.nodeValue=
j;var u=i.ownerDocument,v=u.createElement("SPAN");v.className=d[a+1];var x=i.parentNode;x.replaceChild(v,i);v.appendChild(i);e<o&&(l[h+1]=i=u.createTextNode(t.substring(b,o)),x.insertBefore(i,v.nextSibling))}e=b;e>=o&&(h+=2);e>=c&&(a+=2)}}catch(w){"console"in window&&console.log(w&&w.stack?w.stack:w)}}var v=["break,continue,do,else,for,if,return,while"],w=[[v,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"],
"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],F=[w,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],G=[w,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"],
H=[G,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"],w=[w,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"],I=[v,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"],
J=[v,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"],v=[v,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],K=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/,N=/\S/,O=u({keywords:[F,H,w,"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END"+
I,J,v],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),A={};k(O,["default-code"]);k(x([],[["pln",/^[^<?]+/],["dec",/^<!\w[^>]*(?:>|$)/],["com",/^<\!--[\S\s]*?(?:--\>|$)/],["lang-",/^<\?([\S\s]+?)(?:\?>|$)/],["lang-",/^<%([\S\s]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-",/^<xmp\b[^>]*>([\S\s]+?)<\/xmp\b[^>]*>/i],["lang-js",/^<script\b[^>]*>([\S\s]*?)(<\/script\b[^>]*>)/i],["lang-css",/^<style\b[^>]*>([\S\s]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),
["default-markup","htm","html","mxml","xhtml","xml","xsl"]);k(x([["pln",/^\s+/,q," \t\r\n"],["atv",/^(?:"[^"]*"?|'[^']*'?)/,q,"\"'"]],[["tag",/^^<\/?[a-z](?:[\w-.:]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^\s"'>]*(?:[^\s"'/>]|\/(?=\s)))/],["pun",/^[/<->]+/],["lang-js",/^on\w+\s*=\s*"([^"]+)"/i],["lang-js",/^on\w+\s*=\s*'([^']+)'/i],["lang-js",/^on\w+\s*=\s*([^\s"'>]+)/i],["lang-css",/^style\s*=\s*"([^"]+)"/i],["lang-css",/^style\s*=\s*'([^']+)'/i],["lang-css",
/^style\s*=\s*([^\s"'>]+)/i]]),["in.tag"]);k(x([],[["atv",/^[\S\s]+/]]),["uq.val"]);k(u({keywords:F,hashComments:!0,cStyleComments:!0,types:K}),["c","cc","cpp","cxx","cyc","m"]);k(u({keywords:"null,true,false"}),["json"]);k(u({keywords:H,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:K}),["cs"]);k(u({keywords:G,cStyleComments:!0}),["java"]);k(u({keywords:v,hashComments:!0,multiLineStrings:!0}),["bsh","csh","sh"]);k(u({keywords:I,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}),
["cv","py"]);k(u({keywords:"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["perl","pl","pm"]);k(u({keywords:J,hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb"]);k(u({keywords:w,cStyleComments:!0,regexLiterals:!0}),["js"]);k(u({keywords:"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes",
hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),["coffee"]);k(x([],[["str",/^[\S\s]+/]]),["regex"]);window.prettyPrintOne=function(a,m,e){var h=document.createElement("PRE");h.innerHTML=a;e&&D(h,e);E({g:m,i:e,h:h});return h.innerHTML};window.prettyPrint=function(a){function m(){for(var e=window.PR_SHOULD_USE_CONTINUATION?l.now()+250:Infinity;p<h.length&&l.now()<e;p++){var n=h[p],k=n.className;if(k.indexOf("prettyprint")>=0){var k=k.match(g),f,b;if(b=
!k){b=n;for(var o=void 0,c=b.firstChild;c;c=c.nextSibling)var i=c.nodeType,o=i===1?o?b:c:i===3?N.test(c.nodeValue)?b:o:o;b=(f=o===b?void 0:o)&&"CODE"===f.tagName}b&&(k=f.className.match(g));k&&(k=k[1]);b=!1;for(o=n.parentNode;o;o=o.parentNode)if((o.tagName==="pre"||o.tagName==="code"||o.tagName==="xmp")&&o.className&&o.className.indexOf("prettyprint")>=0){b=!0;break}b||((b=(b=n.className.match(/\blinenums\b(?::(\d+))?/))?b[1]&&b[1].length?+b[1]:!0:!1)&&D(n,b),d={g:k,h:n,i:b},E(d))}}p<h.length?setTimeout(m,
250):a&&a()}for(var e=[document.getElementsByTagName("pre"),document.getElementsByTagName("code"),document.getElementsByTagName("xmp")],h=[],k=0;k<e.length;++k)for(var t=0,s=e[k].length;t<s;++t)h.push(e[k][t]);var e=q,l=Date;l.now||(l={now:function(){return+new Date}});var p=0,d,g=/\blang(?:uage)?-([\w.]+)(?!\S)/;m()};window.PR={createSimpleLexer:x,registerLangHandler:k,sourceDecorator:u,PR_ATTRIB_NAME:"atn",PR_ATTRIB_VALUE:"atv",PR_COMMENT:"com",PR_DECLARATION:"dec",PR_KEYWORD:"kwd",PR_LITERAL:"lit",
PR_NOCODE:"nocode",PR_PLAIN:"pln",PR_PUNCTUATION:"pun",PR_SOURCE:"src",PR_STRING:"str",PR_TAG:"tag",PR_TYPE:"typ"}})();

View File

@ -0,0 +1,290 @@
html
{
overflow: auto;
background-color: #fff;
}
body
{
font: 14px "DejaVu Sans Condensed", "Liberation Sans", "Nimbus Sans L", Tahoma, Geneva, "Helvetica Neue", Helvetica, Arial, sans serif;
line-height: 130%;
color: #000;
background-color: #fff;
}
a {
color: #444;
}
a:visited {
color: #444;
}
a:active {
color: #444;
}
header
{
display: block;
padding: 6px 4px;
}
.class-description {
font-style: italic;
font-family: Palatino, 'Palatino Linotype', serif;
font-size: 130%;
line-height: 140%;
margin-bottom: 1em;
margin-top: 1em;
}
#main {
float: left;
width: 100%;
}
section
{
display: block;
background-color: #fff;
padding: 12px 24px;
border-bottom: 1px solid #ccc;
margin-right: 240px;
}
.variation {
display: none;
}
.optional:after {
content: "opt";
font-size: 60%;
color: #aaa;
font-style: italic;
font-weight: lighter;
}
nav
{
display: block;
float: left;
margin-left: -230px;
margin-top: 28px;
width: 220px;
border-left: 1px solid #ccc;
padding-left: 9px;
}
nav ul {
font-family: 'Lucida Grande', 'Lucida Sans Unicode', arial, sans-serif;
font-size: 100%;
line-height: 17px;
padding:0;
margin:0;
list-style-type:none;
}
nav h2 a, nav h2 a:visited {
color: #A35A00;
text-decoration: none;
}
nav h3 {
margin-top: 12px;
}
nav li {
margin-top: 6px;
}
nav a {
color: #5C5954;
}
nav a:visited {
color: #5C5954;
}
nav a:active {
color: #5C5954;
}
footer {
display: block;
padding: 6px;
margin-top: 12px;
font-style: italic;
font-size: 90%;
}
h1
{
font-size: 200%;
font-weight: bold;
letter-spacing: -0.01em;
margin: 6px 0 9px 0;
}
h2
{
font-size: 170%;
font-weight: bold;
letter-spacing: -0.01em;
margin: 6px 0 3px 0;
}
h3
{
font-size: 150%;
font-weight: bold;
letter-spacing: -0.01em;
margin-top: 16px;
margin: 6px 0 3px 0;
}
h4
{
font-size: 130%;
font-weight: bold;
letter-spacing: -0.01em;
margin-top: 16px;
margin: 18px 0 3px 0;
color: #A35A00;
}
h5, .container-overview .subsection-title
{
font-size: 120%;
font-weight: bold;
letter-spacing: -0.01em;
margin: 8px 0 3px -16px;
}
h6
{
font-size: 100%;
letter-spacing: -0.01em;
margin: 6px 0 3px 0;
font-style: italic;
}
.ancestors { color: #999; }
.ancestors a
{
color: #999 !important;
text-decoration: none;
}
.important
{
font-weight: bold;
color: #950B02;
}
.yes-def {
text-indent: -1000px;
}
.type-signature {
color: #aaa;
}
.name, .signature {
font-family: Consolas, "Lucida Console", Monaco, monospace;
}
.details { margin-top: 14px; border-left: 2px solid #DDD; }
.details dt { width:100px; float:left; padding-left: 10px; padding-top: 6px; }
.details dd { margin-left: 50px; }
.details ul { margin: 0; }
.details ul { list-style-type: none; }
.details li { margin-left: 30px; padding-top: 6px; }
.details pre.prettyprint { margin: 0 }
.details .object-value { padding-top: 0; }
.description {
margin-bottom: 1em;
margin-left: -16px;
margin-top: 1em;
}
.code-caption
{
font-style: italic;
font-family: Palatino, 'Palatino Linotype', serif;
font-size: 107%;
margin: 0;
}
.prettyprint
{
border: 1px solid #ddd;
width: 80%;
overflow: auto;
}
.prettyprint.source {
width: inherit;
}
.prettyprint code
{
font-family: Consolas, 'Lucida Console', Monaco, monospace;
font-size: 100%;
line-height: 18px;
display: block;
padding: 4px 12px;
margin: 0;
background-color: #fff;
color: #000;
border-left: 3px #ddd solid;
}
.prettyprint code span.line
{
display: inline-block;
}
.params, .props
{
border-spacing: 0;
border: 0;
border-collapse: collapse;
}
.params .name, .props .name, .name code {
color: #A35A00;
font-family: Consolas, 'Lucida Console', Monaco, monospace;
font-size: 100%;
}
.params td, .params th, .props td, .props th
{
border: 1px solid #ddd;
margin: 0px;
text-align: left;
vertical-align: top;
padding: 4px 6px;
display: table-cell;
}
.params thead tr, .props thead tr
{
background-color: #ddd;
font-weight: bold;
}
.params .params thead tr, .props .props thead tr
{
background-color: #fff;
font-weight: bold;
}
.params th, .props th { border-right: 1px solid #aaa; }
.params thead .last, .props thead .last { border-right: 1px solid #ddd; }
.disabled {
color: #454545;
}

View File

@ -0,0 +1,111 @@
/* JSDoc prettify.js theme */
/* plain text */
.pln {
color: #000000;
font-weight: normal;
font-style: normal;
}
/* string content */
.str {
color: #006400;
font-weight: normal;
font-style: normal;
}
/* a keyword */
.kwd {
color: #000000;
font-weight: bold;
font-style: normal;
}
/* a comment */
.com {
font-weight: normal;
font-style: italic;
}
/* a type name */
.typ {
color: #000000;
font-weight: normal;
font-style: normal;
}
/* a literal value */
.lit {
color: #006400;
font-weight: normal;
font-style: normal;
}
/* punctuation */
.pun {
color: #000000;
font-weight: bold;
font-style: normal;
}
/* lisp open bracket */
.opn {
color: #000000;
font-weight: bold;
font-style: normal;
}
/* lisp close bracket */
.clo {
color: #000000;
font-weight: bold;
font-style: normal;
}
/* a markup tag name */
.tag {
color: #006400;
font-weight: normal;
font-style: normal;
}
/* a markup attribute name */
.atn {
color: #006400;
font-weight: normal;
font-style: normal;
}
/* a markup attribute value */
.atv {
color: #006400;
font-weight: normal;
font-style: normal;
}
/* a declaration */
.dec {
color: #000000;
font-weight: bold;
font-style: normal;
}
/* a variable name */
.var {
color: #000000;
font-weight: normal;
font-style: normal;
}
/* a function name */
.fun {
color: #000000;
font-weight: bold;
font-style: normal;
}
/* Specify class=linenums on a pre to get line numbering */
ol.linenums {
margin-top: 0;
margin-bottom: 0;
}

View File

@ -0,0 +1,132 @@
/* Tomorrow Theme */
/* Original theme - https://github.com/chriskempson/tomorrow-theme */
/* Pretty printing styles. Used with prettify.js. */
/* SPAN elements with the classes below are added by prettyprint. */
/* plain text */
.pln {
color: #4d4d4c; }
@media screen {
/* string content */
.str {
color: #718c00; }
/* a keyword */
.kwd {
color: #8959a8; }
/* a comment */
.com {
color: #8e908c; }
/* a type name */
.typ {
color: #4271ae; }
/* a literal value */
.lit {
color: #f5871f; }
/* punctuation */
.pun {
color: #4d4d4c; }
/* lisp open bracket */
.opn {
color: #4d4d4c; }
/* lisp close bracket */
.clo {
color: #4d4d4c; }
/* a markup tag name */
.tag {
color: #c82829; }
/* a markup attribute name */
.atn {
color: #f5871f; }
/* a markup attribute value */
.atv {
color: #3e999f; }
/* a declaration */
.dec {
color: #f5871f; }
/* a variable name */
.var {
color: #c82829; }
/* a function name */
.fun {
color: #4271ae; } }
/* Use higher contrast and text-weight for printable form. */
@media print, projection {
.str {
color: #060; }
.kwd {
color: #006;
font-weight: bold; }
.com {
color: #600;
font-style: italic; }
.typ {
color: #404;
font-weight: bold; }
.lit {
color: #044; }
.pun, .opn, .clo {
color: #440; }
.tag {
color: #006;
font-weight: bold; }
.atn {
color: #404; }
.atv {
color: #060; } }
/* Style */
/*
pre.prettyprint {
background: white;
font-family: Menlo, Monaco, Consolas, monospace;
font-size: 12px;
line-height: 1.5;
border: 1px solid #ccc;
padding: 10px; }
*/
/* Specify class=linenums on a pre to get line numbering */
ol.linenums {
margin-top: 0;
margin-bottom: 0; }
/* IE indents via margin-left */
li.L0,
li.L1,
li.L2,
li.L3,
li.L4,
li.L5,
li.L6,
li.L7,
li.L8,
li.L9 {
/* */ }
/* Alternate shading for lines */
li.L1,
li.L3,
li.L5,
li.L7,
li.L9 {
/* */ }

129
lib/driver.js Executable file
View File

@ -0,0 +1,129 @@
/** @module driver */
"use strict";
var helpers = require('./helpers');
/**
* Base Database Driver
*
* @type {{identifierChar: string, quoteIdentifiers: quoteIdentifiers}}
*/
module.exports = {
identifierChar: '"',
tablePrefix: null,
/**
* Low level function for naive quoting of strings
* @param {String} str
* @return {String}
* @private
*/
_quote: function(str) {
return (helpers.isString(str) && ! (str.startsWith(this.identifierChar) || str.endsWith(this.identifierChar)))
? this.identifierChar + str + this.identifierChar
: str;
},
/**
* Sets the table prefix on the passed string
*
* @param {String} str
* @return {String}
* @private
*/
_prefix: function(str) {
if (str.startsWith(this.prefix))
{
return str;
}
return this.prefix + str;
},
/**
* Set the limit clause
* @param {String} sql
* @param {Number} limit
* @param {Number|null} offset
* @return {String}
*/
limit: function(sql, limit, offset) {
sql += " LIMIT " + limit;
if (helpers.isNumber(offset))
{
sql += " OFFSET " + offset;
}
return sql;
},
/**
* Prefixes a table if it is not already prefixed
*
* @param {String} table
* @return {String}
*/
prefixTable: function(table) {
if (this.tablePrefix)
{
// Split identifier by period, will split into:
// database.schema.table OR
// schema.table OR
// database.table OR
// table
var idents = table.split('.', table);
var segments = idents.length;
// Add the database prefix
idents[segments - 1] = this._prefix(idents[segments - 1]);
table = idents.join('.');
}
return table;
},
/**
* Quote database table name, and set prefix
*
* @param {String} table
* @return {String}
*/
quoteTable: function(table) {
table = this.prefixTable(table);
// Quote after prefix
return this.quoteIdentifiers(table);
},
/**
* Use the driver's escape character to quote identifiers
*
* @param {String|Array}
* @return {String|Array}
*/
quoteIdentifiers: function(str) {
var hiers, raw;
// Recurse for arrays of identifiiers
if (Array.isArray(str))
{
return str.map(this.quoteIdentifiers);
}
// Handle commas
str = helpers.splitTrim(',', str);
// Split identifiers by period
hiers = str.split('.').map(String.trim).map(this._quote);
raw = hiers.join('.');
// TODO: fix functions
return raw;
}
};

27
lib/drivers/mysql.js Executable file
View File

@ -0,0 +1,27 @@
"use strict";
/**
* Driver for MySQL databases
*
* @returns {driver}
*/
module.exports = function() {
var driver = require('../driver'),
helpers = require('../helpers');
driver.identifierChar = '`';
/**
* Override default limit method because mysql likes to be different
*/
driver.limit = function(sql, limit, offset) {
if ( ! helpers.isNumber(offset))
{
return sql += " LIMIT " + limit;
}
return sql += " LIMIT " + offset + "," + limit;
};
return driver;
};

12
lib/drivers/pg.js Executable file
View File

@ -0,0 +1,12 @@
"use strict";
/**
* Driver for PostgreSQL databases
*
* @returns {driver}
*/
module.exports = function() {
var driver = require('../driver');
return driver;
};

59
lib/helpers.js Executable file
View File

@ -0,0 +1,59 @@
/** @module helpers */
"use strict";
if (!String.prototype.startsWith) {
Object.defineProperty(String.prototype, 'startsWith', {
enumerable: false,
configurable: false,
writable: false,
value: function (searchString, position) {
position = position || 0;
return this.lastIndexOf(searchString, position) === position;
}
});
}
if (!String.prototype.endsWith) {
Object.defineProperty(String.prototype, 'endsWith', {
value: function (searchString, position) {
var subjectString = this.toString();
if (position === undefined || position > subjectString.length) {
position = subjectString.length;
}
position -= searchString.length;
var lastIndex = subjectString.indexOf(searchString, position);
return lastIndex !== -1 && lastIndex === position;
}
});
}
module.exports = {
/**
* Split a string by a character, trim the string
* and rejoin the string
*
* @param {String} char
* @param {String} string
* @return {String}
*/
splitTrim: function(char, string) {
return string.split(char).map(String.trim).join(char);
},
/**
* Determine whether an object is a string
* @param {mixed} obj
* @return {bool}
*/
isString: function(obj) {
return (typeof obj === 'string' || obj instanceof String);
},
/**
* Determine whether an object is numeric
* @param {mixed} obj
* @return {bool}
*/
isNumber: function(obj) {
return ! isNaN(parseFloat(obj)) && isFinite(obj);
}
};

11
lib/node-query.js Normal file → Executable file
View File

@ -1,5 +1,14 @@
"use strict";
module.exports = function query() {
module.exports = function(driverType, connObject) {
var connection = null,
driverType = null;
return {
connect: function(driverName, connObject) {
driverType = driverName;
connection = connObject;
}
};
};

309
lib/query-builder.js Executable file
View File

@ -0,0 +1,309 @@
/** @module query-builder */
var async = require('async');
module.exports = function(driver) {
"use strict";
/**
* Variables controlling the sql building
*
* @private
* @type {{}}
*/
var state = {};
// ------------------------------------------------------------------------
/**
* "Private" methods
*
* @private
*/
var _p = {
/**
* Complete the sql building based on the type provided
*
* @param {String} type
* @param {String} table
* @return {String}
*/
compile: function (type, table) {
switch(type) {
case "insert":
break;
case "update":
break;
case "delete":
break;
default:
break;
}
},
compileType: function (type, table) {
}
};
// ------------------------------------------------------------------------
// Set up state object
this.resetQuery();
// ------------------------------------------------------------------------
// ! Query Builder Methods
// ------------------------------------------------------------------------
/**
* Specify rows to select in the query
*
* @param {String|Array} fields
* @returns {exports}
*/
this.select = function(fields) {
// Split/trim fields by comma
fields = (Array.isArray(fields)) ? fields : fields.split(",").map(String.trim);
// Split on 'As'
fields.forEach(function (field, index) {
if (field.match(/as/i))
{
fields[index] = field.split(/ as /i).map(String.trim);
}
});
var safeArray = driver.quoteIdentifiers(fields);
// Join the strings back together
safeArray.forEach(function (field, index) {
if (Array.isArray(field))
{
safeArray[index] = safeArray[index].join(' AS ');
}
});
state.selectString += safeArray.join(', ');
return this;
};
/**
* Specify the database table to select from
*
* @param {String} tableName
* @returns {exports}
*/
this.from = function(tableName) {
// Split identifiers on spaces
var identArray = String.trim(tableName).split(' ').map(String.trim);
// Quote/prefix identifiers
identArray[0] = driver.quoteTable(identArray[0]);
identArray = driver.quoteIdentifiers(identArray);
// Put it back together
state.fromString = identArray.join(' ');
return this;
};
this.like = function(field, val, pos) {
};
this.orLike = function(field, val, pos) {
};
this.orNotLike = function(field, val, pos) {
};
this.having = function(key, val) {
};
this.orHaving = function(key, val) {
};
this.where = function(key, val) {
};
this.orWhere = function(key, val) {
};
this.whereIn = function(key, val) {
};
this.orWhereIn = function(key, val) {
};
this.whereNotIn = function(key, val) {
};
this.orWhereNotIn = function(key, val) {
};
this.set = function(key, val) {
return this;
};
this.join = function(table1, cond, table2, type) {
type = type || "inner";
return this;
};
this.groupBy = function(field) {
};
this.orderBy = function(field) {
};
this.limit = function(limit, offset) {
state.limit = limit;
state.offset = offset;
return this;
};
this.groupStart = function() {
};
this.orGroupStart = function() {
};
this.orNotGroupStart = function() {
};
this.groupEnd = function() {
};
// ------------------------------------------------------------------------
// ! Result Methods
// ------------------------------------------------------------------------
this.get = function(table, limit, offset) {
// Reset state
this.resetQuery();
};
this.getWhere = function(table, where, limit, offset) {
// Reset state
this.resetQuery();
};
this.insert = function(table, data) {
// Reset state
this.resetQuery();
};
this.update = function(table, data) {
// Reset state
this.resetQuery();
};
this['delete'] = function (table, where) {
// Reset state
this.resetQuery();
};
// ------------------------------------------------------------------------
// ! Methods returning SQL
// ------------------------------------------------------------------------
/**
* Return generated select query SQL
*
* @return {String}
*/
this.getCompiledSelect = function() {
// Return sql
// Reset state
this.resetQuery();
};
this.getCompiledInsert = function() {
// Return sql
// Reset state
this.resetQuery();
};
this.getCompiledUpdate = function() {
// Return sql
// Reset state
this.resetQuery();
};
this.getCompiledDelete = function() {
// Return sql
// Reset state
this.resetQuery();
};
// ----------------------------------------------------------------------------
// ! Miscellaneous Methods
// ----------------------------------------------------------------------------
/**
* Reset the object state for a new query
*
* @return void
*/
this.resetQuery = function() {
state = {
// Arrays/Maps
queryMap: {},
values: [],
whereValues: [],
setArrayKeys: [],
orderArray: [],
groupArray: [],
havingMap: [],
// Partials
selectString: '',
fromString: '',
setString: '',
orderString: '',
groupString: '',
// Other various values
limit: null,
offset: null
};
};
/**
* Returns the current class state for testing or other purposes
*
* @return {Object}
*/
this.getState = function() {
return state;
};
return this;
};

1
node_modules/.bin/grunt-jsdoc generated vendored Symbolic link
View File

@ -0,0 +1 @@
../grunt-jsdoc/bin/grunt-jsdoc

1
node_modules/.bin/jsdoc generated vendored Symbolic link
View File

@ -0,0 +1 @@
../jsdoc/nodejs/bin/jsdoc

1
node_modules/.bin/nodeunit generated vendored Symbolic link
View File

@ -0,0 +1 @@
../nodeunit/bin/nodeunit

3
node_modules/async/.travis.yml generated vendored Normal file
View File

@ -0,0 +1,3 @@
language: node_js
node_js:
- "0.10"

19
node_modules/async/LICENSE generated vendored Normal file
View File

@ -0,0 +1,19 @@
Copyright (c) 2010-2014 Caolan McMahon
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

1646
node_modules/async/README.md generated vendored Normal file

File diff suppressed because it is too large Load Diff

11
node_modules/async/component.json generated vendored Normal file
View File

@ -0,0 +1,11 @@
{
"name": "async",
"repo": "caolan/async",
"description": "Higher-order functions and common patterns for asynchronous code",
"version": "0.1.23",
"keywords": [],
"dependencies": {},
"development": {},
"main": "lib/async.js",
"scripts": [ "lib/async.js" ]
}

1123
node_modules/async/lib/async.js generated vendored Executable file

File diff suppressed because it is too large Load Diff

45
node_modules/async/package.json generated vendored Normal file

File diff suppressed because one or more lines are too long

22
node_modules/grunt-contrib-nodeunit/LICENSE-MIT generated vendored Normal file
View File

@ -0,0 +1,22 @@
Copyright (c) 2014 "Cowboy" Ben Alman, contributors
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

129
node_modules/grunt-contrib-nodeunit/README.md generated vendored Normal file
View File

@ -0,0 +1,129 @@
# grunt-contrib-nodeunit v0.4.1 [![Build Status: Linux](https://travis-ci.org/gruntjs/grunt-contrib-nodeunit.png?branch=master)](https://travis-ci.org/gruntjs/grunt-contrib-nodeunit) <a href="https://ci.appveyor.com/project/gruntjs/grunt-contrib-nodeunit"><img src="https://ci.appveyor.com/api/projects/status/8526qwiyaavbfbxh/branch/master" alt="Build Status: Windows" height="18" /></a>
> Run Nodeunit unit tests.
## Getting Started
This plugin requires Grunt `~0.4.0`
If you haven't used [Grunt](http://gruntjs.com/) before, be sure to check out the [Getting Started](http://gruntjs.com/getting-started) guide, as it explains how to create a [Gruntfile](http://gruntjs.com/sample-gruntfile) as well as install and use Grunt plugins. Once you're familiar with that process, you may install this plugin with this command:
```shell
npm install grunt-contrib-nodeunit --save-dev
```
Once the plugin has been installed, it may be enabled inside your Gruntfile with this line of JavaScript:
```js
grunt.loadNpmTasks('grunt-contrib-nodeunit');
```
## Nodeunit task
_Run this task with the `grunt nodeunit` command._
Task targets, files and options may be specified according to the grunt [Configuring tasks](http://gruntjs.com/configuring-tasks) guide.
This plugin provides server-side JavaScript unit testing via [nodeunit](https://github.com/caolan/nodeunit/). If you're looking to test JavaScript that uses `window` or the DOM, please use the [grunt-contrib-qunit plugin](https://github.com/gruntjs/grunt-contrib-qunit)`qunit` task.
### Settings
#### options.reporter
* Type: `String`
* Default: `'grunt'`
Specifies the reporter you want to use. For example, `default`, `verbose` or `tap`.
#### options.reporterOutput
* Type: `Boolean`
* Default: `false`
Specifies the file the `reporter`'s output should be saved to. For example, `tests.tap`.
#### options.reporterOptions
* Type: `Object`
* Default: `{}`
Specifies the options passed to the `reporter`. For example, the `junit` reporter requires the `output` option
to be set:
```js
grunt.initConfig({
nodeunit: {
all: ['test/*_test.js'],
options: {
reporter: 'junit',
reporterOptions: {
output: 'outputdir'
}
}
}
});
```
### Usage examples
#### Wildcards
In this example, `grunt nodeunit:all` or `grunt nodeunit` will test all files ending with `_test.js` in the `test` directory.
```js
grunt.initConfig({
nodeunit: {
all: ['test/*_test.js']
}
});
```
With a slight modification, `grunt nodeunit:all` will test files matching the same pattern in the `test` directory _and all subdirectories_.
```js
grunt.initConfig({
nodeunit: {
all: ['test/**/*_test.js']
}
});
```
#### Using Other Reporters
To use a reporter other than the default one, you can specify the `reporter` and `reporterOutput` parameters.
```js
grunt.initConfig({
nodeunit: {
all: ['test/*_test.js'],
options: {
reporter: 'tap',
reporterOutput: 'tests.tap',
reporterOptions: {
output: 'outputdir'
}
}
}
});
```
## Release History
* 2014-06-21v0.4.1Fixes Windows JUnit issue. Check error.stack exists.
* 2014-05-14v0.4.0Bump nodeunit to v0.9.0
* 2014-01-26v0.3.0Adds 'reporter' and 'reporterOutput' options.
* 2013-10-19v0.2.2Allow missing operators on error object.
* 2013-09-24v0.2.1Fix error display.
* 2013-05-23v0.2.0Bump nodeunit to v0.8.0
* 2013-02-15v0.1.2First official release for Grunt 0.4.0.
* 2013-01-18v0.1.2rc6Updating grunt/gruntplugin dependencies to rc6. Changing in-development grunt/gruntplugin dependency versions from tilde version ranges to specific versions.
* 2013-01-09v0.1.2rc5Updating to work with grunt v0.4.0rc5. Switching to this.filesSrc api.
* 2012-11-13v0.1.1Switch to this.file api internally.
* 2012-11-04v0.1.0Work in progress, not yet officially released.
---
Task submitted by ["Cowboy" Ben Alman](http://benalman.com)
*This file was generated on Sat Jun 21 2014 17:24:52.*

View File

@ -0,0 +1,22 @@
Copyright (c) 2012 "Cowboy" Ben Alman
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

View File

@ -0,0 +1,186 @@
# JavaScript Hooker
Monkey-patch (hook) functions for debugging and stuff.
## Getting Started
This code should work just fine in Node.js:
First, install the module with: `npm install hooker`
```javascript
var hooker = require('hooker');
hooker.hook(Math, "max", function() {
console.log(arguments.length + " arguments passed");
});
Math.max(5, 6, 7) // logs: "3 arguments passed", returns 7
```
Or in the browser:
```html
<script src="dist/ba-hooker.min.js"></script>
<script>
hook(Math, "max", function() {
console.log(arguments.length + " arguments passed");
});
Math.max(5, 6, 7) // logs: "3 arguments passed", returns 7
</script>
```
In the browser, you can attach Hooker's methods to any object.
```html
<script>
this.exports = Bocoup.utils;
</script>
<script src="dist/ba-hooker.min.js"></script>
<script>
Bocoup.utils.hook(Math, "max", function() {
console.log(arguments.length + " arguments passed");
});
Math.max(5, 6, 7) // logs: "3 arguments passed", returns 7
</script>
```
## Documentation
### hooker.hook
Monkey-patch (hook) one or more methods of an object.
#### Signature:
`hooker.hook(object, [ props, ] [options | prehookFunction])`
#### `props`
The optional `props` argument can be a method name, array of method names or null. If null (or omitted), all enumerable methods of `object` will be hooked.
#### `options`
* `pre` - (Function) a pre-hook function to be executed before the original function. Arguments passed into the method will be passed into the pre-hook function as well.
* `post` - (Function) a post-hook function to be executed after the original function. The original function's result is passed into the post-hook function as its first argument, followed by the method arguments.
* `once` - (Boolean) if true, auto-unhook the function after the first execution.
* `passName` - (Boolean) if true, pass the name of the method into the pre-hook function as its first arg (preceding all other arguments), and into the post-hook function as the second arg (after result but preceding all other arguments).
#### Returns:
An array of hooked method names.
### hooker.unhook
Un-monkey-patch (unhook) one or more methods of an object.
#### Signature:
`hooker.unhook(object [, props ])`
#### `props`
The optional `props` argument can be a method name, array of method names or null. If null (or omitted), all methods of `object` will be unhooked.
#### Returns:
An array of unhooked method names.
### hooker.orig
Get a reference to the original method from a hooked function.
#### Signature:
`hooker.orig(object, props)`
### hooker.override
When a pre- or post-hook returns the result of this function, the value
passed will be used in place of the original function's return value. Any
post-hook override value will take precedence over a pre-hook override value.
#### Signature:
`hooker.override(value)`
### hooker.preempt
When a pre-hook returns the result of this function, the value passed will
be used in place of the original function's return value, and the original
function will NOT be executed.
#### Signature:
`hooker.preempt(value)`
### hooker.filter
When a pre-hook returns the result of this function, the context and
arguments passed will be applied into the original function.
#### Signature:
`hooker.filter(context, arguments)`
## Examples
See the unit tests for more examples.
```javascript
var hooker = require('hooker');
// Simple logging.
hooker.hook(Math, "max", function() {
console.log(arguments.length + " arguments passed");
});
Math.max(5, 6, 7) // logs: "3 arguments passed", returns 7
hooker.unhook(Math, "max"); // (This is assumed between all further examples)
Math.max(5, 6, 7) // 7
// Returning hooker.override(value) overrides the original value.
hooker.hook(Math, "max", function() {
if (arguments.length === 0) {
return hooker.override(9000);
}
});
Math.max(5, 6, 7) // 7
Math.max() // 9000
// Auto-unhook after one execution.
hooker.hook(Math, "max", {
once: true,
pre: function() {
console.log("Init something here");
}
});
Math.max(5, 6, 7) // logs: "Init something here", returns 7
Math.max(5, 6, 7) // 7
// Filter `this` and arguments through a pre-hook function.
hooker.hook(Math, "max", {
pre: function() {
var args = [].map.call(arguments, function(num) {
return num * 2;
});
return hooker.filter(this, args); // thisValue, arguments
}
});
Math.max(5, 6, 7) // 14
// Modify the original function's result with a post-hook function.
hooker.hook(Math, "max", {
post: function(result) {
return hooker.override(result * 100);
}
});
Math.max(5, 6, 7) // 700
// Hook every Math method. Note: if Math's methods were enumerable, the second
// argument could be omitted. Since they aren't, an array of properties to hook
// must be explicitly passed. Non-method properties will be skipped.
// See a more generic example here: http://bit.ly/vvJlrS
hooker.hook(Math, Object.getOwnPropertyNames(Math), {
passName: true,
pre: function(name) {
console.log("=> Math." + name, [].slice.call(arguments, 1));
},
post: function(result, name) {
console.log("<= Math." + name, result);
}
});
var result = Math.max(5, 6, 7);
// => Math.max [ 5, 6, 7 ]
// <= Math.max 7
result // 7
result = Math.ceil(3.456);
// => Math.ceil [ 3.456 ]
// <= Math.ceil 4
result // 4
```
## Contributing
In lieu of a formal styleguide, take care to maintain the existing coding style. Add unit tests for any new or changed functionality. Lint and test your code using [grunt](https://github.com/cowboy/grunt).
_Also, please don't edit files in the "dist" subdirectory as they are generated via grunt. You'll find source code in the "lib" subdirectory!_
## Release History
2012/01/09 - v0.2.3 - First official release.
## License
Copyright (c) 2012 "Cowboy" Ben Alman
Licensed under the MIT license.
<http://benalman.com/about/license/>

View File

@ -0,0 +1,101 @@
var path = require('path');
var fs = require('fs');
var nodeunit = require('nodeunit');
var filepaths = fs.readdirSync('test').map(function(filename) {
return path.join('test', filename);
});
var unfinished = {};
var currentModule;
function sendMessage(message) {
process.stdout.write(JSON.stringify(message) + '\n');
}
// If an exception is thrown, let the parent process know and exit.
process.on('uncaughtException', function (e) {
sendMessage({error: [e.name, e.message, e.stack]});
process.exit();
});
// If Nodeunit explodes because a test was missing test.done(), handle it.
var unfinished = {};
process.on('exit', function (e) {
var len = Object.keys(unfinished).length
if (len > 0) {
sendMessage({exit: ['UNFINISHED']});
// process.reallyExit(len);
} else {
sendMessage({exit: ['finished']});
}
// process.exit();
});
nodeunit.reporters.test = {
run: function(files, options, callback) {
// Nodeunit needs absolute paths.
var paths = files.map(function (filepath) {
return path.resolve(filepath);
});
nodeunit.runFiles(paths, {
// No idea.
testspec: undefined,
// Executed when the first test in a file is run. If no tests exist in
// the file, this doesn't execute.
moduleStart: function(name) {
// Keep track of this so that moduleDone output can be suppressed in
// cases where a test file contains no tests.
currentModule = name;
// Send back to the parent process.
sendMessage({moduleStart: [name.toString()]});
},
// Executed after a file is done being processed. This executes whether
// tests exist in the file or not.
moduleDone: function(name) {
// Abort if no tests actually ran.
if (name !== currentModule) { return; }
// Send back to the parent process.
sendMessage({moduleDone: [name.toString()]});
},
// Executed before each test is run.
testStart: function(name) {
// Keep track of the current test, in case test.done() was omitted
// and Nodeunit explodes.
unfinished[name] = name;
// Send back to the parent process.
sendMessage({testStart: [name.toString()]});
},
// Executed after each test and all its assertions are run.
testDone: function(name, assertions) {
delete unfinished[name];
// Send back to the parent process.
sendMessage({testDone: [
name.toString(),
assertions.failures(),
assertions.map(function(assertion) {
var e = assertion.error;
if (e) {
assertion.error = {
name: e.name,
message: e.message,
stack: e.stack
};
}
return assertion;
})
]});
},
// Executed when everything is all done.
done: function (assertions) {
// Send back to the parent process.
sendMessage({done: [
assertions.failures(),
assertions.duration,
assertions
]});
}
});
}
}
nodeunit.reporters.test.run(filepaths, {});

View File

@ -0,0 +1,169 @@
/*! JavaScript Hooker - v0.2.3 - 1/29/2012
* http://github.com/cowboy/javascript-hooker
* Copyright (c) 2012 "Cowboy" Ben Alman; Licensed MIT */
(function(exports) {
// Get an array from an array-like object with slice.call(arrayLikeObject).
var slice = [].slice;
// Get an "[object [[Class]]]" string with toString.call(value).
var toString = {}.toString;
// I can't think of a better way to ensure a value is a specific type other
// than to create instances and use the `instanceof` operator.
function HookerOverride(v) { this.value = v; }
function HookerPreempt(v) { this.value = v; }
function HookerFilter(c, a) { this.context = c; this.args = a; }
// When a pre- or post-hook returns the result of this function, the value
// passed will be used in place of the original function's return value. Any
// post-hook override value will take precedence over a pre-hook override
// value.
exports.override = function(value) {
return new HookerOverride(value);
};
// When a pre-hook returns the result of this function, the value passed will
// be used in place of the original function's return value, and the original
// function will NOT be executed.
exports.preempt = function(value) {
return new HookerPreempt(value);
};
// When a pre-hook returns the result of this function, the context and
// arguments passed will be applied into the original function.
exports.filter = function(context, args) {
return new HookerFilter(context, args);
};
// Execute callback(s) for properties of the specified object.
function forMethods(obj, props, callback) {
var prop;
if (typeof props === "string") {
// A single prop string was passed. Create an array.
props = [props];
} else if (props == null) {
// No props were passed, so iterate over all properties, building an
// array. Unfortunately, Object.keys(obj) doesn't work everywhere yet, so
// this has to be done manually.
props = [];
for (prop in obj) {
if (obj.hasOwnProperty(prop)) {
props.push(prop);
}
}
}
// Execute callback for every method in the props array.
var i = props.length;
while (i--) {
// If the property isn't a function...
if (toString.call(obj[props[i]]) !== "[object Function]" ||
// ...or the callback returns false...
callback(obj, props[i]) === false) {
// ...remove it from the props array to be returned.
props.splice(i, 1);
}
}
// Return an array of method names for which the callback didn't fail.
return props;
}
// Monkey-patch (hook) a method of an object.
exports.hook = function(obj, props, options) {
// If the props argument was omitted, shuffle the arguments.
if (options == null) {
options = props;
props = null;
}
// If just a function is passed instead of an options hash, use that as a
// pre-hook function.
if (typeof options === "function") {
options = {pre: options};
}
// Hook the specified method of the object.
return forMethods(obj, props, function(obj, prop) {
// The original (current) method.
var orig = obj[prop];
// The new hooked function.
function hooked() {
var result, origResult, tmp;
// Get an array of arguments.
var args = slice.call(arguments);
// If passName option is specified, prepend prop to the args array,
// passing it as the first argument to any specified hook functions.
if (options.passName) {
args.unshift(prop);
}
// If a pre-hook function was specified, invoke it in the current
// context with the passed-in arguments, and store its result.
if (options.pre) {
result = options.pre.apply(this, args);
}
if (result instanceof HookerFilter) {
// If the pre-hook returned hooker.filter(context, args), invoke the
// original function with that context and arguments, and store its
// result.
origResult = result = orig.apply(result.context, result.args);
} else if (result instanceof HookerPreempt) {
// If the pre-hook returned hooker.preempt(value) just use the passed
// value and don't execute the original function.
origResult = result = result.value;
} else {
// Invoke the original function in the current context with the
// passed-in arguments, and store its result.
origResult = orig.apply(this, arguments);
// If the pre-hook returned hooker.override(value), use the passed
// value, otherwise use the original function's result.
result = result instanceof HookerOverride ? result.value : origResult;
}
if (options.post) {
// If a post-hook function was specified, invoke it in the current
// context, passing in the result of the original function as the
// first argument, followed by any passed-in arguments.
tmp = options.post.apply(this, [origResult].concat(args));
if (tmp instanceof HookerOverride) {
// If the post-hook returned hooker.override(value), use the passed
// value, otherwise use the previously computed result.
result = tmp.value;
}
}
// Unhook if the "once" option was specified.
if (options.once) {
exports.unhook(obj, prop);
}
// Return the result!
return result;
}
// Re-define the method.
obj[prop] = hooked;
// Fail if the function couldn't be hooked.
if (obj[prop] !== hooked) { return false; }
// Store a reference to the original method as a property on the new one.
obj[prop]._orig = orig;
});
};
// Get a reference to the original method from a hooked function.
exports.orig = function(obj, prop) {
return obj[prop]._orig;
};
// Un-monkey-patch (unhook) a method of an object.
exports.unhook = function(obj, props) {
return forMethods(obj, props, function(obj, prop) {
// Get a reference to the original method, if it exists.
var orig = exports.orig(obj, prop);
// If there's no original method, it can't be unhooked, so fail.
if (!orig) { return false; }
// Unhook the method.
obj[prop] = orig;
});
};
}(typeof exports === "object" && exports || this));

View File

@ -0,0 +1,4 @@
/*! JavaScript Hooker - v0.2.3 - 1/29/2012
* http://github.com/cowboy/javascript-hooker
* Copyright (c) 2012 "Cowboy" Ben Alman; Licensed MIT */
(function(a){function d(a){this.value=a}function e(a){this.value=a}function f(a,b){this.context=a,this.args=b}function g(a,b,d){var e;if(typeof b=="string")b=[b];else if(b==null){b=[];for(e in a)a.hasOwnProperty(e)&&b.push(e)}var f=b.length;while(f--)(c.call(a[b[f]])!=="[object Function]"||d(a,b[f])===!1)&&b.splice(f,1);return b}var b=[].slice,c={}.toString;a.override=function(a){return new d(a)},a.preempt=function(a){return new e(a)},a.filter=function(a,b){return new f(a,b)},a.hook=function(c,h,i){return i==null&&(i=h,h=null),typeof i=="function"&&(i={pre:i}),g(c,h,function(c,g){function j(){var j,k,l,m=b.call(arguments);return i.passName&&m.unshift(g),i.pre&&(j=i.pre.apply(this,m)),j instanceof f?k=j=h.apply(j.context,j.args):j instanceof e?k=j=j.value:(k=h.apply(this,arguments),j=j instanceof d?j.value:k),i.post&&(l=i.post.apply(this,[k].concat(m)),l instanceof d&&(j=l.value)),i.once&&a.unhook(c,g),j}var h=c[g];c[g]=j;if(c[g]!==j)return!1;c[g]._orig=h})},a.orig=function(a,b){return a[b]._orig},a.unhook=function(b,c){return g(b,c,function(b,c){var d=a.orig(b,c);if(!d)return!1;b[c]=d})}})(typeof exports=="object"&&exports||this)

View File

@ -0,0 +1,47 @@
/*global config:true, task:true*/
config.init({
pkg: '<json:package.json>',
meta: {
name: 'JavaScript Hooker',
banner: '/*! <%= meta.name %> - v<%= pkg.version %> - <%= template.today("m/d/yyyy") %>\n' +
'* <%= pkg.homepage %>\n' +
'* Copyright (c) <%= template.today("yyyy") %> <%= pkg.author.name %>;' +
' Licensed <%= _.pluck(pkg.licenses, "type").join(", ") %> */'
},
concat: {
'dist/ba-hooker.js': ['<banner>', '<file_strip_banner:lib/hooker.js>']
},
min: {
'dist/ba-hooker.min.js': ['<banner>', 'dist/ba-hooker.js']
},
test: {
files: ['test/**/*.js']
},
lint: {
files: ['grunt.js', 'lib/**/*.js', 'test/**/*.js']
},
watch: {
files: '<config:lint.files>',
tasks: 'lint:files test:files'
},
jshint: {
options: {
curly: true,
eqeqeq: true,
immed: true,
latedef: true,
newcap: true,
noarg: true,
sub: true,
undef: true,
eqnull: true
},
globals: {
exports: true
}
},
uglify: {}
});
// Default task.
task.registerTask('default', 'lint:files test:files concat min');

View File

@ -0,0 +1,174 @@
/*
* JavaScript Hooker
* http://github.com/cowboy/javascript-hooker
*
* Copyright (c) 2012 "Cowboy" Ben Alman
* Licensed under the MIT license.
* http://benalman.com/about/license/
*/
(function(exports) {
// Get an array from an array-like object with slice.call(arrayLikeObject).
var slice = [].slice;
// Get an "[object [[Class]]]" string with toString.call(value).
var toString = {}.toString;
// I can't think of a better way to ensure a value is a specific type other
// than to create instances and use the `instanceof` operator.
function HookerOverride(v) { this.value = v; }
function HookerPreempt(v) { this.value = v; }
function HookerFilter(c, a) { this.context = c; this.args = a; }
// When a pre- or post-hook returns the result of this function, the value
// passed will be used in place of the original function's return value. Any
// post-hook override value will take precedence over a pre-hook override
// value.
exports.override = function(value) {
return new HookerOverride(value);
};
// When a pre-hook returns the result of this function, the value passed will
// be used in place of the original function's return value, and the original
// function will NOT be executed.
exports.preempt = function(value) {
return new HookerPreempt(value);
};
// When a pre-hook returns the result of this function, the context and
// arguments passed will be applied into the original function.
exports.filter = function(context, args) {
return new HookerFilter(context, args);
};
// Execute callback(s) for properties of the specified object.
function forMethods(obj, props, callback) {
var prop;
if (typeof props === "string") {
// A single prop string was passed. Create an array.
props = [props];
} else if (props == null) {
// No props were passed, so iterate over all properties, building an
// array. Unfortunately, Object.keys(obj) doesn't work everywhere yet, so
// this has to be done manually.
props = [];
for (prop in obj) {
if (obj.hasOwnProperty(prop)) {
props.push(prop);
}
}
}
// Execute callback for every method in the props array.
var i = props.length;
while (i--) {
// If the property isn't a function...
if (toString.call(obj[props[i]]) !== "[object Function]" ||
// ...or the callback returns false...
callback(obj, props[i]) === false) {
// ...remove it from the props array to be returned.
props.splice(i, 1);
}
}
// Return an array of method names for which the callback didn't fail.
return props;
}
// Monkey-patch (hook) a method of an object.
exports.hook = function(obj, props, options) {
// If the props argument was omitted, shuffle the arguments.
if (options == null) {
options = props;
props = null;
}
// If just a function is passed instead of an options hash, use that as a
// pre-hook function.
if (typeof options === "function") {
options = {pre: options};
}
// Hook the specified method of the object.
return forMethods(obj, props, function(obj, prop) {
// The original (current) method.
var orig = obj[prop];
// The new hooked function.
function hooked() {
var result, origResult, tmp;
// Get an array of arguments.
var args = slice.call(arguments);
// If passName option is specified, prepend prop to the args array,
// passing it as the first argument to any specified hook functions.
if (options.passName) {
args.unshift(prop);
}
// If a pre-hook function was specified, invoke it in the current
// context with the passed-in arguments, and store its result.
if (options.pre) {
result = options.pre.apply(this, args);
}
if (result instanceof HookerFilter) {
// If the pre-hook returned hooker.filter(context, args), invoke the
// original function with that context and arguments, and store its
// result.
origResult = result = orig.apply(result.context, result.args);
} else if (result instanceof HookerPreempt) {
// If the pre-hook returned hooker.preempt(value) just use the passed
// value and don't execute the original function.
origResult = result = result.value;
} else {
// Invoke the original function in the current context with the
// passed-in arguments, and store its result.
origResult = orig.apply(this, arguments);
// If the pre-hook returned hooker.override(value), use the passed
// value, otherwise use the original function's result.
result = result instanceof HookerOverride ? result.value : origResult;
}
if (options.post) {
// If a post-hook function was specified, invoke it in the current
// context, passing in the result of the original function as the
// first argument, followed by any passed-in arguments.
tmp = options.post.apply(this, [origResult].concat(args));
if (tmp instanceof HookerOverride) {
// If the post-hook returned hooker.override(value), use the passed
// value, otherwise use the previously computed result.
result = tmp.value;
}
}
// Unhook if the "once" option was specified.
if (options.once) {
exports.unhook(obj, prop);
}
// Return the result!
return result;
}
// Re-define the method.
obj[prop] = hooked;
// Fail if the function couldn't be hooked.
if (obj[prop] !== hooked) { return false; }
// Store a reference to the original method as a property on the new one.
obj[prop]._orig = orig;
});
};
// Get a reference to the original method from a hooked function.
exports.orig = function(obj, prop) {
return obj[prop]._orig;
};
// Un-monkey-patch (unhook) a method of an object.
exports.unhook = function(obj, props) {
return forMethods(obj, props, function(obj, prop) {
// Get a reference to the original method, if it exists.
var orig = exports.orig(obj, prop);
// If there's no original method, it can't be unhooked, so fail.
if (!orig) { return false; }
// Unhook the method.
obj[prop] = orig;
});
};
}(typeof exports === "object" && exports || this));

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,17 @@
var spawn = require('child_process').spawn;
function loop() {
console.log('starting');
console.log(this);
//var child = spawn('./node_modules/nodeunit/bin/nodeunit', ['test']);
var child = spawn('node', ['child.js']);
child.stdout.on('data', function(buffer) {
process.stdout.write(buffer);
});
child.on('exit', this.async());
}
var context = {
async: function() { return loop.bind(context); }
};
loop.call(context);

View File

@ -0,0 +1,435 @@
/*global require:true */
var hooker = require('../lib/hooker');
exports['hook'] = {
setUp: function(done) {
this.order = [];
this.track = function() {
[].push.apply(this.order, arguments);
};
this.prop = 1;
this.add = function(a, b) {
this.track("add", this.prop, a, b);
return this.prop + a + b;
};
this.obj = {
that: this,
prop: 1,
add1: function(a, b) {
this.that.track("add1", this.prop, a, b);
return this.prop + a + b;
},
add2: function(a, b) {
this.that.track("add2", this.prop, a, b);
return this.prop + a + b;
},
add3: function(a, b) {
this.that.track("add3", this.prop, a, b);
return this.prop + a + b;
}
};
done();
},
'orig': function(test) {
test.expect(1);
var orig = this.add;
hooker.hook(this, "add", function() {});
test.strictEqual(hooker.orig(this, "add"), orig, "should return a refernce to the original function.");
test.done();
},
'once': function(test) {
test.expect(5);
var orig = this.add;
hooker.hook(this, "add", {
once: true,
pre: function(a, b) {
// Arguments are passed into pre-hook as specified.
this.track("before", this.prop, a, b);
}
});
test.strictEqual(this.add(2, 3), 6, "should return the original function's result.");
test.deepEqual(this.order, ["before", 1, 2, 3, "add", 1, 2, 3], "functions should execute in-order.");
test.strictEqual(this.add, orig, "should automatically unhook when once is specified.");
this.order = [];
test.strictEqual(this.add(2, 3), 6, "should return the original function's result.");
test.deepEqual(this.order, ["add", 1, 2, 3], "only the original function should execute.");
test.done();
},
'pre-hook (simple syntax)': function(test) {
test.expect(3);
// Pre-hook.
var result = hooker.hook(this, "add", function(a, b) {
// Arguments are passed into pre-hook as specified.
this.track("before", this.prop, a, b);
});
test.deepEqual(result, ["add"], "add should have been hooked.");
test.strictEqual(this.add(2, 3), 6, "should return the original function's result.");
test.deepEqual(this.order, ["before", 1, 2, 3, "add", 1, 2, 3], "functions should execute in-order.");
test.done();
},
'pre-hook': function(test) {
test.expect(3);
// Pre-hook.
var result = hooker.hook(this, "add", {
pre: function(a, b) {
// Arguments are passed into pre-hook as specified.
this.track("before", this.prop, a, b);
}
});
test.deepEqual(result, ["add"], "add should have been hooked.");
test.strictEqual(this.add(2, 3), 6, "should return the original function's result.");
test.deepEqual(this.order, ["before", 1, 2, 3, "add", 1, 2, 3], "functions should execute in-order.");
test.done();
},
'post-hook': function(test) {
test.expect(3);
// Post-hook.
var result = hooker.hook(this, "add", {
post: function(result, a, b) {
// Arguments to post-hook are the original function's return value,
// followed by the specified function arguments.
this.track("after", this.prop, a, b, result);
}
});
test.deepEqual(result, ["add"], "add should have been hooked.");
test.strictEqual(this.add(2, 3), 6, "should return the original function's result.");
test.deepEqual(this.order, ["add", 1, 2, 3, "after", 1, 2, 3, 6], "functions should execute in-order.");
test.done();
},
'pre- & post-hook': function(test) {
test.expect(2);
// Pre- & post-hook.
hooker.hook(this, "add", {
pre: function(a, b) {
// Arguments are passed into pre-hook as specified.
this.track("before", this.prop, a, b);
},
post: function(result, a, b) {
// Arguments to post-hook are the original function's return value,
// followed by the specified function arguments.
this.track("after", this.prop, a, b, result);
}
});
test.strictEqual(this.add(2, 3), 6, "should return the original function's result.");
test.deepEqual(this.order, ["before", 1, 2, 3, "add", 1, 2, 3, "after", 1, 2, 3, 6], "functions should execute in-order.");
test.done();
},
'pre-hook, return value override': function(test) {
test.expect(2);
// Pre-hook.
hooker.hook(this, "add", {
pre: function(a, b) {
// Arguments are passed into pre-hook as specified.
this.track("before", this.prop, a, b);
// This return value will override the original function's return value.
return hooker.override("b" + this.prop + a + b);
}
});
test.strictEqual(this.add(2, 3), "b123", "should return the overridden result.");
test.deepEqual(this.order, ["before", 1, 2, 3, "add", 1, 2, 3], "functions should execute in-order.");
test.done();
},
'post-hook, return value override': function(test) {
test.expect(2);
// Post-hook.
hooker.hook(this, "add", {
post: function(result, a, b) {
// Arguments to post-hook are the original function's return value,
// followed by the specified function arguments.
this.track("after", this.prop, a, b, result);
// This return value will override the original function's return value.
return hooker.override("a" + this.prop + a + b + result);
}
});
test.strictEqual(this.add(2, 3), "a1236", "should return the post-hook overridden result.");
test.deepEqual(this.order, ["add", 1, 2, 3, "after", 1, 2, 3, 6], "functions should execute in-order.");
test.done();
},
'pre- & post-hook, return value override': function(test) {
test.expect(2);
// Pre- & post-hook.
hooker.hook(this, "add", {
pre: function(a, b) {
// Arguments are passed into pre-hook as specified.
this.track("before", this.prop, a, b);
// This return value will override the original function's return value.
return hooker.override("b" + this.prop + a + b);
},
post: function(result, a, b) {
// Arguments to post-hook are the original function's return value,
// followed by the specified function arguments.
this.track("after", this.prop, a, b, result);
// This return value will override the original function's return value
// AND the pre-hook's return value.
return hooker.override("a" + this.prop + a + b + result);
}
});
test.strictEqual(this.add(2, 3), "a1236", "should return the overridden result, and post-hook result should take precedence over pre-hook result.");
test.deepEqual(this.order, ["before", 1, 2, 3, "add", 1, 2, 3, "after", 1, 2, 3, 6], "functions should execute in-order.");
test.done();
},
'pre-hook, filtering arguments': function(test) {
test.expect(2);
// Pre-hook.
hooker.hook(this, "add", {
pre: function(a, b) {
// Arguments are passed into pre-hook as specified.
this.track("before", this.prop, a, b);
// Return hooker.filter(context, arguments) and they will be passed into
// the original function. The "track" and "order" propterites are just
// set here for the same of this unit test.
return hooker.filter({prop: "x", track: this.track, order: this.order}, ["y", "z"]);
}
});
test.strictEqual(this.add(2, 3), "xyz", "should return the original function's result, given filtered context and arguments.");
test.deepEqual(this.order, ["before", 1, 2, 3, "add", "x", "y", "z"], "functions should execute in-order.");
test.done();
},
'pre- & post-hook, filtering arguments': function(test) {
test.expect(2);
// Pre- & post-hook.
hooker.hook(this, "add", {
pre: function(a, b) {
// Arguments are passed into pre-hook as specified.
this.track("before", this.prop, a, b);
// Return hooker.filter(context, arguments) and they will be passed into
// the original function. The "track" and "order" propterites are just
// set here for the same of this unit test.
return hooker.filter({prop: "x", track: this.track, order: this.order}, ["y", "z"]);
},
post: function(result, a, b) {
// Arguments to post-hook are the original function's return value,
// followed by the specified function arguments.
this.track("after", this.prop, a, b, result);
}
});
test.strictEqual(this.add(2, 3), "xyz", "should return the original function's result, given filtered context and arguments.");
test.deepEqual(this.order, ["before", 1, 2, 3, "add", "x", "y", "z", "after", 1, 2, 3, "xyz"], "functions should execute in-order.");
test.done();
},
'pre- & post-hook, filtering arguments, return value override': function(test) {
test.expect(2);
// Pre- & post-hook.
hooker.hook(this, "add", {
pre: function(a, b) {
// Arguments are passed into pre-hook as specified.
this.track("before", this.prop, a, b);
// Return hooker.filter(context, arguments) and they will be passed into
// the original function. The "track" and "order" propterites are just
// set here for the same of this unit test.
return hooker.filter({prop: "x", track: this.track, order: this.order}, ["y", "z"]);
},
post: function(result, a, b) {
// Arguments to post-hook are the original function's return value,
// followed by the specified function arguments.
this.track("after", this.prop, a, b, result);
// This return value will override the original function's return value
// AND the pre-hook's return value.
return hooker.override("a" + this.prop + a + b + result);
}
});
test.strictEqual(this.add(2, 3), "a123xyz", "should return the post-hook overridden result.");
test.deepEqual(this.order, ["before", 1, 2, 3, "add", "x", "y", "z", "after", 1, 2, 3, "xyz"], "functions should execute in-order.");
test.done();
},
'pre-hook, preempt original function': function(test) {
test.expect(2);
// Pre-hook.
hooker.hook(this, "add", {
pre: function(a, b) {
// Arguments are passed into pre-hook as specified.
this.track("before", this.prop, a, b);
// Returning hooker.preempt will prevent the original function from being
// invoked and optionally set a return value.
return hooker.preempt();
}
});
test.strictEqual(this.add(2, 3), undefined, "should return the value passed to preempt.");
test.deepEqual(this.order, ["before", 1, 2, 3], "functions should execute in-order.");
test.done();
},
'pre-hook, preempt original function with value': function(test) {
test.expect(2);
// Pre-hook.
hooker.hook(this, "add", {
pre: function(a, b) {
// Arguments are passed into pre-hook as specified.
this.track("before", this.prop, a, b);
// Returning hooker.preempt will prevent the original function from being
// invoked and optionally set a return value.
return hooker.preempt(9000);
}
});
test.strictEqual(this.add(2, 3), 9000, "should return the value passed to preempt.");
test.deepEqual(this.order, ["before", 1, 2, 3], "functions should execute in-order.");
test.done();
},
'pre- & post-hook, preempt original function with value': function(test) {
test.expect(2);
// Pre- & post-hook.
hooker.hook(this, "add", {
pre: function(a, b) {
// Arguments are passed into pre-hook as specified.
this.track("before", this.prop, a, b);
// Returning hooker.preempt will prevent the original function from being
// invoked and optionally set a return value.
return hooker.preempt(9000);
},
post: function(result, a, b) {
// Arguments to post-hook are the original function's return value,
// followed by the specified function arguments.
this.track("after", this.prop, a, b, result);
}
});
test.strictEqual(this.add(2, 3), 9000, "should return the value passed to preempt.");
test.deepEqual(this.order, ["before", 1, 2, 3, "after", 1, 2, 3, 9000], "functions should execute in-order.");
test.done();
},
'pre- & post-hook, preempt original function with value, return value override': function(test) {
test.expect(2);
// Pre- & post-hook.
hooker.hook(this, "add", {
pre: function(a, b) {
// Arguments are passed into pre-hook as specified.
this.track("before", this.prop, a, b);
// Returning hooker.preempt will prevent the original function from being
// invoked and optionally set a return value.
return hooker.preempt(9000);
},
post: function(result, a, b) {
// Arguments to post-hook are the original function's return value,
// followed by the specified function arguments.
this.track("after", this.prop, a, b, result);
// This return value will override any preempt value set in pre-hook.
return hooker.override("a" + this.prop + a + b + result);
}
});
test.strictEqual(this.add(2, 3), "a1239000", "should return the overridden result, and post-hook result should take precedence over preempt value.");
test.deepEqual(this.order, ["before", 1, 2, 3, "after", 1, 2, 3, 9000], "functions should execute in-order.");
test.done();
},
'pre- & post-hook, some properties': function(test) {
test.expect(7);
// Pre- & post-hook.
var result = hooker.hook(this.obj, ["add1", "add2"], {
pre: function(a, b) {
// Arguments are passed into pre-hook as specified.
this.that.track("before", this.prop, a, b);
},
post: function(result, a, b) {
// Arguments to post-hook are the original function's return value,
// followed by the specified function arguments.
this.that.track("after", this.prop, a, b, result);
}
});
test.deepEqual(result.sort(), ["add1", "add2"], "both functions should have been hooked.");
test.strictEqual(this.obj.add1(2, 3), 6, "should return the original function's result.");
test.deepEqual(this.order, ["before", 1, 2, 3, "add1", 1, 2, 3, "after", 1, 2, 3, 6], "functions should execute in-order.");
this.order = [];
test.strictEqual(this.obj.add2(2, 3), 6, "should return the original function's result.");
test.deepEqual(this.order, ["before", 1, 2, 3, "add2", 1, 2, 3, "after", 1, 2, 3, 6], "functions should execute in-order.");
this.order = [];
test.strictEqual(this.obj.add3(2, 3), 6, "should return the original function's result.");
test.deepEqual(this.order, ["add3", 1, 2, 3], "functions should execute in-order.");
test.done();
},
'pre- & post-hook, all properties': function(test) {
test.expect(7);
// Pre- & post-hook.
var result = hooker.hook(this.obj, {
pre: function(a, b) {
// Arguments are passed into pre-hook as specified.
this.that.track("before", this.prop, a, b);
},
post: function(result, a, b) {
// Arguments to post-hook are the original function's return value,
// followed by the specified function arguments.
this.that.track("after", this.prop, a, b, result);
}
});
test.deepEqual(result.sort(), ["add1", "add2", "add3"], "all functions should have been hooked.");
test.strictEqual(this.obj.add1(2, 3), 6, "should return the original function's result.");
test.deepEqual(this.order, ["before", 1, 2, 3, "add1", 1, 2, 3, "after", 1, 2, 3, 6], "functions should execute in-order.");
this.order = [];
test.strictEqual(this.obj.add2(2, 3), 6, "should return the original function's result.");
test.deepEqual(this.order, ["before", 1, 2, 3, "add2", 1, 2, 3, "after", 1, 2, 3, 6], "functions should execute in-order.");
this.order = [];
test.strictEqual(this.obj.add3(2, 3), 6, "should return the original function's result.");
test.deepEqual(this.order, ["before", 1, 2, 3, "add3", 1, 2, 3, "after", 1, 2, 3, 6], "functions should execute in-order.");
test.done();
},
'pre- & post-hook, all properties, passName': function(test) {
test.expect(6);
// Pre- & post-hook.
hooker.hook(this.obj, {
passName: true,
pre: function(name, a, b) {
// Arguments are passed into pre-hook as specified.
this.that.track("before", this.prop, name, a, b);
},
post: function(result, name, a, b) {
// Arguments to post-hook are the original function's return value,
// followed by the specified function arguments.
this.that.track("after", this.prop, name, a, b, result);
}
});
test.strictEqual(this.obj.add1(2, 3), 6, "should return the original function's result.");
test.deepEqual(this.order, ["before", 1, "add1", 2, 3, "add1", 1, 2, 3, "after", 1, "add1", 2, 3, 6], "functions should execute in-order.");
this.order = [];
test.strictEqual(this.obj.add2(2, 3), 6, "should return the original function's result.");
test.deepEqual(this.order, ["before", 1, "add2", 2, 3, "add2", 1, 2, 3, "after", 1, "add2", 2, 3, 6], "functions should execute in-order.");
this.order = [];
test.strictEqual(this.obj.add3(2, 3), 6, "should return the original function's result.");
test.deepEqual(this.order, ["before", 1, "add3", 2, 3, "add3", 1, 2, 3, "after", 1, "add3", 2, 3, 6], "functions should execute in-order.");
test.done();
},
'unhook one property': function(test) {
test.expect(5);
var orig = this.add;
hooker.hook(this, "add", function() {});
var result = hooker.unhook(this, "add");
test.deepEqual(result, ["add"], "one function should have been unhooked.");
test.strictEqual(this.add, orig, "should have unhooked, restoring the original function");
result = hooker.unhook(this, "add");
test.deepEqual(result, [], "nothing should have been unhooked.");
test.strictEqual(this.add, orig, "shouldn't explode if already unhooked");
test.strictEqual(this.add.orig, undefined, "original function shouldn't have an orig property");
test.done();
},
'unhook some properties': function(test) {
test.expect(6);
var add1 = this.obj.add1;
var add2 = this.obj.add2;
hooker.hook(this.obj, ["add1", "add2"], function() {});
test.strictEqual(hooker.orig(this.obj, "add1"), add1, "should return a refernce to the original function");
test.strictEqual(hooker.orig(this.obj, "add2"), add2, "should return a refernce to the original function");
test.strictEqual(hooker.orig(this.obj, "add3"), undefined, "should not have been hooked, so should not have an original function");
var result = hooker.unhook(this.obj, ["add1", "add2"]);
test.deepEqual(result.sort(), ["add1", "add2"], "both functions should have been unhooked.");
test.strictEqual(this.obj.add1, add1, "should have unhooked, restoring the original function");
test.strictEqual(this.obj.add2, add2, "should have unhooked, restoring the original function");
test.done();
},
'unhook all properties': function(test) {
test.expect(7);
var add1 = this.obj.add1;
var add2 = this.obj.add2;
var add3 = this.obj.add3;
hooker.hook(this.obj, function() {});
test.strictEqual(hooker.orig(this.obj, "add1"), add1, "should return a refernce to the original function");
test.strictEqual(hooker.orig(this.obj, "add2"), add2, "should return a refernce to the original function");
test.strictEqual(hooker.orig(this.obj, "add3"), add3, "should return a refernce to the original function");
var result = hooker.unhook(this.obj);
test.deepEqual(result.sort(), ["add1", "add2", "add3"], "all functions should have been unhooked.");
test.strictEqual(this.obj.add1, add1, "should have unhooked, restoring the original function");
test.strictEqual(this.obj.add2, add2, "should have unhooked, restoring the original function");
test.strictEqual(this.obj.add3, add3, "should have unhooked, restoring the original function");
test.done();
}
};

90
node_modules/grunt-contrib-nodeunit/package.json generated vendored Normal file
View File

@ -0,0 +1,90 @@
{
"name": "grunt-contrib-nodeunit",
"description": "Run Nodeunit unit tests.",
"version": "0.4.1",
"homepage": "https://github.com/gruntjs/grunt-contrib-nodeunit",
"author": {
"name": "Grunt Team",
"url": "http://gruntjs.com/"
},
"repository": {
"type": "git",
"url": "git://github.com/gruntjs/grunt-contrib-nodeunit.git"
},
"bugs": {
"url": "https://github.com/gruntjs/grunt-contrib-nodeunit/issues"
},
"licenses": [
{
"type": "MIT",
"url": "https://github.com/gruntjs/grunt-contrib-nodeunit/blob/master/LICENSE-MIT"
}
],
"engines": {
"node": ">= 0.8.0"
},
"scripts": {
"test": "grunt test"
},
"dependencies": {
"hooker": "~0.2.3",
"nodeunit": "~0.9.0"
},
"devDependencies": {
"grunt-contrib-jshint": "~0.10.0",
"grunt-contrib-internal": "~0.4.6",
"grunt-contrib-clean": "~0.5.0",
"grunt": "~0.4.0",
"tap": "~0.4.6"
},
"peerDependencies": {
"grunt": "~0.4.0"
},
"keywords": [
"gruntplugin"
],
"files": [
"tasks",
"LICENSE-MIT"
],
"_id": "grunt-contrib-nodeunit@0.4.1",
"dist": {
"shasum": "943393ee5d66b1cdadb49a9b23aaee44455095b2",
"tarball": "http://registry.npmjs.org/grunt-contrib-nodeunit/-/grunt-contrib-nodeunit-0.4.1.tgz"
},
"_from": "grunt-contrib-nodeunit@*",
"_npmVersion": "1.3.26",
"_npmUser": {
"name": "vladikoff",
"email": "vlad@vladikoff.com"
},
"maintainers": [
{
"name": "tkellen",
"email": "tyler@sleekcode.net"
},
{
"name": "cowboy",
"email": "cowboy@rj3.net"
},
{
"name": "shama",
"email": "kyle@dontkry.com"
},
{
"name": "vladikoff",
"email": "vlad@vladikoff.com"
},
{
"name": "sindresorhus",
"email": "sindresorhus@gmail.com"
},
{
"name": "jmeas",
"email": "jellyes2@gmail.com"
}
],
"directories": {},
"_shasum": "943393ee5d66b1cdadb49a9b23aaee44455095b2",
"_resolved": "https://registry.npmjs.org/grunt-contrib-nodeunit/-/grunt-contrib-nodeunit-0.4.1.tgz"
}

296
node_modules/grunt-contrib-nodeunit/tasks/nodeunit.js generated vendored Normal file
View File

@ -0,0 +1,296 @@
/*
* grunt-contrib-nodeunit
* http://gruntjs.com/
*
* Copyright (c) 2014 "Cowboy" Ben Alman, contributors
* Licensed under the MIT license.
*/
'use strict';
module.exports = function(grunt) {
// Nodejs libs.
var path = require('path');
var util = require('util');
var fs = require('fs');
// External libs.
var nodeunit = require('nodeunit');
var hooker = require('hooker');
// ==========================================================================
// BETTER ERROR DISPLAY
// ==========================================================================
// Much nicer error formatting than what comes with nodeunit.
var betterErrors = function (assertion) {
var e = assertion.error;
if (!e || !('actual' in e) || !('expected' in e)) { return assertion; }
// Temporarily override the global "inspect" property because logging
// the entire global object is just silly.
var globalInspect = global.inspect;
global.inspect = function() { return '[object global]'; };
e._message = e.message;
// Pretty-formatted objects.
var actual = util.inspect(e.actual, false, 10, true);
var expected = util.inspect(e.expected, false, 10, true);
var indent = function(str) {
return (''+str).split('\n').map(function(s) { return ' ' + s; }).join('\n');
};
var stack;
var multiline = (actual + expected).indexOf('\n') !== -1;
if (multiline) {
stack = [
'Actual:', indent(actual),
'Operator:', indent(e.operator),
'Expected:', indent(expected),
].join('\n');
} else {
stack = e.name + ': ' + actual + ' ' + e.operator + ' ' + expected;
}
if (e.stack) {
stack += '\n' + e.stack.split('\n').slice(1).join('\n');
}
e.stack = stack;
// Restore the global "inspect" property.
global.inspect = globalInspect;
return assertion;
};
// Reformat stack trace to remove nodeunit scripts, fix indentation, etc.
var cleanStack = function(error) {
error._stack = error.stack;
// Show a full stack trace?
var fullStack = grunt.option('verbose') || grunt.option('stack');
// Reformat stack trace output.
error.stack = error.stack.split('\n').map(function(line) {
if (line[0] === ' ') {
// Remove nodeunit script srcs from non-verbose stack trace.
if (!fullStack && line.indexOf(path.join('node_modules', 'nodeunit') + path.sep) !== -1) {
return '';
}
// Remove leading spaces.
line = line.replace(/^ {4}(?=at)/, '');
// Remove cwd.
line = line.replace('(' + process.cwd() + path.sep, '(');
} else {
line = line.replace(/Assertion(Error)/, '$1');
}
return line + '\n';
}).join('');
return error;
};
// ==========================================================================
// CUSTOM NODEUNIT REPORTER
// ==========================================================================
// Keep track of the last-started module.
var currentModule;
// Keep track of the last-started test(s).
var unfinished = {};
// If Nodeunit explodes because a test was missing test.done(), handle it.
process.on('exit', function() {
var len = Object.keys(unfinished).length;
// If there are unfinished tests, tell the user why Nodeunit killed grunt.
if (len > 0) {
grunt.log.muted = false;
grunt.verbose.error().or.writeln('F'.red);
grunt.log.error('Incomplete tests/setups/teardowns:');
Object.keys(unfinished).forEach(grunt.log.error, grunt.log);
grunt.fatal('A test was missing test.done(), so nodeunit exploded. Sorry!',
Math.min(99, 90 + len));
}
});
// Keep track of failed assertions for pretty-printing.
var failedAssertions = [];
function logFailedAssertions() {
var assertion, stack;
// Print each assertion error + stack.
while (assertion = failedAssertions.shift()) {
betterErrors(assertion);
cleanStack(assertion.error);
grunt.verbose.or.error(assertion.testName);
if (assertion.error.name === 'AssertionError' && assertion.message) {
grunt.log.error('Message: ' + assertion.message.magenta);
}
grunt.log.error(assertion.error.stack).writeln();
}
}
// Define our own Nodeunit reporter.
nodeunit.reporters.grunt = {
info: 'Grunt reporter',
run: function(files, options, callback) {
var opts = {
// No idea.
testspec: undefined,
// Executed when the first test in a file is run. If no tests exist in
// the file, this doesn't execute.
moduleStart: function(name) {
// Keep track of this so that moduleDone output can be suppressed in
// cases where a test file contains no tests.
currentModule = name;
grunt.verbose.subhead('Testing ' + name).or.write('Testing ' + name);
},
// Executed after a file is done being processed. This executes whether
// tests exist in the file or not.
moduleDone: function(name) {
// Abort if no tests actually ran.
if (name !== currentModule) { return; }
// Print assertion errors here, if verbose mode is disabled.
if (!grunt.option('verbose')) {
if (failedAssertions.length > 0) {
grunt.log.writeln();
logFailedAssertions();
} else {
grunt.log.ok();
}
}
},
// Executed before each test is run.
testStart: function(name) {
// Keep track of the current test, in case test.done() was omitted
// and Nodeunit explodes.
unfinished[name] = name;
grunt.verbose.write(name + '...');
// Mute output, in cases where a function being tested logs through
// grunt (for testing grunt internals).
grunt.log.muted = true;
},
// Executed after each test and all its assertions are run.
testDone: function(name, assertions) {
delete unfinished[name];
// Un-mute output.
grunt.log.muted = false;
// Log errors if necessary, otherwise success.
if (assertions.failures()) {
assertions.forEach(function(ass) {
if (ass.failed()) {
ass.testName = name;
failedAssertions.push(ass);
}
});
if (grunt.option('verbose')) {
grunt.log.error();
logFailedAssertions();
} else {
grunt.log.write('F'.red);
}
} else {
grunt.verbose.ok().or.write('.');
}
},
// Executed when everything is all done.
done: function (assertions) {
if (assertions.failures()) {
grunt.warn(assertions.failures() + '/' + assertions.length +
' assertions failed (' + assertions.duration + 'ms)');
} else if (assertions.length === 0) {
grunt.warn('0/0 assertions ran (' + assertions.duration + 'ms)');
} else {
grunt.verbose.writeln();
grunt.log.ok(assertions.length + ' assertions passed (' +
assertions.duration + 'ms)');
}
// Tell the task manager we're all done.
callback(); // callback(assertions.failures() === 0);
}
};
// Nodeunit needs absolute paths.
var paths = files.map(function(filepath) {
return path.resolve(filepath);
});
nodeunit.runFiles(paths, opts);
}
};
// ==========================================================================
// TASKS
// ==========================================================================
grunt.registerMultiTask('nodeunit', 'Run Nodeunit unit tests.', function() {
var done = this.async();
// Merge task-specific and/or target-specific options with these defaults.
var options = this.options({
reporterOutput: false,
reporter: 'grunt',
reporterOptions: {}
});
// Ensure the default nodeunit options are set by reading in the nodeunit.json file.
var nodeUnitDefaults = {};
// check for nodeunit under our package's node_modules directory first
var nodeUnitDefaultsFile = path.join(__dirname, '..', 'node_modules', 'nodeunit', 'bin', 'nodeunit.json');
if (!fs.existsSync(nodeUnitDefaultsFile)) {
// if both grunt-contrib-nodeunit and nodeunit are listed as dependencies for this project, they'd
// be located at the same folder level. So check for that location next.
nodeUnitDefaultsFile = path.join(__dirname, '..', '..', 'nodeunit', 'bin', 'nodeunit.json');
}
if (fs.existsSync(nodeUnitDefaultsFile)) {
nodeUnitDefaults = JSON.parse(fs.readFileSync(nodeUnitDefaultsFile, 'utf8'));
}
for (var defaultVal in nodeUnitDefaults) {
if (typeof options.reporterOptions[defaultVal] === 'undefined') {
options.reporterOptions[defaultVal] = nodeUnitDefaults[defaultVal];
}
}
if (!nodeunit.reporters[options.reporter]) {
return done(new Error('Reporter ' + options.reporter + ' not found'));
}
var output = '';
if (options.reporterOutput) {
// Hook into stdout to capture report
hooker.hook(process.stdout, 'write', {
pre: function(str) {
output += str;
return hooker.preempt();
}
});
}
// if reporterOutput has a directory destination make sure to create it.
// See: https://github.com/caolan/nodeunit/issues/262
if (options.reporterOptions.output) {
grunt.file.mkdir(path.normalize(options.reporterOptions.output));
}
// Run test(s).
nodeunit.reporters[options.reporter].run(this.filesSrc, options.reporterOptions, function(err) {
// Write the output of the reporter if wanted
if (options.reporterOutput) {
// no longer hook stdout so we can grunt.log
hooker.unhook(process.stdout, 'write');
// save all of the output we saw up to this point
grunt.file.write(options.reporterOutput, output);
grunt.log.ok('Report "' + options.reporterOutput + '" created.');
}
done(err);
});
});
};

6
node_modules/grunt-jsdoc/.npmignore generated vendored Normal file
View File

@ -0,0 +1,6 @@
.travis.yml
.git
.gitignore
tmp
doc
docs

52
node_modules/grunt-jsdoc/Gruntfile.js generated vendored Normal file
View File

@ -0,0 +1,52 @@
module.exports = function(grunt) {
'use strict';
// Project configuration.
grunt.initConfig({
clean : ['doc'],
jsdoc : {
basic : {
src : ['tasks/**.js', 'tasks/lib/*.js'],
options : {
destination: 'doc/basic'
}
},
docstrap : {
src : ['tasks/**.js', 'tasks/lib/*.js', 'README.md'],
options : {
destination : 'doc/docstrap',
template : "node_modules/ink-docstrap/template",
configure : "node_modules/ink-docstrap/template/jsdoc.conf.json"
}
}
},
nodeunit : {
unit : ['test/jsdoc-plugin_test.js'],
basic : ['test/jsdoc-basic_test.js'],
docstrap : ['test/jsdoc-docstrap_test.js']
},
jshint : {
files : ['Gruntfile.js', 'tasks/*.js', 'tasks/lib/*.js', 'test/*.js'],
options: {
node : true,
smarttabs : true
}
}
});
grunt.loadNpmTasks('grunt-contrib-clean');
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-nodeunit');
// Load local tasks.
grunt.loadTasks('tasks');
// Default task.
grunt.registerTask('default', ['jshint', 'test']);
//testing tasks
grunt.registerTask('test-basic', ['jsdoc:basic', 'nodeunit:basic']);
grunt.registerTask('test-docstrap', ['jsdoc:docstrap', 'nodeunit:docstrap']);
grunt.registerTask('test', ['clean', 'nodeunit:unit', 'test-basic', 'test-docstrap']);
};

22
node_modules/grunt-jsdoc/LICENSE-MIT generated vendored Normal file
View File

@ -0,0 +1,22 @@
Copyright (c) 2012 Bertrand Chevrier
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

164
node_modules/grunt-jsdoc/README.md generated vendored Normal file
View File

@ -0,0 +1,164 @@
# grunt-jsdoc [![Build Status](https://travis-ci.org/krampstudio/grunt-jsdoc.png)](https://travis-ci.org/krampstudio/grunt-jsdoc) [![NPM version](https://badge.fury.io/js/grunt-jsdoc.png)](http://badge.fury.io/js/grunt-jsdoc) [![Built with Grunt](https://cdn.gruntjs.com/builtwith.png)](http://gruntjs.com/)
[![Npm Downloads](https://nodei.co/npm/grunt-jsdoc.png?downloads=true&stars=true)](https://nodei.co/npm/grunt-jsdoc.png?downloads=true&stars=true)
This plugin enables you to integrate the generation of comments based documentation into your Grunt build.
## NPM package name change
To comply with convention, the package's name was changed from `grunt-contrib-jsdoc` to `grunt-jsdoc`. You'll have to upgrade your `package.json` if you're still using `grunt-contrib-jsdoc`.
## Install
You need [grunt >= 0.4][grunt] as well as [node] and [npm] installed and running on your system.
You also need `java` installed and available in your PATH.
Install this grunt plugin next to your project's [Gruntfile.js][getting_started] with:
```bash
npm install grunt-jsdoc --save-dev
```
### jsdoc3 3.3.0
The jsdoc3 team is working on the 3.3.0 version that works on node.js and doesn't need Rhino (Java) anymore. This version is not yet stable (flagged as _alpha_). If you want this plugin to use this version, you can install the _beta_ tag of this grunt plugin (branch 0.6.x).
```bash
npm install grunt-jsdoc@beta --save-dev
```
> Feedback on the beta branch is more than welcomed!
### Grunt <= 0.3.x
If you use the previous version of Grunt (0.3), you can install it with:
```bash
npm install grunt-jsdoc-plugin
```
## Upstream issues
*For documentation related issues, please ask the jsdoc3 people.* To be sure the issue comes from the Grunt plugin, you can check by running directly jsdoc3 command. Run the task with the `--debug` flag and the command to run is outputed.
## Documentation
### Configuration
Configure the plugin to your project's [Gruntfile.js][getting_started].
First, add the `jsdoc` entry to the options of the `initConfig` method :
```javascript
grunt.initConfig({
jsdoc : {
dist : {
src: ['src/*.js', 'test/*.js'],
options: {
destination: 'doc'
}
}
}
});
```
The supported options are
* `src` : (required) an array of pattern that matches the files to extract the documentation from. You can also add the pattern to a README.md file to include it in your doc as described [there](http://usejsdoc.org/about-including-readme.html).
* `dest` : (alias to `options.destination`) set up the destination folder, the grunt way
* `jsdoc`: (optional) the path to the jsdoc bin (needed only for some border line cases)
* `options` : options used by jsdoc
* `destination`: (required) the folder where the doc is generated
* `configure` : (optional) path to a config file
* `template` : (optional) path or name to a different template
* `private` : (optional) include the private functions to the doc (`true` by default).
* ... refer the [usejsdocCli] documentation for all the available options.
Then, load the plugin
```javascript
grunt.loadNpmTasks('grunt-jsdoc');
```
### Code Documentation
The current version supports only [jsdoc3] documentation style. The sources configured
must contains valid [jsdoc3] tags. Consult the [usejsdoc] website for the details.
### Templates
The plugin includes [docstrap](https://github.com/terryweiss/docstrap), as well as the default template provided by jsdoc3. To use docstrap, you can use the following configuration:
```javascript
jsdoc : {
dist : {
src: ['src/**/*.js', 'README.md'],
options: {
destination: 'doc',
template : "node_modules/grunt-jsdoc/node_modules/ink-docstrap/template",
configure : "node_modules/grunt-jsdoc/node_modules/ink-docstrap/template/jsdoc.conf.json"
}
}
}
```
### Build
To generate the documentation, you need to call the `jsdoc` task :
```bash
$> grunt jsdoc
```
or integrate it to your build sequence :
```javascript
grunt.registerTask('default', ['lint', 'test', 'jsdoc']);
```
## Contributing
Any contribution is welcome! Please check the [issues](https://github.com/krampstudio/grunt-jsdoc/issues). Do some unit/integration tests as far as possible.
## Release History
* _0.5.0_ Move to NPM dependencies instead of git, jsdoc 3.2.2 (Fix [#65](https://github.com/krampstudio/grunt-jsdoc/issues/65))
* _0.5.1_ Update repo name to prevent confusion with previous version
* _0.5.2_ Upgrade to Grunt 0.4.3 (PR [#74](https://github.com/krampstudio/grunt-jsdoc/pull/74))
* _0.5.3_ Fix peer deps issue
* _0.5.4_ Fix peer deps issue
* _0.5.5_ Update docstrap version
* _0.5.6_ Fix dependencies version and bug [#87](https://github.com/krampstudio/grunt-jsdoc/issues/87)
* _0.5.7_ Update readme, docstrap version
* _0.4.0_ Update to jsdoc 3.2.0 stable, Fix [#37](https://github.com/krampstudio/grunt-jsdoc/issues/37), add integration tests
* _0.4.1_ Fix [#53](https://github.com/krampstudio/grunt-jsdoc/issues/53) and [#54](https://github.com/krampstudio/grunt-jsdoc/issues/54)
* _0.4.2_ Fix [#57](https://github.com/krampstudio/grunt-jsdoc/issues/57)
* _0.4.3_ Grunt 0.4.2 compliance, upgrade to jsdoc 3.2.2 and undeprecate the `dest` option ([#60](https://github.com/krampstudio/grunt-jsdoc/issues/60), [#63](https://github.com/krampstudio/grunt-jsdoc/issues/63) and [#66](https://github.com/krampstudio/grunt-jsdoc/issues/66))
* _0.3.0_ Partial rewrite, Fix [#29](https://github.com/krampstudio/grunt-jsdoc/pull/30) and minor typos fixs
* _0.3.1_ Fix [#29](https://github.com/krampstudio/grunt-jsdoc/issues/29)
* _0.3.2_ Fix [#32](https://github.com/krampstudio/grunt-jsdoc/issues/32)
* _0.3.3_ Fix [#34](https://github.com/krampstudio/grunt-jsdoc/issues/34) and [#36](https://github.com/krampstudio/grunt-jsdoc/issues/34)
* _0.2.0_ Migrate to grunt 0.4
* _0.2.1_ Fix [#10](https://github.com/krampstudio/grunt-jsdoc/issues/10)
* _0.2.2_ Fix [#11](https://github.com/krampstudio/grunt-jsdoc/issues/11)
* _0.2.3_ Fix [#14](https://github.com/krampstudio/grunt-jsdoc/pull/14) and [#15](https://github.com/krampstudio/grunt-jsdoc/issues/15)
* _0.2.4_ Fix Jsdoc 3 dependency to 3.1.1 tag, enables jsdoc options [#19](https://github.com/krampstudio/grunt-jsdoc/issues/19), enable to add jsdoc path [#13](https://github.com/krampstudio/grunt-jsdoc/issues/13) and add peerDependencies
* _0.1.0_ First release, includes basic support of [jsdoc3]
* _0.1.1_ Fix [#2](https://github.com/krampstudio/grunt-jsdoc/issues/2)
* _0.1.2_ Fix [#4](https://github.com/krampstudio/grunt-jsdoc/issues/4)
* _0.1.3_ Fix [#7](https://github.com/krampstudio/grunt-jsdoc/pull/7), Add [feature #8](https://github.com/krampstudio/grunt-jsdoc/pull/8)
* _0.1.4_ Use `child_process.spawn` instead of `exec` to run the command
[jsdoc3]: https://github.com/jsdoc3/jsdoc
## License
Copyright (c) 2012 Bertrand Chevrier
Licensed under the MIT license.
[grunt]: https://gruntjs.com
[node]: http://nodejs.org
[npm]: http://npmjs.org
[getting_started]: https://github.com/gruntjs/grunt/wiki/Getting-started
[usejsdoc]: http://usejsdoc.org
[usejsdocCli]: http://usejsdoc.org/about-commandline.html

2
node_modules/grunt-jsdoc/bin/grunt-jsdoc generated vendored Executable file
View File

@ -0,0 +1,2 @@
#!/usr/bin/env node
require('grunt').npmTasks('jsdoc').cli();

1
node_modules/grunt-jsdoc/node_modules/.bin/jsdoc generated vendored Symbolic link
View File

@ -0,0 +1 @@
../jsdoc/jsdoc.js

View File

@ -0,0 +1,9 @@
node_modules*
components*
bower_components*
*.map
.idea*
ringojs-0.9*
dox*
testdocs/*
npm-debug.log

View File

@ -0,0 +1,421 @@
"use strict";
/**
* @fileOverview Gruntfile tasks. These tasks are intended to help you when modifying the template. If you are
* just using the template, don't sweat this stuff. To use these tasks, you must install grunt, if you haven't already,
* and install the dependencies. All of this requires node.js, of course.
*
* Install grunt:
*
* npm install -g grunt-cli
*
* Then in the directory where you found this file:
*
* npm install
*
* And you are all set. See the individual tasks for details.
*
* @module Gruntfile
* @requires path
* @requires lodash
* @requires http
* @requires async
* @requires fs
*/
var path = require( "path" );
var sys = require( "lodash" );
var http = require( "http" );
var async = require( "async" );
var fs = require( "fs" );
// this rather odd arrangement of composing tasks like this to make sure this works on both
// windows and linux correctly. We can't depend on Grunt or Node to normalize
// paths for us because we shell out to make this work. So we gather up
// our relative paths here, normalize them later and then pass them into
// the shell to be run by JSDoc3.
/**
* The definition to run the development test files. This runs the files in `fixtures` with the
* project's `conf.json` file.
* @private
*/
var jsdocTestPages = {
dest : "./testdocs",
tutorials : "./fixtures/tutorials",
template : "./template",
config : "./fixtures/testdocs.conf.json",
options : " --lenient --verbose --recurse"
};
/**
* The definition to run the sample files. This runs the files in `fixtures` with the
* sample's `conf.json` file. No task directly exposes this configuration. The `fixtures` task
* modifies this for each swatch it finds and then run the docs command against it.
* @private
*/
var jsdocExamplePages = {
src : ["./fixtures/", "./README.md"],
dest : "./themes",
tutorials : "./fixtures/tutorials",
template : "./template",
config : "./fixtures/example.conf.json",
options : " --lenient --verbose --recurse"
};
/**
* This definition provides the project's main, published documentation.
* @private
*/
var projectDocs = {
src : ["./Gruntfile.js", "./README.md", "./template/publish.js"],
dest : "./dox",
tutorials : "",
template : "./template",
config : "./template/jsdoc.conf.json",
options : " --lenient --verbose --recurse --private"
};
/**
* Normalizes all paths from a JSDoc task definition and and returns an executable string that can be passed to the shell.
* @param {object} jsdoc A JSDoc definition
* @returns {string}
*/
function jsdocCommand( jsdoc ) {
var cmd = [];
cmd.unshift( jsdoc.options );
if ( jsdoc.tutorials.length > 0 ) {
cmd.push( "-u " + path.resolve( jsdoc.tutorials ) );
}
cmd.push( "-d " + path.resolve( jsdoc.dest ) );
cmd.push( "-t " + path.resolve( jsdoc.template ) );
cmd.push( "-c " + path.resolve( jsdoc.config ) );
sys.each( jsdoc.src, function ( src ) {
cmd.push( path.resolve( src ) );
} );
cmd.unshift( path.resolve( "./node_modules/jsdoc/jsdoc" ) );
cmd.unshift( "node" );
return cmd.join( " " );
}
var tasks = {
shell : {
options : {
stdout : true,
stderr : true
},
/**
* TASK: Create the a documentation set for testing changes to the template
* @name jsdoc:testdocs
* @memberOf module:Gruntfile
*/
testdocs : {
command : jsdocCommand( jsdocTestPages )
},
/**
* TASK: Create project documentation
* @name shell:dox
* @memberOf module:Gruntfile
*/
dox : {
command : jsdocCommand( projectDocs )
},
release1 : {
command : [
"touch Gruntfile.js",
"git add .",
'git commit -m "ready for release"',
].join( ";" )
},
release2 : {
command : ["npm version patch",
"git push",
"git push --tags",
"npm publish"
].join( "&&" )
}
},
jsdoc : {
testdocs : {
src : ['fixtures/**.js', "./README.md"],
jsdoc : "./node_modules/jsdoc/jsdoc.js",
options : {
destination : './testdocs',
rescurse : true,
"private" : true,
"template" : "./template",
"configure" : "./template/jsdoc.conf.json"
}
}
},
/**
* TASK: The less task creates the themed css file from main.less. The file is written to the template styles
* directory as site.[name of theme].css. Later the .conf file will look for the theme to apply based
* on this naming convention.
* @name less
* @memberOf module:Gruntfile
*/
less : {
dev : {
files : {
"template/static/styles/site.<%= jsdocConf.templates.theme %>.css" : "styles/main.less"
}
}
},
copy : {
docs : {
files : [
{expand : true, cwd : "dox/", src : ['**'], dest : '../docstrap-dox/'},
{expand : true, cwd : "themes/", src : ['**'], dest : '../docstrap-dox/themes'}
]
}
},
uglify : {
template : {
files : {
'template/static/scripts/docstrap.lib.js' : [
'bower_components/jquery/jquery.min.js',
'bower_components/sunlight/src/sunlight.js',
'bower_components/sunlight/src/lang/sunlight.xml.js',
'bower_components/sunlight/src/**/*.js',
// 'bower_components/sunlight/src/lang/*.js',
// 'bower_components/sunlight/src/plugins/*.js',
'bower_components/jquery.scrollTo/jquery.scrollTo.min.js',
'bower_components/jquery.localScroll/jquery.localScroll.min.js',
'bower_components/bootstrap/js/bootstrap-dropdown.js',
'bower_components/toc/toc.js',
'bower_components/toc/copyright.js'
]
}
}
}
};
module.exports = function ( grunt ) {
tasks.jsdocConf = grunt.file.readJSON( 'template/jsdoc.conf.json' );
grunt.initConfig( tasks );
grunt.loadNpmTasks( 'grunt-contrib-less' );
grunt.loadNpmTasks( 'grunt-shell' );
grunt.loadNpmTasks( 'grunt-contrib-copy' );
grunt.loadNpmTasks( 'grunt-contrib-uglify' );
grunt.loadNpmTasks( 'grunt-jsdoc' );
grunt.registerTask( "default", ["docs"] );
/**
* Builds the project's documentation
* @name docs
* @memberof module:Gruntfile
*/
grunt.registerTask( "docs", "Create the project documentation", ["shell:dox"] );
/**
* Compile the CSS and create the project documentation
* @name dev
* @memberof module:Gruntfile
*/
grunt.registerTask( "dev", "Compile the CSS and create the project documentation", ["less", "shell:dox"] );
/**
* TASK: Builds the main less file and then generates the test documents
* @name testdocs
* @memberof module:Gruntfile
*/
grunt.registerTask( "testdocs", "Builds the main less file and then generates the test documents", ["less:dev", "shell:testdocs"] );
/**
* TASK: Builds the whole shebang. Which means creating testdocs, the bootswatch fixtures and then resetting the
* styles directory.
* @name build
* @memberof module:Gruntfile
*/
grunt.registerTask( "build", "Builds the whole shebang. Which means creating testdocs, the bootswatch samples and then resetting the styles directory", ["uglify:template", "testdocs", "shell:dox", "bootswatch", "examples", "apply", "copy"] );
/**
* TASK: Applies the theme in the conf file and applies it to the styles directory.
* @name apply
* @memberof module:Gruntfile
*/
grunt.registerTask( "apply", "Applies the theme in the conf file and applies it to the styles directory", function () {
var def = {
less : "http://bootswatch.com/2/" + tasks.jsdocConf.templates.theme + "/bootswatch.less",
lessVariables : "http://bootswatch.com/2/" + tasks.jsdocConf.templates.theme + "/variables.less"
};
grunt.registerTask( "swatch-apply", sys.partial( applyTheme, grunt, def ) );
grunt.task.run( ["swatch-apply"] );
} );
/**
* TASK: Grab all Bootswatch themes and create css from each one based on the main.less in the styles directory. NOTE that this will
* leave the last swatch downloaded in the styles directory, you will want to call "apply" afterwards
* @name bootswatch
* @memberof module:Gruntfile
*/
grunt.registerTask( "bootswatch", "Grab all Bootswatch themes and create css from each one based on the main.less in the styles directory", function () {
var toRun = [];
var done = this.async();
getBootSwatchList( function ( err, list ) {
if ( err ) {return done( err );}
sys.each( list.themes, function ( entry ) {
toRun.push( "swatch" + entry.name );
grunt.registerTask( "swatch" + entry.name, sys.partial( applyTheme, grunt, entry ) );
var key = "template/static/styles/site." + entry.name.toLowerCase() + ".css";
var def = {};
def[key] = "styles/main.less";
tasks.less["swatch" + entry.name] = {
files : def
};
toRun.push( "less:swatch" + entry.name );
} );
grunt.task.run( toRun );
done();
} );
} );
/**
* TASK:Create fixtures from the themes. The files must have been built first from the bootswatch task.
* @name examples
* @memberof module:Gruntfile
*/
grunt.registerTask( "examples", "Create samples from the themes", function () {
var toRun = [];
var done = this.async();
getBootSwatchList( function ( err, list ) {
if ( err ) {return done( err );}
sys.each( list.themes, function ( entry ) {
var conf = grunt.file.readJSON( './fixtures/example.conf.json' );
conf.templates.theme = entry.name.toLowerCase();
grunt.file.write( "tmp/example.conf." + conf.templates.theme + ".json", JSON.stringify( conf, null, 4 ) );
var jsdenv = sys.cloneDeep( jsdocExamplePages );
jsdenv.config = "./tmp/example.conf." + conf.templates.theme + ".json";
jsdenv.dest = "./themes/" + conf.templates.theme;
tasks.shell["example" + conf.templates.theme] = {
command : jsdocCommand( jsdenv )
};
toRun.push( "shell:example" + conf.templates.theme );
} );
grunt.registerTask( "cleanup", "", function () {
grunt.file["delete"]( "tmp/" );
} );
toRun.push( "cleanup" );
grunt.task.run( toRun );
done();
} );
} );
grunt.registerTask( "release", "Create the project documentation", ["shell:release1", "shell:release2"] );
};
/**
* Applies one of the Bootswatch themes to the working `styles` directory. When you want to modify a particular theme, this where you
* get the basis for it. The files are written to `./styles/variables.less` and `./styles/bootswatch.less`. The `./styles/main.less`
* file includes them directly, so after you apply the theme, modify `main.less` to your heart's content and then run the `less` task
* as in
*
* grunt less
*
* @param {object} grunt The grunt object reference
* @param {object} definition The swatch definition files
* @param {string} definition.less The url to the `bootswatch.less` file
* @param {string} definition.lessVariables The url to the `variables.less` file
* @private
*/
function applyTheme( grunt, definition ) {
//noinspection JSHint
var webProtocol = tasks.jsdocConf.templates.protocol || "//";
console.info( webProtocol );
var done = this.async();
async.waterfall( [
function ( cb ) {
getBootSwatchComponent( definition.less, function ( err, swatch ) {
if ( err ) {return cb( err );}
var fullPath = path.join( __dirname, "styles/bootswatch.less" );
fs.writeFile( fullPath, swatch.replace( "http://", webProtocol ), cb );
} );
},
function ( cb ) {
getBootSwatchComponent( definition.lessVariables, function ( err, swatch ) {
if ( err ) {return cb( err );}
var fullPath = path.join( __dirname, "styles/variables.less" );
fs.writeFile( fullPath, swatch.replace( "http://", webProtocol ), cb );
} );
}
], done );
}
/**
* Gets the list of available Bootswatches from, well, Bootswatch.
*
* @see http://news.bootswatch.com/post/22193315172/bootswatch-api
* @param {function(err, responseBody)} done The callback when complete
* @param {?object} done.err If an error occurred, you will find it here.
* @param {object} done.responseBody This is a parsed edition of the bootswatch server's response. It's format it defined
* by the return message from [here](http://api.bootswatch.com/)
* @private
*/
function getBootSwatchList( done ) {
var options = {
hostname : 'api.bootswatch.com',
port : 80,
path : '/',
method : 'GET'
};
var body = "";
var req = http.request( options, function ( res ) {
res.setEncoding( 'utf8' );
res.on( 'data', function ( chunk ) {
body += chunk;
} );
res.on( 'end', function () {
done( null, JSON.parse( body ) );
} );
res.on( 'error', function ( e ) {
done( 'problem with response: ' + e.message );
} );
} );
req.on( 'error', function ( e ) {
done( 'problem with request: ' + e.message );
} );
req.end();
}
/**
* This method will get one of the components from Bootswatch, which is generally a `less` file or a `lessVariables` file.
*
* @see http://news.bootswatch.com/post/22193315172/bootswatch-api
* @param {string} url The url to retreive from
* @param {function(err, responseText)} done The callback when complete
* @param {?object} done.err If an error occurred, you will find it here.
* @param {string} done.responseText The body of whatever was returned
* @private
*/
function getBootSwatchComponent( url, done ) {
var body = "";
var req = http.request( url, function ( res ) {
res.setEncoding( 'utf8' );
res.on( 'data', function ( chunk ) {
body += chunk;
} );
res.on( 'end', function () {
done( null, body );
} );
res.on( 'error', function ( e ) {
done( 'problem with response: ' + e.message );
} );
} );
req.on( 'error', function ( e ) {
done( 'problem with request: ' + e.message );
} );
req.end();
}

View File

@ -0,0 +1,22 @@
Copyright (c) 2012-13 Terry Weiss. All rights reserved.
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

360
node_modules/grunt-jsdoc/node_modules/ink-docstrap/README.md generated vendored Executable file
View File

@ -0,0 +1,360 @@
[![NPM](https://nodei.co/npm/ink-docstrap.png?downloads=true)](https://nodei.co/npm/ink-docstrap/)
# DocStrap [![Built with Grunt](https://cdn.gruntjs.com/builtwith.png)](http://gruntjs.com/) #
DocStrap is [Bootstrap](http://twitter.github.io/bootstrap/index.html) based template for [JSDoc3](http://usejsdoc.org/).
In addition, it includes all of the themes from [Bootswatch](http://bootswatch.com/) giving you a great deal of look
and feel options for your documentation, along with a simple search. Additionally, it adds some options to the conf.json file that gives
you even more flexibility to tweak the template to your needs. It will also make your teeth whiter.
## New ##
* Courtesy [whitelynx](https://github.com/whitelynx), you can now also select [sunlight themes](https://github.com/tmont/sunlight/tree/master/src/themes)
for code blocks.
* Read about Google Analytics (tip of the hat to [pocesar](https://github.com/pocesar))
support and major syntax highlight changes.
* As of version 0.4.0, DocStrap only supports the node version of JSDoc and will no longer support the Java version of JSDoc
* New options in `jsdoc.conf.json` to provide greater control over the output of source files. See `outputSourceFiles` and `sourceRootPath`
* Several updated components for the development environment
## Features ##
* Right side TOC for navigation in pages, with quick search
* Themed
* Customizable
### What It Looks Like ###
Here are examples of this template with the different Bootswatch themes:
+ [Amelia](http://terryweiss.github.io/docstrap/themes/amelia)
+ [Cerulean](http://terryweiss.github.io/docstrap/themes/cerulean)
+ [Cosmo](http://terryweiss.github.io/docstrap/themes/cosmo)
+ [Cyborg](http://terryweiss.github.io/docstrap/themes/cyborg)
+ [Flatly](http://terryweiss.github.io/docstrap/themes/flatly)
+ [Journal](http://terryweiss.github.io/docstrap/themes/journal)
+ [Readable](http://terryweiss.github.io/docstrap/themes/readable)
+ [Simplex](http://terryweiss.github.io/docstrap/themes/simplex)
+ [Slate](http://terryweiss.github.io/docstrap/themes/slate)
+ [Spacelab](http://terryweiss.github.io/docstrap/themes/spacelab)
+ [Spruce](http://terryweiss.github.io/docstrap/themes/spruce)
+ [Superhero](http://terryweiss.github.io/docstrap/themes/superhero)
+ [United](http://terryweiss.github.io/docstrap/themes/united)
To change your theme, just change it in the `conf.json` file. See below for details.
## Ooooh, I want it! How do I get it?##
If you manage your own version of jsdoc:
```
{@lang bash}
npm install ink-docstrap
```
When using [grunt](http://gruntjs.com/), please look at [grunt-jsdoc](https://github.com/krampstudio/grunt-jsdoc) which includes
docstrap
```
{@lang bash}
npm install grunt-jsdoc
```
## Configuring the template ##
DocStrap ships with a `conf.json` file in the template/ directory. It is just a regular old
[JSDoc configuration file](http://usejsdoc.org/about-configuring-jsdoc.html), but with the following new options:
```
{@lang javascript}
"templates": {
"systemName" : "{string}",
"footer" : "{string}",
"copyright" : "{string}",
"navType" : "{vertical|inline}",
"theme" : "{theme}",
"linenums" : "{boolean}",
"collapseSymbols" : "{boolean}",
"inverseNav" : "{boolean}",
"outputSourceFiles" : "{boolean}" ,
"outputSourcePath" : "{boolean}",
"dateFormat" : "{string}",
"highlightTutorialCode" : "{boolean}",
"syntaxTheme" : "{string}"
}
```
### Options ###
* __systemName__
The name of the system being documented. This will appear in the page title for each page
* __footer__
Any markup want to appear in the footer of each page. This is not processed at all, just printed exactly as you enter it
* __copyright__
You can add a copyright message below the footer and above the JSDoc timestamp at the bottom of the page
* __navType__
The template uses top level navigation with dropdowns for the contents of each category. On large systems these dropdowns
can get large enough to expand beyond the page. To make the dropdowns render wider and stack the entries vertically, set this
option to `"inline"`. Otherwise set it to `"vertical"` to make them regular stacked dropdowns.
* __theme__
This is the name of the them you want to use **in all lowercase**. The valid options are
+ `amelia`
+ `cerulean`
+ `cosmo`
+ `cyborg`
+ `flatly`
+ `journal`
+ `readable`
+ `simplex`
+ `slate`
+ `spacelab`
+ `spruce`
+ `superhero`
+ `united`
* __linenums__
When true, line numbers will appear in the source code listing. If you have
[also turned that on](http://usejsdoc.org/about-configuring-jsdoc.html).
* __collapseSymbols__
If your pages have a large number of symbols, it can be easy to get lost in all the text. If you turn this to `true`
all of the symbols in the page will roll their contents up so that you just get a list of symbols that can be expanded
and collapsed.
* __analytics__ Add a [Google Analytics](http://www.google.com/analytics) code to the template output
_e.g._ `"analytics":{"ua":"UA-XXXXX-XXX", "domain":"XXXX"}`
* __ua__ The google agent (see Google Analytics help for details)
* __domain__ The domain being served. (see Google Analytics help for details)
* __inverseNav__
Bootstrap navbars come in two flavors, regular and inverse where inverse is generally higher contrast. Set this to `true` to
use the inverse header.
* __outputSourceFiles__
When true, the system will produce source pretty printed file listings with a link from the documentation.
* __outputSourcePath__
When `outputSourceFiles` is `false`, you may still want to name the file even without a link to the pretty printed output.
Set this to `true` when `outputSourceFiles` is `false`. `outputSourceFiles` when `true` takes precedence over this setting.
* __dateFormat__ The date format to use when printing dates. It accepts any format string understood by [moment.js](http://momentjs.com/docs/#/displaying/format/)
* __highlightTutorialCode__ Boolean used to determine whether to treat code blocks in "tutorial" markdown as examples and highlight them
* __syntaxTheme__ String that determines the theme used for code blocks. Default value is `"default"`. It can be any value supported
at [sunlight themes](https://github.com/tmont/sunlight/tree/master/src/themes) which right now consists of...uh...`"default"` and `"dark"`,
but at least you have it if you need it.
## Controlling Syntax Highlighting ##
Of course this is intended to document JS. But JS often interacts with other languages, most commonly `HTML`, but also any
language on the server including PHP, C# and other C-like languages. The point is that when you write examples, you may want to
include other languages to make your examples as expressive as possible. So, DocStrap introduces a new documentation tag
which can appear inside any example block in source code, or in any fenced code block in markdown: `{@lang languageName}`, where
_`language`_ can be any of the languages supported by [Sunlight](http://sunlightjs.com/)
Look at this:
For an example of this thing in action [this](http://terryweiss.github.io/docstrap/themes/readable/#toc7) )__
The syntax for adding the tag is as follows. When in markdown, add the tag on the line just after the \`\`\` fence like so:
\`\`\`
`{@lang language}`
`This is my code`
\`\`\`
When in a doclet add the tag just after the `@example` tag like this:
`@example {@lang xml}`
`<div>This is the most interesting web site ever</div>`
These are the supported languages.
* ActionScript
* bash
* C/C++
* C♯
* CSS
* Diff
* DOS batch
* Erlang
* Haskell
* httpd (Apache)
* Java
* JavaScript
* Lisp
* Lua
* MySQL
* nginx
* Objective-C
* Perl
* PHP
* PowerShell
* Python
* Ruby
* Scala
* T-SQL
* VB.NET
* XML (HTML)
## Customizing DocStrap ##
No template can meet every need and customizing templates is a favorite pastime of....well, no-one, but you may need to anyway.
First make sure you have [bower](https://github.com/bower/bower) and [grunt-cli](https://github.com/gruntjs/grunt-cli) installed.
Fetch the source using `git` or grab the [zip file from github.](https://github.com/terryweiss/docstrap/archive/master.zip) and unzip
it somewhere. Everything that follows happens in the unzip directory.
Next, prepare the environment:
bower install
and
npm install
When that is done, you have all of the tools to start modifying the template. The template, like Bootstrap, uses [less](http://lesscss.org/).
The way it works is that `./styles/main.less` pulls in the bootstrap files uncompiled so that you have access to all of bootstraps mixins, colors,
etc, that you would want. There are two more files in that directory, `variables.less`, `bootswatch.less`. These are the
theme files and you can modify them, but keep in mind that if you apply a new theme (see below) those files will be overwritten. It is best
to keep your changes to the `main.less` file.
To compile your changes to `main.less` and any other files it loads up,
grunt less
The output is will be put in `./template/static/styles/site.<theme-name>.css`. The next time you create your documentation, it
will have the new css file included.
To apply a different template to the `styles` directory to modify, open up the `conf.json` in the template directory and
change the `theme` option to the theme you want. Then
grunt apply
And the new theme will be in `variables.less`, `bootswatch.less`. Don't forget to compile your changes using `grunt apply` to
get that change into the template.
**NOTE** that these steps are not necessary to just change the theme, this is only to modify the theme. If all you want to do is
change the theme, just update conf.json with the new theme and build your docs!
## Contributing ##
Yes! Contribute! Test! Share your ideas! Report Bugs!
### Contributers ###
*Huge* thanks to all contributors. If your name should be here, but isn't, please let me know
* [marklagendijk](https://github.com/marklagendijk)
* [michaelward82](https://github.com/michaelward82)
* [kaustavdm](https://github.com/kaustavdm)
* [vmeurisse](https://github.com/vmeurisse)
* [bmathern](https://github.com/bmathern)
* [jrkim123us](https://github.com/jrkim123us)
* [shawke](https://github.com/shawke)
* [mar10](https://github.com/mar10)
* [mwcz](https://github.com/mwcz)
* [pocesar](https://github.com/pocesar)
* [hyperandroid](https://github.com/hyperandroid)
* [vmadman](https://github.com/vmadman)
* [whitelynx](https://github.com/whitelynx)
## History ##
### v0.4.11 ###
* Pull Request #59
### v0.4.8 ###
* Issue #58
### v0.4.7 ###
* Issue #57
### v0.4.5 ###
* Issue #55
* Issue #54
* Issue #52
* Issue #51
* Issue #50
* Issue #45
* Issue #44
### v0.4.3 ###
* Issue #46
* Issue #46
* Issue #47
### v0.4.1-1###
* Issue #44
* Update documentation
* Issue #43
* Issue #42
* Issue #34
### v0.4.0 ###
* Issue #41
* Issue #40
* Issue #39
* Issue #36
* Issue #32
### v0.3.0 ###
* Fixed navigation at page top
* Adds -d switch to example jsdoc command.
* Fixed typo in readme
* Improve search box positioning and styles
* Add dynamic quick search in TOC
* Fix for line numbers styling issue
### v0.2.0 ###
* Added jump to source linenumers - still a problem scrolling with fixed header
* changed syntax highlighter to [sunlight](http://sunlightjs.com/)
* Modify incoming bootswatch files to make font calls without protocol.
### v0.1.0 ###
Initial release
## Notices ##
If you like DocStrap, be sure and check out these excellent projects and support them!
[JSDoc3 is licensed under the Apache License](https://github.com/jsdoc3/jsdoc/blob/master/LICENSE.md)
[So is Bootstrap](https://github.com/twitter/bootstrap/blob/master/LICENSE)
[And Bootswatch](https://github.com/thomaspark/bootswatch/blob/gh-pages/LICENSE)
[TOC is licensed under MIT](https://github.com/jgallen23/toc/blob/master/LICENSE)
[Grunt is also MIT](https://github.com/gruntjs/grunt-cli/blob/master/LICENSE-MIT)
DocStrap [is licensed under the MIT license.](https://github.com/terryweiss/docstrap/blob/master/LICENSE.md)
[Sunlight uses the WTFPL](http://sunlightjs.com/)
## License ##
DocStrap Copyright (c) 2012-2014 Terry Weiss. All rights reserved.
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

View File

@ -0,0 +1,12 @@
{
"name": "ink-docstrap",
"version": "0.1.0",
"dependencies": {
"bootstrap": "~2.3.1",
"jquery": "~2.0.0",
"darkstrap": "git://github.com/danneu/darkstrap.git#~0.9.2",
"toc": "~0.1.2",
"sunlight": "https://github.com/tmont/sunlight.git",
"jquery.localScroll": "~1.2.8"
}
}

View File

@ -0,0 +1,10 @@
{
"name": "ink-docstrap",
"version": "0.1.0",
"dependencies": {
"bootstrap": "~2.3.1",
"jquery": "~2.0.0",
"darkstrap": "git://github.com/danneu/darkstrap.git#~0.9.2",
"toc": "~0.1.2"
}
}

View File

@ -0,0 +1,61 @@
"use strict";
/**
* @fileOverview The chains define the primary composition elements (functions) that determine the order of execution.
*
* @module base/chains
* @requires dcl
*/
var dcl = require( "dcl" );
/**
* @classDesc Chains define the primary composition elements (functions) that determine the order of execution.
* @exports base/chains
* @constructor
*/
var Chains = dcl( null, {declaredClass : "base/chains"} );
/**
* The `close` method asks an object to shut itself down in a way that will allow it to be reopened, unlike the
* [end method]{@link base/chains#end} which will call the destroy method which should make the object unusable, but also
* devoid of all resources whereas `close` may still keep some resources open.
*
* This uses the `before` chain which means the last one defined in the first one destroyed
* @memberOf base/chains#
* @name close
* @see base/chains#open
*/
dcl.chainBefore( Chains, "close" );
/**
* The `end` method will call the destroy method which should make the object unusable and
* devoid of all resources, unlike the
* [close method]{@link base/chains#close} asks an object to shut itself down in a way that will allow it to be reopened.
*
* This uses the `before` chain which means the last one defined in the first one destroyed
* @memberOf base/chains#
* @name end
*/
dcl.chainBefore( Chains, "end" );
/**
* Destroy is called by the end method and it is here that you should clean up after yourself. The difference between
* `destroy` and [end]{@link base/chains#end} is the `end` is the verb that you raise on an object to ask it to go away
* and `destroy` is where you actually do the work to clean up. Think of this as the counterpart of `constructor` yet
* not called automatically.
*
* This uses the `before` chain which means the last one defined is the first one destroyed
* @private
* @memberOf base/chains#
* @name destroy
*/
dcl.chainBefore( Chains, "destroy" );
/**
* If you are using the open/close paradigm for an object that can kind of go dormant on {@link base/chains#close} and can be "reopened"
* again later, here is where the "open" code will go.
*
* This used the `after` chain which means that the first one defined is the first one destroyed.
*
* @memberOf base/chains#
* @name open
* @see base/chains#close
*/
dcl.chainAfter( Chains, "open" );
module.exports = Chains;

View File

@ -0,0 +1,73 @@
"use strict";
/**
* @fileOverview This is base definition for all composed classes defined by the system
* @module base
* @requires base/chains
* @requires dcl
*/
var dcl = require( "dcl" );
var chains = require( "./chains" );
/**
* @classdesc The base of all classes in the system, this is one of the few pure "classes" in core the of the system. It is a
* pretty clean little class whose primary purpose is to surface the composition chains and a basis for storing
* options on mixin and subclass instances. Options are handled at the instance rather than the prototype level
* so that multiple instances don't compete for default values.
*
* @exports base
* @constructor
* @extends base/chains
*/
var Base = dcl( [chains], /** @lends base# */{
declaredClass : "Base",
/**
* Add an option to a class. If any members of the hash already exist in `this.options`, they will be overwritten.
* @param {hash} options A hash of options you want to set
* @see {base#addDefaultOptions}
*/
addOptions : function ( options ) {
options = options || {};
if ( this.options ) {options = sys.extend( {}, sys.result( this, 'options' ), options );}
this.options = options;
},
/**
* Add a default option to a class. The default options are only set if there is not already a
* value for the option.
* @param {hash} options A hash of options you want to set
* @see {base#addOptions}
*/
addDefaultOptions : function ( options ) {
options = options || {};
if ( this.options ) {options = sys.defaults( {}, sys.result( this, 'options' ), options );}
this.options = options;
},
/**
* Call this to close your object and dispose of all maintained resources. You can define this method on your
* own classes without having to call the superclass instance, however it is reccomended that you put
* all disposal code in `destroy()`. You must be disciplined about calling this on your instances.
* @see {base/chains#end}
* @see {base/chains#destroy}
*/
end : function () {
this.destroy()
},
/**
* Called when it is time to get rid of all of your instance level references and objects and events. You can
* define this method on your own classes without having to call the superclass instance. It is called by
* `instance.end()` automatically
* @see {base/chains#end}
* @see {base/chains#destroy}
*/
destroy : function () {
}
} );
Base.compose = dcl;
Base.mixin = dcl.mix;
module.exports = Base;

View File

@ -0,0 +1,178 @@
"use strict";
/**
* @fileOverview allows you to bind a change watcher that looks for get and set operations on an arbitrary
* property of an object at at any depth. This allows you to look for changes or intercept values asynchronously or otherwise.
* @module documents/binder
* @requires async
* @requires documents/probe
* @requires lodash
* @requires promise
*/
var Promise = require( 'promise' );
var async = require( "async" );
var probe = require( "./probe" );
var sys = require( "lodash" );
/**
* Identifies the properties that the binder expects
* @type {{getter: null, getterAsync: boolean, setter: null, validator: null, validatorAsync: boolean, setterAsync: boolean}}
* @private
*/
var dataBinderOptions = exports.dataBinderOptions = {
getter : null,
getterAsync : false,
setter : null,
validator : null,
validatorAsync : false,
setterAsync : false
};
/**
* You can unbind previously bound objects from here.
*
* @param {string} path The path that was bound using {@link module:documents/binder.bind}
* @param {*} record The object that was bound
*/
exports.unbind = function ( path, record ) {
var context = record;
var lastParent = context;
var parts = path.split( probe.delimiter );
var lastPartName = path;
var lastParentName;
sys.each( parts, function ( part ) {
lastParentName = part;
lastParent = context;
context = context[part];
lastPartName = part;
if ( sys.isNull( context ) || sys.isUndefined( context ) ) {
context = {};
}
} );
if ( lastParent === context ) {
deleteBindings( record, lastPartName );
} else {
deleteBindings( lastParent, lastPartName );
}
function deleteBindings( mountPoint, mountName ) {
mountPoint[mountName] = mountPoint["__" + mountName + "__"];
delete mountPoint["__" + mountName + "__"];
}
};
/**
* Bind to a property somewhere in an object. The property is found using dot notation and can be arbitrarily deep.
* @param {string} path The path into the object to locate the property. For instance this could be `"_id"`, `"name.last"`.
* or `"some.really.really.long.path.including.an.array.2.name"`
* @param {object} record Anything you can hang a property off of
* @param {options} options What you wanna do with the doohicky when yoyu bind it.
* @param {function(*):Promise|*=} options.getter This is the method to run when getting the value. When it runs, you will receive
* a single parameter which is the current value as the object understands it. You can return the value directly, just raise an event or
* whatever your little heart demands. However, if you are asynchronous, this will turn your return value into a promise, one of the
* few places this system will embrace promises over node-like error passing and that is mainly because this is a getter so a return value
* is particularly important. *
* @param {*} options.getter.value The current value of the record
* @param {function(err, value)=} options.getter.callback When asynchronous, return you value through this method using node style
* error passing (the promise is handled for you by this method).
* @param {boolean=} options.getterAsync When true (not truthy) the getter is treated asynchronously and returns a promise with your value.
* @param {function(*, *, *)=} options.setter A setter method
* @param {*} options.setter.newVal The new value
* @param {*} options.setter.oldVal The old value
* @param {*} options.setter.record The record hosting the change
* @param {function(*, *, *, function=)=} options.validator If you want a validator to run before settings values, pass this guy in
* @param {*} options.validator.newVal The new value
* @param {*} options.validator.oldVal The old value
* @param {*} options.validator.record The record hosting the change
* @param {function(err)=} options.validator.callback If the validator is asynchronous, then pass your value back here, otherwise pass it back as a return value.
* When you use an asynchronous instance, pass the error in the first value and then the rest of the parameters are yours to play with
* @param {boolean=} options.validatorAsync When true (not truthy) the validator is treated asynchornously and returns a promise with your value.
* @returns {*}
*/
exports.bind = function ( path, record, options ) {
options = sys.extend( {}, dataBinderOptions, options );
var context = record;
var lastParent = context;
var parts = path.split( probe.delimiter );
var lastPartName = path;
var lastParentName;
sys.each( parts, function ( part ) {
lastParentName = part;
lastParent = context;
context = context[part];
lastPartName = part;
if ( sys.isNull( context ) || sys.isUndefined( context ) ) {
context = {};
}
} );
if ( lastParent === context ) {
setUpBindings( record, lastPartName );
} else {
setUpBindings( lastParent, lastPartName );
}
function setUpBindings( mountPoint, mountName ) {
mountPoint["__" + mountName + "__"] = mountPoint[mountName];
Object.defineProperty( mountPoint, mountName, {
get : function () {
if ( sys.isFunction( options.getter ) ) {
var promise;
if ( options.getterAsync === true ) {
promise = Promise.denodeify( options.getter );
}
if ( promise ) {
return promise( mountPoint["__" + mountName + "__"] ).then( function ( val ) {
mountPoint["__" + mountName + "__"] = val;
} );
} else {
mountPoint["__" + mountName + "__"] = options.getter( mountPoint["__" + mountName + "__"] );
return mountPoint["__" + mountName + "__"];
}
} else {
return mountPoint["__" + mountName + "__"];
}
},
set : function ( val ) {
async.waterfall( [
function ( done ) {
if ( sys.isFunction( options.validator ) ) {
if ( options.validatorAsync ) {
options.validator( val, mountPoint["__" + mountName + "__"], record, done );
} else {
var res = options.validator( val, mountPoint["__" + mountName + "__"], record );
if ( res === true ) {
done();
} else {
done( res );
}
}
} else {
done();
}
},
function ( done ) {
if ( sys.isFunction( options.setter ) ) {
if ( options.setterAsync === true ) {
options.setter( val, mountPoint["__" + mountName + "__"], record, done );
} else {
done( null, options.setter( val, mountPoint["__" + mountName + "__"], record ) );
}
} else {
done( null, val );
}
}
], function ( err, newVal ) {
if ( err ) { throw new Error( err ); }
mountPoint["__" + mountName + "__"] = newVal;
} );
}
} );
}
return context;
};

View File

@ -0,0 +1,496 @@
"use strict";
/**
@fileOverview An object and array collector
@module ink/collector
*/
var probe = require( "ink-probe" );
var sys = require( "lodash" );
var dcl = require( "dcl" );
/**
* A collector
* @constructor
*/
var CollectorBase = dcl( Destroyable, {
declaredClass : "CollectorBase",
constructor : function ( obj ) {
var that = this;
if ( obj && !sys.isObject( obj ) ) {
throw new TypeError( "Collectors require an initial object or array passed to the constructor" );
}
/**
* The collection that being managed
* @type {object|array}
*/
this.heap = obj || {};
// mixin the probe
probe.mixTo( this, this.heap );
/**
* Get the size of the collection
* @name length
* @type {number}
* @memberOf module:documents/collector~CollectorBase#
*/
Object.defineProperty( this, "length", {
get : function () {
return sys.size( that.heap );
}
}
);
/**
* Creates an array of shuffled array values, using a version of the Fisher-Yates shuffle.
* See http://en.wikipedia.org/wiki/Fisher-Yates_shuffle.
* @function
* @memberOf module:documents/collector~CollectorBase#
* @returns {array}
*/
this.shuffle = sys.bind( sys.shuffle, this, this.heap );
},
/**
* Adds an item to the collection
* @param {*} key The key to use for the item being added.
* @param {*} item The item to add to the collection. The item is not iterated so that you could add bundled items to the collection
*/
add : function ( key, item ) {
this.heap[key] = item;
},
/**
* Iterate over each item in the collection, or a subset that matches a query. This supports two signatures:
* `.each(query, function)` and `.each(function)`. If you pass in a query, only the items that match the query
* are iterated over.
* @param {object=} query A query to evaluate
* @param {function(val, key)} iterator Function to execute against each item in the collection
* @param {object=} thisobj The value of `this`
*/
each : function ( query, iterator, thisobj ) {
if ( sys.isPlainObject( query ) ) {
thisobj = thisobj || this;
sys.each( this.find( query ), iterator, thisobj );
} else {
thisobj = iterator || this;
sys.each( this.heap, query, thisobj );
}
},
/**
* Returns the collection as an array. If it is already an array, it just returns that.
* @return {array}
*/
toArray : function () {
return sys.toArray( this.heap );
},
/**
* Supports conversion to a JSON string or for passing over the wire
* @return {object}
* @returns {Object|array}
*/
toJSON : function () {
return this.heap;
},
/**
* Maps the contents to an array by iterating over it and transforming it. You supply the iterator. Supports two signatures:
* `.map(query, function)` and `.map(function)`. If you pass in a query, only the items that match the query
* are iterated over.
* @param {object=} query A query to evaluate
* @param {function(val, key)} iterator Function to execute against each item in the collection
* @param {object=} thisobj The value of `this`
*/
map : function ( query, iterator, thisobj ) {
if ( sys.isPlainObject( query ) ) {
thisobj = thisobj || this;
return sys.map( this.find( query ), iterator, thisobj );
} else {
thisobj = iterator || this;
return sys.map( this.heap, query, thisobj );
}
},
/**
* Reduces a collection to a value which is the accumulated result of running each element in the collection through the
* callback, where each successive callback execution consumes the return value of the previous execution. If accumulator
* is not passed, the first element of the collection will be used as the initial accumulator value.
* are iterated over.
* @param {object=} query A query to evaluate
* @param {function(result, val, key)} iterator The function that will be executed in each item in the collection
* @param {*=} accumulator Initial value of the accumulator.
* @param {object=} thisobj The value of `this`
* @return {*}
*/
reduce : function ( query, iterator, accumulator, thisobj ) {
if ( sys.isPlainObject( query ) ) {
thisobj = thisobj || this;
return sys.reduce( this.find( query ), iterator, accumulator, thisobj );
} else {
thisobj = accumulator || this;
return sys.reduce( this.heap, query, iterator, thisobj );
}
},
/**
* Creates an object composed of keys returned from running each element
* of the collection through the given callback. The corresponding value of each key
* is the number of times the key was returned by the callback.
* @param {object=} query A query to evaluate. If you pass in a query, only the items that match the query
* are iterated over.
* @param {function(value, key, collection)} iterator
* @param {object=} thisobj The value of `this`
* @return {object}
*/
countBy : function ( query, iterator, thisobj ) {
if ( sys.isPlainObject( query ) ) {
thisobj = thisobj || this;
return sys.countBy( this.find( query ), iterator, thisobj );
} else {
thisobj = iterator || this;
return sys.countBy( this.heap, query, thisobj );
}
},
/**
* Creates an object composed of keys returned from running each element of the collection through the callback.
* The corresponding value of each key is an array of elements passed to callback that returned the key.
* The callback is invoked with three arguments: (value, index|key, collection).
* @param {object=} query A query to evaluate . If you pass in a query, only the items that match the query
* are iterated over.
* @param {function(value, key, collection)} iterator
* @param {object=} thisobj The value of `this`
* @return {object}
*/
groupBy : function ( query, iterator, thisobj ) {
if ( sys.isPlainObject( query ) ) {
thisobj = thisobj || this;
return sys.groupBy( this.find( query ), iterator, thisobj );
} else {
thisobj = iterator || this;
return sys.groupBy( this.heap, query, thisobj );
}
},
/**
* Reduce the collection to a single value. Supports two signatures:
* `.pluck(query, function)` and `.pluck(function)`
* @param {object=} query The query to evaluate. If you pass in a query, only the items that match the query
* are iterated over.
* @param {string} property The property that will be 'plucked' from the contents of the collection
* @return {*}
*/
pluck : function ( query, property ) {
if ( arguments.length === 2 ) {
return sys.map( this.find( query ), function ( record ) {
return probe.get( record, property );
} );
} else {
return sys.map( this.heap, function ( record ) {
return probe.get( record, query );
} );
}
},
/**
* Returns a sorted copy of the collection.
* @param {object=} query The query to evaluate. If you pass in a query, only the items that match the query
* are iterated over.
* @param {function(value, key)} iterator
* @param {object=} thisobj The value of `this`
* @return {array}
*/
sortBy : function ( query, iterator, thisobj ) {
if ( sys.isPlainObject( query ) ) {
thisobj = thisobj || this;
return sys.sortBy( this.find( query ), iterator, thisobj );
} else {
thisobj = iterator || this;
return sys.sortBy( this.heap, query, thisobj );
}
},
/**
* Retrieves the maximum value of an array. If callback is passed,
* it will be executed for each value in the array to generate the criterion by which the value is ranked.
* @param {object=} query A query to evaluate . If you pass in a query, only the items that match the query
* are iterated over.
* @param {function(value, key, collection)} iterator
* @param {object=} thisobj The value of `this`
* @return {number}
*/
max : function ( query, iterator, thisobj ) {
if ( sys.isPlainObject( query ) ) {
thisobj = thisobj || this;
return sys.max( this.find( query ), iterator, thisobj );
} else {
thisobj = iterator || this;
return sys.max( this.heap, query, thisobj );
}
},
/**
* Retrieves the minimum value of an array. If callback is passed,
* it will be executed for each value in the array to generate the criterion by which the value is ranked.
* @param {object=} query A query to evaluate . If you pass in a query, only the items that match the query
* are iterated over.
* @param {function(value, key, collection)} iterator
* @param {object=} thisobj The value of `this`
* @return {number}
*/
min : function ( query, iterator, thisobj ) {
if ( sys.isPlainObject( query ) ) {
thisobj = thisobj || this;
return sys.min( this.find( query ), iterator, thisobj );
} else {
thisobj = iterator || this;
return sys.min( this.heap, query, thisobj );
}
},
/**
* Destructor called when the object is destroyed.
*/
destroy : function () {
this.heap = null;
}
} );
/**
* An object based collector
* @extends module:documents/collector~CollectorBase
* @constructor
*/
var OCollector = dcl( CollectorBase, {
/**
* Get a record by key
* @param {*} key The key of the record to get
* @return {*}
*/
key : function ( key ) {
return this.heap[key];
}
} );
//noinspection JSCommentMatchesSignature
/**
An array based collector
@extends module:documents/collector~CollectorBase
@constructor
*/
var ACollector = dcl( CollectorBase, {
constructor : function ( obj ) {
if ( obj && !sys.isArray( obj ) ) {
throw new TypeError( "Collectors require an array passed to the constructor" );
}
this.heap = obj || [];
/**
* Creates an array of array elements not present in the other arrays using strict equality for comparisons, i.e. ===.
* @returns {array}
*/
this.difference = sys.bind( sys.difference, this, this.heap );
/**
* This method gets all but the first values of array
* @param {number=} n The numer of items to return
* @returns {*}
*/
this.tail = sys.bind( sys.tail, this, this.heap );
/**
* Gets the first n values of the array
* @param {number=} n The numer of items to return
* @returns {*}
*/
this.head = sys.bind( sys.head, this, this.heap );
},
/**
* Adds to the top of the collection
* @param {*} item The item to add to the collection. Only one item at a time can be added
*/
add : function ( item ) {
this.heap.unshift( item );
},
/**
* Add to the bottom of the list
* @param {*} item The item to add to the collection. Only one item at a time can be added
*/
append : function ( item ) {
this.heap.push( item );
},
/**
* Add an item to the top of the list. This is identical to `add`, but is provided for stack semantics
* @param {*} item The item to add to the collection. Only one item at a time can be added
*/
push : function ( item ) {
this.add( item );
},
/**
* Modifies the collection with all falsey values of array removed. The values false, null, 0, "", undefined and NaN are all falsey.
*/
compact : function () {
this.heap = sys.compact( this.heap );
},
/**
* Creates an array of elements from the specified indexes, or keys, of the collection. Indexes may be specified as
* individual arguments or as arrays of indexes
* @param {indexes} args The indexes to use
*/
at : function () {
var arr = sys.toArray( arguments );
arr.unshift( this.heap );
return sys.at.apply( this, arr );
},
/**
* Flattens a nested array (the nesting can be to any depth). If isShallow is truthy, array will only be flattened a single level.
* If callback is passed, each element of array is passed through a callback before flattening.
* @param {object=} query A query to evaluate . If you pass in a query, only the items that match the query
* are iterated over.
* @param {function(value, key, collection)} iterator,
* @param {object=} thisobj The value of `this`
* @return {number}
*/
flatten : function ( query, iterator, thisobj ) {
if ( sys.isPlainObject( query ) ) {
thisobj = thisobj || this;
return sys.flatten( this.find( query ), iterator, thisobj );
} else {
thisobj = iterator || this;
return sys.flatten( this.heap, query, thisobj );
}
},
/**
* Gets an items by its index
* @param {number} key The index to get
* @return {*}
*/
index : function ( index ) {
return this.heap[ index ];
}
}
);
/**
Collect an object
@param {array|object} obj What to collect
@return {ACollector|OCollector}
*/
exports.collect = function ( obj ) {
if ( sys.isArray( obj ) ) {
return new ACollector( obj );
} else {
return new OCollector( obj );
}
};
exports.array = function ( obj ) {
return new ACollector( obj );
};
exports.object = function ( obj ) {
return new OCollector( obj );
};
/**
Returns true if all items match the query. Aliases as `all`
@function
@param {object} qu The query to execute
@returns {boolean}
@name every
@memberOf module:documents/collector~CollectorBase#
*/
/**
Returns true if any of the items match the query. Aliases as `any`
@function
@param {object} qu The query to execute
@returns {boolean}
@memberOf module:documents/collector~CollectorBase#
@name some
*/
/**
Returns the set of unique records that match a query
@param {object} qu The query to execute.
@return {array}
@memberOf module:documents/collector~CollectorBase#
@name unique
@method
**/
/**
Returns true if all items match the query. Aliases as `every`
@function
@param {object} qu The query to execute
@returns {boolean}
@name all
@memberOf module:documents/collector~CollectorBase#
*/
/**
Returns true if any of the items match the query. Aliases as `all`
@function
@param {object} qu The query to execute
@returns {boolean}
@memberOf module:documents/collector~CollectorBase#
@name any
*/
/**
Remove all items in the object/array that match the query
@param {object} qu The query to execute. See {@link module:ink/probe.queryOperators} for the operators you can use.
@return {object|array} The array or object as appropriate without the records.
@memberOf module:documents/collector~CollectorBase#
@name remove
@method
**/
/**
Returns the first record that matches the query and returns its key or index depending on whether `obj` is an object or array respectively.
Aliased as `seekKey`.
@param {object} qu The query to execute.
@returns {object}
@memberOf module:documents/collector~CollectorBase#
@name findOneKey
@method
*/
/**
Returns the first record that matches the query. Aliased as `seek`.
@param {object} qu The query to execute.
@returns {object}
@memberOf module:documents/collector~CollectorBase#
@name findOne
@method
*/
/**
Find all records that match a query and returns the keys for those items. This is similar to {@link module:ink/probe.find} but instead of returning
records, returns the keys. If `obj` is an object it will return the hash key. If 'obj' is an array, it will return the index
@param {object} qu The query to execute.
@returns {array}
@memberOf module:documents/collector~CollectorBase#
@name findKeys
@method
*/
/**
Find all records that match a query
@param {object} qu The query to execute.
@returns {array} The results
@memberOf module:documents/collector~CollectorBase#
@name find
@method
**/
/**
Updates all records in obj that match the query. See {@link module:ink/probe.updateOperators} for the operators that are supported.
@param {object} qu The query which will be used to identify the records to updated
@param {object} setDocument The update operator. See {@link module:ink/probe.updateOperators}
@memberOf module:documents/collector~CollectorBase#
@name update
@method
*/

View File

@ -0,0 +1,117 @@
"use strict";
/**
* @fileOverview A model is the first level if usable data-bearing entity in the system. It does NOT include any verbs for saving or anything like
* that, it is a pure, in memory data container
* @module documents/model
* @require base
* @require documents/probe
* @require lodash
*/
var Base = require( "../base" );
var probe = require( "./probe" );
var sys = require( "lodash" );
/**
* A model is the first level if usable data-bearing entity in the system. It does NOT include any verbs for saving or anything like
* that, it is a pure, in memory data container
* @exports documents/model
* @constructor
* @borrows module:documents/probe.get as get
* @borrows module:documents/probe.set as set
* @borrows module:documents/probe.any as any
* @borrows module:documents/probe.all as all
* @borrows module:documents/probe.remove as remove
* @borrows module:documents/probe.seekKey as seekKey
* @borrows module:documents/probe.seek as seek
* @borrows module:documents/probe.findOne as findOne
* @borrows module:documents/probe.findOneKey as findOneKey
* @borrows module:documents/probe.findKeys as findKeys
* @borrows module:documents/probe.find as find
* @borrows module:documents/probe.update as update
* @borrows module:documents/probe.some as some
* @borrows module:documents/probe.every as every
*/
var Model = Base.compose( [Base], /** @lends documents/model# */{
constructor : function () {
var that = this;
probe.mixin( this );
var idField = "_id";
/**
* The name of the field that uniquely identifies a record. When provided, some operations will take advantage of it
*
* @name _idField
* @memberOf documents/model#
* @type {string}
* @private
*/
Object.defineProperty( this, "_idField", {
get : function () {
return idField;
},
set : function ( val ) {
idField = val;
},
configurable : false,
enumerable : true,
writable : true
} );
/**
* The value of the primary key if {@link documents/model#_idField} is filled in. It will be null if none found
*
* @name _pkey
* @memberOf documents/model#
* @type {*}
* @private
*/
Object.defineProperty( this, "_pkey", {
get : function () {
var val;
if ( !sys.isEmpty( that._idField ) ) {
val = that[that._idField];
}
return val;
},
set : function ( val ) {
if ( !sys.isEmpty( that._idField ) ) {
that[that._idField] = val;
}
},
configurable : false,
enumerable : true,
writable : true
} );
/**
* If {@link documents/model#_idField} is filled in and it's value is empty this will be true.
* @type {boolean}
* @name isNew
* @memberOf documents/model#
*/
Object.defineProperty( this, "isNew", {
get : function () {
return !sys.isEmpty( that._idField ) && !sys.isEmpty( that[that._idField] )
},
configurable : false,
enumerable : true,
writable : false
} );
/**
* Returns true if this instance is empty
* @type {boolean}
* @name isEmpty
* @memberOf documents/model#
*/
Object.defineProperty( this, "isEmpty", {
get : function () {
return sys.isEmpty( that );
},
configurable : false,
enumerable : true,
writable : false
} );
}
} );
module.exports = Model;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,292 @@
"use strict";
/**
* @fileOverview Enables a schema and validation feature set to your document or other object.
* @module documents/schema
* @requires base
* @requires jjv
* @require lodash
*/
var sys = require( "lodash" );
var Validator = require( "jjv" );
var Base = require( "../base" );
/**
* The validator mixin provides access to the features of the JSON validation system
* @exports documents/schema
* @mixin
*/
var Schema = Base.compose( [Base], /** @lends documents/schema# */{
constructor : function () {
/**
* The schema that defines the validation rules. This should probably be defined at the prototype for each
* object or model classification. It can be an anonymous schema defined right here, or this can be
* registered schema names to use, or just a single name
*
* @type {object}
* @memberOf documents/schema#
* @name schema
*/
/**
* If you want to register multiple schemas, use this property instead
*
* @type {object}
* @memberOf documents/schema#
* @name schemas
*/
/**
* The validation environment
* @private
* @type {jjv}
*/
var env = new Validator();
/**
* The default name of the scheman when you use anonymous schemas. You can define this at the prototype for classified
* schemas. The can also
*
* @type {string|function():{string}}
* @memberOf documents/schema#
* @name _defaultSchemaName
*/
this._defaultSchemaName = sys.result( this, "_defaultSchemaName" ) || sys.uniqueId( "schema" );
/**
* The options to pass to the validator when it runs
* @type {object|function():{object}}
* @name validationOptions
* @memberOf documents/schema#
*/
this.validationOptions = sys.defaults( {}, sys.result( this, 'validationOptions' ), {checkRequired : true} );
/**
* Validate an object against the schema
* @returns {object?}
* @method
* @name validate
* @memberOf documents/schema#
* @param {object=} record The record to validate
* @param {string|object=} schemaName The name of a previously registered schema
* @param {object=} options Options to pass to the validator
* @example
* // This supports these signatures:
*
* instance.validate(record, schemaName, options);
*
*
* instance.validate(); // this, this._defaultSchemaName, this.validationOptions
* instance.validate(record); // record, this._defaultSchemaName, this.validationOptions
* instance.validate(schemaName); //this, schemaName, this.validationOptions
* instance.validate(record, schemaName); //record, schemaName, this.validationOptions
* instance.validate(schemaName, options); //this, schemaName, this.validationOptions
*/
this.validate = function ( record, schemaName, options ) {
if ( arguments.length === 0 ) {
record = this;
schemaName = this._defaultSchemaName;
options = this.validationOptions;
} else {
if ( sys.isString( record ) ) {
schemaName = record;
record = this;
}
if ( sys.isEmpty( options ) ) {
options = this.validationOptions;
}
}
return env.validate( schemaName, record, options );
};
/**
* Initialize the schema collection by registering the with the handler. You can call this at any time and as often as you like. It will be called once
* by the constructor on any instance schemas
* @method
* @name registerSchemas
* @memberOf documents/schema#
* @param {hash} schemas A hash of schemas where the key is the name of the schema
*/
this.registerSchemas = function ( schemas ) {
var schema = sys.result( this, "schema" );
var schemas = schemas || sys.result( this, "schemas" );
if ( !sys.isEmpty( schema ) ) {
env.addSchema( this._defaultSchemaName, schema );
}
if ( !sys.isEmpty( schemas ) ) {
sys.each( schemas, function ( val, key ) {
env.addSchema( val, key );
} );
}
};
/**
* Extracts only the elements of the object that are defined in the schema
* @memberOf documents/schema#
* @name extract
* @param {object=} record The record to extract from
* @param {string=} schema The name of the schema to attach
* @method
*/
this.extract = function ( record, schema ) {
if ( arguments.length === 0 ) {
record = this;
schema = this._defaultSchemaName;
}
if ( sys.isString( record ) ) {
schema = record;
record = this;
}
};
/**
* Create a type to be used in your schemas to define new validators
* @memberOf documents/schema#
* @name addType
* @method
* @param {string} name The name of the type
* @param {function(object)} operation What to do with the type.
* @param {object} operation.value The value to validation
* @returns {boolean}
*/
this.addType = env.addType;
/**
* It is also possible to add support for additional string formats through the addFormat function.
* @memberOf documents/schema#
* @name addFormat
* @method
* @param {string} name The name of the formatter
* @param {function(object)} formatter How to format it
* @param {object} formatter.value The value to format
* @returns {boolean}
*/
this.addFormat = env.addFormat;
/**
* It is possible to add support for custom checks (i.e., minItems, maxItems, minLength, maxLength, etc.) through the addCheck function
* @memberOf documents/schema#
* @name addCheck
* @method
* @param {string} name The name of the check
* @param {function(...object)} formatter Perform the check
* @param {object} formatter.value The value to check followed by any parameters from the schema
* @returns {boolean}
*/
this.addCheck = env.addCheck;
/**
* Custom coercion rules
*
* @memberOf documents/schema#
* @name addTypeCoercion
* @method
* @param {string} name The name of the coercion
* @param {function(object)} coercer Perform the coercion
* @param {object} coercer.value The value to coerce
* @returns {boolean}
*/
this.addTypeCoercion = env.addTypeCoercion;
/**
* Get a registered schema by name
* @param {string=} schemaName
* @returns {object?}
* @memberOf documents/schema#
* @name getSchema
* @method
*/
this.getSchema = function ( schemaName ) {
if ( sys.isEmpty( schemaName ) || !sys.isString() ) {
schemaName = this._defaultSchemaName;
}
return env.schema[schemaName];
}
},
/**
* This method will create a new object that contains only the fields and no methods or other artifacts. This is useful
* for creating objects to pass over the wire or save in a table. This is not deeply copied, so changes made to the
* extracted object will be represented in this class for reference objects.
*
* @param {string=} schema The schema name to use
* @param {object=} src The object to extract fields from
* @return {object} Data-only version of the class instance.
*/
extract : function ( schemaName, src ) {
if ( sys.isObject( schemaName ) ) {
src = schema;
schemaName = this._defaultSchemaName;
}
if ( sys.isEmpty( src ) ) {
src = this;
}
if ( sys.isFunction( src.toJSON ) ) {
src = src.toJSON();
}
var schema = this.getSchema( schemaName ) || {};
var newobj = {};
sys.each( schema.properties, function ( prop, propname ) {
if ( prop.properties && !sys.isUndefined( src[ propname ] ) ) {
newobj[ propname ] = this.extract( prop, src[propname] );
} else if ( !sys.isUndefined( src[ propname ] ) ) {
newobj[ propname ] = src[ propname ];
}
}, this );
return newobj;
},
/**
* Builds a default document based on the schema. What this does is create a document from schema and for each property
* that has a default value or is required, the resultant object will contain that property. It is useful for extending
* values from some source that may be incomplete, like options or some such.
* @param {json-schema} schema A schema to use to create the default document
* @returns {object?}
* @name defaultDoc
* @memberOf documents/schema#
* @method
*/
defaultDoc : function ( schemaName ) {
if ( sys.isEmpty( schemaName ) ) {
schemaName = this._defaultSchemaName;
}
var newdoc = {};
var schema;
if ( sys.isObject( schemaName ) ) {
schema = schemaName;
} else {
schema = this.getSchema( schemaName ) || {};
}
sys.each( schema.properties, function ( val, key ) {
var def = val[ "default" ]; // keyword and all that
if ( val.type === "object" && !sys.isEmpty( val.properties ) ) {
newdoc[ key ] = this.defaultDoc( val );
} else {
if ( sys.isFunction( def ) || sys.isBoolean( def ) || sys.isNumber( def ) || !sys.isEmpty( def ) ) {
if ( sys.isFunction( def ) ) {
newdoc[ key ] = def( schema );
} else {
newdoc[ key ] = def;
}
} else if ( val.required ) {
if ( val.type === 'string' ) {
newdoc[ key ] = null;
} else if ( val.type === 'object' ) {
newdoc[ key ] = {};
} else if ( val.type === 'array' ) {
newdoc[ key ] = [];
} else {
newdoc[ key ] = null;
}
}
}
}, this );
return newdoc;
}
} );
module.exports = Schema;

View File

@ -0,0 +1,26 @@
{
"tags" : {
"allowUnknownTags" : true
},
"plugins" : ["plugins/markdown"],
"templates" : {
"cleverLinks" : false,
"monospaceLinks" : false,
"dateFormat" : "ddd MMM Do YYYY",
"outputSourceFiles" : true,
"outputSourcePath" : true,
"systemName" : "DocStrap",
"footer" : "",
"copyright" : "DocStrap Copyright © 2012-2013 The contributors to the JSDoc3 and DocStrap projects.",
"navType" : "vertical",
"theme" : "cosmo",
"linenums" : true,
"collapseSymbols" : false,
"inverseNav" : true,
"highlightTutorialCode" : true
},
"markdown" : {
"parser" : "gfm",
"hardwrap" : true
}
}

View File

@ -0,0 +1,98 @@
"use strict";
/**
* @fileOverview Provides easy access to the system bus and provides some helper methods for doing so
* @module mixins/bussable
* @requires postal
* @requires lodash
* @requires base
*/
var bus = require( "postal" );
var Base = require( "../base" );
var sys = require( "lodash" );
/**
* @classDesc Provides easy access to the system bus and provides some helper methods for doing so
* @exports mixins/bussable
* @mixin
*/
var Bussable = Base.compose( [Base], /** @lends mixins/bussable# */{
declaredClass : "mixins/Bussable",
constructor : function () {
/**
* The list of subscriptions maintained by the mixin
* @type {Array}
* @memberof mixins/bussable#
* @name _subscriptions
* @private
*/
this._subscriptions = {};
this.log.trace( "Bussable constructor" );
},
/**
* Subscribe to an event
* @param {string} channel The channel to subscribe to
* @param {string} topic The topic to subscribe to
* @param {callback} callback What to do when you get the event
* @returns {object} The subscription definition
*/
subscribe : function ( channel, topic, callback ) {
this.log.trace( "Bussable subscribe" );
var sub = bus.subscribe( {channel : channel, topic : topic, callback : callback} );
this.subscriptions[channel + "." + topic] = sub;
return sub;
},
/**
* Subscribe to an event once
* @param {string} channel The channel to subscribe to
* @param {string} topic The topic to subscribe to
* @param {callback} callback What to do when you get the event
* @returns {object} The subscription definition
*/
once : function ( channel, topic, callback ) {
this.log.trace( "Bussable once" );
var sub = this.subscribe( channel, topic, callback );
this.subscriptions[channel + "." + topic] = sub;
sub.disposeAfter( 1 );
return sub;
},
/**
* Publish an event on the system bus
* @param {string} channel The channel to publish to
* @param {string} topic The topic to publish to
* @param {object=} options What to pass to the event
*/
publish : function ( channel, topic, options ) {
this.log.trace( "Bussable publish" );
bus.publish( {channel : channel, topic : topic, data : options} );
},
/**
* Get a subscription definition
*
* @param {string} channel
* @param {string} topic
* @returns {object=} The subscription definition
*/
getSubscription : function ( channel, topic ) {
this.log.trace( "Bussable getSubscription" );
return this.subscriptions[channel + "." + topic];
},
/**
* Gets rid of all subscriptions for this object.
* @private
*/
destroy : function () {
this.log.trace( "Bussable destroy" );
sys.each( this.subscriptions, function ( sub ) {
sub.unsubscribe();
} );
}
} );
module.exports = Bussable;

View File

@ -0,0 +1,245 @@
"use strict";
/**
* @fileOverview Add the ability to fire signals on your objects. Signals are events, but hard coded into the object
* and don't rely on strings like other events and `eventables`
* @module mixins/signalable
* @requires base
* @requires signals
* @requires base/logger
*/
var Base = require( "../base" );
var signals = require( 'signals' );
var format = require( "../strings/format" );
var sys = require( "lodash" );
/**
* @typedef
* @property {boolean=} memorize If Signal should keep record of previously dispatched parameters and automatically execute listener. Defaults to `false`
* @property {array=} params Default parameters passed to listener during `Signal.raise`/`Signal.fire`/`Signal.trigger` and SignalBinding.execute. (curried parameters). Defaults to `null`
* @property {object=} context When provided the signal will be raised in the context of this object. Defaults to `this` - the signal host
* @name SignalOptions
* @memberOf module:mixins/signalable
* @example
*
* signals:{
* opened: null,
* twisted: { memorize:true },
* applied: { memorize: false, params:[one, two] }
* }
*
* // Setting the context initially can be a hassle, so this also supports a function that returns a hash
*
* signals: function(){
* return {
* opened: null,
* twisted: { memorize:true },
* applied: { memorize: false, params:[one, two] },
* reversed: {context: someOtherRuntimeObject}
* };
* }
*
*/
/**
* @classDesc A signal that can be raised on an object. When you deploy the `Signalable` mixin, it
* creates instances of these for you.
*
* @constructor
* @param {?object} host If hosted, you can identify the host here.
* @param {?string} name The name of the signal
* @type module:mixins/signalable.SignalOptions
*/
var Signal = Base.compose( [Base, signals.Signal], /** @lends module:mixins/signalable~Signal# */{
declaredClass : "mixins/Signal",
constructor : function ( host, name, options ) {
options = options || {};
this.memorize = options.memorize === true;
this.host = host;
this.trigger = this.fire = this.raise = this.dispatch;
this.name = name || sys.uniqueId( "signal" );
this.params = options.params;
this.defaultContext = options.context;
},
/**
* Cleans up
* @private
*/
destroy : function () {
this.removeAll();
this.dispose();
this.host = null;
},
/**
* Ties a listener to a signal.
* @param {function} listener The function to call when the signal is raised
* @param {?object} listenerContext A context to set for the listener. The event host may set a default for this value, but you may override that here.
* @param {?number} priority A priority for the listener.
* @returns {SignalBinding}
*/
on : function ( listener, listenerContext, priority ) {
if ( sys.isNumber( listenerContext ) ) {
priority = listenerContext;
listenerContext = null;
}
listenerContext = listenerContext || this.defaultContext || this.host;
var binding = this.add( listener, listenerContext, priority );
if ( this.options.params ) {
binding.params = this.arams;
}
return binding;
},
/**
* Ties a listener to for a signal for one execution.
* @param {function} listener The function to call when the signal is raised
* @param {?object} listenerContext A context to set for the listener. The event host may set a default for this value, but you may override that here.
* @param {?number} priority A priority for the listener.
* @returns {SignalBinding}
*/
once : function ( listener, listenerContext, priority ) {
if ( sys.isNumber( listenerContext ) ) {
priority = listenerContext;
listenerContext = null;
}
listenerContext = listenerContext || this.defaultContext || this.host;
var binding = this.addOnce( listener, listenerContext, priority );
if ( this.options.params ) {
binding.params = this.params;
}
return binding;
},
/**
* Unbinds a listener to a signal.
* @param {function} listener The function to unbind
* @param {?object} listenerContext The context that was bound
* @returns {function}
*/
off : function ( listener, listenerContext ) {
listenerContext = listenerContext || this.host;
return this.remove( listener, listenerContext );
},
/**
* Check if listener was attached to Signal.
* @param {function} listener The function to check
* @param {?object} listenerContext The context that was bound
* @returns {boolean}
*/
has : function ( listener, listenerContext ) {
listenerContext = listenerContext || this.defaultContext || this.host;
return this.remove( listener, listenerContext );
},
/**
* Strings!
*/
toString : function () {
return format( "{0}\nname:{1}\nlisteners:{2}",
this.declaredClass,
this.name,
this.getNumListeners()
);
}
} );
/**
* @classDesc Make an object capable of handling a signal. Or many signals.
* @exports mixins/signalable
* @mixin
* @extends base
*/
var Signalable = Base.compose( [Base], /** @lends mixins/signalable# */{
declaredClass : "mixins/Signalable",
constructor : function () {
this.autoLoadSignals = this.autoLoadSignals || true;
if ( this.autoLoadSignals === true ) {
this._loadSignals();
}
},
/**
* When you make a change to the signals hash after loading, then you can make it reload
*/
refreshSignals : function () {
this._loadSignals();
},
/**
* Interprets the `signals` hash and instantiates it
* @private
*/
_loadSignals : function () {
var signals = this.signals || {};
sys.each( signals, function ( value, key ) {
var opts = {};
if ( !sys.isEmpty( value ) ) {
if ( sys.isBoolean( value.memorize ) ) {
opts.memorize = value.memorize;
}
if ( sys.isBoolean( value.params ) ) {
opts.params = value.params;
}
if ( !sys.isEmpty( value.context ) ) {
opts.context = value.context;
}
}
this._addSignal( key, opts );
} );
},
/**
* Creates a single signal
* @param {string} name The name of the signal
* @param {module:mixins/signalable~SignalOptions} options The options the signal expects
* @private
*/
_addSignal : function ( name, options ) {
if ( sys.isEmpty( this[name] ) ) {
this[name] = new Signal( this, name, options );
}
},
/**
* Add a signal to an object. If any members of the hash already exist in `this.signals`, they will be overwritten.
* @param {module:mixins/signalable.SignalOptions} signals
* @private
*/
_addSignals : function ( signals ) {
signals = signals || {};
if ( this.options ) {signals = sys.extend( {}, sys.result( this, 'signals' ), signals );}
this.signals = signals;
},
/**
* Clean up
* @private
*/
destroy : function () {
sys.each( sys.keys( this ), function ( key ) {
if ( this[key] instanceof Signal || this[key] instanceof signals.Signal ) {
this[key].close();
}
}, this );
}
} );
module.exports = Signalable;
alable.Signal = Signal;
Signalable.mixin = Base.mixin;
/**
* When true, the class will load the `signals` hash and create the signal definitions during construction
* @memberOf mixins/signalable#
* @name autoLoadSignals
* @type boolean
*/
/**
* A hash of signals to create automatically. Each definition consists of a name for the signal as the key
* and then a hash of options (nullable) for each signal
* @type {hash|function():hash}
* @memberOf mixins/signalable#
* @name signals
* @type module:mixins/signalable.SignalOptions
*/

View File

@ -0,0 +1,32 @@
"use strict";
/**
* @fileOverview String helper methods
*
* @module strings/format
*/
/**
* Format a string quickly and easily using .net style format strings
* @param {string} format A string format like "Hello {0}, now take off your {1}!"
* @param {...?} args One argument per `{}` in the string, positionally replaced
* @returns {string}
*
* @example
* var strings = require("papyrus/strings");
* var s = strings.format("Hello {0}", "Madame Vastra");
* // s = "Hello Madame Vastra"
*
* @example {@lang xml}
* <span>
* <%= strings.format("Hello {0}", "Madame Vastra") %>
* </span>
*/
module.exports = function ( format ) {
var args = Array.prototype.slice.call( arguments, 1 );
return format.replace( /{(\d+)}/g, function ( match, number ) {
return typeof args[number] != 'undefined'
? args[number]
: match
;
} );
};

View File

@ -0,0 +1,39 @@
{
"tags" : {
"allowUnknownTags" : true
},
"plugins" : ["plugins/markdown"],
"source" : {
"include" : [
"fixtures/",
"./README.md"
]
},
"templates" : {
"cleverLinks" : false,
"monospaceLinks" : false,
"dateFormat" : "ddd MMM Do YYYY",
"outputSourceFiles" : true,
"outputSourcePath" : true,
"systemName" : "Test Docs",
"footer" : "",
"copyright" : "DocStrap Copyright © 2012-2014 The contributors to the JSDoc3 and DocStrap projects.",
"navType" : "vertical",
"theme" : "cosmo",
"linenums" : true,
"collapseSymbols" : false,
"inverseNav" : true,
"highlightTutorialCode" : true
},
"markdown" : {
"parser" : "gfm",
"hardwrap" : true
},
"opts" : {
"private" : true,
"recurse": true,
"lenient" : true,
"destination" : "testdocs/",
"template" : "template/"
}
}

View File

@ -0,0 +1,21 @@
#Lorem ipsum dolor sit amet
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec viverra, tellus et fermentum tincidunt, massa ligula dignissim augue, ut aliquam tortor odio in odio. In faucibus metus metus. Curabitur est mi, fermentum lacinia tincidunt vitae, mattis sit amet neque. Quisque diam nisl, accumsan ac porta tincidunt, iaculis facilisis ipsum. Nulla facilisi. Aenean a metus tortor. Pellentesque congue, mauris vitae viverra varius, elit nunc dictum nisl, rhoncus ultrices nulla sapien at leo. Duis ultricies porttitor diam. Nulla facilisi. Nullam elementum, lorem eu imperdiet laoreet, est turpis sollicitudin velit, in porttitor justo dolor vel urna. Mauris in ante magna. Curabitur vitae lacus in magna mollis commodo.
Fusce lacinia, mauris ac aliquam consequat, lacus urna feugiat erat, id viverra mi mi sit amet tortor. Etiam ac ornare erat. Pellentesque et neque lacus, quis posuere orci. Fusce molestie blandit velit, sit amet dictum eros pharetra vitae. In erat urna, condimentum ac feugiat id, rutrum et nisi. Cras ac velit lorem. Nulla facilisi. Maecenas dignissim nulla in turpis tempus sed rhoncus augue dapibus. Nulla feugiat, urna non sagittis laoreet, dolor metus rhoncus justo, sed semper ante lacus eget quam. Sed ac ligula magna. Sed tincidunt pulvinar neque in porta. Nullam quis lacus orci. Pellentesque ornare viverra lacus, id aliquam magna venenatis a.
Sed id tristique lorem. Ut sodales turpis nec mauris gravida interdum. Cras pellentesque, purus at suscipit euismod, elit nunc cursus nisi, ut venenatis metus sapien id velit. Sed lectus orci, pharetra non pulvinar vel, ullamcorper id lorem. Donec vulputate tincidunt ipsum, ut lacinia tortor sollicitudin id. Nunc nec nibh ut felis venenatis egestas. Proin risus mauris, eleifend eget interdum in, venenatis sed velit. Praesent sodales elit ut odio viverra posuere. Donec sapien lorem, molestie in egestas eget, vulputate sed orci. Aenean elit sapien, pellentesque vitae tempor sit amet, sagittis et ligula. Mauris aliquam sapien sit amet lacus ultrices rutrum. Curabitur nec dolor sed elit varius dignissim a a lacus. Aliquam ac convallis enim.
Suspendisse orci massa, hendrerit sagittis lacinia consectetur, sagittis vitae purus. Aliquam id eros diam, eget elementum turpis. Nullam tellus magna, mollis in molestie id, venenatis rhoncus est. Proin id diam justo. Nunc tempus gravida justo at lobortis. Nam vitae venenatis nisi. Donec vel odio massa. Quisque interdum metus sit amet est iaculis tincidunt. Donec bibendum blandit purus, id semper orci aliquam quis. Nam tincidunt dolor eu felis ultricies tempor. Nulla non consectetur erat.
Nunc faucibus lacus eget odio ultricies nec ullamcorper risus pharetra. Nunc nec consequat urna. Curabitur condimentum ante vitae erat tristique vitae gravida quam dapibus. Cras ac justo dui, at faucibus urna. Nunc tristique, velit id feugiat fermentum, dolor enim egestas erat, at vestibulum ante ipsum vel orci. Duis quis ante id justo vehicula eleifend sed et urna. Sed sapien tortor, rutrum id ultrices eu, tincidunt tincidunt mi. Etiam blandit, neque eget interdum dignissim, lacus ante facilisis dolor, non viverra dui lorem vitae nibh. Morbi volutpat augue eget nulla luctus eu aliquam sem facilisis. Pellentesque sollicitudin commodo dolor sit amet vestibulum. Nam dictum posuere quam, in tincidunt erat rutrum eu.
Etiam nec turpis purus, at lacinia sem. In commodo lacinia euismod. Curabitur tincidunt congue leo, eget iaculis orci volutpat pharetra. Fusce dignissim lacus lacus. Integer consectetur lacus rutrum risus malesuada at consectetur erat rutrum. Sed magna ipsum, fringilla eget auctor non, fringilla nec massa. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Vestibulum nec tortor id nisi luctus aliquam. Maecenas cursus tincidunt ornare. Nulla a vestibulum odio. Mauris malesuada commodo justo quis mattis. Suspendisse mauris ligula, placerat at egestas in, tincidunt quis nibh. Aliquam ullamcorper elit at augue cursus quis pellentesque purus viverra.
Nulla ultricies justo ac nisi consectetur posuere. Donec ornare pharetra erat, nec facilisis dui cursus quis. Quisque porttitor porttitor orci, sed facilisis urna facilisis sed. Sed tincidunt adipiscing turpis et hendrerit. Cras posuere orci ut mauris ullamcorper vitae laoreet nisi luctus. In rutrum tristique augue. Nam eleifend dignissim dui.
Donec viverra egestas tellus non viverra. Aenean est ante, egestas sed scelerisque quis, aliquet sed lacus. Praesent non mauris neque, et adipiscing ante. Vestibulum quis quam vitae ipsum aliquet blandit. Vivamus condimentum euismod orci, in tincidunt justo rutrum faucibus. Phasellus nec lorem arcu. Donec tortor dui, facilisis in rutrum sit amet, pulvinar vitae lacus. Nam sodales sem eu nunc scelerisque vitae ullamcorper dolor facilisis. Duis imperdiet nisi in magna tempor convallis. Fusce at metus augue. Quisque dictum tempus mauris, in mattis ligula dignissim ut.
Proin sodales, mi at tincidunt ornare, mi dui sagittis velit, sed dictum risus orci eu erat. Sed nunc leo, congue sed rutrum eget, lobortis ac lectus. Etiam non arcu nulla. Vestibulum rutrum dolor pulvinar lorem posuere blandit. Sed quis sapien dui. Nunc sagittis erat commodo quam porta cursus in non erat. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Proin a molestie neque. Aliquam iaculis lacus sed neque hendrerit at dignissim ligula imperdiet. Suspendisse venenatis, lorem at luctus scelerisque, sem purus pellentesque sapien, vitae ornare ipsum quam nec dui. Mauris neque est, interdum nec pulvinar eget, dapibus eleifend tellus. Fusce non lorem tortor. Nullam eget nunc quis felis aliquam consectetur. Aliquam tristique, turpis in feugiat blandit, lectus erat condimentum tortor, non egestas nisl sapien eget nibh.
Aliquam elit turpis, faucibus et porta et, egestas nec nibh. Sed nisl est, pharetra a eleifend a, pretium ac eros. Sed leo eros, pulvinar vel faucibus dictum, aliquet ut quam. Maecenas et felis non ligula fringilla pretium fringilla sit amet ante. Nam varius imperdiet interdum. Ut non metus mauris, vel volutpat lorem. Nullam sagittis est quis lacus feugiat fringilla. Quisque orci lorem, semper ac accumsan vitae, blandit quis velit. Proin luctus sodales ultrices. Fusce mauris erat, facilisis ut consectetur at, fringilla feugiat orci. Aliquam a nisi a neque interdum suscipit id eget purus. Pellentesque tincidunt justo ut urna posuere non molestie quam auctor.

View File

@ -0,0 +1,10 @@
#Lorem ipsum dolor sit amet
Curabitur est mi, fermentum lacinia tincidunt vitae, mattis sit amet neque. Quisque diam nisl, accumsan ac porta tincidunt, iaculis facilisis ipsum. Nulla facilisi. Aenean a metus tortor. Pellentesque congue, mauris vitae viverra varius, elit nunc dictum nisl, rhoncus ultrices nulla sapien at leo. Duis ultricies porttitor diam. Nulla facilisi. Nullam elementum, lorem eu imperdiet laoreet, est turpis sollicitudin velit, in porttitor justo dolor vel urna. Mauris in ante magna. Curabitur vitae lacus in magna mollis commodo.
##Fusce lacinia, mauris ac aliquam consequat
Fusce molestie blandit velit, sit amet dictum eros pharetra vitae. In erat urna, condimentum ac feugiat id, rutrum et nisi. Cras ac velit lorem. Nulla facilisi. Maecenas dignissim nulla in turpis tempus sed rhoncus augue dapibus. Nulla feugiat, urna non sagittis laoreet, dolor metus rhoncus justo, sed semper ante lacus eget quam. Sed ac ligula magna. Sed tincidunt pulvinar neque in porta. Nullam quis lacus orci. Pellentesque ornare viverra lacus, id aliquam magna venenatis a.
Sed id tristique lorem. Ut sodales turpis nec mauris gravida interdum. Cras pellentesque, purus at suscipit euismod, elit nunc cursus nisi, ut venenatis metus sapien id velit. Sed lectus orci, pharetra non pulvinar vel, ullamcorper id lorem. Donec vulputate tincidunt ipsum, ut lacinia tortor sollicitudin id. Nunc nec nibh ut felis venenatis egestas. Proin risus mauris, eleifend eget interdum in, venenatis sed velit. Praesent sodales elit ut odio viverra posuere. Donec sapien lorem, molestie in egestas eget, vulputate sed orci. Aenean elit sapien, pellentesque vitae tempor sit amet, sagittis et ligula. Mauris aliquam sapien sit amet lacus ultrices rutrum. Curabitur nec dolor sed elit varius dignissim a a lacus. Aliquam ac convallis enim.
Suspendisse orci massa, hendrerit sagittis lacinia consectetur, sagittis vitae purus. Aliquam id eros diam, eget elementum turpis. Nullam tellus magna, mollis in molestie id, venenatis rhoncus est. Proin id diam justo. Nunc tempus gravida justo at lobortis. Nam vitae venenatis nisi. Donec vel odio massa. Quisque interdum metus sit amet est iaculis tincidunt. Donec bibendum blandit purus, id semper orci aliquam quis. Nam tincidunt dolor eu felis ultricies tempor. Nulla non consectetur erat.

View File

@ -0,0 +1,31 @@
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur non libero tristique, interdum quam in, fermentum massa. Aenean vestibulum velit eu massa faucibus accumsan. Aenean tempus quam ornare ligula gravida adipiscing. Suspendisse vestibulum diam quis quam lacinia convallis. Nunc rhoncus a elit ut dictum. Maecenas porta mi et risus convallis commodo. In hac habitasse platea dictumst. Morbi placerat sem nec eleifend hendrerit. Donec hendrerit pulvinar tristique. Pellentesque at nunc blandit, fringilla elit nec, dignissim arcu. Quisque sit amet enim urna. Nunc adipiscing lacinia justo. Pellentesque euismod nisi id elit auctor porttitor. Phasellus rutrum viverra felis, ac cursus ante vulputate ut. Donec laoreet felis ac risus vulputate sodales.
Mauris sit amet risus non ligula lacinia iaculis. Sed ornare tellus velit, vel elementum quam porttitor tempus. Duis vestibulum augue eu diam malesuada auctor. Maecenas dignissim odio ut elit fermentum, id mollis leo mattis. Phasellus posuere augue sed interdum vestibulum. Etiam ac pharetra est. Integer tortor ligula, pharetra ac nisi nec, faucibus laoreet dolor. Nunc vehicula, enim et cursus tincidunt, nulla purus mollis urna, vel ultricies nisl mi a risus. Vestibulum sed urna sodales, pretium nisi sed, pretium sapien. Vivamus et massa tincidunt, semper nibh nec, eleifend urna. Integer auctor, eros at pharetra blandit, erat nibh mattis turpis, rhoncus elementum nisi mi vitae purus.
Quisque elementum sapien id neque volutpat cursus non mattis velit.
```
$mod : function ( qu, value ) {
var operands = sys.flatten( qu.operands );
if ( operands.length !== 2 ) {
throw new Error( "$mod requires two operands" );
}
var mod = operands[0];
var rem = operands[1];
return value % mod === rem;
},
```
```
{@lang bash}
#!/bin/bash
echo Please, enter your firstname and lastname
read FN LN
echo "Hi! $LN, $FN !"
```

View File

@ -0,0 +1,89 @@
"use strict";
/**
* @fileOverview The logging system for papyrus is based on [http://pimterry.github.io/loglevel/](loglevel) and slightly decorated
* @module utils/logger
* @requires dcl
* @requires loglevel
*/
var dcl = require( "dcl" );
var log = require( 'loglevel' );
/**
* A logger class that you can mix into your classes to handle logging settings and state at an object level.
* See {@link utils/logger} for the members of this class
*
* @exports utils/logger.Logger
* @class
* @see utils/logger
*/
var Logger = dcl( null, /** @lends utils/logger.Logger# */{
declaredClass : "utils/Logger",
/**
* Turn off all logging. If you log something, it will not error, but will not do anything either
* and the cycles are minimal.
*
*/
silent : function () {
log.disableAll();
},
/**
* Turns on all logging levels
*
*/
all : function () {
log.enableAll();
},
/**
* Sets the logging level to one of `trace`, `debug`, `info`, `warn`, `error`.
* @param {string} lvl The level to set it to. Can be one of `trace`, `debug`, `info`, `warn`, `error`.
*
*/
level : function ( lvl ) {
if ( lvl.toLowerCase() === "none" ) {
log.disableAll();
} else {
log.setLevel( lvl );
}
},
/**
* Log a `trace` call
* @method
* @param {string} The value to log
*/
trace : log.trace,
/**
* Log a `debug` call
* @method
* @param {string} The value to log
*/
debug : log.debug,
/**
* Log a `info` call
* @method
* @param {string} The value to log
*/
info : log.info,
/**
* Log a `warn` call
* @method
* @param {string} The value to log
*/
warn : log.warn,
/**
* Log a `error` call
* @method
* @param {string} The value to log
*/
error : log.error
} );
module.exports = new Logger();
/**
* The system global, cross-platform logger
* @name utils/logger
* @static
* @type {utils/logger.Logger}
*/
module.exports.Logger = Logger;

View File

@ -0,0 +1 @@
test

View File

@ -0,0 +1,4 @@
{
"SAUCE_USERNAME": "moment",
"SAUCE_ACCESS_KEY": "f28fe67a-27c4-4b87-acf7-699d24ea0cc8"
}

View File

@ -0,0 +1,13 @@
language: node_js
node_js:
- 0.10
env:
global:
- secure: "M4STT2TOZxjzv3cZOgSVi0J4j6enrGjgE+p5YTNUw+S6Dg6FS5pTIPeafu1kGhfm7F0uk7xPVwGKYb+3uWNO9IhkKXz8jySMMQ2iKISHwECGNNuFNjSMD1vIjbIkLwV8TyPO/PurQg2s+WtYz+DoAZsDFKpdaRUtif64OjdQ3vQ="
- secure: "V+i7kHoGe7VXWGplPNqJz+aDtgDF9Dh9/guoaf2BPyXLvkFW6VgMjJyoNUW7JVsakrWzAz2ubb734vAPDt7BCcFQ2BqfatOmabdFogviCaXC6IqVaEkYS2eSP7MIUPIeWJgnTrDGzkFMDk4K7y5SiVJ8UmYwZxe+tJV7kbb0Yig="
before_script:
- npm install -g grunt-cli
script: grunt build:travis

View File

@ -0,0 +1,2 @@
set sts=4
set sw=4

View File

@ -0,0 +1,46 @@
All pull requests to the `master` branch will be closed.
========================================================
Please submit all pull requests to the `develop` branch.
Language translations will not be merged without unit tests.
============================================================
See [the British english unit tests](https://github.com/moment/moment/blob/develop/test/lang/en-gb.js) for an example.
Submitting Issues
=================
If you are submitting a bug, please create a [jsfiddle](http://jsfiddle.net/) demonstrating the issue.
Contributing
============
To contribute, fork the library and install grunt and dependencies.
npm install -g grunt-cli
npm install
You can add tests to the files in `/test/moment` or add a new test file if you are adding a new feature.
To run the tests, do `grunt` to run all tests.
To check the filesize, you can use `grunt size`.
To minify all the files, use `grunt release`.
If your code passes the unit tests (including the ones you wrote), submit a pull request.
Submitting pull requests
========================
Moment.js now uses [git-flow](https://github.com/nvie/gitflow). If you're not familiar with git-flow, please read up on it, you'll be glad you did.
When submitting new features, please create a new feature branch using `git flow feature start <name>` and submit the pull request to the `develop` branch.
Pull requests for enhancements for features should be submitted to the `develop` branch as well.
When submitting a bugfix, please check if there is an existing bugfix branch. If the latest stable version is `1.5.0`, the bugfix branch would be `hotfix/1.5.1`. All pull requests for bug fixes should be on a `hotfix` branch, unless the bug fix depends on a new feature.
The `master` branch should always have the latest stable version. When bugfix or minor releases are needed, the develop/hotfix branch will be merged into master and released.

View File

@ -0,0 +1,211 @@
module.exports = function (grunt) {
var embedOption = grunt.option('embedLanguages'),
embedLanguageDest = embedOption ?
'min/moment-with-customlangs.js' :
'min/moment-with-langs.js',
embedLanguageLangs = 'lang/*.js';
if (embedOption && embedOption.match(/,/)) {
embedLanguageLangs = 'lang/{' + embedOption + '}.js';
}
else if (embedOption) {
embedLanguageLangs = 'lang/' + embedOption + '.js';
}
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
concat : {
langs: {
src: 'lang/*.js',
dest: 'min/langs.js'
},
tests: {
src: [
'test/browser-prefix.js',
'test/moment/*.js',
'test/lang/*.js',
'test/browser-suffix.js'
],
dest: 'min/tests.js'
}
},
env : {
sauceLabs : (grunt.file.exists('.sauce-labs.creds') ?
grunt.file.readJSON('.sauce-labs.creds') : {})
},
karma : {
options: {
frameworks: ['nodeunit'],
files: [
'min/moment-with-langs.js',
'min/tests.js',
'test/browser.js'
],
sauceLabs: {
startConnect: true,
testName: 'MomentJS'
},
customLaunchers: {
slChromeWinXp: {
base: 'SauceLabs',
browserName: 'chrome',
platform: 'Windows XP'
},
slIe9Win7: {
base: 'SauceLabs',
browserName: 'internet explorer',
platform: 'Windows 7',
version: '9'
},
slIe8Win7: {
base: 'SauceLabs',
browserName: 'internet explorer',
platform: 'Windows 7',
version: '8'
},
slFfLinux: {
base: 'SauceLabs',
browserName: 'firefox',
platform: 'Linux'
},
slSafariOsx: {
base: 'SauceLabs',
browserName: 'safari',
platform: 'OS X 10.8'
}
}
},
server: {
browsers: []
},
chrome: {
singleRun: true,
browsers: ['Chrome']
},
firefox: {
singleRun: true,
browsers: ['Firefox']
},
sauce: {
options: {reporters: ['dots']},
singleRun: true,
browsers: [
'slChromeWinXp',
'slIe9Win7',
'slIe8Win7',
'slFfLinux',
'slSafariOsx'
]
}
},
uglify : {
target: {
files: {
'min/moment-with-langs.min.js' : 'min/moment-with-langs.js',
'min/moment-with-customlangs.min.js' : 'min/moment-with-customlangs.js',
'min/langs.min.js' : 'min/langs.js',
'min/moment.min.js' : 'moment.js'
}
},
options: {
mangle: true,
compress: {
dead_code: false // jshint ignore:line
},
output: {
ascii_only: true // jshint ignore:line
},
report: 'min',
preserveComments: 'some'
}
},
nodeunit : {
all : ["test/moment/**/*.js", "test/lang/**/*.js"]
},
jshint: {
all: [
"Gruntfile.js", "moment.js", "lang/**/*.js", "test/**/*.js",
"!test/browser*.js"
],
options: {
"node" : true,
"browser" : true,
"boss" : false,
"curly" : true,
"debug" : false,
"devel" : false,
"eqeqeq" : true,
"eqnull" : true,
"evil" : false,
"forin" : false,
"immed" : false,
"laxbreak" : false,
"newcap" : true,
"noarg" : true,
"noempty" : false,
"nonew" : false,
"onevar" : true,
"plusplus" : false,
"regexp" : false,
"undef" : true,
"sub" : true,
"strict" : false,
"white" : true,
"es3" : true,
"camelcase" : true,
"globals": {
"define": false
}
}
},
watch : {
test : {
files : [
'moment.js',
'lang/*.js',
'test/**/*.js'
],
tasks: ['nodeunit']
},
jshint : {
files : '<%= jshint.all %>',
tasks: ['jshint']
}
},
embedLanguages: {
moment: 'moment.js',
dest: embedLanguageDest,
targetLangs: embedLanguageLangs
}
});
grunt.loadTasks("tasks");
// These plugins provide necessary tasks.
require('load-grunt-tasks')(grunt);
// Default task.
grunt.registerTask('default', ['jshint', 'nodeunit']);
//test tasks
grunt.registerTask('test', ['test:node', 'test:browser']);
grunt.registerTask('test:node', ['nodeunit']);
grunt.registerTask('test:server', ['concat', 'embedLanguages', 'karma:server']);
grunt.registerTask('test:browser', ['concat', 'embedLanguages', 'karma:chrome', 'karma:firefox']);
grunt.registerTask('test:sauce-browser', ['concat', 'embedLanguages', 'env:sauceLabs', 'karma:sauce']);
grunt.registerTask('test:travis-sauce-browser', ['concat', 'embedLanguages', 'karma:sauce']);
// travis build task
grunt.registerTask('build:travis', [
'jshint', 'test:node', 'check-sauce-creds',
'test:travis-sauce-browser'
]);
// Task to be run when releasing a new version
grunt.registerTask('release', [
'jshint', 'nodeunit', 'concat', 'embedLanguages',
'component', 'uglify'
]);
};

View File

@ -0,0 +1,22 @@
Copyright (c) 2011-2014 Tim Wood, Iskren Chernev, Moment.js contributors
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

View File

@ -0,0 +1,20 @@
{
"name": "moment",
"version": "2.6.0",
"main": "moment.js",
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"test",
"tests",
"tasks",
"component.json",
"composer.json",
"CONTRIBUTING.md",
"ender.js",
"Gruntfile.js",
"package.js",
"package.json"
]
}

View File

@ -0,0 +1,82 @@
{
"name": "moment",
"version": "2.5.1",
"main": "moment.js",
"description": "Parse, validate, manipulate, and display dates in javascript.",
"files": [
"moment.js",
"lang/ar-ma.js",
"lang/ar.js",
"lang/bg.js",
"lang/br.js",
"lang/bs.js",
"lang/ca.js",
"lang/cs.js",
"lang/cv.js",
"lang/cy.js",
"lang/da.js",
"lang/de.js",
"lang/el.js",
"lang/en-au.js",
"lang/en-ca.js",
"lang/en-gb.js",
"lang/eo.js",
"lang/es.js",
"lang/et.js",
"lang/eu.js",
"lang/fa.js",
"lang/fi.js",
"lang/fo.js",
"lang/fr-ca.js",
"lang/fr.js",
"lang/gl.js",
"lang/he.js",
"lang/hi.js",
"lang/hr.js",
"lang/hu.js",
"lang/hy-am.js",
"lang/id.js",
"lang/is.js",
"lang/it.js",
"lang/ja.js",
"lang/ka.js",
"lang/km.js",
"lang/ko.js",
"lang/lb.js",
"lang/lt.js",
"lang/lv.js",
"lang/mk.js",
"lang/ml.js",
"lang/mr.js",
"lang/ms-my.js",
"lang/nb.js",
"lang/ne.js",
"lang/nl.js",
"lang/nn.js",
"lang/pl.js",
"lang/pt-br.js",
"lang/pt.js",
"lang/ro.js",
"lang/ru.js",
"lang/sk.js",
"lang/sl.js",
"lang/sq.js",
"lang/sr-cyr.js",
"lang/sr.js",
"lang/sv.js",
"lang/ta.js",
"lang/th.js",
"lang/tl-ph.js",
"lang/tr.js",
"lang/tzm-la.js",
"lang/tzm.js",
"lang/uk.js",
"lang/uz.js",
"lang/vi.js",
"lang/zh-cn.js",
"lang/zh-tw.js"
],
"scripts": [
"moment.js"
]
}

View File

@ -0,0 +1,33 @@
{
"name": "moment/moment",
"description": "Parse, validate, manipulate, and display dates in javascript.",
"keywords": [
"moment",
"date",
"time",
"parse",
"format",
"validate",
"i18n",
"l10n",
"ender"
],
"homepage": "http://github.com/moment/moment/",
"authors": [{"name": "Tim Wood", "email": "washwithcare@gmail.com"}],
"license": "MIT",
"type": "component",
"require": {
"robloach/component-installer": "*"
},
"extra": {
"component": {
"scripts": [
"moment.js"
],
"files": [
"min/*.js",
"lang/*.js"
]
}
}
}

View File

@ -0,0 +1 @@
$.ender({ moment: require('moment') })

View File

@ -0,0 +1,16 @@
moment = require './moment'
year = parseInt(process.argv[2], 10)
m = moment([year, 0, 1])
w = m.weekday()
if w < 4
m.add(4 - w, 'days')
else
m.add(11 - w, 'days')
m.add(371, 'days')
while m.year() > year
m.subtract(1, 'week')
console.log m.isoWeek()

View File

@ -0,0 +1,3 @@
moment = require './moment'
console.log moment("7 Jan 1234")
# console.log moment.utc("+020123-10-09T20:30:40.678").year()

View File

@ -0,0 +1,56 @@
// moment.js language configuration
// language : Moroccan Arabic (ar-ma)
// author : ElFadili Yassine : https://github.com/ElFadiliY
// author : Abdel Said : https://github.com/abdelsaid
(function (factory) {
if (typeof define === 'function' && define.amd) {
define(['moment'], factory); // AMD
} else if (typeof exports === 'object') {
module.exports = factory(require('../moment')); // Node
} else {
factory(window.moment); // Browser global
}
}(function (moment) {
return moment.lang('ar-ma', {
months : "يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر".split("_"),
monthsShort : "يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر".split("_"),
weekdays : "الأحد_الإتنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت".split("_"),
weekdaysShort : "احد_اتنين_ثلاثاء_اربعاء_خميس_جمعة_سبت".split("_"),
weekdaysMin : "ح_ن_ث_ر_خ_ج_س".split("_"),
longDateFormat : {
LT : "HH:mm",
L : "DD/MM/YYYY",
LL : "D MMMM YYYY",
LLL : "D MMMM YYYY LT",
LLLL : "dddd D MMMM YYYY LT"
},
calendar : {
sameDay: "[اليوم على الساعة] LT",
nextDay: '[غدا على الساعة] LT',
nextWeek: 'dddd [على الساعة] LT',
lastDay: '[أمس على الساعة] LT',
lastWeek: 'dddd [على الساعة] LT',
sameElse: 'L'
},
relativeTime : {
future : "في %s",
past : "منذ %s",
s : "ثوان",
m : "دقيقة",
mm : "%d دقائق",
h : "ساعة",
hh : "%d ساعات",
d : "يوم",
dd : "%d أيام",
M : "شهر",
MM : "%d أشهر",
y : "سنة",
yy : "%d سنوات"
},
week : {
dow : 6, // Saturday is the first day of the week.
doy : 12 // The week that contains Jan 1st is the first week of the year.
}
});
}));

View File

@ -0,0 +1,56 @@
// moment.js language configuration
// language : Arabic (ar)
// author : Abdel Said : https://github.com/abdelsaid
// changes in months, weekdays : Ahmed Elkhatib
(function (factory) {
if (typeof define === 'function' && define.amd) {
define(['moment'], factory); // AMD
} else if (typeof exports === 'object') {
module.exports = factory(require('../moment')); // Node
} else {
factory(window.moment); // Browser global
}
}(function (moment) {
return moment.lang('ar', {
months : "يناير/ كانون الثاني_فبراير/ شباط_مارس/ آذار_أبريل/ نيسان_مايو/ أيار_يونيو/ حزيران_يوليو/ تموز_أغسطس/ آب_سبتمبر/ أيلول_أكتوبر/ تشرين الأول_نوفمبر/ تشرين الثاني_ديسمبر/ كانون الأول".split("_"),
monthsShort : "يناير/ كانون الثاني_فبراير/ شباط_مارس/ آذار_أبريل/ نيسان_مايو/ أيار_يونيو/ حزيران_يوليو/ تموز_أغسطس/ آب_سبتمبر/ أيلول_أكتوبر/ تشرين الأول_نوفمبر/ تشرين الثاني_ديسمبر/ كانون الأول".split("_"),
weekdays : "الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت".split("_"),
weekdaysShort : "الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت".split("_"),
weekdaysMin : "ح_ن_ث_ر_خ_ج_س".split("_"),
longDateFormat : {
LT : "HH:mm",
L : "DD/MM/YYYY",
LL : "D MMMM YYYY",
LLL : "D MMMM YYYY LT",
LLLL : "dddd D MMMM YYYY LT"
},
calendar : {
sameDay: "[اليوم على الساعة] LT",
nextDay: '[غدا على الساعة] LT',
nextWeek: 'dddd [على الساعة] LT',
lastDay: '[أمس على الساعة] LT',
lastWeek: 'dddd [على الساعة] LT',
sameElse: 'L'
},
relativeTime : {
future : "في %s",
past : "منذ %s",
s : "ثوان",
m : "دقيقة",
mm : "%d دقائق",
h : "ساعة",
hh : "%d ساعات",
d : "يوم",
dd : "%d أيام",
M : "شهر",
MM : "%d أشهر",
y : "سنة",
yy : "%d سنوات"
},
week : {
dow : 6, // Saturday is the first day of the week.
doy : 12 // The week that contains Jan 1st is the first week of the year.
}
});
}));

View File

@ -0,0 +1,86 @@
// moment.js language configuration
// language : bulgarian (bg)
// author : Krasen Borisov : https://github.com/kraz
(function (factory) {
if (typeof define === 'function' && define.amd) {
define(['moment'], factory); // AMD
} else if (typeof exports === 'object') {
module.exports = factory(require('../moment')); // Node
} else {
factory(window.moment); // Browser global
}
}(function (moment) {
return moment.lang('bg', {
months : "януари_февруари_март_април_май_юни_юли_август_септември_октомври_ноември_декември".split("_"),
monthsShort : "янрев_мар_апрай_юни_юли_авг_сеп_окт_ноеек".split("_"),
weekdays : еделя_понеделник_вторник_срядаетвъртък_петък_събота".split("_"),
weekdaysShort : ед_пон_вто_сря_чет_пет_съб".split("_"),
weekdaysMin : "нд_пн_вт_ср_чт_пт_сб".split("_"),
longDateFormat : {
LT : "H:mm",
L : "D.MM.YYYY",
LL : "D MMMM YYYY",
LLL : "D MMMM YYYY LT",
LLLL : "dddd, D MMMM YYYY LT"
},
calendar : {
sameDay : '[Днес в] LT',
nextDay : '[Утре в] LT',
nextWeek : 'dddd [в] LT',
lastDay : '[Вчера в] LT',
lastWeek : function () {
switch (this.day()) {
case 0:
case 3:
case 6:
return '[В изминалата] dddd [в] LT';
case 1:
case 2:
case 4:
case 5:
return '[В изминалия] dddd [в] LT';
}
},
sameElse : 'L'
},
relativeTime : {
future : "след %s",
past : "преди %s",
s : "няколко секунди",
m : "минута",
mm : "%d минути",
h : "час",
hh : "%d часа",
d : "ден",
dd : "%d дни",
M : "месец",
MM : "%d месеца",
y : "година",
yy : "%d години"
},
ordinal : function (number) {
var lastDigit = number % 10,
last2Digits = number % 100;
if (number === 0) {
return number + '-ев';
} else if (last2Digits === 0) {
return number + '-ен';
} else if (last2Digits > 10 && last2Digits < 20) {
return number + '-ти';
} else if (lastDigit === 1) {
return number + '-ви';
} else if (lastDigit === 2) {
return number + '-ри';
} else if (lastDigit === 7 || lastDigit === 8) {
return number + '-ми';
} else {
return number + '-ти';
}
},
week : {
dow : 1, // Monday is the first day of the week.
doy : 7 // The week that contains Jan 1st is the first week of the year.
}
});
}));

View File

@ -0,0 +1,107 @@
// moment.js language configuration
// language : breton (br)
// author : Jean-Baptiste Le Duigou : https://github.com/jbleduigou
(function (factory) {
if (typeof define === 'function' && define.amd) {
define(['moment'], factory); // AMD
} else if (typeof exports === 'object') {
module.exports = factory(require('../moment')); // Node
} else {
factory(window.moment); // Browser global
}
}(function (moment) {
function relativeTimeWithMutation(number, withoutSuffix, key) {
var format = {
'mm': "munutenn",
'MM': "miz",
'dd': "devezh"
};
return number + ' ' + mutation(format[key], number);
}
function specialMutationForYears(number) {
switch (lastNumber(number)) {
case 1:
case 3:
case 4:
case 5:
case 9:
return number + ' bloaz';
default:
return number + ' vloaz';
}
}
function lastNumber(number) {
if (number > 9) {
return lastNumber(number % 10);
}
return number;
}
function mutation(text, number) {
if (number === 2) {
return softMutation(text);
}
return text;
}
function softMutation(text) {
var mutationTable = {
'm': 'v',
'b': 'v',
'd': 'z'
};
if (mutationTable[text.charAt(0)] === undefined) {
return text;
}
return mutationTable[text.charAt(0)] + text.substring(1);
}
return moment.lang('br', {
months : "Genver_C'hwevrer_Meurzh_Ebrel_Mae_Mezheven_Gouere_Eost_Gwengolo_Here_Du_Kerzu".split("_"),
monthsShort : "Gen_C'hwe_Meu_Ebr_Mae_Eve_Gou_Eos_Gwe_Her_Du_Ker".split("_"),
weekdays : "Sul_Lun_Meurzh_Merc'her_Yaou_Gwener_Sadorn".split("_"),
weekdaysShort : "Sul_Lun_Meu_Mer_Yao_Gwe_Sad".split("_"),
weekdaysMin : "Su_Lu_Me_Mer_Ya_Gw_Sa".split("_"),
longDateFormat : {
LT : "h[e]mm A",
L : "DD/MM/YYYY",
LL : "D [a viz] MMMM YYYY",
LLL : "D [a viz] MMMM YYYY LT",
LLLL : "dddd, D [a viz] MMMM YYYY LT"
},
calendar : {
sameDay : '[Hiziv da] LT',
nextDay : '[Warc\'hoazh da] LT',
nextWeek : 'dddd [da] LT',
lastDay : '[Dec\'h da] LT',
lastWeek : 'dddd [paset da] LT',
sameElse : 'L'
},
relativeTime : {
future : "a-benn %s",
past : "%s 'zo",
s : "un nebeud segondennoù",
m : "ur vunutenn",
mm : relativeTimeWithMutation,
h : "un eur",
hh : "%d eur",
d : "un devezh",
dd : relativeTimeWithMutation,
M : "ur miz",
MM : relativeTimeWithMutation,
y : "ur bloaz",
yy : specialMutationForYears
},
ordinal : function (number) {
var output = (number === 1) ? 'añ' : 'vet';
return number + output;
},
week : {
dow : 1, // Monday is the first day of the week.
doy : 4 // The week that contains Jan 4th is the first week of the year.
}
});
}));

View File

@ -0,0 +1,139 @@
// moment.js language configuration
// language : bosnian (bs)
// author : Nedim Cholich : https://github.com/frontyard
// based on (hr) translation by Bojan Marković
(function (factory) {
if (typeof define === 'function' && define.amd) {
define(['moment'], factory); // AMD
} else if (typeof exports === 'object') {
module.exports = factory(require('../moment')); // Node
} else {
factory(window.moment); // Browser global
}
}(function (moment) {
function translate(number, withoutSuffix, key) {
var result = number + " ";
switch (key) {
case 'm':
return withoutSuffix ? 'jedna minuta' : 'jedne minute';
case 'mm':
if (number === 1) {
result += 'minuta';
} else if (number === 2 || number === 3 || number === 4) {
result += 'minute';
} else {
result += 'minuta';
}
return result;
case 'h':
return withoutSuffix ? 'jedan sat' : 'jednog sata';
case 'hh':
if (number === 1) {
result += 'sat';
} else if (number === 2 || number === 3 || number === 4) {
result += 'sata';
} else {
result += 'sati';
}
return result;
case 'dd':
if (number === 1) {
result += 'dan';
} else {
result += 'dana';
}
return result;
case 'MM':
if (number === 1) {
result += 'mjesec';
} else if (number === 2 || number === 3 || number === 4) {
result += 'mjeseca';
} else {
result += 'mjeseci';
}
return result;
case 'yy':
if (number === 1) {
result += 'godina';
} else if (number === 2 || number === 3 || number === 4) {
result += 'godine';
} else {
result += 'godina';
}
return result;
}
}
return moment.lang('bs', {
months : "januar_februar_mart_april_maj_juni_juli_avgust_septembar_oktobar_novembar_decembar".split("_"),
monthsShort : "jan._feb._mar._apr._maj._jun._jul._avg._sep._okt._nov._dec.".split("_"),
weekdays : "nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota".split("_"),
weekdaysShort : "ned._pon._uto._sri._čet._pet._sub.".split("_"),
weekdaysMin : "ne_po_ut_sr_če_pe_su".split("_"),
longDateFormat : {
LT : "H:mm",
L : "DD. MM. YYYY",
LL : "D. MMMM YYYY",
LLL : "D. MMMM YYYY LT",
LLLL : "dddd, D. MMMM YYYY LT"
},
calendar : {
sameDay : '[danas u] LT',
nextDay : '[sutra u] LT',
nextWeek : function () {
switch (this.day()) {
case 0:
return '[u] [nedjelju] [u] LT';
case 3:
return '[u] [srijedu] [u] LT';
case 6:
return '[u] [subotu] [u] LT';
case 1:
case 2:
case 4:
case 5:
return '[u] dddd [u] LT';
}
},
lastDay : '[jučer u] LT',
lastWeek : function () {
switch (this.day()) {
case 0:
case 3:
return '[prošlu] dddd [u] LT';
case 6:
return '[prošle] [subote] [u] LT';
case 1:
case 2:
case 4:
case 5:
return '[prošli] dddd [u] LT';
}
},
sameElse : 'L'
},
relativeTime : {
future : "za %s",
past : "prije %s",
s : "par sekundi",
m : translate,
mm : translate,
h : translate,
hh : translate,
d : "dan",
dd : translate,
M : "mjesec",
MM : translate,
y : "godinu",
yy : translate
},
ordinal : '%d.',
week : {
dow : 1, // Monday is the first day of the week.
doy : 7 // The week that contains Jan 1st is the first week of the year.
}
});
}));

View File

@ -0,0 +1,66 @@
// moment.js language configuration
// language : catalan (ca)
// author : Juan G. Hurtado : https://github.com/juanghurtado
(function (factory) {
if (typeof define === 'function' && define.amd) {
define(['moment'], factory); // AMD
} else if (typeof exports === 'object') {
module.exports = factory(require('../moment')); // Node
} else {
factory(window.moment); // Browser global
}
}(function (moment) {
return moment.lang('ca', {
months : "gener_febrer_març_abril_maig_juny_juliol_agost_setembre_octubre_novembre_desembre".split("_"),
monthsShort : "gen._febr._mar._abr._mai._jun._jul._ag._set._oct._nov._des.".split("_"),
weekdays : "diumenge_dilluns_dimarts_dimecres_dijous_divendres_dissabte".split("_"),
weekdaysShort : "dg._dl._dt._dc._dj._dv._ds.".split("_"),
weekdaysMin : "Dg_Dl_Dt_Dc_Dj_Dv_Ds".split("_"),
longDateFormat : {
LT : "H:mm",
L : "DD/MM/YYYY",
LL : "D MMMM YYYY",
LLL : "D MMMM YYYY LT",
LLLL : "dddd D MMMM YYYY LT"
},
calendar : {
sameDay : function () {
return '[avui a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT';
},
nextDay : function () {
return '[demà a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT';
},
nextWeek : function () {
return 'dddd [a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT';
},
lastDay : function () {
return '[ahir a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT';
},
lastWeek : function () {
return '[el] dddd [passat a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT';
},
sameElse : 'L'
},
relativeTime : {
future : "en %s",
past : "fa %s",
s : "uns segons",
m : "un minut",
mm : "%d minuts",
h : "una hora",
hh : "%d hores",
d : "un dia",
dd : "%d dies",
M : "un mes",
MM : "%d mesos",
y : "un any",
yy : "%d anys"
},
ordinal : '%dº',
week : {
dow : 1, // Monday is the first day of the week.
doy : 4 // The week that contains Jan 4th is the first week of the year.
}
});
}));

View File

@ -0,0 +1,155 @@
// moment.js language configuration
// language : czech (cs)
// author : petrbela : https://github.com/petrbela
(function (factory) {
if (typeof define === 'function' && define.amd) {
define(['moment'], factory); // AMD
} else if (typeof exports === 'object') {
module.exports = factory(require('../moment')); // Node
} else {
factory(window.moment); // Browser global
}
}(function (moment) {
var months = "leden_únor_březen_duben_květen_červen_červenec_srpen_září_říjen_listopad_prosinec".split("_"),
monthsShort = "led_úno_bře_dub_kvě_čvn_čvc_srp_zář_říj_lis_pro".split("_");
function plural(n) {
return (n > 1) && (n < 5) && (~~(n / 10) !== 1);
}
function translate(number, withoutSuffix, key, isFuture) {
var result = number + " ";
switch (key) {
case 's': // a few seconds / in a few seconds / a few seconds ago
return (withoutSuffix || isFuture) ? 'pár sekund' : 'pár sekundami';
case 'm': // a minute / in a minute / a minute ago
return withoutSuffix ? 'minuta' : (isFuture ? 'minutu' : 'minutou');
case 'mm': // 9 minutes / in 9 minutes / 9 minutes ago
if (withoutSuffix || isFuture) {
return result + (plural(number) ? 'minuty' : 'minut');
} else {
return result + 'minutami';
}
break;
case 'h': // an hour / in an hour / an hour ago
return withoutSuffix ? 'hodina' : (isFuture ? 'hodinu' : 'hodinou');
case 'hh': // 9 hours / in 9 hours / 9 hours ago
if (withoutSuffix || isFuture) {
return result + (plural(number) ? 'hodiny' : 'hodin');
} else {
return result + 'hodinami';
}
break;
case 'd': // a day / in a day / a day ago
return (withoutSuffix || isFuture) ? 'den' : 'dnem';
case 'dd': // 9 days / in 9 days / 9 days ago
if (withoutSuffix || isFuture) {
return result + (plural(number) ? 'dny' : 'dní');
} else {
return result + 'dny';
}
break;
case 'M': // a month / in a month / a month ago
return (withoutSuffix || isFuture) ? 'měsíc' : 'měsícem';
case 'MM': // 9 months / in 9 months / 9 months ago
if (withoutSuffix || isFuture) {
return result + (plural(number) ? 'měsíce' : 'měsíců');
} else {
return result + 'měsíci';
}
break;
case 'y': // a year / in a year / a year ago
return (withoutSuffix || isFuture) ? 'rok' : 'rokem';
case 'yy': // 9 years / in 9 years / 9 years ago
if (withoutSuffix || isFuture) {
return result + (plural(number) ? 'roky' : 'let');
} else {
return result + 'lety';
}
break;
}
}
return moment.lang('cs', {
months : months,
monthsShort : monthsShort,
monthsParse : (function (months, monthsShort) {
var i, _monthsParse = [];
for (i = 0; i < 12; i++) {
// use custom parser to solve problem with July (červenec)
_monthsParse[i] = new RegExp('^' + months[i] + '$|^' + monthsShort[i] + '$', 'i');
}
return _monthsParse;
}(months, monthsShort)),
weekdays : "neděle_pondělí_úterý_středa_čtvrtek_pátek_sobota".split("_"),
weekdaysShort : "ne_po_út_st_čt_pá_so".split("_"),
weekdaysMin : "ne_po_út_st_čt_pá_so".split("_"),
longDateFormat : {
LT: "H.mm",
L : "DD. MM. YYYY",
LL : "D. MMMM YYYY",
LLL : "D. MMMM YYYY LT",
LLLL : "dddd D. MMMM YYYY LT"
},
calendar : {
sameDay: "[dnes v] LT",
nextDay: '[zítra v] LT',
nextWeek: function () {
switch (this.day()) {
case 0:
return '[v neděli v] LT';
case 1:
case 2:
return '[v] dddd [v] LT';
case 3:
return '[ve středu v] LT';
case 4:
return '[ve čtvrtek v] LT';
case 5:
return '[v pátek v] LT';
case 6:
return '[v sobotu v] LT';
}
},
lastDay: '[včera v] LT',
lastWeek: function () {
switch (this.day()) {
case 0:
return '[minulou neděli v] LT';
case 1:
case 2:
return '[minulé] dddd [v] LT';
case 3:
return '[minulou středu v] LT';
case 4:
case 5:
return '[minulý] dddd [v] LT';
case 6:
return '[minulou sobotu v] LT';
}
},
sameElse: "L"
},
relativeTime : {
future : "za %s",
past : "před %s",
s : translate,
m : translate,
mm : translate,
h : translate,
hh : translate,
d : translate,
dd : translate,
M : translate,
MM : translate,
y : translate,
yy : translate
},
ordinal : '%d.',
week : {
dow : 1, // Monday is the first day of the week.
doy : 4 // The week that contains Jan 4th is the first week of the year.
}
});
}));

View File

@ -0,0 +1,59 @@
// moment.js language configuration
// language : chuvash (cv)
// author : Anatoly Mironov : https://github.com/mirontoli
(function (factory) {
if (typeof define === 'function' && define.amd) {
define(['moment'], factory); // AMD
} else if (typeof exports === 'object') {
module.exports = factory(require('../moment')); // Node
} else {
factory(window.moment); // Browser global
}
}(function (moment) {
return moment.lang('cv', {
months : "кăрлач_нарăс_пуш_акаай_çĕртме_утă_çурла_авăн_юпа_чӳк_раштав".split("_"),
monthsShort : "кăрар_пуш_акаай_çĕр_утă_çур_ав_юпа_чӳк_раш".split("_"),
weekdays : "вырсарникун_тунтикун_ытларикун_юнкун_кĕçнерникун_эрнекун_шăматкун".split("_"),
weekdaysShort : "вырун_ытл_юн_кĕç_эрн_шăм".split("_"),
weekdaysMin : р_тн_ыт_юн_кç_эр_шм".split("_"),
longDateFormat : {
LT : "HH:mm",
L : "DD-MM-YYYY",
LL : "YYYY [çулхи] MMMM [уйăхĕн] D[-мĕшĕ]",
LLL : "YYYY [çулхи] MMMM [уйăхĕн] D[-мĕшĕ], LT",
LLLL : "dddd, YYYY [çулхи] MMMM [уйăхĕн] D[-мĕшĕ], LT"
},
calendar : {
sameDay: '[Паян] LT [сехетре]',
nextDay: '[Ыран] LT [сехетре]',
lastDay: '[Ĕнер] LT [сехетре]',
nextWeek: '[Çитес] dddd LT [сехетре]',
lastWeek: '[Иртнĕ] dddd LT [сехетре]',
sameElse: 'L'
},
relativeTime : {
future : function (output) {
var affix = /сехет$/i.exec(output) ? "рен" : /çул$/i.exec(output) ? "тан" : "ран";
return output + affix;
},
past : "%s каялла",
s : "пĕр-ик çеккунт",
m : "пĕр минут",
mm : "%d минут",
h : "пĕр сехет",
hh : "%d сехет",
d : "пĕр кун",
dd : "%d кун",
M : "пĕр уйăх",
MM : "%d уйăх",
y : "пĕр çул",
yy : "%d çул"
},
ordinal : '%d-мĕш',
week : {
dow : 1, // Monday is the first day of the week.
doy : 7 // The week that contains Jan 1st is the first week of the year.
}
});
}));

View File

@ -0,0 +1,77 @@
// moment.js language configuration
// language : Welsh (cy)
// author : Robert Allen
(function (factory) {
if (typeof define === 'function' && define.amd) {
define(['moment'], factory); // AMD
} else if (typeof exports === 'object') {
module.exports = factory(require('../moment')); // Node
} else {
factory(window.moment); // Browser global
}
}(function (moment) {
return moment.lang("cy", {
months: "Ionawr_Chwefror_Mawrth_Ebrill_Mai_Mehefin_Gorffennaf_Awst_Medi_Hydref_Tachwedd_Rhagfyr".split("_"),
monthsShort: "Ion_Chwe_Maw_Ebr_Mai_Meh_Gor_Aws_Med_Hyd_Tach_Rhag".split("_"),
weekdays: "Dydd Sul_Dydd Llun_Dydd Mawrth_Dydd Mercher_Dydd Iau_Dydd Gwener_Dydd Sadwrn".split("_"),
weekdaysShort: "Sul_Llun_Maw_Mer_Iau_Gwe_Sad".split("_"),
weekdaysMin: "Su_Ll_Ma_Me_Ia_Gw_Sa".split("_"),
// time formats are the same as en-gb
longDateFormat: {
LT: "HH:mm",
L: "DD/MM/YYYY",
LL: "D MMMM YYYY",
LLL: "D MMMM YYYY LT",
LLLL: "dddd, D MMMM YYYY LT"
},
calendar: {
sameDay: '[Heddiw am] LT',
nextDay: '[Yfory am] LT',
nextWeek: 'dddd [am] LT',
lastDay: '[Ddoe am] LT',
lastWeek: 'dddd [diwethaf am] LT',
sameElse: 'L'
},
relativeTime: {
future: "mewn %s",
past: "%s yn àl",
s: "ychydig eiliadau",
m: "munud",
mm: "%d munud",
h: "awr",
hh: "%d awr",
d: "diwrnod",
dd: "%d diwrnod",
M: "mis",
MM: "%d mis",
y: "blwyddyn",
yy: "%d flynedd"
},
// traditional ordinal numbers above 31 are not commonly used in colloquial Welsh
ordinal: function (number) {
var b = number,
output = '',
lookup = [
'', 'af', 'il', 'ydd', 'ydd', 'ed', 'ed', 'ed', 'fed', 'fed', 'fed', // 1af to 10fed
'eg', 'fed', 'eg', 'eg', 'fed', 'eg', 'eg', 'fed', 'eg', 'fed' // 11eg to 20fed
];
if (b > 20) {
if (b === 40 || b === 50 || b === 60 || b === 80 || b === 100) {
output = 'fed'; // not 30ain, 70ain or 90ain
} else {
output = 'ain';
}
} else if (b > 0) {
output = lookup[b];
}
return number + output;
},
week : {
dow : 1, // Monday is the first day of the week.
doy : 4 // The week that contains Jan 4th is the first week of the year.
}
});
}));

View File

@ -0,0 +1,56 @@
// moment.js language configuration
// language : danish (da)
// author : Ulrik Nielsen : https://github.com/mrbase
(function (factory) {
if (typeof define === 'function' && define.amd) {
define(['moment'], factory); // AMD
} else if (typeof exports === 'object') {
module.exports = factory(require('../moment')); // Node
} else {
factory(window.moment); // Browser global
}
}(function (moment) {
return moment.lang('da', {
months : "januar_februar_marts_april_maj_juni_juli_august_september_oktober_november_december".split("_"),
monthsShort : "jan_feb_mar_apr_maj_jun_jul_aug_sep_okt_nov_dec".split("_"),
weekdays : "søndag_mandag_tirsdag_onsdag_torsdag_fredag_lørdag".split("_"),
weekdaysShort : "søn_man_tir_ons_tor_fre_lør".split("_"),
weekdaysMin : "sø_ma_ti_on_to_fr_lø".split("_"),
longDateFormat : {
LT : "HH:mm",
L : "DD/MM/YYYY",
LL : "D MMMM YYYY",
LLL : "D MMMM YYYY LT",
LLLL : "dddd D. MMMM, YYYY LT"
},
calendar : {
sameDay : '[I dag kl.] LT',
nextDay : '[I morgen kl.] LT',
nextWeek : 'dddd [kl.] LT',
lastDay : '[I går kl.] LT',
lastWeek : '[sidste] dddd [kl] LT',
sameElse : 'L'
},
relativeTime : {
future : "om %s",
past : "%s siden",
s : "få sekunder",
m : "et minut",
mm : "%d minutter",
h : "en time",
hh : "%d timer",
d : "en dag",
dd : "%d dage",
M : "en måned",
MM : "%d måneder",
y : "et år",
yy : "%d år"
},
ordinal : '%d.',
week : {
dow : 1, // Monday is the first day of the week.
doy : 4 // The week that contains Jan 4th is the first week of the year.
}
});
}));

Some files were not shown because too many files have changed in this diff Show More