From 012255d6220ba05e2f810a0014befa11ba454603 Mon Sep 17 00:00:00 2001 From: thatcher Date: Wed, 25 Jan 2012 14:14:02 -0500 Subject: [PATCH] added jsdoc some files to project, added 'doc' task to build, started to annotate code with docs --- bin/jsdoc/frame.js | 33 + bin/jsdoc/frame/Chain.js | 102 +++ bin/jsdoc/frame/Dumper.js | 144 ++++ bin/jsdoc/frame/Hash.js | 84 +++ bin/jsdoc/frame/Link.js | 173 +++++ bin/jsdoc/frame/Namespace.js | 10 + bin/jsdoc/frame/Opt.js | 134 ++++ bin/jsdoc/frame/Reflection.js | 26 + bin/jsdoc/frame/String.js | 93 +++ bin/jsdoc/frame/Testrun.js | 129 ++++ bin/jsdoc/handlers/FOODOC.js | 26 + bin/jsdoc/handlers/XMLDOC.js | 26 + bin/jsdoc/handlers/XMLDOC/DomReader.js | 159 ++++ bin/jsdoc/handlers/XMLDOC/XMLDoc.js | 16 + bin/jsdoc/handlers/XMLDOC/XMLParse.js | 292 +++++++ bin/jsdoc/jsrun.jar | Bin 0 -> 1303 bytes bin/jsdoc/lib/JSDOC.js | 106 +++ bin/jsdoc/lib/JSDOC/DocComment.js | 204 +++++ bin/jsdoc/lib/JSDOC/DocTag.js | 294 ++++++++ bin/jsdoc/lib/JSDOC/JsDoc.js | 140 ++++ bin/jsdoc/lib/JSDOC/JsPlate.js | 109 +++ bin/jsdoc/lib/JSDOC/Lang.js | 144 ++++ bin/jsdoc/lib/JSDOC/Parser.js | 146 ++++ bin/jsdoc/lib/JSDOC/PluginManager.js | 33 + bin/jsdoc/lib/JSDOC/Symbol.js | 644 ++++++++++++++++ bin/jsdoc/lib/JSDOC/SymbolSet.js | 243 ++++++ bin/jsdoc/lib/JSDOC/TextStream.js | 41 + bin/jsdoc/lib/JSDOC/Token.js | 18 + bin/jsdoc/lib/JSDOC/TokenReader.js | 332 ++++++++ bin/jsdoc/lib/JSDOC/TokenStream.js | 133 ++++ bin/jsdoc/lib/JSDOC/Util.js | 32 + bin/jsdoc/lib/JSDOC/Walker.js | 507 +++++++++++++ bin/jsdoc/main.js | 111 +++ bin/jsdoc/plugins/commentSrcJson.js | 20 + bin/jsdoc/plugins/frameworkPrototype.js | 16 + bin/jsdoc/plugins/functionCall.js | 10 + bin/jsdoc/plugins/publishSrcHilite.js | 62 ++ bin/jsdoc/plugins/symbolLink.js | 10 + bin/jsdoc/plugins/tagParamConfig.js | 31 + bin/jsdoc/plugins/tagSynonyms.js | 43 ++ bin/jsdoc/run.js | 348 +++++++++ bin/jsdoc/t/TestDoc.js | 144 ++++ bin/jsdoc/t/runner.js | 13 + bin/jsdoc/templates/README.txt | 5 + bin/jsdoc/templates/allclasses.tmpl | 20 + bin/jsdoc/templates/allfiles.tmpl | 41 + bin/jsdoc/templates/class.tmpl | 712 ++++++++++++++++++ bin/jsdoc/templates/css/all.css | 358 +++++++++ .../css/fonts/mplus-1m-bold-webfont.eot | Bin 0 -> 18590 bytes .../css/fonts/mplus-1m-bold-webfont.svg | 134 ++++ .../css/fonts/mplus-1m-bold-webfont.ttf | Bin 0 -> 18428 bytes .../css/fonts/mplus-1m-bold-webfont.woff | Bin 0 -> 11772 bytes .../css/fonts/mplus-1m-regular-webfont.eot | Bin 0 -> 19518 bytes .../css/fonts/mplus-1m-regular-webfont.svg | 134 ++++ .../css/fonts/mplus-1m-regular-webfont.ttf | Bin 0 -> 19344 bytes .../css/fonts/mplus-1m-regular-webfont.woff | Bin 0 -> 12304 bytes bin/jsdoc/templates/css/handheld.css | 217 ++++++ bin/jsdoc/templates/css/screen.css | 297 ++++++++ bin/jsdoc/templates/javascript/all.js | 326 ++++++++ bin/jsdoc/templates/javascript/html5.js | 6 + bin/jsdoc/templates/license.txt | 21 + bin/jsdoc/templates/publish.js | 236 ++++++ bin/jsdoc/templates/subtemplates/foot.tmpl | 6 + bin/jsdoc/templates/subtemplates/head.tmpl | 22 + bin/jsdoc/templates/subtemplates/menu.tmpl | 43 ++ bin/jsdoc/test.js | 342 +++++++++ bin/jsdoc/test/addon.js | 24 + bin/jsdoc/test/anon_inner.js | 14 + bin/jsdoc/test/augments.js | 31 + bin/jsdoc/test/augments2.js | 26 + bin/jsdoc/test/borrows.js | 46 ++ bin/jsdoc/test/borrows2.js | 23 + bin/jsdoc/test/config.js | 22 + bin/jsdoc/test/constructs.js | 18 + bin/jsdoc/test/encoding.js | 10 + bin/jsdoc/test/encoding_other.js | 12 + bin/jsdoc/test/event.js | 54 ++ bin/jsdoc/test/exports.js | 14 + bin/jsdoc/test/functions_anon.js | 39 + bin/jsdoc/test/functions_nested.js | 33 + bin/jsdoc/test/global.js | 13 + bin/jsdoc/test/globals.js | 25 + bin/jsdoc/test/ignore.js | 10 + bin/jsdoc/test/inner.js | 16 + bin/jsdoc/test/jsdoc_test.js | 477 ++++++++++++ bin/jsdoc/test/lend.js | 33 + bin/jsdoc/test/memberof.js | 19 + bin/jsdoc/test/memberof2.js | 38 + bin/jsdoc/test/memberof3.js | 33 + bin/jsdoc/test/memberof_constructor.js | 17 + bin/jsdoc/test/module.js | 17 + bin/jsdoc/test/multi_methods.js | 25 + bin/jsdoc/test/name.js | 19 + bin/jsdoc/test/namespace_nested.js | 23 + bin/jsdoc/test/nocode.js | 13 + bin/jsdoc/test/oblit_anon.js | 20 + bin/jsdoc/test/overview.js | 20 + bin/jsdoc/test/param_inline.js | 37 + bin/jsdoc/test/params_optional.js | 8 + bin/jsdoc/test/prototype.js | 17 + bin/jsdoc/test/prototype_nested.js | 9 + bin/jsdoc/test/prototype_oblit.js | 13 + bin/jsdoc/test/prototype_oblit_constructor.js | 24 + bin/jsdoc/test/public.js | 10 + bin/jsdoc/test/scripts/code.js | 5 + bin/jsdoc/test/scripts/notcode.txt | 5 + bin/jsdoc/test/shared.js | 42 ++ bin/jsdoc/test/shared2.js | 2 + bin/jsdoc/test/shortcuts.js | 22 + bin/jsdoc/test/static_this.js | 13 + bin/jsdoc/test/synonyms.js | 31 + bin/jsdoc/test/tosource.js | 23 + bin/jsdoc/test/variable_redefine.js | 14 + bin/run-jsdoc.js | 348 +++++++++ build.properties | 10 +- build.xml | 16 +- openseadragon.js | 703 +++++++++++------ src/button.js | 17 + src/buttongroup.js | 2 +- src/control.js | 44 +- src/displayrectangle.js | 3 + src/drawer.js | 3 + src/dzitilesource.js | 7 +- src/eventhandler.js | 106 +-- src/mousetracker.js | 19 +- src/openseadragon.js | 277 ++++++- src/overlay.js | 9 + src/point.js | 3 + src/profiler.js | 3 + src/rectangle.js | 3 + src/spring.js | 3 + src/tile.js | 7 +- src/tilesource.js | 4 + src/viewer.js | 9 +- src/viewport.js | 104 +-- 135 files changed, 11078 insertions(+), 382 deletions(-) create mode 100644 bin/jsdoc/frame.js create mode 100644 bin/jsdoc/frame/Chain.js create mode 100644 bin/jsdoc/frame/Dumper.js create mode 100644 bin/jsdoc/frame/Hash.js create mode 100644 bin/jsdoc/frame/Link.js create mode 100644 bin/jsdoc/frame/Namespace.js create mode 100644 bin/jsdoc/frame/Opt.js create mode 100644 bin/jsdoc/frame/Reflection.js create mode 100644 bin/jsdoc/frame/String.js create mode 100644 bin/jsdoc/frame/Testrun.js create mode 100644 bin/jsdoc/handlers/FOODOC.js create mode 100755 bin/jsdoc/handlers/XMLDOC.js create mode 100755 bin/jsdoc/handlers/XMLDOC/DomReader.js create mode 100755 bin/jsdoc/handlers/XMLDOC/XMLDoc.js create mode 100755 bin/jsdoc/handlers/XMLDOC/XMLParse.js create mode 100644 bin/jsdoc/jsrun.jar create mode 100644 bin/jsdoc/lib/JSDOC.js create mode 100644 bin/jsdoc/lib/JSDOC/DocComment.js create mode 100644 bin/jsdoc/lib/JSDOC/DocTag.js create mode 100644 bin/jsdoc/lib/JSDOC/JsDoc.js create mode 100644 bin/jsdoc/lib/JSDOC/JsPlate.js create mode 100644 bin/jsdoc/lib/JSDOC/Lang.js create mode 100644 bin/jsdoc/lib/JSDOC/Parser.js create mode 100644 bin/jsdoc/lib/JSDOC/PluginManager.js create mode 100644 bin/jsdoc/lib/JSDOC/Symbol.js create mode 100644 bin/jsdoc/lib/JSDOC/SymbolSet.js create mode 100644 bin/jsdoc/lib/JSDOC/TextStream.js create mode 100644 bin/jsdoc/lib/JSDOC/Token.js create mode 100644 bin/jsdoc/lib/JSDOC/TokenReader.js create mode 100644 bin/jsdoc/lib/JSDOC/TokenStream.js create mode 100644 bin/jsdoc/lib/JSDOC/Util.js create mode 100644 bin/jsdoc/lib/JSDOC/Walker.js create mode 100644 bin/jsdoc/main.js create mode 100644 bin/jsdoc/plugins/commentSrcJson.js create mode 100644 bin/jsdoc/plugins/frameworkPrototype.js create mode 100644 bin/jsdoc/plugins/functionCall.js create mode 100644 bin/jsdoc/plugins/publishSrcHilite.js create mode 100644 bin/jsdoc/plugins/symbolLink.js create mode 100644 bin/jsdoc/plugins/tagParamConfig.js create mode 100644 bin/jsdoc/plugins/tagSynonyms.js create mode 100644 bin/jsdoc/run.js create mode 100644 bin/jsdoc/t/TestDoc.js create mode 100644 bin/jsdoc/t/runner.js create mode 100755 bin/jsdoc/templates/README.txt create mode 100755 bin/jsdoc/templates/allclasses.tmpl create mode 100755 bin/jsdoc/templates/allfiles.tmpl create mode 100755 bin/jsdoc/templates/class.tmpl create mode 100755 bin/jsdoc/templates/css/all.css create mode 100755 bin/jsdoc/templates/css/fonts/mplus-1m-bold-webfont.eot create mode 100755 bin/jsdoc/templates/css/fonts/mplus-1m-bold-webfont.svg create mode 100755 bin/jsdoc/templates/css/fonts/mplus-1m-bold-webfont.ttf create mode 100755 bin/jsdoc/templates/css/fonts/mplus-1m-bold-webfont.woff create mode 100755 bin/jsdoc/templates/css/fonts/mplus-1m-regular-webfont.eot create mode 100755 bin/jsdoc/templates/css/fonts/mplus-1m-regular-webfont.svg create mode 100755 bin/jsdoc/templates/css/fonts/mplus-1m-regular-webfont.ttf create mode 100755 bin/jsdoc/templates/css/fonts/mplus-1m-regular-webfont.woff create mode 100755 bin/jsdoc/templates/css/handheld.css create mode 100755 bin/jsdoc/templates/css/screen.css create mode 100755 bin/jsdoc/templates/javascript/all.js create mode 100755 bin/jsdoc/templates/javascript/html5.js create mode 100755 bin/jsdoc/templates/license.txt create mode 100755 bin/jsdoc/templates/publish.js create mode 100755 bin/jsdoc/templates/subtemplates/foot.tmpl create mode 100755 bin/jsdoc/templates/subtemplates/head.tmpl create mode 100755 bin/jsdoc/templates/subtemplates/menu.tmpl create mode 100644 bin/jsdoc/test.js create mode 100644 bin/jsdoc/test/addon.js create mode 100644 bin/jsdoc/test/anon_inner.js create mode 100644 bin/jsdoc/test/augments.js create mode 100644 bin/jsdoc/test/augments2.js create mode 100644 bin/jsdoc/test/borrows.js create mode 100644 bin/jsdoc/test/borrows2.js create mode 100644 bin/jsdoc/test/config.js create mode 100644 bin/jsdoc/test/constructs.js create mode 100644 bin/jsdoc/test/encoding.js create mode 100644 bin/jsdoc/test/encoding_other.js create mode 100644 bin/jsdoc/test/event.js create mode 100644 bin/jsdoc/test/exports.js create mode 100644 bin/jsdoc/test/functions_anon.js create mode 100644 bin/jsdoc/test/functions_nested.js create mode 100644 bin/jsdoc/test/global.js create mode 100644 bin/jsdoc/test/globals.js create mode 100644 bin/jsdoc/test/ignore.js create mode 100644 bin/jsdoc/test/inner.js create mode 100644 bin/jsdoc/test/jsdoc_test.js create mode 100644 bin/jsdoc/test/lend.js create mode 100644 bin/jsdoc/test/memberof.js create mode 100644 bin/jsdoc/test/memberof2.js create mode 100644 bin/jsdoc/test/memberof3.js create mode 100644 bin/jsdoc/test/memberof_constructor.js create mode 100644 bin/jsdoc/test/module.js create mode 100644 bin/jsdoc/test/multi_methods.js create mode 100644 bin/jsdoc/test/name.js create mode 100644 bin/jsdoc/test/namespace_nested.js create mode 100644 bin/jsdoc/test/nocode.js create mode 100644 bin/jsdoc/test/oblit_anon.js create mode 100644 bin/jsdoc/test/overview.js create mode 100644 bin/jsdoc/test/param_inline.js create mode 100644 bin/jsdoc/test/params_optional.js create mode 100644 bin/jsdoc/test/prototype.js create mode 100644 bin/jsdoc/test/prototype_nested.js create mode 100644 bin/jsdoc/test/prototype_oblit.js create mode 100644 bin/jsdoc/test/prototype_oblit_constructor.js create mode 100644 bin/jsdoc/test/public.js create mode 100644 bin/jsdoc/test/scripts/code.js create mode 100644 bin/jsdoc/test/scripts/notcode.txt create mode 100644 bin/jsdoc/test/shared.js create mode 100644 bin/jsdoc/test/shared2.js create mode 100644 bin/jsdoc/test/shortcuts.js create mode 100644 bin/jsdoc/test/static_this.js create mode 100644 bin/jsdoc/test/synonyms.js create mode 100644 bin/jsdoc/test/tosource.js create mode 100644 bin/jsdoc/test/variable_redefine.js create mode 100644 bin/run-jsdoc.js diff --git a/bin/jsdoc/frame.js b/bin/jsdoc/frame.js new file mode 100644 index 00000000..1beb4055 --- /dev/null +++ b/bin/jsdoc/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"); +} diff --git a/bin/jsdoc/frame/Chain.js b/bin/jsdoc/frame/Chain.js new file mode 100644 index 00000000..506469d1 --- /dev/null +++ b/bin/jsdoc/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"); +} + +*/ \ No newline at end of file diff --git a/bin/jsdoc/frame/Dumper.js b/bin/jsdoc/frame/Dumper.js new file mode 100644 index 00000000..d8b007b1 --- /dev/null +++ b/bin/jsdoc/frame/Dumper.js @@ -0,0 +1,144 @@ +/** + * @class +
+This is a lightly modified version of Kevin Jones' JavaScript
+library Data.Dump. To download the original visit:
+    http://openjsan.org/doc/k/ke/kevinj/Data/Dump/
+
+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
+
+ * @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 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" +}; \ No newline at end of file diff --git a/bin/jsdoc/frame/Hash.js b/bin/jsdoc/frame/Hash.js new file mode 100644 index 00000000..62cfad64 --- /dev/null +++ b/bin/jsdoc/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]}; +} \ No newline at end of file diff --git a/bin/jsdoc/frame/Link.js b/bin/jsdoc/frame/Link.js new file mode 100644 index 00000000..1e6241bf --- /dev/null +++ b/bin/jsdoc/frame/Link.js @@ -0,0 +1,173 @@ +/** 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 = "", + ns = ""; + + if (symbol.isStatic) linker = "."; + else if (symbol.isInner) linker = "-"; + + if (symbol.isEvent && !/^event:/.test(symbol.name)) { + ns = "event:"; + } + return Link.hashPrefix+linker+ns+symbol.name; +} + +Link.getSymbol= function(alias) { + var symbol= Link.symbolSet.getSymbol(alias); + + if (symbol) + return symbol; + + if ('#'!==alias.charAt(0) || !Link.currentSymbol) + return null; + + // resolve relative name + var container= Link.currentSymbol; + + while (container) + { + symbol= Link.symbolSet.getSymbol(container.alias + alias); + if (symbol) + return symbol; + + // No superclass + if (!container.augments.length) + return null; + + container= Link.symbolSet.getSymbol(container.augments[0].desc); + } + + return null; +} + +/** Create a link to another symbol. */ +Link.prototype._makeSymbolLink = function(alias) { + var linkBase = Link.base+publish.conf.symbolsDir; + var linkTo = Link.getSymbol(alias); + var linkPath; + var target = (this.targetName)? " target=\""+this.targetName+"\"" : ""; + + // if there is no symbol by that name just return the name unaltered + 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 + linkPath= (Link.filemap) ? Link.filemap[linkTo.memberOf] : + escape(linkTo.memberOf) || "_global_"; + linkPath += publish.conf.ext + "#" + Link.symbolNameToLinkName(linkTo); + } + else { + linkPath = (Link.filemap)? Link.filemap[linkTo.alias] : 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, linkInner: (this.innerName? "#"+this.innerName : "")}; + + if (typeof JSDOC.PluginManager != "undefined") { + JSDOC.PluginManager.run("onSymbolLink", link); + } + + return ""+link.linkText+""; +} + +/** 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 ""+this.text+""; +} + +/** 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 ""+this.text+""; +} \ No newline at end of file diff --git a/bin/jsdoc/frame/Namespace.js b/bin/jsdoc/frame/Namespace.js new file mode 100644 index 00000000..fa1e41d1 --- /dev/null +++ b/bin/jsdoc/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(); +} \ No newline at end of file diff --git a/bin/jsdoc/frame/Opt.js b/bin/jsdoc/frame/Opt.js new file mode 100644 index 00000000..352f1590 --- /dev/null +++ b/bin/jsdoc/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." + ); + */ \ No newline at end of file diff --git a/bin/jsdoc/frame/Reflection.js b/bin/jsdoc/frame/Reflection.js new file mode 100644 index 00000000..0968f1c6 --- /dev/null +++ b/bin/jsdoc/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(/, ?/); +} diff --git a/bin/jsdoc/frame/String.js b/bin/jsdoc/frame/String.js new file mode 100644 index 00000000..c183c27d --- /dev/null +++ b/bin/jsdoc/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", "newlines only in back are trimmed."); + + s = "\ta bc".trim(); + is(s, "a bc", "tabs only in front are trimmed."); + + s = "\n \t".trim(); + is(s, "", "an all-space string is trimmed to empty."); + + s = "a b\nc".trim(); + is(s, "a b\nc", "a string with no spaces in front or back is trimmed to itself."); + + s = "".trim(); + is(s, "", "an empty string is trimmed to empty."); + +*/ + +String.prototype.balance = function(open, close) { + var i = 0; + while (this.charAt(i) != open) { + if (i == this.length) return [-1, -1]; + i++; + } + + var j = i+1; + var balance = 1; + while (j < this.length) { + if (this.charAt(j) == open) balance++; + if (this.charAt(j) == close) balance--; + if (balance == 0) break; + j++; + if (j == this.length) return [-1, -1]; + } + + return [i, j]; +} +/*t: + plan(16, "Testing String.prototype.balance."); + + var s = "{abc}".balance("{","}"); + is(s[0], 0, "opener in first is found."); + is(s[1], 4, "closer in last is found."); + + s = "ab{c}de".balance("{","}"); + is(s[0], 2, "opener in middle is found."); + is(s[1], 4, "closer in middle is found."); + + s = "a{b{c}de}f".balance("{","}"); + is(s[0], 1, "nested opener is found."); + is(s[1], 8, "nested closer is found."); + + s = "{}".balance("{","}"); + is(s[0], 0, "opener with no content is found."); + is(s[1], 1, "closer with no content is found."); + + s = "".balance("{","}"); + is(s[0], -1, "empty string opener is -1."); + is(s[1], -1, "empty string closer is -1."); + + s = "{abc".balance("{","}"); + is(s[0], -1, "opener with no closer returns -1."); + is(s[1], -1, "no closer returns -1."); + + s = "abc".balance("{","}"); + is(s[0], -1, "no opener or closer returns -1 for opener."); + is(s[1], -1, "no opener or closer returns -1 for closer."); + + s = "aX11/MIT License + * (See the accompanying README file for full details.) + */ + +/** + Yet another unit testing tool for JavaScript. + @author Michael Mathews micmath@gmail.com + @param {object} testCases Properties are testcase names, values are functions to execute as tests. +*/ +function testrun(testCases) { + var ran = 0; + for (t in testCases) { + var result = testCases[t](); + ran++; + } + + return testrun.reportOut+"-------------------------------\n"+((testrun.fails>0)? ":( Failed "+testrun.fails+"/" : ":) Passed all ")+testrun.count+" test"+((testrun.count == 1)? "":"s")+".\n"; +} + + +testrun.count = 0; +testrun.current = null; +testrun.passes = 0; +testrun.fails = 0; +testrun.reportOut = ""; + +/** @private */ +testrun.report = function(text) { + testrun.reportOut += text+"\n"; +} + +/** + Check if test evaluates to true. + @param {string} test To be evaluated. + @param {string} message Optional. To be displayed in the report. + @return {boolean} True if the string test evaluates to true. +*/ +ok = function(test, message) { + testrun.count++; + + var result; + try { + result = eval(test); + + if (result) { + testrun.passes++; + testrun.report(" OK "+testrun.count+" - "+((message != null)? message : "")); + } + else { + testrun.fails++; + testrun.report("NOT OK "+testrun.count+" - "+((message != null)? message : "")); + } + } + catch(e) { + testrun.fails++ + testrun.report("NOT OK "+testrun.count+" - "+((message != null)? message : "")); + + } +} + +/** + Check if test is same as expected. + @param {string} test To be evaluated. + @param {string} expected + @param {string} message Optional. To be displayed in the report. + @return {boolean} True if (test == expected). Note that the comparison is not a strict equality check. +*/ +is = function(test, expected, message) { + testrun.count++; + + var result; + try { + result = eval(test); + + if (result == expected) { + testrun.passes++ + testrun.report(" OK "+testrun.count+" - "+((message != null)? message : "")); + } + else { + testrun.fails++ + testrun.report("NOT OK "+testrun.count+" - "+((message != null)? message : "")); + testrun.report("expected: "+expected); + testrun.report(" got: "+result); + } + } + catch(e) { + testrun.fails++ + testrun.report("NOT OK "+testrun.count+" - "+((message != null)? message : "")); + testrun.report("expected: "+expected); + testrun.report(" got: "+result);} +} + +/** + Check if test matches pattern. + @param {string} test To be evaluated. + @param {string} pattern Used to create a RegExp. + @param {string} message Optional. To be displayed in the report. + @return {boolean} True if test matches pattern. +*/ +like = function(test, pattern, message) { + testrun.count++; + + var result; + try { + result = eval(test); + var rgx = new RegExp(pattern); + + if (rgx.test(result)) { + testrun.passes++ + testrun.report(" OK "+testrun.count+" - "+((message != null)? message : "")); + } + else { + testrun.fails++ + testrun.report("NOT OK "+testrun.count+" - "+((message != null)? message : "")); + testrun.report(" this: "+result); + testrun.report("is not like: "+pattern); + } + } + catch(e) { + testrun.fails++ + testrun.report("NOT OK "+testrun.count+" - "+((message != null)? message : "")); + } +} \ No newline at end of file diff --git a/bin/jsdoc/handlers/FOODOC.js b/bin/jsdoc/handlers/FOODOC.js new file mode 100644 index 00000000..b208f55b --- /dev/null +++ b/bin/jsdoc/handlers/FOODOC.js @@ -0,0 +1,26 @@ +/** + This is the main container for the FOODOC handler. + @namespace +*/ +FOODOC = { +}; + +/** The current version string of this application. */ +FOODOC.VERSION = "1.0"; + +FOODOC.handle = function(srcFile, src) { + LOG.inform("Handling file '" + srcFile + "'"); + + return [ + new JSDOC.Symbol( + "foo", + [], + "VIRTUAL", + new JSDOC.DocComment("/** This is a foo. */") + ) + ]; +}; + +FOODOC.publish = function(symbolgroup) { + LOG.inform("Publishing symbolgroup."); +}; diff --git a/bin/jsdoc/handlers/XMLDOC.js b/bin/jsdoc/handlers/XMLDOC.js new file mode 100755 index 00000000..40f87b35 --- /dev/null +++ b/bin/jsdoc/handlers/XMLDOC.js @@ -0,0 +1,26 @@ +/** + * This is the main container for the XMLDOC handler. + * @namespace + * @author Brett Fattori (bfattori@fry.com) + * @version $Revision: 498 $ + */ +XMLDOC = { + +}; + +/** The current version string of this application. */ +XMLDOC.VERSION = "1.0"; + +/** Include the library necessary to handle XML files */ +IO.includeDir("handlers/XMLDOC/"); + +/** + * @type Symbol[] + */ +XMLDOC.handle = function(srcFile, src) { + +}; + +XMLDOC.publish = function(symbolgroup) { + +} \ No newline at end of file diff --git a/bin/jsdoc/handlers/XMLDOC/DomReader.js b/bin/jsdoc/handlers/XMLDOC/DomReader.js new file mode 100755 index 00000000..240563da --- /dev/null +++ b/bin/jsdoc/handlers/XMLDOC/DomReader.js @@ -0,0 +1,159 @@ +LOG.inform("XMLDOC.DomReader loaded"); + +XMLDOC.DomReader = function(root) { + + this.dom = root; + + /** + * The current node the reader is on + */ + this.node = root; + + /** + * Get the current node the reader is on + * @type XMLDOC.Parser.node + */ + XMLDOC.DomReader.prototype.getNode = function() { + return this.node; + }; + + /** + * Set the node the reader should be positioned on. + * @param node {XMLDOC.Parser.node} + */ + XMLDOC.DomReader.prototype.setNode = function(node) { + this.node = node; + }; + + /** + * A helper method to make sure the current node will + * never return null, unless null is passed as the root. + * @param step {String} An expression to evaluate - should return a node or null + */ + XMLDOC.DomReader.prototype.navigate = function(step) { + var n; + if ((n = step) != null) + { + this.node = n; + return this.node; + } + return null; + }; + + /** + * Get the root node of the current node's document. + */ + XMLDOC.DomReader.prototype.root = function() { + this.navigate(this.dom); + }; + + /** + * Get the parent of the current node. + */ + XMLDOC.DomReader.prototype.parent = function() { + return this.navigate(this.node.parentNode()); + }; + + /** + * Get the first child of the current node. + */ + XMLDOC.DomReader.prototype.firstChild = function() { + return this.navigate(this.node.firstChild()); + }; + + /** + * Get the last child of the current node. + */ + XMLDOC.DomReader.prototype.lastChild = function() { + return this.navigate(this.node.lastChild()); + }; + + /** + * Get the next sibling of the current node. + */ + XMLDOC.DomReader.prototype.nextSibling = function() { + return this.navigate(this.node.nextSibling()); + }; + + /** + * Get the previous sibling of the current node. + */ + XMLDOC.DomReader.prototype.prevSibling = function() { + return this.navigate(this.node.prevSibling()); + }; + + //=============================================================================================== + // Support methods + + /** + * Walk the tree starting with the current node, calling the plug-in for + * each node visited. Each time the plug-in is called, the DomReader + * is passed as the only parameter. Use the {@link XMLDOC.DomReader#getNode} method + * to access the current node. This method uses a depth first traversal pattern. + * + * @param srcFile {String} The source file being evaluated + */ + XMLDOC.DomReader.prototype.getSymbols = function(srcFile) + { + XMLDOC.DomReader.symbols = []; + XMLDOC.DomReader.currentFile = srcFile; + JSDOC.Symbol.srcFile = (srcFile || ""); + + if (defined(JSDOC.PluginManager)) { + JSDOC.PluginManager.run("onDomGetSymbols", this); + } + + return XMLDOC.DomReader.symbols; + }; + + /** + * Find the node with the given name using a depth first traversal. + * Does not modify the DomReader's current node. + * + * @param name {String} The name of the node to find + * @return the node that was found, or null if not found + */ + XMLDOC.DomReader.prototype.findNode = function(name) + { + var findNode = null; + + // Start at the current node and move into the subtree, + // looking for the node with the given name + function deeper(node, find) + { + var look = null; + + if (node) { + if (node.name == find) + { + return node; + } + + if (node.firstChild()) + { + look = deeper(node.firstChild(), find); + } + + if (!look && node.nextSibling()) + { + look = deeper(node.nextSibling(), find); + } + } + + return look; + } + + return deeper(this.getNode().firstChild(), name); + }; + + /** + * Find the next node with the given name using a depth first traversal. + * + * @param name {String} The name of the node to find + */ + XMLDOC.DomReader.prototype.findPreviousNode = function(name) + { + }; + +}; + diff --git a/bin/jsdoc/handlers/XMLDOC/XMLDoc.js b/bin/jsdoc/handlers/XMLDOC/XMLDoc.js new file mode 100755 index 00000000..e9b3e3ce --- /dev/null +++ b/bin/jsdoc/handlers/XMLDOC/XMLDoc.js @@ -0,0 +1,16 @@ +LOG.inform("XMLDOC.symbolize loaded"); + +/** + * Convert the source file to a set of symbols + */ +XMLDOC.symbolize = function(srcFile, src) { + + LOG.inform("Symbolizing file '" + srcFile + "'"); + + // XML files already have a defined structure, so we don't need to + // do anything but parse them. The DOM reader can create a symbol + // table from the parsed XML. + var dr = new XMLDOC.DomReader(XMLDOC.Parser.parse(src)); + return dr.getSymbols(srcFile); + +}; diff --git a/bin/jsdoc/handlers/XMLDOC/XMLParse.js b/bin/jsdoc/handlers/XMLDOC/XMLParse.js new file mode 100755 index 00000000..78e8f455 --- /dev/null +++ b/bin/jsdoc/handlers/XMLDOC/XMLParse.js @@ -0,0 +1,292 @@ +LOG.inform("XMLDOC.Parser loaded"); + +/** + * XML Parser object. Returns an {@link #XMLDOC.Parser.node} which is + * the root element of the parsed document. + *

+ * By default, this parser will only handle well formed XML. To + * allow the parser to handle HTML, set the XMLDOC.Parser.strictMode + * variable to false before calling XMLDOC.Parser.parse(). + *

+ * Note: If you pass poorly formed XML, it will cause the parser to throw + * an exception. + * + * @author Brett Fattori (bfattori@fry.com) + * @author $Author: micmath $ + * @version $Revision: 497 $ + */ +XMLDOC.Parser = {}; + +/** + * Strict mode setting. Setting this to false allows HTML-style source to + * be parsed. Normally, well formed XML has defined end tags, or empty tags + * are properly formed. Default: true + * @type Boolean + */ +XMLDOC.Parser.strictMode = true; + +/** + * A node in an XML Document. Node types are ROOT, ELEMENT, COMMENT, PI, and TEXT. + * @param parent {XMLDOC.Parser.node} The parent node + * @param name {String} The node name + * @param type {String} One of the types + */ +XMLDOC.Parser.node = function(parent, name, type) +{ + this.name = name; + this.type = type || "ELEMENT"; + this.parent = parent; + this.charData = ""; + this.attrs = {}; + this.nodes = []; + this.cPtr = 0; + + XMLDOC.Parser.node.prototype.getAttributeNames = function() { + var a = []; + for (var o in this.attrs) + { + a.push(o); + } + + return a; + }; + + XMLDOC.Parser.node.prototype.getAttribute = function(attr) { + return this.attrs[attr]; + }; + + XMLDOC.Parser.node.prototype.setAttribute = function(attr, val) { + this.attrs[attr] = val; + }; + + XMLDOC.Parser.node.prototype.getChild = function(idx) { + return this.nodes[idx]; + }; + + XMLDOC.Parser.node.prototype.parentNode = function() { + return this.parent; + }; + + XMLDOC.Parser.node.prototype.firstChild = function() { + return this.nodes[0]; + }; + + XMLDOC.Parser.node.prototype.lastChild = function() { + return this.nodes[this.nodes.length - 1]; + }; + + XMLDOC.Parser.node.prototype.nextSibling = function() { + var p = this.parent; + if (p && (p.nodes.indexOf(this) + 1 != p.nodes.length)) + { + return p.getChild(p.nodes.indexOf(this) + 1); + } + return null; + }; + + XMLDOC.Parser.node.prototype.prevSibling = function() { + var p = this.parent; + if (p && (p.nodes.indexOf(this) - 1 >= 0)) + { + return p.getChild(p.nodes.indexOf(this) - 1); + } + return null; + }; +}; + +/** + * Parse an XML Document from the specified source. The XML should be + * well formed, unless strict mode is disabled, then the parser will + * handle HTML-style XML documents. + * @param src {String} The source to parse + */ +XMLDOC.Parser.parse = function(src) +{ + var A = []; + + // Normailize whitespace + A = src.split("\r\n"); + src = A.join("\n"); + A = src.split("\r"); + src = A.join("\n"); + + // Remove XML and DOCTYPE specifier + src.replace(/<\?XML .*\?>/i, ""); + src.replace(//i, ""); + + // The document is the root node and cannot be modified or removed + var doc = new XMLDOC.Parser.node(null, "ROOT", "DOCUMENT"); + + // Let's break it down + XMLDOC.Parser.eat(doc, src); + + return doc; +}; + +/** + * The XML fragment processing routine. This method is private and should not be called + * directly. + * @param parentNode {XMLDOC.Parser.node} The node which is the parent of this fragment + * @param src {String} The source within the fragment to process + * @private + */ +XMLDOC.Parser.eat = function(parentNode, src) +{ + // A simple tag def + var reTag = new RegExp("<(!|)(\\?|--|)((.|\\s)*?)\\2>","g"); + + // Special tag types + var reCommentTag = //; + var rePITag = /<\?((.|\s)*?)\?>/; + + // A start tag (with potential empty marker) + var reStartTag = /<(.*?)( +([\w_\-]*)=(\"|')(.*)\4)*(\/)?>/; + + // An empty HTML style tag (not proper XML, but we'll accept it so we can process HTML) + var reHTMLEmptyTag = /<(.*?)( +([\w_\-]*)=(\"|')(.*)\4)*>/; + + // Fully enclosing tag with nested tags + var reEnclosingTag = /<(.*?)( +([\w_\-]*)=(\"|')(.*?)\4)*>((.|\s)*?)<\/\1>/; + + // Breaks down attributes + var reAttributes = new RegExp(" +([\\w_\\-]*)=(\"|')(.*?)\\2","g"); + + // Find us a tag + var tag; + while ((tag = reTag.exec(src)) != null) + { + if (tag.index > 0) + { + // The next tag has some text before it + var text = src.substring(0, tag.index).replace(/^[ \t\n]+((.|\n)*?)[ \t\n]+$/, "$1"); + + if (text.length > 0 && (text != "\n")) + { + var txtnode = new XMLDOC.Parser.node(parentNode, "", "TEXT"); + txtnode.charData = text; + + // Append the new text node + parentNode.nodes.push(txtnode); + } + + // Reset the lastIndex of reTag + reTag.lastIndex -= src.substring(0, tag.index).length; + + // Eat the text + src = src.substring(tag.index); + } + + if (reCommentTag.test(tag[0])) + { + // Is this a comment? + var comment = new XMLDOC.Parser.node(parentNode, "", "COMMENT"); + comment.charData = reCommentTag.exec(tag[0])[1]; + + // Append the comment + parentNode.nodes.push(comment); + + // Move the lastIndex of reTag + reTag.lastIndex -= tag[0].length; + + // Eat the tag + src = src.replace(reCommentTag, ""); + } + else if (rePITag.test(tag[0])) + { + // Is this a processing instruction? + var pi = new XMLDOC.Parser.node(parentNode, "", "PI"); + pi.charData = rePITag.exec(tag[0])[1]; + + // Append the processing instruction + parentNode.nodes.push(pi); + + // Move the lastIndex of reTag + reTag.lastIndex -= tag[0].length; + + // Eat the tag + src = src.replace(rePITag, ""); + } + else if (reStartTag.test(tag[0])) + { + // Break it down + var e = reStartTag.exec(tag[0]); + var elem = new XMLDOC.Parser.node(parentNode, e[1], "ELEMENT"); + + // Get attributes from the tag + var a; + while ((a = reAttributes.exec(e[2])) != null ) + { + elem.attrs[a[1]] = a[3]; + } + + // Is this an empty XML-style tag? + if (e[6] == "/") + { + // Append the empty element + parentNode.nodes.push(elem); + + // Move the lastIndex of reTag (include the start tag length) + reTag.lastIndex -= e[0].length; + + // Eat the tag + src = src.replace(reStartTag, ""); + } + else + { + // Check for malformed XML tags + var htmlParsed = false; + var htmlStartTag = reHTMLEmptyTag.exec(src); + + // See if there isn't an end tag within this block + var reHTMLEndTag = new RegExp(""); + var htmlEndTag = reHTMLEndTag.exec(src); + + if (XMLDOC.Parser.strictMode && htmlEndTag == null) + { + // Poorly formed XML fails in strict mode + var err = new Error("Malformed XML passed to XMLDOC.Parser... Error contains malformed 'src'"); + err.src = src; + throw err; + } + else if (htmlEndTag == null) + { + // This is an HTML-style empty tag, store the element for it in non-strict mode + parentNode.nodes.push(elem); + + // Eat the tag + src = src.replace(reHTMLEmptyTag, ""); + htmlParsed = true; + } + + // If we didn't parse HTML-style, it must be an enclosing tag + if (!htmlParsed) + { + var enc = reEnclosingTag.exec(src); + + // Go deeper into the document + XMLDOC.Parser.eat(elem, enc[6]); + + // Append the new element node + parentNode.nodes.push(elem); + + // Eat the tag + src = src.replace(reEnclosingTag, ""); + } + } + + // Reset the lastIndex of reTag + reTag.lastIndex = 0; + } + } + + // No tag was found... append the text if there is any + src = src.replace(/^[ \t\n]+((.|\n)*?)[ \t\n]+$/, "$1"); + if (src.length > 0 && (src != "\n")) + { + var txtNode = new XMLDOC.Parser.node(parentNode, "", "TEXT"); + txtNode.charData = src; + + // Append the new text node + parentNode.nodes.push(txtNode); + } +}; diff --git a/bin/jsdoc/jsrun.jar b/bin/jsdoc/jsrun.jar new file mode 100644 index 0000000000000000000000000000000000000000..49c03f4c6f71d4e24f3897794d40585ffc7c20fe GIT binary patch literal 1303 zcmWIWW@h1H00GaQG7B&RN^ml;F!;KLIO=-(x#|Bq#lR2%Rm#EO0aUu9Ei0@CsB|F^ zivTfPsjs7-r<-eVh@P*T?-@hxLk0q@4{Rs=FDMBz@LYUFG5YP200H)J%U7PkSyDwS zAMD?LSLXhAx%EdM#2<;gtGRK06Z2|s%~v1POOLEmkI2#N-!*BGXUoiaufD{7pQn1V898}Z(mUA<;|J`%+l4kt zM)1#AGT{+B!u24J{&~7cCX+A_uVR5~2Gb*zDit}L4+Q!ZP8Q5=ozh@Z#_}eq|F~U0bJK^dd9UJT zHk^Joi{+s8>eWFnw0C(QuLqbl1w0yyq|auAP$IC9u&?Ao`DzhyJoW_FWf4 zWux}p*ezJtp)7dZ;^9QW!Y*UE=SpUR$^xt2?Y$+J(a&7G?vwNGE-cT}pWdN3X!N9okav52Uy5(f@gVO2G6TOzJ;{T|UJ)e){|- zY=(l>+HQH&XsH$6(3S#>76V|kaD$@-cZ>*ngJa|c7n9+{mX;kGotjmb=H5zbs(;GX zajdREK6Q?u&lAJ$>a=&ZJHMaV8Grx1T?6+V&Irdj?oG$r82CPNOyV(*^x*VJ_C8=% zR`KT34P}n_m&@Kw<*?Aat-x_FD!13k|Eh1(lrI5qSLv@xT9M|yvbry?tm|eQhu~_K zjX#APtL#cIU+>-a?83L!cUwDZWjZX52=@1MB+vO^A-b_o!g0l;d*9E_TvqNMyY^{d z=c?T7wAl+3bOSd}nAN8v4L4oaBcY#n@ciAmE)eZ{(*#w< zomu*P+U3BiYpe4lRvog)JAE-0*oy~{1`t@%s0}3H zT9FD1gykIIvIsqkg0+K9cnKuYGc3Ap^pu3q-2hBmUd8Zq72wUv29jg}!Y@FYmj%QF E0CH&O8UO$Q literal 0 HcmV?d00001 diff --git a/bin/jsdoc/lib/JSDOC.js b/bin/jsdoc/lib/JSDOC.js new file mode 100644 index 00000000..5de7b9ef --- /dev/null +++ b/bin/jsdoc/lib/JSDOC.js @@ -0,0 +1,106 @@ +/** + @overview + @date $Date: 2010-06-13 22:02:44 +0100 (Sun, 13 Jun 2010) $ + @version $Revision: 837 $ + @location $HeadURL: https://jsdoc-toolkit.googlecode.com/svn/tags/jsdoc_toolkit-2.4.0/jsdoc-toolkit/app/lib/JSDOC.js $ + @name JSDOC.js + */ + +/** + This is the main container for the JSDOC application. + @namespace +*/ +JSDOC = { +}; + +/** + @requires Opt + */ +if (typeof arguments == "undefined") arguments = []; +JSDOC.opt = Opt.get( + arguments, + { + a: "allfunctions", + c: "conf", + d: "directory", + "D[]": "define", + e: "encoding", + "E[]": "exclude", + h: "help", + m: "multiple", + n: "nocode", + o: "out", + p: "private", + q: "quiet", + r: "recurse", + S: "securemodules", + s: "suppress", + t: "template", + T: "testmode", + u: "unique", + v: "verbose", + x: "ext" + } +); + +/** The current version string of this application. */ +JSDOC.VERSION = "2.4.0"; + +/** Print out usage information and quit. */ +JSDOC.usage = function() { + print("USAGE: java -jar jsrun.jar app/run.js [OPTIONS] ..."); + print(""); + print("OPTIONS:"); + print(" -a or --allfunctions\n Include all functions, even undocumented ones.\n"); + print(" -c or --conf\n Load a configuration file.\n"); + print(" -d= or --directory=\n Output to this directory (defaults to \"out\").\n"); + print(" -D=\"myVar:My value\" or --define=\"myVar:My value\"\n Multiple. Define a variable, available in JsDoc as JSDOC.opt.D.myVar.\n"); + print(" -e= or --encoding=\n Use this encoding to read and write files.\n"); + print(" -E=\"REGEX\" or --exclude=\"REGEX\"\n Multiple. Exclude files based on the supplied regex.\n"); + print(" -h or --help\n Show this message and exit.\n"); + print(" -m or --multiples\n Don't warn about symbols being documented more than once.\n"); + print(" -n or --nocode\n Ignore all code, only document comments with @name tags.\n"); + print(" -o= or --out=\n Print log messages to a file (defaults to stdout).\n"); + print(" -p or --private\n Include symbols tagged as private, underscored and inner symbols.\n"); + print(" -q or --quiet\n Do not output any messages, not even warnings.\n"); + print(" -r= or --recurse=\n Descend into src directories.\n"); + print(" -s or --suppress\n Suppress source code output.\n"); + print(" -S or --securemodules\n Use Secure Modules mode to parse source code.\n"); + print(" -t= or --template=\n Required. Use this template to format the output.\n"); + print(" -T or --test\n Run all unit tests and exit.\n"); + print(" -u or --unique\n Force file names to be unique, but not based on symbol names.\n"); + print(" -v or --verbose\n Provide verbose feedback about what is happening.\n"); + print(" -x=[,EXT]... or --ext=[,EXT]...\n Scan source files with the given extension/s (defaults to js).\n"); + + quit(); +} + +/*t: + plan(4, "Testing JSDOC namespace."); + + is( + typeof JSDOC, + "object", + "JSDOC.usage is a function." + ); + + is( + typeof JSDOC.VERSION, + "string", + "JSDOC.VERSION is a string." + ); + + is( + typeof JSDOC.usage, + "function", + "JSDOC.usage is a function." + ); + + is( + typeof JSDOC.opt, + "object", + "JSDOC.opt is a object." + ); + */ + +if (this.IO) IO.includeDir("lib/JSDOC/"); diff --git a/bin/jsdoc/lib/JSDOC/DocComment.js b/bin/jsdoc/lib/JSDOC/DocComment.js new file mode 100644 index 00000000..4b21cd71 --- /dev/null +++ b/bin/jsdoc/lib/JSDOC/DocComment.js @@ -0,0 +1,204 @@ +if (typeof JSDOC == "undefined") JSDOC = {}; + +/** + Create a new DocComment. This takes a raw documentation comment, + and wraps it in useful accessors. + @class Represents a documentation comment object. + */ +JSDOC.DocComment = function(/**String*/comment) { + this.init(); + if (typeof comment != "undefined") { + this.parse(comment); + } +} + +JSDOC.DocComment.prototype.init = function() { + this.isUserComment = true; + this.src = ""; + this.meta = ""; + this.tagTexts = []; + this.tags = []; +} + +/** + @requires JSDOC.DocTag + */ +JSDOC.DocComment.prototype.parse = function(/**String*/comment) { + if (comment == "") { + comment = "/** @desc */"; + this.isUserComment = false; + } + + this.src = JSDOC.DocComment.unwrapComment(comment); + + this.meta = ""; + if (this.src.indexOf("#") == 0) { + this.src.match(/#(.+[+-])([\s\S]*)$/); + if (RegExp.$1) this.meta = RegExp.$1; + if (RegExp.$2) this.src = RegExp.$2; + } + + if (typeof JSDOC.PluginManager != "undefined") { + JSDOC.PluginManager.run("onDocCommentSrc", this); + } + + this.fixDesc(); + + this.src = JSDOC.DocComment.shared+"\n"+this.src; + + this.tagTexts = + this.src + .split(/(^|[\r\n])\s*@/) + .filter(function($){return $.match(/\S/)}); + + /** + The tags found in the comment. + @type JSDOC.DocTag[] + */ + this.tags = this.tagTexts.map(function($){return new JSDOC.DocTag($)}); + + if (typeof JSDOC.PluginManager != "undefined") { + JSDOC.PluginManager.run("onDocCommentTags", this); + } +} + +/*t: + plan(5, "testing JSDOC.DocComment"); + requires("../frame/String.js"); + requires("../lib/JSDOC/DocTag.js"); + + var com = new JSDOC.DocComment("/**@foo some\n* comment here*"+"/"); + is(com.tagTexts[0], "foo some\ncomment here", "first tag text is found."); + is(com.tags[0].title, "foo", "the title is found in a comment with one tag."); + + var com = new JSDOC.DocComment("/** @foo first\n* @bar second*"+"/"); + is(com.getTag("bar").length, 1, "getTag() returns one tag by that title."); + + JSDOC.DocComment.shared = "@author John Smith"; + var com = new JSDOC.DocComment("/**@foo some\n* comment here*"+"/"); + is(com.tags[0].title, "author", "shared comment is added."); + is(com.tags[1].title, "foo", "shared comment is added to existing tag."); +*/ + +/** + If no @desc tag is provided, this function will add it. + */ +JSDOC.DocComment.prototype.fixDesc = function() { + if (this.meta && this.meta != "@+") return; + if (/^\s*[^@\s]/.test(this.src)) { + this.src = "@desc "+this.src; + } +} + +/*t: + plan(5, "testing JSDOC.DocComment#fixDesc"); + + var com = new JSDOC.DocComment(); + + com.src = "this is a desc\n@author foo"; + com.fixDesc(); + is(com.src, "@desc this is a desc\n@author foo", "if no @desc tag is provided one is added."); + + com.src = "x"; + com.fixDesc(); + is(com.src, "@desc x", "if no @desc tag is provided one is added to a single character."); + + com.src = "\nx"; + com.fixDesc(); + is(com.src, "@desc \nx", "if no @desc tag is provided one is added to return and character."); + + com.src = " "; + com.fixDesc(); + is(com.src, " ", "if no @desc tag is provided one is not added to just whitespace."); + + com.src = ""; + com.fixDesc(); + is(com.src, "", "if no @desc tag is provided one is not added to empty."); +*/ + +/** + Remove slash-star comment wrapper from a raw comment string. + @type String + */ +JSDOC.DocComment.unwrapComment = function(/**String*/comment) { + if (!comment) return ""; + var unwrapped = comment.replace(/(^\/\*\*|\*\/$)/g, "").replace(/^\s*\* ?/gm, ""); + return unwrapped; +} + +/*t: + plan(5, "testing JSDOC.DocComment.unwrapComment"); + + var com = "/**x*"+"/"; + var unwrapped = JSDOC.DocComment.unwrapComment(com); + is(unwrapped, "x", "a single character jsdoc is found."); + + com = "/***x*"+"/"; + unwrapped = JSDOC.DocComment.unwrapComment(com); + is(unwrapped, "x", "three stars are allowed in the opener."); + + com = "/****x*"+"/"; + unwrapped = JSDOC.DocComment.unwrapComment(com); + is(unwrapped, "*x", "fourth star in the opener is kept."); + + com = "/**x\n * y\n*"+"/"; + unwrapped = JSDOC.DocComment.unwrapComment(com); + is(unwrapped, "x\ny\n", "leading stars and spaces are trimmed."); + + com = "/**x\n * y\n*"+"/"; + unwrapped = JSDOC.DocComment.unwrapComment(com); + is(unwrapped, "x\n y\n", "only first space after leading stars are trimmed."); +*/ + +/** + Provides a printable version of the comment. + @type String + */ +JSDOC.DocComment.prototype.toString = function() { + return this.src; +} + +/*t: + plan(1, "testing JSDOC.DocComment#fixDesc"); + var com = new JSDOC.DocComment(); + com.src = "foo"; + is(""+com, "foo", "stringifying a comment returns the unwrapped src."); +*/ + +/** + Given the title of a tag, returns all tags that have that title. + @type JSDOC.DocTag[] + */ +JSDOC.DocComment.prototype.getTag = function(/**String*/tagTitle) { + return this.tags.filter(function($){return $.title == tagTitle}); +} + +JSDOC.DocComment.prototype.deleteTag = function(/**String*/tagTitle) { + this.tags = this.tags.filter(function($){return $.title != tagTitle}) +} + +/*t: + plan(1, "testing JSDOC.DocComment#getTag"); + requires("../frame/String.js"); + requires("../lib/JSDOC/DocTag.js"); + + var com = new JSDOC.DocComment("/**@foo some\n* @bar\n* @bar*"+"/"); + is(com.getTag("bar").length, 2, "getTag returns expected number of tags."); +*/ + +/** + Used to store the currently shared tag text. +*/ +JSDOC.DocComment.shared = ""; + +/*t: + plan(2, "testing JSDOC.DocComment.shared"); + requires("../frame/String.js"); + requires("../lib/JSDOC/DocTag.js"); + + JSDOC.DocComment.shared = "@author Michael"; + + var com = new JSDOC.DocComment("/**@foo\n* @foo*"+"/"); + is(com.getTag("author").length, 1, "getTag returns shared tag."); + is(com.getTag("foo").length, 2, "getTag returns unshared tags too."); +*/ \ No newline at end of file diff --git a/bin/jsdoc/lib/JSDOC/DocTag.js b/bin/jsdoc/lib/JSDOC/DocTag.js new file mode 100644 index 00000000..77ec07ca --- /dev/null +++ b/bin/jsdoc/lib/JSDOC/DocTag.js @@ -0,0 +1,294 @@ +if (typeof JSDOC == "undefined") JSDOC = {}; + +/** + @constructor + */ +JSDOC.DocTag = function(src) { + this.init(); + if (typeof src != "undefined") { + this.parse(src); + } +} + +/** + Create and initialize the properties of this. + */ +JSDOC.DocTag.prototype.init = function() { + this.title = ""; + this.type = ""; + this.name = ""; + this.isOptional = false; + this.defaultValue = ""; + this.desc = ""; + + return this; +} + +/** + Populate the properties of this from the given tag src. + @param {string} src + */ +JSDOC.DocTag.prototype.parse = function(src) { + if (typeof src != "string") throw "src must be a string not "+(typeof src); + + try { + src = this.nibbleTitle(src); + if (JSDOC.PluginManager) { + JSDOC.PluginManager.run("onDocTagSynonym", this); + } + + src = this.nibbleType(src); + + // only some tags are allowed to have names. + if (this.title == "param" || this.title == "property" || this.title == "config") { // @config is deprecated + src = this.nibbleName(src); + } + } + catch(e) { + if (LOG) LOG.warn(e); + else throw e; + } + this.desc = src; // whatever is left + + // example tags need to have whitespace preserved + if (this.title != "example") this.desc = this.desc.trim(); + + if (JSDOC.PluginManager) { + JSDOC.PluginManager.run("onDocTag", this); + } +} + +/** + Automatically called when this is stringified. + */ +JSDOC.DocTag.prototype.toString = function() { + return this.desc; +} + +/*t: + plan(1, "testing JSDOC.DocTag#toString"); + + var tag = new JSDOC.DocTag("param {object} date A valid date."); + is(""+tag, "A valid date.", "stringifying a tag returns the desc."); + */ + +/** + Find and shift off the title of a tag. + @param {string} src + @return src + */ +JSDOC.DocTag.prototype.nibbleTitle = function(src) { + if (typeof src != "string") throw "src must be a string not "+(typeof src); + + var parts = src.match(/^\s*(\S+)(?:\s([\s\S]*))?$/); + + if (parts && parts[1]) this.title = parts[1]; + if (parts && parts[2]) src = parts[2]; + else src = ""; + + return src; +} + +/*t: + plan(8, "testing JSDOC.DocTag#nibbleTitle"); + + var tag = new JSDOC.DocTag(); + + tag.init().nibbleTitle("aTitleGoesHere"); + is(tag.title, "aTitleGoesHere", "a title can be found in a single-word string."); + + var src = tag.init().nibbleTitle("aTitleGoesHere and the rest"); + is(tag.title, "aTitleGoesHere", "a title can be found in a multi-word string."); + is(src, "and the rest", "the rest is returned when the title is nibbled off."); + + src = tag.init().nibbleTitle(""); + is(tag.title, "", "given an empty string the title is empty."); + is(src, "", "the rest is empty when the tag is empty."); + + var src = tag.init().nibbleTitle(" aTitleGoesHere\n a description"); + is(tag.title, "aTitleGoesHere", "leading and trailing spaces are not part of the title."); + is(src, " a description", "leading spaces (less one) are part of the description."); + + tag.init().nibbleTitle("a.Title::Goes_Here foo"); + is(tag.title, "a.Title::Goes_Here", "titles with punctuation are allowed."); + */ + +/** + Find and shift off the type of a tag. + @requires frame/String.js + @param {string} src + @return src + */ +JSDOC.DocTag.prototype.nibbleType = function(src) { + if (typeof src != "string") throw "src must be a string not "+(typeof src); + + if (src.match(/^\s*\{/)) { + var typeRange = src.balance("{", "}"); + if (typeRange[1] == -1) { + throw "Malformed comment tag ignored. Tag type requires an opening { and a closing }: "+src; + } + this.type = src.substring(typeRange[0]+1, typeRange[1]).trim(); + this.type = this.type.replace(/\s*,\s*/g, "|"); // multiples can be separated by , or | + src = src.substring(typeRange[1]+1); + } + + return src; +} + +/*t: + plan(5, "testing JSDOC.DocTag.parser.nibbleType"); + requires("../frame/String.js"); + + var tag = new JSDOC.DocTag(); + + tag.init().nibbleType("{String[]} aliases"); + is(tag.type, "String[]", "type can have non-alpha characters."); + + tag.init().nibbleType("{ aTypeGoesHere } etc etc"); + is(tag.type, "aTypeGoesHere", "type is trimmed."); + + tag.init().nibbleType("{ oneType, twoType ,\n threeType } etc etc"); + is(tag.type, "oneType|twoType|threeType", "multiple types can be separated by commas."); + + var error; + try { tag.init().nibbleType("{widget foo"); } + catch(e) { error = e; } + is(typeof error, "string", "malformed tag type throws error."); + isnt(error.indexOf("Malformed"), -1, "error message tells tag is malformed."); + */ + +/** + Find and shift off the name of a tag. + @requires frame/String.js + @param {string} src + @return src + */ +JSDOC.DocTag.prototype.nibbleName = function(src) { + if (typeof src != "string") throw "src must be a string not "+(typeof src); + + src = src.trim(); + + // is optional? + if (src.charAt(0) == "[") { + var nameRange = src.balance("[", "]"); + if (nameRange[1] == -1) { + throw "Malformed comment tag ignored. Tag optional name requires an opening [ and a closing ]: "+src; + } + this.name = src.substring(nameRange[0]+1, nameRange[1]).trim(); + this.isOptional = true; + + src = src.substring(nameRange[1]+1); + + // has default value? + var nameAndValue = this.name.split("="); + if (nameAndValue.length) { + this.name = nameAndValue.shift().trim(); + this.defaultValue = nameAndValue.join("="); + } + } + else { + var parts = src.match(/^(\S+)(?:\s([\s\S]*))?$/); + if (parts) { + if (parts[1]) this.name = parts[1]; + if (parts[2]) src = parts[2].trim(); + else src = ""; + } + } + + return src; +} + +/*t: + requires("../frame/String.js"); + plan(9, "testing JSDOC.DocTag.parser.nibbleName"); + + var tag = new JSDOC.DocTag(); + + tag.init().nibbleName("[foo] This is a description."); + is(tag.isOptional, true, "isOptional syntax is detected."); + is(tag.name, "foo", "optional param name is found."); + + tag.init().nibbleName("[foo] This is a description."); + is(tag.isOptional, true, "isOptional syntax is detected when no type."); + is(tag.name, "foo", "optional param name is found when no type."); + + tag.init().nibbleName("[foo=7] This is a description."); + is(tag.name, "foo", "optional param name is found when default value."); + is(tag.defaultValue, 7, "optional param default value is found when default value."); + + //tag.init().nibbleName("[foo= a value] This is a description."); + //is(tag.defaultValue, " a value", "optional param default value is found when default value has spaces (issue #112)."); + + tag.init().nibbleName("[foo=[]] This is a description."); + is(tag.defaultValue, "[]", "optional param default value is found when default value is [] (issue #95)."); + + tag.init().nibbleName("[foo=a=b] This is a description."); + is(tag.name, "foo", "optional param name is found when default value is a=b."); + is(tag.defaultValue, "a=b", "optional param default value is found when default value is a=b.") + */ + +/*t: + plan(32, "Testing JSDOC.DocTag.parser."); + requires("../frame/String.js"); + + var tag = new JSDOC.DocTag(); + + is(typeof tag, "object", "JSDOC.DocTag.parser with an empty string returns an object."); + is(typeof tag.title, "string", "returned object has a string property 'title'."); + is(typeof tag.type, "string", "returned object has a string property 'type'."); + is(typeof tag.name, "string", "returned object has a string property 'name'."); + is(typeof tag.defaultValue, "string", "returned object has a string property 'defaultValue'."); + is(typeof tag.isOptional, "boolean", "returned object has a boolean property 'isOptional'."); + is(typeof tag.desc, "string", "returned object has a string property 'desc'."); + + tag = new JSDOC.DocTag("param {widget} foo"); + is(tag.title, "param", "param title is found."); + is(tag.name, "foo", "param name is found when desc is missing."); + is(tag.desc, "", "param desc is empty when missing."); + + tag = new JSDOC.DocTag("param {object} date A valid date."); + is(tag.name, "date", "param name is found with a type."); + is(tag.type, "object", "param type is found."); + is(tag.desc, "A valid date.", "param desc is found with a type."); + + tag = new JSDOC.DocTag("param aName a description goes\n here."); + is(tag.name, "aName", "param name is found without a type."); + is(tag.desc, "a description goes\n here.", "param desc is found without a type."); + + tag = new JSDOC.DocTag("param {widget}"); + is(tag.name, "", "param name is empty when it is not given."); + + tag = new JSDOC.DocTag("param {widget} [foo] This is a description."); + is(tag.name, "foo", "optional param name is found."); + + tag = new JSDOC.DocTag("return {aType} This is a description."); + is(tag.type, "aType", "when return tag has no name, type is found."); + is(tag.desc, "This is a description.", "when return tag has no name, desc is found."); + + tag = new JSDOC.DocTag("author Joe Coder "); + is(tag.title, "author", "author tag has a title."); + is(tag.type, "", "the author tag has no type."); + is(tag.name, "", "the author tag has no name."); + is(tag.desc, "Joe Coder ", "author tag has desc."); + + tag = new JSDOC.DocTag("private \t\n "); + is(tag.title, "private", "private tag has a title."); + is(tag.type, "", "the private tag has no type."); + is(tag.name, "", "the private tag has no name."); + is(tag.desc, "", "private tag has no desc."); + + tag = new JSDOC.DocTag("example\n example(code);\n more();"); + is(tag.desc, " example(code);\n more();", "leading whitespace (less one) in examples code is preserved."); + + tag = new JSDOC.DocTag("param theName \n"); + is(tag.name, "theName", "name only is found."); + + tag = new JSDOC.DocTag("type theDesc \n"); + is(tag.desc, "theDesc", "desc only is found."); + + tag = new JSDOC.DocTag("type {theType} \n"); + is(tag.type, "theType", "type only is found."); + + tag = new JSDOC.DocTag(""); + is(tag.title, "", "title is empty when tag is empty."); + */ \ No newline at end of file diff --git a/bin/jsdoc/lib/JSDOC/JsDoc.js b/bin/jsdoc/lib/JSDOC/JsDoc.js new file mode 100644 index 00000000..02275a69 --- /dev/null +++ b/bin/jsdoc/lib/JSDOC/JsDoc.js @@ -0,0 +1,140 @@ +/** + @constructor + @param [opt] Used to override the commandline options. Useful for testing. + @version $Id: JsDoc.js 831 2010-03-09 14:24:56Z micmath $ +*/ +JSDOC.JsDoc = function(/**object*/ opt) { + if (opt) { + JSDOC.opt = opt; + } + + if (JSDOC.opt.h) { + JSDOC.usage(); + quit(); + } + + // defend against options that are not sane + if (JSDOC.opt._.length == 0) { + LOG.warn("No source files to work on. Nothing to do."); + quit(); + } + if (JSDOC.opt.t === true || JSDOC.opt.d === true) { + JSDOC.usage(); + } + + if (typeof JSDOC.opt.d == "string") { + if (!JSDOC.opt.d.charAt(JSDOC.opt.d.length-1).match(/[\\\/]/)) { + JSDOC.opt.d = JSDOC.opt.d+"/"; + } + LOG.inform("Output directory set to '"+JSDOC.opt.d+"'."); + IO.mkPath(JSDOC.opt.d); + } + if (JSDOC.opt.e) IO.setEncoding(JSDOC.opt.e); + + // the -r option: scan source directories recursively + if (typeof JSDOC.opt.r == "boolean") JSDOC.opt.r = 10; + else if (!isNaN(parseInt(JSDOC.opt.r))) JSDOC.opt.r = parseInt(JSDOC.opt.r); + else JSDOC.opt.r = 1; + + // the -D option: define user variables + var D = {}; + if (JSDOC.opt.D) { + for (var i = 0; i < JSDOC.opt.D.length; i++) { + var param = JSDOC.opt.D[i]; + // remove first and last character if both == " + if ( + param.length > 1 + && param.charAt(0) == '"' + && param.charAt(param.length-1) == '"' + ) { + param = param.substr(1, param.length-2); + } + var defineParts = param.split(":"); + if (defineParts && defineParts.length > 1) { + for ( var dpIdx = 2; dpIdx < defineParts.length; dpIdx++ ) { + defineParts[1] += ':' + defineParts[dpIdx]; + } + D[defineParts[0]] = defineParts[1]; + } + } + } + JSDOC.opt.D = D; + // combine any conf file D options with the commandline D options + if (defined(JSDOC.conf)) for (var c in JSDOC.conf.D) { + if (!defined(JSDOC.opt.D[c])) { + JSDOC.opt.D[c] = JSDOC.conf.D[c]; + } + } + + // Give plugins a chance to initialize + if (defined(JSDOC.PluginManager)) { + JSDOC.PluginManager.run("onInit", JSDOC.opt); + } + + JSDOC.opt.srcFiles = JSDOC.JsDoc._getSrcFiles(); + JSDOC.JsDoc._parseSrcFiles(); + JSDOC.JsDoc.symbolSet = JSDOC.Parser.symbols; +} + +/** + Retrieve source file list. + @returns {String[]} The pathnames of the files to be parsed. + */ +JSDOC.JsDoc._getSrcFiles = function() { + JSDOC.JsDoc.srcFiles = []; + + var ext = ["js"]; + if (JSDOC.opt.x) { + ext = JSDOC.opt.x.split(",").map(function($) {return $.toLowerCase()}); + } + + for (var i = 0; i < JSDOC.opt._.length; i++) { + JSDOC.JsDoc.srcFiles = JSDOC.JsDoc.srcFiles.concat( + IO.ls(JSDOC.opt._[i], JSDOC.opt.r).filter( + function($) { + var thisExt = $.split(".").pop().toLowerCase(); + + if (JSDOC.opt.E) { + for(var n = 0; n < JSDOC.opt.E.length; n++) { + if ($.match(new RegExp(JSDOC.opt.E[n]))) { + LOG.inform("Excluding " + $); + return false; // if the file matches the regex then it's excluded. + } + } + } + + return (ext.indexOf(thisExt) > -1); // we're only interested in files with certain extensions + } + ) + ); + } + + return JSDOC.JsDoc.srcFiles; +} + +JSDOC.JsDoc._parseSrcFiles = function() { + JSDOC.Parser.init(); + for (var i = 0, l = JSDOC.JsDoc.srcFiles.length; i < l; i++) { + var srcFile = JSDOC.JsDoc.srcFiles[i]; + + if (JSDOC.opt.v) LOG.inform("Parsing file: " + srcFile); + + try { + var src = IO.readFile(srcFile); + } + catch(e) { + LOG.warn("Can't read source file '"+srcFile+"': "+e.message); + } + + var tr = new JSDOC.TokenReader(); + var ts = new JSDOC.TokenStream(tr.tokenize(new JSDOC.TextStream(src))); + + JSDOC.Parser.parse(ts, srcFile); + + } + JSDOC.Parser.finish(); + + if (JSDOC.PluginManager) { + JSDOC.PluginManager.run("onFinishedParsing", JSDOC.Parser.symbols); + } +} diff --git a/bin/jsdoc/lib/JSDOC/JsPlate.js b/bin/jsdoc/lib/JSDOC/JsPlate.js new file mode 100644 index 00000000..bcaebc9c --- /dev/null +++ b/bin/jsdoc/lib/JSDOC/JsPlate.js @@ -0,0 +1,109 @@ +/** + @constructor +*/ +JSDOC.JsPlate = function(templateFile) { + if (templateFile) this.template = IO.readFile(templateFile); + + this.templateFile = templateFile; + this.code = ""; + this.parse(); +} + +JSDOC.JsPlate.prototype.parse = function() { + this.template = this.template.replace(/\{#[\s\S]+?#\}/gi, ""); + this.code = "var output=\u001e"+this.template; + + this.code = this.code.replace( + //gi, + function (match, eachName, inName) { + return "\u001e;\rvar $"+eachName+"_keys = keys("+inName+");\rfor(var $"+eachName+"_i = 0; $"+eachName+"_i < $"+eachName+"_keys.length; $"+eachName+"_i++) {\rvar $"+eachName+"_last = ($"+eachName+"_i == $"+eachName+"_keys.length-1);\rvar $"+eachName+"_key = $"+eachName+"_keys[$"+eachName+"_i];\rvar "+eachName+" = "+inName+"[$"+eachName+"_key];\routput+=\u001e"; + } + ); + this.code = this.code.replace(//g, "\u001e;\rif ($1) { output+=\u001e"); + this.code = this.code.replace(//g, "\u001e;}\relse if ($1) { output+=\u001e"); + this.code = this.code.replace(//g, "\u001e;}\relse { output+=\u001e"); + this.code = this.code.replace(/<\/(if|for)>/g, "\u001e;\r};\routput+=\u001e"); + this.code = this.code.replace( + /\{\+\s*([\s\S]+?)\s*\+\}/gi, + function (match, code) { + code = code.replace(/"/g, "\u001e"); // prevent qoute-escaping of inline code + code = code.replace(/(\r?\n)/g, " "); + return "\u001e+ ("+code+") +\u001e"; + } + ); + this.code = this.code.replace( + /\{!\s*([\s\S]+?)\s*!\}/gi, + function (match, code) { + code = code.replace(/"/g, "\u001e"); // prevent qoute-escaping of inline code + code = code.replace(/(\n)/g, " "); + return "\u001e; "+code+";\routput+=\u001e"; + } + ); + this.code = this.code+"\u001e;"; + + this.code = this.code.replace(/(\r?\n)/g, "\\n"); + this.code = this.code.replace(/"/g, "\\\""); + this.code = this.code.replace(/\u001e/g, "\""); +} + +JSDOC.JsPlate.prototype.toCode = function() { + return this.code; +} + +JSDOC.JsPlate.keys = function(obj) { + var keys = []; + if (obj.constructor.toString().indexOf("Array") > -1) { + for (var i = 0; i < obj.length; i++) { + keys.push(i); + } + } + else { + for (var i in obj) { + keys.push(i); + } + } + return keys; +}; + +JSDOC.JsPlate.values = function(obj) { + var values = []; + if (obj.constructor.toString().indexOf("Array") > -1) { + for (var i = 0; i < obj.length; i++) { + values.push(obj[i]); + } + } + else { + for (var i in obj) { + values.push(obj[i]); + } + } + return values; +}; + +JSDOC.JsPlate.prototype.process = function(data, compact) { + var keys = JSDOC.JsPlate.keys; + var values = JSDOC.JsPlate.values; + + try { + eval(this.code); + } + catch (e) { + print(">> There was an error evaluating the compiled code from template: "+this.templateFile); + print(" The error was on line "+e.lineNumber+" "+e.name+": "+e.message); + var lines = this.code.split("\r"); + if (e.lineNumber-2 >= 0) print("line "+(e.lineNumber-1)+": "+lines[e.lineNumber-2]); + print("line "+e.lineNumber+": "+lines[e.lineNumber-1]); + print(""); + } + + if (compact) { // patch by mcbain.asm + // Remove lines that contain only space-characters, usually left by lines in the template + // which originally only contained JSPlate tags or code. This makes it easier to write + // non-tricky templates which still put out nice code (not bloated with extra lines). + // Lines purposely left blank (just a line ending) are left alone. + output = output.replace(/\s+?(\r?)\n/g, "$1\n"); + } + + /*debug*///print(this.code); + return output; +} \ No newline at end of file diff --git a/bin/jsdoc/lib/JSDOC/Lang.js b/bin/jsdoc/lib/JSDOC/Lang.js new file mode 100644 index 00000000..62919d7d --- /dev/null +++ b/bin/jsdoc/lib/JSDOC/Lang.js @@ -0,0 +1,144 @@ +/** + @namespace +*/ +JSDOC.Lang = { +} + +JSDOC.Lang.isBuiltin = function(name) { + return (JSDOC.Lang.isBuiltin.coreObjects.indexOf(name) > -1); +} +JSDOC.Lang.isBuiltin.coreObjects = ['_global_', 'Array', 'Boolean', 'Date', 'Error', 'Function', 'Math', 'Number', 'Object', 'RegExp', 'String']; + +JSDOC.Lang.whitespace = function(ch) { + return JSDOC.Lang.whitespace.names[ch]; +} +JSDOC.Lang.whitespace.names = { + " ": "SPACE", + "\f": "FORMFEED", + "\t": "TAB", + "\u0009": "UNICODE_TAB", + "\u000A": "UNICODE_NBR", + "\u0008": "VERTICAL_TAB" +}; + +JSDOC.Lang.newline = function(ch) { + return JSDOC.Lang.newline.names[ch]; +} +JSDOC.Lang.newline.names = { + "\n": "NEWLINE", + "\r": "RETURN", + "\u000A": "UNICODE_LF", + "\u000D": "UNICODE_CR", + "\u2029": "UNICODE_PS", + "\u2028": "UNICODE_LS" +}; + +JSDOC.Lang.keyword = function(word) { + return JSDOC.Lang.keyword.names["="+word]; +} +JSDOC.Lang.keyword.names = { + "=break": "BREAK", + "=case": "CASE", + "=catch": "CATCH", + "=const": "VAR", + "=continue": "CONTINUE", + "=default": "DEFAULT", + "=delete": "DELETE", + "=do": "DO", + "=else": "ELSE", + "=false": "FALSE", + "=finally": "FINALLY", + "=for": "FOR", + "=function": "FUNCTION", + "=if": "IF", + "=in": "IN", + "=instanceof": "INSTANCEOF", + "=new": "NEW", + "=null": "NULL", + "=return": "RETURN", + "=switch": "SWITCH", + "=this": "THIS", + "=throw": "THROW", + "=true": "TRUE", + "=try": "TRY", + "=typeof": "TYPEOF", + "=void": "VOID", + "=while": "WHILE", + "=with": "WITH", + "=var": "VAR" +}; + +JSDOC.Lang.punc = function(ch) { + return JSDOC.Lang.punc.names[ch]; +} +JSDOC.Lang.punc.names = { + ";": "SEMICOLON", + ",": "COMMA", + "?": "HOOK", + ":": "COLON", + "||": "OR", + "&&": "AND", + "|": "BITWISE_OR", + "^": "BITWISE_XOR", + "&": "BITWISE_AND", + "===": "STRICT_EQ", + "==": "EQ", + "=": "ASSIGN", + "!==": "STRICT_NE", + "!=": "NE", + "<<": "LSH", + "<=": "LE", + "<": "LT", + ">>>": "URSH", + ">>": "RSH", + ">=": "GE", + ">": "GT", + "++": "INCREMENT", + "--": "DECREMENT", + "+": "PLUS", + "-": "MINUS", + "*": "MUL", + "/": "DIV", + "%": "MOD", + "!": "NOT", + "~": "BITWISE_NOT", + ".": "DOT", + "[": "LEFT_BRACKET", + "]": "RIGHT_BRACKET", + "{": "LEFT_CURLY", + "}": "RIGHT_CURLY", + "(": "LEFT_PAREN", + ")": "RIGHT_PAREN" +}; + +JSDOC.Lang.matching = function(name) { + return JSDOC.Lang.matching.names[name]; +} +JSDOC.Lang.matching.names = { + "LEFT_PAREN": "RIGHT_PAREN", + "RIGHT_PAREN": "LEFT_PAREN", + "LEFT_CURLY": "RIGHT_CURLY", + "RIGHT_CURLY": "LEFT_CURLY", + "LEFT_BRACE": "RIGHT_BRACE", + "RIGHT_BRACE": "LEFT_BRACE" +} + +JSDOC.Lang.isNumber = function(str) { + return /^(\.[0-9]|[0-9]+\.|[0-9])[0-9]*([eE][+-][0-9]+)?$/i.test(str); +} + +JSDOC.Lang.isHexDec = function(str) { + return /^0x[0-9A-F]+$/i.test(str); +} + +JSDOC.Lang.isWordChar = function(str) { + return /^[a-zA-Z0-9$_.]+$/.test(str); +} + +JSDOC.Lang.isSpace = function(str) { + return (typeof JSDOC.Lang.whitespace(str) != "undefined"); +} + +JSDOC.Lang.isNewline = function(str) { + return (typeof JSDOC.Lang.newline(str) != "undefined"); +} \ No newline at end of file diff --git a/bin/jsdoc/lib/JSDOC/Parser.js b/bin/jsdoc/lib/JSDOC/Parser.js new file mode 100644 index 00000000..e489c61d --- /dev/null +++ b/bin/jsdoc/lib/JSDOC/Parser.js @@ -0,0 +1,146 @@ +if (typeof JSDOC == "undefined") JSDOC = {}; + +/** + @namespace + @requires JSDOC.Walker + @requires JSDOC.Symbol + @requires JSDOC.DocComment +*/ +JSDOC.Parser = { + conf: { + ignoreCode: JSDOC.opt.n, + ignoreAnonymous: true, // factory: true + treatUnderscoredAsPrivate: true, // factory: true + explain: false // factory: false + }, + + addSymbol: function(symbol) { + + if (JSDOC.Parser.rename) { + for (var n in JSDOC.Parser.rename) { + if (symbol.alias.indexOf(n) == 0) { + if (symbol.name == symbol.alias) { + symbol.name = symbol.name.replace(n, JSDOC.Parser.rename[n]); + } + symbol.alias = symbol.alias.replace(n, JSDOC.Parser.rename[n]); + } + } + } + + if (JSDOC.opt.S) { + if (typeof JSDOC.Parser.secureModules == "undefined") JSDOC.Parser.secureModules = {}; + if (/^exports\./.test(symbol.alias)) { + symbol.srcFile.match(/(^|[\\\/])([^\\\/]+)\.js/i); + var fileNS = RegExp.$2; + + // need to create the namespace associated with this file first + if (!JSDOC.Parser.secureModules[fileNS]) { + JSDOC.Parser.secureModules[fileNS] = 1; + var nsSymbol = new JSDOC.Symbol(fileNS, [], "GLOBAL", new JSDOC.DocComment("")); + nsSymbol.isNamespace = true; + nsSymbol.srcFile = ""; + nsSymbol.isPrivate = false; + nsSymbol.srcFile = symbol.srcFile; + nsSymbol.desc = (JSDOC.Parser.symbols.getSymbol(symbol.srcFile) || {desc: ""}).desc; + JSDOC.Parser.addSymbol(nsSymbol); + } + + symbol.alias = symbol.alias.replace(/^exports\./, fileNS + '.'); + symbol.name = symbol.name.replace(/^exports\./, ''); + symbol.memberOf = fileNS; + symbol.isStatic = true; + } + } + + // if a symbol alias is documented more than once the first one with the user docs wins + if (JSDOC.Parser.symbols.hasSymbol(symbol.alias)) { + var oldSymbol = JSDOC.Parser.symbols.getSymbol(symbol.alias); + if (oldSymbol.comment.isUserComment) { + if (JSDOC.opt.m) return; + if (symbol.comment.isUserComment) { // old and new are both documented + LOG.warn("The symbol '"+symbol.alias+"' is documented more than once."); + return; + } + else { // old is documented but new isn't + return; + } + } + } + + // we don't document anonymous things + if (JSDOC.Parser.conf.ignoreAnonymous && symbol.name.match(/\$anonymous\b/)) return; + + // uderscored things may be treated as if they were marked private, this cascades + if (JSDOC.Parser.conf.treatUnderscoredAsPrivate && symbol.name.match(/[.#-]_[^.#-]+$/)) { + if (!symbol.comment.getTag("public").length > 0) symbol.isPrivate = true; + } + + // -p flag is required to document private things + if (!JSDOC.opt.p && symbol.isPrivate) return; // issue #161 fixed by mcbain.asm + + // ignored things are not documented, this doesn't cascade + if (symbol.isIgnored) return; + JSDOC.Parser.symbols.addSymbol(symbol); + }, + + addBuiltin: function(name) { + var builtin = new JSDOC.Symbol(name, [], "CONSTRUCTOR", new JSDOC.DocComment("")); + builtin.isNamespace = true; + builtin.srcFile = ""; + builtin.isPrivate = false; + JSDOC.Parser.addSymbol(builtin); + return builtin; + }, + + init: function() { + JSDOC.Parser.symbols = new JSDOC.SymbolSet(); + JSDOC.Parser.walker = new JSDOC.Walker(); + }, + + finish: function() { + JSDOC.Parser.symbols.relate(); + + // make a litle report about what was found + if (JSDOC.Parser.conf.explain) { + var symbols = JSDOC.Parser.symbols.toArray(); + var srcFile = ""; + for (var i = 0, l = symbols.length; i < l; i++) { + var symbol = symbols[i]; + if (srcFile != symbol.srcFile) { + srcFile = symbol.srcFile; + print("\n"+srcFile+"\n-------------------"); + } + print(i+":\n alias => "+symbol.alias + "\n name => "+symbol.name+ "\n isa => "+symbol.isa + "\n memberOf => " + symbol.memberOf + "\n isStatic => " + symbol.isStatic + ", isInner => " + symbol.isInner+ ", isPrivate => " + symbol.isPrivate); + } + print("-------------------\n"); + } + } +} + +JSDOC.Parser.parse = function(/**JSDOC.TokenStream*/ts, /**String*/srcFile) { + JSDOC.Symbol.srcFile = (srcFile || ""); + JSDOC.DocComment.shared = ""; // shared comments don't cross file boundaries + + if (!JSDOC.Parser.walker) JSDOC.Parser.init(); + JSDOC.Parser.walker.walk(ts); // adds to our symbols + + // filter symbols by option + for (var p = JSDOC.Parser.symbols._index.first(); p; p = JSDOC.Parser.symbols._index.next()) { + var symbol = p.value; + + if (!symbol) continue; + + if (symbol.is("FILE") || symbol.is("GLOBAL")) { + continue; + } + else if (!JSDOC.opt.a && !symbol.comment.isUserComment) { + JSDOC.Parser.symbols.deleteSymbol(symbol.alias); + } + + if (/#$/.test(symbol.alias)) { // we don't document prototypes + JSDOC.Parser.symbols.deleteSymbol(symbol.alias); + } + } + + return JSDOC.Parser.symbols.toArray(); +} diff --git a/bin/jsdoc/lib/JSDOC/PluginManager.js b/bin/jsdoc/lib/JSDOC/PluginManager.js new file mode 100644 index 00000000..9c911931 --- /dev/null +++ b/bin/jsdoc/lib/JSDOC/PluginManager.js @@ -0,0 +1,33 @@ +/** + @namespace Holds functionality related to running plugins. +*/ +JSDOC.PluginManager = { +} + +/** + @param name A unique name that identifies that plugin. + @param handlers A collection of named functions. The names correspond to hooks in the core code. +*/ +JSDOC.PluginManager.registerPlugin = function(/**String*/name, /**Object*/handlers) { + if (!defined(JSDOC.PluginManager.plugins)) + /** The collection of all plugins. Requires a unique name for each. + */ + JSDOC.PluginManager.plugins = {}; + + + JSDOC.PluginManager.plugins[name] = handlers; +} + +/** + @param hook The name of the hook that is being caught. + @param target Any object. This will be passed as the only argument to the handler whose + name matches the hook name. Handlers cannot return a value, so must modify the target + object to have an effect. +*/ +JSDOC.PluginManager.run = function(/**String*/hook, /**Mixed*/target) { + for (var name in JSDOC.PluginManager.plugins) { + if (defined(JSDOC.PluginManager.plugins[name][hook])) { + JSDOC.PluginManager.plugins[name][hook](target); + } + } +} diff --git a/bin/jsdoc/lib/JSDOC/Symbol.js b/bin/jsdoc/lib/JSDOC/Symbol.js new file mode 100644 index 00000000..1aa44da8 --- /dev/null +++ b/bin/jsdoc/lib/JSDOC/Symbol.js @@ -0,0 +1,644 @@ +if (typeof JSDOC == "undefined") JSDOC = {}; + +/** + Create a new Symbol. + @class Represents a symbol in the source code. + */ +JSDOC.Symbol = function() { + this.init(); + if (arguments.length) this.populate.apply(this, arguments); +} + +JSDOC.Symbol.count = 0; + +JSDOC.Symbol.prototype.init = function() { + this._name = ""; + this._params = []; + this.$args = []; + this.addOn = ""; + this.alias = ""; + this.augments = []; + this.author = ""; + this.classDesc = ""; + this.comment = {}; + this.defaultValue = undefined; + this.deprecated = ""; + this.desc = ""; + this.example = []; + this.exceptions = []; + this.fires = []; + this.id = JSDOC.Symbol.count++; + this.inherits = []; + this.inheritsFrom = []; + this.isa = "OBJECT"; + this.isConstant = false; + this.isEvent = false; + this.isIgnored = false; + this.isInner = false; + this.isNamespace = false; + this.isPrivate = false; + this.isStatic = false; + this.memberOf = ""; + this.methods = []; + this.properties = []; + this.requires = []; + this.returns = []; + this.see = []; + this.since = ""; + this.srcFile = {}; + this.type = ""; + this.version = ""; +} + +JSDOC.Symbol.prototype.serialize = function() { + var keys = []; + for (var p in this) { + keys.push (p); + } + keys = keys.sort(); + + var out = ""; + for (var i in keys) { + if (typeof this[keys[i]] == "function") continue; + out += keys[i]+" => "+Dumper.dump(this[keys[i]])+",\n"; + } + return "\n{\n" + out + "}\n"; +} + +JSDOC.Symbol.prototype.clone = function() { + var clone = new JSDOC.Symbol(); + clone.populate.apply(clone, this.$args); // repopulate using the original arguments + clone.srcFile = this.srcFile; // not the current srcFile, the one when the original was made + return clone; +} + +JSDOC.Symbol.prototype.__defineSetter__("name", + function(n) { n = n.replace(/^_global_[.#-]/, ""); n = n.replace(/\.prototype\.?/g, '#'); this._name = n; } +); +JSDOC.Symbol.prototype.__defineGetter__("name", + function() { return this._name; } +); +JSDOC.Symbol.prototype.__defineSetter__("params", + function(v) { + for (var i = 0, l = v.length; i < l; i++) { + if (v[i].constructor != JSDOC.DocTag) { // may be a generic object parsed from signature, like {type:..., name:...} + this._params[i] = new JSDOC.DocTag("param"+((v[i].type)?" {"+v[i].type+"}":"")+" "+v[i].name); + } + else { + this._params[i] = v[i]; + } + } + } +); +JSDOC.Symbol.prototype.__defineGetter__("params", + function() { return this._params; } +); + +JSDOC.Symbol.prototype.getEvents = function() { + var events = []; + for (var i = 0, l = this.methods.length; i < l; i++) { + if (this.methods[i].isEvent) { + this.methods[i].name = this.methods[i].name.replace("event:", ""); + events.push(this.methods[i]); + } + } + return events; +} + +JSDOC.Symbol.prototype.getMethods = function() { + var nonEvents = []; + for (var i = 0, l = this.methods.length; i < l; i++) { + if (!this.methods[i].isEvent) { + nonEvents.push(this.methods[i]); + } + } + return nonEvents; +} + + +JSDOC.Symbol.prototype.populate = function( + /** String */ name, + /** Object[] */ params, + /** String */ isa, + /** JSDOC.DocComment */ comment +) { + this.$args = arguments; + + this.name = name; + this.alias = this.name; + + this.params = params; + this.isa = (isa == "VIRTUAL")? "OBJECT":isa; + this.comment = comment || new JSDOC.DocComment(""); + this.srcFile = JSDOC.Symbol.srcFile; + + if (this.is("FILE") && !this.alias) this.alias = this.srcFile; + + this.setTags(); + + if (typeof JSDOC.PluginManager != "undefined") { + JSDOC.PluginManager.run("onSymbol", this); + } +} + +JSDOC.Symbol.prototype.setTags = function() { + // @author + var authors = this.comment.getTag("author"); + if (authors.length) { + this.author = authors.map(function($){return $.desc;}).join(", "); + } + + /*t: + plan(34, "testing JSDOC.Symbol"); + + requires("../lib/JSDOC/DocComment.js"); + requires("../frame/String.js"); + requires("../lib/JSDOC/DocTag.js"); + + var sym = new JSDOC.Symbol("foo", [], "OBJECT", new JSDOC.DocComment("/**@author Joe Smith*"+"/")); + is(sym.author, "Joe Smith", "@author tag, author is found."); + */ + + // @desc + var descs = this.comment.getTag("desc"); + if (descs.length) { + this.desc = descs.map(function($){return $.desc;}).join("\n"); // multiple descriptions are concatenated into one + } + + /*t: + var sym = new JSDOC.Symbol("foo", [], "OBJECT", new JSDOC.DocComment("/**@desc This is a description.*"+"/")); + is(sym.desc, "This is a description.", "@desc tag, description is found."); + */ + + // @overview + if (this.is("FILE")) { + if (!this.alias) this.alias = this.srcFile; + + var overviews = this.comment.getTag("overview"); + if (overviews.length) { + this.desc = [this.desc].concat(overviews.map(function($){return $.desc;})).join("\n"); + } + } + + /*t: + var sym = new JSDOC.Symbol("foo", [], "FILE", new JSDOC.DocComment("/**@overview This is an overview.*"+"/")); + is(sym.desc, "\nThis is an overview.", "@overview tag, description is found."); + */ + + // @since + var sinces = this.comment.getTag("since"); + if (sinces.length) { + this.since = sinces.map(function($){return $.desc;}).join(", "); + } + + /*t: + var sym = new JSDOC.Symbol("foo", [], "FILE", new JSDOC.DocComment("/**@since 1.01*"+"/")); + is(sym.since, "1.01", "@since tag, description is found."); + */ + + // @constant + if (this.comment.getTag("constant").length) { + this.isConstant = true; + } + + /*t: + var sym = new JSDOC.Symbol("foo", [], "FILE", new JSDOC.DocComment("/**@constant*"+"/")); + is(sym.isConstant, true, "@constant tag, isConstant set."); + */ + + // @version + var versions = this.comment.getTag("version"); + if (versions.length) { + this.version = versions.map(function($){return $.desc;}).join(", "); + } + + /*t: + var sym = new JSDOC.Symbol("foo", [], "FILE", new JSDOC.DocComment("/**@version 2.0x*"+"/")); + is(sym.version, "2.0x", "@version tag, version is found."); + */ + + // @deprecated + var deprecateds = this.comment.getTag("deprecated"); + if (deprecateds.length) { + this.deprecated = deprecateds.map(function($){return $.desc;}).join("\n"); + } + + /*t: + var sym = new JSDOC.Symbol("foo", [], "FILE", new JSDOC.DocComment("/**@deprecated Use other method.*"+"/")); + is(sym.deprecated, "Use other method.", "@deprecated tag, desc is found."); + */ + + // @example + var examples = this.comment.getTag("example"); + if (examples.length) { + this.example = examples.map( + // trim trailing whitespace + function($) { + $.desc = $.desc.replace(/\s+$/, ""); + return $; + } + ); + } + + /*t: + var sym = new JSDOC.Symbol("foo", [], "FILE", new JSDOC.DocComment("/**@example This\n is an example. \n*"+"/")); + isnt(typeof sym.example[0], "undefined", "@example tag, creates sym.example array."); + is(sym.example[0], "This\n is an example.", "@example tag, desc is found."); + */ + + // @see + var sees = this.comment.getTag("see"); + if (sees.length) { + var thisSee = this.see; + sees.map(function($){thisSee.push($.desc);}); + } + + /*t: + var sym = new JSDOC.Symbol("foo", [], "FILE", new JSDOC.DocComment("/**@see The other thing.*"+"/")); + is(sym.see, "The other thing.", "@see tag, desc is found."); + */ + + // @class + var classes = this.comment.getTag("class"); + if (classes.length) { + this.isa = "CONSTRUCTOR"; + this.classDesc = classes[0].desc; // desc can't apply to the constructor as there is none. + } + + /*t: + var sym = new JSDOC.Symbol("foo", [], "OBJECT", new JSDOC.DocComment("/**@class This describes the class.*"+"/")); + is(sym.isa, "CONSTRUCTOR", "@class tag, makes symbol a constructor."); + is(sym.classDesc, "This describes the class.", "@class tag, class description is found."); + */ + + // @namespace + var namespaces = this.comment.getTag("namespace"); + if (namespaces.length) { + this.classDesc = namespaces[0].desc; + this.isNamespace = true; + } + + /*t: + var sym = new JSDOC.Symbol("foo", [], "OBJECT", new JSDOC.DocComment("/**@namespace This describes the namespace.*"+"/")); + is(sym.classDesc, "This describes the namespace.", "@namespace tag, class description is found."); + */ + + // @param + var params = this.comment.getTag("param"); + if (params.length) { + // user-defined params overwrite those with same name defined by the parser + var thisParams = this.params; + + if (thisParams.length == 0) { // none exist yet, so just bung all these user-defined params straight in + this.params = params; + } + else { // need to overlay these user-defined params on to existing parser-defined params + for (var i = 0, l = params.length; i < l; i++) { + if (thisParams[i]) { + if (params[i].type) thisParams[i].type = params[i].type; + thisParams[i].name = params[i].name; + thisParams[i].desc = params[i].desc; + thisParams[i].isOptional = params[i].isOptional; + thisParams[i].defaultValue = params[i].defaultValue; + } + else thisParams[i] = params[i]; + } + } + } + + /*t: + var sym = new JSDOC.Symbol("foo", [{type: "array", name: "pages"}], "FUNCTION", new JSDOC.DocComment("/**Description.*"+"/")); + is(sym.params.length, 1, "parser defined param is found."); + + sym = new JSDOC.Symbol("foo", [], "FUNCTION", new JSDOC.DocComment("/**Description.\n@param {array} pages*"+"/")); + is(sym.params.length, 1, "user defined param is found."); + is(sym.params[0].type, "array", "user defined param type is found."); + is(sym.params[0].name, "pages", "user defined param name is found."); + + sym = new JSDOC.Symbol("foo", [{type: "array", name: "pages"}], "FUNCTION", new JSDOC.DocComment("/**Description.\n@param {string} uid*"+"/")); + is(sym.params.length, 1, "user defined param overwrites parser defined param."); + is(sym.params[0].type, "string", "user defined param type overwrites parser defined param type."); + is(sym.params[0].name, "uid", "user defined param name overwrites parser defined param name."); + + sym = new JSDOC.Symbol("foo", [{type: "array", name: "pages"}, {type: "number", name: "count"}], "FUNCTION", new JSDOC.DocComment("/**Description.\n@param {string} uid*"+"/")); + is(sym.params.length, 2, "user defined params overlay parser defined params."); + is(sym.params[1].type, "number", "user defined param type overlays parser defined param type."); + is(sym.params[1].name, "count", "user defined param name overlays parser defined param name."); + + sym = new JSDOC.Symbol("foo", [], "FUNCTION", new JSDOC.DocComment("/**Description.\n@param {array} pages The pages description.*"+"/")); + is(sym.params.length, 1, "user defined param with description is found."); + is(sym.params[0].desc, "The pages description.", "user defined param description is found."); + */ + + // @constructor + if (this.comment.getTag("constructor").length) { + this.isa = "CONSTRUCTOR"; + } + + /*t: + var sym = new JSDOC.Symbol("foo", [], "OBJECT", new JSDOC.DocComment("/**@constructor*"+"/")); + is(sym.isa, "CONSTRUCTOR", "@constructor tag, makes symbol a constructor."); + */ + + // @static + if (this.comment.getTag("static").length) { + this.isStatic = true; + if (this.isa == "CONSTRUCTOR") { + this.isNamespace = true; + } + } + + /*t: + var sym = new JSDOC.Symbol("foo", [], "OBJECT", new JSDOC.DocComment("/**@static\n@constructor*"+"/")); + is(sym.isStatic, true, "@static tag, makes isStatic true."); + is(sym.isNamespace, true, "@static and @constructor tag, makes isNamespace true."); + */ + + // @inner + if (this.comment.getTag("inner").length) { + this.isInner = true; + this.isStatic = false; + } + + /*t: + var sym = new JSDOC.Symbol("foo", [], "OBJECT", new JSDOC.DocComment("/**@inner*"+"/")); + is(sym.isStatic, false, "@inner tag, makes isStatic false."); + is(sym.isInner, true, "@inner makes isInner true."); + */ + + // @name + var names = this.comment.getTag("name"); + if (names.length) { + this.name = names[0].desc; + } + + /*t: + // todo + */ + + // @field + if (this.comment.getTag("field").length) { + this.isa = "OBJECT"; + } + + /*t: + var sym = new JSDOC.Symbol("foo", [], "FUNCTION", new JSDOC.DocComment("/**@field*"+"/")); + is(sym.isa, "OBJECT", "@field tag, makes symbol an object."); + */ + + // @function + if (this.comment.getTag("function").length) { + this.isa = "FUNCTION"; + if (/event:/.test(this.alias)) this.isEvent = true; + } + + /*t: + var sym = new JSDOC.Symbol("foo", [], "OBJECT", new JSDOC.DocComment("/**@function*"+"/")); + is(sym.isa, "FUNCTION", "@function tag, makes symbol a function."); + */ + + // @event + var events = this.comment.getTag("event"); + if (events.length) { + this.isa = "FUNCTION"; + this.isEvent = true; + if (!/event:/.test(this.alias)) + this.alias = this.alias.replace(/^(.*[.#-])([^.#-]+)$/, "$1event:$2"); + } + + /*t: + var sym = new JSDOC.Symbol("foo", [], "OBJECT", new JSDOC.DocComment("/**@event*"+"/")); + is(sym.isa, "FUNCTION", "@event tag, makes symbol a function."); + is(sym.isEvent, true, "@event makes isEvent true."); + */ + + // @fires + var fires = this.comment.getTag("fires"); + if (fires.length) { + for (var i = 0; i < fires.length; i++) { + this.fires.push(fires[i].desc); + } + } + + /*t: + // todo + */ + + // @property + var properties = this.comment.getTag("property"); + if (properties.length) { + thisProperties = this.properties; + for (var i = 0; i < properties.length; i++) { + var property = new JSDOC.Symbol(this.alias+"#"+properties[i].name, [], "OBJECT", new JSDOC.DocComment("/**"+properties[i].desc+"*/")); + // TODO: shouldn't the following happen in the addProperty method of Symbol? + if (properties[i].type) property.type = properties[i].type; + if (properties[i].defaultValue) property.defaultValue = properties[i].defaultValue; + this.addProperty(property); + if (!JSDOC.Parser.symbols.getSymbolByName(property.name)) + JSDOC.Parser.addSymbol(property); + } + } + + /*t: + // todo + */ + + // @return + var returns = this.comment.getTag("return"); + if (returns.length) { // there can be many return tags in a single doclet + this.returns = returns; + this.type = returns.map(function($){return $.type}).join(", "); + } + + /*t: + // todo + */ + + // @exception + this.exceptions = this.comment.getTag("throws"); + + /*t: + // todo + */ + + // @requires + var requires = this.comment.getTag("requires"); + if (requires.length) { + this.requires = requires.map(function($){return $.desc}); + } + + /*t: + // todo + */ + + // @type + var types = this.comment.getTag("type"); + if (types.length) { + this.type = types[0].desc; //multiple type tags are ignored + } + + /*t: + // todo + */ + + // @private + if (this.comment.getTag("private").length || this.isInner) { + this.isPrivate = true; + } + + // @ignore + if (this.comment.getTag("ignore").length) { + this.isIgnored = true; + } + + /*t: + // todo + */ + + // @inherits ... as ... + var inherits = this.comment.getTag("inherits"); + if (inherits.length) { + for (var i = 0; i < inherits.length; i++) { + if (/^\s*([a-z$0-9_.#:-]+)(?:\s+as\s+([a-z$0-9_.#:-]+))?/i.test(inherits[i].desc)) { + var inAlias = RegExp.$1; + var inAs = RegExp.$2 || inAlias; + + if (inAlias) inAlias = inAlias.replace(/\.prototype\.?/g, "#"); + + if (inAs) { + inAs = inAs.replace(/\.prototype\.?/g, "#"); + inAs = inAs.replace(/^this\.?/, "#"); + } + + if (inAs.indexOf(inAlias) != 0) { //not a full namepath + var joiner = "."; + if (this.alias.charAt(this.alias.length-1) == "#" || inAs.charAt(0) == "#") { + joiner = ""; + } + inAs = this.alias + joiner + inAs; + } + } + this.inherits.push({alias: inAlias, as: inAs}); + } + } + + /*t: + // todo + */ + + // @augments + this.augments = this.comment.getTag("augments"); + + // @default + var defaults = this.comment.getTag("default"); + if (defaults.length) { + if (this.is("OBJECT")) { + this.defaultValue = defaults[0].desc; + } + } + + /*t: + // todo + */ + + // @memberOf + var memberOfs = this.comment.getTag("memberOf"); + if (memberOfs.length) { + this.memberOf = memberOfs[0].desc; + this.memberOf = this.memberOf.replace(/\.prototype\.?/g, "#"); + } + + /*t: + // todo + */ + + // @public + if (this.comment.getTag("public").length) { + this.isPrivate = false; + } + + /*t: + // todo + */ + + if (JSDOC.PluginManager) { + JSDOC.PluginManager.run("onSetTags", this); + } +} + +JSDOC.Symbol.prototype.is = function(what) { + return this.isa === what; +} + +JSDOC.Symbol.prototype.isBuiltin = function() { + return JSDOC.Lang.isBuiltin(this.alias); +} + +JSDOC.Symbol.prototype.setType = function(/**String*/comment, /**Boolean*/overwrite) { + if (!overwrite && this.type) return; + var typeComment = JSDOC.DocComment.unwrapComment(comment); + this.type = typeComment; +} + +JSDOC.Symbol.prototype.inherit = function(symbol) { + if (!this.hasMember(symbol.name) && !symbol.isInner) { + if (symbol.is("FUNCTION")) + this.methods.push(symbol); + else if (symbol.is("OBJECT")) + this.properties.push(symbol); + } +} + +JSDOC.Symbol.prototype.hasMember = function(name) { + return (this.hasMethod(name) || this.hasProperty(name)); +} + +JSDOC.Symbol.prototype.addMember = function(symbol) { + if (symbol.is("FUNCTION")) { this.addMethod(symbol); } + else if (symbol.is("OBJECT")) { this.addProperty(symbol); } +} + +JSDOC.Symbol.prototype.hasMethod = function(name) { + var thisMethods = this.methods; + for (var i = 0, l = thisMethods.length; i < l; i++) { + if (thisMethods[i].name == name) return true; + if (thisMethods[i].alias == name) return true; + } + return false; +} + +JSDOC.Symbol.prototype.addMethod = function(symbol) { + var methodAlias = symbol.alias; + var thisMethods = this.methods; + for (var i = 0, l = thisMethods.length; i < l; i++) { + if (thisMethods[i].alias == methodAlias) { + thisMethods[i] = symbol; // overwriting previous method + return; + } + } + thisMethods.push(symbol); // new method with this alias +} + +JSDOC.Symbol.prototype.hasProperty = function(name) { + var thisProperties = this.properties; + for (var i = 0, l = thisProperties.length; i < l; i++) { + if (thisProperties[i].name == name) return true; + if (thisProperties[i].alias == name) return true; + } + return false; +} + +JSDOC.Symbol.prototype.addProperty = function(symbol) { + var propertyAlias = symbol.alias; + var thisProperties = this.properties; + for (var i = 0, l = thisProperties.length; i < l; i++) { + if (thisProperties[i].alias == propertyAlias) { + thisProperties[i] = symbol; // overwriting previous property + return; + } + } + + thisProperties.push(symbol); // new property with this alias +} + +JSDOC.Symbol.srcFile = ""; //running reference to the current file being parsed diff --git a/bin/jsdoc/lib/JSDOC/SymbolSet.js b/bin/jsdoc/lib/JSDOC/SymbolSet.js new file mode 100644 index 00000000..8e3a2ebf --- /dev/null +++ b/bin/jsdoc/lib/JSDOC/SymbolSet.js @@ -0,0 +1,243 @@ +/** @constructor */ +JSDOC.SymbolSet = function() { + this.init(); +} + +JSDOC.SymbolSet.prototype.init = function() { + this._index = new Hash(); +} + +JSDOC.SymbolSet.prototype.keys = function() { + return this._index.keys(); +} + +JSDOC.SymbolSet.prototype.hasSymbol = function(alias) { + return this._index.hasKey(alias); +} + +JSDOC.SymbolSet.prototype.addSymbol = function(symbol) { + if (JSDOC.opt.a && this.hasSymbol(symbol.alias)) { + LOG.warn("Overwriting symbol documentation for: " + symbol.alias + "."); + this.deleteSymbol(symbol.alias); + } + this._index.set(symbol.alias, symbol); +} + +JSDOC.SymbolSet.prototype.getSymbol = function(alias) { + if (this.hasSymbol(alias)) return this._index.get(alias); +} + +JSDOC.SymbolSet.prototype.getSymbolByName = function(name) { + for (var p = this._index.first(); p; p = this._index.next()) { + var symbol = p.value; + if (symbol.name == name) return symbol; + } +} + +JSDOC.SymbolSet.prototype.toArray = function() { + return this._index.values(); +} + +JSDOC.SymbolSet.prototype.deleteSymbol = function(alias) { + if (!this.hasSymbol(alias)) return; + this._index.drop(alias); +} + +JSDOC.SymbolSet.prototype.renameSymbol = function(oldName, newName) { + // todo: should check if oldname or newname already exist + this._index.replace(oldName, newName); + this._index.get(newName).alias = newName; + return newName; +} + +JSDOC.SymbolSet.prototype.relate = function() { + this.resolveBorrows(); + this.resolveMemberOf(); + this.resolveAugments(); +} + +JSDOC.SymbolSet.prototype.resolveBorrows = function() { + for (var p = this._index.first(); p; p = this._index.next()) { + var symbol = p.value; + if (symbol.is("FILE") || symbol.is("GLOBAL")) continue; + + var borrows = symbol.inherits; + for (var i = 0; i < borrows.length; i++) { + +if (/#$/.test(borrows[i].alias)) { + LOG.warn("Attempted to borrow entire instance of "+borrows[i].alias+" but that feature is not yet implemented."); + return; +} + var borrowed = this.getSymbol(borrows[i].alias); + + if (!borrowed) { + LOG.warn("Can't borrow undocumented "+borrows[i].alias+"."); + continue; + } + + if (borrows[i].as == borrowed.alias) { + var assumedName = borrowed.name.split(/([#.-])/).pop(); + borrows[i].as = symbol.name+RegExp.$1+assumedName; + LOG.inform("Assuming borrowed as name is "+borrows[i].as+" but that feature is experimental."); + } + + var borrowAsName = borrows[i].as; + var borrowAsAlias = borrowAsName; + if (!borrowAsName) { + LOG.warn("Malformed @borrow, 'as' is required."); + continue; + } + + if (borrowAsName.length > symbol.alias.length && borrowAsName.indexOf(symbol.alias) == 0) { + borrowAsName = borrowAsName.replace(borrowed.alias, "") + } + else { + var joiner = ""; + if (borrowAsName.charAt(0) != "#") joiner = "."; + borrowAsAlias = borrowed.alias + joiner + borrowAsName; + } + + borrowAsName = borrowAsName.replace(/^[#.]/, ""); + + if (this.hasSymbol(borrowAsAlias)) continue; + + var clone = borrowed.clone(); + clone.name = borrowAsName; + clone.alias = borrowAsAlias; + this.addSymbol(clone); + } + } +} + +JSDOC.SymbolSet.prototype.resolveMemberOf = function() { + for (var p = this._index.first(); p; p = this._index.next()) { + var symbol = p.value; + + if (symbol.is("FILE") || symbol.is("GLOBAL")) continue; + + // the memberOf value was provided in the @memberOf tag + else if (symbol.memberOf) { + // like foo.bar is a memberOf foo + if (symbol.alias.indexOf(symbol.memberOf) == 0) { + var memberMatch = new RegExp("^("+symbol.memberOf+")[.#-]?(.+)$"); + var aliasParts = symbol.alias.match(memberMatch); + + if (aliasParts) { + symbol.memberOf = aliasParts[1]; + symbol.name = aliasParts[2]; + } + + var nameParts = symbol.name.match(memberMatch); + + if (nameParts) { + symbol.name = nameParts[2]; + } + } + // like bar is a memberOf foo + else { + var joiner = symbol.memberOf.charAt(symbol.memberOf.length-1); + if (!/[.#-]/.test(joiner)) symbol.memberOf += "."; + this.renameSymbol(symbol.alias, symbol.memberOf + symbol.name); + } + } + // the memberOf must be calculated + else { + var parts = symbol.alias.match(/^(.*[.#-])([^.#-]+)$/); + + if (parts) { + symbol.memberOf = parts[1]; + symbol.name = parts[2]; + } + } + + // set isStatic, isInner + if (symbol.memberOf) { + switch (symbol.memberOf.charAt(symbol.memberOf.length-1)) { + case '#' : + symbol.isStatic = false; + symbol.isInner = false; + break; + case '.' : + symbol.isStatic = true; + symbol.isInner = false; + break; + case '-' : + symbol.isStatic = false; + symbol.isInner = true; + break; + default: // memberOf ends in none of the above + symbol.isStatic = true; + break; + } + } + + // unowned methods and fields belong to the global object + if (!symbol.is("CONSTRUCTOR") && !symbol.isNamespace && symbol.memberOf == "") { + symbol.memberOf = "_global_"; + } + + // clean up + if (symbol.memberOf.match(/[.#-]$/)) { + symbol.memberOf = symbol.memberOf.substr(0, symbol.memberOf.length-1); + } + // add to parent's methods or properties list + if (symbol.memberOf) { + + var container = this.getSymbol(symbol.memberOf); + if (!container) { + if (JSDOC.Lang.isBuiltin(symbol.memberOf)) container = JSDOC.Parser.addBuiltin(symbol.memberOf); + else { + LOG.warn("Trying to document "+symbol.name +" as a member of undocumented symbol "+symbol.memberOf+"."); + } + } + + if (container) container.addMember(symbol); + } + } +} + +JSDOC.SymbolSet.prototype.resolveAugments = function() { + for (var p = this._index.first(); p; p = this._index.next()) { + var symbol = p.value; + + if (symbol.alias == "_global_" || symbol.is("FILE")) continue; + JSDOC.SymbolSet.prototype.walk.apply(this, [symbol]); + } +} + +JSDOC.SymbolSet.prototype.walk = function(symbol) { + var augments = symbol.augments; + for(var i = 0; i < augments.length; i++) { + var contributer = this.getSymbol(augments[i]); + if (!contributer && JSDOC.Lang.isBuiltin(''+augments[i])) { + contributer = new JSDOC.Symbol("_global_."+augments[i], [], augments[i], new JSDOC.DocComment("Built in.")); + contributer.isNamespace = true; + contributer.srcFile = ""; + contributer.isPrivate = false; + JSDOC.Parser.addSymbol(contributer); + } + + if (contributer) { + if (contributer.augments.length) { + JSDOC.SymbolSet.prototype.walk.apply(this, [contributer]); + } + + symbol.inheritsFrom.push(contributer.alias); + //if (!isUnique(symbol.inheritsFrom)) { + // LOG.warn("Can't resolve augments: Circular reference: "+symbol.alias+" inherits from "+contributer.alias+" more than once."); + //} + //else { + var cmethods = contributer.methods; + var cproperties = contributer.properties; + + for (var ci = 0, cl = cmethods.length; ci < cl; ci++) { + if (!cmethods[ci].isStatic) symbol.inherit(cmethods[ci]); + } + for (var ci = 0, cl = cproperties.length; ci < cl; ci++) { + if (!cproperties[ci].isStatic) symbol.inherit(cproperties[ci]); + } + //} + } + else LOG.warn("Can't augment contributer: "+augments[i]+", not found."); + } +} diff --git a/bin/jsdoc/lib/JSDOC/TextStream.js b/bin/jsdoc/lib/JSDOC/TextStream.js new file mode 100644 index 00000000..ccc48a87 --- /dev/null +++ b/bin/jsdoc/lib/JSDOC/TextStream.js @@ -0,0 +1,41 @@ + +/** + @constructor +*/ +JSDOC.TextStream = function(text) { + if (typeof(text) == "undefined") text = ""; + text = ""+text; + this.text = text; + this.cursor = 0; +} + +JSDOC.TextStream.prototype.look = function(n) { + if (typeof n == "undefined") n = 0; + + if (this.cursor+n < 0 || this.cursor+n >= this.text.length) { + var result = new String(""); + result.eof = true; + return result; + } + return this.text.charAt(this.cursor+n); +} + +JSDOC.TextStream.prototype.next = function(n) { + if (typeof n == "undefined") n = 1; + if (n < 1) return null; + + var pulled = ""; + for (var i = 0; i < n; i++) { + if (this.cursor+i < this.text.length) { + pulled += this.text.charAt(this.cursor+i); + } + else { + var result = new String(""); + result.eof = true; + return result; + } + } + + this.cursor += n; + return pulled; +} \ No newline at end of file diff --git a/bin/jsdoc/lib/JSDOC/Token.js b/bin/jsdoc/lib/JSDOC/Token.js new file mode 100644 index 00000000..fb7f9d94 --- /dev/null +++ b/bin/jsdoc/lib/JSDOC/Token.js @@ -0,0 +1,18 @@ +if (typeof JSDOC == "undefined") JSDOC = {}; + +/** + @constructor +*/ +JSDOC.Token = function(data, type, name) { + this.data = data; + this.type = type; + this.name = name; +} + +JSDOC.Token.prototype.toString = function() { + return "<"+this.type+" name=\""+this.name+"\">"+this.data+""; +} + +JSDOC.Token.prototype.is = function(what) { + return this.name === what || this.type === what; +} \ No newline at end of file diff --git a/bin/jsdoc/lib/JSDOC/TokenReader.js b/bin/jsdoc/lib/JSDOC/TokenReader.js new file mode 100644 index 00000000..9f658fb9 --- /dev/null +++ b/bin/jsdoc/lib/JSDOC/TokenReader.js @@ -0,0 +1,332 @@ +if (typeof JSDOC == "undefined") JSDOC = {}; + +/** + @class Search a {@link JSDOC.TextStream} for language tokens. +*/ +JSDOC.TokenReader = function() { + this.keepDocs = true; + this.keepWhite = false; + this.keepComments = false; +} + +/** + @type {JSDOC.Token[]} + */ +JSDOC.TokenReader.prototype.tokenize = function(/**JSDOC.TextStream*/stream) { + var tokens = []; + /**@ignore*/ tokens.last = function() { return tokens[tokens.length-1]; } + /**@ignore*/ tokens.lastSym = function() { + for (var i = tokens.length-1; i >= 0; i--) { + if (!(tokens[i].is("WHIT") || tokens[i].is("COMM"))) return tokens[i]; + } + } + + while (!stream.look().eof) { + if (this.read_mlcomment(stream, tokens)) continue; + if (this.read_slcomment(stream, tokens)) continue; + if (this.read_dbquote(stream, tokens)) continue; + if (this.read_snquote(stream, tokens)) continue; + if (this.read_regx(stream, tokens)) continue; + if (this.read_numb(stream, tokens)) continue; + if (this.read_punc(stream, tokens)) continue; + if (this.read_newline(stream, tokens)) continue; + if (this.read_space(stream, tokens)) continue; + if (this.read_word(stream, tokens)) continue; + + // if execution reaches here then an error has happened + tokens.push(new JSDOC.Token(stream.next(), "TOKN", "UNKNOWN_TOKEN")); + } + return tokens; +} + +/** + @returns {Boolean} Was the token found? + */ +JSDOC.TokenReader.prototype.read_word = function(/**JSDOC.TokenStream*/stream, tokens) { + var found = ""; + while (!stream.look().eof && JSDOC.Lang.isWordChar(stream.look())) { + found += stream.next(); + } + + if (found === "") { + return false; + } + else { + var name; + if ((name = JSDOC.Lang.keyword(found))) tokens.push(new JSDOC.Token(found, "KEYW", name)); + else tokens.push(new JSDOC.Token(found, "NAME", "NAME")); + return true; + } +} + +/** + @returns {Boolean} Was the token found? + */ +JSDOC.TokenReader.prototype.read_punc = function(/**JSDOC.TokenStream*/stream, tokens) { + var found = ""; + var name; + while (!stream.look().eof && JSDOC.Lang.punc(found+stream.look())) { + found += stream.next(); + } + + if (found === "") { + return false; + } + else { + tokens.push(new JSDOC.Token(found, "PUNC", JSDOC.Lang.punc(found))); + return true; + } +} + +/** + @returns {Boolean} Was the token found? + */ +JSDOC.TokenReader.prototype.read_space = function(/**JSDOC.TokenStream*/stream, tokens) { + var found = ""; + + while (!stream.look().eof && JSDOC.Lang.isSpace(stream.look())) { + found += stream.next(); + } + + if (found === "") { + return false; + } + else { + if (this.collapseWhite) found = " "; + if (this.keepWhite) tokens.push(new JSDOC.Token(found, "WHIT", "SPACE")); + return true; + } +} + +/** + @returns {Boolean} Was the token found? + */ +JSDOC.TokenReader.prototype.read_newline = function(/**JSDOC.TokenStream*/stream, tokens) { + var found = ""; + + while (!stream.look().eof && JSDOC.Lang.isNewline(stream.look())) { + found += stream.next(); + } + + if (found === "") { + return false; + } + else { + if (this.collapseWhite) found = "\n"; + if (this.keepWhite) tokens.push(new JSDOC.Token(found, "WHIT", "NEWLINE")); + return true; + } +} + +/** + @returns {Boolean} Was the token found? + */ +JSDOC.TokenReader.prototype.read_mlcomment = function(/**JSDOC.TokenStream*/stream, tokens) { + if (stream.look() == "/" && stream.look(1) == "*") { + var found = stream.next(2); + + while (!stream.look().eof && !(stream.look(-1) == "/" && stream.look(-2) == "*")) { + found += stream.next(); + } + + // to start doclet we allow /** or /*** but not /**/ or /**** + if (/^\/\*\*([^\/]|\*[^*])/.test(found) && this.keepDocs) tokens.push(new JSDOC.Token(found, "COMM", "JSDOC")); + else if (this.keepComments) tokens.push(new JSDOC.Token(found, "COMM", "MULTI_LINE_COMM")); + return true; + } + return false; +} + +/** + @returns {Boolean} Was the token found? + */ +JSDOC.TokenReader.prototype.read_slcomment = function(/**JSDOC.TokenStream*/stream, tokens) { + var found; + if ( + (stream.look() == "/" && stream.look(1) == "/" && (found=stream.next(2))) + || + (stream.look() == "<" && stream.look(1) == "!" && stream.look(2) == "-" && stream.look(3) == "-" && (found=stream.next(4))) + ) { + + while (!stream.look().eof && !JSDOC.Lang.isNewline(stream.look())) { + found += stream.next(); + } + + if (this.keepComments) { + tokens.push(new JSDOC.Token(found, "COMM", "SINGLE_LINE_COMM")); + } + return true; + } + return false; +} + +/** + @returns {Boolean} Was the token found? + */ +JSDOC.TokenReader.prototype.read_dbquote = function(/**JSDOC.TokenStream*/stream, tokens) { + if (stream.look() == "\"") { + // find terminator + var string = stream.next(); + + while (!stream.look().eof) { + if (stream.look() == "\\") { + if (JSDOC.Lang.isNewline(stream.look(1))) { + do { + stream.next(); + } while (!stream.look().eof && JSDOC.Lang.isNewline(stream.look())); + string += "\\\n"; + } + else { + string += stream.next(2); + } + } + else if (stream.look() == "\"") { + string += stream.next(); + tokens.push(new JSDOC.Token(string, "STRN", "DOUBLE_QUOTE")); + return true; + } + else { + string += stream.next(); + } + } + } + return false; // error! unterminated string +} + +/** + @returns {Boolean} Was the token found? + */ +JSDOC.TokenReader.prototype.read_snquote = function(/**JSDOC.TokenStream*/stream, tokens) { + if (stream.look() == "'") { + // find terminator + var string = stream.next(); + + while (!stream.look().eof) { + if (stream.look() == "\\") { // escape sequence + string += stream.next(2); + } + else if (stream.look() == "'") { + string += stream.next(); + tokens.push(new JSDOC.Token(string, "STRN", "SINGLE_QUOTE")); + return true; + } + else { + string += stream.next(); + } + } + } + return false; // error! unterminated string +} + +/** + @returns {Boolean} Was the token found? + */ +JSDOC.TokenReader.prototype.read_numb = function(/**JSDOC.TokenStream*/stream, tokens) { + if (stream.look() === "0" && stream.look(1) == "x") { + return this.read_hex(stream, tokens); + } + + var found = ""; + + while (!stream.look().eof && JSDOC.Lang.isNumber(found+stream.look())){ + found += stream.next(); + } + + if (found === "") { + return false; + } + else { + if (/^0[0-7]/.test(found)) tokens.push(new JSDOC.Token(found, "NUMB", "OCTAL")); + else tokens.push(new JSDOC.Token(found, "NUMB", "DECIMAL")); + return true; + } +} +/*t: + requires("../lib/JSDOC/TextStream.js"); + requires("../lib/JSDOC/Token.js"); + requires("../lib/JSDOC/Lang.js"); + + plan(3, "testing JSDOC.TokenReader.prototype.read_numb"); + + //// setup + var src = "function foo(num){while (num+8.0 >= 0x20 && num < 0777){}}"; + var tr = new JSDOC.TokenReader(); + var tokens = tr.tokenize(new JSDOC.TextStream(src)); + + var hexToken, octToken, decToken; + for (var i = 0; i < tokens.length; i++) { + if (tokens[i].name == "HEX_DEC") hexToken = tokens[i]; + if (tokens[i].name == "OCTAL") octToken = tokens[i]; + if (tokens[i].name == "DECIMAL") decToken = tokens[i]; + } + //// + + is(decToken.data, "8.0", "decimal number is found in source."); + is(hexToken.data, "0x20", "hexdec number is found in source (issue #99)."); + is(octToken.data, "0777", "octal number is found in source."); +*/ + +/** + @returns {Boolean} Was the token found? + */ +JSDOC.TokenReader.prototype.read_hex = function(/**JSDOC.TokenStream*/stream, tokens) { + var found = stream.next(2); + + while (!stream.look().eof) { + if (JSDOC.Lang.isHexDec(found) && !JSDOC.Lang.isHexDec(found+stream.look())) { // done + tokens.push(new JSDOC.Token(found, "NUMB", "HEX_DEC")); + return true; + } + else { + found += stream.next(); + } + } + return false; +} + +/** + @returns {Boolean} Was the token found? + */ +JSDOC.TokenReader.prototype.read_regx = function(/**JSDOC.TokenStream*/stream, tokens) { + var last; + if ( + stream.look() == "/" + && + ( + + ( + !(last = tokens.lastSym()) // there is no last, the regex is the first symbol + || + ( + !last.is("NUMB") + && !last.is("NAME") + && !last.is("RIGHT_PAREN") + && !last.is("RIGHT_BRACKET") + ) + ) + ) + ) { + var regex = stream.next(); + + while (!stream.look().eof) { + if (stream.look() == "\\") { // escape sequence + regex += stream.next(2); + } + else if (stream.look() == "/") { + regex += stream.next(); + + while (/[gmi]/.test(stream.look())) { + regex += stream.next(); + } + + tokens.push(new JSDOC.Token(regex, "REGX", "REGX")); + return true; + } + else { + regex += stream.next(); + } + } + // error: unterminated regex + } + return false; +} diff --git a/bin/jsdoc/lib/JSDOC/TokenStream.js b/bin/jsdoc/lib/JSDOC/TokenStream.js new file mode 100644 index 00000000..1eeb44cb --- /dev/null +++ b/bin/jsdoc/lib/JSDOC/TokenStream.js @@ -0,0 +1,133 @@ +if (typeof JSDOC == "undefined") JSDOC = {}; + +/** + @constructor +*/ +JSDOC.TokenStream = function(tokens) { + this.tokens = (tokens || []); + this.rewind(); +} + +/** + @constructor + @private +*/ +function VoidToken(/**String*/type) { + this.toString = function() {return ""}; + this.is = function(){return false;} +} + +JSDOC.TokenStream.prototype.rewind = function() { + this.cursor = -1; +} + +/** + @type JSDOC.Token +*/ +JSDOC.TokenStream.prototype.look = function(/**Number*/n, /**Boolean*/considerWhitespace) { + if (typeof n == "undefined") n = 0; + + if (considerWhitespace == true) { + if (this.cursor+n < 0 || this.cursor+n > this.tokens.length) return {}; + return this.tokens[this.cursor+n]; + } + else { + var count = 0; + var i = this.cursor; + + while (true) { + if (i < 0) return new JSDOC.Token("", "VOID", "START_OF_STREAM"); + else if (i > this.tokens.length) return new JSDOC.Token("", "VOID", "END_OF_STREAM"); + + if (i != this.cursor && (this.tokens[i] === undefined || this.tokens[i].is("WHIT"))) { + if (n < 0) i--; else i++; + continue; + } + + if (count == Math.abs(n)) { + return this.tokens[i]; + } + count++; + (n < 0)? i-- : i++; + } + + return new JSDOC.Token("", "VOID", "STREAM_ERROR"); // because null isn't an object and caller always expects an object + } +} + +/** + @type JSDOC.Token|JSDOC.Token[] +*/ +JSDOC.TokenStream.prototype.next = function(/**Number*/howMany) { + if (typeof howMany == "undefined") howMany = 1; + if (howMany < 1) return null; + var got = []; + + for (var i = 1; i <= howMany; i++) { + if (this.cursor+i >= this.tokens.length) { + return null; + } + got.push(this.tokens[this.cursor+i]); + } + this.cursor += howMany; + + if (howMany == 1) { + return got[0]; + } + else return got; +} + +/** + @type JSDOC.Token[] +*/ +JSDOC.TokenStream.prototype.balance = function(/**String*/start, /**String*/stop) { + if (!stop) stop = JSDOC.Lang.matching(start); + + var depth = 0; + var got = []; + var started = false; + + while ((token = this.look())) { + if (token.is(start)) { + depth++; + started = true; + } + + if (started) { + got.push(token); + } + + if (token.is(stop)) { + depth--; + if (depth == 0) return got; + } + if (!this.next()) break; + } +} + +JSDOC.TokenStream.prototype.getMatchingToken = function(/**String*/start, /**String*/stop) { + var depth = 0; + var cursor = this.cursor; + + if (!start) { + start = JSDOC.Lang.matching(stop); + depth = 1; + } + if (!stop) stop = JSDOC.Lang.matching(start); + + while ((token = this.tokens[cursor])) { + if (token.is(start)) { + depth++; + } + + if (token.is(stop) && cursor) { + depth--; + if (depth == 0) return this.tokens[cursor]; + } + cursor++; + } +} + +JSDOC.TokenStream.prototype.insertAhead = function(/**JSDOC.Token*/token) { + this.tokens.splice(this.cursor+1, 0, token); +} \ No newline at end of file diff --git a/bin/jsdoc/lib/JSDOC/Util.js b/bin/jsdoc/lib/JSDOC/Util.js new file mode 100644 index 00000000..6d7edb36 --- /dev/null +++ b/bin/jsdoc/lib/JSDOC/Util.js @@ -0,0 +1,32 @@ +/** + * @namespace + * @deprecated Use {@link FilePath} instead. + */ +JSDOC.Util = { +} + +/** + * @deprecated Use {@link FilePath.fileName} instead. + */ +JSDOC.Util.fileName = function(path) { + LOG.warn("JSDOC.Util.fileName is deprecated. Use FilePath.fileName instead."); + var nameStart = Math.max(path.lastIndexOf("/")+1, path.lastIndexOf("\\")+1, 0); + return path.substring(nameStart); +} + +/** + * @deprecated Use {@link FilePath.fileExtension} instead. + */ +JSDOC.Util.fileExtension = function(filename) { + LOG.warn("JSDOC.Util.fileExtension is deprecated. Use FilePath.fileExtension instead."); + return filename.split(".").pop().toLowerCase(); +}; + +/** + * @deprecated Use {@link FilePath.dir} instead. + */ +JSDOC.Util.dir = function(path) { + LOG.warn("JSDOC.Util.dir is deprecated. Use FilePath.dir instead."); + var nameStart = Math.max(path.lastIndexOf("/")+1, path.lastIndexOf("\\")+1, 0); + return path.substring(0, nameStart-1); +} diff --git a/bin/jsdoc/lib/JSDOC/Walker.js b/bin/jsdoc/lib/JSDOC/Walker.js new file mode 100644 index 00000000..6ecaea88 --- /dev/null +++ b/bin/jsdoc/lib/JSDOC/Walker.js @@ -0,0 +1,507 @@ +if (typeof JSDOC == "undefined") JSDOC = {}; + +/** @constructor */ +JSDOC.Walker = function(/**JSDOC.TokenStream*/ts) { + this.init(); + if (typeof ts != "undefined") { + this.walk(ts); + } +} + +JSDOC.Walker.prototype.init = function() { + this.ts = null; + + var globalSymbol = new JSDOC.Symbol("_global_", [], "GLOBAL", new JSDOC.DocComment("")); + globalSymbol.isNamespace = true; + globalSymbol.srcFile = ""; + globalSymbol.isPrivate = false; + JSDOC.Parser.addSymbol(globalSymbol); + this.lastDoc = null; + this.token = null; + + /** + The chain of symbols under which we are currently nested. + @type Array + */ + this.namescope = [globalSymbol]; + this.namescope.last = function(n){ if (!n) n = 0; return this[this.length-(1+n)] || "" }; +} + +JSDOC.Walker.prototype.walk = function(/**JSDOC.TokenStream*/ts) { + this.ts = ts; + while (this.token = this.ts.look()) { + if (this.token.popNamescope) { + + var symbol = this.namescope.pop(); + if (symbol.is("FUNCTION")) { + if (this.ts.look(1).is("LEFT_PAREN") && symbol.comment.getTag("function").length == 0) { + symbol.isa = "OBJECT"; + } + } + } + this.step(); + if (!this.ts.next()) break; + } +} + +JSDOC.Walker.prototype.step = function() { + if (this.token.is("JSDOC")) { // it's a doc comment + + var doc = new JSDOC.DocComment(this.token.data); + + + if (doc.getTag("exports").length > 0) { + var exports = doc.getTag("exports")[0]; + + exports.desc.match(/(\S+) as (\S+)/i); + var n1 = RegExp.$1; + var n2 = RegExp.$2; + + if (!n1 && n2) throw "@exports tag requires a value like: 'name as ns.name'"; + + JSDOC.Parser.rename = (JSDOC.Parser.rename || {}); + JSDOC.Parser.rename[n1] = n2 + } + + if (doc.getTag("lends").length > 0) { + var lends = doc.getTag("lends")[0]; + + var name = lends.desc + if (!name) throw "@lends tag requires a value."; + + var symbol = new JSDOC.Symbol(name, [], "OBJECT", doc); + + this.namescope.push(symbol); + + var matching = this.ts.getMatchingToken("LEFT_CURLY"); + if (matching) matching.popNamescope = name; + else LOG.warn("Mismatched } character. Can't parse code in file " + symbol.srcFile + "."); + + this.lastDoc = null; + return true; + } + else if (doc.getTag("name").length > 0 && doc.getTag("overview").length == 0) { // it's a virtual symbol + var virtualName = doc.getTag("name")[0].desc; + if (!virtualName) throw "@name tag requires a value."; + + if (doc.getTag("memberOf").length > 0) { + virtualName = (doc.getTag("memberOf")[0] + "." + virtualName) + .replace(/([#.])\./, "$1"); + doc.deleteTag("memberOf"); + } + + var symbol = new JSDOC.Symbol(virtualName, [], "VIRTUAL", doc); + + JSDOC.Parser.addSymbol(symbol); + + this.lastDoc = null; + return true; + } + else if (doc.meta) { // it's a meta doclet + if (doc.meta == "@+") JSDOC.DocComment.shared = doc.src; + else if (doc.meta == "@-") JSDOC.DocComment.shared = ""; + else if (doc.meta == "nocode+") JSDOC.Parser.conf.ignoreCode = true; + else if (doc.meta == "nocode-") JSDOC.Parser.conf.ignoreCode = JSDOC.opt.n; + else throw "Unrecognized meta comment: "+doc.meta; + + this.lastDoc = null; + return true; + } + else if (doc.getTag("overview").length > 0) { // it's a file overview + symbol = new JSDOC.Symbol("", [], "FILE", doc); + + JSDOC.Parser.addSymbol(symbol); + + this.lastDoc = null; + return true; + } + else { + this.lastDoc = doc; + return false; + } + } + else if (!JSDOC.Parser.conf.ignoreCode) { // it's code + if (this.token.is("NAME")) { // it's the name of something + var symbol; + var name = this.token.data; + var doc = null; if (this.lastDoc) doc = this.lastDoc; + var params = []; + + // it's inside an anonymous object + if (this.ts.look(1).is("COLON") && this.ts.look(-1).is("LEFT_CURLY") && !(this.ts.look(-2).is("JSDOC") || this.namescope.last().comment.getTag("lends").length || this.ts.look(-2).is("ASSIGN") || this.ts.look(-2).is("COLON"))) { + name = "$anonymous"; + name = this.namescope.last().alias+"-"+name + + params = []; + + symbol = new JSDOC.Symbol(name, params, "OBJECT", doc); + + JSDOC.Parser.addSymbol(symbol); + + this.namescope.push(symbol); + + var matching = this.ts.getMatchingToken(null, "RIGHT_CURLY"); + if (matching) matching.popNamescope = name; + else LOG.warn("Mismatched } character. Can't parse code in file " + symbol.srcFile + "."); + } + // function foo() {} + else if (this.ts.look(-1).is("FUNCTION") && this.ts.look(1).is("LEFT_PAREN")) { + var isInner; + + if (this.lastDoc) doc = this.lastDoc; + + if (doc && doc.getTag("memberOf").length > 0) { + name = (doc.getTag("memberOf")[0]+"."+name).replace("#.", "#"); + doc.deleteTag("memberOf"); + } + else { + name = this.namescope.last().alias+"-"+name; + if (!this.namescope.last().is("GLOBAL")) isInner = true; + } + + if (!this.namescope.last().is("GLOBAL")) isInner = true; + + params = JSDOC.Walker.onParamList(this.ts.balance("LEFT_PAREN")); + + symbol = new JSDOC.Symbol(name, params, "FUNCTION", doc); + if (isInner) symbol.isInner = true; + + if (this.ts.look(1).is("JSDOC")) { + var inlineReturn = ""+this.ts.look(1).data; + inlineReturn = inlineReturn.replace(/(^\/\*\* *| *\*\/$)/g, ""); + symbol.type = inlineReturn; + } + + JSDOC.Parser.addSymbol(symbol); + + this.namescope.push(symbol); + + var matching = this.ts.getMatchingToken("LEFT_CURLY"); + if (matching) matching.popNamescope = name; + else LOG.warn("Mismatched } character. Can't parse code in file " + symbol.srcFile + "."); + } + // foo = function() {} + else if (this.ts.look(1).is("ASSIGN") && this.ts.look(2).is("FUNCTION")) { + var constructs; + var isConstructor = false; + if (doc && (constructs = doc.getTag("constructs")) && constructs.length) { + if (constructs[0].desc) { + name = constructs[0].desc; + isConstructor = true; + } + } + + var isInner; + if (this.ts.look(-1).is("VAR") || this.isInner) { + if (doc && doc.getTag("memberOf").length > 0) { + name = (doc.getTag("memberOf")[0]+"."+name).replace("#.", "#"); + doc.deleteTag("memberOf"); + } + else { + name = this.namescope.last().alias+"-"+name; + if (!this.namescope.last().is("GLOBAL")) isInner = true; + } + if (!this.namescope.last().is("GLOBAL")) isInner = true; + } + else if (name.indexOf("this.") == 0) { + name = this.resolveThis(name); + } + + if (this.lastDoc) doc = this.lastDoc; + params = JSDOC.Walker.onParamList(this.ts.balance("LEFT_PAREN")); + + symbol = new JSDOC.Symbol(name, params, "FUNCTION", doc); + + if (isInner) symbol.isInner = true; + if (isConstructor) symbol.isa = "CONSTRUCTOR"; + + if (this.ts.look(1).is("JSDOC")) { + var inlineReturn = ""+this.ts.look(1).data; + inlineReturn = inlineReturn.replace(/(^\/\*\* *| *\*\/$)/g, ""); + symbol.type = inlineReturn; + } + + JSDOC.Parser.addSymbol(symbol); + + this.namescope.push(symbol); + + var matching = this.ts.getMatchingToken("LEFT_CURLY"); + if (matching) matching.popNamescope = name; + else LOG.warn("Mismatched } character. Can't parse code in file " + symbol.srcFile + "."); + } + // foo = new function() {} or foo = (function() {} + else if (this.ts.look(1).is("ASSIGN") && (this.ts.look(2).is("NEW") || this.ts.look(2).is("LEFT_PAREN")) && this.ts.look(3).is("FUNCTION")) { + var isInner; + if (this.ts.look(-1).is("VAR") || this.isInner) { + name = this.namescope.last().alias+"-"+name + if (!this.namescope.last().is("GLOBAL")) isInner = true; + } + else if (name.indexOf("this.") == 0) { + name = this.resolveThis(name); + } + + this.ts.next(3); // advance past the "new" or "(" + + if (this.lastDoc) doc = this.lastDoc; + params = JSDOC.Walker.onParamList(this.ts.balance("LEFT_PAREN")); + + symbol = new JSDOC.Symbol(name, params, "OBJECT", doc); + if (isInner) symbol.isInner = true; + + if (this.ts.look(1).is("JSDOC")) { + var inlineReturn = ""+this.ts.look(1).data; + inlineReturn = inlineReturn.replace(/(^\/\*\* *| *\*\/$)/g, ""); + symbol.type = inlineReturn; + } + + JSDOC.Parser.addSymbol(symbol); + + symbol.scopeType = "INSTANCE"; + this.namescope.push(symbol); + + var matching = this.ts.getMatchingToken("LEFT_CURLY"); + if (matching) matching.popNamescope = name; + else LOG.warn("Mismatched } character. Can't parse code in file " + symbol.srcFile + "."); + } + // foo: function() {} + else if (this.ts.look(1).is("COLON") && this.ts.look(2).is("FUNCTION")) { + name = (this.namescope.last().alias+"."+name).replace("#.", "#"); + + if (this.lastDoc) doc = this.lastDoc; + params = JSDOC.Walker.onParamList(this.ts.balance("LEFT_PAREN")); + + if (doc && doc.getTag("constructs").length) { + name = name.replace(/\.prototype(\.|$)/, "#"); + + if (name.indexOf("#") > -1) name = name.match(/(^[^#]+)/)[0]; + else name = this.namescope.last().alias; + + symbol = new JSDOC.Symbol(name, params, "CONSTRUCTOR", doc); + } + else { + symbol = new JSDOC.Symbol(name, params, "FUNCTION", doc); + } + + if (this.ts.look(1).is("JSDOC")) { + var inlineReturn = ""+this.ts.look(1).data; + inlineReturn = inlineReturn.replace(/(^\/\*\* *| *\*\/$)/g, ""); + symbol.type = inlineReturn; + } + + JSDOC.Parser.addSymbol(symbol); + + this.namescope.push(symbol); + + var matching = this.ts.getMatchingToken("LEFT_CURLY"); + if (matching) matching.popNamescope = name; + else LOG.warn("Mismatched } character. Can't parse code in file " + symbol.srcFile + "."); + } + // foo = {} + else if (this.ts.look(1).is("ASSIGN") && this.ts.look(2).is("LEFT_CURLY")) { + var isInner; + if (this.ts.look(-1).is("VAR") || this.isInner) { + name = this.namescope.last().alias+"-"+name + if (!this.namescope.last().is("GLOBAL")) isInner = true; + } + else if (name.indexOf("this.") == 0) { + name = this.resolveThis(name); + } + + if (this.lastDoc) doc = this.lastDoc; + + symbol = new JSDOC.Symbol(name, params, "OBJECT", doc); + if (isInner) symbol.isInner = true; + + + if (doc) JSDOC.Parser.addSymbol(symbol); + + this.namescope.push(symbol); + + var matching = this.ts.getMatchingToken("LEFT_CURLY"); + if (matching) matching.popNamescope = name; + else LOG.warn("Mismatched } character. Can't parse code in file " + symbol.srcFile + "."); + } + // var foo; + else if (this.ts.look(1).is("SEMICOLON")) { + var isInner; + + if (this.ts.look(-1).is("VAR") || this.isInner) { + name = this.namescope.last().alias+"-"+name + if (!this.namescope.last().is("GLOBAL")) isInner = true; + + if (this.lastDoc) doc = this.lastDoc; + + symbol = new JSDOC.Symbol(name, params, "OBJECT", doc); + if (isInner) symbol.isInner = true; + + + if (doc) JSDOC.Parser.addSymbol(symbol); + } + } + // foo = x + else if (this.ts.look(1).is("ASSIGN")) { + var isInner; + if (this.ts.look(-1).is("VAR") || this.isInner) { + name = this.namescope.last().alias+"-"+name + if (!this.namescope.last().is("GLOBAL")) isInner = true; + } + else if (name.indexOf("this.") == 0) { + name = this.resolveThis(name); + } + + if (this.lastDoc) doc = this.lastDoc; + + symbol = new JSDOC.Symbol(name, params, "OBJECT", doc); + if (isInner) symbol.isInner = true; + + + if (doc) JSDOC.Parser.addSymbol(symbol); + } + // foo: {} + else if (this.ts.look(1).is("COLON") && this.ts.look(2).is("LEFT_CURLY")) { + name = (this.namescope.last().alias+"."+name).replace("#.", "#"); + + if (this.lastDoc) doc = this.lastDoc; + + symbol = new JSDOC.Symbol(name, params, "OBJECT", doc); + + + if (doc) JSDOC.Parser.addSymbol(symbol); + + this.namescope.push(symbol); + + var matching = this.ts.getMatchingToken("LEFT_CURLY"); + if (matching) matching.popNamescope = name; + else LOG.warn("Mismatched } character. Can't parse code in file " + symbol.srcFile + "."); + } + // foo: x + else if (this.ts.look(1).is("COLON")) { + name = (this.namescope.last().alias+"."+name).replace("#.", "#");; + + if (this.lastDoc) doc = this.lastDoc; + + symbol = new JSDOC.Symbol(name, params, "OBJECT", doc); + + + if (doc) JSDOC.Parser.addSymbol(symbol); + } + // foo(...) + else if (this.ts.look(1).is("LEFT_PAREN")) { + if (typeof JSDOC.PluginManager != "undefined") { + var functionCall = {name: name}; + + var cursor = this.ts.cursor; + params = JSDOC.Walker.onParamList(this.ts.balance("LEFT_PAREN")); + this.ts.cursor = cursor; + + for (var i = 0; i < params.length; i++) + functionCall["arg" + (i + 1)] = params[i].name; + + JSDOC.PluginManager.run("onFunctionCall", functionCall); + if (functionCall.doc) { + this.ts.insertAhead(new JSDOC.Token(functionCall.doc, "COMM", "JSDOC")); + } + } + } + this.lastDoc = null; + } + else if (this.token.is("FUNCTION")) { // it's an anonymous function + if ( + (!this.ts.look(-1).is("COLON") || !this.ts.look(-1).is("ASSIGN")) + && !this.ts.look(1).is("NAME") + ) { + if (this.lastDoc) doc = this.lastDoc; + + name = "$anonymous"; + name = this.namescope.last().alias+"-"+name + + params = JSDOC.Walker.onParamList(this.ts.balance("LEFT_PAREN")); + + symbol = new JSDOC.Symbol(name, params, "FUNCTION", doc); + + JSDOC.Parser.addSymbol(symbol); + + this.namescope.push(symbol); + + var matching = this.ts.getMatchingToken("LEFT_CURLY"); + if (matching) matching.popNamescope = name; + else LOG.warn("Mismatched } character. Can't parse code in file " + symbol.srcFile + "."); + } + } + } + return true; +} + +/** + Resolves what "this." means when it appears in a name. + @param name The name that starts with "this.". + @returns The name with "this." resolved. + */ +JSDOC.Walker.prototype.resolveThis = function(name) { + name.match(/^this\.(.+)$/) + var nameFragment = RegExp.$1; + if (!nameFragment) return name; + + var symbol = this.namescope.last(); + var scopeType = symbol.scopeType || symbol.isa; + + // if we are in a constructor function, `this` means the instance + if (scopeType == "CONSTRUCTOR") { + name = symbol.alias+"#"+nameFragment; + } + + // if we are in an anonymous constructor function, `this` means the instance + else if (scopeType == "INSTANCE") { + name = symbol.alias+"."+nameFragment; + } + + // if we are in a function, `this` means the container (possibly the global) + else if (scopeType == "FUNCTION") { + // in a method of a prototype, so `this` means the constructor + if (symbol.alias.match(/(^.*)[#.-][^#.-]+/)) { + var parentName = RegExp.$1; + var parent = JSDOC.Parser.symbols.getSymbol(parentName); + + if (!parent) { + if (JSDOC.Lang.isBuiltin(parentName)) parent = JSDOC.Parser.addBuiltin(parentName); + else { + if (symbol.alias.indexOf("$anonymous") < 0) // these will be ignored eventually + LOG.warn("Trying to document "+symbol.alias+" without first documenting "+parentName+"."); + } + } + if (parent) name = parentName+(parent.is("CONSTRUCTOR")?"#":".")+nameFragment; + } + else { + parent = this.namescope.last(1); + name = parent.alias+(parent.is("CONSTRUCTOR")?"#":".")+nameFragment; + } + } + // otherwise it means the global + else { + name = nameFragment; + } + + return name; +} + +JSDOC.Walker.onParamList = function(/**Array*/paramTokens) { + if (!paramTokens) { + LOG.warn("Malformed parameter list. Can't parse code."); + return []; + } + var params = []; + for (var i = 0, l = paramTokens.length; i < l; i++) { + if (paramTokens[i].is("JSDOC")) { + var paramType = paramTokens[i].data.replace(/(^\/\*\* *| *\*\/$)/g, ""); + + if (paramTokens[i+1] && paramTokens[i+1].is("NAME")) { + i++; + params.push({type: paramType, name: paramTokens[i].data}); + } + } + else if (paramTokens[i].is("NAME")) { + params.push({name: paramTokens[i].data}); + } + } + return params; +} diff --git a/bin/jsdoc/main.js b/bin/jsdoc/main.js new file mode 100644 index 00000000..f9008c87 --- /dev/null +++ b/bin/jsdoc/main.js @@ -0,0 +1,111 @@ +/** + * @version $Id: main.js 818 2009-11-08 14:51:41Z micmath $ + */ + +function main() { + IO.include("lib/JSDOC.js"); + IO.includeDir("plugins/"); + + // process the options + + // the -c option: options are defined in a configuration file + if (JSDOC.opt.c) { + eval("JSDOC.conf = " + IO.readFile(JSDOC.opt.c)); + + LOG.inform("Using configuration file at '"+JSDOC.opt.c+"'."); + + for (var c in JSDOC.conf) { + if (c !== "D" && !defined(JSDOC.opt[c])) { // commandline overrules config file + JSDOC.opt[c] = JSDOC.conf[c]; + } + } + + if (typeof JSDOC.conf["_"] != "undefined") { + JSDOC.opt["_"] = JSDOC.opt["_"].concat(JSDOC.conf["_"]); + } + + LOG.inform("With configuration: "); + for (var o in JSDOC.opt) { + LOG.inform(" "+o+": "+JSDOC.opt[o]); + } + } + + // be verbose + if (JSDOC.opt.v) LOG.verbose = true; + + // send log messages to a file + if (JSDOC.opt.o) LOG.out = IO.open(JSDOC.opt.o); + + // run the unit tests + if (JSDOC.opt.T) { + LOG.inform("JsDoc Toolkit running in test mode at "+new Date()+"."); + IO.include("frame/Testrun.js"); + IO.include("test.js"); + } + else { + // a template must be defined and must be a directory path + if (!JSDOC.opt.t && System.getProperty("jsdoc.template.dir")) { + JSDOC.opt.t = System.getProperty("jsdoc.template.dir"); + } + if (JSDOC.opt.t && SYS.slash != JSDOC.opt.t.slice(-1)) { + JSDOC.opt.t += SYS.slash; + } + + // verbose messages about the options we were given + LOG.inform("JsDoc Toolkit main() running at "+new Date()+"."); + LOG.inform("With options: "); + for (var o in JSDOC.opt) { + LOG.inform(" "+o+": "+JSDOC.opt[o]); + } + + // initialize and build a symbolSet from your code + JSDOC.JsDoc(); + + // debugger's option: dump the entire symbolSet produced from your code + if (JSDOC.opt.Z) { + LOG.warn("So you want to see the data structure, eh? This might hang if you have circular refs..."); + IO.include("frame/Dumper.js"); + var symbols = JSDOC.JsDoc.symbolSet.toArray(); + for (var i = 0, l = symbols.length; i < l; i++) { + var symbol = symbols[i]; + print("// symbol: " + symbol.alias); + print(symbol.serialize()); + } + } + else { + if (typeof JSDOC.opt.t != "undefined") { + try { + // a file named "publish.js" must exist in the template directory + load(JSDOC.opt.t+"publish.js"); + + // and must define a function named "publish" + if (!publish) { + LOG.warn("No publish() function is defined in that template so nothing to do."); + } + else { + // which will be called with the symbolSet produced from your code + publish(JSDOC.JsDoc.symbolSet); + } + } + catch(e) { + LOG.warn("Sorry, that doesn't seem to be a valid template: "+JSDOC.opt.t+"publish.js : "+e); + } + } + else { + LOG.warn("No template given. Might as well read the usage notes."); + JSDOC.usage(); + } + } + } + + // notify of any warnings + if (!JSDOC.opt.q && LOG.warnings.length) { + print(LOG.warnings.length+" warning"+(LOG.warnings.length != 1? "s":"")+"."); + } + + // stop sending log messages to a file + if (LOG.out) { + LOG.out.flush(); + LOG.out.close(); + } +} \ No newline at end of file diff --git a/bin/jsdoc/plugins/commentSrcJson.js b/bin/jsdoc/plugins/commentSrcJson.js new file mode 100644 index 00000000..e826b572 --- /dev/null +++ b/bin/jsdoc/plugins/commentSrcJson.js @@ -0,0 +1,20 @@ +JSDOC.PluginManager.registerPlugin( + "JSDOC.commentSrcJson", + { + onDocCommentSrc: function(comment) { + var json; + if (/^\s*@json\b/.test(comment)) { + comment.src = new String(comment.src).replace("@json", ""); + + eval("json = "+comment.src); + var tagged = ""; + for (var i in json) { + var tag = json[i]; + // todo handle cases where tag is an object + tagged += "@"+i+" "+tag+"\n"; + } + comment.src = tagged; + } + } + } +); \ No newline at end of file diff --git a/bin/jsdoc/plugins/frameworkPrototype.js b/bin/jsdoc/plugins/frameworkPrototype.js new file mode 100644 index 00000000..9c417518 --- /dev/null +++ b/bin/jsdoc/plugins/frameworkPrototype.js @@ -0,0 +1,16 @@ +JSDOC.PluginManager.registerPlugin( + "JSDOC.frameworkPrototype", + { + onPrototypeClassCreate: function(classCreator) { + var desc = ""; + if (classCreator.comment) { + desc = classCreator.comment; + } + var insert = desc+"/** @name "+classCreator.name+"\n@constructor\n@scope "+classCreator.name+".prototype */" + + insert = insert.replace(/\*\/\/\*\*/g, "\n"); + /*DEBUG*///print("insert is "+insert); + classCreator.addComment.data = insert; + } + } +); diff --git a/bin/jsdoc/plugins/functionCall.js b/bin/jsdoc/plugins/functionCall.js new file mode 100644 index 00000000..6f87705e --- /dev/null +++ b/bin/jsdoc/plugins/functionCall.js @@ -0,0 +1,10 @@ +JSDOC.PluginManager.registerPlugin( + "JSDOC.functionCall", + { + onFunctionCall: function(functionCall) { + if (functionCall.name == "dojo.define" && functionCall.arg1) { + functionCall.doc = "/** @lends "+eval(functionCall.arg1)+".prototype */"; + } + } + } +); \ No newline at end of file diff --git a/bin/jsdoc/plugins/publishSrcHilite.js b/bin/jsdoc/plugins/publishSrcHilite.js new file mode 100644 index 00000000..65514f2c --- /dev/null +++ b/bin/jsdoc/plugins/publishSrcHilite.js @@ -0,0 +1,62 @@ +JSDOC.PluginManager.registerPlugin( + "JSDOC.publishSrcHilite", + { + onPublishSrc: function(src) { + if (src.path in JsHilite.cache) { + return; // already generated src code + } + else JsHilite.cache[src.path] = true; + + try { + var sourceCode = IO.readFile(src.path); + } + catch(e) { + print(e.message); + quit(); + } + + var hiliter = new JsHilite(sourceCode, src.charset); + src.hilited = hiliter.hilite(); + } + } +); + +function JsHilite(src, charset) { + + var tr = new JSDOC.TokenReader(); + + tr.keepComments = true; + tr.keepDocs = true; + tr.keepWhite = true; + + this.tokens = tr.tokenize(new JSDOC.TextStream(src)); + + // TODO is redefining toString() the best way? + JSDOC.Token.prototype.toString = function() { + return ""+this.data.replace(/"; + } + + if (!charset) charset = "utf-8"; + + this.header = ' '+ + "

";
+	this.footer = "
"; + this.showLinenumbers = true; +} + +JsHilite.cache = {}; + +JsHilite.prototype.hilite = function() { + var hilited = this.tokens.join(""); + var line = 1; + if (this.showLinenumbers) hilited = hilited.replace(/(^|\n)/g, function(m){return m+""+((line<10)? " ":"")+((line<100)? " ":"")+(line++)+" "}); + + return this.header+hilited+this.footer; +} \ No newline at end of file diff --git a/bin/jsdoc/plugins/symbolLink.js b/bin/jsdoc/plugins/symbolLink.js new file mode 100644 index 00000000..c87f1ca7 --- /dev/null +++ b/bin/jsdoc/plugins/symbolLink.js @@ -0,0 +1,10 @@ +JSDOC.PluginManager.registerPlugin( + "JSDOC.symbolLink", + { + onSymbolLink: function(link) { + // modify link.linkPath (the href part of the link) + // or link.linkText (the text displayed) + // or link.linkInner (the #name part of the link) + } + } +); \ No newline at end of file diff --git a/bin/jsdoc/plugins/tagParamConfig.js b/bin/jsdoc/plugins/tagParamConfig.js new file mode 100644 index 00000000..3ea8a1be --- /dev/null +++ b/bin/jsdoc/plugins/tagParamConfig.js @@ -0,0 +1,31 @@ +JSDOC.PluginManager.registerPlugin( + "JSDOC.tagParamConfig", + { + onDocCommentTags: function(comment) { + var currentParam = null; + var tags = comment.tags; + for (var i = 0, l = tags.length; i < l; i++) { + + if (tags[i].title == "param") { + if (tags[i].name.indexOf(".") == -1) { + currentParam = i; + } + } + else if (tags[i].title == "config") { + tags[i].title = "param"; + if (currentParam == null) { + tags[i].name = "arguments"+"."+tags[i].name; + } + else if (tags[i].name.indexOf(tags[currentParam].name+".") != 0) { + tags[i].name = tags[currentParam].name+"."+tags[i].name; + } + currentParam != null + //tags[currentParam].properties.push(tags[i]); + } + else { + currentParam = null; + } + } + } + } +); diff --git a/bin/jsdoc/plugins/tagSynonyms.js b/bin/jsdoc/plugins/tagSynonyms.js new file mode 100644 index 00000000..49a874f1 --- /dev/null +++ b/bin/jsdoc/plugins/tagSynonyms.js @@ -0,0 +1,43 @@ +JSDOC.PluginManager.registerPlugin( + "JSDOC.tagSynonyms", + { + onDocCommentSrc: function(comment) { + comment.src = comment.src.replace(/@methodOf\b/i, "@function\n@memberOf"); + comment.src = comment.src.replace(/@fieldOf\b/i, "@field\n@memberOf"); + }, + + onDocCommentTags: function(comment) { + for (var i = 0, l = comment.tags.length; i < l; i++) { + var title = comment.tags[i].title.toLowerCase(); + var syn; + if ((syn = JSDOC.tagSynonyms.synonyms["="+title])) { + comment.tags[i].title = syn; + } + } + } + } +); + +new Namespace( + "JSDOC.tagSynonyms", + function() { + JSDOC.tagSynonyms.synonyms = { + "=member": "memberOf", + "=memberof": "memberOf", + "=description": "desc", + "=exception": "throws", + "=argument": "param", + "=returns": "return", + "=classdescription": "class", + "=fileoverview": "overview", + "=extends": "augments", + "=base": "augments", + "=projectdescription": "overview", + "=classdescription": "class", + "=link": "see", + "=borrows": "inherits", + "=scope": "lends", + "=construct": "constructor" + } + } +); \ No newline at end of file diff --git a/bin/jsdoc/run.js b/bin/jsdoc/run.js new file mode 100644 index 00000000..1f875cdb --- /dev/null +++ b/bin/jsdoc/run.js @@ -0,0 +1,348 @@ +/** + * @fileOverview + * A bootstrap script that creates some basic required objects + * for loading other scripts. + * @author Michael Mathews, micmath@gmail.com + * @version $Id: run.js 756 2009-01-07 21:32:58Z micmath $ + */ + +/** + * @namespace Keep track of any messages from the running script. + */ +LOG = { + warn: function(msg, e) { + if (JSDOC.opt.q) return; + if (e) msg = e.fileName+", line "+e.lineNumber+": "+msg; + + msg = ">> WARNING: "+msg; + LOG.warnings.push(msg); + if (LOG.out) LOG.out.write(msg+"\n"); + else print(msg); + }, + + inform: function(msg) { + if (JSDOC.opt.q) return; + msg = " > "+msg; + if (LOG.out) LOG.out.write(msg+"\n"); + else if (typeof LOG.verbose != "undefined" && LOG.verbose) print(msg); + } +}; +LOG.warnings = []; +LOG.verbose = false +LOG.out = undefined; + +/** + * @class Manipulate a filepath. + */ +function FilePath(absPath, separator) { + this.slash = separator || "/"; + this.root = this.slash; + this.path = []; + this.file = ""; + + var parts = absPath.split(/[\\\/]/); + if (parts) { + if (parts.length) this.root = parts.shift() + this.slash; + if (parts.length) this.file = parts.pop() + if (parts.length) this.path = parts; + } + + this.path = this.resolvePath(); +} + +/** Collapse any dot-dot or dot items in a filepath. */ +FilePath.prototype.resolvePath = function() { + var resolvedPath = []; + for (var i = 0; i < this.path.length; i++) { + if (this.path[i] == "..") resolvedPath.pop(); + else if (this.path[i] != ".") resolvedPath.push(this.path[i]); + } + return resolvedPath; +} + +/** Trim off the filename. */ +FilePath.prototype.toDir = function() { + if (this.file) this.file = ""; + return this; +} + +/** Go up a directory. */ +FilePath.prototype.upDir = function() { + this.toDir(); + if (this.path.length) this.path.pop(); + return this; +} + +FilePath.prototype.toString = function() { + return this.root + + this.path.join(this.slash) + + ((this.path.length > 0)? this.slash : "") + + this.file; +} + +/** + * Turn a path into just the name of the file. + */ +FilePath.fileName = function(path) { + var nameStart = Math.max(path.lastIndexOf("/")+1, path.lastIndexOf("\\")+1, 0); + return path.substring(nameStart); +} + +/** + * Get the extension of a filename + */ +FilePath.fileExtension = function(filename) { + return filename.split(".").pop().toLowerCase(); +}; + +/** + * Turn a path into just the directory part. + */ +FilePath.dir = function(path) { + var nameStart = Math.max(path.lastIndexOf("/")+1, path.lastIndexOf("\\")+1, 0); + return path.substring(0, nameStart-1); +} + + +importClass(java.lang.System); + +/** + * @namespace A collection of information about your system. + */ +SYS = { + /** + * Information about your operating system: arch, name, version. + * @type string + */ + os: [ + new String(System.getProperty("os.arch")), + new String(System.getProperty("os.name")), + new String(System.getProperty("os.version")) + ].join(", "), + + /** + * Which way does your slash lean. + * @type string + */ + slash: System.getProperty("file.separator")||"/", + + /** + * The path to the working directory where you ran java. + * @type string + */ + userDir: new String(System.getProperty("user.dir")), + + /** + * Where is Java's home folder. + * @type string + */ + javaHome: new String(System.getProperty("java.home")), + + /** + * The absolute path to the directory containing this script. + * @type string + */ + pwd: undefined +}; + +// jsrun appends an argument, with the path to here. +if (arguments[arguments.length-1].match(/^-j=(.+)/)) { + if (RegExp.$1.charAt(0) == SYS.slash || RegExp.$1.charAt(1) == ":") { // absolute path to here + SYS.pwd = new FilePath(RegExp.$1).toDir().toString(); + } + else { // relative path to here + SYS.pwd = new FilePath(SYS.userDir + SYS.slash + RegExp.$1).toDir().toString(); + } + arguments.pop(); +} +else { + print("The run.js script requires you use jsrun.jar."); + quit(); +} + +// shortcut +var File = Packages.java.io.File; + +/** + * @namespace A collection of functions that deal with reading a writing to disk. + */ +IO = { + + /** + * Create a new file in the given directory, with the given name and contents. + */ + saveFile: function(/**string*/ outDir, /**string*/ fileName, /**string*/ content) { + var out = new Packages.java.io.PrintWriter( + new Packages.java.io.OutputStreamWriter( + new Packages.java.io.FileOutputStream(outDir+SYS.slash+fileName), + IO.encoding + ) + ); + out.write(content); + out.flush(); + out.close(); + }, + + /** + * @type string + */ + readFile: function(/**string*/ path) { + if (!IO.exists(path)) { + throw "File doesn't exist there: "+path; + } + return readFile(path, IO.encoding); + }, + + /** + * @param inFile + * @param outDir + * @param [fileName=The original filename] + */ + copyFile: function(/**string*/ inFile, /**string*/ outDir, /**string*/ fileName) { + if (fileName == null) fileName = FilePath.fileName(inFile); + + var inFile = new File(inFile); + var outFile = new File(outDir+SYS.slash+fileName); + + var bis = new Packages.java.io.BufferedInputStream(new Packages.java.io.FileInputStream(inFile), 4096); + var bos = new Packages.java.io.BufferedOutputStream(new Packages.java.io.FileOutputStream(outFile), 4096); + var theChar; + while ((theChar = bis.read()) != -1) { + bos.write(theChar); + } + bos.close(); + bis.close(); + }, + + /** + * Creates a series of nested directories. + */ + mkPath: function(/**Array*/ path) { + if (path.constructor != Array) path = path.split(/[\\\/]/); + var make = ""; + for (var i = 0, l = path.length; i < l; i++) { + make += path[i] + SYS.slash; + if (! IO.exists(make)) { + IO.makeDir(make); + } + } + }, + + /** + * Creates a directory at the given path. + */ + makeDir: function(/**string*/ path) { + (new File(path)).mkdir(); + }, + + /** + * @type string[] + * @param dir The starting directory to look in. + * @param [recurse=1] How many levels deep to scan. + * @returns An array of all the paths to files in the given dir. + */ + ls: function(/**string*/ dir, /**number*/ recurse, _allFiles, _path) { + if (_path === undefined) { // initially + var _allFiles = []; + var _path = [dir]; + } + if (_path.length == 0) return _allFiles; + if (recurse === undefined) recurse = 1; + + dir = new File(dir); + if (!dir.directory) return [String(dir)]; + var files = dir.list(); + + for (var f = 0; f < files.length; f++) { + var file = String(files[f]); + if (file.match(/^\.[^\.\/\\]/)) continue; // skip dot files + + if ((new File(_path.join(SYS.slash)+SYS.slash+file)).list()) { // it's a directory + _path.push(file); + if (_path.length-1 < recurse) IO.ls(_path.join(SYS.slash), recurse, _allFiles, _path); + _path.pop(); + } + else { + _allFiles.push((_path.join(SYS.slash)+SYS.slash+file).replace(SYS.slash+SYS.slash, SYS.slash)); + } + } + + return _allFiles; + }, + + /** + * @type boolean + */ + exists: function(/**string*/ path) { + file = new File(path); + + if (file.isDirectory()){ + return true; + } + if (!file.exists()){ + return false; + } + if (!file.canRead()){ + return false; + } + return true; + }, + + /** + * + */ + open: function(/**string*/ path, /**string*/ append) { + var append = true; + var outFile = new File(path); + var out = new Packages.java.io.PrintWriter( + new Packages.java.io.OutputStreamWriter( + new Packages.java.io.FileOutputStream(outFile, append), + IO.encoding + ) + ); + return out; + }, + + /** + * Sets {@link IO.encoding}. + * Encoding is used when reading and writing text to files, + * and in the meta tags of HTML output. + */ + setEncoding: function(/**string*/ encoding) { + if (/ISO-8859-([0-9]+)/i.test(encoding)) { + IO.encoding = "ISO8859_"+RegExp.$1; + } + else { + IO.encoding = encoding; + } + }, + + /** + * @default "utf-8" + * @private + */ + encoding: "utf-8", + + /** + * Load the given script. + */ + include: function(relativePath) { + load(SYS.pwd+relativePath); + }, + + /** + * Loads all scripts from the given directory path. + */ + includeDir: function(path) { + if (!path) return; + + for (var lib = IO.ls(SYS.pwd+path), i = 0; i < lib.length; i++) + if (/\.js$/i.test(lib[i])) load(lib[i]); + } +} + +// now run the application +IO.include("frame.js"); +IO.include("main.js"); + +main(); diff --git a/bin/jsdoc/t/TestDoc.js b/bin/jsdoc/t/TestDoc.js new file mode 100644 index 00000000..c0768b71 --- /dev/null +++ b/bin/jsdoc/t/TestDoc.js @@ -0,0 +1,144 @@ +var TestDoc = { + fails: 0, + plans: 0, + passes: 0, + results: [] +}; + +TestDoc.record = function(result) { + TestDoc.results.push(result); + if (typeof result.verdict == "boolean") { + if (result.verdict === false) TestDoc.fails++; + if (result.verdict === true) TestDoc.passes++; + } +} + +TestDoc.prove = function(filePath) { + if (typeof document != "undefined" && typeof document.write != "undefined") { + if (TestDoc.console) print = function(s) { TestDoc.console.appendChild(document.createTextNode(s+"\n")); } + else print = function(s) { document.write(s+"
"); } + } + TestDoc.run(TestDoc.readFile(filePath)); +} + +TestDoc.run = function(src) { + try { eval(src); } catch(e) { print("# ERROR! "+e); } + + var chunks = src.split(/\/\*t:/); + + var run = function(chunk) { + // local shortcuts + var is = TestDoc.assertEquals; + var isnt = TestDoc.assertNotEquals; + var plan = TestDoc.plan; + var requires = TestDoc.requires; + + try { eval(chunk); } catch(e) { print("# ERROR! "+e); } + } + for (var start = -1, end = 0; (start = src.indexOf("/*t:", end)) > end; start = end) { + run( + src.substring( + start+4, + (end = src.indexOf("*/", start)) + ) + ); + } +} + +TestDoc.Result = function(verdict, message) { + this.verdict = verdict; + this.message = message; +} + +TestDoc.Result.prototype.toString = function() { + if (typeof this.verdict == "boolean") { + return (this.verdict? "ok" : "not ok") + " " + (++TestDoc.report.counter) + " - " + this.message; + } + + return "# " + this.message; +} + +TestDoc.requires = function(file) { + if (!TestDoc.requires.loaded[file]) { + load(file); + TestDoc.requires.loaded[file] = true; + } +} +TestDoc.requires.loaded = {}; + +TestDoc.report = function() { + TestDoc.report.counter = 0; + print("1.."+TestDoc.plans); + for (var i = 0; i < TestDoc.results.length; i++) { + print(TestDoc.results[i]); + } + print("----------------------------------------"); + if (TestDoc.fails == 0 && TestDoc.passes == TestDoc.plans) { + print("All tests successful."); + } + else { + print("Failed " + TestDoc.fails + "/" + TestDoc.plans + " tests, "+((TestDoc.plans == 0)? 0 : Math.round(TestDoc.passes/(TestDoc.passes+TestDoc.fails)*10000)/100)+"% okay. Planned to run "+TestDoc.plans+", did run "+(TestDoc.passes+TestDoc.fails)+".") + } +} + +TestDoc.plan = function(n, message) { + TestDoc.plans += n; + TestDoc.record(new TestDoc.Result(null, message+" ("+n+" tests)")); +} + +TestDoc.assertEquals = function(a, b, message) { + var result = (a == b); + if (!result) message += "\n#\n# " + a + " does not equal " + b + "\n#"; + TestDoc.record(new TestDoc.Result(result, message)); +} + +TestDoc.assertNotEquals = function(a, b, message) { + var result = (a != b); + if (!result) message += "\n#\n# " + a + " equals " + b + "\n#"; + TestDoc.record(new TestDoc.Result(result, message)); +} + +TestDoc.readFile = (function(){ + // rhino + if (typeof readFile == "function") { + return function(url) { + var text = readFile(url); + return text || ""; + } + } + + // a web browser + else { + return function(url) { + var httpRequest; + + if (window.XMLHttpRequest) { // Mozilla, Safari, etc + httpRequest = new XMLHttpRequest(); + } + else if (window.ActiveXObject) { // IE + try { + httpRequest = new ActiveXObject("Msxml2.XMLHTTP"); + } + catch (e) { + try { + httpRequest = new ActiveXObject("Microsoft.XMLHTTP"); + } + catch (e) { + } + } + } + + if (!httpRequest) { throw "Cannot create HTTP Request."; } + + httpRequest.open('GET', url, false); + httpRequest.send(''); + if (httpRequest.readyState == 4) { + if (httpRequest.status >= 400) { + throw "The HTTP Request returned an error code: "+httpRequest.status; + } + } + + return httpRequest.responseText || ""; + } + } +})(); diff --git a/bin/jsdoc/t/runner.js b/bin/jsdoc/t/runner.js new file mode 100644 index 00000000..3f9fb4c9 --- /dev/null +++ b/bin/jsdoc/t/runner.js @@ -0,0 +1,13 @@ +// try: java -jar ../../jsrun.jar runner.js + +load("TestDoc.js"); + +TestDoc.prove("../frame/Opt.js"); +TestDoc.prove("../lib/JSDOC.js"); +TestDoc.prove("../frame/String.js"); +TestDoc.prove("../lib/JSDOC/DocTag.js"); +TestDoc.prove("../lib/JSDOC/DocComment.js"); +TestDoc.prove("../lib/JSDOC/TokenReader.js"); +TestDoc.prove("../lib/JSDOC/Symbol.js"); + +TestDoc.report(); diff --git a/bin/jsdoc/templates/README.txt b/bin/jsdoc/templates/README.txt new file mode 100755 index 00000000..f593f4aa --- /dev/null +++ b/bin/jsdoc/templates/README.txt @@ -0,0 +1,5 @@ +Codeview is a template for JSDoc Toolkit. With JSDoc Toolkit you can generate a documentation website. + +The Codeview template is, like JSDoc Toolkit itself, published under the X11/MIT License. + +Codeview is Copyright (c) 2010 Wouter Bos (www.thebrightlines.com) \ No newline at end of file diff --git a/bin/jsdoc/templates/allclasses.tmpl b/bin/jsdoc/templates/allclasses.tmpl new file mode 100755 index 00000000..774643ab --- /dev/null +++ b/bin/jsdoc/templates/allclasses.tmpl @@ -0,0 +1,20 @@ +{! Link.base = ""; /* all generated links will be relative to this */ !} +{+subtemplate("subtemplates/head.tmpl", {subtitle: "Class Index"})+} +{+subtemplate("subtemplates/menu.tmpl")+} +
+
+
+

Class Index

+ +
    + +
  • +

    {+(new Link().toSymbol(thisClass.alias))+}

    +

    {+resolveLinks(summarize(thisClass.classDesc))+}

    +
  • +
    +
+
+
+
+{+subtemplate("subtemplates/foot.tmpl")+} diff --git a/bin/jsdoc/templates/allfiles.tmpl b/bin/jsdoc/templates/allfiles.tmpl new file mode 100755 index 00000000..042927a2 --- /dev/null +++ b/bin/jsdoc/templates/allfiles.tmpl @@ -0,0 +1,41 @@ +{! Link.base = ""; /* all generated links will be relative to this */ !} +{+subtemplate("subtemplates/head.tmpl", {subtitle: "File Index"})+} +{+subtemplate("subtemplates/menu.tmpl")+} +
+
+
+

File Index

+ +
    + +
  • +

    {+new Link().toSrc(item.alias).withText(item.name)+}

    + + {+resolveLinks(item.desc)+} + +
    + +
    Author:
    +
    {+item.author+}
    +
    + + +
    Version:
    +
    {+item.version+}
    +
    + + {! var locations = item.comment.getTag('location').map(function($){return $.toString().replace(/(^\$ ?| ?\$$)/g, '').replace(/^HeadURL: https:/g, 'http:');}) !} + +
    Location:
    + +
    {+location+}
    +
    +
    +
    +
  • +
    +
+
+
+
+{+subtemplate("subtemplates/foot.tmpl")+} \ No newline at end of file diff --git a/bin/jsdoc/templates/class.tmpl b/bin/jsdoc/templates/class.tmpl new file mode 100755 index 00000000..276a91b7 --- /dev/null +++ b/bin/jsdoc/templates/class.tmpl @@ -0,0 +1,712 @@ +{! Link.base = "../"; /* all generated links will be relative to this */ !} +{+subtemplate("subtemplates/head.tmpl", {subtitle: data.alias})+} +{+subtemplate("subtemplates/menu.tmpl")+} +
+
+
+
+

+ {! + var classType = ""; + + if (data.isBuiltin()) { + classType += "Built-In "; + } + + if (data.isNamespace) { + if (data.is('FUNCTION')) { + classType += "Function "; + } + classType += "Namespace "; + } else { + classType += "Class "; + } + !} + {+classType+}{+data.alias+} +

+ +
+

+ {+resolveLinks(data.classDesc)+} +

+ + +
    + +
  • Version {+ data.version +}
  • +
    + + {# isn't defined in any file #} +
  • Defined in: {+new Link().toSrc(data.srcFile)+}
  • +
    +
  • Extends + {+ + data.augments + .sort() + .map( + function($) { return new Link().toSymbol($); } + ) + .join(", ") + +}
  • +
    +
+
+
+
+ + +
+
+ + + + + + + + + + + + + + +
{+classType+}Summary
Constructor AttributesConstructor Name and Description
{! + if (data.isPrivate) output += "<private> "; + if (data.isInner) output += "<inner> "; + !}  +
+ {+ new Link().toSymbol(data.alias).inner('constructor')+}{+ makeSignature(data.params) +} +
+
{+resolveLinks(summarize(data.desc))+}
+
+
+
+
+ + + {! var ownProperties = data.properties.filter(function($){return $.memberOf == data.alias && !$.isNamespace}).sort(makeSortby("name")); !} +
+ + + + + + + +
+
+ + +
+ {! var ownMethods = data.methods.filter(function($){return $.memberOf == data.alias && !$.isNamespace}).sort(makeSortby("name")); !} + +
+

Method Summary

+ + + + + + + + +
+
+
+ + + + {! var ownEvents = data.events.filter(function($){return $.memberOf == data.alias && !$.isNamespace}).sort(makeSortby("name")); !} +
+ + + + + + + +
+
+ + +
+
+
+

+ {+classType+}Detail +

+ +
{! + if (data.isPrivate) output += "<private> "; + if (data.isInner) output += "<inner> "; + !} + {+ data.alias +}{+ makeSignature(data.params) +} +
+ +
+ {+resolveLinks(data.desc)+} +
Author: {+data.author+}.
+
+ + + +
{+example+}
+
+
+ + +
+
Parameters:
+ +
+ {+((item.type)?""+("{"+(new Link().toSymbol(item.type)+"} ")) : "")+} {+item.name+} + Optional, Default: {+item.defaultValue+} +
+
{+resolveLinks(item.desc)+}
+
+
+
+ + +
+ +
+ {+resolveLinks(data.deprecated)+} +
+
+ + +
Since:
+
{+ data.since +}
+
+ + +
Throws:
+ +
+ {+((item.type)?"{"+(new Link().toSymbol(item.type))+"} " : "")+} {+item.name+} +
+
{+resolveLinks(item.desc)+}
+
+
+ + +
Returns:
+ +
{+((item.type)?"{"+(new Link().toSymbol(item.type))+"} " : "")+}{+resolveLinks(item.desc)+}
+
+
+ + +
Requires:
+ +
{+ resolveLinks(item) +}
+
+
+ + +
See:
+ +
{+ new Link().toSymbol(item) +}
+
+
+
+
+
+
+
+
+ + +
+
+
+

+ Field Detail +

+ + +
+ + {! + if (member.isPrivate) output += "<private> "; + if (member.isInner) output += "<inner> "; + if (member.isStatic) output += "<static> "; + if (member.isConstant) output += "<constant> "; + !} + + + {{+new Link().toSymbol(member.type)+}} + + {+member.memberOf+}.{+member.name+} +
+ +
+ {+resolveLinks(member.desc)+} + +
+ Defined in: {+new Link().toSrc(member.srcFile)+}. +
+ +
Author: {+member.author+}.
+
+ + + +
{+example+}
+
+
+ +
+ + +
Deprecated:
+
+ {+ resolveLinks(member.deprecated) +} +
+
+ +
Since:
+
{+ member.since +}
+
+ +
See:
+ +
{+ new Link().toSymbol(item) +}
+
+
+ +
Default Value:
+
+ {+resolveLinks(member.defaultValue)+} +
+
+
+
+ +
+
+
+
+
+
+ + +
+
+
+

+ Method Detail +

+ +
    + {! + var methodDetailCount = 0; + !} + +
  • +
    + + {! + if (member.isPrivate) output += "<private> "; + if (member.isInner) output += "<inner> "; + if (member.isStatic) output += "<static> "; + !} + + + {{+new Link().toSymbol(member.type)+}} + + {+member.memberOf+}.{+member.name.replace(/\^\d+$/, '')+}{+makeSignature(member.params)+} +
    + +
    + {+resolveLinks(member.desc)+} + + +
    + Defined in: {+new Link().toSrc(member.srcFile)+}. +
    + +
    Author: {+member.author+}.
    +
    + + + +
    {+example+}
    +
    +
    + + +
    +
    Parameters:
    + +
    + {+((item.type)?"{"+(new Link().toSymbol(item.type))+"} " : "")+}{+item.name+} + Optional, Default: {+item.defaultValue+} +
    +
    {+resolveLinks(item.desc)+}
    +
    +
    +
    + + +
    + + +
    Deprecated:
    +
    + {+ resolveLinks(member.deprecated) +} +
    +
    + + +
    Since:
    +
    {+ member.since +}
    +
    + + +
    Throws:
    + +
    + {+((item.type)?"{"+(new Link().toSymbol(item.type))+"} " : "")+} {+item.name+} +
    +
    {+resolveLinks(item.desc)+}
    +
    +
    + + +
    Returns:
    + +
    {+((item.type)?"{"+(new Link().toSymbol(item.type))+"} " : "")+}{+resolveLinks(item.desc)+}
    +
    +
    + + +
    Requires:
    + +
    {+ resolveLinks(item) +}
    +
    +
    + + +
    See:
    + +
    {+ new Link().toSymbol(item) +}
    +
    +
    + +
    +
    +
    +
  • +
    +
+
+
+
+
+ + + +
+
+
+

+ Event Detail +

+ + +
+ + {! + if (member.isPrivate) output += "<private> "; + if (member.isInner) output += "<inner> "; + if (member.isStatic) output += "<static> "; + !} + + + {{+new Link().toSymbol(member.type)+}} + + {+member.memberOf+}.{+member.name+}{+makeSignature(member.params)+} +
+ +
+ {+resolveLinks(member.desc)+} + + +
+ Defined in: {+new Link().toSrc(member.srcFile)+}. +
+ +
Author: {+member.author+}.
+
+ + + +
{+example+}
+
+
+ + +
+
Parameters:
+ +
+ {+((item.type)?"{"+(new Link().toSymbol(item.type))+"} " : "")+}{+item.name+} + Optional, Default: {+item.defaultValue+} +
+
{+ resolveLinks(item.desc) +}
+
+
+
+ + +
+ +
Deprecated:
+
{+ resolveLinks(member.deprecated) +}
+
+ + +
Since:
+
{+ member.since +}
+
+ + +
Throws:
+ +
+ {+((item.type)?"{"+(new Link().toSymbol(item.type))+"} " : "")+} {+item.name+} +
+
{+ resolveLinks(item.desc) +}
+
+
+ + +
Returns:
+ +
{+((item.type)?"{"+(new Link().toSymbol(item.type))+"} " : "")+}{+resolveLinks(item.desc)+}
+
+
+ + +
Requires:
+ +
{+ resolveLinks(item) +}
+
+
+ + +
See:
+ +
{+ new Link().toSymbol(item) +}
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+ +{+subtemplate("subtemplates/foot.tmpl")+} diff --git a/bin/jsdoc/templates/css/all.css b/bin/jsdoc/templates/css/all.css new file mode 100755 index 00000000..c253cb0d --- /dev/null +++ b/bin/jsdoc/templates/css/all.css @@ -0,0 +1,358 @@ +/* TABLE OF CONTENTS: + * - Browser reset + * - HTML elements + * - JsDoc styling + */ + + + + + + +/* + * BEGIN BROWSER RESET + */ + +body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,p,pre,form,fieldset,input,textarea,p,blockquote,th,td { + margin:0; + padding:0 +} +html { + height:100%; + overflow:-moz-scrollbars-vertical; + overflow-x:auto +} +table { + border:0; + border-collapse:collapse; + border-spacing:0 +} +fieldset,img { + border:0 +} +address,caption,cite,code,dfn,em,strong,th,var { + font-style:normal; + font-weight:normal +} +em,cite { + font-style:italic +} +strong { + font-weight:bold +} +ol,ul { + list-style:none +} +caption,th { + text-align:left +} +h1,h2,h3,h4,h5,h6 { + font-size:100%; + font-weight:normal; + margin:0; + padding:0 +} +q:before,q:after { + content:'' +} +abbr,acronym { + border:0 +} +section,article,header,footer,nav,aside,hgroup { + display:block +} + +/* + * END BROWSER RESET + */ + + + + + + +/* + * HTML ELEMENTS + */ + +@font-face { + font-family: 'M1m'; + src: url('fonts/mplus-1m-regular-webfont.eot'); + src: local('☺'), url('fonts/mplus-1m-regular-webfont.woff') format('woff'), url('fonts/mplus-1m-regular-webfont.ttf') format('truetype'), url('fonts/mplus-1m-regular-webfont.svg#webfontVd14f4NN') format('svg'); + font-weight: normal; + font-style: normal; +} + +@font-face { + font-family: 'M1m'; + src: url('fonts/mplus-1m-bold-webfont.eot'); + src: local('☺'), url('fonts/mplus-1m-bold-webfont.woff') format('woff'), url('fonts/mplus-1m-bold-webfont.ttf') format('truetype'), url('fonts/mplus-1m-bold-webfont.svg#webfontIjI5mZqE') format('svg'); + font-weight: bold; + font-style: normal; +} + + + +* { + line-height: 1.4em; +} + +html { + font-size: 100%; +} + +body { + font-size: 0.75em; + padding: 15px 0; + background: #eee; + background-image: -moz-linear-gradient(left, #dddddd, #f9f9f9) fixed; + background-image: -webkit-gradient(linear,left bottom,right bottom,color-stop(0, #dddddd),color-stop(1, #f9f9f9)) fixed; + } + +body, +input, +select, +textarea { + color: #000; + font-family: Arial, Geneva, sans-serif; +} + +a:link, +a:hover, +a:active, +a:visited { + color: #19199e; +} +a:hover, +a:focus { + color: #00f; + text-decoration: none; +} + +p { + margin: 0 0 1.5em 0; +} + +/* + * END HTML ELEMENTS + */ + + + +/* + * BEGIN HACK + */ + +div.containerMain:after, +div.safeBox:after { + content:""; + display:block; + height:0; + clear:both; +} + +/* + * END HACK + */ + + + +/* + * BEGIN JSDOC + */ + +/* Start menu */ +div.index *.heading1 { + margin-bottom: 0.5em; + border-bottom: 1px solid #999999; + font-family: M1m, Arial, sans-serif; + font-size: 1.6em; + letter-spacing: 1px; + line-height: 1.3em; +} + +div.index div.menu { + background-color: #FFFFFF; +} +*+html div.index div.menu { + background-color: #FFFFFF; +} +* html div.index div.menu { + background-color: #FFFFFF; +} + +div.index div.menu div { + text-align: left; +} + +div.index div.menu a { + text-decoration: none; +} +div.index div.menu a:hover { + text-decoration: underline; +} + +div.index ul.classList { + padding-left: 0; +} + +div.index ul.classList a { + display: block; + margin: 1px 0; + padding: 4px 0 2px 10px; + text-indent: -10px; +} + +div.index div.fineprint { + color: #777; + font-size: 0.9em; +} +div.index div.fineprint a { + color: #777; +} +/* End menu */ + + + +/* Start content */ +div.content ul { + padding-left: 0; +} + +div.content *.classTitle { + font-size: 1.2em; + font-weight: bold; + line-height: 1em; +} + +div.content *.classTitle span { + display: block; + font-size: 2em; + letter-spacing: 2px; + line-height: 1em; + padding-top: 5px; + text-shadow: 1px 1px 1px #999999; + word-wrap: break-word; +} + +div.content p.summary { + font-size: 1.25em; +} + +div.content ul *.classname a, +div.content ul *.filename a { + font-family: Consolas, "Courier New", Courier, monospace; + text-decoration: none; + font-weight: bold; +} +div.content ul *.classname a:hover, +div.content ul *.filename a:hover { + text-decoration: underline; +} + +div.content div.props { + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + border-radius: 5px; + background: #fff; + background: -moz-linear-gradient(top, rgba(255, 255, 255, 0.7), rgba(255, 255, 255, 0.2)); /* FF3.6 */ + background: -webkit-gradient(linear,left top,left bottom,color-stop(0, rgba(255, 255, 255, 0.7)),color-stop(1, rgba(255, 255, 255, 0.2))); + -moz-box-shadow: 0px 0px 10px #ccc; + -webkit-box-shadow: 0px 0px 5px #bbb; + box-shadow: 0px 0px 5px #bbb; +} + + + +*.sectionTitle { + font-family: M1m, sans-serif; + font-size: 1.6em; + letter-spacing: 1px; +} + +table.summaryTable td, +table.summaryTable th { + vertical-align: top; +} +table.summaryTable tr:last-child td { + padding-bottom: 0; +} + +table.summaryTable th { + font-weight: bold; +} + +table.summaryTable td.attributes { + font-family: Consolas, "Courier New", Courier, monospace; + color: #666; +} + +table.summaryTable td.nameDescription div.fixedFont { + font-weight: bold; +} + +table.summaryTable div.description { + color: #333; +} + + + +dl.detailList dt { + font-weight: bold; +} + +dl.inheritsList dd + dt { + margin-top: 10px; +} + +dl.inheritsList dd { + display: inline; +} + + + +.fixedFont { + font-family: Consolas, "Courier New", Courier, monospace; +} + +.fixedFont.heading { + font-size: 1.25em; + line-height: 1.1em +} + +.fixedFont.heading + .description { + font-size: 1.2em; +} + +.fixedFont.heading .light, +.fixedFont.heading .lighter { + font-weight: bold; +} + +pre.code { + overflow: auto; + font-family: Consolas, "Courier New", Courier, monospace; + background: #eee; +} +/* Start content */ + + + +/* Start general styles */ +.light { + color: #666; +} + +.lighter { + color: #999; +} + +span.break { + font-size: 1px; + line-height: 1px; +} +/* End general styles */ + +/* + * END JSDOC + */ diff --git a/bin/jsdoc/templates/css/fonts/mplus-1m-bold-webfont.eot b/bin/jsdoc/templates/css/fonts/mplus-1m-bold-webfont.eot new file mode 100755 index 0000000000000000000000000000000000000000..6c64f8d71d2dc6a375c4305c90921ec5359d72cd GIT binary patch literal 18590 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 literal 0 HcmV?d00001 diff --git a/bin/jsdoc/templates/css/fonts/mplus-1m-bold-webfont.svg b/bin/jsdoc/templates/css/fonts/mplus-1m-bold-webfont.svg new file mode 100755 index 00000000..51295128 --- /dev/null +++ b/bin/jsdoc/templates/css/fonts/mplus-1m-bold-webfont.svg @@ -0,0 +1,134 @@ + + + + +This is a custom SVG webfont generated by Font Squirrel. +Foundry URL : http://mplus-fonts.sourceforge.jp + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/bin/jsdoc/templates/css/fonts/mplus-1m-bold-webfont.ttf b/bin/jsdoc/templates/css/fonts/mplus-1m-bold-webfont.ttf new file mode 100755 index 0000000000000000000000000000000000000000..0cf54cbbef86edd4a4ed0f9749baa373503e6854 GIT binary patch literal 18428 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%0AC(?{gh&L` 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.{ zVmBk|B^IAJF{~8BLODUdfvJbn3D3ctPSqn^qeZHSb#c@ot^xZ7t>3<-GrFLCU+;>h zmd3`GrWL*W+80DSd9xHc>th9T3vd2?f{9|x8>Jw8_FutgcQTk~T6qo5Xwqhq?HK}&IN=nM z!P8)UIOQIkB8x@&EH3<9pq*#{#MdH(ZKzLUEn??_C2i@p*~VU)y)T`s%hQh-i!$dN z!I!QgD^v&rcw=H0eX=Jk784hJx@4WXVjw84ne!AS5MO5nj*U{9SXBVcVV#kTc8j#V zn{>~TD|p-_aY`K%p@d~cnw!!?Is+S~Ws27sSbYsc`9lUc51o&FU~qhV`~#M$G5hs7#zAB9HY|+9E8Ps=oQ~t*h{-Ke zZq_^2>rWF2})o%N3w22_G0^k=f;Oh@8gGxrS*-XoNAm+ z-zeu}zW*%q)FMxUuREJi#A$3dzV4(pF6UkozBiH^m~!oF+)I1*0robgNXxjF(KGN{ zrXNTbaj%vC68}hol~yxjo?$aTbu3u(<88jVzhX6}w{hj8|5kwIT7~Hc_%e~h|44Kf ze|XQd~FSZJ7 zIc#ItwqknDxOp*z`^BrtdHq}Y8r*>@Re~59*;=H_v#bf^! z8xdi&?Zoypwr24TwVAeZTd-aR^Fgnt8Y914Jd5{n4E;jvssFc&J<0d;A4w0HHkl5Y z9y1k9|6op-=bH!2T^BmdfT0HZ+5@ve&5sN+2eV|^Kk0}@Yl7E)} zPX8JIMgOk@!N7^YTfzF^c<@J|nV~O-ejKh39}J%fzY$pynTUKRS`i(KJ|9cO4#vJ2 zyI9d(@#%^eD?X^)Q~6NkFRNPc->Ir|zvsVKt9}}n;uZ1P@kQ}n@rn4C#D8B!&uJbV zVJ%n%6NOcxe@{cg+6V0Ly|w=DTi6kK;>hg4lS{Da$26yCeK=j0aJ>jM%-ph6)NwxW@4a|89n}hY=^N__{z`B957hwdJU>thT zi{)$u#$**VVhu)W9Y$$A#%Uu)=vKCwZDD<^AKd>Z*Z{i?k?b~h2O9+4bDEnFGg!El z+qj)OxRblMn|rvI`?!qk-6Z=a`xYy*Z?He(3iq=Uwoi`iZEaoHYV4QLKG)hR&arPZ z&U3~-Z|r9o`*vgBVeC7N{cL03W$YK~`!=K8Hly5JkAA%!t3aRU*B(^)=h-UN-rJ{f sezITdp??!ZmGKXX1UKN|GyQS=10Dl?$dM+Ns;0~mu3Geiel?i+S6FInOaK4? literal 0 HcmV?d00001 diff --git a/bin/jsdoc/templates/css/fonts/mplus-1m-bold-webfont.woff b/bin/jsdoc/templates/css/fonts/mplus-1m-bold-webfont.woff new file mode 100755 index 0000000000000000000000000000000000000000..f90475d890f59f3dc11bd651aac3859e148d3499 GIT binary patch literal 11772 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%0A{fAkNLr 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 + + + +This is a custom SVG webfont generated by Font Squirrel. +Foundry URL : http://mplus-fonts.sourceforge.jp + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/bin/jsdoc/templates/css/fonts/mplus-1m-regular-webfont.ttf b/bin/jsdoc/templates/css/fonts/mplus-1m-regular-webfont.ttf new file mode 100755 index 0000000000000000000000000000000000000000..684abfd19f9d3fb00e02c8accb576edd2798383d GIT binary patch literal 19344 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 literal 0 HcmV?d00001 diff --git a/bin/jsdoc/templates/css/handheld.css b/bin/jsdoc/templates/css/handheld.css new file mode 100755 index 00000000..073c0d1d --- /dev/null +++ b/bin/jsdoc/templates/css/handheld.css @@ -0,0 +1,217 @@ +/* + * TABLE OF CONTENTS: + * - Browser reset + * - HTML elements + * - JsDoc styling + * - Media query check + */ + + + + + + +/* + * HTML ELEMENTS + */ + +body { + padding: 1% 4% 1% 4%; +} + +/* + * HTML ELEMENTS + */ + + + + + +/* + * BEGIN JSDOC + */ + +/* Start menu */ +div.index div.menu { + position: fixed; + top: 0; + right: 0; + -moz-border-radius-bottomleft: 15px; + -webkit-border-bottom-left-radius: 15px; + -border-bottom-left-radius: 15px; + padding: 4px 5px 8px 10px; + -moz-box-shadow: 0px 0px 10px #c4c4c4; + -webkit-box-shadow: 0px 0px 10px #c4c4c4; + box-shadow: 0px 0px 10px #c4c4c4; + background-color: rgba(255, 255, 255, 0.9); +} + +div.index input.classFilter { + display: none; +} + +div.index div.indexLinks a { + float: right; + clear: both; + font-size: 1.1em; +} + +div.index *.heading1 { + display:none; +} + +div.index ul.classList { + display:none; +} + +div.index div.fineprint { + display:none; +} + +div.indexStatic { + display: none; +} +/* End menu */ + + + +/* Start content */ +div.content *.classTitle { + margin-right: 60px; + margin-bottom: 15px; +} + +div.content div.intro { + margin: 15px 0 35px; +} + +div.content p.description.summary { + margin-bottom: 0.2em; +} + +div.content div.props { + margin: 1.5em -2% 0 -2%; + padding: 2%; +} + +table.summaryTable { + position: relative; + left: -10px; + width: 100%; + border-collapse: collapse; + box-sizing: content-box; + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; + -ms-box-sizing: content-box; + -o-box-sizing: content-box; + -icab-box-sizing: content-box; + -khtml-box-sizing: content-box; +} + +*.sectionTitle { + padding: 0 10px 10px 0; +} +caption.sectionTitle { + padding-left: 10px; +} + +table.summaryTable td, +table.summaryTable th { + padding: 0px 10px 10px 10px; +} +table.summaryTable tr:last-child td { + padding-bottom: 0; +} + +table.summaryTable td.attributes { + width: 35%; +} + +table.summaryTable td.nameDescription { + width: 65% +} + + + +dl.detailList { + margin-top: 0.5em; +} + +dl.detailList.nomargin + dl.detailList.nomargin { + margin-top: 0; +} + +dl.detailList dt { + display: inline; + margin-right: 5px; +} + +dl.detailList dt:before { + display: block; + content: ""; +} + +dl.detailList dd { + display: inline; +} + +dl.detailList.params dt { + display: block; +} +dl.detailList.params dd { + display: block; + padding-left: 2em; + padding-bottom: 0.4em; +} + + + + +ul.fileList li { + margin-bottom: 1.5em; +} + + + +.fixedFont.heading { + margin-bottom: 0.5em; +} + +pre.code { + margin: 10px 0 10px 0; + padding: 10px; + border: 1px solid #ccc; + -moz-border-radius: 2px; + -webkit-border-radius: 2px; + border-radius: 2px; +} +/* End content */ + +/* + * END JSDOC + */ + + + + + + + +/* + * START MEDIA QUERY CHECK + */ + +.cssLoadCheck { + position: absolute; + top: -99999px; + left: -99999px; + border: 0; + width: 100px; + padding: 0; + overflow: hidden; +} + +/* + * END MEDIA QUERY CHECK + */ + diff --git a/bin/jsdoc/templates/css/screen.css b/bin/jsdoc/templates/css/screen.css new file mode 100755 index 00000000..8cb4bba3 --- /dev/null +++ b/bin/jsdoc/templates/css/screen.css @@ -0,0 +1,297 @@ +/* + * TABLE OF CONTENTS: + * - JsDoc styling + * - Media query check + */ + + + + + + +/* + * BEGIN JSDOC + */ + +/* Start menu */ +div.index { + position: fixed; + top: 0; + bottom: 0; + float: left; + width: 30%; + min-width: 100px; + max-width: 300px; + padding: 0 0 10px 0; + overflow: auto; +} + +div.index *.heading1 { + padding: 8px 0 0 0; +} + +div.index div.menu { + margin: 0 15px 0 -15px; + -moz-border-radius-bottomright: 15px; + -webkit-border-bottom-right-radius: 15px; + -border-bottom-right-radius: 15px; + padding: 15px 15px 15px 30px; + -moz-box-shadow: 0px 0px 10px #c4c4c4; + -webkit-box-shadow: 0px 0px 10px #c4c4c4; + box-shadow: 0px 0px 10px #c4c4c4; + background-color: rgba(255, 255, 255, 0.5); +} + +div.index div.indexLinks { + margin-top: 13px; + position: absolute; + right: 30px; +} + +div.index div.indexLinks a { + color: #999999; + text-transform: lowercase; +} + +div.index div.indexLinks a:first-child { + margin-right: 3px; + border-right: 1px solid #999999; + padding-right: 5px; +} + +div.index input.classFilter { + margin-bottom: 4px; + width: 100%; + border-width: 1px; + border-style: solid; + border-color: #CCCCCC #999999 #999999 #CCCCCC; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + -border-radius: 3px; +} + +div.index ul.classList a { + line-height: 1.3em; +} + +div.index ul.classList a + a { + margin-left: 0.5em; +} + +div.index div.fineprint { + margin: 1em 0 0 15px; + color: #777; + font-size: 0.9em; +} + +div.index div.fineprint a { + color: #777; +} + +div.indexStatic { + position: static; + min-height: 1em; +} +/* End menu */ + + +/* Start content */ +div.content { + float: left; + width: 70%; + min-width: 300px; + max-width: 600px; +} +div.innerContent { + padding: 0 0 0 2.5em; +} + +div.content ul, +div.content ol { + margin-bottom: 3em; +} + +div.content ul.methodDetail { + margin-bottom: 0; +} + +div.content *.classTitle { + position: relative; + left: -10px; + margin: -30px 0 15px 0; + -moz-border-radius: 15px; + -webkit-border-radius: 15px; + border-radius: 15px; + padding: 25px 15px 15px 15px; + background-color: #FFFFFF; + background-color: rgba(255, 255, 255, 0.5); + -moz-box-shadow: 0px 0px 10px #c4c4c4; + -webkit-box-shadow: 0px 0px 10px #c4c4c4; + box-shadow: 0px 0px 10px #c4c4c4; +} + +div.content div.intro { + margin: 15px 0 45px +} + +div.content p.summary { + margin-bottom: 0.5em; +} + +div.content ul.summary { + margin-bottom: 1.5em; +} + +div.content ul *.classname a, +div.content ul *.filename a { + font-family: Consolas, "Courier New", Courier, monospace; + text-decoration: none; + font-weight: bold; +} +div.content ul *.classname a:hover, +div.content ul *.filename a:hover { + text-decoration: underline; +} + +div.content div.props { + position: relative; + left: -10px; + margin-bottom: 2.5em; + padding: 10px 15px 15px 15px; + overflow: hidden; +} + +div.content div.hr { + margin: 0 10px 0 0; + height: 4em; +} + + + +table.summaryTable { + position: relative; + left: -10px; + width: 100%; + border-collapse: collapse; + box-sizing: content-box; + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; + -ms-box-sizing: content-box; + -o-box-sizing: content-box; + -icab-box-sizing: content-box; + -khtml-box-sizing: content-box; +} + +*.sectionTitle { + padding: 0 10px 10px 0; +} +caption.sectionTitle { + padding-left: 10px; +} + +table.summaryTable td, +table.summaryTable th { + padding: 0px 10px 10px 10px; +} +table.summaryTable tr:last-child td { + padding-bottom: 0; +} + +table.summaryTable td.attributes { + width: 35%; +} + +table.summaryTable td.nameDescription { + width: 65% +} + + + +dl.detailList { + margin-top: 0.5em; +} + +dl.detailList.nomargin + dl.detailList.nomargin { + margin-top: 0; +} + +dl.detailList dt { + display: inline; + margin-right: 5px; +} + +dl.detailList dt:before { + display: block; + content: ""; +} + +dl.detailList dd { + display: inline; +} + +dl.detailList.params dt { + display: block; +} +dl.detailList.params dd { + display: block; + padding-left: 2em; + padding-bottom: 0.4em; +} + + + + +ul.fileList li { + margin-bottom: 1.5em; +} + + + +.fixedFont.heading { + margin-bottom: 0.5em; +} + +pre.code { + margin: 10px 0 10px 0; + padding: 10px; + border: 1px solid #ccc; + -moz-border-radius: 2px; + -webkit-border-radius: 2px; + border-radius: 2px; +} +/* End content */ + +.clear { + clear: both; + width: 100%; + min-height: 0; +} + +/* + * END JSDOC + */ + + + + + + + +/* + * START MEDIA QUERY CHECK + */ + +.cssLoadCheck { + position: absolute; + top: -99999px; + left: -99999px; + border: 0; + width: 100px; + padding: 0; + overflow: hidden; +} + +/* + * END MEDIA QUERY CHECK + */ + diff --git a/bin/jsdoc/templates/javascript/all.js b/bin/jsdoc/templates/javascript/all.js new file mode 100755 index 00000000..5b6876af --- /dev/null +++ b/bin/jsdoc/templates/javascript/all.js @@ -0,0 +1,326 @@ +/** + * @fileOverview Contains standard code in the namespace 'wbos' and code specifically written for Codeview in the namespace 'codeview' + * @author Wouter Bos (www.thebrightlines.com) + * @since 1.0 - 2010-09-10 + * @version 1.0 - 2010-09-10 + */ + + + + + + +if (typeof(wbos) == "undefined") { + /** + * @namespace Standard code of Wouter Bos (wbos) + */ + wbos = {} +} +if (typeof(wbos.CssTools) == "undefined") { + /** + * @namespace Namespace for CSS-related functionality + */ + wbos.CssTools = {} +} + + + + +/** + * @namespace Fallback for CSS advanced media query + * @class + * @since 1.0 - 2010-09-10 + * @version 1.0 - 2010-09-10 + */ +wbos.CssTools.MediaQueryFallBack = ( function() { + var config = { + cssScreen: "/css/screen.css", + cssHandheld: "/css/handheld.css", + mobileMaxWidth: 660, + testDivClass: "cssLoadCheck", + dynamicCssLinkId: "DynCssLink", + resizeDelay: 30 + } + var noMediaQuery = false; + var delay; + var currentCssMediaType; + + // Adding events to elements in the DOM without overwriting it + function addEvent(element, newFunction, eventType) { + var oldEvent = eval("element." + eventType); + var eventContentType = eval("typeof element." + eventType) + + if ( eventContentType != 'function' ) { + eval("element." + eventType + " = newFunction") + } else { + eval("element." + eventType + " = function(e) { oldEvent(e); newFunction(e); }") + } + } + + // Get the the inner width of the browser window + function getWindowWidth() { + if (window.innerWidth) { + return window.innerWidth; + } else if (document.documentElement.clientWidth) { + return document.documentElement.clientWidth; + } else if (document.body.clientWidth) { + return document.body.clientWidth; + } else{ + return 0; + } + } + + function addCssLink(cssHref) { + var cssNode = document.createElement('link'); + var windowWidth; + cssNode.type = 'text/css'; + cssNode.rel = 'stylesheet'; + cssNode.media = 'screen, handheld, fallback'; + cssNode.href = cssHref; + document.getElementsByTagName("head")[0].appendChild(cssNode); + } + + + + /* Start public */ + return { + /** + * Adds link to CSS in the head if no CSS is loaded + * + * @since 1.0 - 2010-08-21 + * @version 1.0 - 2010-08-21 + * @param {String|Object} cssScreen URL to CSS file for larger screens + * @param {String|Object} cssHandheld URL to CSS file for smaller screens + * @param {Number} mobileMaxWidth Maximum width for handheld devices + * @example + * wbos.CssTools.MediaQueryFallBack.LoadCss(['screen.css', 'screen2.css'], 'mobile.css', 480) + */ + LoadCss: function(cssScreen, cssHandheld, mobileMaxWidth) { + // Set config values + if (typeof(cssScreen) != "undefined") { + config.cssScreen = cssScreen; + } + if (typeof(cssHandheld) != "undefined") { + config.cssHandheld = cssHandheld; + } + if (typeof(mobileMaxWidth) != "undefined") { + config.mobileMaxWidth = mobileMaxWidth; + } + + // Check if CSS is loaded + var cssloadCheckNode = document.createElement('div'); + cssloadCheckNode.className = config.testDivClass; + document.getElementsByTagName("body")[0].appendChild(cssloadCheckNode); + if (cssloadCheckNode.offsetWidth != 100 && noMediaQuery == false) { + noMediaQuery = true; + } + cssloadCheckNode.parentNode.removeChild(cssloadCheckNode) + + if (noMediaQuery == true) { + // Browser does not support Media Queries, so JavaScript will supply a fallback + var cssHref = ""; + + // Determines what CSS file to load + if (getWindowWidth() <= config.mobileMaxWidth) { + cssHref = config.cssHandheld; + newCssMediaType = "handheld"; + } else { + cssHref = config.cssScreen; + newCssMediaType = "screen"; + } + + // Add CSS link to of page + if (cssHref != "" && currentCssMediaType != newCssMediaType) { + var currentCssLinks = document.styleSheets + for (var i = 0; i < currentCssLinks.length; i++) { + for (var ii = 0; ii < currentCssLinks[i].media.length; ii++) { + if (typeof(currentCssLinks[i].media) == "object") { + if (currentCssLinks[i].media.item(ii) == "fallback") { + currentCssLinks[i].ownerNode.parentNode.removeChild(currentCssLinks[i].ownerNode) + i-- + break; + } + } else { + if (currentCssLinks[i].media.indexOf("fallback") >= 0) { + currentCssLinks[i].owningElement.parentNode.removeChild(currentCssLinks[i].owningElement) + i-- + break; + } + } + } + } + if (typeof(cssHref) == "object") { + for (var i = 0; i < cssHref.length; i++) { + addCssLink(cssHref[i]) + } + } else { + addCssLink(cssHref) + } + + currentCssMediaType = newCssMediaType; + } + + + // Check screen size again if user resizes window + addEvent(window, wbos.CssTools.MediaQueryFallBack.LoadCssDelayed, 'onresize') + } + }, + + /** + * Runs LoadCSS after a short delay + * + * @since 1.0 - 2010-08-21 + * @version 1.0 - 2010-08-21 + * @example + * wbos.CssTools.MediaQueryFallBack.LoadCssDelayed() + */ + LoadCssDelayed: function() { + clearTimeout(delay); + delay = setTimeout( "wbos.CssTools.MediaQueryFallBack.LoadCss()", config.resizeDelay) + } + + } + /* End public */ +})(); + + + + + + +/** + * @namespace Adds a function to an event of a single element. Use this if + * you don't want to use jQuery + * @class + * @since 1.0 - 2010-02-23 + * @version 1.0 - 2010-02-23 + */ +wbos.Events = ( function() { + /* Start public */ + return { + /** + * Adds a function to an event of a single element + * + * @since 1.0 - 2010-02-23 + * @version 1.0 - 2010-02-23 + * @param {Object} element The element on which the event is placed + * @param {Function} newFunction The function that has to be linked to the event + * @param {String} eventType Name of the event + * @example + * wbos.Events.AddEvent( document.getElementById('elementId'), functionName, "onclick" ) + */ + AddEvent: function( element, newFunction, eventType ) { + var oldEvent = eval("element." + eventType); + var eventContentType = eval("typeof element." + eventType) + + if ( eventContentType != 'function' ) { + eval("element." + eventType + " = newFunction") + } else { + eval("element." + eventType + " = function(e) { oldEvent(e); newFunction(e); }") + } + } + } + /* End public */ +})(); + + + + + + +if (typeof(codeview) == "undefined") { + /** + * @namespace Code written for the Codeview template + */ + codeview = {} +} + + + + + + + +/** + * @namespace Enables filtering in class lists + * @class + * @since 1.0 - 2010-11-08 + * @version 1.0 - 2010-11-08 + */ +codeview.classFilter = ( function() { + function onkeyup_ClassFilter() { + var listItems + var search = document.getElementById('ClassFilter').value + search = search.toLowerCase() + if (document.getElementById('ClassList')) { + listItems = document.getElementById('ClassList').getElementsByTagName('li') + filterList(listItems, search) + } + if (document.getElementById('ClassList2')) { + listItems = document.getElementById('ClassList2').getElementsByTagName('li') + filterList(listItems, search) + } + if (document.getElementById('FileList')) { + listItems = document.getElementById('FileList').getElementsByTagName('li') + filterList(listItems, search) + } + if (document.getElementById('MethodsListInherited')) { + var links = document.getElementById('MethodsListInherited').getElementsByTagName('a') + var linksSelected = new Array() + for (var i=0; i < links.length; i++) { + if (links[i].parentNode.parentNode.tagName == "DD") { + linksSelected.push(links[i]) + } + } + filterList(linksSelected, search) + } + if (document.getElementById('MethodsList')) { + listItems = document.getElementById('MethodsList').getElementsByTagName('tbody')[0].getElementsByTagName('tr') + filterList(listItems, search, document.getElementById('MethodDetail').getElementsByTagName('li')) + } + } + + function filterList(listItems, search, relatedElements) { + var itemContent = "" + for (var i=0; i < listItems.length; i++) { + itemContent = listItems[i].textContent||listItems[i].innerText + if (itemContent != undefined) { + itemContent = itemContent.toLowerCase() + itemContent = itemContent.replace(/\s/g, "") + if (itemContent.indexOf(search) >= 0 || itemContent == "") { + listItems[i].style.display = "" + } else { + listItems[i].style.display = "none" + } + if (relatedElements != null) { + filterRelatedList(listItems[i], search, relatedElements) + } + } + } + } + + function filterRelatedList(listItem, search, relatedElements) { + var itemIndex = parseInt(listItem.className.replace('item', '')) + if (itemIndex <= relatedElements.length) { + if (relatedElements[itemIndex].className == "item"+ itemIndex) { + relatedElements[itemIndex].style.display = listItem.style.display + } + } + } + + + + + + /* Start public */ + return { + Init: function() { + wbos.Events.AddEvent( + document.getElementById('ClassFilter'), + onkeyup_ClassFilter, + "onkeyup" + ) + } + } + /* End public */ +})(); diff --git a/bin/jsdoc/templates/javascript/html5.js b/bin/jsdoc/templates/javascript/html5.js new file mode 100755 index 00000000..3587bf73 --- /dev/null +++ b/bin/jsdoc/templates/javascript/html5.js @@ -0,0 +1,6 @@ +// html5shiv MIT @rem remysharp.com/html5-enabling-script +// iepp v1.6.2 MIT @jon_neal iecss.com/print-protector +/*@cc_on(function(m,c){var z="abbr|article|aside|audio|canvas|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video";function n(d){for(var a=-1;++ai";if(g.childNodes.length!==1){var i=z.split("|"),o=i.length,s=RegExp("(^|\\s)("+z+")", +"gi"),t=RegExp("<(/*)("+z+")","gi"),u=RegExp("(^|[^\\n]*?\\s)("+z+")([^\\n]*)({[\\n\\w\\W]*?})","gi"),r=c.createDocumentFragment(),k=c.documentElement;g=k.firstChild;var h=c.createElement("body"),l=c.createElement("style"),f;n(c);n(r);g.insertBefore(l, +g.firstChild);l.media="print";m.attachEvent("onbeforeprint",function(){var d=-1,a=p(c.styleSheets,"all"),e=[],b;for(f=f||c.body;(b=u.exec(a))!=null;)e.push((b[1]+b[2]+b[3]).replace(s,"$1.iepp_$2")+b[4]);for(l.styleSheet.cssText=e.join("\n");++d 1)? + lcAlias+"_"+filemapCounts[lcAlias] : lcAlias; + } + } + + // create each of the class pages + for (var i = 0, l = publish.classes.length; i < l; i++) { + var symbol = publish.classes[i]; + + symbol.events = symbol.getEvents(); // 1 order matters + symbol.methods = symbol.getMethods(); // 2 + + var output = ""; + output = classTemplate.process(symbol); + + IO.saveFile(publish.conf.outDir+publish.conf.symbolsDir, ((JSDOC.opt.u)? Link.filemap[symbol.alias] : symbol.alias) + publish.conf.ext, output); + } + + // create the class index page + try { + var classesindexTemplate = new JSDOC.JsPlate(publish.conf.templatesDir+"allclasses.tmpl"); + } + catch(e) { print(e.message); quit(); } + + var classesIndex = classesindexTemplate.process(publish.classes); + IO.saveFile(publish.conf.outDir, (JSDOC.opt.D.index=="files"?"allclasses":"index")+publish.conf.ext, classesIndex); + classesindexTemplate = classesIndex = classes = null; + + // create the file index page + try { + var fileindexTemplate = new JSDOC.JsPlate(publish.conf.templatesDir+"allfiles.tmpl"); + } + catch(e) { print(e.message); quit(); } + + var documentedFiles = symbols.filter(isaFile); // files that have file-level docs + var allFiles = []; // not all files have file-level docs, but we need to list every one + + for (var i = 0; i < files.length; i++) { + allFiles.push(new JSDOC.Symbol(files[i], [], "FILE", new JSDOC.DocComment("/** */"))); + } + + for (var i = 0; i < documentedFiles.length; i++) { + var offset = files.indexOf(documentedFiles[i].alias); + allFiles[offset] = documentedFiles[i]; + } + + allFiles = allFiles.sort(makeSortby("name")); + + // output the file index page + var filesIndex = fileindexTemplate.process(allFiles); + IO.saveFile(publish.conf.outDir, (JSDOC.opt.D.index=="files"?"index":"files")+publish.conf.ext, filesIndex); + fileindexTemplate = filesIndex = files = null; + + // copy static files + IO.copyFile(publish.conf.templatesDir+"/"+publish.conf.cssDir+"all.css", publish.conf.outDir+"/"+publish.conf.cssDir); + IO.copyFile(publish.conf.templatesDir+"/"+publish.conf.cssDir+"screen.css", publish.conf.outDir+"/"+publish.conf.cssDir); + IO.copyFile(publish.conf.templatesDir+"/"+publish.conf.cssDir+"handheld.css", publish.conf.outDir+"/"+publish.conf.cssDir); + IO.copyFile(publish.conf.templatesDir+"/"+publish.conf.jsDir+"all.js", publish.conf.outDir+"/"+publish.conf.jsDir); + IO.copyFile(publish.conf.templatesDir+"/"+publish.conf.jsDir+"html5.js", publish.conf.outDir+"/"+publish.conf.jsDir); + IO.copyFile(publish.conf.templatesDir+"/"+publish.conf.fontsDir+"mplus-1m-regular-webfont.eot", publish.conf.outDir+"/"+publish.conf.fontsDir); + IO.copyFile(publish.conf.templatesDir+"/"+publish.conf.fontsDir+"mplus-1m-regular-webfont.svg", publish.conf.outDir+"/"+publish.conf.fontsDir); + IO.copyFile(publish.conf.templatesDir+"/"+publish.conf.fontsDir+"mplus-1m-regular-webfont.ttf", publish.conf.outDir+"/"+publish.conf.fontsDir); + IO.copyFile(publish.conf.templatesDir+"/"+publish.conf.fontsDir+"mplus-1m-regular-webfont.woff", publish.conf.outDir+"/"+publish.conf.fontsDir); + IO.copyFile(publish.conf.templatesDir+"/"+publish.conf.fontsDir+"mplus-1m-bold-webfont.eot", publish.conf.outDir+"/"+publish.conf.fontsDir); + IO.copyFile(publish.conf.templatesDir+"/"+publish.conf.fontsDir+"mplus-1m-bold-webfont.svg", publish.conf.outDir+"/"+publish.conf.fontsDir); + IO.copyFile(publish.conf.templatesDir+"/"+publish.conf.fontsDir+"mplus-1m-bold-webfont.ttf", publish.conf.outDir+"/"+publish.conf.fontsDir); + IO.copyFile(publish.conf.templatesDir+"/"+publish.conf.fontsDir+"mplus-1m-bold-webfont.woff", publish.conf.outDir+"/"+publish.conf.fontsDir); } + +/** Include a sub-template in the current template, specifying a data object */ +function subtemplate(template, data) { + try { + return new JSDOC.JsPlate(publish.conf.templatesDir+template).process(data); + } + catch(e) { print(e.message); quit(); } +} + +/** Just the first sentence (up to a full stop). Should not break on dotted variable names. */ +function summarize(desc) { + if (typeof desc != "undefined") + return desc.match(/([\w\W]+?\.)[^a-z0-9_$]/i)? RegExp.$1 : desc; +} + +/** Make a symbol sorter by some attribute. */ +function makeSortby(attribute) { + return function(a, b) { + if (a[attribute] != undefined && b[attribute] != undefined) { + a = a[attribute].toLowerCase(); + b = b[attribute].toLowerCase(); + if (a < b) return -1; + if (a > b) return 1; + return 0; + } + } +} + +function wordwrapNamespace(classLink) { + var classText = classLink.match(/[^<>]+(?=[<])/) + ""; + var classTextNew = classText.replace(/\./g, " . ") + ""; + classLink = classLink.replace(/[^<>]+(?=[<])/, classTextNew); + return classLink; +} + +/** Pull in the contents of an external file at the given path. */ +function include(path) { + var path = publish.conf.templatesDir+path; + return IO.readFile(path); +} + +/** Turn a raw source file into a code-hilited page in the docs. */ +function makeSrcFile(path, srcDir, name) { + if (JSDOC.opt.s) return; + + if (!name) { + name = path.replace(/\.\.?[\\\/]/g, "").replace(/[\\\/]/g, "_"); + name = name.replace(/\:/g, "_"); + } + + var src = {path: path, name:name, charset: IO.encoding, hilited: ""}; + + if (defined(JSDOC.PluginManager)) { + JSDOC.PluginManager.run("onPublishSrc", src); + } + + if (src.hilited) { + IO.saveFile(srcDir, name+publish.conf.ext, src.hilited); + } +} + +/** Build output for displaying function parameters. */ +function makeSignature(params) { + if (!params) return "()"; + var signature = "(" + + + params.filter( + function($) { + return $.name.indexOf(".") == -1; // don't show config params in signature + } + ).map( + function($) { + return $.name; + } + ).join(", ") + + + ")"; + return signature; +} + +/** Find symbol {@link ...} strings in text and turn into html links */ +function resolveLinks(str, from) { + str = str.replace(/\{@link ([^}]+)\}/gi, + function(match, symbolName) { + symbolName = symbolName.trim(); + var index = symbolName.indexOf(' '); + if (index > 0) { + var label = symbolName.substring(index + 1); + symbolName = symbolName.substring(0, index); + return new Link().toSymbol(symbolName).withText(label); + } else { + return new Link().toSymbol(symbolName); + } + } + ); + return str; +} \ No newline at end of file diff --git a/bin/jsdoc/templates/subtemplates/foot.tmpl b/bin/jsdoc/templates/subtemplates/foot.tmpl new file mode 100755 index 00000000..27bc13f0 --- /dev/null +++ b/bin/jsdoc/templates/subtemplates/foot.tmpl @@ -0,0 +1,6 @@ + + + diff --git a/bin/jsdoc/templates/subtemplates/head.tmpl b/bin/jsdoc/templates/subtemplates/head.tmpl new file mode 100755 index 00000000..d823e78f --- /dev/null +++ b/bin/jsdoc/templates/subtemplates/head.tmpl @@ -0,0 +1,22 @@ + + + + + + {+data.subtitle+} | <if test="JSDOC.opt.D.title">{+JSDOC.opt.D.title+}<else />JsDoc Reference</if> + + + + + + + + + + + + + + diff --git a/bin/jsdoc/templates/subtemplates/menu.tmpl b/bin/jsdoc/templates/subtemplates/menu.tmpl new file mode 100755 index 00000000..add1ddd6 --- /dev/null +++ b/bin/jsdoc/templates/subtemplates/menu.tmpl @@ -0,0 +1,43 @@ + + +
diff --git a/bin/jsdoc/test.js b/bin/jsdoc/test.js new file mode 100644 index 00000000..8b2dc8b1 --- /dev/null +++ b/bin/jsdoc/test.js @@ -0,0 +1,342 @@ +load("app/frame/Dumper.js"); +function symbolize(opt) { + symbols = null; + JSDOC.JsDoc(opt); + symbols = JSDOC.JsDoc.symbolSet; +} + +var testCases = [ + function() { + symbolize({a:true, p:true, _: [SYS.pwd+"test/overview.js"]}); + //print(Dumper.dump(symbols)); + is('symbols.getSymbolByName("My Cool Library").name', 'My Cool Library', 'File overview can be found by alias.'); + } + , + function() { + symbolize({_: [SYS.pwd+"test/name.js"]}); + + is('symbols.getSymbol("Response").name', "Response", 'Virtual class name is found.'); + is('symbols.getSymbol("Response#text").alias', "Response#text", 'Virtual method name is found.'); + is('symbols.getSymbol("Response#text").memberOf', "Response", 'Virtual method parent name is found.'); + } + , + function() { + symbolize({a:true, p:true, _: [SYS.pwd+"test/prototype.js"]}); + + is('symbols.getSymbol("Article").name', "Article", 'Function set to constructor prototype with inner constructor name is found.'); + is('symbols.getSymbol("Article").hasMethod("init")', true, 'The initializer method name of prototype function is correct.'); + is('symbols.getSymbol("Article").hasMember("counter")', true, 'A static property set in the prototype definition is found.'); + is('symbols.getSymbol("Article").hasMember("title")', true, 'An instance property set in the prototype is found.'); + is('symbols.getSymbol("Article#title").isStatic', false, 'An instance property has isStatic set to false.'); + is('symbols.getSymbol("Article.counter").name', "counter", 'A static property set in the initializer has the name set correctly.'); + is('symbols.getSymbol("Article.counter").memberOf', "Article", 'A static property set in the initializer has the memberOf set correctly.'); + is('symbols.getSymbol("Article.counter").isStatic', true, 'A static property set in the initializer has isStatic set to true.'); + } + , + function() { + symbolize({a:true, _: [SYS.pwd+"test/prototype_oblit.js"]}); + + is('symbols.getSymbol("Article").name', "Article", 'Oblit set to constructor prototype name is found.'); + is('typeof symbols.getSymbol("Article.prototype")', "undefined", 'The prototype oblit is not a symbol.'); + is('symbols.getSymbol("Article#getTitle").name', "getTitle", 'The nonstatic method name of prototype oblit is correct.'); + is('symbols.getSymbol("Article#getTitle").alias', "Article#getTitle", 'The alias of non-static method of prototype oblit is correct.'); + is('symbols.getSymbol("Article#getTitle").isStatic', false, 'The isStatic of a nonstatic method of prototype oblit is correct.'); + is('symbols.getSymbol("Article.getTitle").name', "getTitle", 'The static method name of prototype oblit is correct.'); + is('symbols.getSymbol("Article.getTitle").isStatic', true, 'The isStatic of a static method of prototype oblit is correct.'); + is('symbols.getSymbol("Article#getTitle").isa', "FUNCTION", 'The isa of non-static method of prototype oblit is correct.'); + is('symbols.getSymbol("Article.getTitle").alias', "Article.getTitle", 'The alias of a static method of prototype oblit is correct.'); + is('symbols.getSymbol("Article.getTitle").isa', "FUNCTION", 'The isa of static method of prototype oblit is correct.'); + } + , + function() { + symbolize({a:true, p:true, _: [SYS.pwd+"test/prototype_oblit_constructor.js"]}); + + is('symbols.getSymbol("Article").name', "Article", 'Oblit set to constructor prototype with inner constructor name is found.'); + is('symbols.getSymbol("Article#init").name', "init", 'The initializer method name of prototype oblit is correct.'); + is('symbols.getSymbol("Article").hasMember("pages")', true, 'Property set by initializer method "this" is on the outer constructor.'); + is('symbols.getSymbol("Article#Title").name', "Title", 'Name of the inner constructor name is found.'); + is('symbols.getSymbol("Article#Title").memberOf', "Article", 'The memberOf of the inner constructor name is found.'); + is('symbols.getSymbol("Article#Title").isa', "CONSTRUCTOR", 'The isa of the inner constructor name is constructor.'); + is('symbols.getSymbol("Article#Title").hasMember("title")', true, 'A property set on the inner constructor "this" is on the inner constructor.'); + } + , + function() { + symbolize({a:true, p:true, _: [SYS.pwd+"test/inner.js"]}); + + is('symbols.getSymbol("Outer").name', "Outer", 'Outer constructor prototype name is found.'); + is('symbols.getSymbol("Outer").methods.length', 1, 'Inner function doesnt appear as a method of the outer.'); + is('symbols.getSymbol("Outer").hasMethod("open")', true, 'Outer constructors methods arent affected by inner function.'); + is('symbols.getSymbol("Outer-Inner").alias', "Outer-Inner", 'Alias of inner function is found.'); + is('symbols.getSymbol("Outer-Inner").isa', "CONSTRUCTOR", 'isa of inner function constructor is found.'); + is('symbols.getSymbol("Outer-Inner").memberOf', "Outer", 'The memberOf of inner function is found.'); + is('symbols.getSymbol("Outer-Inner").name', "Inner", 'The name of inner function is found.'); + is('symbols.getSymbol("Outer-Inner#name").name', "name", 'A member of the inner function constructor, attached to "this" is found on inner.'); + is('symbols.getSymbol("Outer-Inner#name").memberOf', "Outer-Inner", 'The memberOf of an inner function member is found.'); + } + , + function() { + symbolize({a:true, _: [SYS.pwd+"test/prototype_nested.js"]}); + + is('symbols.getSymbol("Word").name', "Word", 'Base constructor name is found.'); + is('symbols.getSymbol("Word").hasMethod("reverse")', true, 'Base constructor method is found.'); + is('symbols.getSymbol("Word").methods.length', 1, 'Base constructor has only one method.'); + is('symbols.getSymbol("Word").memberOf', "", 'Base constructor memberOf is empty.'); + is('symbols.getSymbol("Word#reverse").name', "reverse", 'Member of constructor prototype name is found.'); + is('symbols.getSymbol("Word#reverse").memberOf', "Word", 'Member of constructor prototype memberOf is found.'); + is('symbols.getSymbol("Word#reverse.utf8").name', "utf8", 'Member of constructor prototype method name is found.'); + is('symbols.getSymbol("Word#reverse.utf8").memberOf', "Word#reverse", 'Static nested member memberOf is found.'); + } + , + function() { + symbolize({a:true, _: [SYS.pwd+"test/namespace_nested.js"]}); + + is('symbols.getSymbol("ns1").name', "ns1", 'Base namespace name is found.'); + is('symbols.getSymbol("ns1").memberOf', "", 'Base namespace memberOf is empty (its a constructor).'); + is('symbols.getSymbol("ns1.ns2").name', "ns2", 'Nested namespace name is found.'); + is('symbols.getSymbol("ns1.ns2").alias', "ns1.ns2", 'Nested namespace alias is found.'); + is('symbols.getSymbol("ns1.ns2").memberOf', "ns1", 'Nested namespace memberOf is found.'); + is('symbols.getSymbol("ns1.ns2.Function1").name', "Function1", 'Method of nested namespace name is found.'); + is('symbols.getSymbol("ns1.ns2.Function1").memberOf', "ns1.ns2", 'Constructor of nested namespace memberOf is found.'); + } + , + function() { + symbolize({a:true, p:true, _: [SYS.pwd+"test/functions_nested.js"]}); + + is('symbols.getSymbol("Zop").name', "Zop", 'Any constructor name is found.'); + is('symbols.getSymbol("Zop").isa', "CONSTRUCTOR", 'It isa constructor.'); + is('symbols.getSymbol("Zop").hasMethod("zap")', true, 'Its method name, set later, is in methods array.'); + is('symbols.getSymbol("Foo").name', "Foo", 'The containing constructor name is found.'); + is('symbols.getSymbol("Foo").hasMethod("methodOne")', true, 'Its method name is found.'); + is('symbols.getSymbol("Foo").hasMethod("methodTwo")', true, 'Its second method name is found.'); + is('symbols.getSymbol("Foo#methodOne").alias', "Foo#methodOne", 'A methods alias is found.'); + is('symbols.getSymbol("Foo#methodOne").isStatic', false, 'A methods is not static.'); + is('symbols.getSymbol("Bar").name', "Bar", 'A global function declared inside another function is found.'); + is('symbols.getSymbol("Bar").isa', "FUNCTION", 'It isa function.'); + is('symbols.getSymbol("Bar").memberOf', "_global_", 'It is global.'); + is('symbols.getSymbol("Foo-inner").name', "inner", 'An inner functions name is found.'); + is('symbols.getSymbol("Foo-inner").memberOf', "Foo", 'It is member of the outer function.'); + is('symbols.getSymbol("Foo-inner").isInner', true, 'It is an inner function.'); + } + , + function() { + symbolize({a:true, _: [SYS.pwd+"test/memberof_constructor.js"]}); + + is('symbols.getSymbol("Circle#Tangent").name', "Tangent", 'Constructor set on prototype using @member has correct name.'); + is('symbols.getSymbol("Circle#Tangent").memberOf', "Circle", 'Constructor set on prototype using @member has correct memberOf.'); + is('symbols.getSymbol("Circle#Tangent").alias', "Circle#Tangent", 'Constructor set on prototype using @member has correct alias.'); + is('symbols.getSymbol("Circle#Tangent").isa', "CONSTRUCTOR", 'Constructor set on prototype using @member has correct isa.'); + is('symbols.getSymbol("Circle#Tangent").isStatic', false, 'Constructor set on prototype using @member is not static.'); + is('symbols.getSymbol("Circle#Tangent#getDiameter").name', "getDiameter", 'Method set on prototype using @member has correct name.'); + is('symbols.getSymbol("Circle#Tangent#getDiameter").memberOf', "Circle#Tangent", 'Method set on prototype using @member has correct memberOf.'); + is('symbols.getSymbol("Circle#Tangent#getDiameter").alias', "Circle#Tangent#getDiameter", 'Method set on prototype using @member has correct alias.'); + is('symbols.getSymbol("Circle#Tangent#getDiameter").isa', "FUNCTION", 'Method set on prototype using @member has correct isa.'); + is('symbols.getSymbol("Circle#Tangent#getDiameter").isStatic', false, 'Method set on prototype using @member is not static.'); + } + , + function() { + symbolize({a:true, p: true, _: [SYS.pwd+"test/memberof.js"]}); + + is('symbols.getSymbol("pack.install").alias', "pack.install", 'Using @memberOf sets alias, when parent name is in memberOf tag.'); + is('symbols.getSymbol("pack.install.overwrite").name', "install.overwrite", 'Using @memberOf sets name, even if the name is dotted.'); + is('symbols.getSymbol("pack.install.overwrite").memberOf', "pack", 'Using @memberOf sets memberOf.'); + is('symbols.getSymbol("pack.install.overwrite").isStatic', true, 'Using @memberOf with value not ending in octothorp sets isStatic to true.'); + } + , + function() { + symbolize({a:true, p: true, _: [SYS.pwd+"test/memberof2.js"]}); + + is('symbols.getSymbol("Foo#bar").alias', "Foo#bar", 'An inner function can be documented as an instance method.'); + is('symbols.getSymbol("Foo.zip").alias', "Foo.zip", 'An inner function can be documented as a static method.'); + is('symbols.getSymbol("Foo.Fiz").alias', "Foo.Fiz", 'An inner function can be documented as a static constructor.'); + is('symbols.getSymbol("Foo.Fiz#fipple").alias', "Foo.Fiz#fipple", 'An inner function can be documented as a static constructor with a method.'); + is('symbols.getSymbol("Foo#blat").alias', "Foo#blat", 'An global function can be documented as an instance method.'); + } + , + function() { + symbolize({a:true, p: true, _: [SYS.pwd+"test/memberof3.js"]}); + + is('symbols.getSymbol("Foo#bar").alias', "Foo#bar", 'A virtual field can be documented as an instance method.'); + is('symbols.getSymbol("Foo2#bar").alias', "Foo2#bar", 'A virtual field with the same name can be documented as an instance method.'); + } + , + function() { + symbolize({a:true, p:true, _: [SYS.pwd+"test/borrows.js"]}); + + is('symbols.getSymbol("Layout").name', "Layout", 'Constructor can be found.'); + is('symbols.getSymbol("Layout").hasMethod("init")', true, 'Constructor method name can be found.'); + is('symbols.getSymbol("Layout").hasMember("orientation")', true, 'Constructor property name can be found.'); + + is('symbols.getSymbol("Page").hasMethod("reset")', true, 'Second constructor method name can be found.'); + is('symbols.getSymbol("Page").hasMember("orientation")', true, 'Second constructor borrowed property name can be found in properties.'); + is('symbols.getSymbol("Page#orientation").memberOf', "Page", 'Second constructor borrowed property memberOf can be found.'); + is('symbols.getSymbol("Page-getInnerElements").alias', "Page-getInnerElements", 'Can borrow an inner function and it is still inner.'); + is('symbols.getSymbol("Page.units").alias', "Page.units", 'Can borrow a static function and it is still static.'); + + is('symbols.getSymbol("ThreeColumnPage#init").alias', "ThreeColumnPage#init", 'Third constructor method can be found even though method with same name is borrowed.'); + is('symbols.getSymbol("ThreeColumnPage#reset").alias', "ThreeColumnPage#reset", 'Borrowed method can be found.'); + is('symbols.getSymbol("ThreeColumnPage#orientation").alias', "ThreeColumnPage#orientation", 'Twice borrowed method can be found.'); + + } + , + function() { + symbolize({a:true, p:true, _: [SYS.pwd+"test/borrows2.js"]}); + + is('symbols.getSymbol("Foo").hasMethod("my_zop")', true, 'Borrowed method can be found.'); + is('symbols.getSymbol("Bar").hasMethod("my_zip")', true, 'Second borrowed method can be found.'); + } + , + function() { + symbolize({a:true, p:true, _: [SYS.pwd+"test/constructs.js"]}); + + is('symbols.getSymbol("Person").hasMethod("say")', true, 'The constructs tag creates a class that lends can add a method to.'); + } + , + function() { + symbolize({a: true, _: [SYS.pwd+"test/augments.js", SYS.pwd+"test/augments2.js"]}); + + is('symbols.getSymbol("Page").augments[0]', "Layout", 'An augmented class can be found.'); + is('symbols.getSymbol("Page#reset").alias', "Page#reset", 'Method of augmenter can be found.'); + is('symbols.getSymbol("Page").hasMethod("Layout#init")', true, 'Method from augmented can be found.'); + is('symbols.getSymbol("Page").hasMember("Layout#orientation")', true, 'Property from augmented can be found.'); + is('symbols.getSymbol("Page").methods.length', 3, 'Methods of augmented class are included in methods array.'); + + is('symbols.getSymbol("ThreeColumnPage").augments[0]', "Page", 'The extends tag is a synonym for augments.'); + is('symbols.getSymbol("ThreeColumnPage").hasMethod("ThreeColumnPage#init")', true, 'Local method overrides augmented method of same name.'); + is('symbols.getSymbol("ThreeColumnPage").methods.length', 3, 'Local method count is right.'); + + is('symbols.getSymbol("NewsletterPage").augments[0]', "ThreeColumnPage", 'Can augment across file boundaries.'); + is('symbols.getSymbol("NewsletterPage").augments.length', 2, 'Multiple augments are supported.'); + is('symbols.getSymbol("NewsletterPage").inherits[0].alias', "Junkmail#annoy", 'Inherited method with augments.'); + is('symbols.getSymbol("NewsletterPage").methods.length', 6, 'Methods of augmented class are included in methods array across files.'); + is('symbols.getSymbol("NewsletterPage").properties.length', 1, 'Properties of augmented class are included in properties array across files.'); + } + , + function() { + symbolize({a:true, _: [SYS.pwd+"test/static_this.js"]}); + + is('symbols.getSymbol("box.holder").name', "holder", 'Static namespace name can be found.'); + is('symbols.getSymbol("box.holder.foo").name', "foo", 'Static namespace method name can be found.'); + is('symbols.getSymbol("box.holder").isStatic', true, 'Static namespace method is static.'); + + is('symbols.getSymbol("box.holder.counter").name', "counter", 'Instance namespace property name set on "this" can be found.'); + is('symbols.getSymbol("box.holder.counter").alias', "box.holder.counter", 'Instance namespace property alias set on "this" can be found.'); + is('symbols.getSymbol("box.holder.counter").memberOf', "box.holder", 'Static namespace property memberOf set on "this" can be found.'); + } + , + function() { + symbolize({a:true, p: true, _: [SYS.pwd+"test/lend.js"]}); + + is('symbols.getSymbol("Person").name', "Person", 'Class defined in lend comment is found.'); + is('symbols.getSymbol("Person").hasMethod("initialize")', true, 'Lent instance method name can be found.'); + is('symbols.getSymbol("Person").hasMethod("say")', true, 'Second instance method can be found.'); + is('symbols.getSymbol("Person#sing").isStatic', false, 'Instance method is known to be not static.'); + + is('symbols.getSymbol("Person.getCount").name', "getCount", 'Static method name from second lend comment can be found.'); + is('symbols.getSymbol("Person.getCount").isStatic', true, 'Static method from second lend comment is known to be static.'); + + is('LOG.warnings.filter(function($){if($.indexOf("notok") > -1) return $}).length', 1, 'A warning is emitted when lending to an undocumented parent.'); + } + , + function() { + symbolize({a:true, _: [SYS.pwd+"test/param_inline.js"]}); + + is('symbols.getSymbol("Layout").params[0].type', "int", 'Inline param name is set.'); + is('symbols.getSymbol("Layout").params[0].desc', "The number of columns.", 'Inline param desc is set from comment.'); + is('symbols.getSymbol("Layout#getElement").params[0].name', "id", 'User defined param documentation takes precedence over parser defined.'); + is('symbols.getSymbol("Layout#getElement").params[0].isOptional', true, 'Default for param is to not be optional.'); + is('symbols.getSymbol("Layout#getElement").params[1].isOptional', false, 'Can mark a param as being optional.'); + is('symbols.getSymbol("Layout#getElement").params[1].type', "number|string", 'Type of inline param doc can have multiple values.'); + is('symbols.getSymbol("Layout#Canvas").params[0].type', "", 'Type can be not defined for some params.'); + is('symbols.getSymbol("Layout#Canvas").params[2].type', "int", 'Type can be defined inline for only some params.'); + is('symbols.getSymbol("Layout#rotate").params.length', 0, 'Docomments inside function sig is ignored without a param.'); + is('symbols.getSymbol("Layout#init").params[2].type', "zoppler", 'Doc comment type overrides inline type for param with same name.'); + } + , + function() { + symbolize({a: true, _: [SYS.pwd+"test/shared.js", SYS.pwd+"test/shared2.js"]}); + + is('symbols.getSymbol("Array#some").name', 'some', 'The name of a symbol in a shared section is found.'); + is('symbols.getSymbol("Array#some").alias', 'Array#some', 'The alias of a symbol in a shared section is found.'); + is('symbols.getSymbol("Array#some").desc', "Extension to builtin array.", 'A description can be shared.'); + is('symbols.getSymbol("Array#filter").desc', "Extension to builtin array.\nChange every element of an array.", 'A shared description is appended.'); + is('symbols.getSymbol("Queue").desc', "A first in, first out data structure.", 'A description is not shared when outside a shared section.'); + is('symbols.getSymbol("Queue.rewind").alias', "Queue.rewind", 'Second shared tag can be started.'); + is('symbols.getSymbol("startOver").alias', "startOver", 'Shared tag doesnt cross over files.'); + } + , + function() { + symbolize({a: true, _: [SYS.pwd+"test/config.js"]}); + is('symbols.getSymbol("Contact").params[0].name', 'person', 'The name of a param is found.'); + is('symbols.getSymbol("Contact").params[1].name', 'person.name', 'The name of a param set with a dot name is found.'); + is('symbols.getSymbol("Contact").params[2].name', 'person.age', 'The name of a second param set with a dot name is found.'); + is('symbols.getSymbol("Contact").params[4].name', 'connection', 'The name of a param after config is found.'); + + is('symbols.getSymbol("Family").params[0].name', 'persons', 'Another name of a param is found.'); + is('symbols.getSymbol("Family").params[1].name', 'persons.Father', 'The name of a param+config is found.'); + is('symbols.getSymbol("Family").params[2].name', 'persons.Mother', 'The name of a second param+config is found.'); + is('symbols.getSymbol("Family").params[3].name', 'persons.Children', 'The name of a third param+config is found.'); + } + , + function() { + symbolize({a:true, p:true, _: [SYS.pwd+"test/ignore.js"]}); + is('LOG.warnings.filter(function($){if($.indexOf("undocumented symbol Ignored") > -1) return $}).length', 1, 'A warning is emitted when documenting members of an ignored parent.'); + } + , + function() { + symbolize({a:true, p:true, _: [SYS.pwd+"test/functions_anon.js"]}); + is('symbols.getSymbol("a.b").alias', 'a.b', 'In anonymous constructor this is found to be the container object.'); + is('symbols.getSymbol("a.f").alias', 'a.f', 'In anonymous constructor this can have a method.'); + is('symbols.getSymbol("a.c").alias', 'a.c', 'In anonymous constructor method this is found to be the container object.'); + is('symbols.getSymbol("g").alias', 'g', 'In anonymous function executed inline this is the global.'); + is('symbols.getSymbol("bar2.p").alias', 'bar2.p', 'In named constructor executed inline this is the container object.'); + is('symbols.getSymbol("module.pub").alias', 'module.pub', 'In parenthesized anonymous function executed inline function scoped variables arent documented.'); + } + , + function() { + symbolize({a:true, p:true, _: [SYS.pwd+"test/oblit_anon.js"]}); + is('symbols.getSymbol("opt").name', 'opt', 'Anonymous object properties are created.'); + is('symbols.getSymbol("opt.conf.keep").alias', 'opt.conf.keep', 'Anonymous object first property is assigned to $anonymous.'); + is('symbols.getSymbol("opt.conf.base").alias', 'opt.conf.base', 'Anonymous object second property is assigned to $anonymous.'); + } + , + function() { + symbolize({a:true, p:true, _: [SYS.pwd+"test/params_optional.js"]}); + is('symbols.getSymbol("Document").params.length', 3, 'Correct number of params are found when optional param syntax is used.'); + is('symbols.getSymbol("Document").params[1].name', "id", 'Name of optional param is found.'); + is('symbols.getSymbol("Document").params[1].isOptional', true, 'Optional param is marked isOptional.'); + is('symbols.getSymbol("Document").params[2].name', "title", 'Name of optional param with default value is found.'); + is('symbols.getSymbol("Document").params[2].isOptional', true, 'Optional param with default value is marked isOptional.'); + is('symbols.getSymbol("Document").params[2].defaultValue', " This is untitled.", 'Optional param default value is found.'); + } + , + function() { + symbolize({a:true, p:true, _: [SYS.pwd+"test/synonyms.js"]}); + is('symbols.getSymbol("myObject.myFunc").type', 'function', 'Type can be set to function.'); + } + , + function() { + symbolize({a:true, p:true, _: [SYS.pwd+"test/event.js"]}); + is('symbols.getSymbol("Kitchen#event:cakeEaten").isEvent', true, 'Function with event prefix is an event.'); + is('symbols.getSymbol("Kitchen#cakeEaten").isa', "FUNCTION", 'Function with same name as event isa function.'); + } + , + function() { + symbolize({x:"js", a:true, _: [SYS.pwd+"test/scripts/"]}); + is('JSDOC.JsDoc.srcFiles.length', 1, 'Only js files are scanned when -x=js.'); + } + , + function() { + symbolize({x:"js", a:true, _: [SYS.pwd+"test/exports.js"]}); + is('symbols.getSymbol("mxn.Map#doThings").name', 'doThings', 'Exports creates a documentation alias that can have methods.'); + } + , + function() { + symbolize({p:true, a:true, _: [SYS.pwd+"test/module.js"]}); + is('symbols.getSymbol("myProject.myModule.myPublicMethod").name', 'myPublicMethod', 'A function wrapped in parens can be recognized.'); + is('symbols.getSymbol("myProject.myModule-myPrivateMethod").name', 'myPrivateMethod', 'A private method in the scope of a function wrapped in parens can be recognized.'); + is('symbols.getSymbol("myProject.myModule-myPrivateVar").name', 'myPrivateVar', 'A private member in the scope of a function wrapped in parens can be recognized.'); + } +]; + +//// run and print results +print(testrun(testCases)); diff --git a/bin/jsdoc/test/addon.js b/bin/jsdoc/test/addon.js new file mode 100644 index 00000000..88862053 --- /dev/null +++ b/bin/jsdoc/test/addon.js @@ -0,0 +1,24 @@ +String.prototype.reverse = function() { +} + +String.prototype.reverse.utf8 = function() { +} + +Function.count = function() { +} + +/** @memberOf Function */ +Function.count.reset = function() { +} + +/** @memberOf Function */ +count.getValue = function() { +} + +/** @memberOf Function.prototype */ +getSig = function() { +} + +/** @memberOf Function.prototype */ +Function.prototype.getProps = function() { +} diff --git a/bin/jsdoc/test/anon_inner.js b/bin/jsdoc/test/anon_inner.js new file mode 100644 index 00000000..227eeee5 --- /dev/null +++ b/bin/jsdoc/test/anon_inner.js @@ -0,0 +1,14 @@ +/** + * @name bar + * @namespace + */ + +new function() { + /** + * @name bar-foo + * @function + * @param {number} x + */ + function foo(x) { + } +} \ No newline at end of file diff --git a/bin/jsdoc/test/augments.js b/bin/jsdoc/test/augments.js new file mode 100644 index 00000000..12e706eb --- /dev/null +++ b/bin/jsdoc/test/augments.js @@ -0,0 +1,31 @@ +/** +@constructor +*/ +function Layout(p) { + this.init = function(p) { + } + + this.getId = function() { + } + + /** @type Page */ + this.orientation = "landscape"; +} + +/** +@constructor +@augments Layout +*/ +function Page() { + this.reset = function(b) { + } +} + +/** +@extends Page +@constructor +*/ +function ThreeColumnPage() { + this.init = function(resetCode) { + } +} diff --git a/bin/jsdoc/test/augments2.js b/bin/jsdoc/test/augments2.js new file mode 100644 index 00000000..e8388f0f --- /dev/null +++ b/bin/jsdoc/test/augments2.js @@ -0,0 +1,26 @@ +/** +@constructor +*/ +function LibraryItem() { + this.reserve = function() { + } +} + +/** +@constructor +*/ +function Junkmail() { + this.annoy = function() { + } +} + +/** +@inherits Junkmail.prototype.annoy as pester +@augments ThreeColumnPage +@augments LibraryItem +@constructor +*/ +function NewsletterPage() { + this.getHeadline = function() { + } +} diff --git a/bin/jsdoc/test/borrows.js b/bin/jsdoc/test/borrows.js new file mode 100644 index 00000000..a5d8ea4a --- /dev/null +++ b/bin/jsdoc/test/borrows.js @@ -0,0 +1,46 @@ +/** +@constructor +*/ +function Layout(p) { + /** initilize 1 */ + this.init = function(p) { + } + + /** get the id */ + this.getId = function() { + } + + /** @type string */ + this.orientation = "landscape"; + + function getInnerElements(elementSecretId){ + } +} + +/** A static method. */ +Layout.units = function() { +} + +/** +@constructor +@borrows Layout#orientation +@borrows Layout-getInnerElements +@borrows Layout.units +*/ +function Page() { + /** reset the page */ + this.reset = function(b) { + } +} + +/** +@constructor +@borrows Layout.prototype.orientation as this.orientation +@borrows Layout.prototype.init as #init +@inherits Page.prototype.reset as #reset +*/ +function ThreeColumnPage() { + /** initilize 2 */ + this.init = function(p) { + } +} diff --git a/bin/jsdoc/test/borrows2.js b/bin/jsdoc/test/borrows2.js new file mode 100644 index 00000000..c0d5ea21 --- /dev/null +++ b/bin/jsdoc/test/borrows2.js @@ -0,0 +1,23 @@ +// testing circular borrows + +/** + @class + @borrows Bar#zop as this.my_zop +*/ +function Foo() { + /** this is a zip. */ + this.zip = function() {} + + this.my_zop = new Bar().zop; +} + +/** + @class + @borrows Foo#zip as this.my_zip +*/ +function Bar() { + /** this is a zop. */ + this.zop = function() {} + + this.my_zip = new Foo().zip; +} \ No newline at end of file diff --git a/bin/jsdoc/test/config.js b/bin/jsdoc/test/config.js new file mode 100644 index 00000000..0748a210 --- /dev/null +++ b/bin/jsdoc/test/config.js @@ -0,0 +1,22 @@ +/** + * @constructor + * @param person The person. + * @param {string} person.name The person's name. + * @config {integer} age The person's age. + * @config [id=1] Optional id number to use. + * @param connection + */ +function Contact(person, connection) { + +} + +/** + * @constructor + * @param persons + * @config {string} Father The paternal person. + * @config {string} Mother The maternal person. + * @config {string[]} Children And the rest. + */ +function Family(/**Object*/persons) { + +} diff --git a/bin/jsdoc/test/constructs.js b/bin/jsdoc/test/constructs.js new file mode 100644 index 00000000..cca5dbd3 --- /dev/null +++ b/bin/jsdoc/test/constructs.js @@ -0,0 +1,18 @@ +var Person = makeClass( + /** + @scope Person + */ + { + /** + This is just another way to define a constructor. + @constructs + @param {string} name The name of the person. + */ + initialize: function(name) { + this.name = name; + }, + say: function(message) { + return this.name + " says: " + message; + } + } +); \ No newline at end of file diff --git a/bin/jsdoc/test/encoding.js b/bin/jsdoc/test/encoding.js new file mode 100644 index 00000000..ba642193 --- /dev/null +++ b/bin/jsdoc/test/encoding.js @@ -0,0 +1,10 @@ + +/** + * @Constructor + * @desc é…置文件 + * @class 什么也ä¸è¿”回 + */ +function Test(conf) { + // do something; +} + diff --git a/bin/jsdoc/test/encoding_other.js b/bin/jsdoc/test/encoding_other.js new file mode 100644 index 00000000..b144da4c --- /dev/null +++ b/bin/jsdoc/test/encoding_other.js @@ -0,0 +1,12 @@ + +/** + * @Constructor + * @desc ðïîÛ + * @class ßàáâãäåæçèçìëêíîï °±²³´µ¡¶·¸¹ + */ +function Test(conf) { + // do something; +} + +// run with commanline option -e=iso-8859-5 + diff --git a/bin/jsdoc/test/event.js b/bin/jsdoc/test/event.js new file mode 100644 index 00000000..7e41d6f6 --- /dev/null +++ b/bin/jsdoc/test/event.js @@ -0,0 +1,54 @@ +/** + * @name Kitchen + * @constructor + * @fires Bakery#event:donutOrdered + */ + +/** + * Fired when some cake is eaten. + * @name Kitchen#event:cakeEaten + * @function + * @param {Number} pieces The number of pieces eaten. + */ + +/** + * Find out if cake was eaten. + * @name Kitchen#cakeEaten + * @function + * @param {Boolean} wasEaten + */ + +/** + * @name getDesert + * @function + * @fires Kitchen#event:cakeEaten + */ + +/** + * @name Bakery + * @constructor + * @extends Kitchen + */ + +/** + * Fired when a donut order is made. + * @name Bakery#event:donutOrdered + * @event + * @param {Event} e The event object. + * @param {String} [e.topping] Optional sprinkles. + */ + +/** + * @constructor + * @borrows Bakery#event:donutOrdered as this.event:cakeOrdered + */ +function CakeShop() { +} + +/** @event */ +CakeShop.prototype.icingReady = function(isPink) { +} + +/** @event */ +function amHungry(/**Boolean*/enoughToEatAHorse) { +} \ No newline at end of file diff --git a/bin/jsdoc/test/exports.js b/bin/jsdoc/test/exports.js new file mode 100644 index 00000000..63a87cb4 --- /dev/null +++ b/bin/jsdoc/test/exports.js @@ -0,0 +1,14 @@ +/** @namespace */ +var mxn = {}; + +(function(){ + /** @exports Map as mxn.Map */ + var Map = + /** @constructor */ + mxn.Map = function() { + }; + + /** A method. */ + Map.prototype.doThings = function() { + }; +})(); \ No newline at end of file diff --git a/bin/jsdoc/test/functions_anon.js b/bin/jsdoc/test/functions_anon.js new file mode 100644 index 00000000..e9dd6c1b --- /dev/null +++ b/bin/jsdoc/test/functions_anon.js @@ -0,0 +1,39 @@ +/** an anonymous constructor executed inline */ +a = new function() { + /** a.b*/ + this.b = 1; + /** a.f */ + this.f = function() { + /** a.c */ + this.c = 2; + } +} + + +/** + named function executed inline +*/ +bar1 = function Zoola1() { + /** property of global */ + this.g = 1; +}(); + +/** + named constructor executed inline +*/ +bar2 = new function Zoola2() { + /** property of bar */ + this.p = 1; +}; + +/** module pattern */ +module = (function () { + /** won't appear in documentation */ + var priv = 1; + + /** @scope module */ + return { + /** will appear as a property of module */ + pub: 1 + } +})(); diff --git a/bin/jsdoc/test/functions_nested.js b/bin/jsdoc/test/functions_nested.js new file mode 100644 index 00000000..f044fafe --- /dev/null +++ b/bin/jsdoc/test/functions_nested.js @@ -0,0 +1,33 @@ +/** @constructor */ +function Zop() { +} + +/** + @class +*/ +Foo = function(id) { + // this is a bit twisted, but if you call Foo() you will then + // modify Foo(). This is kinda, sorta non-insane, because you + // would have to call Foo() 100% of the time to use Foo's methods + Foo.prototype.methodOne = function(bar) { + alert(bar); + }; + + // same again + Foo.prototype.methodTwo = function(bar2) { + alert(bar2); + }; + + // and these are only executed if the enclosing function is actually called + // and who knows if that will ever happen? + Bar = function(pez) { + alert(pez); + }; + Zop.prototype.zap = function(p){ + alert(p); + }; + + // but this is only visible inside Foo + function inner() { + } +}; diff --git a/bin/jsdoc/test/global.js b/bin/jsdoc/test/global.js new file mode 100644 index 00000000..5ea48949 --- /dev/null +++ b/bin/jsdoc/test/global.js @@ -0,0 +1,13 @@ +/** ecks */ +var x = [1, 2, 4]; + +var y = { + foo: function(){ + } +} + +bar = function() { +} + +function zop() { +} diff --git a/bin/jsdoc/test/globals.js b/bin/jsdoc/test/globals.js new file mode 100644 index 00000000..3f83fb1f --- /dev/null +++ b/bin/jsdoc/test/globals.js @@ -0,0 +1,25 @@ +function example(/**Circle*/a, b) { + /** a global defined in function */ + var number = a; + + var hideNumber = function(){ + } + + setNumber = function(){ + } + alert('You have chosen: ' + b); +} + +function initPage() { + var supported = document.createElement && document.getElementsByTagName; + if (!supported) return; + // start of DOM script + var x = document.getElementById('writeroot'); + // etc. +} + +/** an example var */ +var document = new Document(x, y); + +var getNumber = function(){ +} \ No newline at end of file diff --git a/bin/jsdoc/test/ignore.js b/bin/jsdoc/test/ignore.js new file mode 100644 index 00000000..d3fac9ed --- /dev/null +++ b/bin/jsdoc/test/ignore.js @@ -0,0 +1,10 @@ +/** + * A test constructor. + * @constructor + * @ignore + */ +function Ignored() { + /** a method */ + this.bar = function() { + } +} \ No newline at end of file diff --git a/bin/jsdoc/test/inner.js b/bin/jsdoc/test/inner.js new file mode 100644 index 00000000..37cfa9dc --- /dev/null +++ b/bin/jsdoc/test/inner.js @@ -0,0 +1,16 @@ +/** + * @constructor + */ +function Outer() { + /** + * @constructor + */ + function Inner(name) { + /** The name of this. */ + this.name = name; + } + + this.open = function(name) { + return (new Inner(name)); + } +} \ No newline at end of file diff --git a/bin/jsdoc/test/jsdoc_test.js b/bin/jsdoc/test/jsdoc_test.js new file mode 100644 index 00000000..08177128 --- /dev/null +++ b/bin/jsdoc/test/jsdoc_test.js @@ -0,0 +1,477 @@ +/** + * @fileoverview This file is to be used for testing the JSDoc parser + * It is not intended to be an example of good JavaScript OO-programming, + * nor is it intended to fulfill any specific purpose apart from + * demonstrating the functionality of the + * JSDoc parser + * + * @author Gabriel Reid gab_reid@users.sourceforge.net + * @version 0.1 + */ + + +/** + * Construct a new Shape object. + * @class This is the basic Shape class. + * It can be considered an abstract class, even though no such thing + * really existing in JavaScript + * @constructor + * @throws MemoryException if there is no more memory + * @throws GeneralShapeException rarely (if ever) + * @return {Shape|Coordinate} A new shape. + */ +function Shape(){ + + /** + * This is an example of a function that is not given as a property + * of a prototype, but instead it is assigned within a constructor. + * For inner functions like this to be picked up by the parser, the + * function that acts as a constructor must be denoted with + * the @constructor tag in its comment. + * @type String + */ + this.getClassName = function(){ + return "Shape"; + } + + /** + * This is an inner method, just used here as an example + * @since version 0.5 + * @author Sue Smart + */ + function addReference(){ + // Do nothing... + } + +} + +/** + * Create a new Hexagon instance. + * @extends Shape + * @class Hexagon is a class that is a logical sublcass of + * {@link Shape} (thanks to the @extends tag), but in + * reality it is completely unrelated to Shape. + * @param {int} sideLength The length of one side for the new Hexagon + * @example + * var h = new Hexagon(2); + * @example + * if (hasHex) { + * hex = new Hexagon(5); + * color = hex.getColor(); + * } + */ +function Hexagon(sideLength) { +} + + +/** + * This is an unattached (static) function that adds two integers together. + * @param {int} One The first number to add + * @param {int} Two The second number to add + * @author Gabriel Reid + * @deprecated So you shouldn't use it anymore! Use {@link Shape#getClassName} instead. + */ +function Add(One, Two){ + return One + Two; +} + + +/** + * The color of this shape + * @type Color + */ +Shape.prototype.color = null; + +/** + * The border of this shape. + * @field + * @type int + */ +Shape.prototype.border = function(){return border;}; + +/* + * These are all the instance method implementations for Shape + */ + +/** + * Get the coordinates of this shape. It is assumed that we're always talking + * about shapes in a 2D location here. + * @requires The {@link Shape} class + * @returns A Coordinate object representing the location of this Shape + * @type Coordinate[] + */ +Shape.prototype.getCoords = function(){ + return this.coords; +} + +/** + * Get the color of this shape. + * @see #setColor + * @see The Color library. + * @link Shape + * @type Color + */ +Shape.prototype.getColor = function(){ + return this.color; +} + +/** + * Set the coordinates for this Shape + * @param {Coordinate} coordinates The coordinates to set for this Shape + */ +Shape.prototype.setCoords = function(coordinates){ + this.coords = coordinates; +} + +/** + * Set the color for this Shape + * @param {Color} color The color to set for this Shape + * @param other There is no other param, but it can still be documented if + * optional parameters are used + * @throws NonExistantColorException (no, not really!) + * @see #getColor + */ +Shape.prototype.setColor = function(color){ + this.color = color; +} + +/** + * Clone this shape + * @returns A copy of this shape + * @type Shape + * @author Gabriel Reid + */ +Shape.prototype.clone = function(){ + return new Shape(); +} + +/** + * Create a new Rectangle instance. + * @class A basic rectangle class, inherits from Shape. + * This class could be considered a concrete implementation class + * @constructor + * @param {int} width The optional width for this Rectangle + * @param {int} height Thie optional height for this Rectangle + * @author Gabriel Reid + * @see Shape is the base class for this + * @augments Shape + * @hilited + */ +function Rectangle(width, // This is the width + height // This is the height + ){ + if (width){ + this.width = width; + if (height){ + this.height = height; + } + } +} + + +/* Inherit from Shape */ +Rectangle.prototype = new Shape(); + +/** + * Value to represent the width of the Rectangle. + *
Text in bold and italic and a + * link to SourceForge + * @private + * @type int + */ +Rectangle.prototype.width = 0; + +/** + * Value to represent the height of the Rectangle + * @private + * @type int + */ +Rectangle.prototype.height = 0; + +/** + * Get the type of this object. + * @type String + */ +Rectangle.prototype.getClassName= function(){ + return "Rectangle"; +} + +/** + * Get the value of the width for the Rectangle + * @type int + * @see Rectangle#setWidth + */ +Rectangle.prototype.getWidth = function(){ + return this.width; +} + +/** + * Get the value of the height for the Rectangle. + * Another getter is the {@link Shape#getColor} method in the + * {@link Shape} base class. + * @return The height of this Rectangle + * @type int + * @see Rectangle#setHeight + */ +Rectangle.prototype.getHeight = function(){ + return this.height; +} + +/** + * Set the width value for this Rectangle. + * @param {int} width The width value to be set + * @see #setWidth + */ +Rectangle.prototype.setWidth = function(width){ + this.width = width; +} + +/** + * Set the height value for this Rectangle. + * @param {int} height The height value to be set + * @see #getHeight + */ +Rectangle.prototype.setHeight = function(height){ + this.height = height; +} + +/** + * Get the value for the total area of this Rectangle + * @return total area of this Rectangle + * @type int + */ +Rectangle.prototype.getArea = function(){ + return width * height; +} + + +/** + * Create a new Square instance. + * @class A Square is a subclass of {@link Rectangle} + * @param {int} width The optional width for this Rectangle + * @param {int} height The optional height for this Rectangle + * @augments Rectangle + */ +function Square(width, height){ + if (width){ + this.width = width; + if (height){ + this.height = height; + } + } + +} + +/* Square is a subclass of Rectangle */ +Square.prototype = new Rectangle(); + +/** + * Set the width value for this Shape. + * @param {int} width The width value to be set + * @see #getWidth + */ +Square.prototype.setWidth = function(width){ + this.width = this.height = width; +} + +/** + * Set the height value for this Shape + * Sets the {@link Rectangle#height} attribute in the Rectangle. + * @param {int} height The height value to be set + */ +Square.prototype.setHeight = function(height){ + this.height = this.width = height; +} + + +/** + * Create a new Circle instance based on a radius. + * @class Circle class is another subclass of Shape + * @extends Shape + * @param {int} radius The optional radius of this {@link Circle } + * @mixin Square.prototype.setWidth as this.setDiameter + */ +function Circle(radius){ + if (radius) { + /** The radius of the this Circle. */ + this.radius = radius; + } +} + +/* Circle inherits from {@link Shape} */ +Circle.prototype = new Shape(); + +/** + * The radius value for this Circle + * @private + * @type int + */ +Circle.prototype.radius = 0; + +/** + * A very simple class (static) field that is also a constant + * @final + * @type float + */ +Circle.PI = 3.14; + +/** + * Get the radius value for this Circle + * @type int + * @see #setRadius + */ +Circle.prototype.getRadius = function(){ + return this.radius; +} + +/** + * Set the radius value for this Circle + * @param {int} radius The {@link Circle#radius} value to set + * @see #getRadius + */ +Circle.prototype.setRadius = function(radius){ + this.radius = radius; +} + +/** + * An example of a class (static) method that acts as a factory for Circle + * objects. Given a radius value, this method creates a new Circle. + * @param {int} radius The radius value to use for the new Circle. + * @type Circle + */ +Circle.createCircle = function(radius){ + return new Circle(radius); +} + + +/** + * Create a new Coordinate instance based on x and y grid data. + * @class Coordinate is a class that can encapsulate location information. + * @param {int} [x=0] The optional x portion of the Coordinate + * @param {int} [y=0] The optinal y portion of the Coordinate + */ +function Coordinate(x, y){ + if (x){ + this.x = x; + if (y){ + this.y = y; + } + } +} + +/** + * The x portion of the Coordinate + * @type int + * @see #getX + * @see #setX + */ +Coordinate.prototype.x = 0; + +/** + * The y portion of the Coordinate + * @type int + * @see #getY + * @see #setY + */ +Coordinate.prototype.y = 0; + +/** + * Gets the x portion of the Coordinate. + * @type int + * @see #setX + */ +Coordinate.prototype.getX = function(){ + return this.x; +} + +/** + * Get the y portion of the Coordinate. + * @type int + * @see #setY + */ +Coordinate.prototype.getY = function(){ + return this.y; +} + +/** + * Sets the x portion of the Coordinate. + * @param {int} x The x value to set + * @see #getX + */ +Coordinate.prototype.setX = function(x){ + this.x = x; +} + +/** + * Sets the y portion of the Coordinate. + * @param {int} y The y value to set + * @see #getY + */ +Coordinate.prototype.setY = function(y){ + this.y = y; +} + +/** + * @class This class exists to demonstrate the assignment of a class prototype + * as an anonymous block. + */ +function ShapeFactory(){ +} + +ShapeFactory.prototype = { + /** + * Creates a new {@link Shape} instance. + * @return A new {@link Shape} + * @type Shape + */ + createShape: function(){ + return new Shape(); + } +} + +/** + * An example of a singleton class + * @param ... Arguments represent {@link coordinate}s in the shape. + * @constructor + */ +MySingletonShapeFactory = function(){ + + /** + * Get the next {@link Shape} + * @type Shape + * @return A new {@link Shape} + */ + this.getShape = function(){ + return null; + } + +} + + +/** + * Create a new Foo instance. + * @class This is the Foo class. It exists to demonstrate 'nested' classes. + * @constructor + * @see Foo.Bar + */ +function Foo(){} + +/** + * Creates a new instance of Bar. + * @class This class exists to demonstrate 'nested' classes. + * @constructor + * @see Foo.Bar + */ +function Bar(){} + +/** + * Nested class + * @constructor + */ +Foo.Bar = function(){ + /** The x. */ this.x = 2; +} + +Foo.Bar.prototype = new Bar(); +/** The y. */ +Foo.Bar.prototype.y = '3'; diff --git a/bin/jsdoc/test/lend.js b/bin/jsdoc/test/lend.js new file mode 100644 index 00000000..92b15d5a --- /dev/null +++ b/bin/jsdoc/test/lend.js @@ -0,0 +1,33 @@ + /** @class */ +var Person = Class.create( + /** + @lends Person.prototype + */ + { + initialize: function(name) { + this.name = name; + }, + say: function(message) { + return this.name + ': ' + message; + } + } + ); + +/** @lends Person.prototype */ +{ + /** like say but more musical */ + sing: function(song) { + } +} + +/** @lends Person */ +{ + getCount: function() { + } +} + +/** @lends Unknown.prototype */ +{ + notok: function() { + } +} \ No newline at end of file diff --git a/bin/jsdoc/test/memberof.js b/bin/jsdoc/test/memberof.js new file mode 100644 index 00000000..883bbdeb --- /dev/null +++ b/bin/jsdoc/test/memberof.js @@ -0,0 +1,19 @@ +/** @constructor */ +pack = function() { + this.init = function(){} + function config(){} +} + + pack.build = function(task) {}; + +/** @memberOf pack */ +pack.install = function() {} + +/** @memberOf pack */ +pack.install.overwrite = function() {} + +/** @memberOf pack */ +clean = function() {} + +/** @memberOf pack-config */ +install = function() {}; diff --git a/bin/jsdoc/test/memberof2.js b/bin/jsdoc/test/memberof2.js new file mode 100644 index 00000000..bc3d9d8f --- /dev/null +++ b/bin/jsdoc/test/memberof2.js @@ -0,0 +1,38 @@ +/** + * @constructor + */ +function Foo() { + /** + @memberOf Foo.prototype + */ + function bar(a, b) { + } + + /** + @memberOf Foo + */ + var zip = function(p, q) { + } + + /** + @memberOf Foo + */ + function zop( x,y ) { + } + + /** + @memberOf Foo + @constructor + */ + function Fiz() { + /** A method of Foo#Fiz. */ + this.fipple = function(fop){} + } +} + +/** + @memberOf Foo# + */ +var blat = function() { + +} \ No newline at end of file diff --git a/bin/jsdoc/test/memberof3.js b/bin/jsdoc/test/memberof3.js new file mode 100644 index 00000000..8c259425 --- /dev/null +++ b/bin/jsdoc/test/memberof3.js @@ -0,0 +1,33 @@ +/** +* @name Foo +* @class +*/ + +/**#@+ +* @memberOf Foo# +* @field +*/ + +/** +* @name bar +* @type Object[] +*/ + +/**#@-*/ + +/** +* @name Foo2 +* @class +*/ + +/**#@+ +* @memberOf Foo2# +* @field +*/ + +/** +* @name bar +* @type Object[] +*/ + +/**#@-*/ \ No newline at end of file diff --git a/bin/jsdoc/test/memberof_constructor.js b/bin/jsdoc/test/memberof_constructor.js new file mode 100644 index 00000000..80fde735 --- /dev/null +++ b/bin/jsdoc/test/memberof_constructor.js @@ -0,0 +1,17 @@ +/** @constructor */ +function Circle(){} + +/** + @constructor + @memberOf Circle# + */ +Circle.prototype.Tangent = function(){}; + +// renaming Circle#Tangent to Circle#Circle#Tangent + +/** + @memberOf Circle#Tangent# + */ +Circle.prototype.Tangent.prototype.getDiameter = function(){}; + + diff --git a/bin/jsdoc/test/module.js b/bin/jsdoc/test/module.js new file mode 100644 index 00000000..5b3fe42c --- /dev/null +++ b/bin/jsdoc/test/module.js @@ -0,0 +1,17 @@ +/** @namespace */ +myProject = myProject || {}; + +/** @namespace */ +myProject.myModule = (function () { + /** describe myPrivateVar here */ + var myPrivateVar = ""; + + var myPrivateMethod = function () { + } + + /** @scope myProject.myModule */ + return { + myPublicMethod: function () { + } + }; +})(); \ No newline at end of file diff --git a/bin/jsdoc/test/multi_methods.js b/bin/jsdoc/test/multi_methods.js new file mode 100644 index 00000000..bab35c76 --- /dev/null +++ b/bin/jsdoc/test/multi_methods.js @@ -0,0 +1,25 @@ + +/** + Get the entire flavor. + @name flavor^3 + @function + @returns {Object} The entire flavor hash. +*/ +/** + Get a named flavor. + @name flavor^2 + @function + @param {String} name The name of the flavor to get. + @returns {String} The value of that flavor. +*/ +/** + Set the flavor. + @param {String} name The name of the flavor to set. + @param {String} value The value of the flavor. + @returns {String} The value of that flavor. +*/ +function flavor(name, value) { + if (arguments.length > 1) flavor[name] = value; + else if (arguments.length == 1) return flavor[name]; + else return flavor; +} \ No newline at end of file diff --git a/bin/jsdoc/test/name.js b/bin/jsdoc/test/name.js new file mode 100644 index 00000000..e88a51a7 --- /dev/null +++ b/bin/jsdoc/test/name.js @@ -0,0 +1,19 @@ +/** + @name Response + @class +*/ + +Response.prototype = { + /** + @name Response#text + @function + @description + Gets the body of the response as plain text + @returns {String} + Response as text + */ + + text: function() { + return this.nativeResponse.responseText; + } +} \ No newline at end of file diff --git a/bin/jsdoc/test/namespace_nested.js b/bin/jsdoc/test/namespace_nested.js new file mode 100644 index 00000000..46cafa2f --- /dev/null +++ b/bin/jsdoc/test/namespace_nested.js @@ -0,0 +1,23 @@ +/** + @namespace This is the first namespace. +*/ +ns1 = {}; + +/** + This is the second namespace. + @namespace +*/ +ns1.ns2 = {}; + +/** + This part of ns1.ns2 + @constructor +*/ +ns1.ns2.Function1 = function() { +}; + +ns1.staticFunction = function() { +}; + +/** A static field in a namespace. */ +ns1.ns2.staticField = 1; diff --git a/bin/jsdoc/test/nocode.js b/bin/jsdoc/test/nocode.js new file mode 100644 index 00000000..1cf99bc9 --- /dev/null +++ b/bin/jsdoc/test/nocode.js @@ -0,0 +1,13 @@ +/**#nocode+*/ + /** + @name star + @function + */ + function blahblah() { + + } +/**#nocode-*/ + +function yaddayadda() { + +} \ No newline at end of file diff --git a/bin/jsdoc/test/oblit_anon.js b/bin/jsdoc/test/oblit_anon.js new file mode 100644 index 00000000..8d9e9413 --- /dev/null +++ b/bin/jsdoc/test/oblit_anon.js @@ -0,0 +1,20 @@ +/** the options */ +opt = Opt.get( + arguments, + { + d: "directory", + c: "conf", + "D[]": "define" + } +); + +/** configuration */ +opt.conf = { + /** keep */ + keep: true, + /** base */ + base: getBase(this, {p: properties}) +} + + + diff --git a/bin/jsdoc/test/overview.js b/bin/jsdoc/test/overview.js new file mode 100644 index 00000000..1dfc09b1 --- /dev/null +++ b/bin/jsdoc/test/overview.js @@ -0,0 +1,20 @@ +/** + * @overview This "library" contains a + * lot of classes and functions. + * @example +
+	var x (x < 1);
+	alert("This 'is' \"code\"");
+ 
+ * @name My Cool Library + * @author Joe Smith jsmith@company.com + * @version 0.1 + */ + +/** + * Gets the current foo + * @param {String} fooId The unique identifier for the foo. + * @return {Object} Returns the current foo. + */ +function getFoo(fooID){ +} \ No newline at end of file diff --git a/bin/jsdoc/test/param_inline.js b/bin/jsdoc/test/param_inline.js new file mode 100644 index 00000000..09845b28 --- /dev/null +++ b/bin/jsdoc/test/param_inline.js @@ -0,0 +1,37 @@ +/** + @constructor + @param columns The number of columns. +*/ +function Layout(/**int*/columns){ + /** + @param [id] The id of the element. + @param elName The name of the element. + */ + this.getElement = function( + /** string */ elName, + /** number|string */ id + ) { + }; + + /** + @constructor + */ + this.Canvas = function(top, left, /**int*/width, height) { + /** Is it initiated yet? */ + this.initiated = true; + } + + this.rotate = function(/**nothing*/) { + } + + /** + @param x + @param y + @param {zoppler} z*/ + this.init = function(x, y, /**abbler*/z) { + /** The xyz. */ + this.xyz = x+y+z; + this.getXyz = function() { + } + } +} diff --git a/bin/jsdoc/test/params_optional.js b/bin/jsdoc/test/params_optional.js new file mode 100644 index 00000000..18bf5982 --- /dev/null +++ b/bin/jsdoc/test/params_optional.js @@ -0,0 +1,8 @@ + +/** + * @param {Page[]} pages + * @param {number} [id] Specifies the id, if applicable. + * @param {String} [title = This is untitled.] Specifies the title. + */ +function Document(pages, id, title){ +} \ No newline at end of file diff --git a/bin/jsdoc/test/prototype.js b/bin/jsdoc/test/prototype.js new file mode 100644 index 00000000..11470083 --- /dev/null +++ b/bin/jsdoc/test/prototype.js @@ -0,0 +1,17 @@ +/** @constructor */ +function Article() { +} + +Article.prototype.init = function(title) { + /** the instance title */ + this.title = title; + + /** the static counter */ + Article.counter = 1; +} + +a = new Article(); +a.Init("my title"); + +print(a.title); +print(Article.counter); \ No newline at end of file diff --git a/bin/jsdoc/test/prototype_nested.js b/bin/jsdoc/test/prototype_nested.js new file mode 100644 index 00000000..e8ca1ced --- /dev/null +++ b/bin/jsdoc/test/prototype_nested.js @@ -0,0 +1,9 @@ +/** @constructor */ +function Word() { +} + +Word.prototype.reverse = function() { +} + +Word.prototype.reverse.utf8 = function() { +} \ No newline at end of file diff --git a/bin/jsdoc/test/prototype_oblit.js b/bin/jsdoc/test/prototype_oblit.js new file mode 100644 index 00000000..6cfc39ca --- /dev/null +++ b/bin/jsdoc/test/prototype_oblit.js @@ -0,0 +1,13 @@ +/** @constructor */ +function Article() { +} + +Article.prototype = { + /** instance get title */ + getTitle: function(){ + } +} + +/** static get title */ +Article.getTitle = function(){ +} \ No newline at end of file diff --git a/bin/jsdoc/test/prototype_oblit_constructor.js b/bin/jsdoc/test/prototype_oblit_constructor.js new file mode 100644 index 00000000..92482486 --- /dev/null +++ b/bin/jsdoc/test/prototype_oblit_constructor.js @@ -0,0 +1,24 @@ +/** @constructor */ +function Article() { +} + +Article.prototype = { + /** @constructor */ + Title: function(title) { + /** the value of the Title instance */ + this.title = title; + }, + + init: function(pages) { + /** the value of the pages of the Article instance */ + this.pages = pages; + } +} + +f = new Article(); +f.init("one two three"); + +t = new f.Title("my title"); + +print(f.pages); +print(t.title); \ No newline at end of file diff --git a/bin/jsdoc/test/public.js b/bin/jsdoc/test/public.js new file mode 100644 index 00000000..35d34f6f --- /dev/null +++ b/bin/jsdoc/test/public.js @@ -0,0 +1,10 @@ +/**@constructor*/ +function Foo() { + /** + @public + @static + @field + */ + var bar = function(x) { + } +} \ No newline at end of file diff --git a/bin/jsdoc/test/scripts/code.js b/bin/jsdoc/test/scripts/code.js new file mode 100644 index 00000000..e9d7ed2e --- /dev/null +++ b/bin/jsdoc/test/scripts/code.js @@ -0,0 +1,5 @@ +/** + @class + */ +function thisiscode() { +} \ No newline at end of file diff --git a/bin/jsdoc/test/scripts/notcode.txt b/bin/jsdoc/test/scripts/notcode.txt new file mode 100644 index 00000000..fcd737e7 --- /dev/null +++ b/bin/jsdoc/test/scripts/notcode.txt @@ -0,0 +1,5 @@ +(This is not code) +function foo(){{{{ +( +! +@ \ No newline at end of file diff --git a/bin/jsdoc/test/shared.js b/bin/jsdoc/test/shared.js new file mode 100644 index 00000000..e1c277a6 --- /dev/null +++ b/bin/jsdoc/test/shared.js @@ -0,0 +1,42 @@ + +/** + * Builtin object. + * @class + * @name Array + */ + +/**#@+ + * Extension to builtin array. + * @memberOf Array + * @method + */ + +/** + * @returns Boolen if some array members... + */ +Array.prototype.some = function(){}; + +/** + * Change every element of an array. + * @returns Filtered array copy. + */ +Array.prototype.filter = function(){}; + +/**#@-*/ + + +/** + * A first in, first out data structure. + * @constructor + */ +Queue = function(){}; + +/**#@+ + * Extension to Queue. + * @memberOf Queue + */ + +rewind = function(){ +} + +// should close automatically here. \ No newline at end of file diff --git a/bin/jsdoc/test/shared2.js b/bin/jsdoc/test/shared2.js new file mode 100644 index 00000000..3f7736a7 --- /dev/null +++ b/bin/jsdoc/test/shared2.js @@ -0,0 +1,2 @@ +startOver = function(){ +} \ No newline at end of file diff --git a/bin/jsdoc/test/shortcuts.js b/bin/jsdoc/test/shortcuts.js new file mode 100644 index 00000000..f738f1e1 --- /dev/null +++ b/bin/jsdoc/test/shortcuts.js @@ -0,0 +1,22 @@ +// /**#=+ +// * { +// * 'D': 'Date.prototype', +// * '$N': 'Number' +// * } +// */ +// var D = Date.prototype, +// $N = Number; +// +// D.locale = function(){ +// }; +// +// /** +// @return {string} The cardinal number string. +// */ +// $N.nth = function(n){ +// }; +// +// LOAD.file = function(){ +// } +// +// /**#=-*/ \ No newline at end of file diff --git a/bin/jsdoc/test/static_this.js b/bin/jsdoc/test/static_this.js new file mode 100644 index 00000000..9407b20f --- /dev/null +++ b/bin/jsdoc/test/static_this.js @@ -0,0 +1,13 @@ +/** the parent */ +var box = {}; + +/** @namespace */ +box.holder = {} + +box.holder.foo = function() { + /** the counter */ + this.counter = 1; +} + +box.holder.foo(); +print(box.holder.counter); diff --git a/bin/jsdoc/test/synonyms.js b/bin/jsdoc/test/synonyms.js new file mode 100644 index 00000000..09066b98 --- /dev/null +++ b/bin/jsdoc/test/synonyms.js @@ -0,0 +1,31 @@ +/** + @class + @inherits Bar#zop as #my_zop +*/ +function Foo() { + /** this is a zip. */ + this.zip = function() {} + + /** from Bar */ + this.my_zop = new Bar().zop; +} + +/** + @class + @borrows Foo#zip as this.my_zip +*/ +function Bar() { + /** this is a zop. */ + this.zop = function() {} + + /** from Foo */ + this.my_zip = new Foo().zip; +} + +/** @namespace */ +var myObject = { + /** + @type function + */ + myFunc: getFunction() +} \ No newline at end of file diff --git a/bin/jsdoc/test/tosource.js b/bin/jsdoc/test/tosource.js new file mode 100644 index 00000000..706d4765 --- /dev/null +++ b/bin/jsdoc/test/tosource.js @@ -0,0 +1,23 @@ +/** + * @param {Object} object + * @return {string} + */ +function valueOf(object) {} + +/** + * @param {Object} object + * @return {string} + */ +function toString(object) {} + +/** + * @param {Object} object + * @return {string} + */ +function toSource(object) {} + +/** + * @param {Object} object + * @return {string} + */ +function constructor(object) {} \ No newline at end of file diff --git a/bin/jsdoc/test/variable_redefine.js b/bin/jsdoc/test/variable_redefine.js new file mode 100644 index 00000000..2c07da09 --- /dev/null +++ b/bin/jsdoc/test/variable_redefine.js @@ -0,0 +1,14 @@ +/** @constructor */ +function Foo() { + var bar = 1; + bar = 2; // redefining a private + + this.baz = 1; + baz = 2; // global + + /** a private */ + var blap = { + /** in here */ + tada: 1 + } +} \ No newline at end of file diff --git a/bin/run-jsdoc.js b/bin/run-jsdoc.js new file mode 100644 index 00000000..1f875cdb --- /dev/null +++ b/bin/run-jsdoc.js @@ -0,0 +1,348 @@ +/** + * @fileOverview + * A bootstrap script that creates some basic required objects + * for loading other scripts. + * @author Michael Mathews, micmath@gmail.com + * @version $Id: run.js 756 2009-01-07 21:32:58Z micmath $ + */ + +/** + * @namespace Keep track of any messages from the running script. + */ +LOG = { + warn: function(msg, e) { + if (JSDOC.opt.q) return; + if (e) msg = e.fileName+", line "+e.lineNumber+": "+msg; + + msg = ">> WARNING: "+msg; + LOG.warnings.push(msg); + if (LOG.out) LOG.out.write(msg+"\n"); + else print(msg); + }, + + inform: function(msg) { + if (JSDOC.opt.q) return; + msg = " > "+msg; + if (LOG.out) LOG.out.write(msg+"\n"); + else if (typeof LOG.verbose != "undefined" && LOG.verbose) print(msg); + } +}; +LOG.warnings = []; +LOG.verbose = false +LOG.out = undefined; + +/** + * @class Manipulate a filepath. + */ +function FilePath(absPath, separator) { + this.slash = separator || "/"; + this.root = this.slash; + this.path = []; + this.file = ""; + + var parts = absPath.split(/[\\\/]/); + if (parts) { + if (parts.length) this.root = parts.shift() + this.slash; + if (parts.length) this.file = parts.pop() + if (parts.length) this.path = parts; + } + + this.path = this.resolvePath(); +} + +/** Collapse any dot-dot or dot items in a filepath. */ +FilePath.prototype.resolvePath = function() { + var resolvedPath = []; + for (var i = 0; i < this.path.length; i++) { + if (this.path[i] == "..") resolvedPath.pop(); + else if (this.path[i] != ".") resolvedPath.push(this.path[i]); + } + return resolvedPath; +} + +/** Trim off the filename. */ +FilePath.prototype.toDir = function() { + if (this.file) this.file = ""; + return this; +} + +/** Go up a directory. */ +FilePath.prototype.upDir = function() { + this.toDir(); + if (this.path.length) this.path.pop(); + return this; +} + +FilePath.prototype.toString = function() { + return this.root + + this.path.join(this.slash) + + ((this.path.length > 0)? this.slash : "") + + this.file; +} + +/** + * Turn a path into just the name of the file. + */ +FilePath.fileName = function(path) { + var nameStart = Math.max(path.lastIndexOf("/")+1, path.lastIndexOf("\\")+1, 0); + return path.substring(nameStart); +} + +/** + * Get the extension of a filename + */ +FilePath.fileExtension = function(filename) { + return filename.split(".").pop().toLowerCase(); +}; + +/** + * Turn a path into just the directory part. + */ +FilePath.dir = function(path) { + var nameStart = Math.max(path.lastIndexOf("/")+1, path.lastIndexOf("\\")+1, 0); + return path.substring(0, nameStart-1); +} + + +importClass(java.lang.System); + +/** + * @namespace A collection of information about your system. + */ +SYS = { + /** + * Information about your operating system: arch, name, version. + * @type string + */ + os: [ + new String(System.getProperty("os.arch")), + new String(System.getProperty("os.name")), + new String(System.getProperty("os.version")) + ].join(", "), + + /** + * Which way does your slash lean. + * @type string + */ + slash: System.getProperty("file.separator")||"/", + + /** + * The path to the working directory where you ran java. + * @type string + */ + userDir: new String(System.getProperty("user.dir")), + + /** + * Where is Java's home folder. + * @type string + */ + javaHome: new String(System.getProperty("java.home")), + + /** + * The absolute path to the directory containing this script. + * @type string + */ + pwd: undefined +}; + +// jsrun appends an argument, with the path to here. +if (arguments[arguments.length-1].match(/^-j=(.+)/)) { + if (RegExp.$1.charAt(0) == SYS.slash || RegExp.$1.charAt(1) == ":") { // absolute path to here + SYS.pwd = new FilePath(RegExp.$1).toDir().toString(); + } + else { // relative path to here + SYS.pwd = new FilePath(SYS.userDir + SYS.slash + RegExp.$1).toDir().toString(); + } + arguments.pop(); +} +else { + print("The run.js script requires you use jsrun.jar."); + quit(); +} + +// shortcut +var File = Packages.java.io.File; + +/** + * @namespace A collection of functions that deal with reading a writing to disk. + */ +IO = { + + /** + * Create a new file in the given directory, with the given name and contents. + */ + saveFile: function(/**string*/ outDir, /**string*/ fileName, /**string*/ content) { + var out = new Packages.java.io.PrintWriter( + new Packages.java.io.OutputStreamWriter( + new Packages.java.io.FileOutputStream(outDir+SYS.slash+fileName), + IO.encoding + ) + ); + out.write(content); + out.flush(); + out.close(); + }, + + /** + * @type string + */ + readFile: function(/**string*/ path) { + if (!IO.exists(path)) { + throw "File doesn't exist there: "+path; + } + return readFile(path, IO.encoding); + }, + + /** + * @param inFile + * @param outDir + * @param [fileName=The original filename] + */ + copyFile: function(/**string*/ inFile, /**string*/ outDir, /**string*/ fileName) { + if (fileName == null) fileName = FilePath.fileName(inFile); + + var inFile = new File(inFile); + var outFile = new File(outDir+SYS.slash+fileName); + + var bis = new Packages.java.io.BufferedInputStream(new Packages.java.io.FileInputStream(inFile), 4096); + var bos = new Packages.java.io.BufferedOutputStream(new Packages.java.io.FileOutputStream(outFile), 4096); + var theChar; + while ((theChar = bis.read()) != -1) { + bos.write(theChar); + } + bos.close(); + bis.close(); + }, + + /** + * Creates a series of nested directories. + */ + mkPath: function(/**Array*/ path) { + if (path.constructor != Array) path = path.split(/[\\\/]/); + var make = ""; + for (var i = 0, l = path.length; i < l; i++) { + make += path[i] + SYS.slash; + if (! IO.exists(make)) { + IO.makeDir(make); + } + } + }, + + /** + * Creates a directory at the given path. + */ + makeDir: function(/**string*/ path) { + (new File(path)).mkdir(); + }, + + /** + * @type string[] + * @param dir The starting directory to look in. + * @param [recurse=1] How many levels deep to scan. + * @returns An array of all the paths to files in the given dir. + */ + ls: function(/**string*/ dir, /**number*/ recurse, _allFiles, _path) { + if (_path === undefined) { // initially + var _allFiles = []; + var _path = [dir]; + } + if (_path.length == 0) return _allFiles; + if (recurse === undefined) recurse = 1; + + dir = new File(dir); + if (!dir.directory) return [String(dir)]; + var files = dir.list(); + + for (var f = 0; f < files.length; f++) { + var file = String(files[f]); + if (file.match(/^\.[^\.\/\\]/)) continue; // skip dot files + + if ((new File(_path.join(SYS.slash)+SYS.slash+file)).list()) { // it's a directory + _path.push(file); + if (_path.length-1 < recurse) IO.ls(_path.join(SYS.slash), recurse, _allFiles, _path); + _path.pop(); + } + else { + _allFiles.push((_path.join(SYS.slash)+SYS.slash+file).replace(SYS.slash+SYS.slash, SYS.slash)); + } + } + + return _allFiles; + }, + + /** + * @type boolean + */ + exists: function(/**string*/ path) { + file = new File(path); + + if (file.isDirectory()){ + return true; + } + if (!file.exists()){ + return false; + } + if (!file.canRead()){ + return false; + } + return true; + }, + + /** + * + */ + open: function(/**string*/ path, /**string*/ append) { + var append = true; + var outFile = new File(path); + var out = new Packages.java.io.PrintWriter( + new Packages.java.io.OutputStreamWriter( + new Packages.java.io.FileOutputStream(outFile, append), + IO.encoding + ) + ); + return out; + }, + + /** + * Sets {@link IO.encoding}. + * Encoding is used when reading and writing text to files, + * and in the meta tags of HTML output. + */ + setEncoding: function(/**string*/ encoding) { + if (/ISO-8859-([0-9]+)/i.test(encoding)) { + IO.encoding = "ISO8859_"+RegExp.$1; + } + else { + IO.encoding = encoding; + } + }, + + /** + * @default "utf-8" + * @private + */ + encoding: "utf-8", + + /** + * Load the given script. + */ + include: function(relativePath) { + load(SYS.pwd+relativePath); + }, + + /** + * Loads all scripts from the given directory path. + */ + includeDir: function(path) { + if (!path) return; + + for (var lib = IO.ls(SYS.pwd+path), i = 0; i < lib.length; i++) + if (/\.js$/i.test(lib[i])) load(lib[i]); + } +} + +// now run the application +IO.include("frame.js"); +IO.include("main.js"); + +main(); diff --git a/build.properties b/build.properties index 78ad7a3b..e40d3257 100644 --- a/build.properties +++ b/build.properties @@ -1,15 +1,19 @@ -#OpenSeadragon build.properties -#TODO: how do you auto-increment build_id's with every commit? +# OpenSeadragon build.properties +# TODO: how do you auto-increment build_id's with every commit? # TRY: continuos integration # TRY: git-hooks PROJECT: openseadragon BUILD_MAJOR: 0 BUILD_MINOR: 8 -BUILD_ID: 23 +BUILD_ID: 24 BUILD: ${PROJECT}.${BUILD_MAJOR}.${BUILD_MINOR}.${BUILD_ID} VERSION: ${BUILD_MAJOR}.${BUILD_MINOR}.${BUILD_ID} # This is the location of where we want to copy the built js file # and other distributables like images. WWW: ../www/openseadragon/ +WWW_DOCS: ${WWW}docs/ + +# Supporting libraries for supplimental build tasks +DOC_LIB: ./lib/jsdoc.jar diff --git a/build.xml b/build.xml index 06090e41..5e05ca58 100644 --- a/build.xml +++ b/build.xml @@ -26,7 +26,7 @@ - + @@ -54,4 +54,18 @@ + + + | Generating Public API Documentation + + + + + + + + + \ No newline at end of file diff --git a/openseadragon.js b/openseadragon.js index 8298070c..a20ba81e 100644 --- a/openseadragon.js +++ b/openseadragon.js @@ -1,9 +1,26 @@ /** - * (c) 2011 Christopher Thatcher - * (c) 2010 OpenSeadragon - * (c) 2010 CodePlex Foundation + * @version OpenSeadragon 0.8.24 * - * OpenSeadragon 0.8.23 + * @fileOverview + *

+ * + * OpenSeadragon - Javascript Deep Zooming + * + *

+ *

+ * OpenSeadragon is provides an html interface for creating + * deep zoom user interfaces. The simplest examples include deep + * zoom for large resolution images, and complex examples include + * zoomable map interfaces driven by SVG files. + *

+ * + * @author
(c) 2011 Christopher Thatcher + * @author
(c) 2010 OpenSeadragon Team + * @author
(c) 2010 CodePlex Foundation + * + *

+ * Original license preserved below:
+ *

  * ----------------------------------------------------------------------------
  * 
  *  License: New BSD License (BSD)
@@ -37,11 +54,21 @@
  *  POSSIBILITY OF SUCH DAMAGE.
  * 
  * ----------------------------------------------------------------------------
- *
+ * 
+ *

**/ + /** + * The root namespace for OpenSeadragon. All utility methods and classes + * are defined on or below this namespace. The OpenSeadragon namespace will + * only be defined once even if mutliple versions are loaded on the page in + * succession. + * @namespace + * @name OpenSeadragon + * @exports $ as OpenSeadragon + */ OpenSeadragon = window.OpenSeadragon || (function(){ - + //Taken from jquery 1.6.1 // [[Class]] -> type pairs var class2type = { @@ -120,36 +147,52 @@ OpenSeadragon = window.OpenSeadragon || (function(){ }()); -(function( $ ){ - +(function( $ ){ + + /** + * @static + * @ignore + */ $.SIGNAL = "----seadragon----"; - $.delegate = function(object, method) { + /** + * Invokes the the method as if it where a method belonging to the object. + * @param {Object} object + * @param {Function} method + */ + $.delegate = function( object, method ) { return function() { - if (arguments === undefined) + if ( arguments === undefined ) arguments = []; - return method.apply(object, arguments); + return method.apply( object, arguments ); }; }; - - //Taken from jQuery 1.6.1: + + /** + * Taken from jQuery 1.6.1, see the jQuery documentation + */ $.extend = function() { - var options, name, src, copy, copyIsArray, clone, - target = arguments[0] || {}, - i = 1, - length = arguments.length, - deep = false; + var options, + name, + src, + copy, + copyIsArray, + clone, + target = arguments[ 0 ] || {}, + length = arguments.length, + deep = false, + i = 1; // Handle a deep copy situation if ( typeof target === "boolean" ) { - deep = target; - target = arguments[1] || {}; + deep = target; + target = arguments[ 1 ] || {}; // skip the boolean and the target i = 2; } // Handle case when target is a string or something (possible in deep copy) - if ( typeof target !== "object" && !OpenSeadragon.isFunction(target) ) { + if ( typeof target !== "object" && !OpenSeadragon.isFunction( target ) ) { target = {}; } @@ -161,7 +204,7 @@ OpenSeadragon = window.OpenSeadragon || (function(){ for ( ; i < length; i++ ) { // Only deal with non-null/undefined values - if ( (options = arguments[ i ]) != null ) { + if ( ( options = arguments[ i ] ) != null ) { // Extend the base object for ( name in options ) { src = target[ name ]; @@ -173,13 +216,13 @@ OpenSeadragon = window.OpenSeadragon || (function(){ } // Recurse if we're merging plain objects or arrays - if ( deep && copy && ( OpenSeadragon.isPlainObject(copy) || (copyIsArray = OpenSeadragon.isArray(copy)) ) ) { + if ( deep && copy && ( OpenSeadragon.isPlainObject( copy ) || ( copyIsArray = OpenSeadragon.isArray( copy ) ) ) ) { if ( copyIsArray ) { copyIsArray = false; - clone = src && OpenSeadragon.isArray(src) ? src : []; + clone = src && OpenSeadragon.isArray( src ) ? src : []; } else { - clone = src && OpenSeadragon.isPlainObject(src) ? src : {}; + clone = src && OpenSeadragon.isPlainObject( src ) ? src : {}; } // Never move original objects, clone them @@ -198,10 +241,16 @@ OpenSeadragon = window.OpenSeadragon || (function(){ }; //The following functions are originally from the Openseadragon Utils - //module but have been moved to Openseadragon to avoid the Utils anti- + //module but have been moved to Openseadragon to avoid the 'Utils' anti- //pattern. Not all of the code is A-grade compared to equivalent functions // from libraries like jquery, but until we need better we'll leave those //orignally developed by the project. + + /** + * An enumeration of Browser vendors including UNKNOWN, IE, FIREFOX, + * SAFARI, CHROME, and OPERA. + * @static + */ $.BROWSERS = { UNKNOWN: 0, IE: 1, @@ -211,6 +260,13 @@ OpenSeadragon = window.OpenSeadragon || (function(){ OPERA: 5 }; + /** + * The current browser vendor, version, and related information regarding + * detected features. Features include
+ * 'alpha' - Does the browser support image alpha + * transparency.
+ * @static + */ $.Browser = { vendor: $.BROWSERS.UNKNOWN, version: 0, @@ -233,7 +289,8 @@ OpenSeadragon = window.OpenSeadragon || (function(){ URLPARAMS = {}; (function() { - + //A small auto-executing routine to determine the browser vendor, + //version and supporting feature sets. var app = navigator.appName, ver = navigator.appVersion, ua = navigator.userAgent; @@ -277,8 +334,8 @@ OpenSeadragon = window.OpenSeadragon || (function(){ break; } - - var query = window.location.search.substring( 1 ), // ignore '?' + // ignore '?' portion of query string + var query = window.location.search.substring( 1 ), parts = query.split('&'), part, sep, @@ -294,7 +351,7 @@ OpenSeadragon = window.OpenSeadragon || (function(){ } } - //determine if this browser supports + //determine if this browser supports image alpha transparency $.Browser.alpha = !( $.Browser.vendor == $.BROWSERS.IE || ( $.Browser.vendor == $.BROWSERS.CHROME && @@ -304,16 +361,28 @@ OpenSeadragon = window.OpenSeadragon || (function(){ })(); - //TODO: $.Debug is often used inside a try/catch block which generally + //TODO: $.console is often used inside a try/catch block which generally // prevents allowings errors to occur with detection until a debugger // is attached. Although I've been guilty of the same anti-pattern // I eventually was convinced that errors should naturally propogate in // all but the most special cases. - $.Debug = window.console ? window.console : function(){}; + /** + * A convenient alias for console when available, and a simple null + * function when console is unavailable. + * @static + */ + $.console = window.console ? window.console : function(){}; $.extend( $, { + /** + * Returns a DOM Element for the given id or element. + * @function + * @name OpenSeadragon.getElement + * @param {String|Element} element Accepts an id or element. + * @returns {Element} The element with the given id, null, or the element itself. + */ getElement: function( element ) { if ( typeof ( element ) == "string") { element = document.getElementById( element ); @@ -321,6 +390,13 @@ OpenSeadragon = window.OpenSeadragon || (function(){ return element; }, + /** + * @function + * @name OpenSeadragon.getOffsetParent + * @param {Element} element + * @param {Boolean} [isFixed] + * @returns {Element} + */ getOffsetParent: function( element, isFixed ) { if ( isFixed && element != document.body ) { return document.body; @@ -329,6 +405,12 @@ OpenSeadragon = window.OpenSeadragon || (function(){ } }, + /** + * @function + * @name OpenSeadragon.getElementPosition + * @param {Element|String} element + * @returns {Point} + */ getElementPosition: function( element ) { var result = new $.Point(), isFixed, @@ -355,6 +437,12 @@ OpenSeadragon = window.OpenSeadragon || (function(){ return result; }, + /** + * @function + * @name OpenSeadragon.getElementSize + * @param {Element|String} element + * @returns {Point} + */ getElementSize: function( element ) { element = $.getElement( element ); @@ -364,6 +452,12 @@ OpenSeadragon = window.OpenSeadragon || (function(){ ); }, + /** + * @function + * @name OpenSeadragon.getElementStyle + * @param {Element|String} element + * @returns {CSSStyle} + */ getElementStyle: function( element ) { element = $.getElement( element ); @@ -376,10 +470,22 @@ OpenSeadragon = window.OpenSeadragon || (function(){ } }, + /** + * @function + * @name OpenSeadragon.getEvent + * @param {Event} [event] + * @returns {Event} + */ getEvent: function( event ) { return event ? event : window.event; }, + /** + * @function + * @name OpenSeadragon.getMousePosition + * @param {Event} [event] + * @returns {Point} + */ getMousePosition: function( event ) { var result = new $.Point(); @@ -406,6 +512,11 @@ OpenSeadragon = window.OpenSeadragon || (function(){ return result; }, + /** + * @function + * @name OpenSeadragon.getPageScroll + * @returns {Point} + */ getPageScroll: function() { var result = new $.Point(), docElmt = document.documentElement || {}, @@ -425,6 +536,11 @@ OpenSeadragon = window.OpenSeadragon || (function(){ return result; }, + /** + * @function + * @name OpenSeadragon.getWindowSize + * @returns {Point} + */ getWindowSize: function() { var result = new $.Point(), docElmt = document.documentElement || {}, @@ -446,11 +562,23 @@ OpenSeadragon = window.OpenSeadragon || (function(){ return result; }, + /** + * @function + * @name OpenSeadragon.imageFormatSupported + * @param {String} [extension] + * @returns {Boolean} + */ imageFormatSupported: function( extension ) { extension = extension ? extension : ""; return !!FILEFORMATS[ extension.toLowerCase() ]; }, + /** + * @function + * @name OpenSeadragon.makeCenteredNode + * @param {Element|String} element + * @returns {Element} + */ makeCenteredNode: function( element ) { var div = $.makeNeutralElement( "div" ), @@ -488,6 +616,12 @@ OpenSeadragon = window.OpenSeadragon || (function(){ return div; }, + /** + * @function + * @name OpenSeadragon.makeNeutralElement + * @param {String} tagName + * @returns {Element} + */ makeNeutralElement: function( tagName ) { var element = document.createElement( tagName ), style = element.style; @@ -501,6 +635,12 @@ OpenSeadragon = window.OpenSeadragon || (function(){ return element; }, + /** + * @function + * @name OpenSeadragon.makeTransparentImage + * @param {String} src + * @returns {Element} + */ makeTransparentImage: function( src ) { var img = $.makeNeutralElement( "img" ), element = null; @@ -535,6 +675,13 @@ OpenSeadragon = window.OpenSeadragon || (function(){ return element; }, + /** + * @function + * @name OpenSeadragon.setElementOpacity + * @param {Element|String} element + * @param {Number} opacity + * @param {Boolean} [usesAlpha] + */ setElementOpacity: function( element, opacity, usesAlpha ) { var previousFilter, @@ -575,6 +722,15 @@ OpenSeadragon = window.OpenSeadragon || (function(){ } }, + /** + * @function + * @name OpenSeadragon.addEvent + * @param {Element|String} element + * @param {String} eventName + * @param {Function} handler + * @param {Boolean} [useCapture] + * @throws {Error} + */ addEvent: function( element, eventName, handler, useCapture ) { element = $.getElement( element ); @@ -594,6 +750,15 @@ OpenSeadragon = window.OpenSeadragon || (function(){ } }, + /** + * @function + * @name OpenSeadragon.removeEvent + * @param {Element|String} element + * @param {String} eventName + * @param {Function} handler + * @param {Boolean} [useCapture] + * @throws {Error} + */ removeEvent: function( element, eventName, handler, useCapture ) { element = $.getElement( element ); @@ -613,17 +778,29 @@ OpenSeadragon = window.OpenSeadragon || (function(){ } }, + /** + * @function + * @name OpenSeadragon.cancelEvent + * @param {Event} [event] + */ cancelEvent: function( event ) { event = $.getEvent( event ); if ( event.preventDefault ) { - event.preventDefault(); // W3C for preventing default + // W3C for preventing default + event.preventDefault(); } - - event.cancel = true; // legacy for preventing default - event.returnValue = false; // IE for preventing default + // legacy for preventing default + event.cancel = true; + // IE for preventing default + event.returnValue = false; }, + /** + * @function + * @name OpenSeadragon.stopEvent + * @param {Event} [event] + */ stopEvent: function( event ) { event = $.getEvent( event ); @@ -634,6 +811,14 @@ OpenSeadragon = window.OpenSeadragon || (function(){ event.cancelBubble = true; // IE for stopping propagation }, + /** + * @function + * @name OpenSeadragon.createCallback + * @param {Object} object + * @param {Function} method + * @param [args] any additional arguments are passed as arguments to the created callback + * @returns {Function} + */ createCallback: function( object, method ) { //TODO: This pattern is painful to use and debug. It's much cleaner // to use pinning plus anonymous functions. Get rid of this @@ -655,11 +840,23 @@ OpenSeadragon = window.OpenSeadragon || (function(){ }; }, + /** + * @function + * @name OpenSeadragon.getUrlParameter + * @param {String} key + * @returns {String} The value of the url parameter or null if no param matches. + */ getUrlParameter: function( key ) { var value = URLPARAMS[ key ]; return value ? value : null; }, + /** + * @function + * @name OpenSeadragon.makeAjaxRequest + * @param {String} url + * @param {Function} [callback] + */ makeAjaxRequest: function( url, callback ) { var async = typeof( callback ) == "function", request = null, @@ -699,6 +896,7 @@ OpenSeadragon = window.OpenSeadragon || (function(){ if ( async ) { + /** @ignore */ request.onreadystatechange = function() { if ( request.readyState == 4) { request.onreadystatechange = new function() { }; @@ -728,6 +926,13 @@ OpenSeadragon = window.OpenSeadragon || (function(){ return async ? null : request; }, + /** + * Parses an XML string into a DOM Document. + * @function + * @name OpenSeadragon.parseXml + * @param {String} string + * @returns {Document} + */ parseXml: function( string ) { //TODO: yet another example where we can determine the correct // implementation once at start-up instead of everytime we use @@ -759,61 +964,63 @@ OpenSeadragon = window.OpenSeadragon || (function(){ (function($){ +/** + * @class + */ +$.EventHandler = function() { + this.events = {}; +}; - $.EventHandler = function() { - this.events = {}; - }; +$.EventHandler.prototype = { - $.EventHandler.prototype = { - - addHandler: function( id, handler ) { - var events = this.events[ id ]; - if( !events ){ - this.events[ id ] = events = []; - } - events[ events.length ] = handler; - }, - - removeHandler: function( id, handler ) { - //Start Thatcher - unneccessary indirection. Also, because events were - // - not actually being removed, we need to add the code - // - to do the removal ourselves. TODO - var events = this.events[ id ]; - if ( !events ){ - return; - } - //End Thatcher - }, - - getHandler: function( id ) { - var events = this.events[ id ]; - if ( !events || !events.length ){ - return null; - } - events = events.length === 1 ? - [ events[ 0 ] ] : - Array.apply( null, events ); - return function( source, args ) { - var i, - length = events.length; - for ( i = 0; i < length; i++ ) { - events[ i ]( source, args ); - } - }; - }, - - raiseEvent: function( eventName, eventArgs ) { - var handler = this.getHandler( eventName ); - - if ( handler ) { - if ( !eventArgs ) { - eventArgs = new Object(); - } - - handler( this, eventArgs ); - } + addHandler: function( id, handler ) { + var events = this.events[ id ]; + if( !events ){ + this.events[ id ] = events = []; } - }; + events[ events.length ] = handler; + }, + + removeHandler: function( id, handler ) { + //Start Thatcher - unneccessary indirection. Also, because events were + // - not actually being removed, we need to add the code + // - to do the removal ourselves. TODO + var events = this.events[ id ]; + if ( !events ){ + return; + } + //End Thatcher + }, + + getHandler: function( id ) { + var events = this.events[ id ]; + if ( !events || !events.length ){ + return null; + } + events = events.length === 1 ? + [ events[ 0 ] ] : + Array.apply( null, events ); + return function( source, args ) { + var i, + length = events.length; + for ( i = 0; i < length; i++ ) { + events[ i ]( source, args ); + } + }; + }, + + raiseEvent: function( eventName, eventArgs ) { + var handler = this.getHandler( eventName ); + + if ( handler ) { + if ( !eventArgs ) { + eventArgs = new Object(); + } + + handler( this, eventArgs ); + } + } +}; }( OpenSeadragon )); @@ -833,7 +1040,9 @@ OpenSeadragon = window.OpenSeadragon || (function(){ ieTrackersActive = {}, // dictionary from hash to MouseTracker ieTrackersCapturing = []; // list of trackers interested in capture - + /** + * @class + */ $.MouseTracker = function (elmt, clickTimeThreshold, clickDistThreshold) { //Start Thatcher - TODO: remove local function definitions in favor of // - a global closure for MouseTracker so the number @@ -986,7 +1195,7 @@ OpenSeadragon = window.OpenSeadragon || (function(){ self.enterHandler(self, getMouseRelative(event, elmt), buttonDownElmt, buttonDownAny); } catch (e) { - $.Debug.error(e.name + + $.console.error(e.name + " while executing enter handler: " + e.message, e); } } @@ -1012,7 +1221,7 @@ OpenSeadragon = window.OpenSeadragon || (function(){ self.exitHandler(self, getMouseRelative(event, elmt), buttonDownElmt, buttonDownAny); } catch (e) { - $.Debug.error(e.name + + $.console.error(e.name + " while executing exit handler: " + e.message, e); } } @@ -1035,7 +1244,7 @@ OpenSeadragon = window.OpenSeadragon || (function(){ try { self.pressHandler(self, getMouseRelative(event, elmt)); } catch (e) { - $.Debug.error(e.name + + $.console.error(e.name + " while executing press handler: " + e.message, e); } } @@ -1069,7 +1278,7 @@ OpenSeadragon = window.OpenSeadragon || (function(){ self.releaseHandler(self, getMouseRelative(event, elmt), insideElmtPress, insideElmtRelease); } catch (e) { - $.Debug.error(e.name + + $.console.error(e.name + " while executing release handler: " + e.message, e); } } @@ -1152,7 +1361,7 @@ OpenSeadragon = window.OpenSeadragon || (function(){ try { self.scrollHandler(self, getMouseRelative(event, elmt), nDelta, event.shiftKey); } catch (e) { - $.Debug.error(e.name + + $.console.error(e.name + " while executing scroll handler: " + e.message, e); } @@ -1178,7 +1387,7 @@ OpenSeadragon = window.OpenSeadragon || (function(){ self.clickHandler(self, getMouseRelative(event, elmt), quick, event.shiftKey); } catch (e) { - $.Debug.error(e.name + + $.console.error(e.name + " while executing click handler: " + e.message, e); } } @@ -1200,7 +1409,7 @@ OpenSeadragon = window.OpenSeadragon || (function(){ event.shiftKey ); } catch (e) { - $.Debug.error( + $.console.error( e.name + " while executing drag handler: " + e.message, @@ -1240,6 +1449,7 @@ OpenSeadragon = window.OpenSeadragon || (function(){ } /** + * @private * Returns true if elmtB is a child node of elmtA, or if they're equal. */ function isChild( elmtA, elmtB ) { @@ -1277,7 +1487,12 @@ OpenSeadragon = window.OpenSeadragon || (function(){ (function( $ ){ - +/** + * An enumeration of supported locations where controls can be anchored, + * including NONE, TOP_LEFT, TOP_RIGHT, BOTTOM_RIGHT, and BOTTOM_LEFT. + * The anchoring is always relative to the container + * @static + */ $.ControlAnchor = { NONE: 0, TOP_LEFT: 1, @@ -1286,6 +1501,24 @@ $.ControlAnchor = { BOTTOM_LEFT: 4 }; +/** + * A Control represents any interface element which is meant to allow the user + * to interact with the zoomable interface. Any control can be anchored to any + * element. + * @class + * @param {Element} elmt - the contol element to be anchored in the container. + * @param {OpenSeadragon.ControlAnchor} anchor - the location to anchor at. + * @param {Element} container - the element to control will be anchored too. + * + * @property {Element} elmt - the element providing the user interface with + * some type of control. Eg a zoom-in button + * @property {OpenSeadragon.ControlAnchor} anchor - the position of the control + * relative to the container. + * @property {Element} container - the element within with the control is + * positioned. + * @property {Element} wrapper - a nuetral element surrounding the control + * element. + */ $.Control = function ( elmt, anchor, container ) { this.elmt = elmt; this.anchor = anchor; @@ -1312,21 +1545,40 @@ $.Control = function ( elmt, anchor, container ) { $.Control.prototype = { + /** + * Removes the control from the container. + * @function + */ destroy: function() { this.wrapper.removeChild( this.elmt ); this.container.removeChild( this.wrapper ); }, + /** + * Determines if the control is currently visible. + * @function + * @return {Boolean} true if currenly visible, false otherwise. + */ isVisible: function() { return this.wrapper.style.display != "none"; }, + /** + * Toggles the visibility of the control. + * @function + * @param {Boolean} visible - true to make visible, false to hide. + */ setVisible: function( visible ) { this.wrapper.style.display = visible ? "inline-block" : "none"; }, + /** + * Sets the opacity level for the control. + * @function + * @param {Number} opactiy - a value between 1 and 0 inclusively. + */ setOpacity: function( opacity ) { if ( this.elmt[ $.SIGNAL ] && $.Browser.vendor == $.BROWSERS.IE ) { $.setElementOpacity( this.elmt, opacity, true ); @@ -1340,7 +1592,7 @@ $.Control.prototype = { (function( $ ){ /** - * OpenSeadragon Viewer + * @class * * The main point of entry into creating a zoomable image on the page. * @@ -1726,7 +1978,7 @@ $.extend( $.Viewer.prototype, $.EventHandler.prototype, { this._lastOpenEndTime = +new Date(); if ( this._lastOpenStartTime < viewer._lastOpenStartTime ) { - $.Debug.log( "Ignoring out-of-date open." ); + $.console.log( "Ignoring out-of-date open." ); this.raiseEvent( "ignore" ); return; } @@ -1747,7 +1999,8 @@ $.extend( $.Viewer.prototype, $.EventHandler.prototype, { this.viewport, this.canvas ); - this.profiler = new $.Profiler(); + + //this.profiler = new $.Profiler(); this._animating = false; this._forceRedraw = true; @@ -1790,7 +2043,7 @@ $.extend( $.Viewer.prototype, $.EventHandler.prototype, { this.source = null; this.viewport = null; this.drawer = null; - this.profiler = null; + //this.profiler = null; this.canvas.innerHTML = ""; }, @@ -2337,6 +2590,9 @@ $.extend( $, { (function( $ ){ +/** + * @class + */ $.Point = function( x, y ) { this.x = typeof ( x ) == "number" ? x : 0; this.y = typeof ( y ) == "number" ? y : 0; @@ -2406,91 +2662,10 @@ $.Point.prototype = { (function( $ ){ -$.Profiler = function() { - - this.midUpdate = false; - this.numUpdates = 0; - - this.lastBeginTime = null; - this.lastEndTime = null; - - this.minUpdateTime = Infinity; - this.avgUpdateTime = 0; - this.maxUpdateTime = 0; - - this.minIdleTime = Infinity; - this.avgIdleTime = 0; - this.maxIdleTime = 0; -}; - -$.Profiler.prototype = { - - beginUpdate: function() { - if (this.midUpdate) { - this.endUpdate(); - } - - this.midUpdate = true; - this.lastBeginTime = new Date().getTime(); - - if (this.numUpdates < 1) { - return; // this is the first update - } - - var time = this.lastBeginTime - this.lastEndTime; - - this.avgIdleTime = (this.avgIdleTime * (this.numUpdates - 1) + time) / this.numUpdates; - - if (time < this.minIdleTime) { - this.minIdleTime = time; - } - if (time > this.maxIdleTime) { - this.maxIdleTime = time; - } - }, - - endUpdate: function() { - if (!this.midUpdate) { - return; - } - - this.lastEndTime = new Date().getTime(); - this.midUpdate = false; - - var time = this.lastEndTime - this.lastBeginTime; - - this.numUpdates++; - this.avgUpdateTime = (this.avgUpdateTime * (this.numUpdates - 1) + time) / this.numUpdates; - - if (time < this.minUpdateTime) { - this.minUpdateTime = time; - } - if (time > this.maxUpdateTime) { - this.maxUpdateTime = time; - } - }, - - clearProfile: function() { - this.midUpdate = false; - this.numUpdates = 0; - - this.lastBeginTime = null; - this.lastEndTime = null; - - this.minUpdateTime = Infinity; - this.avgUpdateTime = 0; - this.maxUpdateTime = 0; - - this.minIdleTime = Infinity; - this.avgIdleTime = 0; - this.maxIdleTime = 0; - } -}; - -}( OpenSeadragon )); - -(function( $ ){ +/** + * @class + */ $.TileSource = function( width, height, tileSize, tileOverlap, minLevel, maxLevel ) { this.aspectRatio = width / height; this.dimensions = new $.Point( width, height ); @@ -2567,7 +2742,9 @@ $.TileSource.prototype = { (function( $ ){ - +/** + * @class + */ $.DziTileSource = function( width, height, tileSize, tileOverlap, tilesUrl, fileFormat, displayRects ) { var i, rect, @@ -2641,6 +2818,9 @@ $.extend( $.DziTileSource.prototype, $.TileSource.prototype, { } }); +/** + * @static + */ $.DziTileSourceHelper = { createFromXml: function( xmlUrl, xmlString, callback ) { @@ -2821,8 +3001,13 @@ $.DziTileSourceHelper = { }( OpenSeadragon )); + (function( $ ){ +/** + * An enumeration of button states including, REST, GROUP, HOVER, and DOWN + * @static + */ $.ButtonState = { REST: 0, GROUP: 1, @@ -2830,6 +3015,18 @@ $.ButtonState = { DOWN: 3 }; +/** + * Manages events, hover states for individual buttons, tool-tips, as well + * as fading the bottons out when the user has not interacted with them + * for a specified period. + * @class + * @param {Object} options + * @param {String} options.tooltip + * @param {String} options.srcRest URL of image to use in 'rest' state + * @param {String} options.srcGroup URL of image to use in 'up' state + * @param {String} options.srcHover URL of image to use in 'hover' state + * @param {String} options.srcDown URL of image to use in 'domn' state + */ $.Button = function( options ) { var _this = this; @@ -3061,7 +3258,7 @@ function outTo( button, newState ) { (function( $ ){ /** - * OpenSeadragon ButtonGroup + * @class * * Manages events on groups of buttons. * @@ -3142,6 +3339,9 @@ $.ButtonGroup.prototype = { (function( $ ){ +/** + * @class + */ $.Rect = function( x, y, width, height ) { this.x = typeof ( x ) == "number" ? x : 0; this.y = typeof ( y ) == "number" ? y : 0; @@ -3199,6 +3399,9 @@ $.Rect.prototype = { (function( $ ){ +/** + * @class + */ $.DisplayRect = function( x, y, width, height, minLevel, maxLevel ) { $.Rect.apply( this, [ x, y, width, height ] ); @@ -3212,6 +3415,9 @@ $.extend( $.DisplayRect.prototype, $.Rect.prototype ); (function( $ ){ +/** + * @class + */ $.Spring = function( options ) { var args = arguments; @@ -3297,6 +3503,9 @@ function transform( stiffness, x ) { (function( $ ){ +/** + * @class + */ $.Tile = function(level, x, y, bounds, exists, url) { this.level = level; this.x = x; @@ -3334,7 +3543,7 @@ $.Tile.prototype = { size = this.size.apply( Math.ceil ); if ( !this.loaded ) { - $.Debug.warn( + $.console.warn( "Attempting to draw tile %s when it's not yet loaded.", this.toString() ); @@ -3370,7 +3579,7 @@ $.Tile.prototype = { size = this.size; if (!this.loaded) { - $.Debug.warn( + $.console.warn( "Attempting to draw tile %s when it's not yet loaded.", this.toString() ); @@ -3397,6 +3606,12 @@ $.Tile.prototype = { (function( $ ){ + /** + * An enumeration of positions that an overlay may be assigned relative + * to the viewport including CENTER, TOP_LEFT (default), TOP, TOP_RIGHT, + * RIGHT, BOTTOM_RIGHT, BOTTOM, BOTTOM_LEFT, and LEFT. + * @static + */ $.OverlayPlacement = { CENTER: 0, TOP_LEFT: 1, @@ -3409,6 +3624,9 @@ $.Tile.prototype = { LEFT: 8 }; + /** + * @class + */ $.Overlay = function( elmt, location, placement ) { this.elmt = elmt; this.scales = location instanceof $.Rect; @@ -3562,6 +3780,9 @@ var QUOTA = 100, USE_CANVAS = $.isFunction( document.createElement( "canvas" ).getContext ) && SUBPIXEL_RENDERING; +/** + * @class + */ $.Drawer = function(source, viewport, elmt) { this.container = $.getElement( elmt ); @@ -4328,7 +4549,11 @@ function numberOfTiles( drawer, level ){ }( OpenSeadragon )); (function( $ ){ - + + +/** + * @class + */ $.Viewport = function( options ) { var options; @@ -4377,16 +4602,19 @@ $.Viewport = function( options ) { }; $.Viewport.prototype = { + getHomeZoom: function() { var aspectFactor = this.contentAspect / this.getAspectRatio(); - return (aspectFactor >= 1) ? 1 : aspectFactor; + return ( aspectFactor >= 1 ) ? + 1 : + aspectFactor; }, getMinZoom: function() { var homeZoom = this.getHomeZoom() zoom = this.minZoomImageRatio * homeZoom; - return Math.min(zoom, homeZoom); + return Math.min( zoom, homeZoom ); }, getMaxZoom: function() { @@ -4394,7 +4622,7 @@ $.Viewport.prototype = { this.contentSize.x * this.maxZoomPixelRatio / this.containerSize.x; - return Math.max(zoom, this.getHomeZoom()); + return Math.max( zoom, this.getHomeZoom() ); }, getAspectRatio: function() { @@ -4402,12 +4630,15 @@ $.Viewport.prototype = { }, getContainerSize: function() { - return new $.Point(this.containerSize.x, this.containerSize.y); + return new $.Point( + this.containerSize.x, + this.containerSize.y + ); }, getBounds: function( current ) { - var center = this.getCenter(current), - width = 1.0 / this.getZoom(current), + var center = this.getCenter( current ), + width = 1.0 / this.getZoom( current ), height = width / this.getAspectRatio(); return new $.Rect( @@ -4436,9 +4667,9 @@ $.Viewport.prototype = { deltaZoomPixels, deltaZoomPoints; - if (current) { + if ( current ) { return centerCurrent; - } else if (!this.zoomPoint) { + } else if ( !this.zoomPoint ) { return centerTarget; } @@ -4531,6 +4762,9 @@ $.Viewport.prototype = { this.applyConstraints( immediately ); }, + /** + * + */ fitBounds: function( bounds, immediately ) { var aspect = this.getAspectRatio(), center = bounds.getCenter(), @@ -4545,7 +4779,7 @@ $.Viewport.prototype = { newZoom, referencePoint; - if (newBounds.getAspectRatio() >= aspect) { + if ( newBounds.getAspectRatio() >= aspect ) { newBounds.height = bounds.width / aspect; newBounds.y = center.y - newBounds.height / 2; } else { @@ -4553,13 +4787,13 @@ $.Viewport.prototype = { newBounds.x = center.x - newBounds.width / 2; } - this.panTo(this.getCenter(true), true); - this.zoomTo(this.getZoom(true), null, true); + this.panTo( this.getCenter( true ), true ); + this.zoomTo( this.getZoom( true ), null, true ); oldBounds = this.getBounds(); oldZoom = this.getZoom(); newZoom = 1.0 / newBounds.width; - if (newZoom == oldZoom || newBounds.width == oldBounds.width) { + if ( newZoom == oldZoom || newBounds.width == oldBounds.width ) { this.panTo( center, immediately ); return; } @@ -4579,25 +4813,27 @@ $.Viewport.prototype = { this.zoomTo( newZoom, referencePoint, immediately ); }, - goHome: function(immediately) { + goHome: function( immediately ) { var center = this.getCenter(); if ( this.wrapHorizontal ) { - center.x = (1 + (center.x % 1)) % 1; - this.centerSpringX.resetTo(center.x); + center.x = ( 1 + ( center.x % 1 ) ) % 1; + this.centerSpringX.resetTo( center.x ); this.centerSpringX.update(); } if ( this.wrapVertical ) { - center.y = (this.contentHeight + (center.y % this.contentHeight)) % this.contentHeight; - this.centerSpringY.resetTo(center.y); + center.y = ( + this.contentHeight + ( center.y % this.contentHeight ) + ) % this.contentHeight; + this.centerSpringY.resetTo( center.y ); this.centerSpringY.update(); } - this.fitBounds(this.homeBounds, immediately); + this.fitBounds( this.homeBounds, immediately ); }, - panBy: function(delta, immediately) { + panBy: function( delta, immediately ) { var center = new $.Point( this.centerSpringX.target.value, this.centerSpringY.target.value @@ -4605,44 +4841,49 @@ $.Viewport.prototype = { this.panTo( center.plus( delta ), immediately ); }, - panTo: function(center, immediately) { - if (immediately) { - this.centerSpringX.resetTo(center.x); - this.centerSpringY.resetTo(center.y); + panTo: function( center, immediately ) { + if ( immediately ) { + this.centerSpringX.resetTo( center.x ); + this.centerSpringY.resetTo( center.y ); } else { - this.centerSpringX.springTo(center.x); - this.centerSpringY.springTo(center.y); + this.centerSpringX.springTo( center.x ); + this.centerSpringY.springTo( center.y ); } }, - zoomBy: function(factor, refPoint, immediately) { - this.zoomTo(this.zoomSpring.target.value * factor, refPoint, immediately); + zoomBy: function( factor, refPoint, immediately ) { + this.zoomTo( this.zoomSpring.target.value * factor, refPoint, immediately ); }, - zoomTo: function(zoom, refPoint, immediately) { + zoomTo: function( zoom, refPoint, immediately ) { - if (immediately) { - this.zoomSpring.resetTo(zoom); + if ( immediately ) { + this.zoomSpring.resetTo( zoom ); } else { - this.zoomSpring.springTo(zoom); + this.zoomSpring.springTo( zoom ); } - this.zoomPoint = refPoint instanceof $.Point ? refPoint : null; + this.zoomPoint = refPoint instanceof $.Point ? + refPoint : + null; }, - resize: function(newContainerSize, maintain) { + resize: function( newContainerSize, maintain ) { var oldBounds = this.getBounds(), newBounds = oldBounds, widthDeltaFactor = newContainerSize.x / this.containerSize.x; - this.containerSize = new $.Point(newContainerSize.x, newContainerSize.y); + this.containerSize = new $.Point( + newContainerSize.x, + newContainerSize.y + ); if (maintain) { newBounds.width = oldBounds.width * widthDeltaFactor; newBounds.height = newBounds.width / this.getAspectRatio(); } - this.fitBounds(newBounds, true); + this.fitBounds( newBounds, true ); }, update: function() { @@ -4655,14 +4896,14 @@ $.Viewport.prototype = { deltaZoomPoints; if (this.zoomPoint) { - oldZoomPixel = this.pixelFromPoint(this.zoomPoint, true); + oldZoomPixel = this.pixelFromPoint( this.zoomPoint, true ); } this.zoomSpring.update(); if (this.zoomPoint && this.zoomSpring.current.value != oldZoom) { newZoomPixel = this.pixelFromPoint( this.zoomPoint, true ); - deltaZoomPixels = newZoomPixel.minus( oldZoomPixel); + deltaZoomPixels = newZoomPixel.minus( oldZoomPixel ); deltaZoomPoints = this.deltaPointsFromPixels( deltaZoomPixels, true ); this.centerSpringX.shiftBy( deltaZoomPoints.x ); @@ -4680,19 +4921,19 @@ $.Viewport.prototype = { }, - deltaPixelsFromPoints: function(deltaPoints, current) { + deltaPixelsFromPoints: function( deltaPoints, current ) { return deltaPoints.times( this.containerSize.x * this.getZoom( current ) ); }, - deltaPointsFromPixels: function(deltaPixels, current) { + deltaPointsFromPixels: function( deltaPixels, current ) { return deltaPixels.divide( this.containerSize.x * this.getZoom( current ) ); }, - pixelFromPoint: function(point, current) { + pixelFromPoint: function( point, current ) { var bounds = this.getBounds( current ); return point.minus( bounds.getTopLeft() @@ -4701,7 +4942,7 @@ $.Viewport.prototype = { ); }, - pointFromPixel: function(pixel, current) { + pointFromPixel: function( pixel, current ) { var bounds = this.getBounds( current ); return pixel.divide( this.containerSize.x / bounds.width diff --git a/src/button.js b/src/button.js index 4115783b..680c3c31 100644 --- a/src/button.js +++ b/src/button.js @@ -1,6 +1,11 @@ + (function( $ ){ +/** + * An enumeration of button states including, REST, GROUP, HOVER, and DOWN + * @static + */ $.ButtonState = { REST: 0, GROUP: 1, @@ -8,6 +13,18 @@ $.ButtonState = { DOWN: 3 }; +/** + * Manages events, hover states for individual buttons, tool-tips, as well + * as fading the bottons out when the user has not interacted with them + * for a specified period. + * @class + * @param {Object} options + * @param {String} options.tooltip + * @param {String} options.srcRest URL of image to use in 'rest' state + * @param {String} options.srcGroup URL of image to use in 'up' state + * @param {String} options.srcHover URL of image to use in 'hover' state + * @param {String} options.srcDown URL of image to use in 'domn' state + */ $.Button = function( options ) { var _this = this; diff --git a/src/buttongroup.js b/src/buttongroup.js index 2fd29799..c1f1f774 100644 --- a/src/buttongroup.js +++ b/src/buttongroup.js @@ -1,7 +1,7 @@ (function( $ ){ /** - * OpenSeadragon ButtonGroup + * @class * * Manages events on groups of buttons. * diff --git a/src/control.js b/src/control.js index 87d10aa9..3d244cb9 100644 --- a/src/control.js +++ b/src/control.js @@ -1,7 +1,12 @@ (function( $ ){ - +/** + * An enumeration of supported locations where controls can be anchored, + * including NONE, TOP_LEFT, TOP_RIGHT, BOTTOM_RIGHT, and BOTTOM_LEFT. + * The anchoring is always relative to the container + * @static + */ $.ControlAnchor = { NONE: 0, TOP_LEFT: 1, @@ -10,6 +15,24 @@ $.ControlAnchor = { BOTTOM_LEFT: 4 }; +/** + * A Control represents any interface element which is meant to allow the user + * to interact with the zoomable interface. Any control can be anchored to any + * element. + * @class + * @param {Element} elmt - the contol element to be anchored in the container. + * @param {OpenSeadragon.ControlAnchor} anchor - the location to anchor at. + * @param {Element} container - the element to control will be anchored too. + * + * @property {Element} elmt - the element providing the user interface with + * some type of control. Eg a zoom-in button + * @property {OpenSeadragon.ControlAnchor} anchor - the position of the control + * relative to the container. + * @property {Element} container - the element within with the control is + * positioned. + * @property {Element} wrapper - a nuetral element surrounding the control + * element. + */ $.Control = function ( elmt, anchor, container ) { this.elmt = elmt; this.anchor = anchor; @@ -36,21 +59,40 @@ $.Control = function ( elmt, anchor, container ) { $.Control.prototype = { + /** + * Removes the control from the container. + * @function + */ destroy: function() { this.wrapper.removeChild( this.elmt ); this.container.removeChild( this.wrapper ); }, + /** + * Determines if the control is currently visible. + * @function + * @return {Boolean} true if currenly visible, false otherwise. + */ isVisible: function() { return this.wrapper.style.display != "none"; }, + /** + * Toggles the visibility of the control. + * @function + * @param {Boolean} visible - true to make visible, false to hide. + */ setVisible: function( visible ) { this.wrapper.style.display = visible ? "inline-block" : "none"; }, + /** + * Sets the opacity level for the control. + * @function + * @param {Number} opactiy - a value between 1 and 0 inclusively. + */ setOpacity: function( opacity ) { if ( this.elmt[ $.SIGNAL ] && $.Browser.vendor == $.BROWSERS.IE ) { $.setElementOpacity( this.elmt, opacity, true ); diff --git a/src/displayrectangle.js b/src/displayrectangle.js index 6966c9b3..5171028e 100644 --- a/src/displayrectangle.js +++ b/src/displayrectangle.js @@ -1,6 +1,9 @@ (function( $ ){ +/** + * @class + */ $.DisplayRect = function( x, y, width, height, minLevel, maxLevel ) { $.Rect.apply( this, [ x, y, width, height ] ); diff --git a/src/drawer.js b/src/drawer.js index c1ec117e..085b6a18 100644 --- a/src/drawer.js +++ b/src/drawer.js @@ -21,6 +21,9 @@ var QUOTA = 100, USE_CANVAS = $.isFunction( document.createElement( "canvas" ).getContext ) && SUBPIXEL_RENDERING; +/** + * @class + */ $.Drawer = function(source, viewport, elmt) { this.container = $.getElement( elmt ); diff --git a/src/dzitilesource.js b/src/dzitilesource.js index da4fe4b9..209211ee 100644 --- a/src/dzitilesource.js +++ b/src/dzitilesource.js @@ -1,7 +1,9 @@ (function( $ ){ - +/** + * @class + */ $.DziTileSource = function( width, height, tileSize, tileOverlap, tilesUrl, fileFormat, displayRects ) { var i, rect, @@ -75,6 +77,9 @@ $.extend( $.DziTileSource.prototype, $.TileSource.prototype, { } }); +/** + * @static + */ $.DziTileSourceHelper = { createFromXml: function( xmlUrl, xmlString, callback ) { diff --git a/src/eventhandler.js b/src/eventhandler.js index c49c7d43..446e2fff 100644 --- a/src/eventhandler.js +++ b/src/eventhandler.js @@ -1,60 +1,62 @@ (function($){ +/** + * @class + */ +$.EventHandler = function() { + this.events = {}; +}; - $.EventHandler = function() { - this.events = {}; - }; +$.EventHandler.prototype = { - $.EventHandler.prototype = { - - addHandler: function( id, handler ) { - var events = this.events[ id ]; - if( !events ){ - this.events[ id ] = events = []; - } - events[ events.length ] = handler; - }, - - removeHandler: function( id, handler ) { - //Start Thatcher - unneccessary indirection. Also, because events were - // - not actually being removed, we need to add the code - // - to do the removal ourselves. TODO - var events = this.events[ id ]; - if ( !events ){ - return; - } - //End Thatcher - }, - - getHandler: function( id ) { - var events = this.events[ id ]; - if ( !events || !events.length ){ - return null; - } - events = events.length === 1 ? - [ events[ 0 ] ] : - Array.apply( null, events ); - return function( source, args ) { - var i, - length = events.length; - for ( i = 0; i < length; i++ ) { - events[ i ]( source, args ); - } - }; - }, - - raiseEvent: function( eventName, eventArgs ) { - var handler = this.getHandler( eventName ); - - if ( handler ) { - if ( !eventArgs ) { - eventArgs = new Object(); - } - - handler( this, eventArgs ); - } + addHandler: function( id, handler ) { + var events = this.events[ id ]; + if( !events ){ + this.events[ id ] = events = []; } - }; + events[ events.length ] = handler; + }, + + removeHandler: function( id, handler ) { + //Start Thatcher - unneccessary indirection. Also, because events were + // - not actually being removed, we need to add the code + // - to do the removal ourselves. TODO + var events = this.events[ id ]; + if ( !events ){ + return; + } + //End Thatcher + }, + + getHandler: function( id ) { + var events = this.events[ id ]; + if ( !events || !events.length ){ + return null; + } + events = events.length === 1 ? + [ events[ 0 ] ] : + Array.apply( null, events ); + return function( source, args ) { + var i, + length = events.length; + for ( i = 0; i < length; i++ ) { + events[ i ]( source, args ); + } + }; + }, + + raiseEvent: function( eventName, eventArgs ) { + var handler = this.getHandler( eventName ); + + if ( handler ) { + if ( !eventArgs ) { + eventArgs = new Object(); + } + + handler( this, eventArgs ); + } + } +}; }( OpenSeadragon )); diff --git a/src/mousetracker.js b/src/mousetracker.js index ef774db0..7b503588 100644 --- a/src/mousetracker.js +++ b/src/mousetracker.js @@ -15,7 +15,9 @@ ieTrackersActive = {}, // dictionary from hash to MouseTracker ieTrackersCapturing = []; // list of trackers interested in capture - + /** + * @class + */ $.MouseTracker = function (elmt, clickTimeThreshold, clickDistThreshold) { //Start Thatcher - TODO: remove local function definitions in favor of // - a global closure for MouseTracker so the number @@ -168,7 +170,7 @@ self.enterHandler(self, getMouseRelative(event, elmt), buttonDownElmt, buttonDownAny); } catch (e) { - $.Debug.error(e.name + + $.console.error(e.name + " while executing enter handler: " + e.message, e); } } @@ -194,7 +196,7 @@ self.exitHandler(self, getMouseRelative(event, elmt), buttonDownElmt, buttonDownAny); } catch (e) { - $.Debug.error(e.name + + $.console.error(e.name + " while executing exit handler: " + e.message, e); } } @@ -217,7 +219,7 @@ try { self.pressHandler(self, getMouseRelative(event, elmt)); } catch (e) { - $.Debug.error(e.name + + $.console.error(e.name + " while executing press handler: " + e.message, e); } } @@ -251,7 +253,7 @@ self.releaseHandler(self, getMouseRelative(event, elmt), insideElmtPress, insideElmtRelease); } catch (e) { - $.Debug.error(e.name + + $.console.error(e.name + " while executing release handler: " + e.message, e); } } @@ -334,7 +336,7 @@ try { self.scrollHandler(self, getMouseRelative(event, elmt), nDelta, event.shiftKey); } catch (e) { - $.Debug.error(e.name + + $.console.error(e.name + " while executing scroll handler: " + e.message, e); } @@ -360,7 +362,7 @@ self.clickHandler(self, getMouseRelative(event, elmt), quick, event.shiftKey); } catch (e) { - $.Debug.error(e.name + + $.console.error(e.name + " while executing click handler: " + e.message, e); } } @@ -382,7 +384,7 @@ event.shiftKey ); } catch (e) { - $.Debug.error( + $.console.error( e.name + " while executing drag handler: " + e.message, @@ -422,6 +424,7 @@ } /** + * @private * Returns true if elmtB is a child node of elmtA, or if they're equal. */ function isChild( elmtA, elmtB ) { diff --git a/src/openseadragon.js b/src/openseadragon.js index 76a886a8..1c710964 100644 --- a/src/openseadragon.js +++ b/src/openseadragon.js @@ -1,9 +1,26 @@ /** - * (c) 2011 Christopher Thatcher - * (c) 2010 OpenSeadragon - * (c) 2010 CodePlex Foundation + * @version OpenSeadragon @VERSION@ * - * OpenSeadragon @VERSION@ + * @fileOverview + *

+ * + * OpenSeadragon - Javascript Deep Zooming + * + *

+ *

+ * OpenSeadragon is provides an html interface for creating + * deep zoom user interfaces. The simplest examples include deep + * zoom for large resolution images, and complex examples include + * zoomable map interfaces driven by SVG files. + *

+ * + * @author
(c) 2011 Christopher Thatcher + * @author
(c) 2010 OpenSeadragon Team + * @author
(c) 2010 CodePlex Foundation + * + *

+ * Original license preserved below:
+ *

  * ----------------------------------------------------------------------------
  * 
  *  License: New BSD License (BSD)
@@ -37,11 +54,21 @@
  *  POSSIBILITY OF SUCH DAMAGE.
  * 
  * ----------------------------------------------------------------------------
- *
+ * 
+ *

**/ + /** + * The root namespace for OpenSeadragon. All utility methods and classes + * are defined on or below this namespace. The OpenSeadragon namespace will + * only be defined once even if mutliple versions are loaded on the page in + * succession. + * @namespace + * @name OpenSeadragon + * @exports $ as OpenSeadragon + */ OpenSeadragon = window.OpenSeadragon || (function(){ - + //Taken from jquery 1.6.1 // [[Class]] -> type pairs var class2type = { @@ -120,36 +147,52 @@ OpenSeadragon = window.OpenSeadragon || (function(){ }()); -(function( $ ){ - +(function( $ ){ + + /** + * @static + * @ignore + */ $.SIGNAL = "----seadragon----"; - $.delegate = function(object, method) { + /** + * Invokes the the method as if it where a method belonging to the object. + * @param {Object} object + * @param {Function} method + */ + $.delegate = function( object, method ) { return function() { - if (arguments === undefined) + if ( arguments === undefined ) arguments = []; - return method.apply(object, arguments); + return method.apply( object, arguments ); }; }; - - //Taken from jQuery 1.6.1: + + /** + * Taken from jQuery 1.6.1, see the jQuery documentation + */ $.extend = function() { - var options, name, src, copy, copyIsArray, clone, - target = arguments[0] || {}, - i = 1, - length = arguments.length, - deep = false; + var options, + name, + src, + copy, + copyIsArray, + clone, + target = arguments[ 0 ] || {}, + length = arguments.length, + deep = false, + i = 1; // Handle a deep copy situation if ( typeof target === "boolean" ) { - deep = target; - target = arguments[1] || {}; + deep = target; + target = arguments[ 1 ] || {}; // skip the boolean and the target i = 2; } // Handle case when target is a string or something (possible in deep copy) - if ( typeof target !== "object" && !OpenSeadragon.isFunction(target) ) { + if ( typeof target !== "object" && !OpenSeadragon.isFunction( target ) ) { target = {}; } @@ -161,7 +204,7 @@ OpenSeadragon = window.OpenSeadragon || (function(){ for ( ; i < length; i++ ) { // Only deal with non-null/undefined values - if ( (options = arguments[ i ]) != null ) { + if ( ( options = arguments[ i ] ) != null ) { // Extend the base object for ( name in options ) { src = target[ name ]; @@ -173,13 +216,13 @@ OpenSeadragon = window.OpenSeadragon || (function(){ } // Recurse if we're merging plain objects or arrays - if ( deep && copy && ( OpenSeadragon.isPlainObject(copy) || (copyIsArray = OpenSeadragon.isArray(copy)) ) ) { + if ( deep && copy && ( OpenSeadragon.isPlainObject( copy ) || ( copyIsArray = OpenSeadragon.isArray( copy ) ) ) ) { if ( copyIsArray ) { copyIsArray = false; - clone = src && OpenSeadragon.isArray(src) ? src : []; + clone = src && OpenSeadragon.isArray( src ) ? src : []; } else { - clone = src && OpenSeadragon.isPlainObject(src) ? src : {}; + clone = src && OpenSeadragon.isPlainObject( src ) ? src : {}; } // Never move original objects, clone them @@ -198,10 +241,16 @@ OpenSeadragon = window.OpenSeadragon || (function(){ }; //The following functions are originally from the Openseadragon Utils - //module but have been moved to Openseadragon to avoid the Utils anti- + //module but have been moved to Openseadragon to avoid the 'Utils' anti- //pattern. Not all of the code is A-grade compared to equivalent functions // from libraries like jquery, but until we need better we'll leave those //orignally developed by the project. + + /** + * An enumeration of Browser vendors including UNKNOWN, IE, FIREFOX, + * SAFARI, CHROME, and OPERA. + * @static + */ $.BROWSERS = { UNKNOWN: 0, IE: 1, @@ -211,6 +260,13 @@ OpenSeadragon = window.OpenSeadragon || (function(){ OPERA: 5 }; + /** + * The current browser vendor, version, and related information regarding + * detected features. Features include
+ * 'alpha' - Does the browser support image alpha + * transparency.
+ * @static + */ $.Browser = { vendor: $.BROWSERS.UNKNOWN, version: 0, @@ -233,7 +289,8 @@ OpenSeadragon = window.OpenSeadragon || (function(){ URLPARAMS = {}; (function() { - + //A small auto-executing routine to determine the browser vendor, + //version and supporting feature sets. var app = navigator.appName, ver = navigator.appVersion, ua = navigator.userAgent; @@ -277,8 +334,8 @@ OpenSeadragon = window.OpenSeadragon || (function(){ break; } - - var query = window.location.search.substring( 1 ), // ignore '?' + // ignore '?' portion of query string + var query = window.location.search.substring( 1 ), parts = query.split('&'), part, sep, @@ -294,7 +351,7 @@ OpenSeadragon = window.OpenSeadragon || (function(){ } } - //determine if this browser supports + //determine if this browser supports image alpha transparency $.Browser.alpha = !( $.Browser.vendor == $.BROWSERS.IE || ( $.Browser.vendor == $.BROWSERS.CHROME && @@ -304,16 +361,28 @@ OpenSeadragon = window.OpenSeadragon || (function(){ })(); - //TODO: $.Debug is often used inside a try/catch block which generally + //TODO: $.console is often used inside a try/catch block which generally // prevents allowings errors to occur with detection until a debugger // is attached. Although I've been guilty of the same anti-pattern // I eventually was convinced that errors should naturally propogate in // all but the most special cases. - $.Debug = window.console ? window.console : function(){}; + /** + * A convenient alias for console when available, and a simple null + * function when console is unavailable. + * @static + */ + $.console = window.console ? window.console : function(){}; $.extend( $, { + /** + * Returns a DOM Element for the given id or element. + * @function + * @name OpenSeadragon.getElement + * @param {String|Element} element Accepts an id or element. + * @returns {Element} The element with the given id, null, or the element itself. + */ getElement: function( element ) { if ( typeof ( element ) == "string") { element = document.getElementById( element ); @@ -321,6 +390,13 @@ OpenSeadragon = window.OpenSeadragon || (function(){ return element; }, + /** + * @function + * @name OpenSeadragon.getOffsetParent + * @param {Element} element + * @param {Boolean} [isFixed] + * @returns {Element} + */ getOffsetParent: function( element, isFixed ) { if ( isFixed && element != document.body ) { return document.body; @@ -329,6 +405,12 @@ OpenSeadragon = window.OpenSeadragon || (function(){ } }, + /** + * @function + * @name OpenSeadragon.getElementPosition + * @param {Element|String} element + * @returns {Point} + */ getElementPosition: function( element ) { var result = new $.Point(), isFixed, @@ -355,6 +437,12 @@ OpenSeadragon = window.OpenSeadragon || (function(){ return result; }, + /** + * @function + * @name OpenSeadragon.getElementSize + * @param {Element|String} element + * @returns {Point} + */ getElementSize: function( element ) { element = $.getElement( element ); @@ -364,6 +452,12 @@ OpenSeadragon = window.OpenSeadragon || (function(){ ); }, + /** + * @function + * @name OpenSeadragon.getElementStyle + * @param {Element|String} element + * @returns {CSSStyle} + */ getElementStyle: function( element ) { element = $.getElement( element ); @@ -376,10 +470,22 @@ OpenSeadragon = window.OpenSeadragon || (function(){ } }, + /** + * @function + * @name OpenSeadragon.getEvent + * @param {Event} [event] + * @returns {Event} + */ getEvent: function( event ) { return event ? event : window.event; }, + /** + * @function + * @name OpenSeadragon.getMousePosition + * @param {Event} [event] + * @returns {Point} + */ getMousePosition: function( event ) { var result = new $.Point(); @@ -406,6 +512,11 @@ OpenSeadragon = window.OpenSeadragon || (function(){ return result; }, + /** + * @function + * @name OpenSeadragon.getPageScroll + * @returns {Point} + */ getPageScroll: function() { var result = new $.Point(), docElmt = document.documentElement || {}, @@ -425,6 +536,11 @@ OpenSeadragon = window.OpenSeadragon || (function(){ return result; }, + /** + * @function + * @name OpenSeadragon.getWindowSize + * @returns {Point} + */ getWindowSize: function() { var result = new $.Point(), docElmt = document.documentElement || {}, @@ -446,11 +562,23 @@ OpenSeadragon = window.OpenSeadragon || (function(){ return result; }, + /** + * @function + * @name OpenSeadragon.imageFormatSupported + * @param {String} [extension] + * @returns {Boolean} + */ imageFormatSupported: function( extension ) { extension = extension ? extension : ""; return !!FILEFORMATS[ extension.toLowerCase() ]; }, + /** + * @function + * @name OpenSeadragon.makeCenteredNode + * @param {Element|String} element + * @returns {Element} + */ makeCenteredNode: function( element ) { var div = $.makeNeutralElement( "div" ), @@ -488,6 +616,12 @@ OpenSeadragon = window.OpenSeadragon || (function(){ return div; }, + /** + * @function + * @name OpenSeadragon.makeNeutralElement + * @param {String} tagName + * @returns {Element} + */ makeNeutralElement: function( tagName ) { var element = document.createElement( tagName ), style = element.style; @@ -501,6 +635,12 @@ OpenSeadragon = window.OpenSeadragon || (function(){ return element; }, + /** + * @function + * @name OpenSeadragon.makeTransparentImage + * @param {String} src + * @returns {Element} + */ makeTransparentImage: function( src ) { var img = $.makeNeutralElement( "img" ), element = null; @@ -535,6 +675,13 @@ OpenSeadragon = window.OpenSeadragon || (function(){ return element; }, + /** + * @function + * @name OpenSeadragon.setElementOpacity + * @param {Element|String} element + * @param {Number} opacity + * @param {Boolean} [usesAlpha] + */ setElementOpacity: function( element, opacity, usesAlpha ) { var previousFilter, @@ -575,6 +722,15 @@ OpenSeadragon = window.OpenSeadragon || (function(){ } }, + /** + * @function + * @name OpenSeadragon.addEvent + * @param {Element|String} element + * @param {String} eventName + * @param {Function} handler + * @param {Boolean} [useCapture] + * @throws {Error} + */ addEvent: function( element, eventName, handler, useCapture ) { element = $.getElement( element ); @@ -594,6 +750,15 @@ OpenSeadragon = window.OpenSeadragon || (function(){ } }, + /** + * @function + * @name OpenSeadragon.removeEvent + * @param {Element|String} element + * @param {String} eventName + * @param {Function} handler + * @param {Boolean} [useCapture] + * @throws {Error} + */ removeEvent: function( element, eventName, handler, useCapture ) { element = $.getElement( element ); @@ -613,17 +778,29 @@ OpenSeadragon = window.OpenSeadragon || (function(){ } }, + /** + * @function + * @name OpenSeadragon.cancelEvent + * @param {Event} [event] + */ cancelEvent: function( event ) { event = $.getEvent( event ); if ( event.preventDefault ) { - event.preventDefault(); // W3C for preventing default + // W3C for preventing default + event.preventDefault(); } - - event.cancel = true; // legacy for preventing default - event.returnValue = false; // IE for preventing default + // legacy for preventing default + event.cancel = true; + // IE for preventing default + event.returnValue = false; }, + /** + * @function + * @name OpenSeadragon.stopEvent + * @param {Event} [event] + */ stopEvent: function( event ) { event = $.getEvent( event ); @@ -634,6 +811,14 @@ OpenSeadragon = window.OpenSeadragon || (function(){ event.cancelBubble = true; // IE for stopping propagation }, + /** + * @function + * @name OpenSeadragon.createCallback + * @param {Object} object + * @param {Function} method + * @param [args] any additional arguments are passed as arguments to the created callback + * @returns {Function} + */ createCallback: function( object, method ) { //TODO: This pattern is painful to use and debug. It's much cleaner // to use pinning plus anonymous functions. Get rid of this @@ -655,11 +840,23 @@ OpenSeadragon = window.OpenSeadragon || (function(){ }; }, + /** + * @function + * @name OpenSeadragon.getUrlParameter + * @param {String} key + * @returns {String} The value of the url parameter or null if no param matches. + */ getUrlParameter: function( key ) { var value = URLPARAMS[ key ]; return value ? value : null; }, + /** + * @function + * @name OpenSeadragon.makeAjaxRequest + * @param {String} url + * @param {Function} [callback] + */ makeAjaxRequest: function( url, callback ) { var async = typeof( callback ) == "function", request = null, @@ -699,6 +896,7 @@ OpenSeadragon = window.OpenSeadragon || (function(){ if ( async ) { + /** @ignore */ request.onreadystatechange = function() { if ( request.readyState == 4) { request.onreadystatechange = new function() { }; @@ -728,6 +926,13 @@ OpenSeadragon = window.OpenSeadragon || (function(){ return async ? null : request; }, + /** + * Parses an XML string into a DOM Document. + * @function + * @name OpenSeadragon.parseXml + * @param {String} string + * @returns {Document} + */ parseXml: function( string ) { //TODO: yet another example where we can determine the correct // implementation once at start-up instead of everytime we use diff --git a/src/overlay.js b/src/overlay.js index 7bbcb53f..9f135b6e 100644 --- a/src/overlay.js +++ b/src/overlay.js @@ -1,6 +1,12 @@ (function( $ ){ + /** + * An enumeration of positions that an overlay may be assigned relative + * to the viewport including CENTER, TOP_LEFT (default), TOP, TOP_RIGHT, + * RIGHT, BOTTOM_RIGHT, BOTTOM, BOTTOM_LEFT, and LEFT. + * @static + */ $.OverlayPlacement = { CENTER: 0, TOP_LEFT: 1, @@ -13,6 +19,9 @@ LEFT: 8 }; + /** + * @class + */ $.Overlay = function( elmt, location, placement ) { this.elmt = elmt; this.scales = location instanceof $.Rect; diff --git a/src/point.js b/src/point.js index 21c11b70..dbea4b98 100644 --- a/src/point.js +++ b/src/point.js @@ -1,6 +1,9 @@ (function( $ ){ +/** + * @class + */ $.Point = function( x, y ) { this.x = typeof ( x ) == "number" ? x : 0; this.y = typeof ( y ) == "number" ? y : 0; diff --git a/src/profiler.js b/src/profiler.js index 17703ec8..0c0f0b5e 100644 --- a/src/profiler.js +++ b/src/profiler.js @@ -1,6 +1,9 @@ (function( $ ){ +/** + * @class + */ $.Profiler = function() { this.midUpdate = false; diff --git a/src/rectangle.js b/src/rectangle.js index a4311982..af3c942c 100644 --- a/src/rectangle.js +++ b/src/rectangle.js @@ -1,6 +1,9 @@ (function( $ ){ +/** + * @class + */ $.Rect = function( x, y, width, height ) { this.x = typeof ( x ) == "number" ? x : 0; this.y = typeof ( y ) == "number" ? y : 0; diff --git a/src/spring.js b/src/spring.js index 54634333..c00e70b1 100644 --- a/src/spring.js +++ b/src/spring.js @@ -1,6 +1,9 @@ (function( $ ){ +/** + * @class + */ $.Spring = function( options ) { var args = arguments; diff --git a/src/tile.js b/src/tile.js index 24922af1..f9a7cb69 100644 --- a/src/tile.js +++ b/src/tile.js @@ -1,6 +1,9 @@ (function( $ ){ +/** + * @class + */ $.Tile = function(level, x, y, bounds, exists, url) { this.level = level; this.x = x; @@ -38,7 +41,7 @@ $.Tile.prototype = { size = this.size.apply( Math.ceil ); if ( !this.loaded ) { - $.Debug.warn( + $.console.warn( "Attempting to draw tile %s when it's not yet loaded.", this.toString() ); @@ -74,7 +77,7 @@ $.Tile.prototype = { size = this.size; if (!this.loaded) { - $.Debug.warn( + $.console.warn( "Attempting to draw tile %s when it's not yet loaded.", this.toString() ); diff --git a/src/tilesource.js b/src/tilesource.js index f51f4589..be667dc1 100644 --- a/src/tilesource.js +++ b/src/tilesource.js @@ -1,6 +1,10 @@ (function( $ ){ + +/** + * @class + */ $.TileSource = function( width, height, tileSize, tileOverlap, minLevel, maxLevel ) { this.aspectRatio = width / height; this.dimensions = new $.Point( width, height ); diff --git a/src/viewer.js b/src/viewer.js index 5de59ca2..42ee974d 100644 --- a/src/viewer.js +++ b/src/viewer.js @@ -1,7 +1,7 @@ (function( $ ){ /** - * OpenSeadragon Viewer + * @class * * The main point of entry into creating a zoomable image on the page. * @@ -387,7 +387,7 @@ $.extend( $.Viewer.prototype, $.EventHandler.prototype, { this._lastOpenEndTime = +new Date(); if ( this._lastOpenStartTime < viewer._lastOpenStartTime ) { - $.Debug.log( "Ignoring out-of-date open." ); + $.console.log( "Ignoring out-of-date open." ); this.raiseEvent( "ignore" ); return; } @@ -408,7 +408,8 @@ $.extend( $.Viewer.prototype, $.EventHandler.prototype, { this.viewport, this.canvas ); - this.profiler = new $.Profiler(); + + //this.profiler = new $.Profiler(); this._animating = false; this._forceRedraw = true; @@ -451,7 +452,7 @@ $.extend( $.Viewer.prototype, $.EventHandler.prototype, { this.source = null; this.viewport = null; this.drawer = null; - this.profiler = null; + //this.profiler = null; this.canvas.innerHTML = ""; }, diff --git a/src/viewport.js b/src/viewport.js index cb4d28a5..27f1b8e3 100644 --- a/src/viewport.js +++ b/src/viewport.js @@ -1,6 +1,10 @@ (function( $ ){ - + + +/** + * @class + */ $.Viewport = function( options ) { var options; @@ -49,16 +53,19 @@ $.Viewport = function( options ) { }; $.Viewport.prototype = { + getHomeZoom: function() { var aspectFactor = this.contentAspect / this.getAspectRatio(); - return (aspectFactor >= 1) ? 1 : aspectFactor; + return ( aspectFactor >= 1 ) ? + 1 : + aspectFactor; }, getMinZoom: function() { var homeZoom = this.getHomeZoom() zoom = this.minZoomImageRatio * homeZoom; - return Math.min(zoom, homeZoom); + return Math.min( zoom, homeZoom ); }, getMaxZoom: function() { @@ -66,7 +73,7 @@ $.Viewport.prototype = { this.contentSize.x * this.maxZoomPixelRatio / this.containerSize.x; - return Math.max(zoom, this.getHomeZoom()); + return Math.max( zoom, this.getHomeZoom() ); }, getAspectRatio: function() { @@ -74,12 +81,15 @@ $.Viewport.prototype = { }, getContainerSize: function() { - return new $.Point(this.containerSize.x, this.containerSize.y); + return new $.Point( + this.containerSize.x, + this.containerSize.y + ); }, getBounds: function( current ) { - var center = this.getCenter(current), - width = 1.0 / this.getZoom(current), + var center = this.getCenter( current ), + width = 1.0 / this.getZoom( current ), height = width / this.getAspectRatio(); return new $.Rect( @@ -108,9 +118,9 @@ $.Viewport.prototype = { deltaZoomPixels, deltaZoomPoints; - if (current) { + if ( current ) { return centerCurrent; - } else if (!this.zoomPoint) { + } else if ( !this.zoomPoint ) { return centerTarget; } @@ -203,6 +213,9 @@ $.Viewport.prototype = { this.applyConstraints( immediately ); }, + /** + * + */ fitBounds: function( bounds, immediately ) { var aspect = this.getAspectRatio(), center = bounds.getCenter(), @@ -217,7 +230,7 @@ $.Viewport.prototype = { newZoom, referencePoint; - if (newBounds.getAspectRatio() >= aspect) { + if ( newBounds.getAspectRatio() >= aspect ) { newBounds.height = bounds.width / aspect; newBounds.y = center.y - newBounds.height / 2; } else { @@ -225,13 +238,13 @@ $.Viewport.prototype = { newBounds.x = center.x - newBounds.width / 2; } - this.panTo(this.getCenter(true), true); - this.zoomTo(this.getZoom(true), null, true); + this.panTo( this.getCenter( true ), true ); + this.zoomTo( this.getZoom( true ), null, true ); oldBounds = this.getBounds(); oldZoom = this.getZoom(); newZoom = 1.0 / newBounds.width; - if (newZoom == oldZoom || newBounds.width == oldBounds.width) { + if ( newZoom == oldZoom || newBounds.width == oldBounds.width ) { this.panTo( center, immediately ); return; } @@ -251,25 +264,27 @@ $.Viewport.prototype = { this.zoomTo( newZoom, referencePoint, immediately ); }, - goHome: function(immediately) { + goHome: function( immediately ) { var center = this.getCenter(); if ( this.wrapHorizontal ) { - center.x = (1 + (center.x % 1)) % 1; - this.centerSpringX.resetTo(center.x); + center.x = ( 1 + ( center.x % 1 ) ) % 1; + this.centerSpringX.resetTo( center.x ); this.centerSpringX.update(); } if ( this.wrapVertical ) { - center.y = (this.contentHeight + (center.y % this.contentHeight)) % this.contentHeight; - this.centerSpringY.resetTo(center.y); + center.y = ( + this.contentHeight + ( center.y % this.contentHeight ) + ) % this.contentHeight; + this.centerSpringY.resetTo( center.y ); this.centerSpringY.update(); } - this.fitBounds(this.homeBounds, immediately); + this.fitBounds( this.homeBounds, immediately ); }, - panBy: function(delta, immediately) { + panBy: function( delta, immediately ) { var center = new $.Point( this.centerSpringX.target.value, this.centerSpringY.target.value @@ -277,44 +292,49 @@ $.Viewport.prototype = { this.panTo( center.plus( delta ), immediately ); }, - panTo: function(center, immediately) { - if (immediately) { - this.centerSpringX.resetTo(center.x); - this.centerSpringY.resetTo(center.y); + panTo: function( center, immediately ) { + if ( immediately ) { + this.centerSpringX.resetTo( center.x ); + this.centerSpringY.resetTo( center.y ); } else { - this.centerSpringX.springTo(center.x); - this.centerSpringY.springTo(center.y); + this.centerSpringX.springTo( center.x ); + this.centerSpringY.springTo( center.y ); } }, - zoomBy: function(factor, refPoint, immediately) { - this.zoomTo(this.zoomSpring.target.value * factor, refPoint, immediately); + zoomBy: function( factor, refPoint, immediately ) { + this.zoomTo( this.zoomSpring.target.value * factor, refPoint, immediately ); }, - zoomTo: function(zoom, refPoint, immediately) { + zoomTo: function( zoom, refPoint, immediately ) { - if (immediately) { - this.zoomSpring.resetTo(zoom); + if ( immediately ) { + this.zoomSpring.resetTo( zoom ); } else { - this.zoomSpring.springTo(zoom); + this.zoomSpring.springTo( zoom ); } - this.zoomPoint = refPoint instanceof $.Point ? refPoint : null; + this.zoomPoint = refPoint instanceof $.Point ? + refPoint : + null; }, - resize: function(newContainerSize, maintain) { + resize: function( newContainerSize, maintain ) { var oldBounds = this.getBounds(), newBounds = oldBounds, widthDeltaFactor = newContainerSize.x / this.containerSize.x; - this.containerSize = new $.Point(newContainerSize.x, newContainerSize.y); + this.containerSize = new $.Point( + newContainerSize.x, + newContainerSize.y + ); if (maintain) { newBounds.width = oldBounds.width * widthDeltaFactor; newBounds.height = newBounds.width / this.getAspectRatio(); } - this.fitBounds(newBounds, true); + this.fitBounds( newBounds, true ); }, update: function() { @@ -327,14 +347,14 @@ $.Viewport.prototype = { deltaZoomPoints; if (this.zoomPoint) { - oldZoomPixel = this.pixelFromPoint(this.zoomPoint, true); + oldZoomPixel = this.pixelFromPoint( this.zoomPoint, true ); } this.zoomSpring.update(); if (this.zoomPoint && this.zoomSpring.current.value != oldZoom) { newZoomPixel = this.pixelFromPoint( this.zoomPoint, true ); - deltaZoomPixels = newZoomPixel.minus( oldZoomPixel); + deltaZoomPixels = newZoomPixel.minus( oldZoomPixel ); deltaZoomPoints = this.deltaPointsFromPixels( deltaZoomPixels, true ); this.centerSpringX.shiftBy( deltaZoomPoints.x ); @@ -352,19 +372,19 @@ $.Viewport.prototype = { }, - deltaPixelsFromPoints: function(deltaPoints, current) { + deltaPixelsFromPoints: function( deltaPoints, current ) { return deltaPoints.times( this.containerSize.x * this.getZoom( current ) ); }, - deltaPointsFromPixels: function(deltaPixels, current) { + deltaPointsFromPixels: function( deltaPixels, current ) { return deltaPixels.divide( this.containerSize.x * this.getZoom( current ) ); }, - pixelFromPoint: function(point, current) { + pixelFromPoint: function( point, current ) { var bounds = this.getBounds( current ); return point.minus( bounds.getTopLeft() @@ -373,7 +393,7 @@ $.Viewport.prototype = { ); }, - pointFromPixel: function(pixel, current) { + pointFromPixel: function( pixel, current ) { var bounds = this.getBounds( current ); return pixel.divide( this.containerSize.x / bounds.width
+ +
+ +
+