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
+"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 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