You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ponymail.apache.org by hu...@apache.org on 2016/09/02 12:30:22 UTC

[2/2] incubator-ponymail git commit: add an actual test output

add an actual test output

make a menu bar etc


Project: http://git-wip-us.apache.org/repos/asf/incubator-ponymail/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-ponymail/commit/42e2b482
Tree: http://git-wip-us.apache.org/repos/asf/incubator-ponymail/tree/42e2b482
Diff: http://git-wip-us.apache.org/repos/asf/incubator-ponymail/diff/42e2b482

Branch: refs/heads/coffee-and-cake
Commit: 42e2b482b40ad76f5491a9bb91c585d5284775a0
Parents: 8941f3e
Author: Daniel Gruno <hu...@apache.org>
Authored: Fri Sep 2 14:29:56 2016 +0200
Committer: Daniel Gruno <hu...@apache.org>
Committed: Fri Sep 2 14:29:56 2016 +0200

----------------------------------------------------------------------
 site/css/ponymail2.css     |  78 +++++
 site/js/coffee/test.coffee |  31 +-
 site/js/ponymail-coffee.js | 676 ++++++++++++++++++++++++++++++++++++++++
 site/list2.html            |  29 ++
 4 files changed, 813 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ponymail/blob/42e2b482/site/css/ponymail2.css
----------------------------------------------------------------------
diff --git a/site/css/ponymail2.css b/site/css/ponymail2.css
new file mode 100644
index 0000000..7fb365c
--- /dev/null
+++ b/site/css/ponymail2.css
@@ -0,0 +1,78 @@
+#topMenu {
+    background: #0099FF;
+    background-position: top left;
+    background-repeat: no-repeat;
+    background-size: contain;
+    border-radius: 5px;
+    margin: 20px auto;
+    box-shadow: 1px 1px 2px 2px rgba(0,0,0,0.2);
+    height: 40px;
+    min-width: 300px;
+    max-width: 90%;
+    color: #FFF;
+}
+
+#topMenu li {
+  list-style: none;
+  float: left;
+}
+
+
+#topMenu li:not(.logo) {
+  font-family: sans-serif;
+  font-size: 10pt;
+  font-weight: 500;
+  padding-top: 12px;
+  padding-bottom: 12px;
+  height: 100%;
+  border-left: 1px solid #3A7CA8;
+  padding-left: 10px;
+  padding-right: 10px;
+  cursor: pointer;
+  position: relative;
+}
+
+#topMenu li:not(.logo):last-child {
+  border-right: 1px solid #3A7CA8;
+}
+
+#topMenu a {
+    color: #FFF;
+    text-decoration: none;
+    padding-top: 16px;
+    padding-bottom: 16px;
+    margin-top: -16px;
+    margin-bottom: -16px;
+}
+
+#topMenu a:hover {
+  
+}
+#topMenu li:not(.logo) a:hover:before {
+  content: " ";
+  position: absolute;
+  left: calc(50% - 10px);
+  height: 0; 
+  border-left: 5px solid transparent;
+  border-right: 5px solid transparent;
+  bottom: 0px;
+  margin-left: 5px;
+  border-bottom: 5px solid #1968FC;
+}
+
+body, html {
+    background: #D2D2D2;
+    margin: 0;
+}
+
+.sbox {
+    box-shadow: 1px 1px 2px 2px rgba(0,0,0,0.1);
+    border: 1px solid #666;
+    background: #EEE;
+    color: #222;
+    margin: 20px;
+    padding: 5px;
+    border-radius: 2px;
+    font-family: sans-serif;
+    font-size:  9pt;
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-ponymail/blob/42e2b482/site/js/coffee/test.coffee
----------------------------------------------------------------------
diff --git a/site/js/coffee/test.coffee b/site/js/coffee/test.coffee
index 2f02187..fdf59c5 100644
--- a/site/js/coffee/test.coffee
+++ b/site/js/coffee/test.coffee
@@ -1,8 +1,37 @@
 testCoffee = () ->
     ### Get main div from HTML ###
     parent = get('testdiv')
+    
+    # Make the top menu
+    menu = new HTML('div', { id: "topMenu"})
+    parent.inject(menu)
+    
+    # Add menu points
+    ul = new HTML('ul')
+    
+    # Add logo first
+    logo = new HTML('li', {
+        class: 'logo'
+    }, new HTML('a', {
+        href: "./"
+    }, new HTML('img', {
+        src: "images/logo.png",
+        style: {
+            paddingRight: "10px",
+            height: "38px",
+            width: "auto"
+        }
+    })))
+    ul.inject(logo)
+    
+    # Menu points
+    for item in ['Home', 'Lists', 'Third item']
+        li = new HTML('li', {}, item)
+        ul.inject(li)
+    menu.inject(ul)
+    
     # Make a paragraph with some text in it
-    p = new HTML('p', { class: "fooclass", style: { textAlign: 'center'}}, "Text goes here")
+    p = new HTML('p', { class: "sbox", style: { textAlign: 'center'}}, "Text goes here")
     
     # Inject paragraph into div
     parent.inject(p)

http://git-wip-us.apache.org/repos/asf/incubator-ponymail/blob/42e2b482/site/js/ponymail-coffee.js
----------------------------------------------------------------------
diff --git a/site/js/ponymail-coffee.js b/site/js/ponymail-coffee.js
new file mode 100644
index 0000000..5188c57
--- /dev/null
+++ b/site/js/ponymail-coffee.js
@@ -0,0 +1,676 @@
+// Generated by CoffeeScript 1.9.3
+
+/*
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+var HTML, HTTPRequest, cog, dbRead, dbWrite, e, genColors, get, hsl2rgb, isArray, isHash, pm_storage_available, pm_storage_globvar, set, testCoffee, testToggle, txt;
+
+hsl2rgb = function(h, s, l) {
+  var fract, min, sh, sv, switcher, v, vsf;
+  h = h % 1;
+  if (s > 1) {
+    s = 1;
+  }
+  if (l > 1) {
+    l = 1;
+  }
+  if (l <= 0.5) {
+    v = l * (1 + s);
+  } else {
+    v = l + s - l * s;
+  }
+  if (v === 0) {
+    return {
+      r: 0,
+      g: 0,
+      b: 0
+    };
+  }
+  min = 2 * l - v;
+  sv = (v - min) / v;
+  sh = (6 * h) % 6;
+  switcher = Math.floor(sh);
+  fract = sh - switcher;
+  vsf = v * sv * fract;
+  switch (switcher) {
+    case 0:
+      return {
+        r: v,
+        g: min + vsf,
+        b: min
+      };
+    case 1:
+      return {
+        r: v - vsf,
+        g: v,
+        b: min
+      };
+    case 2:
+      return {
+        r: min,
+        g: v,
+        b: min + vsf
+      };
+    case 3:
+      return {
+        r: min,
+        g: v - vsf,
+        b: v
+      };
+    case 4:
+      return {
+        r: min + vsf,
+        g: min,
+        b: v
+      };
+    case 5:
+      return {
+        r: v,
+        g: min,
+        b: v - vsf
+      };
+  }
+  return {
+    r: 0,
+    g: 0,
+    b: 0
+  };
+};
+
+genColors = function(numColors, saturation, lightness, hex) {
+  var baseHue, c, cls, h, i, j, ref;
+  cls = [];
+  baseHue = 1.34;
+  for (i = j = 1, ref = numColors; 1 <= ref ? j <= ref : j >= ref; i = 1 <= ref ? ++j : --j) {
+    c = hsl2rgb(baseHue, saturation, lightness);
+    if (hex) {
+      h = (Math.round(c.r * 255 * 255 * 255) + Math.round(c.g * 255 * 255) + Math.round(c.b * 255)).toString(16);
+      while (h.length < 6) {
+        h = '0' + h;
+      }
+      h = '#' + h;
+      cls.push(h);
+    } else {
+      cls.push({
+        r: parseInt(c.r * 255),
+        g: parseInt(c.g * 255),
+        b: parseInt(c.b * 255)
+      });
+    }
+    baseHue -= 0.23;
+    if (baseHue < 0) {
+      baseHue += 1;
+    }
+  }
+  return cls;
+};
+
+
+/*
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+
+/**
+ * HTML: DOM creator class
+ * args:
+ * - type: HTML element type (div, table, p etc) to produce
+ * - params: hash of element params to add (class, style etc)
+ * - children: optional child or children objects to insert into the new element
+ * Example:
+ * div = new HTML('div', {
+ *    class: "footer",
+ *    style: {
+ *        fontWeight: "bold"
+ *    }
+#}, "Some text inside a div")
+ */
+
+HTML = (function() {
+  function HTML(type, params, children) {
+
+    /* create the raw element */
+    var child, j, key, len, subkey, subval, val;
+    this.element = document.createElement(type);
+
+    /* If params have been passed, set them */
+    if (isHash(params)) {
+      for (key in params) {
+        val = params[key];
+
+        /* Standard string value? */
+        if (typeof val === "string") {
+          this.element.setAttribute(key, val);
+        } else if (isArray(val)) {
+
+          /* Are we passing a list of data to set? concatenate then */
+          this.element.setAttribute(key, val.join(" "));
+        } else if (isHash(val)) {
+
+          /* Are we trying to set multiple sub elements, like a style? */
+          for (subkey in val) {
+            subval = val[subkey];
+            this.element[key][subkey] = subval;
+          }
+        }
+      }
+    }
+
+    /* If any children have been passed, add them to the element */
+    if (children) {
+
+      /* If string, convert to textNode using txt() */
+      if (typeof children === "string") {
+        this.element.inject(txt(children));
+      } else {
+
+        /* If children is an array of elems, iterate and add */
+        if (isArray(children)) {
+          for (j = 0, len = children.length; j < len; j++) {
+            child = children[j];
+
+            /* String? Convert via txt() then */
+            if (typeof child === "string") {
+              this.element.inject(txt(child));
+            } else {
+
+              /* Plain element, add normally */
+              this.element.inject(k);
+            }
+          }
+        } else {
+
+          /* Just a single element, add it */
+          this.element.inject(children);
+        }
+      }
+    }
+    return this.element;
+  }
+
+  return HTML;
+
+})();
+
+
+/* Set: shortcut for a.setAttribute(b,c) */
+
+set = function(a, b, c) {
+  return a.setAttribute(b, c);
+};
+
+
+/* txt: shortcut for creating a text node */
+
+txt = function(a) {
+  return document.createTextNode(a);
+};
+
+
+/* Get: Shortcut for doc.getElementById */
+
+get = function(a) {
+  return document.getElementById(a);
+};
+
+
+/**
+ * prototype injector for HTML elements:
+ * Example: mydiv.inject(otherdiv)
+ */
+
+HTMLElement.prototype.inject = function(child) {
+  var item, j, len;
+  if (isArray(child)) {
+    for (j = 0, len = child.length; j < len; j++) {
+      item = child[j];
+      if (typeof item === 'string') {
+        item = txt(item);
+      }
+      this.appendChild(item);
+    }
+  } else {
+    if (typeof child === 'string') {
+      child = txt(child);
+    }
+    this.appendChild(child);
+  }
+  return child;
+};
+
+
+/**
+ * prototype show/hide function for HTML elements:
+ * If called with a bool, show if True, hide if False.
+ * If no bool, toggle show/hide based on current state.
+ */
+
+HTMLElement.prototype.show = function(bool) {
+  var b, d;
+  d = 'block';
+  if (typeof bool === 'undefined') {
+    d = this.style.display === 'none' ? 'block' : 'none';
+  } else if (bool === false) {
+    d = 'none';
+  } else if (bool === true) {
+    b = 'block';
+  }
+  this.style.display = d;
+  return d;
+};
+
+
+/* Cog: Loading panel for when waiting for a response */
+
+cog = function(div, size) {
+  var i, idiv;
+  if (size == null) {
+    size = 200;
+  }
+  idiv = mk('div', {
+    "class": "icon",
+    style: {
+      texAlign: 'center',
+      verticalAlign: 'middle',
+      height: '500px'
+    }
+  });
+  i = mk('i', {
+    "class": 'fa fa-spin fa-cog',
+    style: {
+      fontSize: size + 'pt !important',
+      color: '#AAB'
+    }
+  });
+  idiv.inject([i, mk('br'), "Loading data, please wait..."]);
+  div.innerHTML = "";
+  return div.appendChild(idiv);
+};
+
+
+/*
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+
+/**
+ * HTTPRequest: Fire off a HTTP request.
+ * Args:
+ * - url: The URL to request (may be relative or absolute)
+ * - args:
+ * - - state: A callback stateful object
+ * - - data: Any form/JSON data to send along if POST (method is derived
+ *           from whether data is attached or not)
+ * - - getdata: Any form vars to append to the URL as URI-encoded formdata
+ * - - datatype: 'form' or 'json' data?
+ * - - callback: function to call when request has returned a response
+ * - - snap: snap function in case of internal server error or similar
+ * - - nocreds: don't pass on cookies?
+
+ * Example POST request:
+ *    HTTPRequest("/api/foo.lua", {
+ *        state: {
+ *            ponies: true
+ *        },
+ *        callback: foofunc,
+ *        data: {
+ *            list: "foo.bar"
+ *        }
+ *   })
+ */
+
+HTTPRequest = (function() {
+  function HTTPRequest(url, args) {
+    var tmp;
+    this.url = url;
+    this.args = args;
+
+    /* Set internal class data, determine request type */
+    this.state = this.args.state;
+    this.method = this.args.data ? 'POST' : 'GET';
+    this.data = this.args.data;
+    this.getdata = this.args.get;
+    this.datatype = this.args.datatype || 'form';
+    this.callback = this.args.callback;
+    this.snap = this.args.snap || pm_snap;
+    this.nocreds = this.args.nocreds || false;
+
+    /* Construct request object */
+    if (window.XMLHttpRequest) {
+      this.request = new XMLHttpRequest();
+    } else {
+      this.request = new ActiveXObject("Microsoft.XMLHTTP");
+    }
+
+    /* Default to sending credentials */
+    if (!this.nocreds) {
+      this.request.withCredentials = true;
+    }
+
+    /* Determine what to send as data (if anything) */
+    this.rdata = null;
+    if (this.method === 'POST') {
+      if (this.datatype === 'json') {
+        this.rdata = JSON.stringify(this.data);
+      } else {
+        this.rdata = this.formdata(this.data);
+      }
+    }
+
+    /* If tasked with appending data to the URL, do so */
+    if (isHash(this.getdata)) {
+      tmp = this.formdata(this.getdata);
+      if (tmp.length > 0) {
+
+        /* Do we have form data here aleady? if so, append the new */
+
+        /* by adding an ampersand first */
+        if (this.url.match(/\?/)) {
+          this.url += "&" + tmp;
+        } else {
+          this.url += "?" + tmp;
+        }
+      }
+    }
+
+    /* Use @method on URL */
+    this.request.open(this.method, this.url, true);
+
+    /* Send data */
+    this.request.send(this.rdata);
+
+    /* Set onChange behavior */
+    this.request.onreadystatechange = this.onchange;
+
+    /* all done! */
+    return this;
+  }
+
+
+  /* HTTPRequest state change calback */
+
+  HTTPRequest.prototype.onchange = function() {
+
+    /* Internal Server Error: Try to call snap */
+    var e;
+    if (this.request.readyState === 4 && this.request.status === 500) {
+      if (this.snap) {
+        this.snap(this.state);
+      }
+    }
+
+    /* 200 OK, everything is okay, try to parse JSON response */
+    if (this.request.readyState === 4 && this.request.status === 200) {
+      if (this.callback) {
+
+        /* Try to parse as JSON and deal with cache objects, fall back to old style parse-and-pass */
+        try {
+
+          /* Parse JSON response */
+          this.response = JSON.parse(this.request.responseText);
+
+          /* If loginRequired (rare!), redirect to oauth page */
+          if (this.response && this.response.loginRequired) {
+            location.href = "/oauth.html";
+            return;
+          }
+
+          /* Otherwise, call the callback function */
+          return this.callback(this.response, this.state);
+        } catch (_error) {
+          e = _error;
+          return this.callback(this.request.responseText, this.state);
+        }
+      }
+    }
+  };
+
+
+  /* Standard form data joiner for POST data */
+
+  HTTPRequest.prototype.formdata = function(kv) {
+    var ar, k, v;
+    ar = [];
+
+    /* For each key/value pair (assuming this is a hash) */
+    if (isHash(kv)) {
+      for (k in kv) {
+        v = kv[k];
+
+        /* Only append if the value is non-empty */
+        if (v && v !== "") {
+
+          /*  URI-Encode value and add to an array */
+          ar.push(k + "=" + encodeURIComponent(v));
+        }
+      }
+    }
+
+    /* Join the array with ampersands, so we get "foo=bar&foo2=baz" */
+    return ar.join("&");
+  };
+
+  return HTTPRequest;
+
+})();
+
+
+/*
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+
+/**
+ * Init: Test if localStorage is available or not
+ * If not, fall back to plain global var storage (not effective, but meh)
+ */
+
+pm_storage_available = false;
+
+pm_storage_globvar = {};
+
+try {
+  if (typeof window.localStorage !== "undefined") {
+    window.localStorage.setItem("pm_test", "1");
+    pm_storage_available = true;
+  }
+} catch (_error) {
+  e = _error;
+  pm_storage_available = false;
+}
+
+
+/**
+ * dbWrite: Store a key/val pair
+ * Example: dbWrite("ponies", "They are awesome!")
+ */
+
+dbWrite = function(key, value) {
+
+  /* Can we use localStorage? */
+  if (pm_storage_available) {
+    return window.localStorage.setItem(key, value);
+  } else {
+
+    /* Guess not, fall back to (ineffective) global var */
+    pm_storage_globvar[key] = value;
+    return true;
+  }
+};
+
+
+/* dbRead: Given a key, read the corresponding value from storage */
+
+dbRead = function(key) {
+
+  /* Do we have localStorage? */
+  if (pm_storage_available) {
+    return window.localStorage.getItem(key);
+  } else {
+
+    /* Nope, try global var */
+    return pm_storage_globvar[key];
+  }
+};
+
+
+/*
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License.  You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+
+/**
+ * Number prettification prototype:
+ * Converts 1234567 into 1,234,567 etc
+ */
+
+Number.prototype.pretty = function(fix) {
+  if (fix) {
+    return String(this.toFixed(fix)).replace(/(\d)(?=(\d{3})+\.)/g, '$1,');
+  }
+  return String(this.toFixed(0)).replace(/(\d)(?=(\d{3})+$)/g, '$1,');
+};
+
+
+/**
+ * Number padding
+ * usage: 123.pad(6) -> 000123
+ */
+
+Number.prototype.pad = function(n) {
+  var str;
+  str = String(this);
+
+  /* Do we need to pad? if so, do it using String.repeat */
+  if (str.length < n) {
+    str = "0".repeat(n - str.length) + str;
+  }
+  return str;
+};
+
+
+/* isArray: function to detect if an object is an array */
+
+isArray = function(value) {
+  return value && typeof value === 'object' && value instanceof Array && typeof value.length === 'number' && typeof value.splice === 'function' && !(value.propertyIsEnumerable('length'));
+};
+
+
+/* isHash: function to detect if an object is a hash */
+
+isHash = function(value) {
+  return value && typeof value === 'object' && !isArray(value);
+};
+
+testCoffee = function() {
+
+  /* Get main div from HTML */
+  var hider, item, j, len, li, logo, menu, p, parent, ref, ul;
+  parent = get('testdiv');
+  menu = new HTML('div', {
+    id: "topMenu"
+  });
+  parent.inject(menu);
+  ul = new HTML('ul');
+  logo = new HTML('li', {
+    "class": 'logo'
+  }, new HTML('a', {
+    href: "./"
+  }, new HTML('img', {
+    src: "images/logo.png",
+    style: {
+      paddingRight: "10px",
+      height: "38px",
+      width: "auto"
+    }
+  })));
+  ul.inject(logo);
+  ref = ['Home', 'Lists', 'Third item'];
+  for (j = 0, len = ref.length; j < len; j++) {
+    item = ref[j];
+    li = new HTML('li', {}, item);
+    ul.inject(li);
+  }
+  menu.inject(ul);
+  p = new HTML('p', {
+    "class": "sbox",
+    style: {
+      textAlign: 'center'
+    }
+  }, "Text goes here");
+  parent.inject(p);
+  p.inject([". Here's a textNode added afterwards", new HTML('br')]);
+  hider = new HTML('b', {
+    onclick: 'testToggle(this);'
+  }, "Click here to hide this text!");
+  return p.inject(hider);
+};
+
+testToggle = function(div) {
+  return div.show();
+};

http://git-wip-us.apache.org/repos/asf/incubator-ponymail/blob/42e2b482/site/list2.html
----------------------------------------------------------------------
diff --git a/site/list2.html b/site/list2.html
new file mode 100644
index 0000000..deba3c5
--- /dev/null
+++ b/site/list2.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<!-- Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements. See the NOTICE file distributed with
+this work for additional information regarding copyright ownership. The
+ASF licenses this file to you under the Apache License, Version 2.0 (the
+&quot;License&quot;); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at .
+http://www.apache.org/licenses/LICENSE-2.0 . Unless required by
+applicable law or agreed to in writing, software distributed under the
+License is distributed on an &quot;AS IS&quot; BASIS, WITHOUT WARRANTIES
+OR CONDITIONS OF ANY KIND, either express or implied. See the License
+for the specific language governing permissions and limitations under
+the License. -->
+<html lang="en">
+  <head>
+    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+    <meta charset="utf-8">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge">
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+    <link rel="stylesheet" href="css/ponymail2.css"/>
+    <title>Pony Mail!</title>
+  </head>
+  <body onLoad="testCoffee();">
+    <div id="testdiv">
+      
+    </div>
+    <script type="text/javascript" src="js/ponymail-coffee.js"></script>
+  </body>
+</html>
\ No newline at end of file