Merge branch 'master' of git://github.com/phonegap/phonegap-android

This commit is contained in:
macdonst 2011-09-09 10:46:51 -04:00
commit 61c4836366
106 changed files with 12403 additions and 6295 deletions

6
.gitignore vendored
View File

@ -3,9 +3,13 @@ default.properties
gen
assets/www/phonegap.js
local.properties
framework/proguard.cfg
framework/phonegap.jar
framework/phonegap-*.jar
framework/bin
framework/assets/www/.DS_Store
framework/assets/www/phonegap-*.js
.DS_Store
example
test
tmp
*.tmp

134
README.md
View File

@ -1,62 +1,62 @@
PhoneGap/Android
================
===
PhoneGap/Android is an Android application library that allows for PhoneGap based projects to be built for the Android Platform. PhoneGap based applications are, at the core, an application written with web technology: HTML, CSS and JavaScript.
Pre Requisites
--------------
Requires
---
- Java JDK 1.5
- Android SDK [http://developer.android.com](http://developer.android.com)
- Apache ANT
- Ruby (Optional, see section: DroidGap with JRuby)
- Android SDK [http://developer.android.com](http://developer.android.com)
Install
-------
PhoneGap/Android Developer Tools
---
On any POSIX machine add PhoneGap/Android to your PATH variable like so:
The PhoneGap developer tooling is split between general tooling and project level tooling.
export PATH=$PATH:~/phonegap-android/bin
Commands
On Windows add the phonegap-android/bin to your PATH as normal.
./bin/create [path package activity] ... create the ./exmaple app or a phonegap/android project
./bin/bench ............................ generate a bench proj
./bin/autotest ......................... test the cli tools
./bin/test ............................. run mobile-spec
DroidGap: PhoneGap/Android Dev Script
-------------------------------------
Project Commands
Tools for developers building mobile apps using PhoneGap for Android.
These commands live in a generated PhoneGap/Android project.
Usage:
./phonegap/debug [path] ..................... install to first device
./phonegap/emulate .......................... start avd (emulator) named default
./phonegap/log .............................. starts logcat
<pre>droidgap [command] [parameters]</pre>
Running the Example Project
---
Commands:
Start avd (emulator) named `default`:
<pre>
help ...... See this message. Type help [command name] to see specific help topics.
gen ....... Generate the example PhoneGap application to current directory (or optionally provide an output directory as parameter).
create .... Creates an Android compatible project from a WWW folder.
classic ... Backwards support for droidgap script. Run "droidgap help classic" for more info.
update .... Copy a fresh phonegap.jar and phonegap.js into a valid PhoneGap/Android project.
test ...... Gets edge copy of mobile-spec and runs in first device or emulator attached.
</pre>
./bin/emulate
Quickstart:
Create the exmaple project and build it to the first device:
<pre>
$ droidgap gen exampleapp
$ cd exampleapp
$ ant debug install && adb logcat
</pre>
./bin/create
cd example
./phonegap/debug
DroidGap with JRuby
-------------------
Start adb logcat (console.log calls output here):
If you want to use the droidgap command but do not want to install Ruby then you can call it using jruby jar included in the lib folder. All the options are the same and a call looks like this:
./phonegap/log
java -jar jruby-complete-1.4.0RC1.jar ../bin/droidgap help run
Keep in mind this will be slower due to JVM warmup.
Running the [phonegap/mobile-spec](http://github.com/phonegap/mobile-spec) tests:
Importing a PhoneGap/Android app into Eclipse
---------------------------------------------
./bin/test
Create a new PhoneGap/Android Project
./bin/create ~/Desktop/myapp com.phonegap.special MyApp
Importing a PhoneGap/Android Project into Eclipse
----
1. File > New > Project...
2. Android > Android Project
@ -66,63 +66,9 @@ Importing a PhoneGap/Android app into Eclipse
6. Click on the Target tab and select Manual (this way you can choose the emulator or device to build to)
Common Command Line Tasks
=========================
Running Mobile Spec
Further Reading
---
droidgap test
Compile an APK
---
Make sure you have a device plugged in (with debugging enabled) or a running emulator. Then:
ant debug install
or
droidgap run
Converting a W3C Widget into a an APK
---
Given a Widget called FooBar with an index.html file in it. You navigate to its folder and run:
droidgap create
cd ../FooBar_android
ant debug install
List devices attached
---
adb devices
List of devices attached
0123456789012 device
Install APK onto device
---
apk -s 0123456789012 install phonegap.apk
Logging
---
Via console.log calls from your apps javascript.
adb logcat
Debugging
---
Attach it to a process on the device
$ adb jdwp
adb forward tcp:8000 jdwp: jdb -attach localhost:8000
For more info see
-----------------
- [http://developer.android.com](http://developer.android.com)
- [http://docs.phonegap.com](http://docs.phonegap.com)
- [http://wiki.phonegap.com](http://wiki.phonegap.com)

4
bin/BOOM Executable file
View File

@ -0,0 +1,4 @@
#! /bin/sh
./bin/create
cd ./example && ./phonegap/debug && ./phonegap/log

View File

@ -1,2 +0,0 @@
@ECHO OFF
echo %~dp$PATH:1

2
bin/autotest Executable file
View File

@ -0,0 +1,2 @@
#! /usr/bin/env node
require('nodeunit').reporters.default.run(['bin/tests'])

29
bin/bench Executable file
View File

@ -0,0 +1,29 @@
#! /bin/sh
#
# Creates an app in `./bench` that posts results to http://phonegap-bench.heroku.com with current PhoneGap/Android sha.
#
# USAGE
# ./bin/bench
#
# clobber any existing bench
if [ -e ./bench ]
then
rm -rf ./bench
fi
# create a benching app
./bin/create ./bench com.phonegap.bench PhoneGapBench
# grab the latest bench www code
git clone git@github.com:brianleroux/phonegap-bench.git
# copy it into the app
cat ./phonegap-bench/www/index.html > ./bench/assets/www/index.html
#cat ~/Desktop/phonegap-bench/www/index.html > ./bench/assets/www/index.html
# clean up
rm -rf ./phonegap-bench
# launch to the first device found
./bin/debug ./bench

46
bin/create Executable file
View File

@ -0,0 +1,46 @@
#! /bin/sh
#
# create a phonegap/android project
#
# USAGE
# ./create [path package activity]
#
set -e
PROJECT_PATH=${1:-"./example"}
PACKAGE=${2:-"com.phonegap.example"}
ACTIVITY=${3:-"PhoneGapExample"}
TARGET=$(android list targets | grep 'id: ' | sed 's/id: \([0-9]*\).*/\1/g' | tail -1)
VERSION=$(cat ./VERSION)
# clobber any existing example
if [ $# -eq 0 ]
then
rm -rf $PROJECT_PATH
fi
# update the phonegap-android framework for the desired target
android update project --target $TARGET --path ./framework
# compile phonegap.js and phonegap.jar
cd ./framework && ant jar && cd ../
# copy all the bin scripts etc in there
cp -R ./bin/templates/project/ $PROJECT_PATH
# copy in phonegap.js
cp ./framework/assets/www/phonegap-$VERSION.js $PROJECT_PATH/.phonegap/android/phonegap-$VERSION.js
# copy in phonegap.jar
cp ./framework/phonegap-$VERSION.jar $PROJECT_PATH/.phonegap/android/phonegap-$VERSION.jar
# app properties
cat > $PROJECT_PATH/.phonegap/config <<eom
VERSION=$VERSION
PROJECT_PATH=$PROJECT_PATH
PACKAGE=$PACKAGE
ACTIVITY=$ACTIVITY
TARGET=$TARGET
eom
(cd $PROJECT_PATH && ./phonegap/create)

1
bin/create.bat Normal file
View File

@ -0,0 +1 @@
cscript create.js

88
bin/create.js Normal file
View File

@ -0,0 +1,88 @@
/*
* create a phonegap/android project
*
* USAGE
* ./create [path package activity]
*/
function read(filename) {
var fso=WScript.CreateObject("Scripting.FileSystemObject");
var f=fso.OpenTextFile(filename, 1, true);
var s=f.ReadAll();
f.Close();
return s;
}
function write(filename, contents) {
var fso=WScript.CreateObject("Scripting.FileSystemObject");
var f=fso.OpenTextFile(filename, 2, true);
f.Write(contents);
f.Close();
}
function replaceInFile(filename, regexp, replacement) {
write(filename, read(filename).replace(regexp, replacement));
}
function exec(s) {
var o=shell.Exec(s);
}
var args = WScript.Arguments, PROJECT_PATH="example",
PACKAGE="com.phonegap.example", ACTIVITY="PhoneGapExample",
shell=WScript.CreateObject("WScript.Shell");
if (args.Count() == 3) {
WScript.Echo('Found expected arguments');
PROJECT_PATH=args(0);
PACKAGE=args(1);
ACTIVITY=args(2);
}
var PACKAGE_AS_PATH=PACKAGE.replace(/\./g, '\\');
var ACTIVITY_PATH=PROJECT_PATH+'\\src\\'+PACKAGE_AS_PATH+'\\'+ACTIVITY+'.java';
var MANIFEST_PATH=PROJECT_PATH+'\\AndroidManifest.xml';
var TARGET=shell.Exec('android.bat list targets').StdOut.ReadAll().match(/id:\s([0-9]).*/)[1];
var VERSION=read('VERSION').replace(/\r\n/,'').replace(/\n/,'');
// clobber any existing example
/*
if [ $# -eq 0 ]
then
rm -rf $PROJECT_PATH
fi
*/
// create the project
exec('android.bat create project --target '+TARGET+' --path '+PROJECT_PATH+' --package '+PACKAGE+' --activity '+ACTIVITY);
// update the phonegap framework project to a target that exists on this machine
exec('android.bat update project --target '+TARGET+' --path framework');
// compile phonegap.js and phonegap.jar
// if you see an error about "Unable to resolve target" then you may need to
// update your android tools or install an additional Android platform version
exec('ant.bat -f framework\\build.xml jar');
// copy in the project template
exec('cmd /c xcopy bin\\templates\\project '+PROJECT_PATH+' /S /Y');
// copy in phonegap.js
exec('cmd /c copy framework\\assets\\www\\phonegap-'+VERSION+'.js '+PROJECT_PATH+'\\assets\\www\\phonegap-'+VERSION+'.js /Y');
// copy in phonegap.jar
exec('cmd /c copy framework\\phonegap-'+VERSION+'.jar '+PROJECT_PATH+'\\libs\\phonegap-'+VERSION+'.jar /Y');
// copy in default activity
exec('cmd /c copy bin\\templates\\Activity.java '+ACTIVITY_PATH+' /Y');
// interpolate the activity name and package
replaceInFile(ACTIVITY_PATH, /__ACTIVITY__/, ACTIVITY);
replaceInFile(ACTIVITY_PATH, /__ID__/, PACKAGE);
replaceInFile(MANIFEST_PATH, /__ACTIVITY__/, ACTIVITY);
replaceInFile(MANIFEST_PATH, /__PACKAGE__/, PACKAGE);
/*
# leave the id for launching
touch $PROJECT_PATH/package-activity
echo $PACKAGE/$PACKAGE.$ACTIVITY > $PROJECT_PATH/package-activity
*/

79
bin/create.xml Normal file
View File

@ -0,0 +1,79 @@
<?xml version="1.0" encoding="UTF-8"?>
<project name="PhoneGap" default="create" basedir="../">
<property name="project.path" value="${basedir}/example"/>
<property name="package" value="com.phonegap.example"/>
<property name="activity" value="PhoneGapExample"/>
<target name="create">
<!-- this stuff is seriously stupid -->
<echo file="tmp/package.tmp">package-as-path=${package}</echo>
<replace file="tmp/package.tmp" token="." value="\\" />
<property file="tmp/package.tmp" />
<property name="activity.path" value="${project.path}/src/${package-as-path}/${activity}.java" />
<property name="manifest.path" value="${project.path}/AndroidManifest.xml" />
<!-- get the highest target on this machine -->
<!-- this stuff is also seriously stupid -->
<exec executable="cmd" osfamily="windows" output="tmp/target.list.tmp">
<arg line="/c android.bat list targets"/>
</exec>
<exec executable="android" osfamily="mac" output="tmp/target.list.tmp">
<arg line="list targets"/>
</exec>
<replaceregexp file="tmp/target.list.tmp" match=".*id:\s([0-9]).*" replace="target=\1" flags="s" />
<property file="tmp/target.list.tmp" />
<!-- var VERSION=read('VERSION').replace(/\r\n/,'').replace(/\n/,''); -->
<copy file="VERSION" tofile="tmp/VERSION.tmp" overwrite="true" />
<replaceregexp file="tmp/VERSION.tmp" match="^" replace="version=" />
<replaceregexp file="tmp/VERSION.tmp" match="\r\n" replace="" />
<property file="tmp/VERSION.tmp" />
<!-- clobber any existing example -->
<!-- create the project -->
<exec executable="cmd" osfamily="windows">
<arg line="/c android.bat create project --target ${target} --path ${project.path} --package ${package} --activity ${activity}"/>
</exec>
<exec executable="android" osfamily="mac">
<arg line="create project --target ${target} --path ${project.path} --package ${package} --activity ${activity}"/>
</exec>
<!-- update the framework dir -->
<exec executable="cmd" osfamily="windows">
<arg line="/c android.bat update project --target ${target} --path ${basedir}/framework"/>
</exec>
<exec executable="android" osfamily="mac">
<arg line="update project --target ${target} --path ${basedir}/framework"/>
</exec>
<!-- compile phonegap.js and phonegap.jar -->
<!-- // if you see an error about "Unable to resolve target" then you may need to
// update your android tools or install an additional Android platform version -->
<ant antfile="${basedir}/framework/build.xml" useNativeBasedir="true" inheritAll="false" />
<!-- copy in the project template -->
<copy todir="${project.path}" overwrite="true">
<fileset dir="${basedir}/bin/templates/project"/>
</copy>
<!-- copy in phonegap.js -->
<copy file="${basedir}/framework/assets/www/phonegap-${version}.js" todir="${project.path}/assets/www/" />
<!-- copy in phonegap.jar -->
<copy file="${basedir}/framework/phonegap-${version}.jar" todir="${project.path}/libs/" />
<!-- copy in default activity -->
<copy file="${basedir}/bin/templates/Activity.java" tofile="${activity.path}" overwrite="true" />
<!-- interpolate the activity name and package -->
<replaceregexp file="${activity.path}" match="__ACTIVITY__" replace="${activity}" />
<replaceregexp file="${activity.path}" match="__ID__" replace="${package}" />
<replaceregexp file="${manifest.path}" match="__ACTIVITY__" replace="${activity}" />
<replaceregexp file="${manifest.path}" match="__PACKAGE__" replace="${package}" />
</target>
</project>

View File

@ -1,173 +0,0 @@
#!/usr/bin/env ruby
ROOT = File.expand_path(File.dirname(__FILE__).gsub(/bin$/,''))
require 'fileutils'
require File.join(ROOT, "lib", "generate.rb")
require File.join(ROOT, "lib", "classic.rb")
require File.join(ROOT, "lib", "create.rb")
require File.join(ROOT, "lib", "run.rb")
require File.join(ROOT, "lib", "update.rb")
require File.join(ROOT, "lib", "test.rb")
# ---------------------------------------------------------- #
# #
# command line interface #
# #
# ---------------------------------------------------------- #
# droidgap gen [app name]
Generate.new(ARGV[1]) if ARGV.first == 'gen'
# droidgap classic (for windows users mostly)
Classic.new(ARGV[1..-1]) if ARGV.first == 'classic'
# droidgap create [path to phonegap project]
Create.new(ARGV[1]) if ARGV.first == 'create'
# droidgap run [optional directory]
Run.new if ARGV.first == 'run'
# droidgap update [params]
Update.new if ARGV.first == 'update'
# droidgap log
if ARGV.first == 'log'
$stdout.sync = true
IO.popen('adb logcat') do |f|
until f.eof?
puts f.gets
end
end
end
# droidgap test
Test.new if ARGV.first == 'test'
# TODO implement these!
puts "droidgap ship not implemented" if ARGV.first == 'ship'
if ARGV.first.nil? || ARGV.first == 'help'
help = <<-EOF
DroidGap: PhoneGap/Android Dev Script
-------------------------------------
Useful utilities for devlopers building mobile apps using PhoneGap for Android.
Usage:
droidgap <command> <parameters>
Commands:
help ...... See this message. Type help [command name] to see specific help topics.
gen ....... Generate the example PhoneGap application to current directory (or optionally provide an output directory as parameter).
create .... Creates an Android compatible project from a WWW folder.
classic ... Backwards support for droidgap script. Run "droidgap help classic" for more info.
update .... Copy a fresh phonegap.jar and phonegap.js into a valid PhoneGap/Android project.
ship ...... Build and sign an APK suitable for submission to an Android Marketplace.
Quickstart:
$ droidgap gen exampleapp
$ cd exampleapp
$ ant debug install && adb logcat
EOF
gen = <<-EOF
DroidGap Generate
-----------------
Generate the example PhoneGap application to path supplied or current working directory if none is supplied.
Usage:
droidgap gen [path]
NOTE: Do *not* run "droidgap gen example" - you will end up with a recursive directory problem.
EOF
run = <<-EOF
DroidGap Run
------------
Launches PhoneGap project to first device found and attaches a logger that listens for console.log statements.
Usage:
droidgap run <path>
EOF
ship = <<-EOF
DroidGap Ship
-------------
Build and sign an APK suitable for submission to an Android Marketplace.
Usage:
droidgap ship <path>
EOF
log = <<-EOF
DroidGap Log
-------------
Launches LogCat
Usage:
droidgap log
EOF
create = <<-EOF
DroidGap Create
----------------
Creates an Android compatable project from a PhoneGap project. For example, if you have MyProject with index.html this command will create MyProject_android.
Usage:
droidgap create <path>
EOF
update = <<-EOF
DroidGap Update
~~~~~~~~~~~~~~~
Builds the JS and PhoneGap Android jar file and copies them to your project.
EOF
classic = <<-EOF
DroidGap Classic
~~~~~~~~~~~~-~~~
Compatability for older droidgap scripts.
Usage:
droidgap classic [android_sdk_path] [name] [package_name] [www] [path]
android_sdk_path ... The path to your Android SDK install.
name ............... The name of your application.
package_name ....... The name of your package (For example: com.nitobi.demo)
www ................ The path to your www folder. (Wherein your HTML, CSS and JS app is.)
path ............... The path to generate the application.
EOF
puts ARGV[1].nil? ? help : eval(ARGV[1])
end

View File

@ -1 +0,0 @@
ruby %~dp0droidgap %1 %2

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

@ -0,0 +1 @@
../coffee-script/bin/cake

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

@ -0,0 +1 @@
../coffee-script/bin/coffee

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

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

11
bin/node_modules/coffee-script/.npmignore generated vendored Normal file
View File

@ -0,0 +1,11 @@
*.coffee
*.html
.DS_Store
.git*
Cakefile
documentation/
examples/
extras/coffee-script.js
raw/
src/
test/

22
bin/node_modules/coffee-script/LICENSE generated vendored Normal file
View File

@ -0,0 +1,22 @@
Copyright (c) 2011 Jeremy Ashkenas
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.

48
bin/node_modules/coffee-script/README generated vendored Normal file
View File

@ -0,0 +1,48 @@
=
{
} } {
{ { } }
} }{ {
{ }{ } } _____ __ __
( }{ }{ { ) / ____| / _|/ _|
.- { { } { }} -. | | ___ | |_| |_ ___ ___
( ( } { } { } } ) | | / _ \| _| _/ _ \/ _ \
|`-..________ ..-'| | |___| (_) | | | || __/ __/
| | \_____\___/|_| |_| \___|\___|
| ;--.
| (__ \ _____ _ _
| | ) ) / ____| (_) | |
| |/ / | (___ ___ _ __ _ _ __ | |_
| ( / \___ \ / __| '__| | '_ \| __|
| |/ ____) | (__| | | | |_) | |_
| | |_____/ \___|_| |_| .__/ \__|
`-.._________..-' | |
|_|
CoffeeScript is a little language that compiles into JavaScript.
Install Node.js, and then the CoffeeScript compiler:
sudo bin/cake install
Or, if you have the Node Package Manager installed:
npm install -g coffee-script
(Leave off the -g if you don't wish to install globally.)
Compile a script:
coffee /path/to/script.coffee
For documentation, usage, and examples, see:
http://coffeescript.org/
To suggest a feature, report a bug, or general discussion:
http://github.com/jashkenas/coffee-script/issues/
If you'd like to chat, drop by #coffeescript on Freenode IRC,
or on webchat.freenode.net.
The source repository:
git://github.com/jashkenas/coffee-script.git
All contributors are listed here:
http://github.com/jashkenas/coffee-script/contributors

78
bin/node_modules/coffee-script/Rakefile generated vendored Normal file
View File

@ -0,0 +1,78 @@
require 'rubygems'
require 'erb'
require 'fileutils'
require 'rake/testtask'
require 'json'
desc "Build the documentation page"
task :doc do
source = 'documentation/index.html.erb'
child = fork { exec "bin/coffee -bcw -o documentation/js documentation/coffee/*.coffee" }
at_exit { Process.kill("INT", child) }
Signal.trap("INT") { exit }
loop do
mtime = File.stat(source).mtime
if !@mtime || mtime > @mtime
rendered = ERB.new(File.read(source)).result(binding)
File.open('index.html', 'w+') {|f| f.write(rendered) }
end
@mtime = mtime
sleep 1
end
end
desc "Build coffee-script-source gem"
task :gem do
require 'rubygems'
require 'rubygems/package'
gemspec = Gem::Specification.new do |s|
s.name = 'coffee-script-source'
s.version = JSON.parse(File.read('package.json'))["version"]
s.date = Time.now.strftime("%Y-%m-%d")
s.homepage = "http://jashkenas.github.com/coffee-script/"
s.summary = "The CoffeeScript Compiler"
s.description = <<-EOS
CoffeeScript is a little language that compiles into JavaScript.
Underneath all of those embarrassing braces and semicolons,
JavaScript has always had a gorgeous object model at its heart.
CoffeeScript is an attempt to expose the good parts of JavaScript
in a simple way.
EOS
s.files = [
'lib/coffee_script/coffee-script.js',
'lib/coffee_script/source.rb'
]
s.authors = ['Jeremy Ashkenas']
s.email = 'jashkenas@gmail.com'
s.rubyforge_project = 'coffee-script-source'
end
file = File.open("coffee-script-source.gem", "w")
Gem::Package.open(file, 'w') do |pkg|
pkg.metadata = gemspec.to_yaml
path = "lib/coffee_script/source.rb"
contents = <<-ERUBY
module CoffeeScript
module Source
def self.bundled_path
File.expand_path("../coffee-script.js", __FILE__)
end
end
end
ERUBY
pkg.add_file_simple(path, 0644, contents.size) do |tar_io|
tar_io.write(contents)
end
contents = File.read("extras/coffee-script.js")
path = "lib/coffee_script/coffee-script.js"
pkg.add_file_simple(path, 0644, contents.size) do |tar_io|
tar_io.write(contents)
end
end
end

7
bin/node_modules/coffee-script/bin/cake generated vendored Executable file
View File

@ -0,0 +1,7 @@
#!/usr/bin/env node
var path = require('path');
var fs = require('fs');
var lib = path.join(path.dirname(fs.realpathSync(__filename)), '../lib');
require(lib + '/cake').run();

7
bin/node_modules/coffee-script/bin/coffee generated vendored Executable file
View File

@ -0,0 +1,7 @@
#!/usr/bin/env node
var path = require('path');
var fs = require('fs');
var lib = path.join(path.dirname(fs.realpathSync(__filename)), '../lib');
require(lib + '/command').run();

44
bin/node_modules/coffee-script/extras/jsl.conf generated vendored Normal file
View File

@ -0,0 +1,44 @@
# JavaScriptLint configuration file for CoffeeScript.
+no_return_value # function {0} does not always return a value
+duplicate_formal # duplicate formal argument {0}
-equal_as_assign # test for equality (==) mistyped as assignment (=)?{0}
+var_hides_arg # variable {0} hides argument
+redeclared_var # redeclaration of {0} {1}
-anon_no_return_value # anonymous function does not always return a value
+missing_semicolon # missing semicolon
+meaningless_block # meaningless block; curly braces have no impact
-comma_separated_stmts # multiple statements separated by commas (use semicolons?)
+unreachable_code # unreachable code
+missing_break # missing break statement
-missing_break_for_last_case # missing break statement for last case in switch
-comparison_type_conv # comparisons against null, 0, true, false, or an empty string allowing implicit type conversion (use === or !==)
-inc_dec_within_stmt # increment (++) and decrement (--) operators used as part of greater statement
-useless_void # use of the void type may be unnecessary (void is always undefined)
+multiple_plus_minus # unknown order of operations for successive plus (e.g. x+++y) or minus (e.g. x---y) signs
+use_of_label # use of label
-block_without_braces # block statement without curly braces
+leading_decimal_point # leading decimal point may indicate a number or an object member
+trailing_decimal_point # trailing decimal point may indicate a number or an object member
+octal_number # leading zeros make an octal number
+nested_comment # nested comment
+misplaced_regex # regular expressions should be preceded by a left parenthesis, assignment, colon, or comma
+ambiguous_newline # unexpected end of line; it is ambiguous whether these lines are part of the same statement
+empty_statement # empty statement or extra semicolon
-missing_option_explicit # the "option explicit" control comment is missing
+partial_option_explicit # the "option explicit" control comment, if used, must be in the first script tag
+dup_option_explicit # duplicate "option explicit" control comment
+useless_assign # useless assignment
+ambiguous_nested_stmt # block statements containing block statements should use curly braces to resolve ambiguity
+ambiguous_else_stmt # the else statement could be matched with one of multiple if statements (use curly braces to indicate intent)
-missing_default_case # missing default case in switch statement
+duplicate_case_in_switch # duplicate case in switch statements
+default_not_at_end # the default case is not at the end of the switch statement
+legacy_cc_not_understood # couldn't understand control comment using /*@keyword@*/ syntax
+jsl_cc_not_understood # couldn't understand control comment using /*jsl:keyword*/ syntax
+useless_comparison # useless comparison; comparing identical expressions
+with_statement # with statement hides undeclared variables; use temporary variable instead
+trailing_comma_in_array # extra comma is not recommended in array initializers
+assign_to_function_call # assignment to a function call
+parseint_missing_radix # parseInt missing radix parameter
+lambda_assign_requires_semicolon

75
bin/node_modules/coffee-script/lib/browser.js generated vendored Normal file
View File

@ -0,0 +1,75 @@
(function() {
var CoffeeScript, runScripts;
CoffeeScript = require('./coffee-script');
CoffeeScript.require = require;
CoffeeScript.eval = function(code, options) {
return eval(CoffeeScript.compile(code, options));
};
CoffeeScript.run = function(code, options) {
if (options == null) {
options = {};
}
options.bare = true;
return Function(CoffeeScript.compile(code, options))();
};
if (typeof window === "undefined" || window === null) {
return;
}
CoffeeScript.load = function(url, callback) {
var xhr;
xhr = new (window.ActiveXObject || XMLHttpRequest)('Microsoft.XMLHTTP');
xhr.open('GET', url, true);
if ('overrideMimeType' in xhr) {
xhr.overrideMimeType('text/plain');
}
xhr.onreadystatechange = function() {
var _ref;
if (xhr.readyState === 4) {
if ((_ref = xhr.status) === 0 || _ref === 200) {
CoffeeScript.run(xhr.responseText);
} else {
throw new Error("Could not load " + url);
}
if (callback) {
return callback();
}
}
};
return xhr.send(null);
};
runScripts = function() {
var coffees, execute, index, length, s, scripts;
scripts = document.getElementsByTagName('script');
coffees = (function() {
var _i, _len, _results;
_results = [];
for (_i = 0, _len = scripts.length; _i < _len; _i++) {
s = scripts[_i];
if (s.type === 'text/coffeescript') {
_results.push(s);
}
}
return _results;
})();
index = 0;
length = coffees.length;
(execute = function() {
var script;
script = coffees[index++];
if ((script != null ? script.type : void 0) === 'text/coffeescript') {
if (script.src) {
return CoffeeScript.load(script.src, execute);
} else {
CoffeeScript.run(script.innerHTML);
return execute();
}
}
})();
return null;
};
if (window.addEventListener) {
addEventListener('DOMContentLoaded', runScripts, false);
} else {
attachEvent('onload', runScripts);
}
}).call(this);

76
bin/node_modules/coffee-script/lib/cake.js generated vendored Executable file
View File

@ -0,0 +1,76 @@
(function() {
var CoffeeScript, fs, helpers, missingTask, oparse, options, optparse, path, printTasks, switches, tasks;
fs = require('fs');
path = require('path');
helpers = require('./helpers');
optparse = require('./optparse');
CoffeeScript = require('./coffee-script');
tasks = {};
options = {};
switches = [];
oparse = null;
helpers.extend(global, {
task: function(name, description, action) {
var _ref;
if (!action) {
_ref = [description, action], action = _ref[0], description = _ref[1];
}
return tasks[name] = {
name: name,
description: description,
action: action
};
},
option: function(letter, flag, description) {
return switches.push([letter, flag, description]);
},
invoke: function(name) {
if (!tasks[name]) {
missingTask(name);
}
return tasks[name].action(options);
}
});
exports.run = function() {
return path.exists('Cakefile', function(exists) {
var arg, args, _i, _len, _ref, _results;
if (!exists) {
throw new Error("Cakefile not found in " + (process.cwd()));
}
args = process.argv.slice(2);
CoffeeScript.run(fs.readFileSync('Cakefile').toString(), {
filename: 'Cakefile'
});
oparse = new optparse.OptionParser(switches);
if (!args.length) {
return printTasks();
}
options = oparse.parse(args);
_ref = options.arguments;
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
arg = _ref[_i];
_results.push(invoke(arg));
}
return _results;
});
};
printTasks = function() {
var desc, name, spaces, task;
console.log('');
for (name in tasks) {
task = tasks[name];
spaces = 20 - name.length;
spaces = spaces > 0 ? Array(spaces + 1).join(' ') : '';
desc = task.description ? "# " + task.description : '';
console.log("cake " + name + spaces + " " + desc);
}
if (switches.length) {
return console.log(oparse.help());
}
};
missingTask = function(task) {
console.log("No such task: \"" + task + "\"");
return process.exit(1);
};
}).call(this);

135
bin/node_modules/coffee-script/lib/coffee-script.js generated vendored Executable file
View File

@ -0,0 +1,135 @@
(function() {
var Lexer, RESERVED, compile, fs, lexer, parser, path, _ref;
var __hasProp = Object.prototype.hasOwnProperty;
fs = require('fs');
path = require('path');
_ref = require('./lexer'), Lexer = _ref.Lexer, RESERVED = _ref.RESERVED;
parser = require('./parser').parser;
if (require.extensions) {
require.extensions['.coffee'] = function(module, filename) {
var content;
content = compile(fs.readFileSync(filename, 'utf8'), {
filename: filename
});
return module._compile(content, filename);
};
} else if (require.registerExtension) {
require.registerExtension('.coffee', function(content) {
return compile(content);
});
}
exports.VERSION = '1.1.2';
exports.RESERVED = RESERVED;
exports.helpers = require('./helpers');
exports.compile = compile = function(code, options) {
if (options == null) {
options = {};
}
try {
return (parser.parse(lexer.tokenize(code))).compile(options);
} catch (err) {
if (options.filename) {
err.message = "In " + options.filename + ", " + err.message;
}
throw err;
}
};
exports.tokens = function(code, options) {
return lexer.tokenize(code, options);
};
exports.nodes = function(source, options) {
if (typeof source === 'string') {
return parser.parse(lexer.tokenize(source, options));
} else {
return parser.parse(source);
}
};
exports.run = function(code, options) {
var Module, mainModule;
mainModule = require.main;
mainModule.filename = process.argv[1] = options.filename ? fs.realpathSync(options.filename) : '.';
mainModule.moduleCache && (mainModule.moduleCache = {});
if (process.binding('natives').module) {
Module = require('module').Module;
mainModule.paths = Module._nodeModulePaths(path.dirname(options.filename));
}
if (path.extname(mainModule.filename) !== '.coffee' || require.extensions) {
return mainModule._compile(compile(code, options), mainModule.filename);
} else {
return mainModule._compile(code, mainModule.filename);
}
};
exports.eval = function(code, options) {
var Module, Script, js, k, o, r, sandbox, v, _i, _len, _module, _ref2, _ref3, _ref4, _require;
if (options == null) {
options = {};
}
if (!(code = code.trim())) {
return;
}
if (_ref2 = require('vm'), Script = _ref2.Script, _ref2) {
sandbox = Script.createContext();
sandbox.global = sandbox.root = sandbox.GLOBAL = sandbox;
if (options.sandbox != null) {
if (options.sandbox instanceof sandbox.constructor) {
sandbox = options.sandbox;
} else {
_ref3 = options.sandbox;
for (k in _ref3) {
if (!__hasProp.call(_ref3, k)) continue;
v = _ref3[k];
sandbox[k] = v;
}
}
}
sandbox.__filename = options.filename || 'eval';
sandbox.__dirname = path.dirname(sandbox.__filename);
if (!(sandbox.module || sandbox.require)) {
Module = require('module');
sandbox.module = _module = new Module(options.modulename || 'eval');
sandbox.require = _require = function(path) {
return Module._load(path, _module);
};
_module.filename = sandbox.__filename;
_ref4 = Object.getOwnPropertyNames(require);
for (_i = 0, _len = _ref4.length; _i < _len; _i++) {
r = _ref4[_i];
_require[r] = require[r];
}
_require.paths = _module.paths = Module._nodeModulePaths(process.cwd());
_require.resolve = function(request) {
return Module._resolveFilename(request, _module);
};
}
}
o = {};
for (k in options) {
if (!__hasProp.call(options, k)) continue;
v = options[k];
o[k] = v;
}
o.bare = true;
js = compile(code, o);
if (Script) {
return Script.runInContext(js, sandbox);
} else {
return eval(js);
}
};
lexer = new Lexer;
parser.lexer = {
lex: function() {
var tag, _ref2;
_ref2 = this.tokens[this.pos++] || [''], tag = _ref2[0], this.yytext = _ref2[1], this.yylineno = _ref2[2];
return tag;
},
setInput: function(tokens) {
this.tokens = tokens;
return this.pos = 0;
},
upcomingInput: function() {
return "";
}
};
parser.yy = require('./nodes');
}).call(this);

301
bin/node_modules/coffee-script/lib/command.js generated vendored Normal file
View File

@ -0,0 +1,301 @@
(function() {
var BANNER, CoffeeScript, EventEmitter, SWITCHES, compileJoin, compileOptions, compileScript, compileScripts, compileStdio, contents, exec, forkNode, fs, helpers, lint, loadRequires, optionParser, optparse, opts, parseOptions, path, printLine, printTokens, printWarn, sources, spawn, usage, version, watch, writeJs, _ref;
fs = require('fs');
path = require('path');
helpers = require('./helpers');
optparse = require('./optparse');
CoffeeScript = require('./coffee-script');
_ref = require('child_process'), spawn = _ref.spawn, exec = _ref.exec;
EventEmitter = require('events').EventEmitter;
helpers.extend(CoffeeScript, new EventEmitter);
printLine = function(line) {
return process.stdout.write(line + '\n');
};
printWarn = function(line) {
return process.binding('stdio').writeError(line + '\n');
};
BANNER = 'Usage: coffee [options] path/to/script.coffee';
SWITCHES = [['-c', '--compile', 'compile to JavaScript and save as .js files'], ['-i', '--interactive', 'run an interactive CoffeeScript REPL'], ['-o', '--output [DIR]', 'set the directory for compiled JavaScript'], ['-j', '--join [FILE]', 'concatenate the scripts before compiling'], ['-w', '--watch', 'watch scripts for changes, and recompile'], ['-p', '--print', 'print the compiled JavaScript to stdout'], ['-l', '--lint', 'pipe the compiled JavaScript through JavaScript Lint'], ['-s', '--stdio', 'listen for and compile scripts over stdio'], ['-e', '--eval', 'compile a string from the command line'], ['-r', '--require [FILE*]', 'require a library before executing your script'], ['-b', '--bare', 'compile without the top-level function wrapper'], ['-t', '--tokens', 'print the tokens that the lexer produces'], ['-n', '--nodes', 'print the parse tree that Jison produces'], ['--nodejs [ARGS]', 'pass options through to the "node" binary'], ['-v', '--version', 'display CoffeeScript version'], ['-h', '--help', 'display this help message']];
opts = {};
sources = [];
contents = [];
optionParser = null;
exports.run = function() {
parseOptions();
if (opts.nodejs) {
return forkNode();
}
if (opts.help) {
return usage();
}
if (opts.version) {
return version();
}
if (opts.require) {
loadRequires();
}
if (opts.interactive) {
return require('./repl');
}
if (opts.stdio) {
return compileStdio();
}
if (opts.eval) {
return compileScript(null, sources[0]);
}
if (!sources.length) {
return require('./repl');
}
if (opts.run) {
opts.literals = sources.splice(1).concat(opts.literals);
}
process.ARGV = process.argv = process.argv.slice(0, 2).concat(opts.literals);
process.argv[0] = 'coffee';
process.execPath = require.main.filename;
return compileScripts();
};
compileScripts = function() {
var base, compile, source, unprocessed, _i, _j, _len, _len2, _results;
unprocessed = [];
for (_i = 0, _len = sources.length; _i < _len; _i++) {
source = sources[_i];
unprocessed[sources.indexOf(source)] = 1;
}
_results = [];
for (_j = 0, _len2 = sources.length; _j < _len2; _j++) {
source = sources[_j];
base = path.join(source);
compile = function(source, sourceIndex, topLevel) {
var remaining_files;
remaining_files = function() {
var total, x, _k, _len3;
total = 0;
for (_k = 0, _len3 = unprocessed.length; _k < _len3; _k++) {
x = unprocessed[_k];
total += x;
}
return total;
};
return path.exists(source, function(exists) {
if (topLevel && !exists && source.slice(-7) !== '.coffee') {
return compile("" + source + ".coffee", sourceIndex, topLevel);
}
if (topLevel && !exists) {
throw new Error("File not found: " + source);
}
return fs.stat(source, function(err, stats) {
if (err) {
throw err;
}
if (stats.isDirectory()) {
return fs.readdir(source, function(err, files) {
var file, _k, _len3;
if (err) {
throw err;
}
unprocessed[sourceIndex] += files.length;
for (_k = 0, _len3 = files.length; _k < _len3; _k++) {
file = files[_k];
compile(path.join(source, file), sourceIndex);
}
return unprocessed[sourceIndex] -= 1;
});
} else if (topLevel || path.extname(source) === '.coffee') {
fs.readFile(source, function(err, code) {
if (err) {
throw err;
}
unprocessed[sourceIndex] -= 1;
if (opts.join) {
contents[sourceIndex] = helpers.compact([contents[sourceIndex], code.toString()]).join('\n');
if (helpers.compact(contents).length > 0 && remaining_files() === 0) {
return compileJoin();
}
} else {
return compileScript(source, code.toString(), base);
}
});
if (opts.watch && !opts.join) {
return watch(source, base);
}
} else {
return unprocessed[sourceIndex] -= 1;
}
});
});
};
_results.push(compile(source, sources.indexOf(source), true));
}
return _results;
};
compileScript = function(file, input, base) {
var o, options, t, task;
o = opts;
options = compileOptions(file);
try {
t = task = {
file: file,
input: input,
options: options
};
CoffeeScript.emit('compile', task);
if (o.tokens) {
return printTokens(CoffeeScript.tokens(t.input));
} else if (o.nodes) {
return printLine(CoffeeScript.nodes(t.input).toString().trim());
} else if (o.run) {
return CoffeeScript.run(t.input, t.options);
} else {
t.output = CoffeeScript.compile(t.input, t.options);
CoffeeScript.emit('success', task);
if (o.print) {
return printLine(t.output.trim());
} else if (o.compile) {
return writeJs(t.file, t.output, base);
} else if (o.lint) {
return lint(t.file, t.output);
}
}
} catch (err) {
CoffeeScript.emit('failure', err, task);
if (CoffeeScript.listeners('failure').length) {
return;
}
if (o.watch) {
return printLine(err.message);
}
printWarn(err.stack);
return process.exit(1);
}
};
compileStdio = function() {
var code, stdin;
code = '';
stdin = process.openStdin();
stdin.on('data', function(buffer) {
if (buffer) {
return code += buffer.toString();
}
});
return stdin.on('end', function() {
return compileScript(null, code);
});
};
compileJoin = function() {
var code;
code = contents.join('\n');
return compileScript(opts.join, code, opts.join);
};
loadRequires = function() {
var realFilename, req, _i, _len, _ref2;
realFilename = module.filename;
module.filename = '.';
_ref2 = opts.require;
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
req = _ref2[_i];
require(req);
}
return module.filename = realFilename;
};
watch = function(source, base) {
return fs.watchFile(source, {
persistent: true,
interval: 500
}, function(curr, prev) {
if (curr.size === prev.size && curr.mtime.getTime() === prev.mtime.getTime()) {
return;
}
return fs.readFile(source, function(err, code) {
if (err) {
throw err;
}
return compileScript(source, code.toString(), base);
});
});
};
writeJs = function(source, js, base) {
var baseDir, compile, dir, filename, jsPath, srcDir;
filename = path.basename(source, path.extname(source)) + '.js';
srcDir = path.dirname(source);
baseDir = base === '.' ? srcDir : srcDir.substring(base.length);
dir = opts.output ? path.join(opts.output, baseDir) : srcDir;
jsPath = path.join(dir, filename);
compile = function() {
if (js.length <= 0) {
js = ' ';
}
return fs.writeFile(jsPath, js, function(err) {
if (err) {
return printLine(err.message);
} else if (opts.compile && opts.watch) {
return console.log("" + ((new Date).toLocaleTimeString()) + " - compiled " + source);
}
});
};
return path.exists(dir, function(exists) {
if (exists) {
return compile();
} else {
return exec("mkdir -p " + dir, compile);
}
});
};
lint = function(file, js) {
var conf, jsl, printIt;
printIt = function(buffer) {
return printLine(file + ':\t' + buffer.toString().trim());
};
conf = __dirname + '/../extras/jsl.conf';
jsl = spawn('jsl', ['-nologo', '-stdin', '-conf', conf]);
jsl.stdout.on('data', printIt);
jsl.stderr.on('data', printIt);
jsl.stdin.write(js);
return jsl.stdin.end();
};
printTokens = function(tokens) {
var strings, tag, token, value;
strings = (function() {
var _i, _len, _ref2, _results;
_results = [];
for (_i = 0, _len = tokens.length; _i < _len; _i++) {
token = tokens[_i];
_ref2 = [token[0], token[1].toString().replace(/\n/, '\\n')], tag = _ref2[0], value = _ref2[1];
_results.push("[" + tag + " " + value + "]");
}
return _results;
})();
return printLine(strings.join(' '));
};
parseOptions = function() {
var o;
optionParser = new optparse.OptionParser(SWITCHES, BANNER);
o = opts = optionParser.parse(process.argv.slice(2));
o.compile || (o.compile = !!o.output);
o.run = !(o.compile || o.print || o.lint);
o.print = !!(o.print || (o.eval || o.stdio && o.compile));
return sources = o.arguments;
};
compileOptions = function(filename) {
return {
filename: filename,
bare: opts.bare
};
};
forkNode = function() {
var args, nodeArgs;
nodeArgs = opts.nodejs.split(/\s+/);
args = process.argv.slice(1);
args.splice(args.indexOf('--nodejs'), 2);
return spawn(process.execPath, nodeArgs.concat(args), {
cwd: process.cwd(),
env: process.env,
customFds: [0, 1, 2]
});
};
usage = function() {
return printLine((new optparse.OptionParser(SWITCHES, BANNER)).help());
};
version = function() {
return printLine("CoffeeScript version " + CoffeeScript.VERSION);
};
}).call(this);

591
bin/node_modules/coffee-script/lib/grammar.js generated vendored Normal file
View File

@ -0,0 +1,591 @@
(function() {
var Parser, alt, alternatives, grammar, name, o, operators, token, tokens, unwrap;
Parser = require('jison').Parser;
unwrap = /^function\s*\(\)\s*\{\s*return\s*([\s\S]*);\s*\}/;
o = function(patternString, action, options) {
var match;
patternString = patternString.replace(/\s{2,}/g, ' ');
if (!action) {
return [patternString, '$$ = $1;', options];
}
action = (match = unwrap.exec(action)) ? match[1] : "(" + action + "())";
action = action.replace(/\bnew /g, '$&yy.');
action = action.replace(/\b(?:Block\.wrap|extend)\b/g, 'yy.$&');
return [patternString, "$$ = " + action + ";", options];
};
grammar = {
Root: [
o('', function() {
return new Block;
}), o('Body'), o('Block TERMINATOR')
],
Body: [
o('Line', function() {
return Block.wrap([$1]);
}), o('Body TERMINATOR Line', function() {
return $1.push($3);
}), o('Body TERMINATOR')
],
Line: [o('Expression'), o('Statement')],
Statement: [
o('Return'), o('Throw'), o('Comment'), o('STATEMENT', function() {
return new Literal($1);
})
],
Expression: [o('Value'), o('Invocation'), o('Code'), o('Operation'), o('Assign'), o('If'), o('Try'), o('While'), o('For'), o('Switch'), o('Class')],
Block: [
o('INDENT OUTDENT', function() {
return new Block;
}), o('INDENT Body OUTDENT', function() {
return $2;
})
],
Identifier: [
o('IDENTIFIER', function() {
return new Literal($1);
})
],
AlphaNumeric: [
o('NUMBER', function() {
return new Literal($1);
}), o('STRING', function() {
return new Literal($1);
})
],
Literal: [
o('AlphaNumeric'), o('JS', function() {
return new Literal($1);
}), o('REGEX', function() {
return new Literal($1);
}), o('BOOL', function() {
var val;
val = new Literal($1);
if ($1 === 'undefined') {
val.isUndefined = true;
}
return val;
})
],
Assign: [
o('Assignable = Expression', function() {
return new Assign($1, $3);
}), o('Assignable = INDENT Expression OUTDENT', function() {
return new Assign($1, $4);
})
],
AssignObj: [
o('ObjAssignable', function() {
return new Value($1);
}), o('ObjAssignable : Expression', function() {
return new Assign(new Value($1), $3, 'object');
}), o('ObjAssignable :\
INDENT Expression OUTDENT', function() {
return new Assign(new Value($1), $4, 'object');
}), o('Comment')
],
ObjAssignable: [o('Identifier'), o('AlphaNumeric'), o('ThisProperty')],
Return: [
o('RETURN Expression', function() {
return new Return($2);
}), o('RETURN', function() {
return new Return;
})
],
Comment: [
o('HERECOMMENT', function() {
return new Comment($1);
})
],
Code: [
o('PARAM_START ParamList PARAM_END FuncGlyph Block', function() {
return new Code($2, $5, $4);
}), o('FuncGlyph Block', function() {
return new Code([], $2, $1);
})
],
FuncGlyph: [
o('->', function() {
return 'func';
}), o('=>', function() {
return 'boundfunc';
})
],
OptComma: [o(''), o(',')],
ParamList: [
o('', function() {
return [];
}), o('Param', function() {
return [$1];
}), o('ParamList , Param', function() {
return $1.concat($3);
})
],
Param: [
o('ParamVar', function() {
return new Param($1);
}), o('ParamVar ...', function() {
return new Param($1, null, true);
}), o('ParamVar = Expression', function() {
return new Param($1, $3);
})
],
ParamVar: [o('Identifier'), o('ThisProperty'), o('Array'), o('Object')],
Splat: [
o('Expression ...', function() {
return new Splat($1);
})
],
SimpleAssignable: [
o('Identifier', function() {
return new Value($1);
}), o('Value Accessor', function() {
return $1.push($2);
}), o('Invocation Accessor', function() {
return new Value($1, [$2]);
}), o('ThisProperty')
],
Assignable: [
o('SimpleAssignable'), o('Array', function() {
return new Value($1);
}), o('Object', function() {
return new Value($1);
})
],
Value: [
o('Assignable'), o('Literal', function() {
return new Value($1);
}), o('Parenthetical', function() {
return new Value($1);
}), o('Range', function() {
return new Value($1);
}), o('This')
],
Accessor: [
o('. Identifier', function() {
return new Access($2);
}), o('?. Identifier', function() {
return new Access($2, 'soak');
}), o(':: Identifier', function() {
return new Access($2, 'proto');
}), o('::', function() {
return new Access(new Literal('prototype'));
}), o('Index')
],
Index: [
o('INDEX_START IndexValue INDEX_END', function() {
return $2;
}), o('INDEX_SOAK Index', function() {
return extend($2, {
soak: true
});
}), o('INDEX_PROTO Index', function() {
return extend($2, {
proto: true
});
})
],
IndexValue: [
o('Expression', function() {
return new Index($1);
}), o('Slice', function() {
return new Slice($1);
})
],
Object: [
o('{ AssignList OptComma }', function() {
return new Obj($2, $1.generated);
})
],
AssignList: [
o('', function() {
return [];
}), o('AssignObj', function() {
return [$1];
}), o('AssignList , AssignObj', function() {
return $1.concat($3);
}), o('AssignList OptComma TERMINATOR AssignObj', function() {
return $1.concat($4);
}), o('AssignList OptComma INDENT AssignList OptComma OUTDENT', function() {
return $1.concat($4);
})
],
Class: [
o('CLASS', function() {
return new Class;
}), o('CLASS Block', function() {
return new Class(null, null, $2);
}), o('CLASS EXTENDS Value', function() {
return new Class(null, $3);
}), o('CLASS EXTENDS Value Block', function() {
return new Class(null, $3, $4);
}), o('CLASS SimpleAssignable', function() {
return new Class($2);
}), o('CLASS SimpleAssignable Block', function() {
return new Class($2, null, $3);
}), o('CLASS SimpleAssignable EXTENDS Value', function() {
return new Class($2, $4);
}), o('CLASS SimpleAssignable EXTENDS Value Block', function() {
return new Class($2, $4, $5);
})
],
Invocation: [
o('Value OptFuncExist Arguments', function() {
return new Call($1, $3, $2);
}), o('Invocation OptFuncExist Arguments', function() {
return new Call($1, $3, $2);
}), o('SUPER', function() {
return new Call('super', [new Splat(new Literal('arguments'))]);
}), o('SUPER Arguments', function() {
return new Call('super', $2);
})
],
OptFuncExist: [
o('', function() {
return false;
}), o('FUNC_EXIST', function() {
return true;
})
],
Arguments: [
o('CALL_START CALL_END', function() {
return [];
}), o('CALL_START ArgList OptComma CALL_END', function() {
return $2;
})
],
This: [
o('THIS', function() {
return new Value(new Literal('this'));
}), o('@', function() {
return new Value(new Literal('this'));
})
],
ThisProperty: [
o('@ Identifier', function() {
return new Value(new Literal('this'), [new Access($2)], 'this');
})
],
Array: [
o('[ ]', function() {
return new Arr([]);
}), o('[ ArgList OptComma ]', function() {
return new Arr($2);
})
],
RangeDots: [
o('..', function() {
return 'inclusive';
}), o('...', function() {
return 'exclusive';
})
],
Range: [
o('[ Expression RangeDots Expression ]', function() {
return new Range($2, $4, $3);
})
],
Slice: [
o('Expression RangeDots Expression', function() {
return new Range($1, $3, $2);
}), o('Expression RangeDots', function() {
return new Range($1, null, $2);
}), o('RangeDots Expression', function() {
return new Range(null, $2, $1);
})
],
ArgList: [
o('Arg', function() {
return [$1];
}), o('ArgList , Arg', function() {
return $1.concat($3);
}), o('ArgList OptComma TERMINATOR Arg', function() {
return $1.concat($4);
}), o('INDENT ArgList OptComma OUTDENT', function() {
return $2;
}), o('ArgList OptComma INDENT ArgList OptComma OUTDENT', function() {
return $1.concat($4);
})
],
Arg: [o('Expression'), o('Splat')],
SimpleArgs: [
o('Expression'), o('SimpleArgs , Expression', function() {
return [].concat($1, $3);
})
],
Try: [
o('TRY Block', function() {
return new Try($2);
}), o('TRY Block Catch', function() {
return new Try($2, $3[0], $3[1]);
}), o('TRY Block FINALLY Block', function() {
return new Try($2, null, null, $4);
}), o('TRY Block Catch FINALLY Block', function() {
return new Try($2, $3[0], $3[1], $5);
})
],
Catch: [
o('CATCH Identifier Block', function() {
return [$2, $3];
})
],
Throw: [
o('THROW Expression', function() {
return new Throw($2);
})
],
Parenthetical: [
o('( Body )', function() {
return new Parens($2);
}), o('( INDENT Body OUTDENT )', function() {
return new Parens($3);
})
],
WhileSource: [
o('WHILE Expression', function() {
return new While($2);
}), o('WHILE Expression WHEN Expression', function() {
return new While($2, {
guard: $4
});
}), o('UNTIL Expression', function() {
return new While($2, {
invert: true
});
}), o('UNTIL Expression WHEN Expression', function() {
return new While($2, {
invert: true,
guard: $4
});
})
],
While: [
o('WhileSource Block', function() {
return $1.addBody($2);
}), o('Statement WhileSource', function() {
return $2.addBody(Block.wrap([$1]));
}), o('Expression WhileSource', function() {
return $2.addBody(Block.wrap([$1]));
}), o('Loop', function() {
return $1;
})
],
Loop: [
o('LOOP Block', function() {
return new While(new Literal('true')).addBody($2);
}), o('LOOP Expression', function() {
return new While(new Literal('true')).addBody(Block.wrap([$2]));
})
],
For: [
o('Statement ForBody', function() {
return new For($1, $2);
}), o('Expression ForBody', function() {
return new For($1, $2);
}), o('ForBody Block', function() {
return new For($2, $1);
})
],
ForBody: [
o('FOR Range', function() {
return {
source: new Value($2)
};
}), o('ForStart ForSource', function() {
$2.own = $1.own;
$2.name = $1[0];
$2.index = $1[1];
return $2;
})
],
ForStart: [
o('FOR ForVariables', function() {
return $2;
}), o('FOR OWN ForVariables', function() {
$3.own = true;
return $3;
})
],
ForValue: [
o('Identifier'), o('Array', function() {
return new Value($1);
}), o('Object', function() {
return new Value($1);
})
],
ForVariables: [
o('ForValue', function() {
return [$1];
}), o('ForValue , ForValue', function() {
return [$1, $3];
})
],
ForSource: [
o('FORIN Expression', function() {
return {
source: $2
};
}), o('FOROF Expression', function() {
return {
source: $2,
object: true
};
}), o('FORIN Expression WHEN Expression', function() {
return {
source: $2,
guard: $4
};
}), o('FOROF Expression WHEN Expression', function() {
return {
source: $2,
guard: $4,
object: true
};
}), o('FORIN Expression BY Expression', function() {
return {
source: $2,
step: $4
};
}), o('FORIN Expression WHEN Expression BY Expression', function() {
return {
source: $2,
guard: $4,
step: $6
};
}), o('FORIN Expression BY Expression WHEN Expression', function() {
return {
source: $2,
step: $4,
guard: $6
};
})
],
Switch: [
o('SWITCH Expression INDENT Whens OUTDENT', function() {
return new Switch($2, $4);
}), o('SWITCH Expression INDENT Whens ELSE Block OUTDENT', function() {
return new Switch($2, $4, $6);
}), o('SWITCH INDENT Whens OUTDENT', function() {
return new Switch(null, $3);
}), o('SWITCH INDENT Whens ELSE Block OUTDENT', function() {
return new Switch(null, $3, $5);
})
],
Whens: [
o('When'), o('Whens When', function() {
return $1.concat($2);
})
],
When: [
o('LEADING_WHEN SimpleArgs Block', function() {
return [[$2, $3]];
}), o('LEADING_WHEN SimpleArgs Block TERMINATOR', function() {
return [[$2, $3]];
})
],
IfBlock: [
o('IF Expression Block', function() {
return new If($2, $3, {
type: $1
});
}), o('IfBlock ELSE IF Expression Block', function() {
return $1.addElse(new If($4, $5, {
type: $3
}));
})
],
If: [
o('IfBlock'), o('IfBlock ELSE Block', function() {
return $1.addElse($3);
}), o('Statement POST_IF Expression', function() {
return new If($3, Block.wrap([$1]), {
type: $2,
statement: true
});
}), o('Expression POST_IF Expression', function() {
return new If($3, Block.wrap([$1]), {
type: $2,
statement: true
});
})
],
Operation: [
o('UNARY Expression', function() {
return new Op($1, $2);
}), o('- Expression', (function() {
return new Op('-', $2);
}), {
prec: 'UNARY'
}), o('+ Expression', (function() {
return new Op('+', $2);
}), {
prec: 'UNARY'
}), o('-- SimpleAssignable', function() {
return new Op('--', $2);
}), o('++ SimpleAssignable', function() {
return new Op('++', $2);
}), o('SimpleAssignable --', function() {
return new Op('--', $1, null, true);
}), o('SimpleAssignable ++', function() {
return new Op('++', $1, null, true);
}), o('Expression ?', function() {
return new Existence($1);
}), o('Expression + Expression', function() {
return new Op('+', $1, $3);
}), o('Expression - Expression', function() {
return new Op('-', $1, $3);
}), o('Expression MATH Expression', function() {
return new Op($2, $1, $3);
}), o('Expression SHIFT Expression', function() {
return new Op($2, $1, $3);
}), o('Expression COMPARE Expression', function() {
return new Op($2, $1, $3);
}), o('Expression LOGIC Expression', function() {
return new Op($2, $1, $3);
}), o('Expression RELATION Expression', function() {
if ($2.charAt(0) === '!') {
return new Op($2.slice(1), $1, $3).invert();
} else {
return new Op($2, $1, $3);
}
}), o('SimpleAssignable COMPOUND_ASSIGN\
Expression', function() {
return new Assign($1, $3, $2);
}), o('SimpleAssignable COMPOUND_ASSIGN\
INDENT Expression OUTDENT', function() {
return new Assign($1, $4, $2);
}), o('SimpleAssignable EXTENDS Expression', function() {
return new Extends($1, $3);
})
]
};
operators = [['left', '.', '?.', '::'], ['left', 'CALL_START', 'CALL_END'], ['nonassoc', '++', '--'], ['left', '?'], ['right', 'UNARY'], ['left', 'MATH'], ['left', '+', '-'], ['left', 'SHIFT'], ['left', 'RELATION'], ['left', 'COMPARE'], ['left', 'LOGIC'], ['nonassoc', 'INDENT', 'OUTDENT'], ['right', '=', ':', 'COMPOUND_ASSIGN', 'RETURN', 'THROW', 'EXTENDS'], ['right', 'FORIN', 'FOROF', 'BY', 'WHEN'], ['right', 'IF', 'ELSE', 'FOR', 'DO', 'WHILE', 'UNTIL', 'LOOP', 'SUPER', 'CLASS'], ['right', 'POST_IF']];
tokens = [];
for (name in grammar) {
alternatives = grammar[name];
grammar[name] = (function() {
var _i, _j, _len, _len2, _ref, _results;
_results = [];
for (_i = 0, _len = alternatives.length; _i < _len; _i++) {
alt = alternatives[_i];
_ref = alt[0].split(' ');
for (_j = 0, _len2 = _ref.length; _j < _len2; _j++) {
token = _ref[_j];
if (!grammar[token]) {
tokens.push(token);
}
}
if (name === 'Root') {
alt[1] = "return " + alt[1];
}
_results.push(alt);
}
return _results;
})();
}
exports.parser = new Parser({
tokens: tokens.join(' '),
bnf: grammar,
operators: operators.reverse(),
startSymbol: 'Root'
});
}).call(this);

66
bin/node_modules/coffee-script/lib/helpers.js generated vendored Normal file
View File

@ -0,0 +1,66 @@
(function() {
var extend, flatten;
exports.starts = function(string, literal, start) {
return literal === string.substr(start, literal.length);
};
exports.ends = function(string, literal, back) {
var len;
len = literal.length;
return literal === string.substr(string.length - len - (back || 0), len);
};
exports.compact = function(array) {
var item, _i, _len, _results;
_results = [];
for (_i = 0, _len = array.length; _i < _len; _i++) {
item = array[_i];
if (item) {
_results.push(item);
}
}
return _results;
};
exports.count = function(string, substr) {
var num, pos;
num = pos = 0;
if (!substr.length) {
return 1 / 0;
}
while (pos = 1 + string.indexOf(substr, pos)) {
num++;
}
return num;
};
exports.merge = function(options, overrides) {
return extend(extend({}, options), overrides);
};
extend = exports.extend = function(object, properties) {
var key, val;
for (key in properties) {
val = properties[key];
object[key] = val;
}
return object;
};
exports.flatten = flatten = function(array) {
var element, flattened, _i, _len;
flattened = [];
for (_i = 0, _len = array.length; _i < _len; _i++) {
element = array[_i];
if (element instanceof Array) {
flattened = flattened.concat(flatten(element));
} else {
flattened.push(element);
}
}
return flattened;
};
exports.del = function(obj, key) {
var val;
val = obj[key];
delete obj[key];
return val;
};
exports.last = function(array, back) {
return array[array.length - (back || 0) - 1];
};
}).call(this);

8
bin/node_modules/coffee-script/lib/index.js generated vendored Normal file
View File

@ -0,0 +1,8 @@
(function() {
var key, val, _ref;
_ref = require('./coffee-script');
for (key in _ref) {
val = _ref[key];
exports[key] = val;
}
}).call(this);

656
bin/node_modules/coffee-script/lib/lexer.js generated vendored Normal file
View File

@ -0,0 +1,656 @@
(function() {
var ASSIGNED, BOOL, CALLABLE, CODE, COFFEE_ALIASES, COFFEE_ALIAS_MAP, COFFEE_KEYWORDS, COMMENT, COMPARE, COMPOUND_ASSIGN, HEREDOC, HEREDOC_ILLEGAL, HEREDOC_INDENT, HEREGEX, HEREGEX_OMIT, IDENTIFIER, INDEXABLE, JSTOKEN, JS_FORBIDDEN, JS_KEYWORDS, LINE_BREAK, LINE_CONTINUER, LOGIC, Lexer, MATH, MULTILINER, MULTI_DENT, NOT_REGEX, NOT_SPACED_REGEX, NO_NEWLINE, NUMBER, OPERATOR, REGEX, RELATION, RESERVED, Rewriter, SHIFT, SIMPLESTR, TRAILING_SPACES, UNARY, WHITESPACE, compact, count, key, last, starts, _ref;
var __indexOf = Array.prototype.indexOf || function(item) {
for (var i = 0, l = this.length; i < l; i++) {
if (this[i] === item) return i;
}
return -1;
};
Rewriter = require('./rewriter').Rewriter;
_ref = require('./helpers'), count = _ref.count, starts = _ref.starts, compact = _ref.compact, last = _ref.last;
exports.Lexer = Lexer = (function() {
function Lexer() {}
Lexer.prototype.tokenize = function(code, opts) {
var i;
if (opts == null) {
opts = {};
}
if (WHITESPACE.test(code)) {
code = "\n" + code;
}
code = code.replace(/\r/g, '').replace(TRAILING_SPACES, '');
this.code = code;
this.line = opts.line || 0;
this.indent = 0;
this.indebt = 0;
this.outdebt = 0;
this.indents = [];
this.tokens = [];
i = 0;
while (this.chunk = code.slice(i)) {
i += this.identifierToken() || this.commentToken() || this.whitespaceToken() || this.lineToken() || this.heredocToken() || this.stringToken() || this.numberToken() || this.regexToken() || this.jsToken() || this.literalToken();
}
this.closeIndentation();
if (opts.rewrite === false) {
return this.tokens;
}
return (new Rewriter).rewrite(this.tokens);
};
Lexer.prototype.identifierToken = function() {
var colon, forcedIdentifier, id, input, match, prev, tag, _ref2, _ref3;
if (!(match = IDENTIFIER.exec(this.chunk))) {
return 0;
}
input = match[0], id = match[1], colon = match[2];
if (id === 'own' && this.tag() === 'FOR') {
this.token('OWN', id);
return id.length;
}
forcedIdentifier = colon || (prev = last(this.tokens)) && (((_ref2 = prev[0]) === '.' || _ref2 === '?.' || _ref2 === '::') || !prev.spaced && prev[0] === '@');
tag = 'IDENTIFIER';
if (!forcedIdentifier && (__indexOf.call(JS_KEYWORDS, id) >= 0 || __indexOf.call(COFFEE_KEYWORDS, id) >= 0)) {
tag = id.toUpperCase();
if (tag === 'WHEN' && (_ref3 = this.tag(), __indexOf.call(LINE_BREAK, _ref3) >= 0)) {
tag = 'LEADING_WHEN';
} else if (tag === 'FOR') {
this.seenFor = true;
} else if (tag === 'UNLESS') {
tag = 'IF';
} else if (__indexOf.call(UNARY, tag) >= 0) {
tag = 'UNARY';
} else if (__indexOf.call(RELATION, tag) >= 0) {
if (tag !== 'INSTANCEOF' && this.seenFor) {
tag = 'FOR' + tag;
this.seenFor = false;
} else {
tag = 'RELATION';
if (this.value() === '!') {
this.tokens.pop();
id = '!' + id;
}
}
}
}
if (__indexOf.call(JS_FORBIDDEN, id) >= 0) {
if (forcedIdentifier) {
tag = 'IDENTIFIER';
id = new String(id);
id.reserved = true;
} else if (__indexOf.call(RESERVED, id) >= 0) {
this.identifierError(id);
}
}
if (!forcedIdentifier) {
if (__indexOf.call(COFFEE_ALIASES, id) >= 0) {
id = COFFEE_ALIAS_MAP[id];
}
tag = (function() {
switch (id) {
case '!':
return 'UNARY';
case '==':
case '!=':
return 'COMPARE';
case '&&':
case '||':
return 'LOGIC';
case 'true':
case 'false':
case 'null':
case 'undefined':
return 'BOOL';
case 'break':
case 'continue':
case 'debugger':
return 'STATEMENT';
default:
return tag;
}
})();
}
this.token(tag, id);
if (colon) {
this.token(':', ':');
}
return input.length;
};
Lexer.prototype.numberToken = function() {
var match, number;
if (!(match = NUMBER.exec(this.chunk))) {
return 0;
}
number = match[0];
this.token('NUMBER', number);
return number.length;
};
Lexer.prototype.stringToken = function() {
var match, string;
switch (this.chunk.charAt(0)) {
case "'":
if (!(match = SIMPLESTR.exec(this.chunk))) {
return 0;
}
this.token('STRING', (string = match[0]).replace(MULTILINER, '\\\n'));
break;
case '"':
if (!(string = this.balancedString(this.chunk, '"'))) {
return 0;
}
if (0 < string.indexOf('#{', 1)) {
this.interpolateString(string.slice(1, -1));
} else {
this.token('STRING', this.escapeLines(string));
}
break;
default:
return 0;
}
this.line += count(string, '\n');
return string.length;
};
Lexer.prototype.heredocToken = function() {
var doc, heredoc, match, quote;
if (!(match = HEREDOC.exec(this.chunk))) {
return 0;
}
heredoc = match[0];
quote = heredoc.charAt(0);
doc = this.sanitizeHeredoc(match[2], {
quote: quote,
indent: null
});
if (quote === '"' && 0 <= doc.indexOf('#{')) {
this.interpolateString(doc, {
heredoc: true
});
} else {
this.token('STRING', this.makeString(doc, quote, true));
}
this.line += count(heredoc, '\n');
return heredoc.length;
};
Lexer.prototype.commentToken = function() {
var comment, here, match;
if (!(match = this.chunk.match(COMMENT))) {
return 0;
}
comment = match[0], here = match[1];
if (here) {
this.token('HERECOMMENT', this.sanitizeHeredoc(here, {
herecomment: true,
indent: Array(this.indent + 1).join(' ')
}));
this.token('TERMINATOR', '\n');
}
this.line += count(comment, '\n');
return comment.length;
};
Lexer.prototype.jsToken = function() {
var match, script;
if (!(this.chunk.charAt(0) === '`' && (match = JSTOKEN.exec(this.chunk)))) {
return 0;
}
this.token('JS', (script = match[0]).slice(1, -1));
return script.length;
};
Lexer.prototype.regexToken = function() {
var length, match, prev, regex, _ref2;
if (this.chunk.charAt(0) !== '/') {
return 0;
}
if (match = HEREGEX.exec(this.chunk)) {
length = this.heregexToken(match);
this.line += count(match[0], '\n');
return length;
}
prev = last(this.tokens);
if (prev && (_ref2 = prev[0], __indexOf.call((prev.spaced ? NOT_REGEX : NOT_SPACED_REGEX), _ref2) >= 0)) {
return 0;
}
if (!(match = REGEX.exec(this.chunk))) {
return 0;
}
regex = match[0];
this.token('REGEX', regex === '//' ? '/(?:)/' : regex);
return regex.length;
};
Lexer.prototype.heregexToken = function(match) {
var body, flags, heregex, re, tag, tokens, value, _i, _len, _ref2, _ref3, _ref4, _ref5;
heregex = match[0], body = match[1], flags = match[2];
if (0 > body.indexOf('#{')) {
re = body.replace(HEREGEX_OMIT, '').replace(/\//g, '\\/');
this.token('REGEX', "/" + (re || '(?:)') + "/" + flags);
return heregex.length;
}
this.token('IDENTIFIER', 'RegExp');
this.tokens.push(['CALL_START', '(']);
tokens = [];
_ref2 = this.interpolateString(body, {
regex: true
});
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
_ref3 = _ref2[_i], tag = _ref3[0], value = _ref3[1];
if (tag === 'TOKENS') {
tokens.push.apply(tokens, value);
} else {
if (!(value = value.replace(HEREGEX_OMIT, ''))) {
continue;
}
value = value.replace(/\\/g, '\\\\');
tokens.push(['STRING', this.makeString(value, '"', true)]);
}
tokens.push(['+', '+']);
}
tokens.pop();
if (((_ref4 = tokens[0]) != null ? _ref4[0] : void 0) !== 'STRING') {
this.tokens.push(['STRING', '""'], ['+', '+']);
}
(_ref5 = this.tokens).push.apply(_ref5, tokens);
if (flags) {
this.tokens.push([',', ','], ['STRING', '"' + flags + '"']);
}
this.token(')', ')');
return heregex.length;
};
Lexer.prototype.lineToken = function() {
var diff, indent, match, noNewlines, prev, size;
if (!(match = MULTI_DENT.exec(this.chunk))) {
return 0;
}
indent = match[0];
this.line += count(indent, '\n');
prev = last(this.tokens, 1);
size = indent.length - 1 - indent.lastIndexOf('\n');
noNewlines = this.unfinished();
if (size - this.indebt === this.indent) {
if (noNewlines) {
this.suppressNewlines();
} else {
this.newlineToken();
}
return indent.length;
}
if (size > this.indent) {
if (noNewlines) {
this.indebt = size - this.indent;
this.suppressNewlines();
return indent.length;
}
diff = size - this.indent + this.outdebt;
this.token('INDENT', diff);
this.indents.push(diff);
this.outdebt = this.indebt = 0;
} else {
this.indebt = 0;
this.outdentToken(this.indent - size, noNewlines);
}
this.indent = size;
return indent.length;
};
Lexer.prototype.outdentToken = function(moveOut, noNewlines, close) {
var dent, len;
while (moveOut > 0) {
len = this.indents.length - 1;
if (this.indents[len] === void 0) {
moveOut = 0;
} else if (this.indents[len] === this.outdebt) {
moveOut -= this.outdebt;
this.outdebt = 0;
} else if (this.indents[len] < this.outdebt) {
this.outdebt -= this.indents[len];
moveOut -= this.indents[len];
} else {
dent = this.indents.pop() - this.outdebt;
moveOut -= dent;
this.outdebt = 0;
this.token('OUTDENT', dent);
}
}
if (dent) {
this.outdebt -= moveOut;
}
if (!(this.tag() === 'TERMINATOR' || noNewlines)) {
this.token('TERMINATOR', '\n');
}
return this;
};
Lexer.prototype.whitespaceToken = function() {
var match, nline, prev;
if (!((match = WHITESPACE.exec(this.chunk)) || (nline = this.chunk.charAt(0) === '\n'))) {
return 0;
}
prev = last(this.tokens);
if (prev) {
prev[match ? 'spaced' : 'newLine'] = true;
}
if (match) {
return match[0].length;
} else {
return 0;
}
};
Lexer.prototype.newlineToken = function() {
if (this.tag() !== 'TERMINATOR') {
this.token('TERMINATOR', '\n');
}
return this;
};
Lexer.prototype.suppressNewlines = function() {
if (this.value() === '\\') {
this.tokens.pop();
}
return this;
};
Lexer.prototype.literalToken = function() {
var match, prev, tag, value, _ref2, _ref3, _ref4, _ref5;
if (match = OPERATOR.exec(this.chunk)) {
value = match[0];
if (CODE.test(value)) {
this.tagParameters();
}
} else {
value = this.chunk.charAt(0);
}
tag = value;
prev = last(this.tokens);
if (value === '=' && prev) {
if (!prev[1].reserved && (_ref2 = prev[1], __indexOf.call(JS_FORBIDDEN, _ref2) >= 0)) {
this.assignmentError();
}
if ((_ref3 = prev[1]) === '||' || _ref3 === '&&') {
prev[0] = 'COMPOUND_ASSIGN';
prev[1] += '=';
return value.length;
}
}
if (value === ';') {
tag = 'TERMINATOR';
} else if (__indexOf.call(MATH, value) >= 0) {
tag = 'MATH';
} else if (__indexOf.call(COMPARE, value) >= 0) {
tag = 'COMPARE';
} else if (__indexOf.call(COMPOUND_ASSIGN, value) >= 0) {
tag = 'COMPOUND_ASSIGN';
} else if (__indexOf.call(UNARY, value) >= 0) {
tag = 'UNARY';
} else if (__indexOf.call(SHIFT, value) >= 0) {
tag = 'SHIFT';
} else if (__indexOf.call(LOGIC, value) >= 0 || value === '?' && (prev != null ? prev.spaced : void 0)) {
tag = 'LOGIC';
} else if (prev && !prev.spaced) {
if (value === '(' && (_ref4 = prev[0], __indexOf.call(CALLABLE, _ref4) >= 0)) {
if (prev[0] === '?') {
prev[0] = 'FUNC_EXIST';
}
tag = 'CALL_START';
} else if (value === '[' && (_ref5 = prev[0], __indexOf.call(INDEXABLE, _ref5) >= 0)) {
tag = 'INDEX_START';
switch (prev[0]) {
case '?':
prev[0] = 'INDEX_SOAK';
break;
case '::':
prev[0] = 'INDEX_PROTO';
}
}
}
this.token(tag, value);
return value.length;
};
Lexer.prototype.sanitizeHeredoc = function(doc, options) {
var attempt, herecomment, indent, match, _ref2;
indent = options.indent, herecomment = options.herecomment;
if (herecomment) {
if (HEREDOC_ILLEGAL.test(doc)) {
throw new Error("block comment cannot contain \"*/\", starting on line " + (this.line + 1));
}
if (doc.indexOf('\n') <= 0) {
return doc;
}
} else {
while (match = HEREDOC_INDENT.exec(doc)) {
attempt = match[1];
if (indent === null || (0 < (_ref2 = attempt.length) && _ref2 < indent.length)) {
indent = attempt;
}
}
}
if (indent) {
doc = doc.replace(RegExp("\\n" + indent, "g"), '\n');
}
if (!herecomment) {
doc = doc.replace(/^\n/, '');
}
return doc;
};
Lexer.prototype.tagParameters = function() {
var i, stack, tok, tokens;
if (this.tag() !== ')') {
return this;
}
stack = [];
tokens = this.tokens;
i = tokens.length;
tokens[--i][0] = 'PARAM_END';
while (tok = tokens[--i]) {
switch (tok[0]) {
case ')':
stack.push(tok);
break;
case '(':
case 'CALL_START':
if (stack.length) {
stack.pop();
} else if (tok[0] === '(') {
tok[0] = 'PARAM_START';
return this;
} else {
return this;
}
}
}
return this;
};
Lexer.prototype.closeIndentation = function() {
return this.outdentToken(this.indent);
};
Lexer.prototype.identifierError = function(word) {
throw SyntaxError("Reserved word \"" + word + "\" on line " + (this.line + 1));
};
Lexer.prototype.assignmentError = function() {
throw SyntaxError("Reserved word \"" + (this.value()) + "\" on line " + (this.line + 1) + " can't be assigned");
};
Lexer.prototype.balancedString = function(str, end) {
var i, letter, match, prev, stack, _ref2;
stack = [end];
for (i = 1, _ref2 = str.length; 1 <= _ref2 ? i < _ref2 : i > _ref2; 1 <= _ref2 ? i++ : i--) {
switch (letter = str.charAt(i)) {
case '\\':
i++;
continue;
case end:
stack.pop();
if (!stack.length) {
return str.slice(0, i + 1);
}
end = stack[stack.length - 1];
continue;
}
if (end === '}' && (letter === '"' || letter === "'")) {
stack.push(end = letter);
} else if (end === '}' && letter === '/' && (match = HEREGEX.exec(str.slice(i)) || REGEX.exec(str.slice(i)))) {
i += match[0].length - 1;
} else if (end === '}' && letter === '{') {
stack.push(end = '}');
} else if (end === '"' && prev === '#' && letter === '{') {
stack.push(end = '}');
}
prev = letter;
}
throw new Error("missing " + (stack.pop()) + ", starting on line " + (this.line + 1));
};
Lexer.prototype.interpolateString = function(str, options) {
var expr, heredoc, i, inner, interpolated, len, letter, nested, pi, regex, tag, tokens, value, _len, _ref2, _ref3, _ref4;
if (options == null) {
options = {};
}
heredoc = options.heredoc, regex = options.regex;
tokens = [];
pi = 0;
i = -1;
while (letter = str.charAt(i += 1)) {
if (letter === '\\') {
i += 1;
continue;
}
if (!(letter === '#' && str.charAt(i + 1) === '{' && (expr = this.balancedString(str.slice(i + 1), '}')))) {
continue;
}
if (pi < i) {
tokens.push(['NEOSTRING', str.slice(pi, i)]);
}
inner = expr.slice(1, -1);
if (inner.length) {
nested = new Lexer().tokenize(inner, {
line: this.line,
rewrite: false
});
nested.pop();
if (((_ref2 = nested[0]) != null ? _ref2[0] : void 0) === 'TERMINATOR') {
nested.shift();
}
if (len = nested.length) {
if (len > 1) {
nested.unshift(['(', '(']);
nested.push([')', ')']);
}
tokens.push(['TOKENS', nested]);
}
}
i += expr.length;
pi = i + 1;
}
if ((i > pi && pi < str.length)) {
tokens.push(['NEOSTRING', str.slice(pi)]);
}
if (regex) {
return tokens;
}
if (!tokens.length) {
return this.token('STRING', '""');
}
if (tokens[0][0] !== 'NEOSTRING') {
tokens.unshift(['', '']);
}
if (interpolated = tokens.length > 1) {
this.token('(', '(');
}
for (i = 0, _len = tokens.length; i < _len; i++) {
_ref3 = tokens[i], tag = _ref3[0], value = _ref3[1];
if (i) {
this.token('+', '+');
}
if (tag === 'TOKENS') {
(_ref4 = this.tokens).push.apply(_ref4, value);
} else {
this.token('STRING', this.makeString(value, '"', heredoc));
}
}
if (interpolated) {
this.token(')', ')');
}
return tokens;
};
Lexer.prototype.token = function(tag, value) {
return this.tokens.push([tag, value, this.line]);
};
Lexer.prototype.tag = function(index, tag) {
var tok;
return (tok = last(this.tokens, index)) && (tag ? tok[0] = tag : tok[0]);
};
Lexer.prototype.value = function(index, val) {
var tok;
return (tok = last(this.tokens, index)) && (val ? tok[1] = val : tok[1]);
};
Lexer.prototype.unfinished = function() {
var prev, value;
return LINE_CONTINUER.test(this.chunk) || (prev = last(this.tokens, 1)) && prev[0] !== '.' && (value = this.value()) && !value.reserved && NO_NEWLINE.test(value) && !CODE.test(value) && !ASSIGNED.test(this.chunk);
};
Lexer.prototype.escapeLines = function(str, heredoc) {
return str.replace(MULTILINER, heredoc ? '\\n' : '');
};
Lexer.prototype.makeString = function(body, quote, heredoc) {
if (!body) {
return quote + quote;
}
body = body.replace(/\\([\s\S])/g, function(match, contents) {
if (contents === '\n' || contents === quote) {
return contents;
} else {
return match;
}
});
body = body.replace(RegExp("" + quote, "g"), '\\$&');
return quote + this.escapeLines(body, heredoc) + quote;
};
return Lexer;
})();
JS_KEYWORDS = ['true', 'false', 'null', 'this', 'new', 'delete', 'typeof', 'in', 'instanceof', 'return', 'throw', 'break', 'continue', 'debugger', 'if', 'else', 'switch', 'for', 'while', 'do', 'try', 'catch', 'finally', 'class', 'extends', 'super'];
COFFEE_KEYWORDS = ['undefined', 'then', 'unless', 'until', 'loop', 'of', 'by', 'when'];
COFFEE_ALIAS_MAP = {
and: '&&',
or: '||',
is: '==',
isnt: '!=',
not: '!',
yes: 'true',
no: 'false',
on: 'true',
off: 'false'
};
COFFEE_ALIASES = (function() {
var _results;
_results = [];
for (key in COFFEE_ALIAS_MAP) {
_results.push(key);
}
return _results;
})();
COFFEE_KEYWORDS = COFFEE_KEYWORDS.concat(COFFEE_ALIASES);
RESERVED = ['case', 'default', 'function', 'var', 'void', 'with', 'const', 'let', 'enum', 'export', 'import', 'native', '__hasProp', '__extends', '__slice', '__bind', '__indexOf'];
JS_FORBIDDEN = JS_KEYWORDS.concat(RESERVED);
exports.RESERVED = RESERVED.concat(JS_KEYWORDS).concat(COFFEE_KEYWORDS);
IDENTIFIER = /^([$A-Za-z_\x7f-\uffff][$\w\x7f-\uffff]*)([^\n\S]*:(?!:))?/;
NUMBER = /^0x[\da-f]+|^\d*\.?\d+(?:e[+-]?\d+)?/i;
HEREDOC = /^("""|''')([\s\S]*?)(?:\n[^\n\S]*)?\1/;
OPERATOR = /^(?:[-=]>|[-+*\/%<>&|^!?=]=|>>>=?|([-+:])\1|([&|<>])\2=?|\?\.|\.{2,3})/;
WHITESPACE = /^[^\n\S]+/;
COMMENT = /^###([^#][\s\S]*?)(?:###[^\n\S]*|(?:###)?$)|^(?:\s*#(?!##[^#]).*)+/;
CODE = /^[-=]>/;
MULTI_DENT = /^(?:\n[^\n\S]*)+/;
SIMPLESTR = /^'[^\\']*(?:\\.[^\\']*)*'/;
JSTOKEN = /^`[^\\`]*(?:\\.[^\\`]*)*`/;
REGEX = /^\/(?![\s=])[^[\/\n\\]*(?:(?:\\[\s\S]|\[[^\]\n\\]*(?:\\[\s\S][^\]\n\\]*)*])[^[\/\n\\]*)*\/[imgy]{0,4}(?!\w)/;
HEREGEX = /^\/{3}([\s\S]+?)\/{3}([imgy]{0,4})(?!\w)/;
HEREGEX_OMIT = /\s+(?:#.*)?/g;
MULTILINER = /\n/g;
HEREDOC_INDENT = /\n+([^\n\S]*)/g;
HEREDOC_ILLEGAL = /\*\//;
ASSIGNED = /^\s*@?([$A-Za-z_][$\w\x7f-\uffff]*|['"].*['"])[^\n\S]*?[:=][^:=>]/;
LINE_CONTINUER = /^\s*(?:,|\??\.(?![.\d])|::)/;
TRAILING_SPACES = /\s+$/;
NO_NEWLINE = /^(?:[-+*&|\/%=<>!.\\][<>=&|]*|and|or|is(?:nt)?|n(?:ot|ew)|delete|typeof|instanceof)$/;
COMPOUND_ASSIGN = ['-=', '+=', '/=', '*=', '%=', '||=', '&&=', '?=', '<<=', '>>=', '>>>=', '&=', '^=', '|='];
UNARY = ['!', '~', 'NEW', 'TYPEOF', 'DELETE', 'DO'];
LOGIC = ['&&', '||', '&', '|', '^'];
SHIFT = ['<<', '>>', '>>>'];
COMPARE = ['==', '!=', '<', '>', '<=', '>='];
MATH = ['*', '/', '%'];
RELATION = ['IN', 'OF', 'INSTANCEOF'];
BOOL = ['TRUE', 'FALSE', 'NULL', 'UNDEFINED'];
NOT_REGEX = ['NUMBER', 'REGEX', 'BOOL', '++', '--', ']'];
NOT_SPACED_REGEX = NOT_REGEX.concat(')', '}', 'THIS', 'IDENTIFIER', 'STRING');
CALLABLE = ['IDENTIFIER', 'STRING', 'REGEX', ')', ']', '}', '?', '::', '@', 'THIS', 'SUPER'];
INDEXABLE = CALLABLE.concat('NUMBER', 'BOOL');
LINE_BREAK = ['INDENT', 'OUTDENT', 'TERMINATOR'];
}).call(this);

2289
bin/node_modules/coffee-script/lib/nodes.js generated vendored Normal file

File diff suppressed because it is too large Load Diff

111
bin/node_modules/coffee-script/lib/optparse.js generated vendored Executable file
View File

@ -0,0 +1,111 @@
(function() {
var LONG_FLAG, MULTI_FLAG, OPTIONAL, OptionParser, SHORT_FLAG, buildRule, buildRules, normalizeArguments;
exports.OptionParser = OptionParser = (function() {
function OptionParser(rules, banner) {
this.banner = banner;
this.rules = buildRules(rules);
}
OptionParser.prototype.parse = function(args) {
var arg, i, isOption, matchedRule, options, rule, value, _i, _len, _len2, _ref;
options = {
arguments: [],
literals: []
};
args = normalizeArguments(args);
for (i = 0, _len = args.length; i < _len; i++) {
arg = args[i];
if (arg === '--') {
options.literals = args.slice(i + 1);
break;
}
isOption = !!(arg.match(LONG_FLAG) || arg.match(SHORT_FLAG));
matchedRule = false;
_ref = this.rules;
for (_i = 0, _len2 = _ref.length; _i < _len2; _i++) {
rule = _ref[_i];
if (rule.shortFlag === arg || rule.longFlag === arg) {
value = rule.hasArgument ? args[i += 1] : true;
options[rule.name] = rule.isList ? (options[rule.name] || []).concat(value) : value;
matchedRule = true;
break;
}
}
if (isOption && !matchedRule) {
throw new Error("unrecognized option: " + arg);
}
if (!isOption) {
options.arguments = args.slice(i);
break;
}
}
return options;
};
OptionParser.prototype.help = function() {
var letPart, lines, rule, spaces, _i, _len, _ref;
lines = [];
if (this.banner) {
lines.unshift("" + this.banner + "\n");
}
_ref = this.rules;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
rule = _ref[_i];
spaces = 15 - rule.longFlag.length;
spaces = spaces > 0 ? Array(spaces + 1).join(' ') : '';
letPart = rule.shortFlag ? rule.shortFlag + ', ' : ' ';
lines.push(' ' + letPart + rule.longFlag + spaces + rule.description);
}
return "\n" + (lines.join('\n')) + "\n";
};
return OptionParser;
})();
LONG_FLAG = /^(--\w[\w\-]+)/;
SHORT_FLAG = /^(-\w)/;
MULTI_FLAG = /^-(\w{2,})/;
OPTIONAL = /\[(\w+(\*?))\]/;
buildRules = function(rules) {
var tuple, _i, _len, _results;
_results = [];
for (_i = 0, _len = rules.length; _i < _len; _i++) {
tuple = rules[_i];
if (tuple.length < 3) {
tuple.unshift(null);
}
_results.push(buildRule.apply(null, tuple));
}
return _results;
};
buildRule = function(shortFlag, longFlag, description, options) {
var match;
if (options == null) {
options = {};
}
match = longFlag.match(OPTIONAL);
longFlag = longFlag.match(LONG_FLAG)[1];
return {
name: longFlag.substr(2),
shortFlag: shortFlag,
longFlag: longFlag,
description: description,
hasArgument: !!(match && match[1]),
isList: !!(match && match[2])
};
};
normalizeArguments = function(args) {
var arg, l, match, result, _i, _j, _len, _len2, _ref;
args = args.slice(0);
result = [];
for (_i = 0, _len = args.length; _i < _len; _i++) {
arg = args[_i];
if (match = arg.match(MULTI_FLAG)) {
_ref = match[1].split('');
for (_j = 0, _len2 = _ref.length; _j < _len2; _j++) {
l = _ref[_j];
result.push('-' + l);
}
} else {
result.push(arg);
}
}
return result;
};
}).call(this);

676
bin/node_modules/coffee-script/lib/parser.js generated vendored Executable file

File diff suppressed because one or more lines are too long

123
bin/node_modules/coffee-script/lib/repl.js generated vendored Normal file
View File

@ -0,0 +1,123 @@
(function() {
var ACCESSOR, CoffeeScript, Module, REPL_PROMPT, REPL_PROMPT_CONTINUATION, SIMPLEVAR, Script, autocomplete, backlog, completeAttribute, completeVariable, enableColours, error, g, getCompletions, inspect, nonContextGlobals, readline, repl, run, sandbox, stdin, stdout, _i, _len;
CoffeeScript = require('./coffee-script');
readline = require('readline');
inspect = require('util').inspect;
Script = require('vm').Script;
Module = require('module');
REPL_PROMPT = 'coffee> ';
REPL_PROMPT_CONTINUATION = '......> ';
enableColours = false;
if (process.platform !== 'win32') {
enableColours = !process.env.NODE_DISABLE_COLORS;
}
stdin = process.openStdin();
stdout = process.stdout;
error = function(err) {
return stdout.write((err.stack || err.toString()) + '\n\n');
};
backlog = '';
sandbox = Script.createContext();
nonContextGlobals = ['Buffer', 'console', 'process', 'setInterval', 'clearInterval', 'setTimeout', 'clearTimeout'];
for (_i = 0, _len = nonContextGlobals.length; _i < _len; _i++) {
g = nonContextGlobals[_i];
sandbox[g] = global[g];
}
sandbox.global = sandbox.root = sandbox.GLOBAL = sandbox;
run = function(buffer) {
var code, returnValue, _;
if (!buffer.toString().trim() && !backlog) {
repl.prompt();
return;
}
code = backlog += buffer;
if (code[code.length - 1] === '\\') {
backlog = "" + backlog.slice(0, -1) + "\n";
repl.setPrompt(REPL_PROMPT_CONTINUATION);
repl.prompt();
return;
}
repl.setPrompt(REPL_PROMPT);
backlog = '';
try {
_ = sandbox._;
returnValue = CoffeeScript.eval("_=(" + code + "\n)", {
sandbox: sandbox,
filename: 'repl',
modulename: 'repl'
});
if (returnValue === void 0) {
sandbox._ = _;
} else {
process.stdout.write(inspect(returnValue, false, 2, enableColours) + '\n');
}
} catch (err) {
error(err);
}
return repl.prompt();
};
ACCESSOR = /\s*([\w\.]+)(?:\.(\w*))$/;
SIMPLEVAR = /\s*(\w*)$/i;
autocomplete = function(text) {
return completeAttribute(text) || completeVariable(text) || [[], text];
};
completeAttribute = function(text) {
var all, completions, match, obj, prefix, val;
if (match = text.match(ACCESSOR)) {
all = match[0], obj = match[1], prefix = match[2];
try {
val = Script.runInContext(obj, sandbox);
} catch (error) {
return;
}
completions = getCompletions(prefix, Object.getOwnPropertyNames(val));
return [completions, prefix];
}
};
completeVariable = function(text) {
var completions, free, possibilities, vars, _ref;
if (free = (_ref = text.match(SIMPLEVAR)) != null ? _ref[1] : void 0) {
vars = Script.runInContext('Object.getOwnPropertyNames(this)', sandbox);
possibilities = vars.concat(CoffeeScript.RESERVED);
completions = getCompletions(free, possibilities);
return [completions, free];
}
};
getCompletions = function(prefix, candidates) {
var el, _j, _len2, _results;
_results = [];
for (_j = 0, _len2 = candidates.length; _j < _len2; _j++) {
el = candidates[_j];
if (el.indexOf(prefix) === 0) {
_results.push(el);
}
}
return _results;
};
process.on('uncaughtException', error);
if (readline.createInterface.length < 3) {
repl = readline.createInterface(stdin, autocomplete);
stdin.on('data', function(buffer) {
return repl.write(buffer);
});
} else {
repl = readline.createInterface(stdin, stdout, autocomplete);
}
repl.on('attemptClose', function() {
if (backlog) {
backlog = '';
process.stdout.write('\n');
repl.setPrompt(REPL_PROMPT);
return repl.prompt();
} else {
return repl.close();
}
});
repl.on('close', function() {
process.stdout.write('\n');
return stdin.destroy();
});
repl.on('line', run);
repl.setPrompt(REPL_PROMPT);
repl.prompt();
}).call(this);

363
bin/node_modules/coffee-script/lib/rewriter.js generated vendored Normal file
View File

@ -0,0 +1,363 @@
(function() {
var BALANCED_PAIRS, EXPRESSION_CLOSE, EXPRESSION_END, EXPRESSION_START, IMPLICIT_BLOCK, IMPLICIT_CALL, IMPLICIT_END, IMPLICIT_FUNC, IMPLICIT_UNSPACED_CALL, INVERSES, LINEBREAKS, SINGLE_CLOSERS, SINGLE_LINERS, left, rite, _i, _len, _ref;
var __indexOf = Array.prototype.indexOf || function(item) {
for (var i = 0, l = this.length; i < l; i++) {
if (this[i] === item) return i;
}
return -1;
}, __slice = Array.prototype.slice;
exports.Rewriter = (function() {
function Rewriter() {}
Rewriter.prototype.rewrite = function(tokens) {
this.tokens = tokens;
this.removeLeadingNewlines();
this.removeMidExpressionNewlines();
this.closeOpenCalls();
this.closeOpenIndexes();
this.addImplicitIndentation();
this.tagPostfixConditionals();
this.addImplicitBraces();
this.addImplicitParentheses();
this.ensureBalance(BALANCED_PAIRS);
this.rewriteClosingParens();
return this.tokens;
};
Rewriter.prototype.scanTokens = function(block) {
var i, token, tokens;
tokens = this.tokens;
i = 0;
while (token = tokens[i]) {
i += block.call(this, token, i, tokens);
}
return true;
};
Rewriter.prototype.detectEnd = function(i, condition, action) {
var levels, token, tokens, _ref, _ref2;
tokens = this.tokens;
levels = 0;
while (token = tokens[i]) {
if (levels === 0 && condition.call(this, token, i)) {
return action.call(this, token, i);
}
if (!token || levels < 0) {
return action.call(this, token, i - 1);
}
if (_ref = token[0], __indexOf.call(EXPRESSION_START, _ref) >= 0) {
levels += 1;
} else if (_ref2 = token[0], __indexOf.call(EXPRESSION_END, _ref2) >= 0) {
levels -= 1;
}
i += 1;
}
return i - 1;
};
Rewriter.prototype.removeLeadingNewlines = function() {
var i, tag, _len, _ref;
_ref = this.tokens;
for (i = 0, _len = _ref.length; i < _len; i++) {
tag = _ref[i][0];
if (tag !== 'TERMINATOR') {
break;
}
}
if (i) {
return this.tokens.splice(0, i);
}
};
Rewriter.prototype.removeMidExpressionNewlines = function() {
return this.scanTokens(function(token, i, tokens) {
var _ref;
if (!(token[0] === 'TERMINATOR' && (_ref = this.tag(i + 1), __indexOf.call(EXPRESSION_CLOSE, _ref) >= 0))) {
return 1;
}
tokens.splice(i, 1);
return 0;
});
};
Rewriter.prototype.closeOpenCalls = function() {
var action, condition;
condition = function(token, i) {
var _ref;
return ((_ref = token[0]) === ')' || _ref === 'CALL_END') || token[0] === 'OUTDENT' && this.tag(i - 1) === ')';
};
action = function(token, i) {
return this.tokens[token[0] === 'OUTDENT' ? i - 1 : i][0] = 'CALL_END';
};
return this.scanTokens(function(token, i) {
if (token[0] === 'CALL_START') {
this.detectEnd(i + 1, condition, action);
}
return 1;
});
};
Rewriter.prototype.closeOpenIndexes = function() {
var action, condition;
condition = function(token, i) {
var _ref;
return (_ref = token[0]) === ']' || _ref === 'INDEX_END';
};
action = function(token, i) {
return token[0] = 'INDEX_END';
};
return this.scanTokens(function(token, i) {
if (token[0] === 'INDEX_START') {
this.detectEnd(i + 1, condition, action);
}
return 1;
});
};
Rewriter.prototype.addImplicitBraces = function() {
var action, condition, stack, start, startIndent;
stack = [];
start = null;
startIndent = 0;
condition = function(token, i) {
var one, tag, three, two, _ref, _ref2;
_ref = this.tokens.slice(i + 1, (i + 3 + 1) || 9e9), one = _ref[0], two = _ref[1], three = _ref[2];
if ('HERECOMMENT' === (one != null ? one[0] : void 0)) {
return false;
}
tag = token[0];
return ((tag === 'TERMINATOR' || tag === 'OUTDENT') && !((two != null ? two[0] : void 0) === ':' || (one != null ? one[0] : void 0) === '@' && (three != null ? three[0] : void 0) === ':')) || (tag === ',' && one && ((_ref2 = one[0]) !== 'IDENTIFIER' && _ref2 !== 'NUMBER' && _ref2 !== 'STRING' && _ref2 !== '@' && _ref2 !== 'TERMINATOR' && _ref2 !== 'OUTDENT'));
};
action = function(token, i) {
var tok;
tok = ['}', '}', token[2]];
tok.generated = true;
return this.tokens.splice(i, 0, tok);
};
return this.scanTokens(function(token, i, tokens) {
var ago, idx, tag, tok, value, _ref, _ref2;
if (_ref = (tag = token[0]), __indexOf.call(EXPRESSION_START, _ref) >= 0) {
stack.push([(tag === 'INDENT' && this.tag(i - 1) === '{' ? '{' : tag), i]);
return 1;
}
if (__indexOf.call(EXPRESSION_END, tag) >= 0) {
start = stack.pop();
return 1;
}
if (!(tag === ':' && ((ago = this.tag(i - 2)) === ':' || ((_ref2 = stack[stack.length - 1]) != null ? _ref2[0] : void 0) !== '{'))) {
return 1;
}
stack.push(['{']);
idx = ago === '@' ? i - 2 : i - 1;
while (this.tag(idx - 2) === 'HERECOMMENT') {
idx -= 2;
}
value = new String('{');
value.generated = true;
tok = ['{', value, token[2]];
tok.generated = true;
tokens.splice(idx, 0, tok);
this.detectEnd(i + 2, condition, action);
return 2;
});
};
Rewriter.prototype.addImplicitParentheses = function() {
var action, noCall;
noCall = false;
action = function(token, i) {
var idx;
idx = token[0] === 'OUTDENT' ? i + 1 : i;
return this.tokens.splice(idx, 0, ['CALL_END', ')', token[2]]);
};
return this.scanTokens(function(token, i, tokens) {
var callObject, current, next, prev, seenControl, seenSingle, tag, _ref, _ref2, _ref3;
tag = token[0];
if (tag === 'CLASS' || tag === 'IF') {
noCall = true;
}
_ref = tokens.slice(i - 1, (i + 1 + 1) || 9e9), prev = _ref[0], current = _ref[1], next = _ref[2];
callObject = !noCall && tag === 'INDENT' && next && next.generated && next[0] === '{' && prev && (_ref2 = prev[0], __indexOf.call(IMPLICIT_FUNC, _ref2) >= 0);
seenSingle = false;
seenControl = false;
if (__indexOf.call(LINEBREAKS, tag) >= 0) {
noCall = false;
}
if (prev && !prev.spaced && tag === '?') {
token.call = true;
}
if (token.fromThen) {
return 1;
}
if (!(callObject || (prev != null ? prev.spaced : void 0) && (prev.call || (_ref3 = prev[0], __indexOf.call(IMPLICIT_FUNC, _ref3) >= 0)) && (__indexOf.call(IMPLICIT_CALL, tag) >= 0 || !(token.spaced || token.newLine) && __indexOf.call(IMPLICIT_UNSPACED_CALL, tag) >= 0))) {
return 1;
}
tokens.splice(i, 0, ['CALL_START', '(', token[2]]);
this.detectEnd(i + 1, function(token, i) {
var post, _ref4;
tag = token[0];
if (!seenSingle && token.fromThen) {
return true;
}
if (tag === 'IF' || tag === 'ELSE' || tag === 'CATCH' || tag === '->' || tag === '=>') {
seenSingle = true;
}
if (tag === 'IF' || tag === 'ELSE' || tag === 'SWITCH' || tag === 'TRY') {
seenControl = true;
}
if ((tag === '.' || tag === '?.' || tag === '::') && this.tag(i - 1) === 'OUTDENT') {
return true;
}
return !token.generated && this.tag(i - 1) !== ',' && (__indexOf.call(IMPLICIT_END, tag) >= 0 || (tag === 'INDENT' && !seenControl)) && (tag !== 'INDENT' || (this.tag(i - 2) !== 'CLASS' && (_ref4 = this.tag(i - 1), __indexOf.call(IMPLICIT_BLOCK, _ref4) < 0) && !((post = this.tokens[i + 1]) && post.generated && post[0] === '{')));
}, action);
if (prev[0] === '?') {
prev[0] = 'FUNC_EXIST';
}
return 2;
});
};
Rewriter.prototype.addImplicitIndentation = function() {
return this.scanTokens(function(token, i, tokens) {
var action, condition, indent, outdent, starter, tag, _ref, _ref2;
tag = token[0];
if (tag === 'TERMINATOR' && this.tag(i + 1) === 'THEN') {
tokens.splice(i, 1);
return 0;
}
if (tag === 'ELSE' && this.tag(i - 1) !== 'OUTDENT') {
tokens.splice.apply(tokens, [i, 0].concat(__slice.call(this.indentation(token))));
return 2;
}
if (tag === 'CATCH' && ((_ref = this.tag(i + 2)) === 'OUTDENT' || _ref === 'TERMINATOR' || _ref === 'FINALLY')) {
tokens.splice.apply(tokens, [i + 2, 0].concat(__slice.call(this.indentation(token))));
return 4;
}
if (__indexOf.call(SINGLE_LINERS, tag) >= 0 && this.tag(i + 1) !== 'INDENT' && !(tag === 'ELSE' && this.tag(i + 1) === 'IF')) {
starter = tag;
_ref2 = this.indentation(token), indent = _ref2[0], outdent = _ref2[1];
if (starter === 'THEN') {
indent.fromThen = true;
}
indent.generated = outdent.generated = true;
tokens.splice(i + 1, 0, indent);
condition = function(token, i) {
var _ref3;
return token[1] !== ';' && (_ref3 = token[0], __indexOf.call(SINGLE_CLOSERS, _ref3) >= 0) && !(token[0] === 'ELSE' && (starter !== 'IF' && starter !== 'THEN'));
};
action = function(token, i) {
return this.tokens.splice((this.tag(i - 1) === ',' ? i - 1 : i), 0, outdent);
};
this.detectEnd(i + 2, condition, action);
if (tag === 'THEN') {
tokens.splice(i, 1);
}
return 1;
}
return 1;
});
};
Rewriter.prototype.tagPostfixConditionals = function() {
var condition;
condition = function(token, i) {
var _ref;
return (_ref = token[0]) === 'TERMINATOR' || _ref === 'INDENT';
};
return this.scanTokens(function(token, i) {
var original;
if (token[0] !== 'IF') {
return 1;
}
original = token;
this.detectEnd(i + 1, condition, function(token, i) {
if (token[0] !== 'INDENT') {
return original[0] = 'POST_' + original[0];
}
});
return 1;
});
};
Rewriter.prototype.ensureBalance = function(pairs) {
var close, level, levels, open, openLine, tag, token, _i, _j, _len, _len2, _ref, _ref2;
levels = {};
openLine = {};
_ref = this.tokens;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
token = _ref[_i];
tag = token[0];
for (_j = 0, _len2 = pairs.length; _j < _len2; _j++) {
_ref2 = pairs[_j], open = _ref2[0], close = _ref2[1];
levels[open] |= 0;
if (tag === open) {
if (levels[open]++ === 0) {
openLine[open] = token[2];
}
} else if (tag === close && --levels[open] < 0) {
throw Error("too many " + token[1] + " on line " + (token[2] + 1));
}
}
}
for (open in levels) {
level = levels[open];
if (level > 0) {
throw Error("unclosed " + open + " on line " + (openLine[open] + 1));
}
}
return this;
};
Rewriter.prototype.rewriteClosingParens = function() {
var debt, key, stack;
stack = [];
debt = {};
for (key in INVERSES) {
debt[key] = 0;
}
return this.scanTokens(function(token, i, tokens) {
var inv, match, mtag, oppos, tag, val, _ref;
if (_ref = (tag = token[0]), __indexOf.call(EXPRESSION_START, _ref) >= 0) {
stack.push(token);
return 1;
}
if (__indexOf.call(EXPRESSION_END, tag) < 0) {
return 1;
}
if (debt[inv = INVERSES[tag]] > 0) {
debt[inv] -= 1;
tokens.splice(i, 1);
return 0;
}
match = stack.pop();
mtag = match[0];
oppos = INVERSES[mtag];
if (tag === oppos) {
return 1;
}
debt[mtag] += 1;
val = [oppos, mtag === 'INDENT' ? match[1] : oppos];
if (this.tag(i + 2) === mtag) {
tokens.splice(i + 3, 0, val);
stack.push(match);
} else {
tokens.splice(i, 0, val);
}
return 1;
});
};
Rewriter.prototype.indentation = function(token) {
return [['INDENT', 2, token[2]], ['OUTDENT', 2, token[2]]];
};
Rewriter.prototype.tag = function(i) {
var _ref;
return (_ref = this.tokens[i]) != null ? _ref[0] : void 0;
};
return Rewriter;
})();
BALANCED_PAIRS = [['(', ')'], ['[', ']'], ['{', '}'], ['INDENT', 'OUTDENT'], ['CALL_START', 'CALL_END'], ['PARAM_START', 'PARAM_END'], ['INDEX_START', 'INDEX_END']];
INVERSES = {};
EXPRESSION_START = [];
EXPRESSION_END = [];
for (_i = 0, _len = BALANCED_PAIRS.length; _i < _len; _i++) {
_ref = BALANCED_PAIRS[_i], left = _ref[0], rite = _ref[1];
EXPRESSION_START.push(INVERSES[rite] = left);
EXPRESSION_END.push(INVERSES[left] = rite);
}
EXPRESSION_CLOSE = ['CATCH', 'WHEN', 'ELSE', 'FINALLY'].concat(EXPRESSION_END);
IMPLICIT_FUNC = ['IDENTIFIER', 'SUPER', ')', 'CALL_END', ']', 'INDEX_END', '@', 'THIS'];
IMPLICIT_CALL = ['IDENTIFIER', 'NUMBER', 'STRING', 'JS', 'REGEX', 'NEW', 'PARAM_START', 'CLASS', 'IF', 'TRY', 'SWITCH', 'THIS', 'BOOL', 'UNARY', 'SUPER', '@', '->', '=>', '[', '(', '{', '--', '++'];
IMPLICIT_UNSPACED_CALL = ['+', '-'];
IMPLICIT_BLOCK = ['->', '=>', '{', '[', ','];
IMPLICIT_END = ['POST_IF', 'FOR', 'WHILE', 'UNTIL', 'WHEN', 'BY', 'LOOP', 'TERMINATOR'];
SINGLE_LINERS = ['ELSE', '->', '=>', 'TRY', 'FINALLY', 'THEN'];
SINGLE_CLOSERS = ['TERMINATOR', 'CATCH', 'FINALLY', 'ELSE', 'OUTDENT', 'LEADING_WHEN'];
LINEBREAKS = ['TERMINATOR', 'INDENT', 'OUTDENT'];
}).call(this);

120
bin/node_modules/coffee-script/lib/scope.js generated vendored Normal file
View File

@ -0,0 +1,120 @@
(function() {
var Scope, extend, last, _ref;
_ref = require('./helpers'), extend = _ref.extend, last = _ref.last;
exports.Scope = Scope = (function() {
Scope.root = null;
function Scope(parent, expressions, method) {
this.parent = parent;
this.expressions = expressions;
this.method = method;
this.variables = [
{
name: 'arguments',
type: 'arguments'
}
];
this.positions = {};
if (!this.parent) {
Scope.root = this;
}
}
Scope.prototype.add = function(name, type, immediate) {
var pos;
if (this.shared && !immediate) {
return this.parent.add(name, type, immediate);
}
if (typeof (pos = this.positions[name]) === 'number') {
return this.variables[pos].type = type;
} else {
return this.positions[name] = this.variables.push({
name: name,
type: type
}) - 1;
}
};
Scope.prototype.find = function(name, options) {
if (this.check(name, options)) {
return true;
}
this.add(name, 'var');
return false;
};
Scope.prototype.parameter = function(name) {
if (this.shared && this.parent.check(name, true)) {
return;
}
return this.add(name, 'param');
};
Scope.prototype.check = function(name, immediate) {
var found, _ref2;
found = !!this.type(name);
if (found || immediate) {
return found;
}
return !!((_ref2 = this.parent) != null ? _ref2.check(name) : void 0);
};
Scope.prototype.temporary = function(name, index) {
if (name.length > 1) {
return '_' + name + (index > 1 ? index : '');
} else {
return '_' + (index + parseInt(name, 36)).toString(36).replace(/\d/g, 'a');
}
};
Scope.prototype.type = function(name) {
var v, _i, _len, _ref2;
_ref2 = this.variables;
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
v = _ref2[_i];
if (v.name === name) {
return v.type;
}
}
return null;
};
Scope.prototype.freeVariable = function(type) {
var index, temp;
index = 0;
while (this.check((temp = this.temporary(type, index)))) {
index++;
}
this.add(temp, 'var', true);
return temp;
};
Scope.prototype.assign = function(name, value) {
this.add(name, {
value: value,
assigned: true
});
return this.hasAssignments = true;
};
Scope.prototype.hasDeclarations = function() {
return !!this.declaredVariables().length;
};
Scope.prototype.declaredVariables = function() {
var realVars, tempVars, v, _i, _len, _ref2;
realVars = [];
tempVars = [];
_ref2 = this.variables;
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
v = _ref2[_i];
if (v.type === 'var') {
(v.name.charAt(0) === '_' ? tempVars : realVars).push(v.name);
}
}
return realVars.sort().concat(tempVars.sort());
};
Scope.prototype.assignedVariables = function() {
var v, _i, _len, _ref2, _results;
_ref2 = this.variables;
_results = [];
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
v = _ref2[_i];
if (v.type.assigned) {
_results.push("" + v.name + " = " + v.type.value);
}
}
return _results;
};
return Scope;
})();
}).call(this);

27
bin/node_modules/coffee-script/package.json generated vendored Normal file
View File

@ -0,0 +1,27 @@
{
"name": "coffee-script",
"description": "Unfancy JavaScript",
"keywords": ["javascript", "language", "coffeescript", "compiler"],
"author": "Jeremy Ashkenas",
"version": "1.1.2",
"licenses": [{
"type": "MIT",
"url": "http://github.com/jashkenas/coffee-script/raw/master/LICENSE"
}],
"engines": {
"node": ">=0.2.5"
},
"directories" : {
"lib" : "./lib"
},
"main" : "./lib/coffee-script",
"bin": {
"coffee": "./bin/coffee",
"cake": "./bin/cake"
},
"homepage": "http://coffeescript.org",
"repository": {
"type": "git",
"url": "git://github.com/jashkenas/coffee-script.git"
}
}

5
bin/node_modules/nodeunit/.gitignore generated vendored Normal file
View File

@ -0,0 +1,5 @@
dist
stamp-build
*~
gmon.out
v8.log

3
bin/node_modules/nodeunit/.npmignore generated vendored Normal file
View File

@ -0,0 +1,3 @@
dist
stamp-build
test/fixtures/dir2

60
bin/node_modules/nodeunit/CONTRIBUTORS.md generated vendored Normal file
View File

@ -0,0 +1,60 @@
Nodeunit contributors (sorted alphabeticaly)
============================================
* **[Alex Gorbatchev](https://github.com/alexgorbatchev)**
* Deeper default object inspection
* Timeout to ensure flushing of console output (default reporter)
* **[Alex Wolfe](https://github.com/alexkwolfe)**
* HTML test reporter
* **[Caolan McMahon](https://github.com/caolan)**
* Author and maintainer
* Most features develpopment
* **[Carl Fürstenberg](https://github.com/azatoth)**
* Debian-friendly Makefile, supports both 'node' and 'nodejs' executables
* Sandbox utility
* Minimal test reporter
* **[Gerad Suyderhoud](https://github.com/gerad)**
* First comand-line tool
* **[Kadir Pekel](https://github.com/coffeemate)**
* Improvements to default test reporter
* HTTP test utility
* **[Matthias Lübken](https://github.com/luebken)**
* Utility functions for tracking incomplete tests on exit
* **[Oleg Efimov](https://github.com/Sannis)**
* Adding 'make lint' and fixing nodelint errors
* Option parsing, --help text and config file support
* Reporters option for command-line tool
* **[Orlando Vazquez](https://github.com/orlandov)**
* Added jUnit XML reporter
* **[Ryan Dahl](https://github.com/ry)**
* Add package.json
* **[Sam Stephenson](https://github.com/sstephenson)**
* Coffee-script support
* **[Thomas Mayfield](https://github.com/thegreatape)**
* Async setUp and tearDown support for testCase
**[Full contributors list](https://github.com/caolan/nodeunit/contributors).**

19
bin/node_modules/nodeunit/LICENSE generated vendored Normal file
View File

@ -0,0 +1,19 @@
Copyright (c) 2010 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.

126
bin/node_modules/nodeunit/Makefile generated vendored Normal file
View File

@ -0,0 +1,126 @@
PACKAGE = nodeunit
NODEJS = $(if $(shell test -f /usr/bin/nodejs && echo "true"),nodejs,node)
PREFIX ?= /usr/local
BINDIR ?= $(PREFIX)/bin
DATADIR ?= $(PREFIX)/share
MANDIR ?= $(PREFIX)/share/man
LIBDIR ?= $(PREFIX)/lib
NODEJSLIBDIR ?= $(LIBDIR)/$(NODEJS)
BUILDDIR = dist
DOCS = $(shell find doc -name '*.md' \
|sed 's|.md|.1|g' \
|sed 's|doc/|man1/|g' \
)
$(shell if [ ! -d $(BUILDDIR) ]; then mkdir $(BUILDDIR); fi)
all: build doc
browser:
# super hacky build script for browser version!
mkdir -p $(BUILDDIR)/browser
rm -rf $(BUILDDIR)/browser/*
# build browser version of nodeunit.js
cat share/license.js >> $(BUILDDIR)/browser/nodeunit.js
echo "nodeunit = (function(){" >> $(BUILDDIR)/browser/nodeunit.js
cat deps/json2.js >> $(BUILDDIR)/browser/nodeunit.js
# make assert global
echo "var assert = this.assert = {};" >> $(BUILDDIR)/browser/nodeunit.js
echo "var types = {};" >> $(BUILDDIR)/browser/nodeunit.js
echo "var core = {};" >> $(BUILDDIR)/browser/nodeunit.js
echo "var nodeunit = {};" >> $(BUILDDIR)/browser/nodeunit.js
echo "var reporter = {};" >> $(BUILDDIR)/browser/nodeunit.js
cat deps/async.js >> $(BUILDDIR)/browser/nodeunit.js
echo "(function(exports){" >> $(BUILDDIR)/browser/nodeunit.js
cat lib/assert.js >> $(BUILDDIR)/browser/nodeunit.js
echo "})(assert);" >> $(BUILDDIR)/browser/nodeunit.js
echo "(function(exports){" >> $(BUILDDIR)/browser/nodeunit.js
cat lib/types.js >> $(BUILDDIR)/browser/nodeunit.js
echo "})(types);" >> $(BUILDDIR)/browser/nodeunit.js
echo "(function(exports){" >> $(BUILDDIR)/browser/nodeunit.js
cat lib/core.js >> $(BUILDDIR)/browser/nodeunit.js
echo "})(core);" >> $(BUILDDIR)/browser/nodeunit.js
echo "(function(exports){" >> $(BUILDDIR)/browser/nodeunit.js
cat lib/reporters/browser.js >> $(BUILDDIR)/browser/nodeunit.js
echo "})(reporter);" >> $(BUILDDIR)/browser/nodeunit.js
echo "nodeunit = core;" >> $(BUILDDIR)/browser/nodeunit.js
echo "nodeunit.assert = assert;" >> $(BUILDDIR)/browser/nodeunit.js
echo "nodeunit.reporter = reporter;" >> $(BUILDDIR)/browser/nodeunit.js
echo "nodeunit.run = reporter.run;" >> $(BUILDDIR)/browser/nodeunit.js
echo "return nodeunit; })();" >> $(BUILDDIR)/browser/nodeunit.js
sed -i "/\@REMOVE_LINE_FOR_BROWSER/d" $(BUILDDIR)/browser/nodeunit.js
# copy nodeunit.css
cp share/nodeunit.css $(BUILDDIR)/browser/nodeunit.css
# create nodeunit.min.js
uglifyjs $(BUILDDIR)/browser/nodeunit.js > $(BUILDDIR)/browser/nodeunit.min.js
# create test scripts
mkdir -p $(BUILDDIR)/browser/test
cp test/test.html $(BUILDDIR)/browser/test/test.html
# test-base.js
echo "(function (exports) {" > $(BUILDDIR)/browser/test/test-base.js
cat test/test-base.js >> $(BUILDDIR)/browser/test/test-base.js
echo "})(this.test_base = {});" >> $(BUILDDIR)/browser/test/test-base.js
sed -i "/\@REMOVE_LINE_FOR_BROWSER/d" $(BUILDDIR)/browser/test/test-base.js
# test-runmodule.js
echo "(function (exports) {" > $(BUILDDIR)/browser/test/test-runmodule.js
cat test/test-runmodule.js >> $(BUILDDIR)/browser/test/test-runmodule.js
echo "})(this.test_runmodule = {});" >> $(BUILDDIR)/browser/test/test-runmodule.js
sed -i "/\@REMOVE_LINE_FOR_BROWSER/d" $(BUILDDIR)/browser/test/test-runmodule.js
# test-runtest.js
echo "(function (exports) {" > $(BUILDDIR)/browser/test/test-runtest.js
cat test/test-runtest.js >> $(BUILDDIR)/browser/test/test-runtest.js
echo "})(this.test_runtest = {});" >> $(BUILDDIR)/browser/test/test-runtest.js
sed -i "/\@REMOVE_LINE_FOR_BROWSER/d" $(BUILDDIR)/browser/test/test-runtest.js
# test-testcase.js
echo "(function (exports) {" > $(BUILDDIR)/browser/test/test-testcase.js
cat test/test-testcase.js >> $(BUILDDIR)/browser/test/test-testcase.js
echo "})(this.test_testcase = {});" >> $(BUILDDIR)/browser/test/test-testcase.js
sed -i "/\@REMOVE_LINE_FOR_BROWSER/d" $(BUILDDIR)/browser/test/test-testcase.js
# copy nodeunit.js to dist/browser/test to make it easier for me to host and
# run on windows VMs with IE
cp $(BUILDDIR)/browser/nodeunit.js $(BUILDDIR)/browser/test/nodeunit.js
cp $(BUILDDIR)/browser/nodeunit.css $(BUILDDIR)/browser/test/nodeunit.css
build: stamp-build
stamp-build: $(wildcard deps/* lib/*.js)
touch $@;
mkdir -p $(BUILDDIR)/nodeunit
cp -R bin deps index.js lib package.json $(BUILDDIR)/nodeunit
printf '#!/bin/sh\n$(NODEJS) $(NODEJSLIBDIR)/$(PACKAGE)/bin/nodeunit $$@' > $(BUILDDIR)/nodeunit.sh
test:
$(NODEJS) ./bin/nodeunit test
install: build
install -d $(NODEJSLIBDIR)
cp -a $(BUILDDIR)/nodeunit $(NODEJSLIBDIR)
install -m 0755 $(BUILDDIR)/nodeunit.sh $(BINDIR)/nodeunit
install -d $(MANDIR)/man1/
cp -a man1/nodeunit.1 $(MANDIR)/man1/
uninstall:
rm -rf $(NODEJSLIBDIR)/nodeunit $(NODEJSLIBDIR)/nodeunit.js $(BINDIR)/nodeunit
rm -rf $(MANDIR)/man1/nodeunit.1
clean:
rm -rf $(BUILDDIR) stamp-build
lint:
nodelint --config nodelint.cfg ./index.js ./bin/nodeunit ./bin/nodeunit.json ./lib/*.js ./lib/reporters/*.js ./test/*.js
doc: man1 $(DOCS)
@true
man1:
@if ! test -d man1 ; then mkdir -p man1 ; fi
# use `npm install ronn` for this to work.
man1/%.1: doc/%.md
ronn --roff $< > $@
.PHONY: browser test install uninstall build all

432
bin/node_modules/nodeunit/README.md generated vendored Normal file
View File

@ -0,0 +1,432 @@
Nodeunit
========
Simple syntax, powerful tools. Nodeunit provides easy async unit testing for
node.js and the browser.
* Simple to use
* Just export the tests from a module
* Works with node.js and in the browser.
* Helps you avoid common pitfalls when testing asynchronous code
* Easy to add test cases with setUp and tearDown functions if you wish
* Flexible reporters for custom output, built-in support for HTML and jUnit XML
* Allows the use of mocks and stubs
__Contributors__
* [alexgorbatchev](https://github.com/alexgorbatchev)
* [alexkwolfe](https://github.com/alexkwolfe)
* [azatoth](https://github.com/azatoth)
* [coffeemate](https://github.com/coffeemate)
* [luebken](https://github.com/luebken)
* [orlandov](https://github.com/orlandov)
* [Sannis](https://github.com/Sannis)
* [sstephenson](https://github.com/sstephenson)
* [thegreatape](https://github.com/thegreatape)
* and thanks to [cjohansen](https://github.com/cjohansen) for input and advice
on implementing setUp and tearDown functions. See
[cjohansen's fork](https://github.com/cjohansen/nodeunit).
Also, check out gerad's [nodeunit-dsl](https://github.com/gerad/nodeunit-dsl)
project, which implements a 'pretty dsl on top of nodeunit'.
More contributor information can be found in the
[CONTRIBUTORS.md](https://github.com/caolan/nodeunit/blob/master/CONTRIBUTORS.md)
file.
Usage
-----
Here is an example unit test module:
exports.testSomething = function(test){
test.expect(1);
test.ok(true, "this assertion should pass");
test.done();
};
exports.testSomethingElse = function(test){
test.ok(false, "this assertion should fail");
test.done();
};
When run using the included test runner, this will output the following:
<img src="https://github.com/caolan/nodeunit/raw/master/img/example_fail.png" />
Installation
------------
There are two options for installing nodeunit:
1. Clone / download nodeunit from [github](https://github.com/caolan/nodeunit),
then:
make && sudo make install
2. Install via npm:
npm install nodeunit
API Documentation
-----------------
Nodeunit uses the functions available in the node.js
[assert module](http://nodejs.org/docs/v0.4.2/api/assert.html):
* __ok(value, [message])__ - Tests if value is a true value.
* __equal(actual, expected, [message])__ - Tests shallow, coercive equality
with the equal comparison operator ( == ).
* __notEqual(actual, expected, [message])__ - Tests shallow, coercive
non-equality with the not equal comparison operator ( != ).
* __deepEqual(actual, expected, [message])__ - Tests for deep equality.
* __notDeepEqual(actual, expected, [message])__ - Tests for any deep
inequality.
* __strictEqual(actual, expected, [message])__ - Tests strict equality, as
determined by the strict equality operator ( === )
* __notStrictEqual(actual, expected, [message])__ - Tests strict non-equality,
as determined by the strict not equal operator ( !== )
* __throws(block, [error], [message])__ - Expects block to throw an error.
* __doesNotThrow(block, [error], [message])__ - Expects block not to throw an
error.
* __ifError(value)__ - Tests if value is not a false value, throws if it is a
true value. Useful when testing the first argument, error in callbacks.
Nodeunit also provides the following functions within tests:
* __expect(amount)__ - Specify how many assertions are expected to run within a
test. Very useful for ensuring that all your callbacks and assertions are
run.
* __done()__ - Finish the current test function, and move on to the next. ALL
tests should call this!
Nodeunit aims to be simple and easy to learn. This is achieved through using
existing structures (such as node.js modules) to maximum effect, and reducing
the API where possible, to make it easier to digest.
Tests are simply exported from a module, but they are still run in the order
they are defined.
__Note:__ Users of old nodeunit versions may remember using ok, equals and same
in the style of qunit, instead of the assert functions above. These functions
still exist for backwards compatibility, and are simply aliases to their assert
module counterparts.
Asynchronous Testing
--------------------
When testing asynchronous code, there are a number of sharp edges to watch out
for. Thankfully, nodeunit is designed to help you avoid as many of these
pitfalls as possible. For the most part, testing asynchronous code in nodeunit
_just works_.
### Tests run in series
While running tests in parallel seems like a good idea for speeding up your
test suite, in practice I've found it means writing much more complicated
tests. Because of node's module cache, running tests in parallel means mocking
and stubbing is pretty much impossible. One of the nicest things about testing
in javascript is the ease of doing stubs:
var _readFile = fs.readFile;
fs.readFile = function(path, callback){
// its a stub!
};
// test function that uses fs.readFile
// we're done
fs.readFile = _readFile;
You cannot do this when running tests in parallel. In order to keep testing as
simple as possible, nodeunit avoids it. Thankfully, most unit-test suites run
fast anyway.
### Explicit ending of tests
When testing async code its important that tests end at the correct point, not
just after a given number of assertions. Otherwise your tests can run short,
ending before all assertions have completed. Its important to detect too
many assertions as well as too few. Combining explicit ending of tests with
an expected number of assertions helps to avoid false test passes, so be sure
to use the test.expect() method at the start of your test functions, and
test.done() when finished.
Groups, setUp and tearDown
--------------------------
Nodeunit allows the nesting of test functions:
exports.test1 = function (test) {
...
}
exports.group = {
test2: function (test) {
...
},
test3: function (test) {
...
}
}
This would be run as:
test1
group - test2
group - test3
Using these groups its possible to add setUp and tearDown functions to your
tests. Nodeunit has a utility function called testCase which allows you to
define a setUp function, which is run before each test, and a tearDown
function, which is run after each test calls test.done():
var testCase = require('nodeunit').testCase;
module.exports = testCase({
setUp: function (callback) {
this.foo = 'bar';
callback();
},
tearDown: function (callback) {
// clean up
callback();
},
test1: function (test) {
test.equals(this.foo, 'bar');
test.done();
}
});
In this way, its possible to have multiple groups of tests in a module, each
group with its own setUp and tearDown functions.
Running Tests
-------------
Nodeunit comes with a basic command-line test runner, which can be installed
using 'sudo make install'. Example usage:
nodeunit testmodule1.js testfolder [...]
The default test reporter uses color output, because I think that's more fun :) I
intend to add a no-color option in future. To give you a feeling of the fun you'll
be having writing tests, lets fix the example at the start of the README:
<img src="https://github.com/caolan/nodeunit/raw/master/img/example_pass.png" />
Ahhh, Doesn't that feel better?
When using the included test runner, it will exit using the failed number of
assertions as the exit code. Exiting with 0 when all tests pass.
### Command-line Options
* __--reporter FILE__ - you can set the test reporter to a custom module or
on of the modules in nodeunit/lib/reporters, when omitted, the default test runner
is used.
* __--list-reporters__ - list available build-in reporters.
* __--config FILE__ - load config options from a JSON file, allows
the customisation of color schemes for the default test reporter etc. See
bin/nodeunit.json for current available options.
* __--version__ or __-v__ - report nodeunit version
* __--help__ - show nodeunit help
Running tests in the browser
----------------------------
Nodeunit tests can also be run inside the browser. For example usage, see
the examples/browser folder. The basic syntax is as follows:
__test.html__
<html>
<head>
<title>Example Test Suite</title>
<link rel="stylesheet" href="nodeunit.css" type="text/css" />
<script src="nodeunit.js"></script>
<script src="suite1.js"></script>
<script src="suite2.js"></script>
</head>
<body>
<h1 id="nodeunit-header>Example Test Suite</h1>
<script>
nodeunit.run({
'Suite One': suite1,
'Suite Two': suite2
});
</script>
</body>
</html>
Here, suite1 and suite2 are just object literals containing test functions or
groups, as would be returned if you did require('test-suite') in node.js:
__suite1.js__
this.suite1 = {
'example test': function (test) {
test.ok(true, 'everything is ok');
test.done();
}
};
If you wish to use a commonjs format for your test suites (using exports), it is
up to you to define the commonjs tools for the browser. There are a number of
alternatives and its important it fits with your existing code, which is
why nodeunit does not currently provide this out of the box.
In the example above, the tests will run when the page is loaded.
The browser-version of nodeunit.js is created in dist/browser when you do, 'make
browser'. You'll need [UglifyJS](https://github.com/mishoo/UglifyJS) installed in
order for it to automatically create nodeunit.min.js.
Adding nodeunit to Your Projects
--------------------------------
If you don't want people to have to install the nodeunit command-line tool,
you'll want to create a script that runs the tests for your project with the
correct require paths set up. Here's an example test script, with a deps
directory containing the projects dependencies:
#!/usr/bin/env node
require.paths.unshift(__dirname + '/deps');
var reporter = require('nodeunit').reporters.default;
reporter.run(['test']);
If you're using git, you might find it useful to include nodeunit as a
submodule. Using submodules makes it easy for developers to download nodeunit
and run your test suite, without cluttering up your repository with
the source code. To add nodeunit as a git submodule do the following:
git submodule add git://github.com/caolan/nodeunit.git deps/nodeunit
This will add nodeunit to the deps folder of your project. Now, when cloning
the repository, nodeunit can be downloaded by doing the following:
git submodule init
git submodule update
Let's update the test script above with a helpful hint on how to get nodeunit,
if its missing:
#!/usr/bin/env node
require.paths.unshift(__dirname + '/deps');
try {
var reporter = require('nodeunit').reporters.default;
}
catch(e) {
console.log("Cannot find nodeunit module.");
console.log("You can download submodules for this project by doing:");
console.log("");
console.log(" git submodule init");
console.log(" git submodule update");
console.log("");
process.exit();
}
process.chdir(__dirname);
reporter.run(['test']);
Now if someone attempts to run your test suite without nodeunit installed they
will be prompted to download the submodules for your project.
Built-in Test Reporters
-----------------------
* __default__ - The standard reporter seen in the nodeunit screenshots
* __minimal__ - Pretty, minimal output, shows errors and progress only
* __html__ - Outputs a HTML report to stdout
* __junit__ - Creates jUnit compatible XML reports, which can be used with
continuous integration tools such as [Hudson](http://hudson-ci.org/).
Writing a Test Reporter
---------------------
Nodeunit exports runTest(fn, options), runModule(mod, options) and
runFiles(paths, options). You'll most likely want to run test suites from
files, which can be done using the latter function. The _options_ argument can
contain callbacks which run during testing. Nodeunit provides the following
callbacks:
* __moduleStart(name)__ - called before a module is tested
* __moduleDone(name, assertions)__ - called once all test functions within the
module have completed (see assertions object reference below)
ALL tests within the module
* __testStart(name)__ - called before a test function is run
* __testDone(name, assertions)__ - called once a test function has completed
(by calling test.done())
* __log(assertion)__ - called whenever an assertion is made (see assertion
object reference below)
* __done(assertions)__ - called after all tests/modules are complete
The __assertion__ object:
* __passed()__ - did the assertion pass?
* __failed()__ - did the assertion fail?
* __error__ - the AssertionError if the assertion failed
* __method__ - the nodeunit assertion method used (ok, same, equals...)
* __message__ - the message the assertion method was called with (optional)
The __assertionList__ object:
* An array-like object with the following new attributes:
* __failures()__ - the number of assertions which failed
* __duration__ - the time taken for the test to complete in msecs
For a reference implementation of a test reporter, see lib/reporters/default.js in
the nodeunit project directory.
Sandbox utility
---------------
This is a function which evaluates JavaScript files in a sandbox and returns the
context. The sandbox function can be used for testing client-side code or private
un-exported functions within a module.
var sandbox = require('nodeunit').utils.sandbox;
var example = sandbox('example.js');
__sandbox(files, sandbox)__ - Evaluates JavaScript files in a sandbox, returning
the context. The first argument can either be a single filename or an array of
filenames. If multiple filenames are given their contents are concatenated before
evalution. The second argument is an optional context to use for the sandbox.
Running the nodeunit Tests
--------------------------
The tests for nodeunit are written using nodeunit itself as the test framework.
However, the module test-base.js first does some basic tests using the assert
module to ensure that test functions are actually run, and a basic level of
nodeunit functionality is available.
To run the nodeunit tests do:
make test
__Note:__ There was a bug in node v0.2.0 causing the tests to hang, upgrading
to v0.2.1 fixes this.
Contributing
------------
Contributions to the project are most welcome, so feel free to fork and improve.
When submitting a pull request, please run 'make lint' first to ensure
we're following a consistent coding style.

120
bin/node_modules/nodeunit/bin/nodeunit generated vendored Executable file
View File

@ -0,0 +1,120 @@
#!/usr/bin/env node
var
fs = require('fs'),
path = require('path');
// TODO: remove this when https://github.com/joyent/node/pull/1312
// lands in core.
//
// Until then, use console.log from npm (https://gist.github.com/1077544)
require('../deps/console.log');
require.paths.push(process.cwd());
var args = process.ARGV.slice(2);
var files = [];
var testrunner,
config_file,
config_param_found = false,
output_param_found = false,
reporter_file = 'default',
reporter_param_found = false,
testspec_param_found = false;
var usage = "Usage: nodeunit [options] testmodule1.js testfolder [...] \n" +
"Options:\n\n" +
" --config FILE the path to a JSON file with options\n" +
" --reporter FILE optional path to a reporter file to customize the output\n" +
" --list-reporters list available build-in reporters\n" +
" -t name, specify a test to run\n" +
" -h, --help display this help and exit\n" +
" -v, --version output version information and exit";
// load default options
var content = fs.readFileSync(__dirname + '/nodeunit.json', 'utf8');
var options = JSON.parse(content);
// a very basic pseudo --options parser
args.forEach(function (arg) {
if (arg.slice(0, 9) === "--config=") {
config_file = arg.slice(9);
} else if (arg === '--config') {
config_param_found = true;
} else if (config_param_found) {
config_file = arg;
config_param_found = false;
} else if (arg.slice(0, 9) === "--output=") {
options.output = arg.slice(9);
} else if (arg === '--output') {
output_param_found = true;
} else if (output_param_found) {
options.output = arg;
output_param_found = false;
} else if (arg.slice(0, 11) === "--reporter=") {
reporter_file = arg.slice(11);
} else if (arg === '--reporter') {
reporter_param_found = true;
} else if (reporter_param_found) {
reporter_file = arg;
reporter_param_found = false;
} else if (arg === '-t') {
testspec_param_found = true;
} else if (testspec_param_found) {
options.testspec = arg;
testspec_param_found = false;
} else if (arg === '--list-reporters') {
var reporters = fs.readdirSync(__dirname + '/../lib/reporters');
reporters = reporters.filter(function (reporter_file) {
return (/\.js$/).test(reporter_file);
}).map(function (reporter_file) {
return reporter_file.replace(/\.js$/, '');
}).filter(function (reporter_file) {
return reporter_file !== 'index';
});
console.log('Build-in reporters: ');
reporters.forEach(function (reporter_file) {
var reporter = require('../lib/reporters/' + reporter_file);
console.log(' * ' + reporter_file + (reporter.info ? ': ' + reporter.info : ''));
});
process.exit(0);
} else if ((arg === '-v') || (arg === '--version')) {
var content = fs.readFileSync(__dirname + '/../package.json', 'utf8');
var pkg = JSON.parse(content);
console.log(pkg.version);
process.exit(0);
} else if ((arg === '-h') || (arg === '--help')) {
console.log(usage);
process.exit(0);
} else {
files.push(arg);
}
});
if (files.length === 0) {
console.log('Files required.');
console.log(usage);
process.exit(1);
}
if (config_file) {
content = fs.readFileSync(config_file, 'utf8');
var custom_options = JSON.parse(content);
for (var option in custom_options) {
if (typeof option === 'string') {
options[option] = custom_options[option];
}
}
}
var builtin_reporters = require(__dirname + '/../lib/reporters');
if (reporter_file in builtin_reporters) {
testrunner = builtin_reporters[reporter_file];
}
else {
testrunner = require(reporter_file);
}
testrunner.run(files, options);

10
bin/node_modules/nodeunit/bin/nodeunit.json generated vendored Normal file
View File

@ -0,0 +1,10 @@
{
"error_prefix": "\u001B[31m",
"error_suffix": "\u001B[39m",
"ok_prefix": "\u001B[32m",
"ok_suffix": "\u001B[39m",
"bold_prefix": "\u001B[1m",
"bold_suffix": "\u001B[22m",
"assertion_prefix": "\u001B[35m",
"assertion_suffix": "\u001B[39m"
}

623
bin/node_modules/nodeunit/deps/async.js generated vendored Normal file
View File

@ -0,0 +1,623 @@
/*global setTimeout: false, console: false */
(function () {
var async = {};
// global on the server, window in the browser
var root = this,
previous_async = root.async;
if (typeof module !== 'undefined' && module.exports) {
module.exports = async;
}
else {
root.async = async;
}
async.noConflict = function () {
root.async = previous_async;
return async;
};
//// cross-browser compatiblity functions ////
var _forEach = function (arr, iterator) {
if (arr.forEach) {
return arr.forEach(iterator);
}
for (var i = 0; i < arr.length; i += 1) {
iterator(arr[i], i, arr);
}
};
var _map = function (arr, iterator) {
if (arr.map) {
return arr.map(iterator);
}
var results = [];
_forEach(arr, function (x, i, a) {
results.push(iterator(x, i, a));
});
return results;
};
var _reduce = function (arr, iterator, memo) {
if (arr.reduce) {
return arr.reduce(iterator, memo);
}
_forEach(arr, function (x, i, a) {
memo = iterator(memo, x, i, a);
});
return memo;
};
var _keys = function (obj) {
if (Object.keys) {
return Object.keys(obj);
}
var keys = [];
for (var k in obj) {
if (obj.hasOwnProperty(k)) {
keys.push(k);
}
}
return keys;
};
var _indexOf = function (arr, item) {
if (arr.indexOf) {
return arr.indexOf(item);
}
for (var i = 0; i < arr.length; i += 1) {
if (arr[i] === item) {
return i;
}
}
return -1;
};
//// exported async module functions ////
//// nextTick implementation with browser-compatible fallback ////
if (typeof process === 'undefined' || !(process.nextTick)) {
async.nextTick = function (fn) {
setTimeout(fn, 0);
};
}
else {
async.nextTick = process.nextTick;
}
async.forEach = function (arr, iterator, callback) {
if (!arr.length) {
return callback();
}
var completed = 0;
_forEach(arr, function (x) {
iterator(x, function (err) {
if (err) {
callback(err);
callback = function () {};
}
else {
completed += 1;
if (completed === arr.length) {
callback();
}
}
});
});
};
async.forEachSeries = function (arr, iterator, callback) {
if (!arr.length) {
return callback();
}
var completed = 0;
var iterate = function () {
iterator(arr[completed], function (err) {
if (err) {
callback(err);
callback = function () {};
}
else {
completed += 1;
if (completed === arr.length) {
callback();
}
else {
iterate();
}
}
});
};
iterate();
};
var doParallel = function (fn) {
return function () {
var args = Array.prototype.slice.call(arguments);
return fn.apply(null, [async.forEach].concat(args));
};
};
var doSeries = function (fn) {
return function () {
var args = Array.prototype.slice.call(arguments);
return fn.apply(null, [async.forEachSeries].concat(args));
};
};
var _asyncMap = function (eachfn, arr, iterator, callback) {
var results = [];
arr = _map(arr, function (x, i) {
return {index: i, value: x};
});
eachfn(arr, function (x, callback) {
iterator(x.value, function (err, v) {
results[x.index] = v;
callback(err);
});
}, function (err) {
callback(err, results);
});
};
async.map = doParallel(_asyncMap);
async.mapSeries = doSeries(_asyncMap);
// reduce only has a series version, as doing reduce in parallel won't
// work in many situations.
async.reduce = function (arr, memo, iterator, callback) {
async.forEachSeries(arr, function (x, callback) {
iterator(memo, x, function (err, v) {
memo = v;
callback(err);
});
}, function (err) {
callback(err, memo);
});
};
// inject alias
async.inject = async.reduce;
// foldl alias
async.foldl = async.reduce;
async.reduceRight = function (arr, memo, iterator, callback) {
var reversed = _map(arr, function (x) {
return x;
}).reverse();
async.reduce(reversed, memo, iterator, callback);
};
// foldr alias
async.foldr = async.reduceRight;
var _filter = function (eachfn, arr, iterator, callback) {
var results = [];
arr = _map(arr, function (x, i) {
return {index: i, value: x};
});
eachfn(arr, function (x, callback) {
iterator(x.value, function (v) {
if (v) {
results.push(x);
}
callback();
});
}, function (err) {
callback(_map(results.sort(function (a, b) {
return a.index - b.index;
}), function (x) {
return x.value;
}));
});
};
async.filter = doParallel(_filter);
async.filterSeries = doSeries(_filter);
// select alias
async.select = async.filter;
async.selectSeries = async.filterSeries;
var _reject = function (eachfn, arr, iterator, callback) {
var results = [];
arr = _map(arr, function (x, i) {
return {index: i, value: x};
});
eachfn(arr, function (x, callback) {
iterator(x.value, function (v) {
if (!v) {
results.push(x);
}
callback();
});
}, function (err) {
callback(_map(results.sort(function (a, b) {
return a.index - b.index;
}), function (x) {
return x.value;
}));
});
};
async.reject = doParallel(_reject);
async.rejectSeries = doSeries(_reject);
var _detect = function (eachfn, arr, iterator, main_callback) {
eachfn(arr, function (x, callback) {
iterator(x, function (result) {
if (result) {
main_callback(x);
}
else {
callback();
}
});
}, function (err) {
main_callback();
});
};
async.detect = doParallel(_detect);
async.detectSeries = doSeries(_detect);
async.some = function (arr, iterator, main_callback) {
async.forEach(arr, function (x, callback) {
iterator(x, function (v) {
if (v) {
main_callback(true);
main_callback = function () {};
}
callback();
});
}, function (err) {
main_callback(false);
});
};
// any alias
async.any = async.some;
async.every = function (arr, iterator, main_callback) {
async.forEach(arr, function (x, callback) {
iterator(x, function (v) {
if (!v) {
main_callback(false);
main_callback = function () {};
}
callback();
});
}, function (err) {
main_callback(true);
});
};
// all alias
async.all = async.every;
async.sortBy = function (arr, iterator, callback) {
async.map(arr, function (x, callback) {
iterator(x, function (err, criteria) {
if (err) {
callback(err);
}
else {
callback(null, {value: x, criteria: criteria});
}
});
}, function (err, results) {
if (err) {
return callback(err);
}
else {
var fn = function (left, right) {
var a = left.criteria, b = right.criteria;
return a < b ? -1 : a > b ? 1 : 0;
};
callback(null, _map(results.sort(fn), function (x) {
return x.value;
}));
}
});
};
async.auto = function (tasks, callback) {
callback = callback || function () {};
var keys = _keys(tasks);
if (!keys.length) {
return callback(null);
}
var completed = [];
var listeners = [];
var addListener = function (fn) {
listeners.unshift(fn);
};
var removeListener = function (fn) {
for (var i = 0; i < listeners.length; i += 1) {
if (listeners[i] === fn) {
listeners.splice(i, 1);
return;
}
}
};
var taskComplete = function () {
_forEach(listeners, function (fn) {
fn();
});
};
addListener(function () {
if (completed.length === keys.length) {
callback(null);
}
});
_forEach(keys, function (k) {
var task = (tasks[k] instanceof Function) ? [tasks[k]]: tasks[k];
var taskCallback = function (err) {
if (err) {
callback(err);
// stop subsequent errors hitting callback multiple times
callback = function () {};
}
else {
completed.push(k);
taskComplete();
}
};
var requires = task.slice(0, Math.abs(task.length - 1)) || [];
var ready = function () {
return _reduce(requires, function (a, x) {
return (a && _indexOf(completed, x) !== -1);
}, true);
};
if (ready()) {
task[task.length - 1](taskCallback);
}
else {
var listener = function () {
if (ready()) {
removeListener(listener);
task[task.length - 1](taskCallback);
}
};
addListener(listener);
}
});
};
async.waterfall = function (tasks, callback) {
if (!tasks.length) {
return callback();
}
callback = callback || function () {};
var wrapIterator = function (iterator) {
return function (err) {
if (err) {
callback(err);
callback = function () {};
}
else {
var args = Array.prototype.slice.call(arguments, 1);
var next = iterator.next();
if (next) {
args.push(wrapIterator(next));
}
else {
args.push(callback);
}
async.nextTick(function () {
iterator.apply(null, args);
});
}
};
};
wrapIterator(async.iterator(tasks))();
};
async.parallel = function (tasks, callback) {
callback = callback || function () {};
if (tasks.constructor === Array) {
async.map(tasks, function (fn, callback) {
if (fn) {
fn(function (err) {
var args = Array.prototype.slice.call(arguments, 1);
if (args.length <= 1) {
args = args[0];
}
callback.call(null, err, args || null);
});
}
}, callback);
}
else {
var results = {};
async.forEach(_keys(tasks), function (k, callback) {
tasks[k](function (err) {
var args = Array.prototype.slice.call(arguments, 1);
if (args.length <= 1) {
args = args[0];
}
results[k] = args;
callback(err);
});
}, function (err) {
callback(err, results);
});
}
};
async.series = function (tasks, callback) {
callback = callback || function () {};
if (tasks.constructor === Array) {
async.mapSeries(tasks, function (fn, callback) {
if (fn) {
fn(function (err) {
var args = Array.prototype.slice.call(arguments, 1);
if (args.length <= 1) {
args = args[0];
}
callback.call(null, err, args || null);
});
}
}, callback);
}
else {
var results = {};
async.forEachSeries(_keys(tasks), function (k, callback) {
tasks[k](function (err) {
var args = Array.prototype.slice.call(arguments, 1);
if (args.length <= 1) {
args = args[0];
}
results[k] = args;
callback(err);
});
}, function (err) {
callback(err, results);
});
}
};
async.iterator = function (tasks) {
var makeCallback = function (index) {
var fn = function () {
if (tasks.length) {
tasks[index].apply(null, arguments);
}
return fn.next();
};
fn.next = function () {
return (index < tasks.length - 1) ? makeCallback(index + 1): null;
};
return fn;
};
return makeCallback(0);
};
async.apply = function (fn) {
var args = Array.prototype.slice.call(arguments, 1);
return function () {
return fn.apply(
null, args.concat(Array.prototype.slice.call(arguments))
);
};
};
var _concat = function (eachfn, arr, fn, callback) {
var r = [];
eachfn(arr, function (x, cb) {
fn(x, function (err, y) {
r = r.concat(y || []);
cb(err);
});
}, function (err) {
callback(err, r);
});
};
async.concat = doParallel(_concat);
async.concatSeries = doSeries(_concat);
async.whilst = function (test, iterator, callback) {
if (test()) {
iterator(function (err) {
if (err) {
return callback(err);
}
async.whilst(test, iterator, callback);
});
}
else {
callback();
}
};
async.until = function (test, iterator, callback) {
if (!test()) {
iterator(function (err) {
if (err) {
return callback(err);
}
async.until(test, iterator, callback);
});
}
else {
callback();
}
};
async.queue = function (worker, concurrency) {
var workers = 0;
var tasks = [];
var q = {
concurrency: concurrency,
push: function (data, callback) {
tasks.push({data: data, callback: callback});
async.nextTick(q.process);
},
process: function () {
if (workers < q.concurrency && tasks.length) {
var task = tasks.splice(0, 1)[0];
workers += 1;
worker(task.data, function () {
workers -= 1;
if (task.callback) {
task.callback.apply(task, arguments);
}
q.process();
});
}
},
length: function () {
return tasks.length;
}
};
return q;
};
var _console_fn = function (name) {
return function (fn) {
var args = Array.prototype.slice.call(arguments, 1);
fn.apply(null, args.concat([function (err) {
var args = Array.prototype.slice.call(arguments, 1);
if (typeof console !== 'undefined') {
if (err) {
if (console.error) {
console.error(err);
}
}
else if (console[name]) {
_forEach(args, function (x) {
console[name](x);
});
}
}
}]));
};
};
async.log = _console_fn('log');
async.dir = _console_fn('dir');
/*async.info = _console_fn('info');
async.warn = _console_fn('warn');
async.error = _console_fn('error');*/
async.memoize = function (fn, hasher) {
var memo = {};
hasher = hasher || function (x) {
return x;
};
return function () {
var args = Array.prototype.slice.call(arguments);
var callback = args.pop();
var key = hasher.apply(null, args);
if (key in memo) {
callback.apply(null, memo[key]);
}
else {
fn.apply(null, args.concat([function () {
memo[key] = arguments;
callback.apply(null, arguments);
}]));
}
};
};
}());

55
bin/node_modules/nodeunit/deps/console.log.js generated vendored Normal file
View File

@ -0,0 +1,55 @@
/*
A console.log that won't leave you hanging when node exits
90% of this file was ripped from node.js
License: see: https://github.com/joyent/node/blob/master/lib/console.js
*/
// console object
var formatRegExp = /%[sdj]/g;
function format(f) {
var util = require('util');
if (typeof f !== 'string') {
var objects = [];
for (var i = 0; i < arguments.length; i++) {
objects.push(util.inspect(arguments[i]));
}
return objects.join(' ');
}
var i = 1;
var args = arguments;
var str = String(f).replace(formatRegExp, function(x) {
switch (x) {
case '%s': return String(args[i++]);
case '%d': return Number(args[i++]);
case '%j': return JSON.stringify(args[i++]);
default:
return x;
}
});
for (var len = args.length, x = args[i]; i < len; x = args[++i]) {
if (x === null || typeof x !== 'object') {
str += ' ' + x;
} else {
str += ' ' + util.inspect(x);
}
}
return str;
}
console.log = function() {
var res = process.stdout.write(format.apply(this, arguments) + '\n');
// this is the first time stdout got backed up
if (!res && !process.stdout.pendingWrite) {
process.stdout.pendingWrite = true;
// magic sauce: keep node alive until stdout has flushed
process.stdout.once('drain', function () {
process.stdout.draining = false;
});
}
};

125
bin/node_modules/nodeunit/deps/ejs.js generated vendored Normal file
View File

@ -0,0 +1,125 @@
/*!
* EJS
* Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
* MIT Licensed
*/
/**
* Module dependencies.
*/
var sys = require('sys');
/**
* Library version.
*/
exports.version = '0.0.3';
/**
* Intermediate js cache.
*
* @type Object
*/
var cache = {};
/**
* Clear intermediate js cache.
*
* @api public
*/
exports.clearCache = function(){
cache = {};
};
/**
* Escape the given string of `html`.
*
* @param {String} html
* @return {String}
* @api private
*/
function escape(html){
return String(html)
.replace(/&(?!\w+;)/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;');
}
/**
* Parse the given `str` of ejs, returning the function body.
*
* @param {String} str
* @return {String}
* @api public
*/
var parse = exports.parse = function(str){
return 'var buf = [];\n'
+ "with (locals) {\nbuf.push('"
+ String(str)
.replace(/[\r\t]/g, " ")
.replace(/\n/g, "\\n")
.split("<%").join("\t")
.replace(/((^|%>)[^\t]*)'/g, "$1\r")
.replace(/\t=(.*?)%>/g, "', escape($1) ,'")
.replace(/\t-(.*?)%>/g, "', $1 ,'")
.split("\t").join("');")
.split("%>").join("buf.push('")
.split("\r").join("\\'")
+ "');\n}\nreturn buf.join('');";
};
/**
* Compile the given `str` of ejs into a `Function`.
*
* @param {String} str
* @param {Object} options
* @return {Function}
* @api public
*/
var compile = exports.compile = function(str, options){
if (options.debug) sys.puts(parse(str));
return new Function('locals, escape', parse(str));
};
/**
* Render the given `str` of ejs.
*
* Options:
*
* - `locals` Local variables object
* - `cache` Compiled functions are cached, requires `filename`
* - `filename` Used by `cache` to key caches
* - `context|scope` Function execution context
* - `debug` Output generated function body
*
* @param {String} str
* @param {Object} options
* @return {String}
* @api public
*/
exports.render = function(str, options){
var fn,
options = options || {};
if (options.cache) {
if (options.filename) {
fn = cache[options.filename] = compile(str, options);
} else {
throw new Error('"cache" option requires "filename".');
}
} else {
fn = compile(str, options);
}
return fn.call(
options.context || options.scope,
options.locals || {},
escape);
};

483
bin/node_modules/nodeunit/deps/json2.js generated vendored Normal file
View File

@ -0,0 +1,483 @@
/*
http://www.JSON.org/json2.js
2010-11-17
Public Domain.
NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
See http://www.JSON.org/js.html
This code should be minified before deployment.
See http://javascript.crockford.com/jsmin.html
USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
NOT CONTROL.
This file creates a global JSON object containing two methods: stringify
and parse.
JSON.stringify(value, replacer, space)
value any JavaScript value, usually an object or array.
replacer an optional parameter that determines how object
values are stringified for objects. It can be a
function or an array of strings.
space an optional parameter that specifies the indentation
of nested structures. If it is omitted, the text will
be packed without extra whitespace. If it is a number,
it will specify the number of spaces to indent at each
level. If it is a string (such as '\t' or '&nbsp;'),
it contains the characters used to indent at each level.
This method produces a JSON text from a JavaScript value.
When an object value is found, if the object contains a toJSON
method, its toJSON method will be called and the result will be
stringified. A toJSON method does not serialize: it returns the
value represented by the name/value pair that should be serialized,
or undefined if nothing should be serialized. The toJSON method
will be passed the key associated with the value, and this will be
bound to the value
For example, this would serialize Dates as ISO strings.
Date.prototype.toJSON = function (key) {
function f(n) {
// Format integers to have at least two digits.
return n < 10 ? '0' + n : n;
}
return this.getUTCFullYear() + '-' +
f(this.getUTCMonth() + 1) + '-' +
f(this.getUTCDate()) + 'T' +
f(this.getUTCHours()) + ':' +
f(this.getUTCMinutes()) + ':' +
f(this.getUTCSeconds()) + 'Z';
};
You can provide an optional replacer method. It will be passed the
key and value of each member, with this bound to the containing
object. The value that is returned from your method will be
serialized. If your method returns undefined, then the member will
be excluded from the serialization.
If the replacer parameter is an array of strings, then it will be
used to select the members to be serialized. It filters the results
such that only members with keys listed in the replacer array are
stringified.
Values that do not have JSON representations, such as undefined or
functions, will not be serialized. Such values in objects will be
dropped; in arrays they will be replaced with null. You can use
a replacer function to replace those with JSON values.
JSON.stringify(undefined) returns undefined.
The optional space parameter produces a stringification of the
value that is filled with line breaks and indentation to make it
easier to read.
If the space parameter is a non-empty string, then that string will
be used for indentation. If the space parameter is a number, then
the indentation will be that many spaces.
Example:
text = JSON.stringify(['e', {pluribus: 'unum'}]);
// text is '["e",{"pluribus":"unum"}]'
text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
// text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'
text = JSON.stringify([new Date()], function (key, value) {
return this[key] instanceof Date ?
'Date(' + this[key] + ')' : value;
});
// text is '["Date(---current time---)"]'
JSON.parse(text, reviver)
This method parses a JSON text to produce an object or array.
It can throw a SyntaxError exception.
The optional reviver parameter is a function that can filter and
transform the results. It receives each of the keys and values,
and its return value is used instead of the original value.
If it returns what it received, then the structure is not modified.
If it returns undefined then the member is deleted.
Example:
// Parse the text. Values that look like ISO date strings will
// be converted to Date objects.
myData = JSON.parse(text, function (key, value) {
var a;
if (typeof value === 'string') {
a =
/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
if (a) {
return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
+a[5], +a[6]));
}
}
return value;
});
myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
var d;
if (typeof value === 'string' &&
value.slice(0, 5) === 'Date(' &&
value.slice(-1) === ')') {
d = new Date(value.slice(5, -1));
if (d) {
return d;
}
}
return value;
});
This is a reference implementation. You are free to copy, modify, or
redistribute.
*/
/*jslint evil: true, strict: false, regexp: false */
/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
lastIndex, length, parse, prototype, push, replace, slice, stringify,
test, toJSON, toString, valueOf
*/
// Create a JSON object only if one does not already exist. We create the
// methods in a closure to avoid creating global variables.
if (!this.JSON) {
this.JSON = {};
}
(function () {
"use strict";
function f(n) {
// Format integers to have at least two digits.
return n < 10 ? '0' + n : n;
}
if (typeof Date.prototype.toJSON !== 'function') {
Date.prototype.toJSON = function (key) {
return isFinite(this.valueOf()) ?
this.getUTCFullYear() + '-' +
f(this.getUTCMonth() + 1) + '-' +
f(this.getUTCDate()) + 'T' +
f(this.getUTCHours()) + ':' +
f(this.getUTCMinutes()) + ':' +
f(this.getUTCSeconds()) + 'Z' : null;
};
String.prototype.toJSON =
Number.prototype.toJSON =
Boolean.prototype.toJSON = function (key) {
return this.valueOf();
};
}
var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
gap,
indent,
meta = { // table of character substitutions
'\b': '\\b',
'\t': '\\t',
'\n': '\\n',
'\f': '\\f',
'\r': '\\r',
'"' : '\\"',
'\\': '\\\\'
},
rep;
function quote(string) {
// If the string contains no control characters, no quote characters, and no
// backslash characters, then we can safely slap some quotes around it.
// Otherwise we must also replace the offending characters with safe escape
// sequences.
escapable.lastIndex = 0;
return escapable.test(string) ?
'"' + string.replace(escapable, function (a) {
var c = meta[a];
return typeof c === 'string' ? c :
'\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
}) + '"' :
'"' + string + '"';
}
function str(key, holder) {
// Produce a string from holder[key].
var i, // The loop counter.
k, // The member key.
v, // The member value.
length,
mind = gap,
partial,
value = holder[key];
// If the value has a toJSON method, call it to obtain a replacement value.
if (value && typeof value === 'object' &&
typeof value.toJSON === 'function') {
value = value.toJSON(key);
}
// If we were called with a replacer function, then call the replacer to
// obtain a replacement value.
if (typeof rep === 'function') {
value = rep.call(holder, key, value);
}
// What happens next depends on the value's type.
switch (typeof value) {
case 'string':
return quote(value);
case 'number':
// JSON numbers must be finite. Encode non-finite numbers as null.
return isFinite(value) ? String(value) : 'null';
case 'boolean':
case 'null':
// If the value is a boolean or null, convert it to a string. Note:
// typeof null does not produce 'null'. The case is included here in
// the remote chance that this gets fixed someday.
return String(value);
// If the type is 'object', we might be dealing with an object or an array or
// null.
case 'object':
// Due to a specification blunder in ECMAScript, typeof null is 'object',
// so watch out for that case.
if (!value) {
return 'null';
}
// Make an array to hold the partial results of stringifying this object value.
gap += indent;
partial = [];
// Is the value an array?
if (Object.prototype.toString.apply(value) === '[object Array]') {
// The value is an array. Stringify every element. Use null as a placeholder
// for non-JSON values.
length = value.length;
for (i = 0; i < length; i += 1) {
partial[i] = str(i, value) || 'null';
}
// Join all of the elements together, separated with commas, and wrap them in
// brackets.
v = partial.length === 0 ? '[]' :
gap ? '[\n' + gap +
partial.join(',\n' + gap) + '\n' +
mind + ']' :
'[' + partial.join(',') + ']';
gap = mind;
return v;
}
// If the replacer is an array, use it to select the members to be stringified.
if (rep && typeof rep === 'object') {
length = rep.length;
for (i = 0; i < length; i += 1) {
k = rep[i];
if (typeof k === 'string') {
v = str(k, value);
if (v) {
partial.push(quote(k) + (gap ? ': ' : ':') + v);
}
}
}
} else {
// Otherwise, iterate through all of the keys in the object.
for (k in value) {
if (Object.hasOwnProperty.call(value, k)) {
v = str(k, value);
if (v) {
partial.push(quote(k) + (gap ? ': ' : ':') + v);
}
}
}
}
// Join all of the member texts together, separated with commas,
// and wrap them in braces.
v = partial.length === 0 ? '{}' :
gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' +
mind + '}' : '{' + partial.join(',') + '}';
gap = mind;
return v;
}
}
// If the JSON object does not yet have a stringify method, give it one.
if (typeof JSON.stringify !== 'function') {
JSON.stringify = function (value, replacer, space) {
// The stringify method takes a value and an optional replacer, and an optional
// space parameter, and returns a JSON text. The replacer can be a function
// that can replace values, or an array of strings that will select the keys.
// A default replacer method can be provided. Use of the space parameter can
// produce text that is more easily readable.
var i;
gap = '';
indent = '';
// If the space parameter is a number, make an indent string containing that
// many spaces.
if (typeof space === 'number') {
for (i = 0; i < space; i += 1) {
indent += ' ';
}
// If the space parameter is a string, it will be used as the indent string.
} else if (typeof space === 'string') {
indent = space;
}
// If there is a replacer, it must be a function or an array.
// Otherwise, throw an error.
rep = replacer;
if (replacer && typeof replacer !== 'function' &&
(typeof replacer !== 'object' ||
typeof replacer.length !== 'number')) {
throw new Error('JSON.stringify');
}
// Make a fake root object containing our value under the key of ''.
// Return the result of stringifying the value.
return str('', {'': value});
};
}
// If the JSON object does not yet have a parse method, give it one.
if (typeof JSON.parse !== 'function') {
JSON.parse = function (text, reviver) {
// The parse method takes a text and an optional reviver function, and returns
// a JavaScript value if the text is a valid JSON text.
var j;
function walk(holder, key) {
// The walk method is used to recursively walk the resulting structure so
// that modifications can be made.
var k, v, value = holder[key];
if (value && typeof value === 'object') {
for (k in value) {
if (Object.hasOwnProperty.call(value, k)) {
v = walk(value, k);
if (v !== undefined) {
value[k] = v;
} else {
delete value[k];
}
}
}
}
return reviver.call(holder, key, value);
}
// Parsing happens in four stages. In the first stage, we replace certain
// Unicode characters with escape sequences. JavaScript handles many characters
// incorrectly, either silently deleting them, or treating them as line endings.
text = String(text);
cx.lastIndex = 0;
if (cx.test(text)) {
text = text.replace(cx, function (a) {
return '\\u' +
('0000' + a.charCodeAt(0).toString(16)).slice(-4);
});
}
// In the second stage, we run the text against regular expressions that look
// for non-JSON patterns. We are especially concerned with '()' and 'new'
// because they can cause invocation, and '=' because it can cause mutation.
// But just to be safe, we want to reject all unexpected forms.
// We split the second stage into 4 regexp operations in order to work around
// crippling inefficiencies in IE's and Safari's regexp engines. First we
// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
// replace all simple value tokens with ']' characters. Third, we delete all
// open brackets that follow a colon or comma or that begin the text. Finally,
// we look to see that the remaining characters are only whitespace or ']' or
// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
if (/^[\],:{}\s]*$/
.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')
.replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
// In the third stage we use the eval function to compile the text into a
// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
// in JavaScript: it can begin a block or an object literal. We wrap the text
// in parens to eliminate the ambiguity.
j = eval('(' + text + ')');
// In the optional fourth stage, we recursively walk the new structure, passing
// each name/value pair to a reviver function for possible transformation.
return typeof reviver === 'function' ?
walk({'': j}, '') : j;
}
// If the text is not JSON parseable, then a SyntaxError is thrown.
throw new SyntaxError('JSON.parse');
};
}
}());

60
bin/node_modules/nodeunit/doc/nodeunit.md generated vendored Normal file
View File

@ -0,0 +1,60 @@
nodeunit(1) -- simple node.js unit testing tool
===============================================
## SYNOPSIS
nodeunit [options] <file-or-directory> [<file-or-directory> ...]
## DESCRIPTION
Nodeunit is a simple unit testing tool based on the node.js assert module.
* Simple to use
* Just export the tests from a module
* Helps you avoid common pitfalls when testing asynchronous code
* Easy to add test cases with setUp and tearDown functions if you wish
* Allows the use of mocks and stubs
## OPTIONS
__--config FILE__:
Load config options from a JSON file, allows the customisation
of color schemes for the default test reporter etc.
See bin/nodeunit.json for current available options.
__--reporter FILE__:
You can set the test reporter to a custom module or on of the modules
in nodeunit/lib/reporters, when omitted, the default test runner is used.
__--list-reporters__:
List available build-in reporters.
__-h__, __--help__:
Display the help and exit.
__-v__, __--version__:
Output version information and exit.
__<file-or-directory>__:
You can run nodeunit on specific files or on all *\*.js* files inside
a directory.
## AUTHORS
Written by Caolan McMahon and other nodeunit contributors.
Contributors list: <http://github.com/caolan/nodeunit/contributors>.
## REPORTING BUGS
Report nodeunit bugs to <http://github.com/caolan/nodeunit/issues>.
## COPYRIGHT
Copyright © 2010 Caolan McMahon.
Nodeunit has been released under the MIT license:
<http://github.com/caolan/nodeunit/raw/master/LICENSE>.
## SEE ALSO
node(1)

1757
bin/node_modules/nodeunit/examples/browser/nodeunit.js generated vendored Normal file

File diff suppressed because it is too large Load Diff

12
bin/node_modules/nodeunit/examples/browser/suite1.js generated vendored Normal file
View File

@ -0,0 +1,12 @@
this.suite1 = {
'test one': function (test) {
test.ok(true, 'everythings ok');
setTimeout(function () {
test.done();
}, 10);
},
'apples and oranges': function (test) {
test.equal('apples', 'oranges', 'comparing apples and oranges');
test.done();
}
};

13
bin/node_modules/nodeunit/examples/browser/suite2.js generated vendored Normal file
View File

@ -0,0 +1,13 @@
this.suite2 = {
'another test': function (test) {
setTimeout(function () {
// lots of assertions
test.ok(true, 'everythings ok');
test.ok(true, 'everythings ok');
test.ok(true, 'everythings ok');
test.ok(true, 'everythings ok');
test.ok(true, 'everythings ok');
test.done();
}, 10);
}
};

16
bin/node_modules/nodeunit/examples/browser/test.html generated vendored Normal file
View File

@ -0,0 +1,16 @@
<html>
<head>
<title>Example tests</title>
<script src="nodeunit.js"></script>
<script src="suite1.js"></script>
<script src="suite2.js"></script>
</head>
<body>
<script>
nodeunit.run({
'suite1': suite1,
'suite2': suite2
});
</script>
</body>
</html>

BIN
bin/node_modules/nodeunit/img/example_fail.png generated vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

BIN
bin/node_modules/nodeunit/img/example_pass.png generated vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

3
bin/node_modules/nodeunit/index.js generated vendored Normal file
View File

@ -0,0 +1,3 @@
// This file is just added for convenience so this repository can be
// directly checked out into a project's deps folder
module.exports = require('./lib/nodeunit');

316
bin/node_modules/nodeunit/lib/assert.js generated vendored Normal file
View File

@ -0,0 +1,316 @@
/**
* This file is based on the node.js assert module, but with some small
* changes for browser-compatibility
* THIS FILE SHOULD BE BROWSER-COMPATIBLE JS!
*/
/**
* Added for browser compatibility
*/
var _keys = function(obj){
if(Object.keys) return Object.keys(obj);
var keys = [];
for(var k in obj){
if(obj.hasOwnProperty(k)) keys.push(k);
}
return keys;
};
// http://wiki.commonjs.org/wiki/Unit_Testing/1.0
//
// THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8!
//
// Originally from narwhal.js (http://narwhaljs.org)
// Copyright (c) 2009 Thomas Robinson <280north.com>
//
// 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 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.
var pSlice = Array.prototype.slice;
// 1. The assert module provides functions that throw
// AssertionError's when particular conditions are not met. The
// assert module must conform to the following interface.
var assert = exports;
// 2. The AssertionError is defined in assert.
// new assert.AssertionError({message: message, actual: actual, expected: expected})
assert.AssertionError = function AssertionError (options) {
this.name = "AssertionError";
this.message = options.message;
this.actual = options.actual;
this.expected = options.expected;
this.operator = options.operator;
var stackStartFunction = options.stackStartFunction || fail;
if (Error.captureStackTrace) {
Error.captureStackTrace(this, stackStartFunction);
}
};
// code from util.inherits in node
assert.AssertionError.super_ = Error;
// EDITED FOR BROWSER COMPATIBILITY: replaced Object.create call
// TODO: test what effect this may have
var ctor = function () { this.constructor = assert.AssertionError; };
ctor.prototype = Error.prototype;
assert.AssertionError.prototype = new ctor();
assert.AssertionError.prototype.toString = function() {
if (this.message) {
return [this.name+":", this.message].join(' ');
} else {
return [ this.name+":"
, JSON.stringify(this.expected )
, this.operator
, JSON.stringify(this.actual)
].join(" ");
}
};
// assert.AssertionError instanceof Error
assert.AssertionError.__proto__ = Error.prototype;
// At present only the three keys mentioned above are used and
// understood by the spec. Implementations or sub modules can pass
// other keys to the AssertionError's constructor - they will be
// ignored.
// 3. All of the following functions must throw an AssertionError
// when a corresponding condition is not met, with a message that
// may be undefined if not provided. All assertion methods provide
// both the actual and expected values to the assertion error for
// display purposes.
function fail(actual, expected, message, operator, stackStartFunction) {
throw new assert.AssertionError({
message: message,
actual: actual,
expected: expected,
operator: operator,
stackStartFunction: stackStartFunction
});
}
// EXTENSION! allows for well behaved errors defined elsewhere.
assert.fail = fail;
// 4. Pure assertion tests whether a value is truthy, as determined
// by !!guard.
// assert.ok(guard, message_opt);
// This statement is equivalent to assert.equal(true, guard,
// message_opt);. To test strictly for the value true, use
// assert.strictEqual(true, guard, message_opt);.
assert.ok = function ok(value, message) {
if (!!!value) fail(value, true, message, "==", assert.ok);
};
// 5. The equality assertion tests shallow, coercive equality with
// ==.
// assert.equal(actual, expected, message_opt);
assert.equal = function equal(actual, expected, message) {
if (actual != expected) fail(actual, expected, message, "==", assert.equal);
};
// 6. The non-equality assertion tests for whether two objects are not equal
// with != assert.notEqual(actual, expected, message_opt);
assert.notEqual = function notEqual(actual, expected, message) {
if (actual == expected) {
fail(actual, expected, message, "!=", assert.notEqual);
}
};
// 7. The equivalence assertion tests a deep equality relation.
// assert.deepEqual(actual, expected, message_opt);
assert.deepEqual = function deepEqual(actual, expected, message) {
if (!_deepEqual(actual, expected)) {
fail(actual, expected, message, "deepEqual", assert.deepEqual);
}
};
function _deepEqual(actual, expected) {
// 7.1. All identical values are equivalent, as determined by ===.
if (actual === expected) {
return true;
// 7.2. If the expected value is a Date object, the actual value is
// equivalent if it is also a Date object that refers to the same time.
} else if (actual instanceof Date && expected instanceof Date) {
return actual.getTime() === expected.getTime();
// 7.3. Other pairs that do not both pass typeof value == "object",
// equivalence is determined by ==.
} else if (typeof actual != 'object' && typeof expected != 'object') {
return actual == expected;
// 7.4. For all other Object pairs, including Array objects, equivalence is
// determined by having the same number of owned properties (as verified
// with Object.prototype.hasOwnProperty.call), the same set of keys
// (although not necessarily the same order), equivalent values for every
// corresponding key, and an identical "prototype" property. Note: this
// accounts for both named and indexed properties on Arrays.
} else {
return objEquiv(actual, expected);
}
}
function isUndefinedOrNull (value) {
return value === null || value === undefined;
}
function isArguments (object) {
return Object.prototype.toString.call(object) == '[object Arguments]';
}
function objEquiv (a, b) {
if (isUndefinedOrNull(a) || isUndefinedOrNull(b))
return false;
// an identical "prototype" property.
if (a.prototype !== b.prototype) return false;
//~~~I've managed to break Object.keys through screwy arguments passing.
// Converting to array solves the problem.
if (isArguments(a)) {
if (!isArguments(b)) {
return false;
}
a = pSlice.call(a);
b = pSlice.call(b);
return _deepEqual(a, b);
}
try{
var ka = _keys(a),
kb = _keys(b),
key, i;
} catch (e) {//happens when one is a string literal and the other isn't
return false;
}
// having the same number of owned properties (keys incorporates hasOwnProperty)
if (ka.length != kb.length)
return false;
//the same set of keys (although not necessarily the same order),
ka.sort();
kb.sort();
//~~~cheap key test
for (i = ka.length - 1; i >= 0; i--) {
if (ka[i] != kb[i])
return false;
}
//equivalent values for every corresponding key, and
//~~~possibly expensive deep test
for (i = ka.length - 1; i >= 0; i--) {
key = ka[i];
if (!_deepEqual(a[key], b[key] ))
return false;
}
return true;
}
// 8. The non-equivalence assertion tests for any deep inequality.
// assert.notDeepEqual(actual, expected, message_opt);
assert.notDeepEqual = function notDeepEqual(actual, expected, message) {
if (_deepEqual(actual, expected)) {
fail(actual, expected, message, "notDeepEqual", assert.notDeepEqual);
}
};
// 9. The strict equality assertion tests strict equality, as determined by ===.
// assert.strictEqual(actual, expected, message_opt);
assert.strictEqual = function strictEqual(actual, expected, message) {
if (actual !== expected) {
fail(actual, expected, message, "===", assert.strictEqual);
}
};
// 10. The strict non-equality assertion tests for strict inequality, as determined by !==.
// assert.notStrictEqual(actual, expected, message_opt);
assert.notStrictEqual = function notStrictEqual(actual, expected, message) {
if (actual === expected) {
fail(actual, expected, message, "!==", assert.notStrictEqual);
}
};
function _throws (shouldThrow, block, err, message) {
var exception = null,
threw = false,
typematters = true;
message = message || "";
//handle optional arguments
if (arguments.length == 3) {
if (typeof(err) == "string") {
message = err;
typematters = false;
}
} else if (arguments.length == 2) {
typematters = false;
}
try {
block();
} catch (e) {
threw = true;
exception = e;
}
if (shouldThrow && !threw) {
fail( "Missing expected exception"
+ (err && err.name ? " ("+err.name+")." : '.')
+ (message ? " " + message : "")
);
}
if (!shouldThrow && threw && typematters && exception instanceof err) {
fail( "Got unwanted exception"
+ (err && err.name ? " ("+err.name+")." : '.')
+ (message ? " " + message : "")
);
}
if ((shouldThrow && threw && typematters && !(exception instanceof err)) ||
(!shouldThrow && threw)) {
throw exception;
}
};
// 11. Expected to throw an error:
// assert.throws(block, Error_opt, message_opt);
assert.throws = function(block, /*optional*/error, /*optional*/message) {
_throws.apply(this, [true].concat(pSlice.call(arguments)));
};
// EXTENSION! This is annoying to write outside this module.
assert.doesNotThrow = function(block, /*optional*/error, /*optional*/message) {
_throws.apply(this, [false].concat(pSlice.call(arguments)));
};
assert.ifError = function (err) { if (err) {throw err;}};

260
bin/node_modules/nodeunit/lib/core.js generated vendored Normal file
View File

@ -0,0 +1,260 @@
/*!
* Nodeunit
* Copyright (c) 2010 Caolan McMahon
* MIT Licensed
*
* THIS FILE SHOULD BE BROWSER-COMPATIBLE JS!
* You can use @REMOVE_LINE_FOR_BROWSER to remove code from the browser build.
* Only code on that line will be removed, its mostly to avoid requiring code
* that is node specific
*/
/**
* Module dependencies
*/
var async = require('../deps/async'), //@REMOVE_LINE_FOR_BROWSER
types = require('./types'); //@REMOVE_LINE_FOR_BROWSER
/**
* Added for browser compatibility
*/
var _keys = function(obj){
if(Object.keys) return Object.keys(obj);
var keys = [];
for(var k in obj){
if(obj.hasOwnProperty(k)) keys.push(k);
}
return keys;
};
var _copy = function(obj){
var nobj = Object();
var keys = _keys(obj);
for (var i = 0; i < keys.length; i++){
nobj[keys[i]] = obj[keys[i]];
}
return nobj;
}
/**
* Runs a test function (fn) from a loaded module. After the test function
* calls test.done(), the callback is executed with an assertionList as its
* second argument.
*
* @param {String} name
* @param {Function} fn
* @param {Object} opt
* @param {Function} callback
* @api public
*/
exports.runTest = function (name, fn, opt, callback) {
var options = types.options(opt);
options.testStart(name);
var start = new Date().getTime();
var test = types.test(name, start, options, callback);
try {
fn(test);
}
catch (e) {
test.done(e);
}
};
/**
* Takes an object containing test functions or other test suites as properties
* and runs each in series. After all tests have completed, the callback is
* called with a list of all assertions as the second argument.
*
* If a name is passed to this function it is prepended to all test and suite
* names that run within it.
*
* @param {String} name
* @param {Object} suite
* @param {Object} opt
* @param {Function} callback
* @api public
*/
exports.runSuite = function (name, suite, opt, callback) {
var keys = _keys(suite);
async.concatSeries(keys, function (k, cb) {
var prop = suite[k], _name;
_name = name ? [].concat(name, k) : [k];
_name.toString = function () {
// fallback for old one
return this.join(' - ');
};
if (typeof prop === 'function') {
if (!opt.testspec || _name.indexOf(opt.testspec) != -1){
if (opt.moduleStart)
opt.moduleStart();
exports.runTest(_name, suite[k], opt, cb);
} else
return cb();
}
else {
exports.runSuite(_name, suite[k], opt, cb);
}
}, callback);
};
/**
* Run each exported test function or test suite from a loaded module.
*
* @param {String} name
* @param {Object} mod
* @param {Object} opt
* @param {Function} callback
* @api public
*/
exports.runModule = function (name, mod, opt, callback) {
var options = _copy(types.options(opt));
var _run = false;
var _moduleStart = options.moduleStart;
function run_once(){
if (!_run){
_run = true;
_moduleStart(name);
}
}
options.moduleStart = run_once;
var start = new Date().getTime();
exports.runSuite(null, mod, options, function (err, a_list) {
var end = new Date().getTime();
var assertion_list = types.assertionList(a_list, end - start);
options.moduleDone(name, assertion_list);
callback(null, a_list);
});
};
/**
* Treats an object literal as a list of modules keyed by name. Runs each
* module and finished with calling 'done'. You can think of this as a browser
* safe alternative to runFiles in the nodeunit module.
*
* @param {Object} modules
* @param {Object} opt
* @api public
*/
// TODO: add proper unit tests for this function
exports.runModules = function (modules, opt) {
var all_assertions = [];
var options = types.options(opt);
var start = new Date().getTime();
async.concatSeries(_keys(modules), function (k, cb) {
exports.runModule(k, modules[k], options, cb);
},
function (err, all_assertions) {
var end = new Date().getTime();
options.done(types.assertionList(all_assertions, end - start));
});
};
/**
* Wraps a test function with setUp and tearDown functions.
* Used by testCase.
*
* @param {Function} setUp
* @param {Function} tearDown
* @param {Function} fn
* @api private
*/
var wrapTest = function (setUp, tearDown, fn) {
return function (test) {
var context = {};
if (tearDown) {
var done = test.done;
test.done = function (err) {
try {
tearDown.call(context, function (err2) {
if (err && err2) {
test._assertion_list.push(
types.assertion({error: err})
);
return done(err2);
}
done(err || err2);
});
}
catch (e) {
done(e);
}
};
}
if (setUp) {
setUp.call(context, function (err) {
if (err) {
return test.done(err);
}
fn.call(context, test);
});
}
else {
fn.call(context, test);
}
}
};
/**
* Wraps a group of tests with setUp and tearDown functions.
* Used by testCase.
*
* @param {Function} setUp
* @param {Function} tearDown
* @param {Object} group
* @api private
*/
var wrapGroup = function (setUp, tearDown, group) {
var tests = {};
var keys = _keys(group);
for (var i=0; i<keys.length; i++) {
var k = keys[i];
if (typeof group[k] === 'function') {
tests[k] = wrapTest(setUp, tearDown, group[k]);
}
else if (typeof group[k] === 'object') {
tests[k] = wrapGroup(setUp, tearDown, group[k]);
}
}
return tests;
}
/**
* Utility for wrapping a suite of test functions with setUp and tearDown
* functions.
*
* @param {Object} suite
* @return {Object}
* @api public
*/
exports.testCase = function (suite) {
var setUp = suite.setUp;
var tearDown = suite.tearDown;
delete suite.setUp;
delete suite.tearDown;
return wrapGroup(setUp, tearDown, suite);
};

82
bin/node_modules/nodeunit/lib/nodeunit.js generated vendored Normal file
View File

@ -0,0 +1,82 @@
/*!
* Nodeunit
* Copyright (c) 2010 Caolan McMahon
* MIT Licensed
*/
/**
* Module dependencies
*/
var async = require('../deps/async'),
types = require('./types'),
utils = require('./utils'),
core = require('./core'),
reporters = require('./reporters'),
assert = require('./assert'),
path = require('path');
/**
* Export sub-modules.
*/
exports.types = types;
exports.utils = utils;
exports.reporters = reporters;
exports.assert = assert;
// backwards compatibility
exports.testrunner = {
run: function () {
console.log(
'WARNING: nodeunit.testrunner is going to be deprecated, please ' +
'use nodeunit.reporters.default instead!'
);
return reporters['default'].run.apply(this, arguments);
}
};
/**
* Export all core functions
*/
for (var k in core) {
exports[k] = core[k];
};
/**
* Load modules from paths array and run all exported tests in series. If a path
* is a directory, load all supported file types inside it as modules. This only
* reads 1 level deep in the directory and does not recurse through
* sub-directories.
*
* @param {Array} paths
* @param {Object} opt
* @api public
*/
exports.runFiles = function (paths, opt) {
var all_assertions = [];
var options = types.options(opt);
var start = new Date().getTime();
if (!paths.length) {
return options.done(types.assertionList(all_assertions));
}
utils.modulePaths(paths, function (err, files) {
if (err) throw err;
async.concatSeries(files, function (file, cb) {
var name = path.basename(file);
exports.runModule(name, require(file), options, cb);
},
function (err, all_assertions) {
var end = new Date().getTime();
options.done(types.assertionList(all_assertions, end - start));
});
});
};

119
bin/node_modules/nodeunit/lib/reporters/browser.js generated vendored Normal file
View File

@ -0,0 +1,119 @@
/*!
* Nodeunit
* Copyright (c) 2010 Caolan McMahon
* MIT Licensed
*
* THIS FILE SHOULD BE BROWSER-COMPATIBLE JS!
* You can use @REMOVE_LINE_FOR_BROWSER to remove code from the browser build.
* Only code on that line will be removed, its mostly to avoid requiring code
* that is node specific
*/
/**
* NOTE: this test runner is not listed in index.js because it cannot be
* used with the command-line tool, only inside the browser.
*/
/**
* Reporter info string
*/
exports.info = "Browser-based test reporter";
/**
* Run all tests within each module, reporting the results
*
* @param {Array} files
* @api public
*/
exports.run = function (modules, options) {
var start = new Date().getTime();
function setText(el, txt) {
if ('innerText' in el) {
el.innerText = txt;
}
else if ('textContent' in el){
el.textContent = txt;
}
}
function getOrCreate(tag, id) {
var el = document.getElementById(id);
if (!el) {
el = document.createElement(tag);
el.id = id;
document.body.appendChild(el);
}
return el;
};
var header = getOrCreate('h1', 'nodeunit-header');
var banner = getOrCreate('h2', 'nodeunit-banner');
var userAgent = getOrCreate('h2', 'nodeunit-userAgent');
var tests = getOrCreate('ol', 'nodeunit-tests');
var result = getOrCreate('p', 'nodeunit-testresult');
setText(userAgent, navigator.userAgent);
nodeunit.runModules(modules, {
moduleStart: function (name) {
/*var mheading = document.createElement('h2');
mheading.innerText = name;
results.appendChild(mheading);
module = document.createElement('ol');
results.appendChild(module);*/
},
testDone: function (name, assertions) {
var test = document.createElement('li');
var strong = document.createElement('strong');
strong.innerHTML = name + ' <b style="color: black;">(' +
'<b class="fail">' + assertions.failures() + '</b>, ' +
'<b class="pass">' + assertions.passes() + '</b>, ' +
assertions.length +
')</b>';
test.className = assertions.failures() ? 'fail': 'pass';
test.appendChild(strong);
var aList = document.createElement('ol');
aList.style.display = 'none';
test.onclick = function () {
var d = aList.style.display;
aList.style.display = (d == 'none') ? 'block': 'none';
};
for (var i=0; i<assertions.length; i++) {
var li = document.createElement('li');
var a = assertions[i];
if (a.failed()) {
li.innerHTML = (a.message || a.method || 'no message') +
'<pre>' + (a.error.stack || a.error) + '</pre>';
li.className = 'fail';
}
else {
li.innerHTML = a.message || a.method || 'no message';
li.className = 'pass';
}
aList.appendChild(li);
}
test.appendChild(aList);
tests.appendChild(test);
},
done: function (assertions) {
var end = new Date().getTime();
var duration = end - start;
var failures = assertions.failures();
banner.className = failures ? 'fail': 'pass';
result.innerHTML = 'Tests completed in ' + duration +
' milliseconds.<br/><span class="passed">' +
assertions.passes() + '</span> assertions of ' +
'<span class="all">' + assertions.length + '<span> passed, ' +
assertions.failures() + ' failed.';
}
});
};

123
bin/node_modules/nodeunit/lib/reporters/default.js generated vendored Normal file
View File

@ -0,0 +1,123 @@
/*!
* Nodeunit
* Copyright (c) 2010 Caolan McMahon
* MIT Licensed
*/
/**
* Module dependencies
*/
var nodeunit = require('../nodeunit'),
utils = require('../utils'),
fs = require('fs'),
track = require('../track'),
path = require('path');
AssertionError = require('../assert').AssertionError;
/**
* Reporter info string
*/
exports.info = "Default tests reporter";
/**
* Run all tests within each module, reporting the results to the command-line.
*
* @param {Array} files
* @api public
*/
exports.run = function (files, options) {
if (!options) {
// load default options
var content = fs.readFileSync(
__dirname + '/../../bin/nodeunit.json', 'utf8'
);
options = JSON.parse(content);
}
var error = function (str) {
return options.error_prefix + str + options.error_suffix;
};
var ok = function (str) {
return options.ok_prefix + str + options.ok_suffix;
};
var bold = function (str) {
return options.bold_prefix + str + options.bold_suffix;
};
var assertion_message = function (str) {
return options.assertion_prefix + str + options.assertion_suffix;
};
var start = new Date().getTime();
var paths = files.map(function (p) {
return path.join(process.cwd(), p);
});
var tracker = track.createTracker(function (tracker) {
if (tracker.unfinished()) {
console.log('');
console.log(error(bold(
'FAILURES: Undone tests (or their setups/teardowns): '
)));
var names = tracker.names();
for (var i = 0; i < names.length; i += 1) {
console.log('- ' + names[i]);
}
console.log('');
console.log('To fix this, make sure all tests call test.done()');
process.reallyExit(tracker.unfinished());
}
});
nodeunit.runFiles(paths, {
testspec: options.testspec,
moduleStart: function (name) {
console.log('\n' + bold(name));
},
testDone: function (name, assertions) {
tracker.remove(name);
if (!assertions.failures()) {
console.log('✔ ' + name);
}
else {
console.log(error('✖ ' + name) + '\n');
assertions.forEach(function (a) {
if (a.failed()) {
a = utils.betterErrors(a);
if (a.error instanceof AssertionError && a.message) {
console.log(
'Assertion Message: ' +
assertion_message(a.message)
);
}
console.log(a.error.stack + '\n');
}
});
}
},
done: function (assertions, end) {
var end = end || new Date().getTime();
var duration = end - start;
if (assertions.failures()) {
console.log(
'\n' + bold(error('FAILURES: ')) + assertions.failures() +
'/' + assertions.length + ' assertions failed (' +
assertions.duration + 'ms)'
);
}
else {
console.log(
'\n' + bold(ok('OK: ')) + assertions.length +
' assertions (' + assertions.duration + 'ms)'
);
}
},
testStart: function(name) {
tracker.put(name);
}
});
};

107
bin/node_modules/nodeunit/lib/reporters/html.js generated vendored Normal file
View File

@ -0,0 +1,107 @@
/*!
* Nodeunit
* Copyright (c) 2010 Caolan McMahon
* MIT Licensed
*/
/**
* Module dependencies
*/
var nodeunit = require('../nodeunit'),
utils = require('../utils'),
fs = require('fs'),
path = require('path'),
AssertionError = require('assert').AssertionError;
/**
* Reporter info string
*/
exports.info = "Report tests result as HTML";
/**
* Run all tests within each module, reporting the results to the command-line.
*
* @param {Array} files
* @api public
*/
exports.run = function (files, options) {
var start = new Date().getTime();
var paths = files.map(function (p) {
return path.join(process.cwd(), p);
});
console.log('<html>');
console.log('<head>');
console.log('<title></title>');
console.log('<style type="text/css">');
console.log('body { font: 12px Helvetica Neue }');
console.log('h2 { margin:0 ; padding:0 }');
console.log('pre { font: 11px Andale Mono; margin-left: 1em; padding-left: 1em; margin-top:0; font-size:smaller;}');
console.log('.assertion_message { margin-left: 1em; }');
console.log(' ol {' +
' list-style: none;' +
' margin-left: 1em;' +
' padding-left: 1em;' +
' text-indent: -1em;' +
'}');
console.log(' ol li.pass:before { content: "\\2714 \\0020"; }');
console.log(' ol li.fail:before { content: "\\2716 \\0020"; }');
console.log('</style>');
console.log('</head>');
console.log('<body>');
nodeunit.runFiles(paths, {
testspec: options.testspec,
moduleStart: function (name) {
console.log('<h2>' + name + '</h2>');
console.log('<ol>');
},
testDone: function (name, assertions) {
if (!assertions.failures()) {
console.log('<li class="pass">' + name + '</li>');
}
else {
console.log('<li class="fail">' + name);
assertions.forEach(function (a) {
if (a.failed()) {
a = utils.betterErrors(a);
if (a.error instanceof AssertionError && a.message) {
console.log('<div class="assertion_message">' +
'Assertion Message: ' + a.message +
'</div>');
}
console.log('<pre>');
console.log(a.error.stack);
console.log('</pre>');
}
});
console.log('</li>');
}
},
moduleDone: function () {
console.log('</ol>');
},
done: function (assertions) {
var end = new Date().getTime();
var duration = end - start;
if (assertions.failures()) {
console.log(
'<h3>FAILURES: ' + assertions.failures() +
'/' + assertions.length + ' assertions failed (' +
assertions.duration + 'ms)</h3>'
);
}
else {
console.log(
'<h3>OK: ' + assertions.length +
' assertions (' + assertions.duration + 'ms)</h3>'
);
}
console.log('</body>');
}
});
};

9
bin/node_modules/nodeunit/lib/reporters/index.js generated vendored Normal file
View File

@ -0,0 +1,9 @@
module.exports = {
'junit': require('./junit'),
'default': require('./default'),
'skip_passed': require('./skip_passed'),
'minimal': require('./minimal'),
'html': require('./html')
// browser test reporter is not listed because it cannot be used
// with the command line tool, only inside a browser.
};

183
bin/node_modules/nodeunit/lib/reporters/junit.js generated vendored Normal file
View File

@ -0,0 +1,183 @@
/*!
* Nodeunit
* Copyright (c) 2010 Caolan McMahon
* MIT Licensed
*/
/**
* Module dependencies
*/
var nodeunit = require('../nodeunit'),
utils = require('../utils'),
fs = require('fs'),
path = require('path'),
async = require('../../deps/async'),
AssertionError = require('assert').AssertionError,
child_process = require('child_process'),
ejs = require('../../deps/ejs');
/**
* Reporter info string
*/
exports.info = "jUnit XML test reports";
/**
* Ensures a directory exists using mkdir -p.
*
* @param {String} path
* @param {Function} callback
* @api private
*/
var ensureDir = function (path, callback) {
var mkdir = child_process.spawn('mkdir', ['-p', path]);
mkdir.on('error', function (err) {
callback(err);
callback = function(){};
});
mkdir.on('exit', function (code) {
if (code === 0) callback();
else callback(new Error('mkdir exited with code: ' + code));
});
};
/**
* Returns absolute version of a path. Relative paths are interpreted
* relative to process.cwd() or the cwd parameter. Paths that are already
* absolute are returned unaltered.
*
* @param {String} p
* @param {String} cwd
* @return {String}
* @api public
*/
var abspath = function (p, /*optional*/cwd) {
if (p[0] === '/') return p;
cwd = cwd || process.cwd();
return path.normalize(path.join(cwd, p));
};
/**
* Run all tests within each module, reporting the results to the command-line,
* then writes out junit-compatible xml documents.
*
* @param {Array} files
* @api public
*/
exports.run = function (files, opts, callback) {
if (!opts.output) {
console.error(
'Error: No output directory defined.\n' +
'\tEither add an "output" property to your nodeunit.json config ' +
'file, or\n\tuse the --output command line option.'
);
return;
}
opts.output = abspath(opts.output);
var error = function (str) {
return opts.error_prefix + str + opts.error_suffix;
};
var ok = function (str) {
return opts.ok_prefix + str + opts.ok_suffix;
};
var bold = function (str) {
return opts.bold_prefix + str + opts.bold_suffix;
};
var start = new Date().getTime();
var paths = files.map(function (p) {
return path.join(process.cwd(), p);
});
var modules = {}
var curModule;
nodeunit.runFiles(paths, {
testspec: opts.testspec,
moduleStart: function (name) {
curModule = {
errorCount: 0,
failureCount: 0,
tests: 0,
testcases: [],
name: name
};
modules[name] = curModule;
},
testDone: function (name, assertions) {
var testcase = {name: name};
for (var i=0; i<assertions.length; i++) {
var a = assertions[i];
if (a.failed()) {
a = utils.betterErrors(a);
testcase.failure = {
message: a.message,
backtrace: a.error.stack
};
if (a.error instanceof AssertionError) {
curModule.failureCount++;
}
else {
curModule.errorCount++;
}
break;
}
}
curModule.tests++;
curModule.testcases.push(testcase);
},
done: function (assertions) {
var end = new Date().getTime();
var duration = end - start;
ensureDir(opts.output, function (err) {
var tmpl = __dirname + "/../../share/junit.xml.ejs";
fs.readFile(tmpl, function (err, data) {
if (err) throw err;
var tmpl = data.toString();
async.forEach(Object.keys(modules), function (k, cb) {
var module = modules[k];
var rendered = ejs.render(tmpl, {
locals: {suites: [module]}
});
var filename = path.join(
opts.output,
module.name + '.xml'
);
console.log('Writing ' + filename);
fs.writeFile(filename, rendered, cb);
},
function (err) {
if (err) throw err;
else if (assertions.failures()) {
console.log(
'\n' + bold(error('FAILURES: ')) +
assertions.failures() + '/' +
assertions.length + ' assertions failed (' +
assertions.duration + 'ms)'
);
}
else {
console.log(
'\n' + bold(ok('OK: ')) + assertions.length +
' assertions (' + assertions.duration + 'ms)'
);
}
});
});
});
}
});
}

112
bin/node_modules/nodeunit/lib/reporters/minimal.js generated vendored Normal file
View File

@ -0,0 +1,112 @@
/*!
* Nodeunit
* Copyright (c) 2010 Caolan McMahon
* MIT Licensed
*/
/**
* Module dependencies
*/
var nodeunit = require('../nodeunit'),
utils = require('../utils'),
fs = require('fs'),
path = require('path'),
AssertionError = require('assert').AssertionError;
/**
* Reporter info string
*/
exports.info = "Pretty minimal output";
/**
* Run all tests within each module, reporting the results to the command-line.
*
* @param {Array} files
* @api public
*/
exports.run = function (files, options) {
if (!options) {
// load default options
var content = fs.readFileSync(
__dirname + '/../../bin/nodeunit.json', 'utf8'
);
options = JSON.parse(content);
}
var red = function (str) {
return options.error_prefix + str + options.error_suffix;
};
var green = function (str) {
return options.ok_prefix + str + options.ok_suffix;
};
var magenta = function (str) {
return options.assertion_prefix + str + options.assertion_suffix;
};
var bold = function (str) {
return options.bold_prefix + str + options.bold_suffix;
};
var start = new Date().getTime();
var paths = files.map(function (p) {
return path.join(process.cwd(), p);
});
nodeunit.runFiles(paths, {
testspec: options.testspec,
moduleStart: function (name) {
process.stdout.write(bold(name) + ': ');
},
moduleDone: function (name, assertions) {
console.log('');
if (assertions.failures()) {
assertions.forEach(function (a) {
if (a.failed()) {
a = utils.betterErrors(a);
if (a.error instanceof AssertionError && a.message) {
console.log(
'Assertion in test ' + bold(a.testname) + ': ' +
magenta(a.message)
);
}
console.log(a.error.stack + '\n');
}
});
}
},
testStart: function () {
},
testDone: function (name, assertions) {
if (!assertions.failures()) {
process.stdout.write('.');
}
else {
process.stdout.write(red('F'));
assertions.forEach(function (assertion) {
assertion.testname = name;
});
}
},
done: function (assertions) {
var end = new Date().getTime();
var duration = end - start;
if (assertions.failures()) {
console.log(
'\n' + bold(red('FAILURES: ')) + assertions.failures() +
'/' + assertions.length + ' assertions failed (' +
assertions.duration + 'ms)'
);
}
else {
console.log(
'\n' + bold(green('OK: ')) + assertions.length +
' assertions (' + assertions.duration + 'ms)'
);
}
}
});
};

105
bin/node_modules/nodeunit/lib/reporters/skip_passed.js generated vendored Normal file
View File

@ -0,0 +1,105 @@
/*!
* Nodeunit
* Copyright (c) 2010 Caolan McMahon
* MIT Licensed
*/
/**
* Module dependencies
*/
var nodeunit = require('../nodeunit'),
utils = require('../utils'),
fs = require('fs'),
path = require('path'),
AssertionError = require('assert').AssertionError;
/**
* Reporter info string
*/
exports.info = "Skip passed tests output";
/**
* Run all tests within each module, reporting the results to the command-line.
*
* @param {Array} files
* @api public
*/
exports.run = function (files, options) {
if (!options) {
// load default options
var content = fs.readFileSync(
__dirname + '/../../bin/nodeunit.json', 'utf8'
);
options = JSON.parse(content);
}
var error = function (str) {
return options.error_prefix + str + options.error_suffix;
};
var ok = function (str) {
return options.ok_prefix + str + options.ok_suffix;
};
var bold = function (str) {
return options.bold_prefix + str + options.bold_suffix;
};
var assertion_message = function (str) {
return options.assertion_prefix + str + options.assertion_suffix;
};
var start = new Date().getTime();
var paths = files.map(function (p) {
return path.join(process.cwd(), p);
});
nodeunit.runFiles(paths, {
testspec: options.testspec,
moduleStart: function (name) {
console.log('\n' + bold(name));
},
testDone: function (name, assertions) {
if (assertions.failures()) {
console.log(error('✖ ' + name) + '\n');
assertions.forEach(function (a) {
if (a.failed()) {
a = utils.betterErrors(a);
if (a.error instanceof AssertionError && a.message) {
console.log(
'Assertion Message: ' + assertion_message(a.message)
);
}
console.log(a.error.stack + '\n');
}
});
}
},
moduleDone: function (name, assertions) {
if (!assertions.failures()) {
console.log('✔ all tests passed');
}
else {
console.log(error('✖ some tests failed'));
}
},
done: function (assertions) {
var end = new Date().getTime();
var duration = end - start;
if (assertions.failures()) {
console.log(
'\n' + bold(error('FAILURES: ')) + assertions.failures() +
'/' + assertions.length + ' assertions failed (' +
assertions.duration + 'ms)'
);
}
else {
console.log(
'\n' + bold(ok('OK: ')) + assertions.length +
' assertions (' + assertions.duration + 'ms)'
);
}
}
});
};

48
bin/node_modules/nodeunit/lib/track.js generated vendored Normal file
View File

@ -0,0 +1,48 @@
/*!
* Simple util module to track tests. Adds a process.exit hook to print
* the undone tests.
*/
exports.createTracker = function (on_exit) {
var names = {};
var tracker = {
names: function () {
var arr = [];
for (var k in names) {
if (names.hasOwnProperty(k)) {
arr.push(k);
}
}
return arr;
},
unfinished: function () {
return tracker.names().length;
},
put: function (testname) {
names[testname] = testname;
},
remove: function (testname) {
delete names[testname];
}
};
process.on('exit', function() {
on_exit = on_exit || exports.default_on_exit;
on_exit(tracker);
});
return tracker;
};
exports.default_on_exit = function (tracker) {
if (tracker.unfinished()) {
console.log('');
console.log('Undone tests (or their setups/teardowns): ');
var names = tracker.names();
for (var i = 0; i < names.length; i += 1) {
console.log(names[i]);
}
process.reallyExit(tracker.unfinished());
}
};

187
bin/node_modules/nodeunit/lib/types.js generated vendored Normal file
View File

@ -0,0 +1,187 @@
/*!
* Nodeunit
* Copyright (c) 2010 Caolan McMahon
* MIT Licensed
*
* THIS FILE SHOULD BE BROWSER-COMPATIBLE JS!
* You can use @REMOVE_LINE_FOR_BROWSER to remove code from the browser build.
* Only code on that line will be removed, its mostly to avoid requiring code
* that is node specific
*/
/**
* Module dependencies
*/
var assert = require('./assert'), //@REMOVE_LINE_FOR_BROWSER
async = require('../deps/async'); //@REMOVE_LINE_FOR_BROWSER
/**
* Creates assertion objects representing the result of an assert call.
* Accepts an object or AssertionError as its argument.
*
* @param {object} obj
* @api public
*/
exports.assertion = function (obj) {
return {
method: obj.method || '',
message: obj.message || (obj.error && obj.error.message) || '',
error: obj.error,
passed: function () {
return !this.error;
},
failed: function () {
return Boolean(this.error);
}
};
};
/**
* Creates an assertion list object representing a group of assertions.
* Accepts an array of assertion objects.
*
* @param {Array} arr
* @param {Number} duration
* @api public
*/
exports.assertionList = function (arr, duration) {
var that = arr || [];
that.failures = function () {
var failures = 0;
for (var i=0; i<this.length; i++) {
if (this[i].failed()) failures++;
}
return failures;
};
that.passes = function () {
return that.length - that.failures();
};
that.duration = duration || 0;
return that;
};
/**
* Create a wrapper function for assert module methods. Executes a callback
* after the it's complete with an assertion object representing the result.
*
* @param {Function} callback
* @api private
*/
var assertWrapper = function (callback) {
return function (new_method, assert_method, arity) {
return function () {
var message = arguments[arity-1];
var a = exports.assertion({method: new_method, message: message});
try {
assert[assert_method].apply(null, arguments);
}
catch (e) {
a.error = e;
}
callback(a);
};
};
};
/**
* Creates the 'test' object that gets passed to every test function.
* Accepts the name of the test function as its first argument, followed by
* the start time in ms, the options object and a callback function.
*
* @param {String} name
* @param {Number} start
* @param {Object} options
* @param {Function} callback
* @api public
*/
exports.test = function (name, start, options, callback) {
var expecting;
var a_list = [];
var wrapAssert = assertWrapper(function (a) {
a_list.push(a);
if (options.log) {
async.nextTick(function () {
options.log(a);
});
}
});
var test = {
done: function (err) {
if (expecting !== undefined && expecting !== a_list.length) {
var e = new Error(
'Expected ' + expecting + ' assertions, ' +
a_list.length + ' ran'
);
var a1 = exports.assertion({method: 'expect', error: e});
a_list.push(a1);
if (options.log) {
async.nextTick(function () {
options.log(a1);
});
}
}
if (err) {
var a2 = exports.assertion({error: err});
a_list.push(a2);
if (options.log) {
async.nextTick(function () {
options.log(a2);
});
}
}
var end = new Date().getTime();
async.nextTick(function () {
var assertion_list = exports.assertionList(a_list, end - start);
options.testDone(name, assertion_list);
callback(null, a_list);
});
},
ok: wrapAssert('ok', 'ok', 2),
same: wrapAssert('same', 'deepEqual', 3),
equals: wrapAssert('equals', 'equal', 3),
expect: function (num) {
expecting = num;
},
_assertion_list: a_list
};
// add all functions from the assert module
for (var k in assert) {
if (assert.hasOwnProperty(k)) {
test[k] = wrapAssert(k, k, assert[k].length);
}
}
return test;
};
/**
* Ensures an options object has all callbacks, adding empty callback functions
* if any are missing.
*
* @param {Object} opt
* @return {Object}
* @api public
*/
exports.options = function (opt) {
var optionalCallback = function (name) {
opt[name] = opt[name] || function () {};
};
optionalCallback('moduleStart');
optionalCallback('moduleDone');
optionalCallback('testStart');
optionalCallback('testDone');
//optionalCallback('log');
// 'done' callback is not optional.
return opt;
};

209
bin/node_modules/nodeunit/lib/utils.js generated vendored Normal file
View File

@ -0,0 +1,209 @@
/*!
* Nodeunit
* Copyright (c) 2010 Caolan McMahon
* MIT Licensed
*/
/**
* Module dependencies
*/
var async = require('../deps/async'),
fs = require('fs'),
util = require('util'),
Script = process.binding('evals').Script,
http = require('http');
/**
* Detect if coffee-script is available and search for .coffee as an
* extension in modulePaths if it is.
*/
var extensionPattern;
try {
require('coffee-script');
extensionPattern = /\.(?:js|coffee)$/;
}
catch (e) {
extensionPattern = /\.js$/;
}
/**
* Finds all modules at each path in an array, If a path is a directory, it
* returns all supported file types inside it. This only reads 1 level deep in
* the directory and does not recurse through sub-directories.
*
* The extension (.js, .coffee etc) is stripped from the filenames so they can
* simply be require()'ed.
*
* @param {Array} paths
* @param {Function} callback
* @api public
*/
exports.modulePaths = function (paths, callback) {
async.concat(paths, function (p, cb) {
fs.stat(p, function (err, stats) {
if (err) {
return cb(err);
}
if (stats.isFile()) {
return cb(null, [p]);
}
if (stats.isDirectory()) {
fs.readdir(p, function (err, files) {
if (err) {
return cb(err);
}
// filter out any filenames with unsupported extensions
var modules = files.filter(function (filename) {
return extensionPattern.exec(filename);
});
// remove extension from module name and prepend the
// directory path
var fullpaths = modules.map(function (filename) {
var mod_name = filename.replace(extensionPattern, '');
return [p, mod_name].join('/');
});
// sort filenames here, because Array.map changes order
fullpaths.sort();
cb(null, fullpaths);
});
}
});
}, callback);
};
/**
* Evaluates JavaScript files in a sandbox, returning the context. The first
* argument can either be a single filename or an array of filenames. If
* multiple filenames are given their contents are concatenated before
* evalution. The second argument is an optional context to use for the sandbox.
*
* @param files
* @param {Object} sandbox
* @return {Object}
* @api public
*/
exports.sandbox = function (files, /*optional*/sandbox) {
var source, script, result;
if (!(files instanceof Array)) {
files = [files];
}
source = files.map(function (file) {
return fs.readFileSync(file, 'utf8');
}).join('');
if (!sandbox) {
sandbox = {};
}
script = new Script(source);
result = script.runInNewContext(sandbox);
return sandbox;
};
/**
* Provides a http request, response testing environment.
*
* Example:
*
* var httputil = require('nodeunit').utils.httputil
* exports.testSomething = function(test) {
* httputil(function (req, resp) {
* resp.writeHead(200, {});
* resp.end('test data');
* },
* function(server, client) {
* client.fetch('GET', '/', {}, function(resp) {
* test.equal('test data', resp.body);
* server.close();
* test.done();
* })
* });
* };
*
* @param {Function} cgi
* @param {Function} envReady
* @api public
*/
exports.httputil = function (cgi, envReady) {
var hostname = process.env.HOSTNAME || 'localhost';
var port = process.env.PORT || 3000;
var server = http.createServer(cgi);
server.listen(port, hostname);
var client = http.createClient(port, hostname);
client.fetch = function (method, path, headers, respReady) {
var request = this.request(method, path, headers);
request.end();
request.on('response', function (response) {
response.setEncoding('utf8');
response.on('data', function (chunk) {
if (response.body) {
response.body += chunk;
} else {
response.body = chunk;
}
});
response.on('end', function () {
if (response.headers['content-type'] === 'application/json') {
response.bodyAsObject = JSON.parse(response.body);
}
respReady(response);
});
});
};
process.nextTick(function () {
if (envReady && typeof envReady === 'function') {
envReady(server, client);
}
});
};
/**
* Improves formatting of AssertionError messages to make deepEqual etc more
* readable.
*
* @param {Object} assertion
* @return {Object}
* @api public
*/
exports.betterErrors = function (assertion) {
if (!assertion.error) return;
var e = assertion.error;
// deepEqual error message is a bit sucky, lets improve it!
// e.actual and e.expected could be null or undefined, so
// using getOwnPropertyDescriptor to see if they exist:
if (Object.getOwnPropertyDescriptor(e, 'actual') &&
Object.getOwnPropertyDescriptor(e, 'expected')) {
// alexgorbatchev 2010-10-22 :: Added a bit of depth to inspection
var actual = util.inspect(e.actual, false, 10).replace(/\n$/, '');
var expected = util.inspect(e.expected, false, 10).replace(/\n$/, '');
var multiline = (
actual.indexOf('\n') !== -1 ||
expected.indexOf('\n') !== -1
);
var spacing = (multiline ? '\n' : ' ');
e._message = e.message;
e.stack = (
e.name + ':' + spacing +
actual + spacing + e.operator + spacing +
expected + '\n' +
e.stack.split('\n').slice(1).join('\n')
);
}
return assertion;
};

95
bin/node_modules/nodeunit/man1/nodeunit.1 generated vendored Normal file
View File

@ -0,0 +1,95 @@
.\" Generated with Ronnjs/v0.1
.\" http://github.com/kapouer/ronnjs/
.
.TH "NODEUNIT" "1" "October 2010" "" ""
.
.SH "NAME"
\fBnodeunit\fR \-\- simple node\.js unit testing tool
.
.SH "SYNOPSIS"
.
.nf
nodeunit [options] <file\-or\-directory> [<file\-or\-directory> \.\.\.]
.
.fi
.
.SH "DESCRIPTION"
Nodeunit is a simple unit testing tool based on the node\.js assert module\.
.
.IP "\(bu" 4
Simple to use
.
.IP "\(bu" 4
Just export the tests from a module
.
.IP "\(bu" 4
Helps you avoid common pitfalls when testing asynchronous code
.
.IP "\(bu" 4
Easy to add test cases with setUp and tearDown functions if you wish
.
.IP "\(bu" 4
Allows the use of mocks and stubs
.
.IP "" 0
.
.SH "OPTIONS"
\fB\-\-config FILE\fR:
.
.br
Load config options from a JSON file, allows the customisation
of color schemes for the default test reporter etc\.
See bin/nodeunit\.json for current available options\.
.
.P
\fB\-\-reporter FILE\fR:
.
.br
You can set the test reporter to a custom module or on of the modules
in nodeunit/lib/reporters, when omitted, the default test runner is used\.
.
.P
\fB\-\-list\-reporters\fR:
.
.br
List available build\-in reporters\.
.
.P
\fB\-h\fR, \fB\-\-help\fR:
.
.br
Display the help and exit\.
.
.P
\fB\-v\fR, \fB\-\-version\fR:
.
.br
Output version information and exit\.
.
.P
\fB<file\-or\-directory>\fR:
You can run nodeunit on specific files or on all \fI*\.js\fR files inside
.
.br
a directory\.
.
.SH "AUTHORS"
Written by Caolan McMahon and other nodeunit contributors\.
.
.br
Contributors list: \fIhttp://github\.com/caolan/nodeunit/contributors\fR\|\.
.
.SH "REPORTING BUGS"
Report nodeunit bugs to \fIhttp://github\.com/caolan/nodeunit/issues\fR\|\.
.
.SH "COPYRIGHT"
Copyright © 2010 Caolan McMahon\.
.
.br
Nodeunit has been released under the MIT license:
.
.br
\fIhttp://github\.com/caolan/nodeunit/raw/master/LICENSE\fR\|\.
.
.SH "SEE ALSO"
node(1)

4
bin/node_modules/nodeunit/nodelint.cfg generated vendored Normal file
View File

@ -0,0 +1,4 @@
var options = {
indent: 4,
onevar: false
};

56
bin/node_modules/nodeunit/package.json generated vendored Normal file
View File

@ -0,0 +1,56 @@
{ "name": "nodeunit"
, "description": "Easy unit testing for node.js and the browser."
, "maintainers":
[ { "name": "Caolan McMahon"
, "web": "https://github.com/caolan"
}
]
, "contributors" :
[ { "name": "Alex Gorbatchev"
, "web": "https://github.com/alexgorbatchev"
}
, { "name": "Alex Wolfe"
, "web": "https://github.com/alexkwolfe"
}
, { "name": "Carl Fürstenberg"
, "web": "https://github.com/azatoth"
}
, { "name": "Gerad Suyderhoud"
, "web": "https://github.com/gerad"
}
, { "name": "Kadir Pekel"
, "web": "https://github.com/coffeemate"
}
, { "name": "Oleg Efimov"
, "web": "https://github.com/Sannis"
}
, { "name": "Orlando Vazquez"
, "web": "https://github.com/orlandov"
}
, { "name": "Ryan Dahl"
, "web": "https://github.com/ry"
}
, { "name": "Sam Stephenson"
, "web": "https://github.com/sstephenson"
}
, { "name": "Thomas Mayfield"
, "web": "https://github.com/thegreatape"
}
, { "name": "Elijah Insua <tmpvar@gmail.com>",
"web": "http://tmpvar.com"
}
]
, "version": "0.5.3"
, "repository" :
{ "type" : "git"
, "url" : "http://github.com/caolan/nodeunit.git"
}
, "bugs" : { "web" : "http://github.com/caolan/nodeunit/issues" }
, "licenses" :
[ { "type" : "MIT"
, "url" : "http://github.com/caolan/nodeunit/raw/master/LICENSE"
}
]
, "directories" : { "lib": "./lib", "doc" : "./doc", "man" : "./man1" }
, "bin" : { "nodeunit" : "./bin/nodeunit" }
}

19
bin/node_modules/nodeunit/share/junit.xml.ejs generated vendored Normal file
View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8" ?>
<% for (var i=0; i < suites.length; i++) { %>
<% var suite=suites[i]; %>
<testsuite name="<%= suite.name %>"
errors="<%= suite.errorCount %>"
failures="<%= suite.failureCount %>"
tests="<%= suite.tests %>">
<% for (var j=0; j < suite.testcases.length; j++) { %>
<% var testcase=suites[i].testcases[j]; %>
<testcase name="<%= testcase.name %>">
<% if (testcase.failure) { %>
<failure message="<%= testcase.failure.message %>">
<% if (testcase.failure.backtrace) { %><%= testcase.failure.backtrace %><% } %>
</failure>
<% } %>
</testcase>
<% } %>
</testsuite>
<% } %>

11
bin/node_modules/nodeunit/share/license.js generated vendored Normal file
View File

@ -0,0 +1,11 @@
/*!
* Nodeunit
* https://github.com/caolan/nodeunit
* Copyright (c) 2010 Caolan McMahon
* MIT Licensed
*
* json2.js
* http://www.JSON.org/json2.js
* Public Domain.
* NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
*/

70
bin/node_modules/nodeunit/share/nodeunit.css generated vendored Normal file
View File

@ -0,0 +1,70 @@
/*!
* Styles taken from qunit.css
*/
h1#nodeunit-header, h1.nodeunit-header {
padding: 15px;
font-size: large;
background-color: #06b;
color: white;
font-family: 'trebuchet ms', verdana, arial;
margin: 0;
}
h1#nodeunit-header a {
color: white;
}
h2#nodeunit-banner {
height: 2em;
border-bottom: 1px solid white;
background-color: #eee;
margin: 0;
font-family: 'trebuchet ms', verdana, arial;
}
h2#nodeunit-banner.pass {
background-color: green;
}
h2#nodeunit-banner.fail {
background-color: red;
}
h2#nodeunit-userAgent, h2.nodeunit-userAgent {
padding: 10px;
background-color: #eee;
color: black;
margin: 0;
font-size: small;
font-weight: normal;
font-family: 'trebuchet ms', verdana, arial;
font-size: 10pt;
}
div#nodeunit-testrunner-toolbar {
background: #eee;
border-top: 1px solid black;
padding: 10px;
font-family: 'trebuchet ms', verdana, arial;
margin: 0;
font-size: 10pt;
}
ol#nodeunit-tests {
font-family: 'trebuchet ms', verdana, arial;
font-size: 10pt;
}
ol#nodeunit-tests li strong {
cursor:pointer;
}
ol#nodeunit-tests .pass {
color: green;
}
ol#nodeunit-tests .fail {
color: red;
}
p#nodeunit-testresult {
margin-left: 1em;
font-size: 10pt;
font-family: 'trebuchet ms', verdana, arial;
}

View File

@ -0,0 +1 @@
ok...

View File

@ -0,0 +1,3 @@
this is local config for phonegap stuff to be eventually moved to
config.xml ...we think. feedback to @davejohnson/@brianleroux
appreciated here!

View File

@ -0,0 +1,36 @@
#! /bin/sh
#
# create a phonegap/android project
#
# USAGE
# ./create [path package activity]
#
# load up the config
. ./.phonegap/config
PACKAGE_AS_PATH=$(echo $PACKAGE | sed 's/\./\//g')
ACTIVITY_PATH=./src/$PACKAGE_AS_PATH/$ACTIVITY.java
MANIFEST_PATH=./AndroidManifest.xml
# create the project
android create project --target $TARGET --path . --package $PACKAGE --activity $ACTIVITY
# copy all the phonegap scripts etc in there
cp -R ./phonegap/templates/project/ .
# copy in phonegap.js
cp ./.phonegap/android/phonegap-$VERSION.js ./assets/www
# copy in phonegap.jar
cp ./.phonegap/android/phonegap-$VERSION.jar ./libs
# copy in default activity
cat ./phonegap/templates/Activity.java > $ACTIVITY_PATH
# interpolate the acivity name and package
find "$ACTIVITY_PATH" | xargs grep '__ACTIVITY__' -sl | xargs -L1 sed -i "" "s/__ACTIVITY__/${ACTIVITY}/g"
find "$ACTIVITY_PATH" | xargs grep '__ID__' -sl | xargs -L1 sed -i "" "s/__ID__/${PACKAGE}/g"
find "$MANIFEST_PATH" | xargs grep '__ACTIVITY__' -sl | xargs -L1 sed -i "" "s/__ACTIVITY__/${ACTIVITY}/g"
find "$MANIFEST_PATH" | xargs grep '__PACKAGE__' -sl | xargs -L1 sed -i "" "s/__PACKAGE__/${PACKAGE}/g"

View File

@ -0,0 +1,9 @@
#! /bin/sh
. ./.phonegap/config
# if there are no devices listed then emulate
ant debug install
adb shell am start -n $PACKAGE/$PACKAGE.$ACTIVITY

View File

@ -0,0 +1,12 @@
#! /bin/sh
#Available Android Virtual Devices:
# Name: default
# Path: /Users/davejohnson/.android/avd/default.avd
# Target: Android 2.2 (API level 8)
# Skin: WVGA800
# Sdcard: 100M
# get the name of the first virtual device or use command line arg or use "default"
emulator -cpu-delay 0 -no-boot-anim -cache ./tmp/cache -avd default > /dev/null 2>&1 & # put the avd's chatty ass in the background

View File

@ -0,0 +1,3 @@
#! /bin/sh
adb logcat

View File

@ -0,0 +1,16 @@
package __ID__;
import android.app.Activity;
import android.os.Bundle;
import com.phonegap.*;
public class __ACTIVITY__ extends DroidGap
{
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
super.loadUrl("file:///android_asset/www/index.html");
}
}

View File

@ -0,0 +1,50 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:windowSoftInputMode="adjustPan"
package="__PACKAGE__" android:versionName="1.1" android:versionCode="5">
<supports-screens
android:largeScreens="true"
android:normalScreens="true"
android:smallScreens="true"
android:xlargeScreens="true"
android:resizeable="true"
android:anyDensity="true"
/>
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.RECORD_VIDEO"/>
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.BROADCAST_STICKY" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
<application android:icon="@drawable/icon" android:label="@string/app_name"
android:debuggable="true">
<activity android:name="__ACTIVITY__" android:label="@string/app_name"
android:configChanges="orientation|keyboardHidden">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="com.phonegap.DroidGap" android:label="@string/app_name"
android:configChanges="orientation|keyboardHidden">
<intent-filter>
</intent-filter>
</activity>
</application>
<uses-sdk android:minSdkVersion="5" />
</manifest>

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<plugins>
<plugin name="App" value="com.phonegap.App"/>
<plugin name="Geolocation" value="com.phonegap.GeoBroker"/>
<plugin name="Device" value="com.phonegap.Device"/>
<plugin name="Accelerometer" value="com.phonegap.AccelListener"/>
<plugin name="Compass" value="com.phonegap.CompassListener"/>
<plugin name="Media" value="com.phonegap.AudioHandler"/>
<plugin name="Camera" value="com.phonegap.CameraLauncher"/>
<plugin name="Contacts" value="com.phonegap.ContactManager"/>
<plugin name="Crypto" value="com.phonegap.CryptoHandler"/>
<plugin name="File" value="com.phonegap.FileUtils"/>
<plugin name="Network Status" value="com.phonegap.NetworkManager"/>
<plugin name="Notification" value="com.phonegap.Notification"/>
<plugin name="Storage" value="com.phonegap.Storage"/>
<plugin name="Temperature" value="com.phonegap.TempListener"/>
<plugin name="FileTransfer" value="com.phonegap.FileTransfer"/>
<plugin name="Capture" value="com.phonegap.Capture"/>
</plugins>

23
bin/test Executable file
View File

@ -0,0 +1,23 @@
#! /bin/sh
set -e
VERSION=$(cat ./VERSION)
# get the latest mobile-spec
git clone git@github.com:phonegap/mobile-spec.git
# clobber test if it exists
if [ -e ./test ]
then
rm -rf ./test
fi
# generate a working proj
./bin/create ./test com.phonegap.test PhoneGapTest
# kill the default app and replace it w/ mobile-spec
rm -rf ./test/assets/www
mv ./mobile-spec ./test/assets/www
# build it, launch it and start logging on stdout
cd ./test && ./bin/debug && ./bin/log

View File

@ -0,0 +1,4 @@
exports['you are sane'] = (test) ->
test.expect 1
test.ok true, "this assertion should always pass"
test.done()

21
bin/tests/create.coffee Normal file
View File

@ -0,0 +1,21 @@
util = require 'util'
exec = require('child_process').exec
path = require 'path'
exports['default example project is generated'] = (test) ->
test.expect 1
exec './bin/create', (error, stdout, stderr) ->
test.ok true, "this assertion should pass" unless error?
test.done()
exports['default example project has a ./.phonegap folder'] = (test) ->
test.expect 1
path.exists './example/.phonegap', (exists) ->
test.ok exists, 'the phonegap folder exists'
test.done()
exports['default example project has a /phonegap folder'] = (test) ->
test.expect 1
path.exists './example/phonegap', (exists) ->
test.ok exists, 'the other phonegap folder exists'
test.done()

0
bin/tests/debug.coffee Normal file
View File

0
bin/tests/test.coffee Normal file
View File

View File

@ -5,10 +5,10 @@
android:largeScreens="true"
android:normalScreens="true"
android:smallScreens="true"
android:xlargeScreens="true"
android:resizeable="true"
android:anyDensity="true"
/>
<!-- android:xlargeScreens="true" screen supported only after Android-9 -->
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.VIBRATE" />

View File

@ -109,7 +109,7 @@
<target name="build-javascript">
<!-- Clean up existing files -->
<delete file="assets/www/phonegap_${version}.js"/>
<!--<delete file="assets/www/phonegap_${version}.js"/>-->
<!-- Create uncompressed JS file -->
<concat destfile="assets/www/phonegap-${version}.js">
@ -119,15 +119,15 @@
<!-- update project files to reference phonegap-x.x.x.min.js -->
<replaceregexp match="phonegap(.*)\.js" replace="phonegap-${version}.js" byline="true">
<fileset file="assets/www/index.html" />
<fileset file="../example/index.html" />
<fileset file="assets/www/index.html" />
<!-- <fileset file="../bin/templates/project/assets/www/index.html" /> -->
</replaceregexp>
<replaceregexp match="phonegapVersion = [\u0022].*[\u0022];" replace="phonegapVersion = ${dblQuote}${version}${dblQuote};" byline="true">
<fileset file="src/com/phonegap/Device.java" />
</replaceregexp>
<!-- Delete temp file -->
<delete file="assets/www/phonegap-tmp.js"/>
<!--<delete file="assets/www/phonegap-tmp.js"/>-->
</target>
<!-- Build PhoneGap jar file that includes all native code, and PhoneGap JS file

View File

@ -77,9 +77,6 @@ import com.phonegap.api.PluginManager;
* // Initialize activity
* super.init();
*
* // Add your plugins here or in JavaScript
* super.addService("MyService", "com.phonegap.examples.MyService");
*
* // Clear cache if you want
* super.appView.clearCache(true);
*
@ -91,7 +88,7 @@ import com.phonegap.api.PluginManager;
*
* Properties: The application can be configured using the following properties:
*
* // Display a native loading dialog. Format for value = "Title,Message".
* // Display a native loading dialog when loading app. Format for value = "Title,Message".
* // (String - default=null)
* super.setStringProperty("loadingDialog", "Wait,Loading Demo...");
*
@ -227,13 +224,7 @@ public class DroidGap extends PhonegapActivity {
WebViewReflect.checkCompatibility();
if (android.os.Build.VERSION.RELEASE.startsWith("1.")) {
this.appView.setWebChromeClient(new GapClient(DroidGap.this));
}
else {
this.appView.setWebChromeClient(new EclairClient(DroidGap.this));
}
this.appView.setWebChromeClient(new GapClient(DroidGap.this));
this.setWebViewClient(this.appView, new GapViewClient(this));
this.appView.setInitialScale(100);
@ -272,7 +263,7 @@ public class DroidGap extends PhonegapActivity {
String url = this.getStringProperty("url", null);
if (url != null) {
System.out.println("Loading initial URL="+url);
this.loadUrl(url);
this.loadUrl(url);
}
}
@ -393,7 +384,7 @@ public class DroidGap extends PhonegapActivity {
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// If timeout, then stop loading and handle error
if (me.loadUrlTimeout == currentLoadUrlTimeout) {
@ -602,7 +593,7 @@ public class DroidGap extends PhonegapActivity {
public void setDoubleProperty(String name, double value) {
this.getIntent().putExtra(name, value);
}
@Override
/**
* Called when the system is about to start resuming a previous activity.
@ -612,7 +603,7 @@ public class DroidGap extends PhonegapActivity {
if (this.appView == null) {
return;
}
// Send pause event to JavaScript
this.appView.loadUrl("javascript:try{PhoneGap.onPause.fire();}catch(e){};");
@ -685,10 +676,9 @@ public class DroidGap extends PhonegapActivity {
// Load blank page so that JavaScript onunload is called
this.appView.loadUrl("about:blank");
// Forward to plugins
this.pluginManager.onDestroy();
}
}
@ -711,8 +701,7 @@ public class DroidGap extends PhonegapActivity {
public void sendJavascript(String statement) {
this.callbackServer.sendJavascript(statement);
}
/**
* Display a new browser with the specified URL.
*
@ -803,11 +792,12 @@ public class DroidGap extends PhonegapActivity {
}
/**
* Provides a hook for calling "alert" from javascript. Useful for
* debugging your javascript.
* Set the chrome handler.
*/
public class GapClient extends WebChromeClient {
private String TAG = "PhoneGapLog";
private long MAX_QUOTA = 100 * 1024 * 1024;
private DroidGap ctx;
/**
@ -914,13 +904,13 @@ public class DroidGap extends PhonegapActivity {
}
// Polling for JavaScript messages
else if (reqOk && defaultValue != null && defaultValue.equals("gap_poll:")) {
else if (reqOk && defaultValue != null && defaultValue.equals("gap_poll:")) {
String r = callbackServer.getJavascript();
result.confirm(r);
}
// Calling into CallbackServer
else if (reqOk && defaultValue != null && defaultValue.equals("gap_callbackServer:")) {
else if (reqOk && defaultValue != null && defaultValue.equals("gap_callbackServer:")) {
String r = "";
if (message.equals("usePolling")) {
r = ""+callbackServer.usePolling();
@ -939,7 +929,7 @@ public class DroidGap extends PhonegapActivity {
// PhoneGap JS has initialized, so show webview
// (This solves white flash seen when rendering HTML)
else if (reqOk && defaultValue != null && defaultValue.equals("gap_init:")) {
else if (reqOk && defaultValue != null && defaultValue.equals("gap_init:")) {
appView.setVisibility(View.VISIBLE);
ctx.spinnerStop();
result.confirm("OK");
@ -975,25 +965,6 @@ public class DroidGap extends PhonegapActivity {
return true;
}
}
/**
* WebChromeClient that extends GapClient with additional support for Android 2.X
*/
public class EclairClient extends GapClient {
private String TAG = "PhoneGapLog";
private long MAX_QUOTA = 100 * 1024 * 1024;
/**
* Constructor.
*
* @param ctx
*/
public EclairClient(Context ctx) {
super(ctx);
}
/**
* Handle database quota exceeded notification.
*
@ -1011,9 +982,9 @@ public class DroidGap extends PhonegapActivity {
Log.d(TAG, "event raised onExceededDatabaseQuota estimatedSize: " + Long.toString(estimatedSize) + " currentQuota: " + Long.toString(currentQuota) + " totalUsedQuota: " + Long.toString(totalUsedQuota));
if( estimatedSize < MAX_QUOTA)
{
{
//increase for 1Mb
long newQuota = estimatedSize;
long newQuota = estimatedSize;
Log.d(TAG, "calling quotaUpdater.updateQuota newQuota: " + Long.toString(newQuota) );
quotaUpdater.updateQuota(newQuota);
}
@ -1022,8 +993,8 @@ public class DroidGap extends PhonegapActivity {
// Set the quota to whatever it is and force an error
// TODO: get docs on how to handle this properly
quotaUpdater.updateQuota(currentQuota);
}
}
}
}
// console.log in api level 7: http://developer.android.com/guide/developing/debug-tasks.html
@Override
@ -1041,7 +1012,6 @@ public class DroidGap extends PhonegapActivity {
* @param callback
*/
public void onGeolocationPermissionsShowPrompt(String origin, Callback callback) {
// TODO Auto-generated method stub
super.onGeolocationPermissionsShowPrompt(origin, callback);
callback.invoke(origin, true, false);
}
@ -1074,8 +1044,13 @@ public class DroidGap extends PhonegapActivity {
*/
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
// First give any plugins the chance to handle the url themselves
if (this.ctx.pluginManager.onOverrideUrlLoading(url)) {
}
// If dialing phone (tel:5551212)
if (url.startsWith(WebView.SCHEME_TEL)) {
else if (url.startsWith(WebView.SCHEME_TEL)) {
try {
Intent intent = new Intent(Intent.ACTION_DIAL);
intent.setData(Uri.parse(url));
@ -1083,9 +1058,8 @@ public class DroidGap extends PhonegapActivity {
} catch (android.content.ActivityNotFoundException e) {
System.out.println("Error dialing "+url+": "+ e.toString());
}
return true;
}
// If displaying map (geo:0,0?q=address)
else if (url.startsWith("geo:")) {
try {
@ -1095,9 +1069,8 @@ public class DroidGap extends PhonegapActivity {
} catch (android.content.ActivityNotFoundException e) {
System.out.println("Error showing map "+url+": "+ e.toString());
}
return true;
}
// If sending email (mailto:abc@corp.com)
else if (url.startsWith(WebView.SCHEME_MAILTO)) {
try {
@ -1107,9 +1080,8 @@ public class DroidGap extends PhonegapActivity {
} catch (android.content.ActivityNotFoundException e) {
System.out.println("Error sending email "+url+": "+ e.toString());
}
return true;
}
// If sms:5551212?body=This is the message
else if (url.startsWith("sms:")) {
try {
@ -1140,15 +1112,13 @@ public class DroidGap extends PhonegapActivity {
} catch (android.content.ActivityNotFoundException e) {
System.out.println("Error sending sms "+url+":"+ e.toString());
}
return true;
}
// All else
else {
// If our app or file:, then load into our webview
// NOTE: This replaces our app with new URL. When BACK is pressed,
// our app is reloaded and restarted. All state is lost.
// If our app or file:, then load into a new phonegap webview container by starting a new instance of our activity.
// Our app continues to run. When BACK is pressed, our app is redisplayed.
if (this.ctx.loadInWebView || url.startsWith("file://") || url.indexOf(this.ctx.baseUrl) == 0) {
try {
// Init parameters to new DroidGap activity and propagate existing parameters
@ -1174,7 +1144,7 @@ public class DroidGap extends PhonegapActivity {
System.out.println("Error loading url into DroidGap - "+url+":"+ e.toString());
}
}
// If not our application, let default viewer handle
else {
try {
@ -1185,8 +1155,8 @@ public class DroidGap extends PhonegapActivity {
System.out.println("Error loading url "+url+":"+ e.toString());
}
}
return true;
}
return true;
}
/**
@ -1398,7 +1368,7 @@ public class DroidGap extends PhonegapActivity {
public void setActivityResultCallback(IPlugin plugin) {
this.activityResultCallback = plugin;
}
/**
* Report an error to the host application. These errors are unrecoverable (i.e. the main resource is unavailable).
* The errorCode parameter corresponds to one of the ERROR_* constants.

View File

@ -274,7 +274,7 @@ public class FileTransfer extends Plugin {
dos.writeBytes(LINE_START + BOUNDRY + LINE_END);
dos.writeBytes("Content-Disposition: form-data; name=\"" + key.toString() + "\";");
dos.writeBytes(LINE_END + LINE_END);
dos.writeBytes(params.getString(key.toString()));
dos.write(params.getString(key.toString()).getBytes());
dos.writeBytes(LINE_END);
}
} catch (JSONException e) {

View File

@ -1,175 +0,0 @@
class Classic
attr_reader :android_sdk_path, :name, :pkg, :www, :path
def initialize(a)
@android_sdk_path, @name, @pkg, @www, @path = a
build
end
def build
setup
clobber
build_jar
create_android
include_www
generate_manifest
copy_libs
add_name_to_strings
write_java
end
def setup
@android_dir = File.expand_path(File.dirname(__FILE__).gsub(/lib$/,''))
@framework_dir = File.join(@android_dir, "framework")
@icon = File.join(@www, 'icon.png') unless !@icon.nil? && File.exists?(@icon)
# Hash that stores the location of icons for each resolution type. Uses the default icon for all resolutions as a baseline.
@icons = {
:"drawable-ldpi" => @icon,
:"drawable-mdpi" => @icon,
:"drawable-hdpi" => @icon
} if @icons.nil?
@app_js_dir = ''
@content = 'index.html'
end
# replaces @path with new android project
def clobber
FileUtils.rm_r(@path) if File.exists? @path
FileUtils.mkdir_p @path
end
# removes local.properties and recreates based on android_sdk_path
# then generates framework/phonegap.jar
def build_jar
%w(local.properties phonegap.js phonegap.jar).each do |f|
FileUtils.rm File.join(@framework_dir, f) if File.exists? File.join(@framework_dir, f)
end
open(File.join(@framework_dir, "local.properties"), 'w') do |f|
f.puts "sdk.dir=#{ @android_sdk_path }"
end
Dir.chdir(@framework_dir)
`ant jar`
Dir.chdir(@android_dir)
end
# runs android create project
# TODO need to allow more flexible SDK targetting via config.xml
def create_android
IO.popen("android list targets") { |f|
targets = f.readlines(nil)[0].scan(/id\:.*$/)
if (targets.length > 0)
target_id = targets.last.match(/\d+/).to_a.first
`android create project -t #{ target_id } -k #{ @pkg } -a #{ @name } -n #{ @name } -p #{ @path }`
else
puts "No Android targets found. Please run 'android' and install at least one SDK package."
puts "If that makes no sense then you need to go read the Android SDK documentation."
end
}
end
# copies the project/www folder into tmp/android/www
def include_www
FileUtils.mkdir_p File.join(@path, "assets", "www")
FileUtils.cp_r File.join(@www, "."), File.join(@path, "assets", "www")
end
# creates an AndroidManifest.xml for the project
def generate_manifest
manifest = ""
open(File.join(@framework_dir, "AndroidManifest.xml"), 'r') do |old|
manifest = old.read
manifest.gsub! 'android:versionCode="5"', 'android:versionCode="1"'
manifest.gsub! 'package="com.phonegap"', "package=\"#{ @pkg }\""
manifest.gsub! 'android:name=".StandAlone"', "android:name=\".#{ @name.gsub(' ','') }\""
manifest.gsub! 'android:minSdkVersion="5"', 'android:minSdkVersion="3"'
end
open(File.join(@path, "AndroidManifest.xml"), 'w') { |x| x.puts manifest }
end
# copies stuff from src directory into the android project directory (@path)
def copy_libs
version = IO.read(File.join(@framework_dir, '../VERSION')).lstrip.rstrip
framework_res_dir = File.join(@framework_dir, "res")
app_res_dir = File.join(@path, "res")
# copies in the jar
FileUtils.mkdir_p File.join(@path, "libs")
FileUtils.cp File.join(@framework_dir, "phonegap-#{ version }.jar"), File.join(@path, "libs")
# copies in the strings.xml
FileUtils.mkdir_p File.join(app_res_dir, "values")
FileUtils.cp File.join(framework_res_dir, "values","strings.xml"), File.join(app_res_dir, "values", "strings.xml")
# copies in plugins.xml
FileUtils.mkdir_p File.join(app_res_dir, "xml")
FileUtils.cp File.join(framework_res_dir, "xml","plugins.xml"), File.join(app_res_dir, "xml", "plugins.xml")
# drops in the layout files: main.xml and preview.xml
FileUtils.mkdir_p File.join(app_res_dir, "layout")
%w(main.xml).each do |f|
FileUtils.cp File.join(framework_res_dir, "layout", f), File.join(app_res_dir, "layout", f)
end
# icon file copy
%w(drawable-hdpi drawable-ldpi drawable-mdpi).each do |e|
# if specific resolution icons are specified, use those. if not, see if a general purpose icon was defined.
# finally, fall back to using the default PhoneGap one.
currentIcon = ""
if !@icons[e.to_sym].nil? && File.exists?(File.join(@www, @icons[e.to_sym]))
currentIcon = File.join(@www, @icons[e.to_sym])
elsif File.exists?(@icon)
currentIcon = @icon
else
currentIcon = File.join(framework_res_dir, "drawable", "icon.png")
end
FileUtils.mkdir_p(File.join(app_res_dir, e))
FileUtils.cp(currentIcon, File.join(app_res_dir, e, "icon.png"))
end
# concat JS and put into www folder. this can be overridden in the config.xml via @app_js_dir
js_dir = File.join(@framework_dir, "assets", "js")
phonegapjs = IO.read(File.join(js_dir, 'phonegap.js.base'))
Dir.new(js_dir).entries.each do |script|
next if script[0].chr == "." or script == "phonegap.js.base"
phonegapjs << IO.read(File.join(js_dir, script))
phonegapjs << "\n\n"
end
File.open(File.join(@path, "assets", "www", @app_js_dir, "phonegap-#{ version }.js"), 'w') {|f| f.write(phonegapjs) }
end
# puts app name in strings
def add_name_to_strings
x = "<?xml version=\"1.0\" encoding=\"utf-8\"?>
<resources>
<string name=\"app_name\">#{ @name }</string>
<string name=\"go\">Snap</string>
</resources>
"
open(File.join(@path, "res", "values", "strings.xml"), 'w') do |f|
f.puts x.gsub(' ','')
end
end
# create java source file
def write_java
j = "
package #{ @pkg };
import android.os.Bundle;
import com.phonegap.*;
public class #{ @name.gsub(' ','') } extends DroidGap
{
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
super.loadUrl(\"file:///android_asset/www/#{ @content }\");
}
}
"
code_dir = File.join(@path, "src", @pkg.gsub('.', File::SEPARATOR))
FileUtils.mkdir_p(code_dir)
open(File.join(code_dir, "#{ @name }.java"),'w') { |f| f.puts j }
end
# friendly output for now
def msg
puts "Created #{ @path }"
end
#
end

View File

@ -1,97 +0,0 @@
# Create
#
# Generates an Android project from a valid WWW directory and puts it in ../[PROJECT NAME]_android
#
class Create < Classic
def initialize(path)
guess_paths(path)
read_config
build
end
def guess_paths(path)
# if no path is supplied uses current directory for project
path = FileUtils.pwd if path.nil?
# if a www is found use it for the project
path = File.join(path, 'www') if File.exists? File.join(path, 'www')
# defaults
@name = path.split("/").last.gsub('-','').gsub(' ','') # no dashses nor spaces
@path = File.join(path, '..', "#{ @name }_android")
@www = path
@pkg = "com.phonegap.#{ @name }"
@android_sdk_path = Dir.getwd[0,1] != "/" ? `android-sdk-path.bat android.bat`.gsub('\\tools','').gsub('\\', '\\\\\\\\') : `which android`.gsub(/\/tools\/android$/,'').chomp
@android_dir = File.expand_path(File.dirname(__FILE__).gsub('lib',''))
@framework_dir = File.join(@android_dir, "framework")
@icon = File.join(@www, 'icon.png')
@app_js_dir = ''
@content = 'index.html'
# stop executation on errors
raise "Expected index.html in the following folder #{ path }.\nThe path is expected to be the directory droidgap create is run from or specified as a command line arg like droidgap create my_path." unless File.exists? File.join(path, 'index.html')
raise 'Could not find android in your PATH!' if @android_sdk_path.empty?
end
# reads in a config.xml file
def read_config
config_file = File.join(@www, 'config.xml')
if File.exists?(config_file)
require 'rexml/document'
f = File.new config_file
doc = REXML::Document.new(f)
@config = {}
@config[:id] = doc.root.attributes["id"]
@config[:version] = doc.root.attributes["version"]
@config[:icons] = {}
defaultIconSize = 0
doc.root.elements.each do |n|
@config[:name] = n.text.gsub('-','').gsub(' ','') if n.name == 'name'
@config[:description] = n.text if n.name == 'description'
@config[:content] = n.attributes["src"] if n.name == 'content'
if n.name == 'icon'
if n.attributes["width"] == '72' && n.attributes["height"] == '72'
@config[:icons]["drawable-hdpi".to_sym] = n.attributes["src"]
if 72 > defaultIconSize
@config[:icon] = n.attributes["src"]
defaultIconSize = 72
end
elsif n.attributes["width"] == '48' && n.attributes["height"] == '48'
@config[:icons]["drawable-mdpi".to_sym] = n.attributes["src"]
if 48 > defaultIconSize
@config[:icon] = n.attributes["src"]
defaultIconSize = 48
end
elsif n.attributes["width"] == '36' && n.attributes["height"] == '36'
@config[:icons]["drawable-ldpi".to_sym] = n.attributes["src"]
if 36 > defaultIconSize
@config[:icon] = n.attributes["src"]
defaultIconSize = 36
end
else
@config[:icon] = n.attributes["src"]
end
end
if n.name == "preference" && n.attributes["name"] == 'javascript_folder'
@config[:js_dir] = n.attributes["value"]
end
end
# extract android specific stuff
@config[:versionCode] = doc.elements["//android:versionCode"] ? doc.elements["//android:versionCode"].text : 3
@config[:minSdkVersion] = doc.elements["//android:minSdkVersion"] ? doc.elements["//android:minSdkVersion"].text : 1
# will change the name from the directory to the name element text
@name = @config[:name] if @config[:name]
# set the icon from the config
@icon = File.join(@www, @config[:icon]) if @config[:icon]
@icons = @config[:icons] if @config[:icons].length > 0
# sets the app js dir where phonegap.js gets copied
@app_js_dir = @config[:js_dir] ? @config[:js_dir] : ''
# sets the start page
@content = @config[:content] ? @config[:content] : 'index.html'
end
end
end

View File

@ -1,15 +0,0 @@
# Creates a new PhoneGap/Android project from ./example
class Generate
def initialize(name)
if name.nil?
puts "You need to supply a name to generate a project. Try this:\n\ndroidgap gen MyApp\n\n"
return
end
from = File.join ROOT, "example"
to = File.join FileUtils.pwd, name
FileUtils.cp_r from, to
Create.new(to)
FileUtils.rm_rf to
FileUtils.mv "#{ to }_android", to
end
end

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