diff --git a/docs/index.js b/docs/index.js
index 1ea5a2f..59ca7d4 100644
--- a/docs/index.js
+++ b/docs/index.js
@@ -96,6 +96,8 @@
"application/ld+json": {script:"/render/recipe.html"},
"text/canvas+javascript": {script:"canvas"},
"text/javascript": {script:"script"},
+ // "text/vcard": {script:"/render/contact.html"},
+ "mecard": {script:"contact"},
"application/bitsy": {script:"/render/bitsy.html", sandbox:"bitsy"},
"c": {script:"color"},
"e": {rewrite: "data:text/html;cipher=aes;format=gz;base64,"},
@@ -356,7 +358,8 @@
let scheme = fragment.substring(0,colon);
type = scheme;
- let renderer = renderers[scheme];
+ let renderer = renderers[scheme.toLowerCase()];
+
if (renderer) {
return renderContentWithScript({renderer, title, info, body:fragment, url:fragment});
}
diff --git a/docs/js/nosleep.js b/docs/js/nosleep.js
index 9b49362..2b3c10d 100644
--- a/docs/js/nosleep.js
+++ b/docs/js/nosleep.js
@@ -56,7 +56,6 @@ window.addEventListener("click", function enable() {
video.append(source)
// Play it as a result of user interaction
- console.log("video", video)
video.play()
activate()
})
diff --git a/docs/js/util.js b/docs/js/util.js
index 393fac2..aa05dab 100644
--- a/docs/js/util.js
+++ b/docs/js/util.js
@@ -29,4 +29,7 @@ const m = (selector, ...args) => {
args.forEach(append);
return node;
-};
\ No newline at end of file
+};
+
+
+const el = m;
\ No newline at end of file
diff --git a/docs/render/contact.css b/docs/render/contact.css
new file mode 100644
index 0000000..fe1f070
--- /dev/null
+++ b/docs/render/contact.css
@@ -0,0 +1,91 @@
+* {
+ font-family: -apple-system, BlinkMacSystemFont, sans-serif;
+}
+
+:root {
+ --shadow-color: 0deg 0% 63%;
+ --shadow-elevation-low:
+ 0px 0.5px 0.6px hsl(var(--shadow-color) / 0.34),
+ 0px 0.8px 0.9px -1.2px hsl(var(--shadow-color) / 0.34),
+ 0px 1.9px 2.1px -2.5px hsl(var(--shadow-color) / 0.34);
+ --shadow-elevation-medium:
+ 0px 0.5px 0.6px hsl(var(--shadow-color) / 0.36),
+ 0px 1.5px 1.7px -0.8px hsl(var(--shadow-color) / 0.36),
+ 0px 3.8px 4.3px -1.7px hsl(var(--shadow-color) / 0.36),
+ -0.1px 9.4px 10.6px -2.5px hsl(var(--shadow-color) / 0.36);
+ --shadow-elevation-high:
+ 0px 0.5px 0.6px hsl(var(--shadow-color) / 0.34),
+ 0px 2.7px 3px -0.4px hsl(var(--shadow-color) / 0.34),
+ 0px 5.1px 5.7px -0.7px hsl(var(--shadow-color) / 0.34),
+ -0.1px 8.4px 9.5px -1.1px hsl(var(--shadow-color) / 0.34),
+ -0.1px 13.4px 15.1px -1.4px hsl(var(--shadow-color) / 0.34),
+ -0.2px 20.9px 23.5px -1.8px hsl(var(--shadow-color) / 0.34),
+ -0.2px 31.8px 35.8px -2.1px hsl(var(--shadow-color) / 0.34),
+ -0.4px 46.8px 52.7px -2.5px hsl(var(--shadow-color) / 0.34);
+}
+
+body {
+ color:#16161d;
+ background-color: #eeeeef;
+ display:flex;
+ justify-content:center;
+ align-items: center;
+ min-height:100vh;
+}
+
+.contact {
+ background-color: white;
+ width:320px;
+ height:518px;
+ box-shadow: var(--shadow-elevation-medium);
+ margin-bottom:20vh;
+ padding-top:24px;
+ border-radius:3px;
+ display:flex;
+ flex-direction: column;
+ justify-content: space-between;
+ padding:8px 0;
+}
+
+
+.header {
+ flex: 1 1 auto;
+}
+
+
+
+.icon {
+ order:1;
+ padding: 12px 0;
+}
+
+.row {
+ display:flex;
+ text-decoration:none;
+ color:black;
+ flex-direction: row;
+ border-top:1px solid #eee;
+ min-height:48px;
+ align-items: center;
+}
+.field {
+ flex: 1 1 auto;
+}
+
+.icon svg {
+
+}
+
+a, h1, div.memo {
+ padding: 0 12px;
+ margin:0;
+}
+
+h1 {
+ font-weight:normal;
+ font-size:24px;
+}
+
+.contact a:hover {
+ background-color: #eee;
+}
\ No newline at end of file
diff --git a/docs/render/contact.js b/docs/render/contact.js
new file mode 100644
index 0000000..03f571c
--- /dev/null
+++ b/docs/render/contact.js
@@ -0,0 +1,116 @@
+let script = window.script;
+
+let icon = {
+ bday: '',
+ tel: '',
+ text: '',
+ url: '',
+ adr: '',
+ email: '',
+ note: '',
+ add: '',
+ vid: '',
+}
+
+
+
+
+
+function share() {
+ parent.postMessage({share:{}}, "*");
+}
+
+function render() {
+ document.documentElement.appendChild(el("base", {target:"_top"}))
+ let vcard = params.body.match(/BEGIN:VCARD/);
+ if (vcard) {
+ let data = parse(params.body)
+ console.log(data, params.body.split("\n"));
+ document.body.appendChild(
+ el("div.contact", {},
+ el("h1.header", {}, data.fn),
+ data.email.forEach(email => el("div.email", {}, email.value.pop())),
+ data.tel.forEach(tel => el("div.tel", {}, tel.value.pop())),
+ // array.map(line => el("div.line", {}, line)),
+ )
+ )
+ } else if (params.body.match(/MECARD:/)){
+ let lines = decodeURIComponent(params.body.substring(7)).trim().replace(/\\n/g, "\n").replace(/\\:/g, "\:").split(";");
+ let mecard = {}
+ lines.forEach(line => {
+ let parts = line.split(":");
+ mecard[parts.shift().toLowerCase()] = [parts.join(":")];
+ })
+
+ document.body.appendChild(
+ el("div.contact", {},
+ el("div.header", {},
+ el("h1", {}, mecard.n),
+ ),
+ mecard.tel.map(tel => el("a.row.tel", {href:"tel:" + tel},
+ el("div.icon", {innerHTML:icon.tel}), el("div.field", {}, tel))),
+ mecard.email.map(email => el("a.row.email", {target:"top", href:"mailto:" + email},
+ el("div.icon", {innerHTML:icon.email}), el("div.field", {}, email))),
+ mecard.adr.map(adr => el("a.row.adr", {href:"https://address.fyi/" + adr},
+ el("div.icon", {innerHTML:icon.adr}), el("div.field", {}, adr))),
+ mecard.bday.map(bday => el("a.row.bday", {href:"https://address.fyi/" + bday},
+ el("div.icon", {innerHTML:icon.bday}), el("div.field", {}, bday))),
+ mecard.url.map(url => el("a.row.url", {href:url},
+ el("div.icon", {innerHTML:icon.url}), el("div.field", {}, url.replace(/https?:\/\//, "")))),
+ mecard.memo.map(memo => el("div.row.memo", {}, el("div.field", {}, memo))),
+
+ )
+ )
+ console.log("mecard", lines, mecard);
+ }
+
+}
+
+var path = script.substring(0, script.lastIndexOf("."));
+var cssURL = path + ".css";
+Promise.all([
+ loadSyle(cssURL)
+]).then(render);
+
+function parse(input) {
+ var Re1 = /^(version|fn|title|org):(.+)$/i;
+ var Re2 = /^([^:;]+);([^:]+):(.+)$/;
+ var ReKey = /item\d{1,2}\./;
+ var fields = {};
+
+ input.split(/\r\n|\r|\n/).forEach(function (line) {
+ var results, key;
+
+ if (Re1.test(line)) {
+ results = line.match(Re1);
+ key = results[1].toLowerCase();
+ fields[key] = results[2];
+ } else if (Re2.test(line)) {
+ results = line.match(Re2);
+ key = results[1].replace(ReKey, '').toLowerCase();
+
+ var meta = {};
+ results[2].split(';')
+ .map(function (p, i) {
+ var match = p.match(/([a-z]+)=(.*)/i);
+ if (match) {
+ return [match[1], match[2]];
+ } else {
+ return ["TYPE" + (i === 0 ? "" : i), p];
+ }
+ })
+ .forEach(function (p) {
+ meta[p[0]] = p[1];
+ });
+
+ if (!fields[key]) fields[key] = [];
+
+ fields[key].push({
+ meta: meta,
+ value: results[3].split(';')
+ })
+ }
+ });
+
+ return fields;
+};