Browse files

Initial project structure

  • Loading branch information...
1 parent c34a86e commit 2bd36fae5c6a6dd29f2a7848880259c1f09764b7 @cleishm committed Jul 16, 2009
Showing with 24,518 additions and 0 deletions.
  1. +6 −0 .gitignore
  2. +28 −0 LICENSE
  3. +87 −0 README
  4. +19 −0 build.properties
  5. +106 −0 build.xml
  6. BIN lib/ant-contrib.jar
  7. +8,844 −0 lib/env.rhino.js
  8. +4,376 −0 lib/jquery/jquery-1.3.2.js
  9. +29 −0 lib/jquery/jquery.fn.js
  10. +109 −0 lib/jquery/jquery.print.js
  11. BIN lib/js.jar
  12. BIN lib/jsdoctoolkit-ant-task.jar
  13. +92 −0 lib/screw-unit/screw.behaviors.js
  14. +82 −0 lib/screw-unit/screw.builder.js
  15. +90 −0 lib/screw-unit/screw.css
  16. +45 −0 lib/screw-unit/screw.events.js
  17. +187 −0 lib/screw-unit/screw.matchers.js
  18. +6 −0 spec/core_spec.js
  19. +77 −0 spec/runner.js
  20. 0 spec/spec_helper.js
  21. +17 −0 spec/suite.html
  22. 0 src/jsmockito.js
  23. +146 −0 tools/jsdoc-toolkit/README.txt
  24. +33 −0 tools/jsdoc-toolkit/app/frame.js
  25. +102 −0 tools/jsdoc-toolkit/app/frame/Chain.js
  26. +144 −0 tools/jsdoc-toolkit/app/frame/Dumper.js
  27. +84 −0 tools/jsdoc-toolkit/app/frame/Hash.js
  28. +148 −0 tools/jsdoc-toolkit/app/frame/Link.js
  29. +10 −0 tools/jsdoc-toolkit/app/frame/Namespace.js
  30. +134 −0 tools/jsdoc-toolkit/app/frame/Opt.js
  31. +26 −0 tools/jsdoc-toolkit/app/frame/Reflection.js
  32. +93 −0 tools/jsdoc-toolkit/app/frame/String.js
  33. +129 −0 tools/jsdoc-toolkit/app/frame/Testrun.js
  34. +26 −0 tools/jsdoc-toolkit/app/handlers/FOODOC.js
  35. +26 −0 tools/jsdoc-toolkit/app/handlers/XMLDOC.js
  36. +159 −0 tools/jsdoc-toolkit/app/handlers/XMLDOC/DomReader.js
  37. +16 −0 tools/jsdoc-toolkit/app/handlers/XMLDOC/XMLDoc.js
  38. +292 −0 tools/jsdoc-toolkit/app/handlers/XMLDOC/XMLParse.js
  39. +101 −0 tools/jsdoc-toolkit/app/lib/JSDOC.js
  40. +200 −0 tools/jsdoc-toolkit/app/lib/JSDOC/DocComment.js
  41. +294 −0 tools/jsdoc-toolkit/app/lib/JSDOC/DocTag.js
  42. +126 −0 tools/jsdoc-toolkit/app/lib/JSDOC/JsDoc.js
  43. +109 −0 tools/jsdoc-toolkit/app/lib/JSDOC/JsPlate.js
  44. +144 −0 tools/jsdoc-toolkit/app/lib/JSDOC/Lang.js
  45. +107 −0 tools/jsdoc-toolkit/app/lib/JSDOC/Parser.js
  46. +33 −0 tools/jsdoc-toolkit/app/lib/JSDOC/PluginManager.js
  47. +643 −0 tools/jsdoc-toolkit/app/lib/JSDOC/Symbol.js
  48. +229 −0 tools/jsdoc-toolkit/app/lib/JSDOC/SymbolSet.js
  49. +41 −0 tools/jsdoc-toolkit/app/lib/JSDOC/TextStream.js
  50. +18 −0 tools/jsdoc-toolkit/app/lib/JSDOC/Token.js
  51. +332 −0 tools/jsdoc-toolkit/app/lib/JSDOC/TokenReader.js
  52. +133 −0 tools/jsdoc-toolkit/app/lib/JSDOC/TokenStream.js
  53. +32 −0 tools/jsdoc-toolkit/app/lib/JSDOC/Util.js
  54. +459 −0 tools/jsdoc-toolkit/app/lib/JSDOC/Walker.js
  55. +111 −0 tools/jsdoc-toolkit/app/main.js
  56. +20 −0 tools/jsdoc-toolkit/app/plugins/commentSrcJson.js
  57. +16 −0 tools/jsdoc-toolkit/app/plugins/frameworkPrototype.js
  58. +10 −0 tools/jsdoc-toolkit/app/plugins/functionCall.js
  59. +62 −0 tools/jsdoc-toolkit/app/plugins/publishSrcHilite.js
  60. +9 −0 tools/jsdoc-toolkit/app/plugins/symbolLink.js
  61. +31 −0 tools/jsdoc-toolkit/app/plugins/tagParamConfig.js
  62. +43 −0 tools/jsdoc-toolkit/app/plugins/tagSynonyms.js
  63. +348 −0 tools/jsdoc-toolkit/app/run.js
  64. +144 −0 tools/jsdoc-toolkit/app/t/TestDoc.js
  65. +13 −0 tools/jsdoc-toolkit/app/t/runner.js
  66. +307 −0 tools/jsdoc-toolkit/app/test.js
  67. +24 −0 tools/jsdoc-toolkit/app/test/addon.js
  68. +14 −0 tools/jsdoc-toolkit/app/test/anon_inner.js
  69. +31 −0 tools/jsdoc-toolkit/app/test/augments.js
  70. +26 −0 tools/jsdoc-toolkit/app/test/augments2.js
  71. +41 −0 tools/jsdoc-toolkit/app/test/borrows.js
  72. +23 −0 tools/jsdoc-toolkit/app/test/borrows2.js
  73. +22 −0 tools/jsdoc-toolkit/app/test/config.js
  74. +18 −0 tools/jsdoc-toolkit/app/test/constructs.js
  75. +10 −0 tools/jsdoc-toolkit/app/test/encoding.js
  76. +12 −0 tools/jsdoc-toolkit/app/test/encoding_other.js
  77. +54 −0 tools/jsdoc-toolkit/app/test/event.js
  78. +39 −0 tools/jsdoc-toolkit/app/test/functions_anon.js
  79. +33 −0 tools/jsdoc-toolkit/app/test/functions_nested.js
  80. +13 −0 tools/jsdoc-toolkit/app/test/global.js
  81. +25 −0 tools/jsdoc-toolkit/app/test/globals.js
  82. +10 −0 tools/jsdoc-toolkit/app/test/ignore.js
  83. +16 −0 tools/jsdoc-toolkit/app/test/inner.js
  84. +477 −0 tools/jsdoc-toolkit/app/test/jsdoc_test.js
  85. +33 −0 tools/jsdoc-toolkit/app/test/lend.js
  86. +19 −0 tools/jsdoc-toolkit/app/test/memberof.js
  87. +17 −0 tools/jsdoc-toolkit/app/test/memberof_constructor.js
  88. +19 −0 tools/jsdoc-toolkit/app/test/name.js
  89. +23 −0 tools/jsdoc-toolkit/app/test/namespace_nested.js
  90. +13 −0 tools/jsdoc-toolkit/app/test/nocode.js
  91. +20 −0 tools/jsdoc-toolkit/app/test/oblit_anon.js
  92. +20 −0 tools/jsdoc-toolkit/app/test/overview.js
  93. +37 −0 tools/jsdoc-toolkit/app/test/param_inline.js
  94. +8 −0 tools/jsdoc-toolkit/app/test/params_optional.js
  95. +17 −0 tools/jsdoc-toolkit/app/test/prototype.js
  96. +9 −0 tools/jsdoc-toolkit/app/test/prototype_nested.js
  97. +13 −0 tools/jsdoc-toolkit/app/test/prototype_oblit.js
  98. +24 −0 tools/jsdoc-toolkit/app/test/prototype_oblit_constructor.js
  99. +10 −0 tools/jsdoc-toolkit/app/test/public.js
  100. +42 −0 tools/jsdoc-toolkit/app/test/shared.js
  101. +2 −0 tools/jsdoc-toolkit/app/test/shared2.js
  102. +22 −0 tools/jsdoc-toolkit/app/test/shortcuts.js
  103. +13 −0 tools/jsdoc-toolkit/app/test/static_this.js
  104. +31 −0 tools/jsdoc-toolkit/app/test/synonyms.js
  105. +23 −0 tools/jsdoc-toolkit/app/test/tosource.js
  106. +14 −0 tools/jsdoc-toolkit/app/test/variable_redefine.js
  107. +75 −0 tools/jsdoc-toolkit/changes.txt
  108. +31 −0 tools/jsdoc-toolkit/conf/sample.conf
  109. +36 −0 tools/jsdoc-toolkit/java/build.xml
  110. +36 −0 tools/jsdoc-toolkit/java/build_1.4.xml
  111. BIN tools/jsdoc-toolkit/java/classes/js.jar
  112. +21 −0 tools/jsdoc-toolkit/java/src/JsDebugRun.java
  113. +21 −0 tools/jsdoc-toolkit/java/src/JsRun.java
  114. BIN tools/jsdoc-toolkit/jsdebug.jar
  115. BIN tools/jsdoc-toolkit/jsrun.jar
  116. +17 −0 tools/jsdoc-toolkit/templates/jsdoc/allclasses.tmpl
  117. +56 −0 tools/jsdoc-toolkit/templates/jsdoc/allfiles.tmpl
  118. +646 −0 tools/jsdoc-toolkit/templates/jsdoc/class.tmpl
  119. +39 −0 tools/jsdoc-toolkit/templates/jsdoc/index.tmpl
  120. +184 −0 tools/jsdoc-toolkit/templates/jsdoc/publish.js
  121. +162 −0 tools/jsdoc-toolkit/templates/jsdoc/static/default.css
  122. +2 −0 tools/jsdoc-toolkit/templates/jsdoc/static/header.html
  123. +19 −0 tools/jsdoc-toolkit/templates/jsdoc/static/index.html
  124. +35 −0 tools/jsdoc-toolkit/templates/jsdoc/symbol.tmpl
  125. +74 −0 tools/jsdoc-toolkit/templates/outline/allclasses.tmpl
  126. +64 −0 tools/jsdoc-toolkit/templates/outline/allfiles.tmpl
  127. +443 −0 tools/jsdoc-toolkit/templates/outline/class.tmpl
  128. +65 −0 tools/jsdoc-toolkit/templates/outline/index.tmpl
  129. +132 −0 tools/jsdoc-toolkit/templates/outline/jsdoc-changes/app/frame/Link.js
  130. +60 −0 tools/jsdoc-toolkit/templates/outline/jsdoc-changes/app/plugins/publishSrcHilite.js
  131. +262 −0 tools/jsdoc-toolkit/templates/outline/publish.js
  132. +16 −0 tools/jsdoc-toolkit/templates/outline/static/code.css
  133. +28 −0 tools/jsdoc-toolkit/templates/outline/static/cssIEfixed.html
  134. +440 −0 tools/jsdoc-toolkit/templates/outline/static/default.css
  135. +3 −0 tools/jsdoc-toolkit/templates/outline/static/header.html
  136. BIN tools/jsdoc-toolkit/templates/outline/static/images/bg.png
  137. BIN tools/jsdoc-toolkit/templates/outline/static/images/class_default_obj.png
  138. BIN tools/jsdoc-toolkit/templates/outline/static/images/class_obj.png
  139. BIN tools/jsdoc-toolkit/templates/outline/static/images/classfo_obj.png
  140. BIN tools/jsdoc-toolkit/templates/outline/static/images/collapsebtn.gif
  141. BIN tools/jsdoc-toolkit/templates/outline/static/images/collapsed.png
  142. BIN tools/jsdoc-toolkit/templates/outline/static/images/expandbtn.gif
  143. BIN tools/jsdoc-toolkit/templates/outline/static/images/expanded.png
  144. BIN tools/jsdoc-toolkit/templates/outline/static/images/field_default_obj.png
  145. BIN tools/jsdoc-toolkit/templates/outline/static/images/field_private_obj.png
  146. BIN tools/jsdoc-toolkit/templates/outline/static/images/field_protected_obj.png
  147. BIN tools/jsdoc-toolkit/templates/outline/static/images/field_public_obj.png
  148. BIN tools/jsdoc-toolkit/templates/outline/static/images/file_obj.png
  149. BIN tools/jsdoc-toolkit/templates/outline/static/images/method_default_obj.png
  150. BIN tools/jsdoc-toolkit/templates/outline/static/images/method_private_obj.png
  151. BIN tools/jsdoc-toolkit/templates/outline/static/images/method_protected_obj.png
  152. BIN tools/jsdoc-toolkit/templates/outline/static/images/method_public_obj.png
  153. BIN tools/jsdoc-toolkit/templates/outline/static/images/minus.gif
  154. BIN tools/jsdoc-toolkit/templates/outline/static/images/namespace_function_obj.png
  155. BIN tools/jsdoc-toolkit/templates/outline/static/images/namespace_obj.png
  156. BIN tools/jsdoc-toolkit/templates/outline/static/images/never_translate.png
  157. BIN tools/jsdoc-toolkit/templates/outline/static/images/plus.gif
  158. +19 −0 tools/jsdoc-toolkit/templates/outline/static/index.html
  159. +1 −0 tools/jsdoc-toolkit/templates/outline/static/jproton.js
  160. +182 −0 tools/jsdoc-toolkit/templates/outline/static/sh.css
  161. +1 −0 tools/jsdoc-toolkit/templates/outline/static/sh.js
  162. +113 −0 tools/jsdoc-toolkit/templates/outline/static/ui.js
  163. +35 −0 tools/jsdoc-toolkit/templates/outline/symbol.tmpl
  164. BIN tools/yuicompressor.jar
View
6 .gitignore
@@ -0,0 +1,6 @@
+/build
+/dist
+/doc
+
+.DS_Store
+.*.swp
View
28 LICENSE
@@ -0,0 +1,28 @@
+Copyright (c) 2009 Chris Leishman
+
+https://github.com/chrisleishman/jsmockito
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of JsMockito nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
View
87 README
@@ -0,0 +1,87 @@
+JsMockito
+---------
+
+ http://github.com/chrisleishman/jsmockito/tree/master
+
+
+JsMockito is a JavaScript stub/mock framework inspired by Mockito.
+To quote the mockito website:
+
+ "Mockito is a mocking framework that tastes really good. It
+ lets you write beautiful tests with a clean & simple API.
+ Mockito doesn't give you a hangover because the tests are
+ very readable and they produce clean verification errors."
+
+JsMockito aims to try and reproduce the clean & simple API, with
+a JavaScript twist. And why not add some variation to your
+drinking habits?
+
+
+What do you serve it with?
+--------------------------
+
+JsMockito must be served with JsHamcrest. No only do they go well
+together, it's essential to avoid a very nasty hangover. Get
+JsHamcrest from here:
+
+ http://github.com/danielfm/jshamcrest/
+
+
+How to drink it?
+----------------
+
+To use JsMockito with a JavaScript unit test framework, follow the
+usual installation/configuration instructions for the framework
+and plug JsMockito into it. If you're integrating with Screw.Unit
+(and why wouldn't you?) then more detailed instructions are below.
+
+Once installed, you can verify with interactions:
+
+ var mockedObject = mock(Array);
+
+ // -- start code under test --
+ mockedObject.push("one");
+ // -- end code under test --
+
+ verify(mockedObject).push("one");
+
+
+Or you can stub method calls:
+
+ var mockObject = mock(MyClass);
+
+ when(mockObject).get(1).thenReturn("hello world");
+
+ // -- start code under test --
+ alert(mockedObject.getGreeting("initial"));
+
+ // the following alerts 'true' as get(99) was not stubbed
+ alert(typeof (mockedObject.get(99)) === 'undefined');
+ // -- end code under test --
+
+
+For a JavaScript twist, you can also mock functions:
+
+ mockFunc = mockFunction();
+ when(mockFunc).call(this, anything()).then(function(arg) {
+ return "foo " + arg;
+ });
+
+ // -- start code under test --
+ mockFunc("bar");
+ // -- end code under test --
+
+ verify(mockFunc).call(this, anything());
+
+
+For more examples and documentation, look in the doc directory.
+
+
+Who is your bartender?
+----------------------
+
+This variation is served to you by Chris Leishman and friends. Also a big
+thumbs up and thanks to the mockito guys and appologies for ripping off your
+work so blatantly :-)
+
+Also thanks to the JsHamcrest authors, who made this easy.
View
19 build.properties
@@ -0,0 +1,19 @@
+# Project info
+NAME = jsmockito
+VERSION = 0.1.0
+NAME_V = ${NAME}-${VERSION}
+
+# Third-party libraries and applications
+LIB_DIR = ${basedir}/lib
+TOOLS_DIR = ${basedir}/tools
+
+# Documentation output directory
+DOC_DIR = ${basedir}/doc
+API_DIR = ${DOC_DIR}/api
+
+# Framework source code
+SRC_DIR = ${basedir}/src
+
+# Build output directory
+BUILD_DIR = ${basedir}/build
+DIST_DIR = ${basedir}/dist
View
106 build.xml
@@ -0,0 +1,106 @@
+<project name="JsMockito" default="basic" basedir=".">
+ <property file="build.properties"/>
+
+ <property name="DIST_V" value="${BUILD_DIR}/${NAME_V}.js"/>
+ <property name="DIST_PACK_V" value="${BUILD_DIR}/${NAME_V}-minified.js"/>
+
+ <taskdef resource="net/sf/antcontrib/antcontrib.properties">
+ <classpath>
+ <pathelement location="${LIB_DIR}/ant-contrib.jar"/>
+ </classpath>
+ </taskdef>
+
+ <taskdef name="jsdoctoolkit" classname="uk.co.darrenhurley.ant.tasks.JsDocToolkit">
+ <classpath>
+ <pathelement location="${LIB_DIR}/js.jar"/>
+ <pathelement location="${LIB_DIR}/jsdoctoolkit-ant-task.jar"/>
+ </classpath>
+ </taskdef>
+
+ <exec executable="git" outputproperty="GIT_REVISION">
+ <arg value="rev-list"/>
+ <arg value="--all"/>
+ <arg value="--max-count=1"/>
+ <arg value="--pretty"/>
+ </exec>
+
+ <propertyregex property="REV" input="${GIT_REVISION}" select="\1">
+ <regexp pattern="commit\W+([0-9a-f]+)"/>
+ </propertyregex>
+
+ <propertyregex property="DATE" input="${GIT_REVISION}" select="\1">
+ <regexp pattern="Date:\W+(.*)"/>
+ </propertyregex>
+
+ <target name="clean">
+ <delete dir="${BUILD_DIR}"/>
+ <delete dir="${DIST_DIR}"/>
+ </target>
+
+ <target name="basic" description="Creates the basic script file">
+ <property name="DIST" value="${BUILD_DIR}/${NAME}.js"/>
+ <echo message="Creating ${DIST}" />
+ <mkdir dir="${BUILD_DIR}" />
+ <concat destfile="${DIST}">
+ <fileset dir="${SRC_DIR}" includes="jsmockito.js"/>
+ </concat>
+ <replaceregexp match="@VERSION" replace="${VERSION}" flags="g" byline="true" file="${DIST}"/>
+ <replaceregexp match="@DATE" replace="${DATE}" file="${DIST}"/>
+ <replaceregexp match="@REV" replace="${REV}" file="${DIST}"/>
+ <copy file="${DIST}" tofile="${DIST_V}"/>
+ <echo message="Basic version created at ${DIST}"/>
+ </target>
+
+ <target name="test" depends="basic" description="Run the test suite using Rhino">
+ <echo message="Running test suite"/>
+ <java jar="${LIB_DIR}/js.jar" dir="spec" fork="true" resultproperty="exitCode">
+ <arg value="runner.js"/>
+ </java>
+ <fail message="Test Suite failed">
+ <condition>
+ <not>
+ <equals arg1="${exitCode}" arg2="0"/>
+ </not>
+ </condition>
+ </fail>
+ </target>
+
+ <target name="pack" depends="basic" description="Remove all comments and whitespace and compress">
+ <property name="DIST_PACK" value="${BUILD_DIR}/${NAME}-minified.js"/>
+ <echo message="Packing ${DIST}"/>
+ <java jar="${TOOLS_DIR}/yuicompressor.jar" fork="true">
+ <arg value="-o"/>
+ <arg value="${DIST_PACK}"/>
+ <arg value="${DIST}"/>
+ </java>
+ <copy file="${DIST_PACK}" tofile="${DIST_PACK_V}"/>
+ <echo message="Packed version created at ${DIST_PACK}"/>
+ </target>
+
+ <target name="doc" depends="basic" description="Generate API documentation">
+ <echo message="Creating API docs"/>
+ <jsdoctoolkit jsdochome="${TOOLS_DIR}/jsdoc-toolkit/" template="outline" outputdir="${API_DIR}">
+ <source file="${SRC_DIR}/jsmockito.js"/>
+ </jsdoctoolkit>
+ <echo message="API docs created at ${API_DIR}"/>
+ </target>
+
+ <target name="build" depends="test,doc" description="Performs the build">
+ <echo message="Build complete."/>
+ </target>
+
+ <target name="dist" depends="pack,doc" description="Generates files for distribution">
+ <property name="API_DOC_V" value="${DIST_DIR}/${NAME_V}-api-doc"/>
+ <mkdir dir="${DIST_DIR}"/>
+ <copy file="${DIST_V}" todir="${DIST_DIR}"/>
+ <copy file="${DIST_PACK_V}" todir="${DIST_DIR}"/>
+ <copy todir="${API_DOC_V}">
+ <fileset dir="${API_DIR}"/>
+ </copy>
+ <zip destfile="${API_DOC_V}.zip">
+ <zipfileset dir="${API_DIR}" prefix="${NAME_V}-api-doc"/>
+ </zip>
+ <delete dir="${API_DOC_V}"/>
+ <echo message="Created files for distribution at ${DIST_DIR}"/>
+ </target>
+</project>
View
BIN lib/ant-contrib.jar
Binary file not shown.
View
8,844 lib/env.rhino.js
8,844 additions, 0 deletions not shown because the diff is too large. Please use a local Git client to view these changes.
View
4,376 lib/jquery/jquery-1.3.2.js
4,376 additions, 0 deletions not shown because the diff is too large. Please use a local Git client to view these changes.
View
29 lib/jquery/jquery.fn.js
@@ -0,0 +1,29 @@
+(function($) {
+ $.fn.fn = function() {
+ var self = this;
+ var extension = arguments[0], name = arguments[0];
+ if (typeof name == "string") {
+ return apply(self, name, $.makeArray(arguments).slice(1, arguments.length));
+ } else {
+ $.each(extension, function(key, value) {
+ define(self, key, value);
+ });
+ return self;
+ }
+ }
+ function define(self, name, fn) {
+ self.data(namespacedName(name), fn);
+ };
+ function apply(self, name, args) {
+ var result;
+ self.each(function(i, item) {
+ var fn = $(item).data(namespacedName(name));
+ if (fn) result = fn.apply(item, args)
+ else throw(name + " is not defined");
+ });
+ return result;
+ };
+ function namespacedName(name) {
+ return 'fn.' + name;
+ }
+})(jQuery);
View
109 lib/jquery/jquery.print.js
@@ -0,0 +1,109 @@
+(function($) {
+
+ function print_array(obj, opts) {
+ var result = [];
+ for (var i = 0; i < Math.min(opts.max_array, obj.length); i++)
+ result.push($.print(obj[i], $.extend({}, opts, { max_array: 3, max_string: 40 })));
+
+ if (obj.length > opts.max_array)
+ result.push((obj.length - opts.max_array) + ' more...');
+ if (result.length == 0) return "[]"
+ return "[ " + result.join(", ") + " ]";
+ }
+
+ function print_element(obj) {
+ if (obj.nodeType == 1) {
+ var result = [];
+ var properties = [ 'className', 'id' ];
+ var extra = {
+ 'input': ['type', 'name', 'value'],
+ 'a': ['href', 'target'],
+ 'form': ['method', 'action'],
+ 'script': ['src'],
+ 'link': ['href'],
+ 'img': ['src']
+ };
+
+ $.each(properties.concat(extra[obj.tagName.toLowerCase()] || []), function(){
+ if (obj[this])
+ result.push(' ' + this.replace('className', 'class') + "=" + $.print(obj[this]))
+ });
+ return "<" + obj.tagName.toLowerCase()
+ + result.join('') + ">";
+ }
+ }
+
+ function print_object(obj, opts) {
+ var seen = opts.seen || [ obj ];
+
+ var result = [], key, value;
+ for (var k in obj) {
+ if (obj.hasOwnProperty(k) && $.inArray(obj[k], seen) < 0) {
+ seen.push(obj[k]);
+ value = $.print(obj[k], $.extend({}, opts, { max_array: 6, max_string: 40, seen: seen }));
+ } else
+ value = "...";
+ result.push(k + ": " + value);
+ }
+ if (result.length == 0) return "{}";
+ return "{ " + result.join(", ") + " }";
+ }
+
+ function print_string(value, opts) {
+ var character_substitutions = {
+ '\b': '\\b',
+ '\t': '\\t',
+ '\n': '\\n',
+ '\f': '\\f',
+ '\r': '\\r',
+ '"' : '\\"',
+ '\\': '\\\\'
+ };
+ var r = /["\\\x00-\x1f\x7f-\x9f]/g;
+
+ var str = r.test(value)
+ ? '"' + value.replace(r, function (a) {
+ var c = character_substitutions[a];
+ if (c) return c;
+ c = a.charCodeAt();
+ return '\\u00' + Math.floor(c / 16).toString(16) + (c % 16).toString(16);
+ }) + '"'
+ : '"' + value + '"';
+ if (str.length > opts.max_string)
+ return str.slice(0, opts.max_string + 1) + '..."';
+ else
+ return str;
+ }
+
+ $.print = function(obj, options) {
+ var opts = $.extend({}, { max_array: 10, max_string: 100 }, options);
+
+ if (typeof obj == 'undefined')
+ return "undefined";
+ else if (typeof obj == 'boolean')
+ return obj.toString();
+ else if (!obj && typeof obj == 'number')
+ return 'NaN';
+ else if (!obj)
+ return "null";
+ else if (typeof obj == 'string')
+ return print_string(obj, opts);
+ else if (obj instanceof RegExp)
+ return obj.toString();
+ else if (obj instanceof Array || obj.callee || obj.item)
+ return print_array(obj, opts);
+ else if (typeof obj == 'function' || obj instanceof Function)
+ return obj.toString().match(/^([^)]*\))/)[1];
+ else if (obj.nodeType)
+ return print_element(obj);
+ else if (obj instanceof jQuery)
+ return "$(" + $.print(obj.get()) + ")";
+ else if (obj instanceof Error)
+ return print_object(obj, $.extend({}, options, { max_string: 200 }));
+ else if (obj instanceof Object)
+ return print_object(obj, opts);
+ else
+ return obj.toString().replace(/\n\s*/g, '');
+ }
+
+})(jQuery);
View
BIN lib/js.jar
Binary file not shown.
View
BIN lib/jsdoctoolkit-ant-task.jar
Binary file not shown.
View
92 lib/screw-unit/screw.behaviors.js
@@ -0,0 +1,92 @@
+(function($) {
+ $(Screw).bind('loaded', function() {
+ $('.status').fn({
+ display: function() {
+ $(this).html(
+ $('.passed').length + $('.failed').length + ' test(s), ' + $('.failed').length + ' failure(s)<br />' +
+ ((new Date() - Screw.suite_start_time)/1000.0).toString() + " seconds elapsed"
+ );
+ }
+ });
+
+ $('.describe').fn({
+ parent: function() {
+ return $(this).parent('.describes').parent('.describe');
+ },
+
+ run_befores: function() {
+ $(this).fn('parent').fn('run_befores');
+ $(this).children('.befores').children('.before').fn('run');
+ },
+
+ run_afters: function() {
+ $(this).fn('parent').fn('run_afters');
+ $(this).children('.afters').children('.after').fn('run');
+ },
+
+ enqueue: function() {
+ $(this).children('.its').children('.it').fn('enqueue');
+ $(this).children('.describes').children('.describe').fn('enqueue');
+ },
+
+ selector: function() {
+ return $(this).fn('parent').fn('selector')
+ + ' > .describes > .describe:eq(' + $(this).parent('.describes').children('.describe').index(this) + ')';
+ }
+ });
+
+ $('body > .describe').fn({
+ selector: function() { return 'body > .describe' }
+ });
+
+ $('.it').fn({
+ parent: function() {
+ return $(this).parent('.its').parent('.describe');
+ },
+
+ run: function() {
+ try {
+ try {
+ $(this).fn('parent').fn('run_befores');
+ $(this).data('screwunit.run')();
+ } finally {
+ $(this).fn('parent').fn('run_afters');
+ }
+ $(this).trigger('passed');
+ } catch(e) {
+ $(this).trigger('failed', [e]);
+ }
+ },
+
+ enqueue: function() {
+ var self = $(this).trigger('enqueued');
+ $(Screw)
+ .queue(function() {
+ self.fn('run');
+ setTimeout(function() { $(Screw).dequeue() }, 0);
+ });
+ },
+
+ selector: function() {
+ return $(this).fn('parent').fn('selector')
+ + ' > .its > .it:eq(' + $(this).parent('.its').children('.it').index(this) + ')';
+ }
+ });
+
+ $('.before').fn({
+ run: function() { $(this).data('screwunit.run')() }
+ });
+
+ $('.after').fn({
+ run: function() { $(this).data('screwunit.run')() }
+ });
+
+ $(Screw).trigger('before');
+ var to_run = unescape(location.search.slice(1)) || 'body > .describe > .describes > .describe';
+ $(to_run)
+ .focus()
+ .eq(0).trigger('scroll').end()
+ .fn('enqueue');
+ $(Screw).queue(function() { $(Screw).trigger('after') });
+ })
+})(jQuery);
View
82 lib/screw-unit/screw.builder.js
@@ -0,0 +1,82 @@
+var Screw = (function($) {
+ var screw = {
+ Unit: function(fn) {
+ var contents = fn.toString().match(/^[^\{]*{((.*\n*)*)}/m)[1];
+ var fn = new Function("matchers", "specifications",
+ "with (specifications) { with (matchers) { " + contents + " } }"
+ );
+
+ $(Screw).queue(function() {
+ Screw.Specifications.context.push($('body > .describe'));
+ fn.call(this, Screw.Matchers, Screw.Specifications);
+ Screw.Specifications.context.pop();
+ $(this).dequeue();
+ });
+ },
+
+ Specifications: {
+ context: [],
+
+ describe: function(name, fn) {
+ var describe = $('<li class="describe"></li>')
+ .append($('<h1></h1>').text(name))
+ .append('<ol class="befores"></ol>')
+ .append('<ul class="its"></ul>')
+ .append('<ul class="describes"></ul>')
+ .append('<ol class="afters"></ol>');
+
+ this.context.push(describe);
+ fn.call();
+ this.context.pop();
+
+ this.context[this.context.length-1]
+ .children('.describes')
+ .append(describe);
+ },
+
+ it: function(name, fn) {
+ var it = $('<li class="it"></li>')
+ .append($('<h2></h2>').text(name))
+ .data('screwunit.run', fn);
+
+ this.context[this.context.length-1]
+ .children('.its')
+ .append(it);
+ },
+
+ before: function(fn) {
+ var before = $('<li class="before"></li>')
+ .data('screwunit.run', fn);
+
+ this.context[this.context.length-1]
+ .children('.befores')
+ .append(before);
+ },
+
+ after: function(fn) {
+ var after = $('<li class="after"></li>')
+ .data('screwunit.run', fn);
+
+ this.context[this.context.length-1]
+ .children('.afters')
+ .append(after);
+ }
+ }
+ };
+
+ $(screw).queue(function() { $(screw).trigger('loading') });
+
+ $(window).load(function(){
+ $('<div class="describe"></div>')
+ .append('<h3 class="status"></h3>')
+ .append('<ol class="befores"></ol>')
+ .append('<ul class="describes"></ul>')
+ .append('<ol class="afters"></ol>')
+ .appendTo('body');
+
+ $(screw).dequeue();
+ $(screw).trigger('loaded');
+ });
+
+ return screw;
+})(jQuery);
View
90 lib/screw-unit/screw.css
@@ -0,0 +1,90 @@
+html {
+ padding: 0.5em;
+ font-family: Georgia, serif;
+ background: #EDEBD5;
+}
+
+ li {
+ list-style-type: none;
+ }
+
+ .focused {
+ background-color: #F4F2E4;
+ }
+
+ .focused * {
+ opacity: 1.0;
+ }
+
+ h1, h2, p {
+ opacity: 0.4;
+ }
+
+ .describes {
+ padding-left: 0;
+ }
+
+ .describes h1 {
+ font-size: 1.1em;
+ color: #877C21;
+ line-height: 1.8em;
+ margin: 0pt 0pt 0.6em;
+ border-bottom: 1px solid transparent;
+ }
+
+ .describes h1:hover {
+ cursor: pointer;
+ color: #000;
+ background-color: #F4F2E4;
+ border-bottom: 1px solid #9A8E51;
+ }
+
+ .describes .describe {
+ margin-left: 0.6em;
+ padding-left: 0.6em;
+ border: 1px dashed grey;
+ }
+
+ .describes .describe .its {}
+
+ .describes .describe .its .it {
+ list-style-type: lower-roman;
+ list-style-position: outside;
+ }
+
+ .describes .describe .its .it h2 {
+ font-weight: normal;
+ font-style: italic;
+ padding-left: 0.5em;
+ font-size: 1.0em;
+ color: #877C21;
+ line-height: 1.8em;
+ margin: 0 0 0.5em;
+ border-bottom: 1px solid transparent;
+ }
+
+ .describes .describe .its .it.enqueued h2 {
+ background-color: #CC6600;
+ color: white !important;
+ }
+
+ .describes .describe .its .it.passed h2 {
+ background-color: #5A753D;
+ color: white !important;
+ }
+
+ .describes .describe .its .it.failed h2 {
+ background-color: #993300;
+ color: white !important;
+ }
+
+ .describes .describe .its .it.failed p {
+ margin-left: 1em;
+ color: #993300;
+ }
+
+ .describes .describe .its .it h2:hover {
+ cursor: pointer;
+ color: #000 !important;
+ border-bottom: 1px solid #9A8E51;
+ }
View
45 lib/screw-unit/screw.events.js
@@ -0,0 +1,45 @@
+(function($) {
+ $(Screw)
+ .bind('loaded', function() {
+ $('.describe, .it')
+ .click(function() {
+ document.location = location.href.split('?')[0] + '?' + $(this).fn('selector');
+ return false;
+ })
+ .focus(function() {
+ return $(this).addClass('focused');
+ })
+ .bind('scroll', function() {
+ document.body.scrollTop = $(this).offset().top;
+ });
+
+ $('.it')
+ .bind('enqueued', function() {
+ $(this).addClass('enqueued');
+ })
+ .bind('running', function() {
+ $(this).addClass('running');
+ })
+ .bind('passed', function() {
+ $(this).addClass('passed');
+ })
+ .bind('failed', function(e, reason) {
+ $(this)
+ .addClass('failed')
+ .append($('<p class="error"></p>').text(reason.toString()));
+
+ var file = reason.fileName || reason.sourceURL;
+ var line = reason.lineNumber || reason.line;
+ if (file || line) {
+ $(this).append($('<p class="error"></p>').text('line ' + line + ', ' + file));
+ }
+ })
+ })
+ .bind('before', function() {
+ Screw.suite_start_time = new Date();
+ $('.status').text('Running...');
+ })
+ .bind('after', function() {
+ $('.status').fn('display')
+ })
+})(jQuery);
View
187 lib/screw-unit/screw.matchers.js
@@ -0,0 +1,187 @@
+Screw.Matchers = (function($) {
+ return matchers = {
+ expect: function(actual) {
+ return {
+ to: function(matcher, expected, not) {
+ var matched = matcher.match(expected, actual);
+ if (not ? matched : !matched) {
+ throw(matcher.failure_message(expected, actual, not));
+ }
+ },
+
+ to_not: function(matcher, expected) {
+ this.to(matcher, expected, true);
+ }
+ }
+ },
+
+ equal: {
+ match: function(expected, actual) {
+ if(expected == actual) return true;
+ if(actual == undefined) return false;
+
+ if (expected instanceof Array) {
+ for (var i = 0; i < actual.length; i++)
+ if (!Screw.Matchers.equal.match(expected[i], actual[i])) return false;
+ return actual.length == expected.length;
+ } else if (expected instanceof Object) {
+ for (var key in expected)
+ if (!this.match(expected[key], actual[key])) return false;
+ for (var key in actual)
+ if (!this.match(actual[key], expected[key])) return false;
+ return true;
+ }
+ return false;
+ },
+
+ failure_message: function(expected, actual, not) {
+ return 'expected ' + $.print(actual) + (not ? ' to not equal ' : ' to equal ') + $.print(expected);
+ }
+ },
+
+ be_gt: {
+ match: function(expected, actual) {
+ return actual > expected;
+ },
+
+ failure_message: function(expected, actual, not) {
+ return 'expected ' + $.print(actual) + (not ? ' to not ' : ' to ') + 'be greater than ' + $.print(expected);
+ }
+ },
+
+ be_gte: {
+ match: function(expected, actual) {
+ return actual >= expected;
+ },
+
+ failure_message: function(expected, actual, not) {
+ return 'expected ' + $.print(actual) + (not ? ' to not ' : ' to ') + 'be greater than or equal to ' + $.print(expected);
+ }
+ },
+
+ be_lt: {
+ match: function(expected, actual) {
+ return actual < expected;
+ },
+
+ failure_message: function(expected, actual, not) {
+ return 'expected ' + $.print(actual) + (not ? ' to not ' : ' to ') + 'be less than ' + $.print(expected);
+ }
+ },
+
+ be_lte: {
+ match: function(expected, actual) {
+ return actual <= expected;
+ },
+
+ failure_message: function(expected, actual, not) {
+ return 'expected ' + $.print(actual) + (not ? ' to not ' : ' to ') + 'be less than or equal to ' + $.print(expected);
+ }
+ },
+
+ match: {
+ match: function(expected, actual) {
+ if (expected.constructor == RegExp)
+ return expected.exec(actual.toString());
+ else
+ return actual.indexOf(expected) > -1;
+ },
+
+ failure_message: function(expected, actual, not) {
+ return 'expected ' + $.print(actual) + (not ? ' to not match ' : ' to match ') + $.print(expected);
+ }
+ },
+
+ be_empty: {
+ match: function(expected, actual) {
+ if (actual.length == undefined) throw(actual.toString() + " does not respond to length");
+
+ return actual.length == 0;
+ },
+
+ failure_message: function(expected, actual, not) {
+ return 'expected ' + $.print(actual) + (not ? ' to not be empty' : ' to be empty');
+ }
+ },
+
+ have_length: {
+ match: function(expected, actual) {
+ if (actual.length == undefined) throw(actual.toString() + " does not respond to length");
+
+ return actual.length == expected;
+ },
+
+ failure_message: function(expected, actual, not) {
+ return 'expected ' + $.print(actual) + (not ? ' to not' : ' to') + ' have length ' + expected;
+ }
+ },
+
+ be_null: {
+ match: function(expected, actual) {
+ return actual == null;
+ },
+
+ failure_message: function(expected, actual, not) {
+ return 'expected ' + $.print(actual) + (not ? ' to not be null' : ' to be null');
+ }
+ },
+
+ be_undefined: {
+ match: function(expected, actual) {
+ return actual == undefined;
+ },
+
+ failure_message: function(expected, actual, not) {
+ return 'expected ' + $.print(actual) + (not ? ' to not be undefined' : ' to be undefined');
+ }
+ },
+
+ be_true: {
+ match: function(expected, actual) {
+ return actual;
+ },
+
+ failure_message: function(expected, actual, not) {
+ return 'expected ' + $.print(actual) + (not ? ' to not be true' : ' to be true');
+ }
+ },
+
+ be_false: {
+ match: function(expected, actual) {
+ return !actual;
+ },
+
+ failure_message: function(expected, actual, not) {
+ return 'expected ' + $.print(actual) + (not ? ' to not be false' : ' to be false');
+ }
+ },
+
+ match_selector: {
+ match: function(expected, actual) {
+ if (!(actual instanceof jQuery)) {
+ throw expected.toString() + " must be an instance of jQuery to match against a selector"
+ }
+
+ return actual.is(expected);
+ },
+
+ failure_message: function(expected, actual, not) {
+ return 'expected ' + $.print(actual) + (not ? ' to not match selector ' : ' to match selector ') + expected;
+ }
+ },
+
+ contain_selector: {
+ match: function(expected, actual) {
+ if (!(actual instanceof jQuery)) {
+ throw expected.toString() + " must be an instance of jQuery to match against a selector"
+ }
+
+ return actual.find(expected).length > 0;
+ },
+
+ failure_message: function(expected, actual, not) {
+ return 'expected ' + $.print(actual) + (not ? ' to not contain selector ' : ' to contain selector ') + expected;
+ }
+ }
+ }
+})(jQuery);
View
6 spec/core_spec.js
@@ -0,0 +1,6 @@
+Screw.Unit(function() {
+ describe('JsMockito', function() {
+ it("should do something", function() {
+ });
+ });
+});
View
77 spec/runner.js
@@ -0,0 +1,77 @@
+/*
+Sections of the code below taken from the blue-ridge rake plugin:
+
+ http://github.com/relevance/blue-ridge
+
+Copyright (c) 2008-2009 Relevance, Inc.
+
+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.
+*/
+
+load('../lib/env.rhino.js');
+window.location = 'suite.html';
+
+var scripts = document.getElementsByTagName('script');
+for (var i=0; i < scripts.length; i++) {
+ if (scripts[i].getAttribute('type') == 'text/javascript') {
+ try {
+ load(scripts[i].src);
+ } catch(e) {
+ $error("Error loading script", e);
+ }
+ }
+}
+
+(function($) {
+ var passed = 0;
+ var failed = 0;
+
+ $(Screw).bind("before", function(){
+ function example_name(element){
+ // TODO: handle nested describes!
+ var context_name = $(element).parents(".describe").children("h1").text();
+ var example_name = $(element).children("h2").text();
+
+ return context_name + " - " + example_name;
+ }
+
+ $('.it').bind('passed', function() {
+ passed++;
+ java.lang.System.out.print(".");
+ }).bind('failed', function(e, reason) {
+ failed++;
+ print("\nFAILED: " + example_name(this));
+ print(" " + reason + "\n");
+ });
+ });
+
+ $(Screw).bind("after", function() {
+ var testCount = passed + failed;
+ var elapsedTime = ((new Date() - Screw.suite_start_time)/1000.0);
+
+ print("\n");
+ print(testCount + ' test(s), ' + failed + ' failure(s)');
+ print(elapsedTime.toString() + " seconds elapsed");
+
+ if (failed > 0) { java.lang.System.exit(1) };
+ });
+})(jQuery);
+
+jQuery(window).trigger("load");
View
0 spec/spec_helper.js
No changes.
View
17 spec/suite.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>JsMockito Test Suite</title>
+ <link rel="stylesheet" href="../lib/screw-unit/screw.css" type="text/css" charset="utf-8" />
+ <script type="text/javascript" src="../lib/jquery/jquery-1.3.2.js"></script>
+ <script type="text/javascript" src="../lib/jquery/jquery.fn.js"></script>
+ <script type="text/javascript" src="../lib/jquery/jquery.print.js"></script>
+ <script type="text/javascript" src="../lib/screw-unit/screw.builder.js"></script>
+ <script type="text/javascript" src="../lib/screw-unit/screw.matchers.js"></script>
+ <script type="text/javascript" src="../lib/screw-unit/screw.events.js"></script>
+ <script type="text/javascript" src="../lib/screw-unit/screw.behaviors.js"></script>
+ <script type="text/javascript" src="core_spec.js"></script>
+ </head>
+ <body>
+ </body>
+</html>
View
0 src/jsmockito.js
No changes.
View
146 tools/jsdoc-toolkit/README.txt
@@ -0,0 +1,146 @@
+======================================================================
+
+DESCRIPTION:
+
+This is the source code for JsDoc Toolkit, an automatic documentation
+generation tool for JavaScript. It is written in JavaScript and is run
+from a command line (or terminal) using the Java and Mozilla's Rhino
+JavaScript runtime engine.
+
+Using this tool you can automatically turn JavaDoc-like comments in
+your JavaScript source code into published output files, such as HTML
+or XML.
+
+For more information, to report a bug, or to browse the technical
+documentation for this tool please visit the official JsDoc Toolkit
+project homepage at http://code.google.com/p/jsdoc-toolkit/
+
+For the most up-to-date documentation on JsDoc Toolkit see the
+official wiki at http://code.google.com/p/jsdoc-toolkit/w/list
+
+======================================================================
+
+REQUIREMENTS:
+
+JsDoc Toolkit is known to work with:
+java version "1.6.0_03"
+Java(TM) SE Runtime Environment (build 1.6.0_03-b05)
+on Windows XP,
+and java version "1.5.0_13"
+Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_13-b05-241)
+on Mac OS X 10.4.
+
+Other versions of java may or may not work with JsDoc Toolkit.
+
+======================================================================
+
+USAGE:
+
+Running JsDoc Toolkit requires you to have Java installed on your
+computer. For more information see http://www.java.com/getjava/
+
+Before running the JsDoc Toolkit app you should change your current
+working directory to the jsdoc-toolkit folder. Then follow the
+examples below, or as shown on the project wiki.
+
+On a computer running Windows a valid command line to run JsDoc
+Toolkit might look like this:
+
+> java -jar jsrun.jar app\run.js -a -t=templates\jsdoc mycode.js
+
+On Mac OS X or Linux the same command would look like this:
+
+$ java -jar jsrun.jar app/run.js -a -t=templates/jsdoc mycode.js
+
+The above assumes your current working directory contains jsrun.jar,
+the "app" and "templates" subdirectories from the standard JsDoc
+Toolkit distribution and that the relative path to the code you wish
+to document is "mycode.js".
+
+The output documentation files will be saved to a new directory named
+"out" (by default) in the current directory, or if you specify a
+-d=somewhere_else option, to the somewhere_else directory.
+
+For help (usage notes) enter this on the command line:
+
+$ java -jar jsrun.jar app/run.js --help
+
+More information about the various command line options used by JsDoc
+Toolkit are available on the project wiki.
+
+======================================================================
+
+TESTING:
+
+To run the suite of unit tests included with JsDoc Toolkit enter this
+on the command line:
+
+$ java -jar jsrun.jar app/run.js -T
+
+To see a dump of the internal data structure that JsDoc Toolkit has
+built from your source files use this command:
+
+$ java -jar jsrun.jar app/run.js mycode.js -Z
+
+======================================================================
+
+LICENSE:
+
+JSDoc.pm
+
+This project is based on the JSDoc.pm tool, created by Michael
+Mathews and Gabriel Reid. More information on JsDoc.pm can
+be found on the JSDoc.pm homepage: http://jsdoc.sourceforge.net/
+
+Complete documentation on JsDoc Toolkit can be found on the project
+wiki at http://code.google.com/p/jsdoc-toolkit/w/list
+
+Rhino
+
+Rhino (JavaScript in Java) is open source and licensed by Mozilla
+under the MPL 1.1 or later/GPL 2.0 or later licenses, the text of
+which is available at http://www.mozilla.org/MPL/
+
+You can obtain the source code for Rhino from the Mozilla web site at
+http://www.mozilla.org/rhino/download.html
+
+JsDoc Toolkit is a larger work that uses the Rhino JavaScript engine
+but is not derived from it in any way. The Rhino library is used
+without modification and without any claims whatsoever.
+
+The Rhino Debugger
+
+You can obtain more information about the Rhino Debugger from the
+Mozilla web site at http://www.mozilla.org/rhino/debugger.html
+
+JsDoc Toolkit is a larger work that uses the Rhino Debugger but
+is not derived from it in any way. The Rhino Debugger is used
+without modification and without any claims whatsoever.
+
+JsDoc Toolkit
+
+All code specific to JsDoc Toolkit are free, open source and licensed
+for use under the X11/MIT License.
+
+JsDoc Toolkit is Copyright (c)2009 Michael Mathews <micmath@gmail.com>
+
+This program is free software; you can redistribute it and/or
+modify it under the terms below.
+
+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 must be included in all copies or substantial
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
View
33 tools/jsdoc-toolkit/app/frame.js
@@ -0,0 +1,33 @@
+IO.include("frame/Opt.js");
+IO.include("frame/Chain.js");
+IO.include("frame/Link.js");
+IO.include("frame/String.js");
+IO.include("frame/Hash.js");
+IO.include("frame/Namespace.js");
+//IO.include("frame/Reflection.js");
+
+/** A few helper functions to make life a little easier. */
+
+function defined(o) {
+ return (o !== undefined);
+}
+
+function copy(o) { // todo check for circular refs
+ if (o == null || typeof(o) != 'object') return o;
+ var c = new o.constructor();
+ for(var p in o) c[p] = copy(o[p]);
+ return c;
+}
+
+function isUnique(arr) {
+ var l = arr.length;
+ for(var i = 0; i < l; i++ ) {
+ if (arr.lastIndexOf(arr[i]) > i) return false;
+ }
+ return true;
+}
+
+/** Returns the given string with all regex meta characters backslashed. */
+RegExp.escapeMeta = function(str) {
+ return str.replace(/([$^\\\/()|?+*\[\]{}.-])/g, "\\$1");
+}
View
102 tools/jsdoc-toolkit/app/frame/Chain.js
@@ -0,0 +1,102 @@
+/**@constructor*/
+function ChainNode(object, link) {
+ this.value = object;
+ this.link = link; // describes this node's relationship to the previous node
+}
+
+/**@constructor*/
+function Chain(valueLinks) {
+ this.nodes = [];
+ this.cursor = -1;
+
+ if (valueLinks && valueLinks.length > 0) {
+ this.push(valueLinks[0], "//");
+ for (var i = 1, l = valueLinks.length; i < l; i+=2) {
+ this.push(valueLinks[i+1], valueLinks[i]);
+ }
+ }
+}
+
+Chain.prototype.push = function(o, link) {
+ if (this.nodes.length > 0 && link) this.nodes.push(new ChainNode(o, link));
+ else this.nodes.push(new ChainNode(o));
+}
+
+Chain.prototype.unshift = function(o, link) {
+ if (this.nodes.length > 0 && link) this.nodes[0].link = link;
+ this.nodes.unshift(new ChainNode(o));
+ this.cursor++;
+}
+
+Chain.prototype.get = function() {
+ if (this.cursor < 0 || this.cursor > this.nodes.length-1) return null;
+ return this.nodes[this.cursor];
+}
+
+Chain.prototype.first = function() {
+ this.cursor = 0;
+ return this.get();
+}
+
+Chain.prototype.last = function() {
+ this.cursor = this.nodes.length-1;
+ return this.get();
+}
+
+Chain.prototype.next = function() {
+ this.cursor++;
+ return this.get();
+}
+
+Chain.prototype.prev = function() {
+ this.cursor--;
+ return this.get();
+}
+
+Chain.prototype.toString = function() {
+ var string = "";
+ for (var i = 0, l = this.nodes.length; i < l; i++) {
+ if (this.nodes[i].link) string += " -("+this.nodes[i].link+")-> ";
+ string += this.nodes[i].value.toString();
+ }
+ return string;
+}
+
+Chain.prototype.joinLeft = function() {
+ var result = "";
+ for (var i = 0, l = this.cursor; i < l; i++) {
+ if (result && this.nodes[i].link) result += this.nodes[i].link;
+ result += this.nodes[i].value.toString();
+ }
+ return result;
+}
+
+
+/* USAGE:
+
+var path = "one/two/three.four/five-six";
+var pathChain = new Chain(path.split(/([\/.-])/));
+print(pathChain);
+
+var lineage = new Chain();
+lineage.push("Port");
+lineage.push("Les", "son");
+lineage.push("Dawn", "daughter");
+lineage.unshift("Purdie", "son");
+
+print(lineage);
+
+// walk left
+for (var node = lineage.last(); node !== null; node = lineage.prev()) {
+ print("< "+node.value);
+}
+
+// walk right
+var node = lineage.first()
+while (node !== null) {
+ print(node.value);
+ node = lineage.next();
+ if (node && node.link) print("had a "+node.link+" named");
+}
+
+*/
View
144 tools/jsdoc-toolkit/app/frame/Dumper.js
@@ -0,0 +1,144 @@
+/**
+ * @class
+<pre>
+This is a lightly modified version of Kevin Jones' JavaScript
+library Data.Dump. To download the original visit:
+ <a href="http://openjsan.org/doc/k/ke/kevinj/Data/Dump/">http://openjsan.org/doc/k/ke/kevinj/Data/Dump/</a>
+
+AUTHORS
+
+The Data.Dump JavaScript module is written by Kevin Jones
+(kevinj@cpan.org), based on Data::Dump by Gisle Aas (gisle@aas.no),
+based on Data::Dumper by Gurusamy Sarathy (gsar@umich.edu).
+
+COPYRIGHT
+
+Copyright 2007 Kevin Jones. Copyright 1998-2000,2003-2004 Gisle Aas.
+Copyright 1996-1998 Gurusamy Sarathy.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the Perl Artistic License
+
+See http://www.perl.com/perl/misc/Artistic.html
+</pre>
+ * @static
+ */
+Dumper = {
+ /** @param [...] The objects to dump. */
+ dump: function () {
+ if (arguments.length > 1)
+ return this._dump(arguments);
+ else if (arguments.length == 1)
+ return this._dump(arguments[0]);
+ else
+ return "()";
+ },
+
+ _dump: function (obj) {
+ if (typeof obj == 'undefined') return 'undefined';
+ var out;
+ if (obj.serialize) { return obj.serialize(); }
+ var type = this._typeof(obj);
+ if (obj.circularReference) obj.circularReference++;
+ switch (type) {
+ case 'circular':
+ out = "{ //circularReference\n}";
+ break;
+ case 'object':
+ var pairs = new Array;
+
+ for (var prop in obj) {
+ if (prop != "circularReference" && obj.hasOwnProperty(prop)) { //hide inherited properties
+ pairs.push(prop + ': ' + this._dump(obj[prop]));
+ }
+ }
+
+ out = '{' + this._format_list(pairs) + '}';
+ break;
+
+ case 'string':
+ for (var prop in Dumper.ESC) {
+ if (Dumper.ESC.hasOwnProperty(prop)) {
+ obj = obj.replace(prop, Dumper.ESC[prop]);
+ }
+ }
+
+ // Escape UTF-8 Strings
+ if (obj.match(/^[\x00-\x7f]*$/)) {
+ out = '"' + obj.replace(/\"/g, "\\\"").replace(/([\n\r]+)/g, "\\$1") + '"';
+ }
+ else {
+ out = "unescape('"+escape(obj)+"')";
+ }
+ break;
+
+ case 'array':
+ var elems = new Array;
+
+ for (var i=0; i<obj.length; i++) {
+ elems.push( this._dump(obj[i]) );
+ }
+
+ out = '[' + this._format_list(elems) + ']';
+ break;
+
+ case 'date':
+ // firefox returns GMT strings from toUTCString()...
+ var utc_string = obj.toUTCString().replace(/GMT/,'UTC');
+ out = 'new Date("' + utc_string + '")';
+ break;
+
+ case 'element':
+ // DOM element
+ out = this._dump_dom(obj);
+ break;
+
+ default:
+ out = obj;
+ }
+
+ out = String(out).replace(/\n/g, '\n ');
+ out = out.replace(/\n (.*)$/,"\n$1");
+
+ return out;
+ },
+
+ _format_list: function (list) {
+ if (!list.length) return '';
+ var nl = list.toString().length > 60 ? '\n' : ' ';
+ return nl + list.join(',' + nl) + nl;
+ },
+
+ _typeof: function (obj) {
+ if (obj && obj.circularReference && obj.circularReference > 1) return 'circular';
+ if (Array.prototype.isPrototypeOf(obj)) return 'array';
+ if (Date.prototype.isPrototypeOf(obj)) return 'date';
+ if (typeof obj.nodeType != 'undefined') return 'element';
+ return typeof(obj);
+ },
+
+ _dump_dom: function (obj) {
+ return '"' + Dumper.nodeTypes[obj.nodeType] + '"';
+ }
+};
+
+Dumper.ESC = {
+ "\t": "\\t",
+ "\n": "\\n",
+ "\f": "\\f"
+};
+
+Dumper.nodeTypes = {
+ 1: "ELEMENT_NODE",
+ 2: "ATTRIBUTE_NODE",
+ 3: "TEXT_NODE",
+ 4: "CDATA_SECTION_NODE",
+ 5: "ENTITY_REFERENCE_NODE",
+ 6: "ENTITY_NODE",
+ 7: "PROCESSING_INSTRUCTION_NODE",
+ 8: "COMMENT_NODE",
+ 9: "DOCUMENT_NODE",
+ 10: "DOCUMENT_TYPE_NODE",
+ 11: "DOCUMENT_FRAGMENT_NODE",
+ 12: "NOTATION_NODE"
+};
View
84 tools/jsdoc-toolkit/app/frame/Hash.js
@@ -0,0 +1,84 @@
+/**
+ @constructor
+ @example
+ var _index = new Hash();
+ _index.set("a", "apple");
+ _index.set("b", "blue");
+ _index.set("c", "coffee");
+
+ for (var p = _index.first(); p; p = _index.next()) {
+ print(p.key+" is for "+p.value);
+ }
+
+ */
+var Hash = function() {
+ this._map = {};
+ this._keys = [];
+ this._vals = [];
+ this.reset();
+}
+
+Hash.prototype.set = function(k, v) {
+ if (k != "") {
+ this._keys.push(k);
+ this._map["="+k] = this._vals.length;
+ this._vals.push(v);
+ }
+}
+
+Hash.prototype.replace = function(k, k2, v) {
+ if (k == k2) return;
+
+ var offset = this._map["="+k];
+ this._keys[offset] = k2;
+ if (typeof v != "undefined") this._vals[offset] = v;
+ this._map["="+k2] = offset;
+ delete(this._map["="+k]);
+}
+
+Hash.prototype.drop = function(k) {
+ if (k != "") {
+ var offset = this._map["="+k];
+ this._keys.splice(offset, 1);
+ this._vals.splice(offset, 1);
+ delete(this._map["="+k]);
+ for (var p in this._map) {
+ if (this._map[p] >= offset) this._map[p]--;
+ }
+ if (this._cursor >= offset && this._cursor > 0) this._cursor--;
+ }
+}
+
+Hash.prototype.get = function(k) {
+ if (k != "") {
+ return this._vals[this._map["="+k]];
+ }
+}
+
+Hash.prototype.keys = function() {
+ return this._keys;
+}
+
+Hash.prototype.hasKey = function(k) {
+ if (k != "") {
+ return (typeof this._map["="+k] != "undefined");
+ }
+}
+
+Hash.prototype.values = function() {
+ return this._vals;
+}
+
+Hash.prototype.reset = function() {
+ this._cursor = 0;
+}
+
+Hash.prototype.first = function() {
+ this.reset();
+ return this.next();
+}
+
+Hash.prototype.next = function() {
+ if (this._cursor++ < this._keys.length)
+ return {key: this._keys[this._cursor-1], value: this._vals[this._cursor-1]};
+}
View
148 tools/jsdoc-toolkit/app/frame/Link.js
@@ -0,0 +1,148 @@
+/** Handle the creation of HTML links to documented symbols.
+ @constructor
+*/
+function Link() {
+ this.alias = "";
+ this.src = "";
+ this.file = "";
+ this.text = "";
+ this.innerName = "";
+ this.classLink = false;
+ this.targetName = "";
+
+ this.target = function(targetName) {
+ if (defined(targetName)) this.targetName = targetName;
+ return this;
+ }
+ this.inner = function(inner) {
+ if (defined(inner)) this.innerName = inner;
+ return this;
+ }
+ this.withText = function(text) {
+ if (defined(text)) this.text = text;
+ return this;
+ }
+ this.toSrc = function(filename) {
+ if (defined(filename)) this.src = filename;
+ return this;
+ }
+ this.toSymbol = function(alias) {
+ if (defined(alias)) this.alias = new String(alias);
+ return this;
+ }
+ this.toClass = function(alias) {
+ this.classLink = true;
+ return this.toSymbol(alias);
+ }
+ this.toFile = function(file) {
+ if (defined(file)) this.file = file;
+ return this;
+ }
+
+ this.toString = function() {
+ var linkString;
+ var thisLink = this;
+
+ if (this.alias) {
+ linkString = this.alias.replace(/(^|[^a-z$0-9_#.:^-])([|a-z$0-9_#.:^-]+)($|[^a-z$0-9_#.:^-])/i,
+ function(match, prematch, symbolName, postmatch) {
+ var symbolNames = symbolName.split("|");
+ var links = [];
+ for (var i = 0, l = symbolNames.length; i < l; i++) {
+ thisLink.alias = symbolNames[i];
+ links.push(thisLink._makeSymbolLink(symbolNames[i]));
+ }
+ return prematch+links.join("|")+postmatch;
+ }
+ );
+ }
+ else if (this.src) {
+ linkString = thisLink._makeSrcLink(this.src);
+ }
+ else if (this.file) {
+ linkString = thisLink._makeFileLink(this.file);
+ }
+
+ return linkString;
+ }
+}
+
+/** prefixed for hashes */
+Link.hashPrefix = "";
+
+/** Appended to the front of relative link paths. */
+Link.base = "";
+
+Link.symbolNameToLinkName = function(symbol) {
+ var linker = "";
+ if (symbol.isStatic) linker = ".";
+ else if (symbol.isInner) linker = "-";
+
+ return Link.hashPrefix+linker+symbol.name;
+}
+
+/** Create a link to a snother symbol. */
+Link.prototype._makeSymbolLink = function(alias) {
+ var linkBase = Link.base+publish.conf.symbolsDir;
+ var linkTo = Link.symbolSet.getSymbol(alias);
+ var linkPath;
+ var target = (this.targetName)? " target=\""+this.targetName+"\"" : "";
+
+ // is it an internal link?
+ if (alias.charAt(0) == "#") var linkPath = alias;
+
+ // if there is no symbol by that name just return the name unaltered
+ else if (!linkTo) return this.text || alias;
+
+ // it's a symbol in another file
+ else {
+
+ if (!linkTo.is("CONSTRUCTOR") && !linkTo.isNamespace) { // it's a method or property
+ if (linkTo.isEvent) {
+ linkPath = escape(linkTo.memberOf) || "_global_";
+ linkPath += publish.conf.ext + "#event:" + Link.symbolNameToLinkName(linkTo);
+ }
+ else {
+ linkPath = escape(linkTo.memberOf) || "_global_";
+ linkPath += publish.conf.ext + "#" + Link.symbolNameToLinkName(linkTo);
+ }
+ }
+ else {
+ linkPath = escape(linkTo.alias);
+ linkPath += publish.conf.ext;// + (this.classLink? "":"#" + Link.hashPrefix + "constructor");
+ }
+ linkPath = linkBase + linkPath
+ }
+
+ var linkText = this.text || alias;
+
+ var link = {linkPath: linkPath, linkText: linkText};
+
+ if (typeof JSDOC.PluginManager != "undefined") {
+ JSDOC.PluginManager.run("onSymbolLink", link);
+ }
+
+ return "<a href=\""+link.linkPath+"\""+target+">"+link.linkText+"</a>";
+}
+
+/** Create a link to a source file. */
+Link.prototype._makeSrcLink = function(srcFilePath) {
+ var target = (this.targetName)? " target=\""+this.targetName+"\"" : "";
+
+ // transform filepath into a filename
+ var srcFile = srcFilePath.replace(/\.\.?[\\\/]/g, "").replace(/[:\\\/]/g, "_");
+ var outFilePath = Link.base + publish.conf.srcDir + srcFile + publish.conf.ext;
+
+ if (!this.text) this.text = FilePath.fileName(srcFilePath);
+ return "<a href=\""+outFilePath+"\""+target+">"+this.text+"</a>";
+}
+
+/** Create a link to a source file. */
+Link.prototype._makeFileLink = function(filePath) {
+ var target = (this.targetName)? " target=\""+this.targetName+"\"" : "";
+
+ var outFilePath = Link.base + filePath;
+
+ if (!this.text) this.text = filePath;
+ return "<a href=\""+outFilePath+"\""+target+">"+this.text+"</a>";
+}
View
10 tools/jsdoc-toolkit/app/frame/Namespace.js
@@ -0,0 +1,10 @@
+_global_ = this;
+
+function Namespace(name, f) {
+ var n = name.split(".");
+ for (var o = _global_, i = 0, l = n.length; i < l; i++) {
+ o = o[n[i]] = o[n[i]] || {};
+ }
+
+ if (f) f();
+}
View
134 tools/jsdoc-toolkit/app/frame/Opt.js
@@ -0,0 +1,134 @@
+/** @namespace */
+Opt = {
+ /**
+ * Get commandline option values.
+ * @param {Array} args Commandline arguments. Like ["-a=xml", "-b", "--class=new", "--debug"]
+ * @param {object} optNames Map short names to long names. Like {a:"accept", b:"backtrace", c:"class", d:"debug"}.
+ * @return {object} Short names and values. Like {a:"xml", b:true, c:"new", d:true}
+ */
+ get: function(args, optNames) {
+ var opt = {"_": []}; // the unnamed option allows multiple values
+ for (var i = 0; i < args.length; i++) {
+ var arg = new String(args[i]);
+ var name;
+ var value;
+ if (arg.charAt(0) == "-") {
+ if (arg.charAt(1) == "-") { // it's a longname like --foo
+ arg = arg.substring(2);
+ var m = arg.split("=");
+ name = m.shift();
+ value = m.shift();
+ if (typeof value == "undefined") value = true;
+
+ for (var n in optNames) { // convert it to a shortname
+ if (name == optNames[n]) {
+ name = n;
+ }
+ }
+ }
+ else { // it's a shortname like -f
+ arg = arg.substring(1);
+ var m = arg.split("=");
+ name = m.shift();
+ value = m.shift();
+ if (typeof value == "undefined") value = true;
+
+ for (var n in optNames) { // find the matching key
+ if (name == n || name+'[]' == n) {
+ name = n;
+ break;
+ }
+ }
+ }
+ if (name.match(/(.+)\[\]$/)) { // it's an array type like n[]
+ name = RegExp.$1;
+ if (!opt[name]) opt[name] = [];
+ }
+
+ if (opt[name] && opt[name].push) {
+ opt[name].push(value);
+ }
+ else {
+ opt[name] = value;
+ }
+ }
+ else { // not associated with any optname
+ opt._.push(args[i]);
+ }
+ }
+ return opt;
+ }
+}
+
+/*t:
+ plan(11, "Testing Opt.");
+
+ is(
+ typeof Opt,
+ "object",
+ "Opt is an object."
+ );
+
+ is(
+ typeof Opt.get,
+ "function",
+ "Opt.get is a function."
+ );
+
+ var optNames = {a:"accept", b:"backtrace", c:"class", d:"debug", "e[]":"exceptions"};
+ var t_options = Opt.get(["-a=xml", "-b", "--class=new", "--debug", "-e=one", "-e=two", "foo", "bar"], optNames);
+
+ is(
+ t_options.a,
+ "xml",
+ "an option defined with a short name can be accessed by its short name."
+ );
+
+ is(
+ t_options.b,
+ true,
+ "an option defined with a short name and no value are true."
+ );
+
+ is(
+ t_options.c,
+ "new",
+ "an option defined with a long name can be accessed by its short name."
+ );
+
+ is(
+ t_options.d,
+ true,
+ "an option defined with a long name and no value are true."
+ );
+
+ is(
+ typeof t_options.e,
+ "object",
+ "an option that can accept multiple values is defined."
+ );
+
+ is(
+ t_options.e.length,
+ 2,
+ "an option that can accept multiple values can have more than one value."
+ );
+
+ is(
+ t_options.e[1],
+ "two",
+ "an option that can accept multiple values can be accessed as an array."
+ );
+
+ is(
+ typeof t_options._,
+ "object",
+ "the property '_' is defined for unnamed options."
+ );
+
+ is(
+ t_options._[0],
+ "foo",
+ "the property '_' can be accessed as an array."
+ );
+ */
View
26 tools/jsdoc-toolkit/app/frame/Reflection.js
@@ -0,0 +1,26 @@
+/**@constructor*/
+function Reflection(obj) {
+ this.obj = obj;
+}
+
+Reflection.prototype.getConstructorName = function() {
+ if (this.obj.constructor.name) return this.obj.constructor.name;
+ var src = this.obj.constructor.toSource();
+ var name = src.substring(name.indexOf("function")+8, src.indexOf('(')).replace(/ /g,'');
+ return name;
+}
+
+Reflection.prototype.getMethod = function(name) {
+ for (var p in this.obj) {
+ if (p == name && typeof(this.obj[p]) == "function") return this.obj[p];
+ }
+ return null;
+}
+
+Reflection.prototype.getParameterNames = function() {
+ var src = this.obj.toSource();
+ src = src.substring(
+ src.indexOf("(", 8)+1, src.indexOf(")")
+ );
+ return src.split(/, ?/);
+}
View
93 tools/jsdoc-toolkit/app/frame/String.js
@@ -0,0 +1,93 @@
+/**
+ @name String
+ @class Additions to the core string object.
+*/
+
+/** @author Steven Levithan, released as public domain. */
+String.prototype.trim = function() {
+ var str = this.replace(/^\s+/, '');
+ for (var i = str.length - 1; i >= 0; i--) {
+ if (/\S/.test(str.charAt(i))) {
+ str = str.substring(0, i + 1);
+ break;
+ }
+ }
+ return str;
+}
+/*t:
+ plan(6, "Testing String.prototype.trim.");
+
+ var s = " a bc ".trim();
+ is(s, "a bc", "multiple spaces front and back are trimmed.");
+
+ s = "a bc\n\n".trim();
+ is(s, "a bc", "newline