You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by an...@apache.org on 2013/10/22 01:24:24 UTC

[4/9] first commit

http://git-wip-us.apache.org/repos/asf/cordova-registry-web/blob/f50cc931/attachments/layout.less
----------------------------------------------------------------------
diff --git a/attachments/layout.less b/attachments/layout.less
new file mode 100644
index 0000000..1ccef0a
--- /dev/null
+++ b/attachments/layout.less
@@ -0,0 +1,461 @@
+/* ----- mixins ------ */
+
+.border-radius( @radius: 8px ) {
+    -moz-border-radius: @radius;
+    -webkit-border-radius: @radius;
+    border-radius: @radius;
+}
+
+.transition ( @type: all, @sec: 0.25s ) {
+    -webkit-transition: @type @sec linear;
+    -moz-transition: @type @sec linear;
+    transition: @type @sec linear;
+}
+
+@highlight-color: #4cc2e4;
+@font-color: #3b4854;
+
+@import "font/style.css";
+
+/* ----- font ----- */
+
+html {
+    font-size: 17px;
+    font-family: 'HelveticaNeue-Light', Helvetica, Arial, sans-serif;
+    color: @font-color;
+} 
+
+h1 {
+    font-size: 1.8em;
+    font-weight: normal;
+}
+
+h2 {
+    font-size: 1.2em;
+    font-weight: normal;
+}
+
+
+/* ----- basic layout ----- */
+
+body {
+    background: #fff;
+    margin: 0;
+}
+
+.wrap, #tabs {
+    max-width: 1000px;
+    margin: 0 auto;
+    padding: 40px 0;
+}
+
+.grid {
+    background: url(images/grid.png);
+}
+
+
+/* ----- common elements -----*/
+
+a {
+    color: @highlight-color;
+    text-decoration:none;
+}
+
+a.dep-link {
+    padding-right:7px;
+}
+
+.spacer, .clear { 
+    clear:both; 
+}
+
+.button {
+    display: inline-block;
+    background-color: @highlight-color;
+    margin-left: 8px;
+    padding: 10px 16px;
+    color: #fff;
+    font-size: 1.5em;
+    text-align: center;
+    text-decoration: none;
+    .transition( background );
+    border-bottom: 4px solid darken(@highlight-color,10%);
+
+    &:hover {
+        background-color: #4cd6fc;
+        color: #fff;
+    }
+}
+
+
+/* ----- header ---- */
+
+#header {
+    text-align: left;
+    border-bottom: 3px solid rgba(0,0,0,0.1);
+    position: relative;
+    z-index: 3;
+    margin-bottom: -3px;
+
+    .wrap {
+        padding: 20px 0;
+    }
+
+    a {
+        .transition( color );
+        color: @font-color;
+        display: inline-block;
+        padding: 6px 0;
+        position: relative;
+
+        &:hover {
+            color: @highlight-color;
+        }
+    }
+
+    a.logo {
+        padding-left: 40px;
+        font-size: 1.2em;
+
+        &:before {
+            font-size: 1.5em;
+            position: absolute;
+            left: 0;
+            top: 3px;
+        }
+    }
+
+    #howto {
+        float: right;
+
+        a {
+            padding-top: 10px;
+            margin-left: 24px;
+
+            span {
+                position: absolute;
+                top: -0px;
+                left: 0;
+                font-size: 10px;
+                font-weight: 600;
+            }
+        }
+    }
+}
+
+
+/* ----- content ---- */
+
+#content-wrapper {
+    padding-top: 0;
+}
+
+
+#content,
+#tabs a, #tabs span {
+    background: #fff;
+    padding: 2% 2%;
+    .border-radius( 5px );
+    position: relative;
+}
+
+#content {
+    padding: 4% 2%;
+}
+
+#tabs {
+    margin-bottom: -7px;
+    padding-bottom: 0;
+
+    a, span {
+        display: inline-block;
+        padding: 16px 20px 18px;
+        margin: 0 10px 0 0;
+    }
+
+    a {
+        .transition( background-color );
+        background-color: @highlight-color;
+        color: #fff;
+
+        &:hover {
+            background-color: lighten( @highlight-color, 10% );
+        }
+
+        &.selected {
+            background-color: #fff;
+            color: @font-color;
+            &:hover {
+                background-color: #fff;
+            }
+        }
+    }
+}
+
+#search-box {
+    width: auto;
+    margin-bottom: 20px;
+}
+
+#search-box-input {
+    span {
+        line-height: 60px;
+        width: 5%;
+        font-size: 1.5em;
+        font-weight: bold;
+        text-align: center;
+        float: left;
+    }
+
+    .button {
+        padding-left: 2%;
+        padding-right: 2%;
+        width: 25%;
+        float: left;
+    }
+}
+
+#search-input {
+    width: auto;
+    min-width: 90%;
+    font-size: 1.5em;
+    padding: 10px 2%;
+    border: none;
+    font-weight: normal;
+    margin: 0 8px 0 0;
+    border: 1px solid #ddd;
+    border-top: 4px #ddd solid;
+    // float: left;
+
+    &:focus {
+        outline-color: @highlight-color;
+    }
+}
+
+#browse-anchors {
+
+    a {
+        margin-right:20px;
+        padding: 3px 5px 3px 5px;
+        background-color: #fff;
+
+        display: inline-block;
+        background-color: @highlight-color;
+        margin-right: 8px;
+        padding: 4px 12px;
+        color: #fff;
+        text-align: center;
+        text-decoration: none;
+        .transition( background );
+        border-bottom: 2px solid darken(@highlight-color,10%);
+
+        &:hover {
+        background-color: #4cd6fc;
+        color: #fff;
+    }
+    }
+}
+
+
+// #main-container, #search-box, 
+
+
+
+
+/* ----- footer ---- */
+
+#footer {
+    height:40px;
+}
+
+
+/* ----- everything else ----- */
+
+div#results {
+  font-size:20px;
+  width:100%;
+  padding-top:4px;
+}
+div.result {
+  width:100%;
+}
+div.result-container {
+  padding-bottom:6px;
+}
+span.result-name {
+  padding-right:10px;
+}
+span.result-desc {
+  color:#6B6B6B;
+}
+div.result-tags {
+  text-align:right;
+  font-size:16px;
+  padding-right:4px;
+  float:right;
+}
+span.tag {
+  padding-left:6px;
+  cursor:pointer;
+  color:#878787;
+}
+span.desc-term {
+  color:#141414;
+}
+div.package {
+  text-align:center;
+}
+
+div.package-title {
+  font-size:45px;
+  float:left;
+}
+div.pkg-link {
+  float:left;
+  padding-top:20px;
+  margin-left:30px;
+}
+
+div#latest-packages {
+  width:45%;
+  float:left;
+  margin-right: 5%;
+}
+
+div#top-dep-packages {
+  width:45%;
+  margin-left:5%;
+  float:left;
+}
+
+div.top-title {
+  text-align:center;
+}
+
+div.top-package {
+  width:100%;
+}
+div.top-package-title {
+  padding-right:7px;
+  float:left;
+}
+div.top-package-updated {
+  float:right;
+  text-align:right;
+  padding-right:15px;
+}
+div.top-package-dep {
+  float:right;
+  text-align:right;
+  padding-right:15px;
+}
+
+div.dependencies {
+  width:80%;
+  text-align:left;
+  padding-left:10%;
+  padding-right:10%;
+}
+div.users {
+  width:80%;
+  text-align:left;
+  padding-left:10%;
+  padding-right:10%;
+}
+a.dep {
+  margin-right:10px;
+}
+a.user {
+  margin-right:10px;
+}
+div#totals {
+  float:right;
+  position:absolute;
+  top:10px;
+  right:10px;
+}
+div.all-package {
+  width:100%;
+}
+div.all-package-name {
+  width:40%;
+  padding-right:2%;
+  float:left;
+}
+div.all-package-desc {
+  width:50%;
+  float:left;
+}
+div#more-all {
+  cursor:pointer;
+  color:blue;
+}
+
+div#versions-container {
+  margin-top:10px;
+  width:100%;
+}
+div#version-list {
+  float:left;
+  width:20%;
+}
+div#version-info {
+  float:left;
+  width:78%;
+  background-color:#B9D3EE;
+  padding: 1% 1% 1% 1%;
+}
+div.version-info-cell {
+  width:100%;
+}
+div.version-info-key {
+  float:left;
+}
+div.version-info-value {
+  float:right;
+  text-align:right;
+}
+div.version-selected {
+  background-color:#B9D3EE;
+}
+div.version-link {
+  width:100%;
+  padding: 3px 0px 0px 10px;
+}
+
+span.expand-tags {
+  padding-left:10px;
+  font-size:12px;
+  cursor:pointer;
+  color:#FF1D4E;
+}
+a.tag-val {
+  padding-right:10px;
+  padding-left:5px;
+}
+div.all-package-author {
+  width:30%;
+  float:left;
+}
+
+div.all-package-auth-list {
+  width:70%;
+  float:left;
+}
+div.all-package-deps {
+  width:50%;
+  float:left;
+}
+div.all-package-deps-value {
+  width:50%;
+  float:left;
+}
+div.tags-pkg-name {
+  float:left;
+  width:30%;
+  font-size:30px;
+}
+div.tags-pkg-desc {
+  float:left;
+  width:70%;
+}

http://git-wip-us.apache.org/repos/asf/cordova-registry-web/blob/f50cc931/attachments/more.html
----------------------------------------------------------------------
diff --git a/attachments/more.html b/attachments/more.html
new file mode 100644
index 0000000..c6fa383
--- /dev/null
+++ b/attachments/more.html
@@ -0,0 +1,3 @@
+<h2>Goodies</h2>
+
+<h3><a href="/#/_analytics">Analytics</a></div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-registry-web/blob/f50cc931/attachments/publish.html
----------------------------------------------------------------------
diff --git a/attachments/publish.html b/attachments/publish.html
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/cordova-registry-web/blob/f50cc931/attachments/sammy/plugins/sammy.cache.js
----------------------------------------------------------------------
diff --git a/attachments/sammy/plugins/sammy.cache.js b/attachments/sammy/plugins/sammy.cache.js
new file mode 100644
index 0000000..b2622c8
--- /dev/null
+++ b/attachments/sammy/plugins/sammy.cache.js
@@ -0,0 +1,115 @@
+// deprecated
+(function($) {
+
+  Sammy = Sammy || {};
+
+  // A simple cache strategy that stores key/values in memory.
+  Sammy.MemoryCacheProxy = function(initial) {
+    this._cache = initial || {};
+  };
+
+  $.extend(Sammy.MemoryCacheProxy.prototype, {
+    exists: function(name) {
+      return (typeof this._cache[name] != "undefined");
+    },
+    set: function(name, value) {
+      return this._cache[name] = value;
+    },
+    get: function(name) {
+      return this._cache[name];
+    },
+    clear: function(name) {
+      delete this._cache[name];
+    }
+  });
+
+  // A simple cache strategy that stores key/values <tt>$element.data()</tt> with a <tt>cache.</tt> prefix
+  Sammy.DataCacheProxy = function(initial, $element) {
+    initial = initial || {};
+    this.$element = $element;
+    $.each(initial, function(key, value) {
+      $element.data('cache.' + key, value);
+    });
+  };
+
+  $.extend(Sammy.DataCacheProxy.prototype, {
+    exists: function(name) {
+      return (typeof this.$element.data('cache.' + name) != "undefined");
+    },
+    set: function(name, value) {
+      return this.$element.data('cache.' + name, value);
+    },
+    get: function(name) {
+      return this.$element.data('cache.' + name);
+    },
+    clear: function(name) {
+      this.$element.removeData('cache.' + name);
+    }
+  });
+
+  // Sammy.Cache provides helpers for caching data within the lifecycle of a
+  // Sammy app. The plugin provides two main methods on <tt>Sammy.Application<tt>,
+  // <tt>cache</tt> and <tt>clearCache</tt>. Each app has its own cache store so that
+  // you dont have to worry about collisions. There are currently two different 'cache proxies'
+  // that share the same API but store the data in different ways.
+  //
+  // ### Arguments
+  //
+  // * `proxy` decides which caching proxy to use, either 'memory'(default) or 'data'
+  //
+  Sammy.Cache = function(app, proxy) {
+
+    app.log('**WARNING:** This version of Sammy.Cache has been deprecated in favor of using the version in Sammy.Storage and will be removed in 1.0')
+
+    if (proxy == 'data') {
+      this.cache_proxy = new Sammy.DataCacheProxy({}, this.$element());
+    } else {
+      this.cache_proxy = new Sammy.MemoryCacheProxy({});
+    }
+
+    app.cache_partials = true;
+
+    $.extend(app, {
+      // cache is the main method for interacting with the cache store. The same
+      // method is used for both setting and getting the value. The API is similar
+      // to jQuery.fn.attr()
+      //
+      // ### Examples
+      //
+      //      // setting a value
+      //      cache('key', 'value');
+      //
+      //      // getting a value
+      //      cache('key'); //=> 'value'
+      //
+      //      // setting a value with a callback
+      //      cache('key', function() {
+      //        // this is the app
+      //        return app.element_selector;
+      //      });
+      //
+      cache: function(name, value) {
+        if (typeof value == 'undefined') {
+          return this.cache_proxy.get(name);
+        } else if ($.isFunction(value) && !this.cache_proxy.exists(name)) {
+          return this.cache_proxy.set(name, value.apply(this));
+        } else {
+          return this.cache_proxy.set(name, value)
+        }
+      },
+
+      // clears the cached value for <tt>name</tt>
+      clearCache: function(name) {
+        return this.cache_proxy.clear(name);
+      }
+    });
+
+    app.helpers({
+      // a helper shortcut for use in <tt>Sammy.EventContext</tt>
+      cache: function(name, value) {
+        return this.app.cache(name, value);
+      }
+    });
+  };
+
+})(jQuery);

http://git-wip-us.apache.org/repos/asf/cordova-registry-web/blob/f50cc931/attachments/sammy/plugins/sammy.data_location_proxy.js
----------------------------------------------------------------------
diff --git a/attachments/sammy/plugins/sammy.data_location_proxy.js b/attachments/sammy/plugins/sammy.data_location_proxy.js
new file mode 100644
index 0000000..6b0ada3
--- /dev/null
+++ b/attachments/sammy/plugins/sammy.data_location_proxy.js
@@ -0,0 +1,78 @@
+(function($) {
+
+  Sammy = Sammy || {};
+
+  // The DataLocationProxy is an optional location proxy prototype. As opposed to
+  // the `HashLocationProxy` it gets its location from a jQuery.data attribute
+  // tied to the application's element. You can set the name of the attribute by
+  // passing a string as the second argument to the constructor. The default attribute
+  // name is 'sammy-location'. To read more about location proxies, check out the
+  // documentation for `Sammy.HashLocationProxy`
+  //
+  // An optional `href_attribute` can be passed, which specifies a DOM element
+  // attribute that holds "links" to different locations in the app. When the
+  // proxy is bound, clicks to element that have this attribute activate a
+  // `setLocation()` using the contents of the `href_attribute`.
+  //
+  // ### Example
+  //
+  //      var app = $.sammy(function() {
+  //        // set up the location proxy
+  //        this.setLocationProxy(new Sammy.DataLocationProxy(this, 'location', 'rel'));
+  //
+  //        this.get('about', function() {
+  //          this.partial('about.html');
+  //        });
+  //
+  //      });
+  //
+  // In this scenario, if an element existed within the template:
+  //
+  //      <a href="/about" rel="about">About Us</a>
+  //
+  // Clicking on that link would not go to /about, but would set the apps location
+  // to 'about' and trigger the route.
+  Sammy.DataLocationProxy = function(app, data_name, href_attribute) {
+    this.app            = app;
+    this.data_name      = data_name || 'sammy-location';
+    this.href_attribute = href_attribute;
+  };
+
+  Sammy.DataLocationProxy.prototype = {
+    bind: function() {
+      var proxy = this;
+      this.app.$element().bind('setData', function(e, key, value) {
+        if (key == proxy.data_name) {
+          // jQuery unfortunately fires the event before it sets the value
+          // work around it, by setting the value ourselves
+          proxy.app.$element().each(function() {
+            $.data(this, proxy.data_name, value);
+          });
+          proxy.app.trigger('location-changed');
+        }
+      });
+      if (this.href_attribute) {
+        this.app.$element().delegate('[' + this.href_attribute + ']', 'click', function(e) {
+          e.preventDefault();
+          proxy.setLocation($(this).attr(proxy.href_attribute));
+        });
+      }
+    },
+
+    unbind: function() {
+      if (this.href_attribute) {
+        this.app.$element().undelegate('[' + this.href_attribute + ']', 'click');
+      }
+      this.app.$element().unbind('setData');
+    },
+
+    getLocation: function() {
+      return this.app.$element().data(this.data_name);
+    },
+
+    setLocation: function(new_location) {
+      return this.app.$element().data(this.data_name, new_location);
+    }
+  };
+
+})(jQuery);

http://git-wip-us.apache.org/repos/asf/cordova-registry-web/blob/f50cc931/attachments/sammy/plugins/sammy.ejs.js
----------------------------------------------------------------------
diff --git a/attachments/sammy/plugins/sammy.ejs.js b/attachments/sammy/plugins/sammy.ejs.js
new file mode 100644
index 0000000..4fb7493
--- /dev/null
+++ b/attachments/sammy/plugins/sammy.ejs.js
@@ -0,0 +1,700 @@
+(function($) {
+
+  // Embeddedjs is property of http://embeddedjs.com/
+  // Sammy ejs plugin written Codeofficer @ http://www.codeofficer.com/
+
+  var rsplit = function(string, regex) {
+    var result = regex.exec(string),
+        retArr = new Array(),
+        first_idx, last_idx, first_bit;
+    while (result != null) {
+      first_idx = result.index;
+      last_idx = regex.lastIndex;
+      if ((first_idx) != 0) {
+        first_bit = string.substring(0, first_idx);
+        retArr.push(string.substring(0, first_idx));
+        string = string.slice(first_idx);
+      };
+      retArr.push(result[0]);
+      string = string.slice(result[0].length);
+      result = regex.exec(string);
+    };
+    if (! string == '') {
+      retArr.push(string);
+    };
+    return retArr;
+  };
+
+  var chop = function(string) {
+    return string.substr(0, string.length - 1);
+  };
+
+  var extend = function(d, s) {
+    for (var n in s) {
+      if(s.hasOwnProperty(n))   d[n] = s[n];
+    };
+  };
+
+  /* @Constructor*/
+  EJS = function(options) {
+    options = (typeof(options) == "string") ? {view: options} : options;
+    this.set_options(options);
+    if (options.precompiled) {
+      this.template = {};
+      this.template.process = options.precompiled;
+      EJS.update(this.name, this);
+      return;
+    };
+    if (options.element) {
+      if (typeof(options.element) == 'string') {
+        var name = options.element;
+        options.element = document.getElementById(options.element);
+        if (options.element == null) throw name + 'does not exist!';
+      };
+      if (options.element.value) {
+        this.text = options.element.value;
+      } else {
+        this.text = options.element.innerHTML;
+      };
+      this.name = options.element.id;
+      this.type = '[';
+    } else if (options.url) {
+      options.url = EJS.endExt(options.url, this.extMatch);
+      this.name = this.name ? this.name : options.url;
+      var url = options.url;
+      //options.view = options.absolute_url || options.view || options.;
+      var template = EJS.get(this.name /*url*/, this.cache);
+      if (template) return template;
+      if (template == EJS.INVALID_PATH) return null;
+      try {
+        this.text = EJS.request( url + (this.cache ? '' : '?' + Math.random() ));
+      } catch(e) {};
+      if (this.text == null) {
+        throw( {type: 'EJS', message: 'There is no template at '+url}  );
+      };
+      //this.name = url;
+    };
+    var template = new EJS.Compiler(this.text, this.type);
+    template.compile(options, this.name);
+    EJS.update(this.name, this);
+    this.template = template;
+  };
+
+  /* @Prototype*/
+  EJS.prototype = {
+  /**
+   * Renders an object with extra view helpers attached to the view.
+   * @param {Object} object data to be rendered
+   * @param {Object} extra_helpers an object with additonal view helpers
+   * @return {String} returns the result of the string
+   */
+    render : function(object, extra_helpers) {
+      object = object || {};
+      this._extra_helpers = extra_helpers;
+      var v = new EJS.Helpers(object, extra_helpers || {});
+      return this.template.process.call(object, object,v);
+    },
+
+    update : function(element, options) {
+      if (typeof(element) == 'string') {
+        element = document.getElementById(element);
+      };
+      if (options == null) {
+        _template = this;
+        return function(object) {
+          EJS.prototype.update.call(_template, element, object);
+        };
+      };
+      if (typeof(options) == 'string') {
+        params = {};
+        params.url = options;
+        _template = this;
+        params.onComplete = function(request) {
+          var object = eval(request.responseText);
+          EJS.prototype.update.call(_template, element, object);
+        };
+        EJS.ajax_request(params);
+      } else {
+        element.innerHTML = this.render(options);
+      };
+    },
+
+    out : function() {
+      return this.template.out;
+    },
+
+    /**
+     * Sets options on this view to be rendered with.
+     * @param {Object} options
+     */
+    set_options : function(options){
+      this.type = options.type || EJS.type;
+      this.cache = (options.cache != null) ? options.cache : EJS.cache;
+      this.text = options.text || null;
+      this.name =   options.name || null;
+      this.ext = options.ext || EJS.ext;
+      this.extMatch = new RegExp(this.ext.replace(/\./, '\.'));
+    }
+  };
+
+  EJS.endExt = function(path, match) {
+    if (!path) return null;
+    match.lastIndex = 0;
+    return path + (match.test(path) ? '' : this.ext);
+  };
+
+  /* @Static*/
+  EJS.Scanner = function(source, left, right) {
+    extend(this, {
+      left_delimiter:  left +'%',
+      right_delimiter: '%'+right,
+      double_left: left+'%%',
+      double_right: '%%'+right,
+      left_equal: left+'%=',
+      left_comment: left+'%#'
+    });
+    this.SplitRegexp = (left == '[') ? /(\[%%)|(%%\])|(\[%=)|(\[%#)|(\[%)|(%\]\n)|(%\])|(\n)/ : new RegExp('('+this.double_left+')|(%%'+this.double_right+')|('+this.left_equal+')|('+this.left_comment+')|('+this.left_delimiter+')|('+this.right_delimiter+'\n)|('+this.right_delimiter+')|(\n)');
+    this.source = source;
+    this.stag = null;
+    this.lines = 0;
+  };
+
+  EJS.Scanner.to_text = function(input) {
+    if (input == null || input === undefined) return '';
+    if(input instanceof Date) return input.toDateString();
+    if(input.toString) return input.toString();
+    return '';
+  };
+
+  EJS.Scanner.prototype = {
+    scan: function(block) {
+      scanline = this.scanline;
+      regex = this.SplitRegexp;
+      if (! this.source == '') {
+        var source_split = rsplit(this.source, /\n/);
+        for (var i=0; i<source_split.length; i++) {
+          var item = source_split[i];
+          this.scanline(item, regex, block);
+        };
+      };
+    },
+
+    scanline: function(line, regex, block) {
+      this.lines++;
+      var line_split = rsplit(line, regex);
+      for (var i=0; i<line_split.length; i++) {
+        var token = line_split[i];
+        if (token != null) {
+          try {
+            block(token, this);
+          } catch(e) {
+            throw {type: 'EJS.Scanner', line: this.lines};
+          };
+        };
+      };
+    }
+  };
+
+  EJS.Buffer = function(pre_cmd, post_cmd) {
+    this.line = new Array();
+    this.script = "";
+    this.pre_cmd = pre_cmd;
+    this.post_cmd = post_cmd;
+    for (var i=0; i<this.pre_cmd.length; i++) {
+      this.push(pre_cmd[i]);
+    };
+  };
+
+  EJS.Buffer.prototype = {
+    push: function(cmd) {
+      this.line.push(cmd);
+    },
+
+    cr: function() {
+      this.script = this.script + this.line.join('; ');
+      this.line = new Array();
+      this.script = this.script + "\n";
+    },
+
+    close: function() {
+      if (this.line.length > 0) {
+        for (var i=0; i<this.post_cmd.length; i++){
+          this.push(pre_cmd[i]);
+        };
+        this.script = this.script + this.line.join('; ');
+        line = null;
+      };
+    }
+  };
+
+  EJS.Compiler = function(source, left) {
+    this.pre_cmd = ['var ___ViewO = [];'];
+    this.post_cmd = new Array();
+    this.source = ' ';
+    if (source != null) {
+      if (typeof(source) == 'string') {
+        source = source.replace(/\r\n/g, "\n");
+        source = source.replace(/\r/g,   "\n");
+        this.source = source;
+      } else if (source.innerHTML) {
+        this.source = source.innerHTML;
+      };
+      if (typeof this.source != 'string') {
+        this.source = "";
+      };
+    };
+    left = left || '<';
+    var right = '>';
+    switch(left) {
+      case '[':
+        right = ']';
+        break;
+      case '<':
+        break;
+      default:
+        throw left+' is not a supported deliminator';
+        break;
+    };
+    this.scanner = new EJS.Scanner(this.source, left, right);
+    this.out = '';
+  };
+
+  EJS.Compiler.prototype = {
+    compile: function(options, name) {
+      options = options || {};
+      this.out = '';
+      var put_cmd = "___ViewO.push(";
+      var insert_cmd = put_cmd;
+      var buff = new EJS.Buffer(this.pre_cmd, this.post_cmd);
+      var content = '';
+      var clean = function(content) {
+        content = content.replace(/\\/g, '\\\\');
+        content = content.replace(/\n/g, '\\n');
+        content = content.replace(/"/g,   '\\"');
+        return content;
+      };
+      this.scanner.scan(function(token, scanner) {
+        if (scanner.stag == null)  {
+          switch(token) {
+            case '\n':
+              content = content + "\n";
+              buff.push(put_cmd + '"' + clean(content) + '");');
+              buff.cr();
+              content = '';
+              break;
+            case scanner.left_delimiter:
+            case scanner.left_equal:
+            case scanner.left_comment:
+              scanner.stag = token;
+              if (content.length > 0) {
+                buff.push(put_cmd + '"' + clean(content) + '")');
+              };
+              content = '';
+              break;
+            case scanner.double_left:
+              content = content + scanner.left_delimiter;
+              break;
+            default:
+              content = content + token;
+              break;
+          };
+        } else {
+          switch(token) {
+            case scanner.right_delimiter:
+              switch(scanner.stag) {
+                case scanner.left_delimiter:
+                  if (content[content.length - 1] == '\n') {
+                    content = chop(content);
+                    buff.push(content);
+                    buff.cr();
+                  } else {
+                    buff.push(content);
+                  };
+                  break;
+                case scanner.left_equal:
+                  buff.push(insert_cmd + "(EJS.Scanner.to_text(" + content + ")))");
+                  break;
+              };
+              scanner.stag = null;
+              content = '';
+              break;
+            case scanner.double_right:
+              content = content + scanner.right_delimiter;
+              break;
+            default:
+              content = content + token;
+              break;
+          };
+        };
+      });
+      if (content.length > 0) {
+        // Chould be content.dump in Ruby
+        buff.push(put_cmd + '"' + clean(content) + '")');
+      };
+      buff.close();
+      this.out = buff.script + ";";
+      var to_be_evaled = '/*' + name + '*/this.process = function(_CONTEXT,_VIEW) { try { with(_VIEW) { with (_CONTEXT) {' + this.out + " return ___ViewO.join('');}}}catch(e){e.lineNumber=null;throw e;}};";
+      try {
+        eval(to_be_evaled);
+      } catch(e) {
+        if (typeof JSLINT != 'undefined') {
+          JSLINT(this.out);
+          for (var i = 0; i < JSLINT.errors.length; i++) {
+            var error = JSLINT.errors[i];
+            if (error.reason != "Unnecessary semicolon.") {
+              error.line++;
+              var e = new Error();
+              e.lineNumber = error.line;
+              e.message = error.reason;
+              if (options.view) e.fileName = options.view;
+              throw e;
+            };
+          };
+        } else {
+          throw e;
+        };
+      };
+    }
+  };
+
+  //type, cache, folder
+  /**
+   * Sets default options for all views
+   * @param {Object} options Set view with the following options
+   * <table class="options">
+          <tbody><tr><th>Option</th><th>Default</th><th>Description</th></tr>
+          <tr>
+            <td>type</td>
+            <td>'<'</td>
+            <td>type of magic tags.   Options are '&lt;' or '['
+            </td>
+          </tr>
+          <tr>
+            <td>cache</td>
+            <td>true in production mode, false in other modes</td>
+            <td>true to cache template.
+            </td>
+          </tr>
+    </tbody></table>
+   *
+   */
+  EJS.config = function(options){
+    EJS.cache = (options.cache != null) ? options.cache : EJS.cache;
+    EJS.type = (options.type != null) ? options.type : EJS.type;
+    EJS.ext = (options.ext != null) ? options.ext : EJS.ext;
+    var templates_directory = EJS.templates_directory || {}; //nice and private container
+    EJS.templates_directory = templates_directory;
+    EJS.get = function(path, cache) {
+      if(cache == false) return null;
+      if(templates_directory[path]) return templates_directory[path];
+      return null;
+    };
+    EJS.update = function(path, template) {
+      if (path == null) return;
+      templates_directory[path] = template ;
+    };
+    EJS.INVALID_PATH =  -1;
+  };
+  EJS.config( {cache: true, type: '<', ext: '.ejs' } );
+
+  /**
+   * @constructor
+   * By adding functions to EJS.Helpers.prototype, those functions will be available in the
+   * views.
+   * @init Creates a view helper.   This function is called internally.  You should never call it.
+   * @param {Object} data The data passed to the view.  Helpers have access to it through this._data
+   */
+  EJS.Helpers = function(data, extras){
+    this._data = data;
+    this._extras = extras;
+    extend(this, extras);
+  };
+
+  /* @prototype*/
+  EJS.Helpers.prototype = {
+    /**
+     * Renders a new view.  If data is passed in, uses that to render the view.
+     * @param {Object} options standard options passed to a new view.
+     * @param {optional:Object} data
+     * @return {String}
+     */
+    view: function(options, data, helpers) {
+      if (!helpers) helpers = this._extras;
+      if (!data) data = this._data;
+      return new EJS(options).render(data, helpers);
+    },
+    /**
+     * For a given value, tries to create a human representation.
+     * @param {Object} input the value being converted.
+     * @param {Object} null_text what text should be present if input == null or undefined, defaults to ''
+     * @return {String}
+     */
+    to_text: function(input, null_text) {
+      if (input == null || input === undefined) return null_text || '';
+      if (input instanceof(Date)) return input.toDateString();
+      if (input.toString) return input.toString().replace(/\n/g, '<br />').replace(/''/g, "'");
+      return '';
+    }
+  };
+
+  EJS.newRequest = function() {
+    var factories = [function() { return new ActiveXObject("Msxml2.XMLHTTP"); },function() { return new XMLHttpRequest(); },function() { return new ActiveXObject("Microsoft.XMLHTTP"); }];
+    for(var i = 0; i < factories.length; i++) {
+      try {
+        var request = factories[i]();
+        if (request != null)  return request;
+      } catch(e) { continue; }
+    };
+  };
+
+  EJS.request = function(path) {
+    var request = new EJS.newRequest();
+    request.open("GET", path, false);
+    try {
+      request.send(null);
+    } catch(e){
+      return null;
+    };
+    if ( request.status == 404 || request.status == 2 ||(request.status == 0 && request.responseText == '') ) return null;
+    return request.responseText;
+  };
+
+  EJS.ajax_request = function(params) {
+    params.method = ( params.method ? params.method : 'GET');
+    var request = new EJS.newRequest();
+    request.onreadystatechange = function() {
+      if (request.readyState == 4) {
+        if (request.status == 200) {
+          params.onComplete(request);
+        } else {
+          params.onComplete(request);
+        };
+      };
+    };
+    request.open(params.method, params.url);
+    request.send(null);
+  };
+
+  EJS.Helpers.prototype.date_tag = function(name, value , html_options) {
+    if(!(value instanceof(Date))) value = new Date();
+    var month_names = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
+    var years = [], months = [], days =[];
+    var year = value.getFullYear();
+    var month = value.getMonth();
+    var day = value.getDate();
+    for (var y = year - 15; y < year+15 ; y++) {
+      years.push({value: y, text: y});
+    };
+    for (var m = 0; m < 12; m++) {
+      months.push({value: (m), text: month_names[m]});
+    };
+    for (var d = 0; d < 31; d++) {
+      days.push({value: (d+1), text: (d+1)});
+    };
+    var year_select = this.select_tag(name+'[year]', year, years, {id: name+'[year]'} );
+    var month_select = this.select_tag(name+'[month]', month, months, {id: name+'[month]'});
+    var day_select = this.select_tag(name+'[day]', day, days, {id: name+'[day]'});
+    return year_select+month_select+day_select;
+  };
+
+  EJS.Helpers.prototype.form_tag = function(action, html_options) {
+    html_options = html_options || {};
+    html_options.action = action;
+    if(html_options.multipart == true) {
+      html_options.method = 'post';
+      html_options.enctype = 'multipart/form-data';
+    };
+    return this.start_tag_for('form', html_options);
+  };
+
+  EJS.Helpers.prototype.form_tag_end = function() {
+    return this.tag_end('form');
+  };
+
+  EJS.Helpers.prototype.hidden_field_tag   = function(name, value, html_options) {
+    return this.input_field_tag(name, value, 'hidden', html_options);
+  };
+
+  EJS.Helpers.prototype.input_field_tag = function(name, value , inputType, html_options) {
+    html_options = html_options || {};
+    html_options.id   = html_options.id || name;
+    html_options.value = value || '';
+    html_options.type = inputType || 'text';
+    html_options.name = name;
+    return this.single_tag_for('input', html_options);
+  };
+
+  EJS.Helpers.prototype.is_current_page = function(url) {
+    return (window.location.href == url || window.location.pathname == url ? true : false);
+  };
+
+  EJS.Helpers.prototype.link_to = function(name, url, html_options) {
+    if(!name) var name = 'null';
+    if(!html_options) var html_options = {};
+    if(html_options.confirm){
+      html_options.onclick = " var ret_confirm = confirm(\""+html_options.confirm+"\"); if(!ret_confirm){ return false;} ";
+      html_options.confirm = null;
+    };
+    html_options.href = url;
+    return this.start_tag_for('a', html_options)+name+ this.tag_end('a');
+  };
+
+  EJS.Helpers.prototype.submit_link_to = function(name, url, html_options) {
+    if(!name) var name = 'null';
+    if(!html_options) var html_options = {};
+    html_options.onclick = html_options.onclick || '';
+    if(html_options.confirm){
+      html_options.onclick = " var ret_confirm = confirm(\""+html_options.confirm+"\"); if(!ret_confirm){ return false;} ";
+      html_options.confirm = null;
+    };
+    html_options.value = name;
+    html_options.type = 'submit';
+    html_options.onclick = html_options.onclick + (url ? this.url_for(url) : '')+'return false;';
+    return this.start_tag_for('input', html_options);
+  };
+
+  EJS.Helpers.prototype.link_to_if = function(condition, name, url, html_options, post, block) {
+    return this.link_to_unless((condition == false), name, url, html_options, post, block);
+  };
+
+  EJS.Helpers.prototype.link_to_unless = function(condition, name, url, html_options, block) {
+    html_options = html_options || {};
+    if(condition) {
+      if(block && typeof(block) == 'function') {
+        return block(name, url, html_options, block);
+      } else {
+        return name;
+      };
+    } else {
+      return this.link_to(name, url, html_options);
+    };
+  };
+
+  EJS.Helpers.prototype.link_to_unless_current = function(name, url, html_options, block) {
+    html_options = html_options || {};
+    return this.link_to_unless(this.is_current_page(url), name, url, html_options, block);
+  };
+
+
+  EJS.Helpers.prototype.password_field_tag = function(name, value, html_options) {
+    return this.input_field_tag(name, value, 'password', html_options);
+  };
+
+  EJS.Helpers.prototype.select_tag = function(name, value, choices, html_options) {
+    html_options = html_options || {};
+    html_options.id   = html_options.id  || name;
+    html_options.value = value;
+    html_options.name = name;
+    var txt = '';
+    txt += this.start_tag_for('select', html_options);
+    for(var i = 0; i < choices.length; i++) {
+      var choice = choices[i];
+      var optionOptions = {value: choice.value};
+      if(choice.value == value) optionOptions.selected ='selected';
+      txt += this.start_tag_for('option', optionOptions )+choice.text+this.tag_end('option');
+    };
+    txt += this.tag_end('select');
+    return txt;
+  };
+
+  EJS.Helpers.prototype.single_tag_for = function(tag, html_options) {
+    return this.tag(tag, html_options, '/>');
+  };
+
+  EJS.Helpers.prototype.start_tag_for = function(tag, html_options)   {
+    return this.tag(tag, html_options);
+  };
+
+  EJS.Helpers.prototype.submit_tag = function(name, html_options) {
+    html_options = html_options || {};
+    html_options.type = html_options.type   || 'submit';
+    html_options.value = name || 'Submit';
+    return this.single_tag_for('input', html_options);
+  };
+
+  EJS.Helpers.prototype.tag = function(tag, html_options, end) {
+    if(!end) var end = '>';
+    var txt = ' ';
+    for(var attr in html_options) {
+      if(html_options[attr] != null) {
+        var value = html_options[attr].toString();
+      } else {
+        var value='';
+      };
+      // special case because "class" is a reserved word in IE
+      if(attr == "Class") attr = "class";
+      if( value.indexOf("'") != -1 ) {
+        txt += attr+'=\"'+value+'\" ';
+      } else {
+        txt += attr+"='"+value+"' ";
+      };
+    };
+    return '<' + tag + txt + end;
+  };
+
+  EJS.Helpers.prototype.tag_end = function(tag) {
+    return '</'+tag+'>';
+  };
+
+  EJS.Helpers.prototype.text_area_tag = function(name, value, html_options) {
+    html_options = html_options || {};
+    html_options.id   = html_options.id  || name;
+    html_options.name   = html_options.name  || name;
+    value = value || '';
+    if(html_options.size) {
+      html_options.cols = html_options.size.split('x')[0];
+      html_options.rows = html_options.size.split('x')[1];
+      delete html_options.size;
+    };
+    html_options.cols = html_options.cols  || 50;
+    html_options.rows = html_options.rows  || 4;
+    return  this.start_tag_for('textarea', html_options)+value+this.tag_end('textarea');
+  };
+
+  EJS.Helpers.prototype.text_tag = EJS.Helpers.prototype.text_area_tag;
+
+  EJS.Helpers.prototype.text_field_tag = function(name, value, html_options) {
+    return this.input_field_tag(name, value, 'text', html_options);
+  };
+
+  EJS.Helpers.prototype.url_for = function(url) {
+    return 'window.location="' + url + '";';
+  };
+
+  EJS.Helpers.prototype.img_tag = function(image_location, alt, options){
+    options = options || {};
+    options.src = image_location;
+    options.alt = alt;
+    return this.single_tag_for('img', options);
+  };
+
+  // -------------------------------------------------------------
+
+  Sammy = Sammy || {};
+
+  Sammy.EJS = function(app, method_alias) {
+
+    // *Helper:* Uses simple templating to parse ERB like templates.
+    //
+    // ### Arguments
+    //
+    // * `template` A String template. '<% %>' tags are evaluated as Javascript and replaced with the elements in data.
+    // * `data` An Object containing the replacement values for the template.
+    //data is extended with the <tt>EventContext</tt> allowing you to call its methods within the template.
+    // * `name` An optional String name to cache the template.
+    //
+    var template = function(template, data, name) {
+      // use name for caching
+      if (typeof name == 'undefined') name = template;
+      return new EJS({text: template, name: name}).render(data);
+    };
+
+    // set the default method name/extension
+    if (!method_alias) method_alias = 'ejs';
+
+    // create the helper at the method alias
+    app.helper(method_alias, template);
+
+   };
+
+})(jQuery);

http://git-wip-us.apache.org/repos/asf/cordova-registry-web/blob/f50cc931/attachments/sammy/plugins/sammy.form.js
----------------------------------------------------------------------
diff --git a/attachments/sammy/plugins/sammy.form.js b/attachments/sammy/plugins/sammy.form.js
new file mode 100644
index 0000000..78edb87
--- /dev/null
+++ b/attachments/sammy/plugins/sammy.form.js
@@ -0,0 +1,274 @@
+(function($) {
+
+  Sammy = Sammy || {};
+
+  function getStringContent(object, content) {
+    if (typeof content === 'undefined') {
+      return '';
+    } else if ($.isFunction(content)) {
+      content = content.apply(object);
+    }
+    return content.toString();
+  };
+
+  function simple_element(tag, attributes, content) {
+    var html = "<";
+    html += tag;
+    if (typeof attributes != 'undefined') {
+      $.each(attributes, function(key, value) {
+        if (value != null) {
+          html += " " + key + "='";
+          html += getStringContent(attributes, value).replace(/\'/g, "\'");
+          html += "'";
+        }
+      });
+    }
+    if (content === false) {
+      html += ">";
+    } else if (typeof content != 'undefined') {
+      html += ">";
+      html += getStringContent(this, content);
+      html += "</" + tag + ">";
+    } else {
+      html += " />";
+    }
+    return html;
+  };
+
+  // Sammy.FormBuilder is based very closely on the Rails FormBuilder classes.
+  // Its goal is to make it easy to create HTML forms for creating and editing
+  // JavaScript objects. It eases the process by auto-populating existing values
+  // into form inputs and creating input names suitable for parsing by
+  // Sammy.NestedParams and other backend frameworks.
+  //
+  // You initialize a Sammy.FormBuilder by passing the 'name' of the object and
+  // the object itself. Once initialized you create form elements with the object's
+  // prototype methods. Each of these methods returns a string of HTML suitable for
+  // appending through a template or directly with jQuery.
+  //
+  // ### Example
+  //
+  //      var item = {
+  //        name: 'My Item',
+  //        price: '$25.50',
+  //        meta: {
+  //          id: '123'
+  //        }
+  //      };
+  //      var form = new Sammy.FormBuilder('item', item);
+  //      form.text('name');
+  //      //=> <input type='text' name='item[form]' value='My Item' />
+  //
+  // Nested attributes can be accessed/referred to by a 'keypath' which is
+  // basically a string representation of the dot notation.
+  //
+  //      form.hidden('meta.id');
+  //      //=> <input type='hidden' name='item[meta][id]' value='123' />
+  //
+  Sammy.FormBuilder = function(name, object) {
+    this.name   = name;
+    this.object = object;
+  };
+
+  $.extend(Sammy.FormBuilder.prototype, {
+
+    // creates the open form tag with the object attributes
+    open: function(attributes) {
+      return simple_element('form', $.extend({'method': 'post', 'action': '#/' + this.name + 's'}, attributes), false);
+    },
+
+    // closes the form
+    close: function() {
+      return '</form>';
+    },
+
+    // creates a label for `keypath` with the text `content
+    // with an optional `attributes` object
+    label: function(keypath, content, attributes) {
+      var attrs = {'for': this._attributesForKeyPath(keypath).name};
+      return simple_element('label', $.extend(attrs, attributes), content);
+    },
+
+    // creates a hidden input for `keypath` with an optional `attributes` object
+    hidden: function(keypath, attributes) {
+      attributes = $.extend({type: 'hidden'}, this._attributesForKeyPath(keypath), attributes);
+      return simple_element('input', attributes);
+    },
+
+    // creates a text input for `keypath` with an optional `attributes` object
+    text: function(keypath, attributes) {
+      attributes = $.extend({type: 'text'}, this._attributesForKeyPath(keypath), attributes);
+      return simple_element('input', attributes);
+    },
+
+    // creates a textarea for `keypath` with an optional `attributes` object
+    textarea: function(keypath, attributes) {
+      var current;
+      attributes = $.extend(this._attributesForKeyPath(keypath), attributes);
+      current = attributes.value;
+      delete attributes['value'];
+      return simple_element('textarea', attributes, current);
+    },
+
+    // creates a password input for `keypath` with an optional `attributes` object
+    password: function(keypath, attributes) {
+      return this.text(keypath, $.extend({type: 'password'}, attributes));
+    },
+
+    // creates a select element for `keypath` with the option elements
+    // specified by an array in `options`. If `options` is an array of arrays,
+    // the first element in each subarray becomes the text of the option and the
+    // second becomes the value.
+    //
+    // ### Example
+    //
+    //     var options = [
+    //       ['Small', 's'],
+    //       ['Medium', 'm'],
+    //       ['Large', 'l']
+    //     ];
+    //     form.select('size', options);
+    //     //=> <select name='item[size]'><option value='s'>Small</option> ...
+    //
+    //
+    select: function(keypath, options, attributes) {
+      var option_html = "", selected;
+      attributes = $.extend(this._attributesForKeyPath(keypath), attributes);
+      selected = attributes.value;
+      delete attributes['value'];
+      $.each(options, function(i, option) {
+        var value, text, option_attrs;
+        if ($.isArray(option)) {
+          value = option[1], text = option[0];
+        } else {
+          value = option, text = option;
+        }
+        option_attrs = {value: getStringContent(this.object, value)};
+        // select the correct option
+        if (value === selected) { option_attrs.selected = 'selected'; }
+        option_html += simple_element('option', option_attrs, text);
+      });
+      return simple_element('select', attributes, option_html);
+    },
+
+    // creates a radio input for keypath with the value `value`. Multiple
+    // radios can be created with different value, if `value` equals the
+    // current value of the key of the form builder's object the attribute
+    // checked='checked' will be added.
+    radio: function(keypath, value, attributes) {
+      var selected;
+      attributes = $.extend(this._attributesForKeyPath(keypath), attributes);
+      selected = attributes.value;
+      attributes.value = getStringContent(this.object, value);
+      if (selected == attributes.value) {
+        attributes.checked = 'checked';
+      }
+      return simple_element('input', $.extend({type:'radio'}, attributes));
+    },
+
+    // creates a checkbox input for keypath with the value `value`. Multiple
+    // checkboxes can be created with different value, if `value` equals the
+    // current value of the key of the form builder's object the attribute
+    // checked='checked' will be added.
+    //
+    // By default `checkbox()` also generates a hidden element whose value is
+    // the inverse of the value given. This is known hack to get around a common
+    // gotcha where browsers and jQuery itself does not include 'unchecked'
+    // elements in the list of submittable inputs. This ensures that a value
+    // should always be passed to Sammy and hence the server. You can disable
+    // the creation of the hidden element by setting the `hidden_element` attribute
+    // to `false`
+    checkbox: function(keypath, value, attributes) {
+      var content = "";
+      if (!attributes) { attributes = {}; }
+      if (attributes.hidden_element !== false) {
+        content += this.hidden(keypath, {'value': !value});
+      }
+      delete attributes['hidden_element'];
+      content += this.radio(keypath, value, $.extend({type: 'checkbox'}, attributes));
+      return content;
+    },
+
+    // creates a submit input for `keypath` with an optional `attributes` object
+    submit: function(attributes) {
+      return simple_element('input', $.extend({'type': 'submit'}, attributes));
+    },
+
+    _attributesForKeyPath: function(keypath) {
+      var builder    = this,
+          keys       = $.isArray(keypath) ? keypath : keypath.split(/\./),
+          name       = builder.name,
+          value      = builder.object,
+          class_name = builder.name;
+
+      $.each(keys, function(i, key) {
+        if ((typeof value === 'undefined') || value == '') {
+          value = ''
+        } else if (typeof key == 'number' || key.match(/^\d+$/)) {
+          value = value[parseInt(key, 10)];
+        } else {
+          value = value[key];
+        }
+        name += "[" + key + "]";
+        class_name += "-" + key;
+      });
+      return {'name': name,
+              'value': getStringContent(builder.object, value),
+              'class': class_name};
+    }
+  });
+
+  // Sammy.Form is a Sammy plugin that adds form building helpers to a
+  // Sammy.Application
+  Sammy.Form = function(app) {
+
+    app.helpers({
+      // simple_element is a simple helper for creating HTML tags.
+      //
+      // ### Arguments
+      //
+      // * `tag` the HTML tag to generate e.g. input, p, etc/
+      // * `attributes` an object representing the attributes of the element as
+      //   key value pairs. e.g. {class: 'element-class'}
+      // * `content` an optional string representing the content for the
+      //   the element. If ommited, the element becomes self closing
+      //
+      simple_element: simple_element,
+
+      // formFor creates a Sammy.Form builder object with the passed `name`
+      // and `object` and passes it as an argument to the `content_callback`.
+      // This is a shortcut for creating FormBuilder objects for use within
+      // templates.
+      //
+      // ### Example
+      //
+      //      // in item_form.template
+      //
+      //      <% formFor('item', item, function(f) { %>
+      //        <%= f.open({action: '#/items'}) %>
+      //        <p>
+      //          <%= f.label('name') %>
+      //          <%= f.text('name') %>
+      //        </p>
+      //        <p>
+      //          <%= f.submit() %>
+      //        </p>
+      //        <%= f.close() %>
+      //      <% }); %>
+      //
+      formFor: function(name, object, content_callback) {
+        var builder;
+        // define a form with just a name
+        if ($.isFunction(object)) {
+          content_callback = object;
+          object = this[name];
+        }
+        builder = new Sammy.FormBuilder(name, object),
+        content_callback.apply(this, [builder]);
+        return builder;
+      }
+    });
+
+  };
+
+})(jQuery);

http://git-wip-us.apache.org/repos/asf/cordova-registry-web/blob/f50cc931/attachments/sammy/plugins/sammy.haml.js
----------------------------------------------------------------------
diff --git a/attachments/sammy/plugins/sammy.haml.js b/attachments/sammy/plugins/sammy.haml.js
new file mode 100644
index 0000000..9ea579d
--- /dev/null
+++ b/attachments/sammy/plugins/sammy.haml.js
@@ -0,0 +1,553 @@
+(function($) {
+
+  /*
+    port of http://github.com/creationix/haml-js
+    version v0.2.2 - 2010-04-05
+    by Tim Caswell <ti...@creationix.com>
+  */
+
+  var matchers, self_close_tags, embedder;
+
+  function html_escape(text) {
+    return (text + "").
+      replace(/&/g, "&amp;").
+      replace(/</g, "&lt;").
+      replace(/>/g, "&gt;").
+      replace(/\"/g, "&quot;");
+  }
+
+  function render_attribs(attribs) {
+    var key, value, result = [];
+    for (key in attribs) {
+      if (key !== 'content' && attribs.hasOwnProperty(key)) {
+        switch (attribs[key]) {
+        case 'undefined':
+        case 'false':
+        case 'null':
+        case '""':
+          break;
+        default:
+          try {
+            value = JSON.parse("[" + attribs[key] +"]")[0];
+            if (value === true) {
+              value = key;
+            } else if (typeof value === 'string' && embedder.test(value)) {
+              value = '" +\n' + parse_interpol(html_escape(value)) + ' +\n"';
+            } else {
+              value = html_escape(value);
+            }
+            result.push(" " + key + '=\\"' + value + '\\"');
+          } catch (e) {
+            result.push(" " + key + '=\\"" + html_escape(' + attribs[key] + ') + "\\"');
+          }
+        }
+      }
+    }
+    return result.join("");
+  }
+
+  // Parse the attribute block using a state machine
+  function parse_attribs(line) {
+    var attributes = {},
+        l = line.length,
+        i, c,
+        count = 1,
+        quote = false,
+        skip = false,
+        open, close, joiner, seperator,
+        pair = {
+          start: 1,
+          middle: null,
+          end: null
+        };
+
+    if (!(l > 0 && (line.charAt(0) === '{' || line.charAt(0) === '('))) {
+      return {
+        content: line[0] === ' ' ? line.substr(1, l) : line
+      };
+    }
+    open = line.charAt(0);
+    close = (open === '{') ? '}' : ')';
+    joiner = (open === '{') ? ':' : '=';
+    seperator = (open === '{') ? ',' : ' ';
+
+    function process_pair() {
+      if (typeof pair.start === 'number' &&
+          typeof pair.middle === 'number' &&
+          typeof pair.end === 'number') {
+        var key = line.substr(pair.start, pair.middle - pair.start).trim(),
+            value = line.substr(pair.middle + 1, pair.end - pair.middle - 1).trim();
+        attributes[key] = value;
+      }
+      pair = {
+        start: null,
+        middle: null,
+        end: null
+      };
+    }
+
+    for (i = 1; count > 0; i += 1) {
+
+      // If we reach the end of the line, then there is a problem
+      if (i > l) {
+        throw "Malformed attribute block";
+      }
+
+      c = line.charAt(i);
+      if (skip) {
+        skip = false;
+      } else {
+        if (quote) {
+          if (c === '\\') {
+            skip = true;
+          }
+          if (c === quote) {
+            quote = false;
+          }
+        } else {
+          if (c === '"' || c === "'") {
+            quote = c;
+          }
+
+          if (count === 1) {
+            if (c === joiner) {
+              pair.middle = i;
+            }
+            if (c === seperator || c === close) {
+              pair.end = i;
+              process_pair();
+              if (c === seperator) {
+                pair.start = i + 1;
+              }
+            }
+          }
+
+          if (c === open) {
+            count += 1;
+          }
+          if (c === close) {
+            count -= 1;
+          }
+        }
+      }
+    }
+    attributes.content = line.substr(i, line.length);
+    return attributes;
+  }
+
+  // Split interpolated strings into an array of literals and code fragments.
+  function parse_interpol(value) {
+    var items = [],
+        pos = 0,
+        next = 0,
+        match;
+    while (true) {
+      // Match up to embedded string
+      next = value.substr(pos).search(embedder);
+      if (next < 0) {
+        if (pos < value.length) {
+          items.push(JSON.stringify(value.substr(pos)));
+        }
+        break;
+      }
+      items.push(JSON.stringify(value.substr(pos, next)));
+      pos += next;
+
+      // Match embedded string
+      match = value.substr(pos).match(embedder);
+      next = match[0].length;
+      if (next < 0) { break; }
+      items.push(match[1] || match[2]);
+      pos += next;
+    }
+    return items.filter(function (part) { return part && part.length > 0}).join(" +\n");
+  }
+
+  // Used to find embedded code in interpolated strings.
+  embedder = /\#\{([^}]*)\}/;
+
+  self_close_tags = ["meta", "img", "link", "br", "hr", "input", "area", "base"];
+
+  // All matchers' regexps should capture leading whitespace in first capture
+  // and trailing content in last capture
+  matchers = [
+    // html tags
+    {
+      regexp: /^(\s*)((?:[.#%][a-z_\-][a-z0-9_\-]*)+)(.*)$/i,
+      process: function () {
+        var tag, classes, ids, attribs, content;
+        tag = this.matches[2];
+        classes = tag.match(/\.([a-z_\-][a-z0-9_\-]*)/gi);
+        ids = tag.match(/\#([a-z_\-][a-z0-9_\-]*)/gi);
+        tag = tag.match(/\%([a-z_\-][a-z0-9_\-]*)/gi);
+
+        // Default to <div> tag
+        tag = tag ? tag[0].substr(1, tag[0].length) : 'div';
+
+        attribs = this.matches[3];
+        if (attribs) {
+          attribs = parse_attribs(attribs);
+          if (attribs.content) {
+            this.contents.unshift(attribs.content.trim());
+            delete(attribs.content);
+          }
+        } else {
+          attribs = {};
+        }
+
+        if (classes) {
+          classes = classes.map(function (klass) {
+            return klass.substr(1, klass.length);
+          }).join(' ');
+          if (attribs['class']) {
+            try {
+              attribs['class'] = JSON.stringify(classes + " " + JSON.parse(attribs['class']));
+            } catch (e) {
+              attribs['class'] = JSON.stringify(classes + " ") + " + " + attribs['class'];
+            }
+          } else {
+            attribs['class'] = JSON.stringify(classes);
+          }
+        }
+        if (ids) {
+          ids = ids.map(function (id) {
+            return id.substr(1, id.length);
+          }).join(' ');
+          if (attribs.id) {
+            attribs.id = JSON.stringify(ids + " ") + attribs.id;
+          } else {
+            attribs.id = JSON.stringify(ids);
+          }
+        }
+
+        attribs = render_attribs(attribs);
+
+        content = this.render_contents();
+        if (content === '""') {
+          content = '';
+        }
+
+        if (self_close_tags.indexOf(tag) == -1) {
+          return '"<' + tag + attribs + '>"' +
+            (content.length > 0 ? ' + \n' + content : "") +
+            ' + \n"</' + tag + '>"';
+        } else {
+          return '"<' + tag + attribs + ' />"';
+        }
+      }
+    },
+
+    // each loops
+    {
+      regexp: /^(\s*)(?::for|:each)\s+(?:([a-z_][a-z_\-]*),\s*)?([a-z_][a-z_\-]*)\s+in\s+(.*)(\s*)$/i,
+      process: function () {
+        var ivar = this.matches[2] || '__key__', // index
+            vvar = this.matches[3],              // value
+            avar = this.matches[4],              // array
+            rvar = '__result__';                 // results
+
+        if (this.matches[5]) {
+          this.contents.unshift(this.matches[5]);
+        }
+        return '(function () { ' +
+          'var ' + rvar + ' = [], ' + ivar + ', ' + vvar + '; ' +
+          'for (' + ivar + ' in ' + avar + ') { ' +
+          'if (' + avar + '.hasOwnProperty(' + ivar + ')) { ' +
+          vvar + ' = ' + avar + '[' + ivar + ']; ' +
+          rvar + '.push(\n' + (this.render_contents() || "''") + '\n); ' +
+          '} } return ' + rvar + '.join(""); }).call(this)';
+      }
+    },
+
+    // if statements
+    {
+      regexp: /^(\s*):if\s+(.*)\s*$/i,
+      process: function () {
+        var condition = this.matches[2];
+        return '(function () { ' +
+          'if (' + condition + ') { ' +
+          'return (\n' + (this.render_contents() || '') + '\n);' +
+          '} else { return ""; } }).call(this)';
+      }
+    },
+
+    // declarations
+    {
+      regexp: /^()!!!(?:\s*(.*))\s*$/,
+      process: function () {
+        var line = '';
+        switch ((this.matches[2] || '').toLowerCase()) {
+        case '':
+          // XHTML 1.0 Transitional
+          line = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">';
+          break;
+        case 'strict':
+        case '1.0':
+          // XHTML 1.0 Strict
+          line = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">';
+          break;
+        case 'frameset':
+          // XHTML 1.0 Frameset
+          line = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">';
+          break;
+        case '5':
+          // XHTML 5
+          line = '<!DOCTYPE html>';
+          break;
+        case '1.1':
+          // XHTML 1.1
+          line = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">';
+          break;
+        case 'basic':
+          // XHTML Basic 1.1
+          line = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN" "http://www.w3.org/TR/xhtml-basic/xhtml-basic11.dtd">';
+          break;
+        case 'mobile':
+          // XHTML Mobile 1.2
+          line = '<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.2//EN" "http://www.openmobilealliance.org/tech/DTD/xhtml-mobile12.dtd">';
+          break;
+        case 'xml':
+          // XML
+          line = "<?xml version='1.0' encoding='utf-8' ?>";
+          break;
+        case 'xml iso-8859-1':
+          // XML iso-8859-1
+          line = "<?xml version='1.0' encoding='iso-8859-1' ?>";
+          break;
+        }
+        return JSON.stringify(line + "\n");
+      }
+    },
+
+    // Embedded markdown. Needs to be added to exports externally.
+    {
+      regexp: /^(\s*):markdown\s*$/i,
+      process: function () {
+        return parse_interpol(exports.Markdown.encode(this.contents.join("\n")));
+      }
+    },
+
+    // script blocks
+    {
+      regexp: /^(\s*):(?:java)?script\s*$/,
+      process: function () {
+        return parse_interpol('\n<script type="text/javascript">\n' +
+          '//<![CDATA[\n' +
+          this.contents.join("\n") +
+          "\n//]]>\n</script>\n");
+      }
+    },
+
+    // css blocks
+    {
+      regexp: /^(\s*):css\s*$/,
+      process: function () {
+        return JSON.stringify('\n<style type="text/css">\n' +
+          this.contents.join("\n") +
+          "\n</style>\n");
+      }
+    },
+
+  ];
+
+  function compile(lines) {
+    var block = false,
+        output = [];
+
+    // If lines is a string, turn it into an array
+    if (typeof lines === 'string') {
+      lines = lines.trim().split("\n");
+    }
+
+    lines.forEach(function(line) {
+      var match, found = false;
+
+      // Collect all text as raw until outdent
+      if (block) {
+        match = block.check_indent(line);
+        if (match) {
+          block.contents.push(match[1] || "");
+          return;
+        } else {
+          output.push(block.process());
+          block = false;
+        }
+      }
+
+      matchers.forEach(function (matcher) {
+        if (!found) {
+          match = matcher.regexp(line);
+          if (match) {
+            block = {
+              contents: [],
+              matches: match,
+              check_indent: new RegExp("^(?:\\s*|" + match[1] + "  (.*))$"),
+              process: matcher.process,
+              render_contents: function () {
+                return compile(this. contents);
+              }
+            };
+            found = true;
+          }
+        }
+      });
+
+      // Match plain text
+      if (!found) {
+        output.push(function () {
+          // Escaped plain text
+          if (line[0] === '\\') {
+            return parse_interpol(line.substr(1, line.length));
+          }
+
+          // Plain variable data
+          if (line[0] === '=') {
+            line = line.substr(1, line.length).trim();
+            try {
+              return parse_interpol(JSON.parse(line));
+            } catch (e) {
+              return line;
+            }
+          }
+
+          // HTML escape variable data
+          if (line.substr(0, 2) === "&=") {
+            line = line.substr(2, line.length).trim();
+            try {
+              return JSON.stringify(html_escape(JSON.parse(line)));
+            } catch (e2) {
+              return 'html_escape(' + line + ')';
+            }
+          }
+
+          // Plain text
+          return parse_interpol(line);
+        }());
+      }
+
+    });
+    if (block) {
+      output.push(block.process());
+    }
+    return output.filter(function (part) { return part && part.length > 0}).join(" +\n");
+  };
+
+  function optimize(js) {
+    var new_js = [], buffer = [], part, end;
+
+    function flush() {
+      if (buffer.length > 0) {
+        new_js.push(JSON.stringify(buffer.join("")) + end);
+        buffer = [];
+      }
+    }
+    js.split("\n").forEach(function (line) {
+      part = line.match(/^(\".*\")(\s*\+\s*)?$/);
+      if (!part) {
+        flush();
+        new_js.push(line);
+        return;
+      }
+      end = part[2] || "";
+      part = part[1];
+      try {
+        buffer.push(JSON.parse(part));
+      } catch (e) {
+        flush();
+        new_js.push(line);
+      }
+    });
+    flush();
+    return new_js.join("\n");
+  };
+
+  function Haml(haml) {
+    var js = optimize(compile(haml));
+    return new Function("locals",
+      html_escape + "\n" +
+      "with(locals || {}) {\n" +
+      "  try {\n" +
+      "    return (" + js + ");\n" +
+      "  } catch (e) {\n" +
+      "    return \"\\n<pre class='error'>\" + html_escape(e.stack) + \"</pre>\\n\";\n" +
+      "  }\n" +
+      "}");
+  }
+
+
+  Sammy = Sammy || {};
+
+  // <tt>Sammy.Haml</tt> provides a quick way of using haml style templates in your app.
+  // The plugin itself includes the haml-js library created by Tim Caswell at
+  // at http://github.com/creationix/haml-js
+  //
+  // Haml is an alternative HTML syntax that is really great for describing
+  // the structure of HTML documents.
+  //
+  // By default using Sammy.Haml in your app adds the <tt>haml()</tt> method to the EventContext
+  // prototype. However, just like <tt>Sammy.Template</tt> you can change the default name of the method
+  // by passing a second argument (e.g. you could use the hml() as the method alias so that all the template
+  // files could be in the form file.hml instead of file.haml)
+  //
+  // ### Example
+  //
+  // The template (mytemplate.haml):
+  //
+  //       %h1&= title
+  //
+  //       Hey, #{name}! Welcome to Haml!
+  //
+  // The app:
+  //
+  //       var $.app = $.sammy(function() {
+  //         // include the plugin
+  //         this.use(Sammy.Haml);
+  //
+  //         this.get('#/hello/:name', function() {
+  //           // set local vars
+  //           this.title = 'Hello!'
+  //           this.name = this.params.name;
+  //           // render the template and pass it through haml
+  //           this.partial('mytemplate.haml');
+  //         });
+  //
+  //       });
+  //
+  // If I go to #/hello/AQ in the browser, Sammy will render this to the <tt>body</tt>:
+  //
+  //       <h1>Hello!</h1>
+  //
+  //       Hey, AQ! Welcome to HAML!
+  //
+  // Note: You dont have to include the haml.js file on top of the plugin as the plugin
+  // includes the full source.
+  //
+  Sammy.Haml = function(app, method_alias) {
+    app.use(Sammy.JSON);
+
+    var haml_cache = {};
+    // *Helper* Uses haml-js to parse a template and interpolate and work with the passed data
+    //
+    // ### Arguments
+    //
+    // * `template` A String template.
+    // * `data` An Object containing the replacement values for the template.
+    //   data is extended with the <tt>EventContext</tt> allowing you to call its methods within the template.
+    //
+    var haml = function(template, data, name) {
+      // use name for caching
+      if (typeof name == 'undefined') name = template;
+      var fn = haml_cache[name];
+      if (!fn) {
+        fn = haml_cache[name] = Haml(template);
+      }
+      return fn($.extend({}, this, data));
+    };
+
+    // set the default method name/extension
+    if (!method_alias) method_alias = 'haml';
+    app.helper(method_alias, haml);
+
+  };
+
+})(jQuery);

http://git-wip-us.apache.org/repos/asf/cordova-registry-web/blob/f50cc931/attachments/sammy/plugins/sammy.json.js
----------------------------------------------------------------------
diff --git a/attachments/sammy/plugins/sammy.json.js b/attachments/sammy/plugins/sammy.json.js
new file mode 100644
index 0000000..83b9dd0
--- /dev/null
+++ b/attachments/sammy/plugins/sammy.json.js
@@ -0,0 +1,362 @@
+(function($) {
+
+  // json2.js - only included if native json does not exist
+  // http://www.json.org/js.html
+  if (!window.JSON) {
+    window.JSON = {};
+  }
+  (function () {
+
+      function f(n) {
+          // Format integers to have at least two digits.
+          return n < 10 ? '0' + n : n;
+      }
+
+      if (typeof Date.prototype.toJSON !== 'function') {
+
+          Date.prototype.toJSON = function (key) {
+
+              return this.getUTCFullYear()   + '-' +
+                   f(this.getUTCMonth() + 1) + '-' +
+                   f(this.getUTCDate())      + 'T' +
+                   f(this.getUTCHours())     + ':' +
+                   f(this.getUTCMinutes())   + ':' +
+                   f(this.getUTCSeconds())   + 'Z';
+          };
+
+          String.prototype.toJSON =
+          Number.prototype.toJSON =
+          Boolean.prototype.toJSON = function (key) {
+              return this.valueOf();
+          };
+      }
+
+      var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
+          escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
+          gap,
+          indent,
+          meta = {    // table of character substitutions
+              '\b': '\\b',
+              '\t': '\\t',
+              '\n': '\\n',
+              '\f': '\\f',
+              '\r': '\\r',
+              '"' : '\\"',
+              '\\': '\\\\'
+          },
+          rep;
+
+
+      function quote(string) {
+
+  // If the string contains no control characters, no quote characters, and no
+  // backslash characters, then we can safely slap some quotes around it.
+  // Otherwise we must also replace the offending characters with safe escape
+  // sequences.
+
+          escapable.lastIndex = 0;
+          return escapable.test(string) ?
+              '"' + string.replace(escapable, function (a) {
+                  var c = meta[a];
+                  return typeof c === 'string' ? c :
+                      '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
+              }) + '"' :
+              '"' + string + '"';
+      }
+
+
+      function str(key, holder) {
+
+  // Produce a string from holder[key].
+
+          var i,          // The loop counter.
+              k,          // The member key.
+              v,          // The member value.
+              length,
+              mind = gap,
+              partial,
+              value = holder[key];
+
+  // If the value has a toJSON method, call it to obtain a replacement value.
+
+          if (value && typeof value === 'object' &&
+                  typeof value.toJSON === 'function') {
+              value = value.toJSON(key);
+          }
+
+  // If we were called with a replacer function, then call the replacer to
+  // obtain a replacement value.
+
+          if (typeof rep === 'function') {
+              value = rep.call(holder, key, value);
+          }
+
+  // What happens next depends on the value's type.
+
+          switch (typeof value) {
+          case 'string':
+              return quote(value);
+
+          case 'number':
+
+  // JSON numbers must be finite. Encode non-finite numbers as null.
+
+              return isFinite(value) ? String(value) : 'null';
+
+          case 'boolean':
+          case 'null':
+
+  // If the value is a boolean or null, convert it to a string. Note:
+  // typeof null does not produce 'null'. The case is included here in
+  // the remote chance that this gets fixed someday.
+
+              return String(value);
+
+  // If the type is 'object', we might be dealing with an object or an array or
+  // null.
+
+          case 'object':
+
+  // Due to a specification blunder in ECMAScript, typeof null is 'object',
+  // so watch out for that case.
+
+              if (!value) {
+                  return 'null';
+              }
+
+  // Make an array to hold the partial results of stringifying this object value.
+
+              gap += indent;
+              partial = [];
+
+  // Is the value an array?
+
+              if (Object.prototype.toString.apply(value) === '[object Array]') {
+
+  // The value is an array. Stringify every element. Use null as a placeholder
+  // for non-JSON values.
+
+                  length = value.length;
+                  for (i = 0; i < length; i += 1) {
+                      partial[i] = str(i, value) || 'null';
+                  }
+
+  // Join all of the elements together, separated with commas, and wrap them in
+  // brackets.
+
+                  v = partial.length === 0 ? '[]' :
+                      gap ? '[\n' + gap +
+                              partial.join(',\n' + gap) + '\n' +
+                                  mind + ']' :
+                            '[' + partial.join(',') + ']';
+                  gap = mind;
+                  return v;
+              }
+
+  // If the replacer is an array, use it to select the members to be stringified.
+
+              if (rep && typeof rep === 'object') {
+                  length = rep.length;
+                  for (i = 0; i < length; i += 1) {
+                      k = rep[i];
+                      if (typeof k === 'string') {
+                          v = str(k, value);
+                          if (v) {
+                              partial.push(quote(k) + (gap ? ': ' : ':') + v);
+                          }
+                      }
+                  }
+              } else {
+
+  // Otherwise, iterate through all of the keys in the object.
+
+                  for (k in value) {
+                      if (Object.hasOwnProperty.call(value, k)) {
+                          v = str(k, value);
+                          if (v) {
+                              partial.push(quote(k) + (gap ? ': ' : ':') + v);
+                          }
+                      }
+                  }
+              }
+
+  // Join all of the member texts together, separated with commas,
+  // and wrap them in braces.
+
+              v = partial.length === 0 ? '{}' :
+                  gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' +
+                          mind + '}' : '{' + partial.join(',') + '}';
+              gap = mind;
+              return v;
+          }
+      }
+
+  // If the JSON object does not yet have a stringify method, give it one.
+
+      if (typeof JSON.stringify !== 'function') {
+          JSON.stringify = function (value, replacer, space) {
+
+  // The stringify method takes a value and an optional replacer, and an optional
+  // space parameter, and returns a JSON text. The replacer can be a function
+  // that can replace values, or an array of strings that will select the keys.
+  // A default replacer method can be provided. Use of the space parameter can
+  // produce text that is more easily readable.
+
+              var i;
+              gap = '';
+              indent = '';
+
+  // If the space parameter is a number, make an indent string containing that
+  // many spaces.
+
+              if (typeof space === 'number') {
+                  for (i = 0; i < space; i += 1) {
+                      indent += ' ';
+                  }
+
+  // If the space parameter is a string, it will be used as the indent string.
+
+              } else if (typeof space === 'string') {
+                  indent = space;
+              }
+
+  // If there is a replacer, it must be a function or an array.
+  // Otherwise, throw an error.
+
+              rep = replacer;
+              if (replacer && typeof replacer !== 'function' &&
+                      (typeof replacer !== 'object' ||
+                       typeof replacer.length !== 'number')) {
+                  throw new Error('JSON.stringify');
+              }
+
+  // Make a fake root object containing our value under the key of ''.
+  // Return the result of stringifying the value.
+
+              return str('', {'': value});
+          };
+      }
+
+
+  // If the JSON object does not yet have a parse method, give it one.
+
+      if (typeof JSON.parse !== 'function') {
+          JSON.parse = function (text, reviver) {
+
+  // The parse method takes a text and an optional reviver function, and returns
+  // a JavaScript value if the text is a valid JSON text.
+
+              var j;
+
+              function walk(holder, key) {
+
+  // The walk method is used to recursively walk the resulting structure so
+  // that modifications can be made.
+
+                  var k, v, value = holder[key];
+                  if (value && typeof value === 'object') {
+                      for (k in value) {
+                          if (Object.hasOwnProperty.call(value, k)) {
+                              v = walk(value, k);
+                              if (v !== undefined) {
+                                  value[k] = v;
+                              } else {
+                                  delete value[k];
+                              }
+                          }
+                      }
+                  }
+                  return reviver.call(holder, key, value);
+              }
+
+
+  // Parsing happens in four stages. In the first stage, we replace certain
+  // Unicode characters with escape sequences. JavaScript handles many characters
+  // incorrectly, either silently deleting them, or treating them as line endings.
+
+              cx.lastIndex = 0;
+              if (cx.test(text)) {
+                  text = text.replace(cx, function (a) {
+                      return '\\u' +
+                          ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
+                  });
+              }
+
+  // In the second stage, we run the text against regular expressions that look
+  // for non-JSON patterns. We are especially concerned with '()' and 'new'
+  // because they can cause invocation, and '=' because it can cause mutation.
+  // But just to be safe, we want to reject all unexpected forms.
+
+  // We split the second stage into 4 regexp operations in order to work around
+  // crippling inefficiencies in IE's and Safari's regexp engines. First we
+  // replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
+  // replace all simple value tokens with ']' characters. Third, we delete all
+  // open brackets that follow a colon or comma or that begin the text. Finally,
+  // we look to see that the remaining characters are only whitespace or ']' or
+  // ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
+
+              if (/^[\],:{}\s]*$/.
+  test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@').
+  replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
+  replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
+
+  // In the third stage we use the eval function to compile the text into a
+  // JavaScript structure. The '{' operator is subject to a syntactic ambiguity
+  // in JavaScript: it can begin a block or an object literal. We wrap the text
+  // in parens to eliminate the ambiguity.
+
+                  j = eval('(' + text + ')');
+
+  // In the optional fourth stage, we recursively walk the new structure, passing
+  // each name/value pair to a reviver function for possible transformation.
+
+                  return typeof reviver === 'function' ?
+                      walk({'': j}, '') : j;
+              }
+
+  // If the text is not JSON parseable, then a SyntaxError is thrown.
+
+              throw new SyntaxError('JSON.parse');
+          };
+      }
+  }());
+
+  Sammy = Sammy || {};
+
+  // Sammy.JSON is a simple wrapper around Douglas Crockford's ever-useful json2.js
+  // (http://www.json.org/js.html]) Sammy.JSON includes the top level JSON object if
+  // it doesn't already exist (a.k.a. does not override the native implementation that
+  // some browsers include). It also adds a <tt>json()</tt> helper to a Sammy app when
+  // included.
+  Sammy.JSON = function(app) {
+
+    app.helpers({
+      // json is a polymorphic function that translates objects aback and forth
+      // from JSON to JS. If given a string, it will parse into JS, if given a JS
+      // object it will stringify into JSON.
+      //
+      // ### Example
+      //
+      //      var app = $.sammy(function() {
+      //        this.use(Sammy.JSON);
+      //
+      //        this.get('#/', function() {
+      //          this.json({user_id: 123}); //=> "{\"user_id\":\"123\"}"
+      //          this.json("{\"user_id\":\"123\"}"); //=> [object Object]
+      //          this.json("{\"user_id\":\"123\"}").user_id; //=> "123"
+      //        });
+      //      })
+      //
+      //
+      json: function(object) {
+        if (typeof object == 'string') {
+          return JSON.parse(object);
+        } else {
+          return JSON.stringify(object);
+        }
+      }
+    });
+
+  }
+
+})(jQuery);

http://git-wip-us.apache.org/repos/asf/cordova-registry-web/blob/f50cc931/attachments/sammy/plugins/sammy.meld.js
----------------------------------------------------------------------
diff --git a/attachments/sammy/plugins/sammy.meld.js b/attachments/sammy/plugins/sammy.meld.js
new file mode 100644
index 0000000..9753969
--- /dev/null
+++ b/attachments/sammy/plugins/sammy.meld.js
@@ -0,0 +1,140 @@
+(function($) {
+
+  Sammy = Sammy || {};
+
+  // `Sammy.Meld` is a simple templating engine that uses the power of jQuery's
+  // DOM manipulation to easily meld JSON data and HTML templates very quickly.
+  //
+  // The template can either be a string (i.e. loaded from a remote template)
+  // or a DOM Element/jQuery object. This allows you to have templates be DOM
+  // elements as the initial document load.
+  //
+  // ### Example
+  //
+  // The simplest case is a nested `<div>` whose class name is tied to a
+  // property of a JS object.
+  //
+  // Template:
+  //
+  //        <div class="post">
+  //          <div class="title"></div>
+  //          <div class="entry"></div>
+  //          <div class="author">
+  //            <span class="name"></span>
+  //          </div>
+  //        </div>
+  //
+  // Data:
+  //
+  //        {
+  //          "post": {
+  //            "title": "My Post",
+  //            "entry": "My Entry",
+  //            "author": {
+  //              "name": "@aq"
+  //            }
+  //          }
+  //        }
+  //
+  // Result:
+  //
+  //        <div class="post">
+  //          <div class="title">My Post</div>
+  //          <div class="entry">My Entry</div>
+  //          <div class="author">
+  //            <span class="name">@aq</span>
+  //          </div>
+  //        </div>
+  //
+  // Templates can be much more complex, and more deeply nested.
+  // More examples can be found in `test/fixtures/meld/`
+  //
+  // If you don't think the lookup by classes is semantic for you, you can easily
+  // switch the method of lookup by defining a selector function in the options
+  //
+  // For example:
+  //
+  //      meld($('.post'), post_data, {
+  //        selector: function(k) {
+  //          return '[data-key=' + k + ']';
+  //        }
+  //      });
+  //
+  // Would look for template nodes like `<div data-key='entry'>`
+  //
+  Sammy.Meld = function(app, method_alias) {
+    var default_options = {
+      selector: function(k) { return '.' + k; },
+      remove_false: true
+    };
+
+    var meld = function(template, data, options) {
+      var $template = $(template);
+
+      options = $.extend(default_options, options || {});
+
+      if (typeof data === 'string') {
+        $template.html(data);
+      } else {
+        $.each(data, function(key, value) {
+          var selector = options.selector(key),
+              $sub = $template.filter(selector),
+              $container,
+              $item,
+              is_list = false,
+              subindex = $template.index($sub);
+
+          if ($sub.length === 0) { $sub = $template.find(selector); }
+          if ($sub.length > 0) {
+            if ($.isArray(value)) {
+              $container = $('<div/>');
+              if ($sub.is('ol, ul')) {
+                is_list = true;
+                $item   = $sub.children('li:first');
+                if ($item.length == 0) { $item = $('<li/>'); }
+              } else if ($sub.children().length == 1) {
+                is_list = true;
+                $item = $sub.children(':first').clone();
+              } else {
+                $item = $sub.clone();
+              }
+              for (var i = 0; i < value.length; i++) {
+                $container.append(meld($item.clone(), value[i], options));
+              }
+              if (is_list) {
+                $sub.html($container.html());
+              } else if ($sub[0] == $template[0]) {
+                $template = $($container.html());
+              } else if (subindex >= 0) {
+                var args = [subindex, 1];
+                args = args.concat($container.children().get());
+                $template.splice.apply($template, args);
+              }
+            } else if (options.remove_false && value === false) {
+              $template.splice(subindex, 1);
+            } else if (typeof value === 'object') {
+              if ($sub.is(':empty')) {
+                $sub.attr(value, true);
+              } else {
+                $sub.html(meld($sub.html(), value, options));
+              }
+            } else {
+              $sub.html(value.toString());
+            }
+          } else {
+            $template.attr({key: value}, true);
+          }
+        });
+      }
+      var dom = $template;
+      return dom;
+    };
+
+    // set the default method name/extension
+    if (!method_alias) method_alias = 'meld';
+    // create the helper at the method alias
+    app.helper(method_alias, meld);
+
+  };
+
+})(jQuery);